{"id":27385,"date":"2026-07-28T11:18:32","date_gmt":"2026-07-28T11:18:32","guid":{"rendered":"https:\/\/umang.pk\/2026\/07\/28\/%d8%a7%db%8c-%d9%b9%db%8c-%d8%a7%db%8c%d9%84-%d9%be%d8%a7%d8%a6%d9%be-%d9%84%d8%a7%d8%a6%d9%86%d8%b2-%db%81%db%8c%d9%86%da%88-%d8%a8%da%a9-%d8%a7%d8%b2%da%af%d8%b1-%d9%85%db%8c%da%ba-%d9%be%d8%b1\/"},"modified":"2026-07-28T11:18:33","modified_gmt":"2026-07-28T11:18:33","slug":"%d8%a7%db%8c-%d9%b9%db%8c-%d8%a7%db%8c%d9%84-%d9%be%d8%a7%d8%a6%d9%be-%d9%84%d8%a7%d8%a6%d9%86%d8%b2-%db%81%db%8c%d9%86%da%88-%d8%a8%da%a9-%d8%a7%d8%b2%da%af%d8%b1-%d9%85%db%8c%da%ba-%d9%be%d8%b1","status":"publish","type":"post","link":"https:\/\/umang.pk\/ur\/2026\/07\/28\/%d8%a7%db%8c-%d9%b9%db%8c-%d8%a7%db%8c%d9%84-%d9%be%d8%a7%d8%a6%d9%be-%d9%84%d8%a7%d8%a6%d9%86%d8%b2-%db%81%db%8c%d9%86%da%88-%d8%a8%da%a9-%d8%a7%d8%b2%da%af%d8%b1-%d9%85%db%8c%da%ba-%d9%be%d8%b1\/","title":{"rendered":"\u0627\u06cc \u0679\u06cc \u0627\u06cc\u0644 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646\u0632 \u06c1\u06cc\u0646\u0688 \u0628\u06a9: \u0627\u0632\u06af\u0631 \u0645\u06cc\u06ba \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u06af\u0631\u06cc\u0688 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646\u0632 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u0626\u06cc\u06ba"},"content":{"rendered":"\n<div id=\"\">\n<p>\u0633\u06cc\u0644\u0627\u0628 \u06a9\u06d2 \u062e\u0637\u0631\u06d2 \u0633\u06d2 \u0628\u0627\u062e\u0628\u0631 \u0631\u06c1\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0686\u06be \u063a\u06cc\u0631 \u0648\u0627\u0636\u062d \u0644\u06cc\u06a9\u0646 \u0636\u0631\u0648\u0631\u06cc \u06c1\u06d2: \u0635\u0627\u0641\u060c \u0645\u0646\u0638\u0645 \u0688\u06cc\u0679\u0627\u06d4<\/p>\n<p>\u0627\u0633 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0645\u06cc\u06ba\u060c \u0622\u067e \u0627\u067e\u0646\u0627 \u0688\u06cc\u0679\u0627 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0641\u0631\u0627\u0646\u0633 \u06a9\u06d2 \u0622\u0641\u06cc\u0634\u0644 \u0627\u0648\u067e\u0646 \u0648\u0627\u0679\u0631 \u0688\u06cc\u0679\u0627 API Hub&#8217;Eau \u0633\u06d2 \u0631\u0648\u0632\u0627\u0646\u06c1 \u067e\u0627\u0646\u06cc \u06a9\u06cc \u0633\u0637\u062d \u06a9\u06cc \u0631\u06cc\u0688\u0646\u06af \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 Python ETL (\u0627\u06cc\u06a9\u0633\u0679\u0631\u06cc\u06a9\u0679\u060c \u0679\u0631\u0627\u0646\u0633\u0641\u0627\u0631\u0645\u060c \u0644\u0648\u0688) \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 \u067e\u06be\u0631 \u06c1\u0645 \u0627\u0633 \u0688\u06cc\u0679\u0627 \u06a9\u0648 \u0635\u0627\u0641 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0644\u0627\u0626\u06cc\u0648 \u0648\u0631\u0698\u0646 \u06a9\u06cc \u0637\u0631\u062d \u0627\u06cc\u06a9 \u0639\u0648\u0627\u0645\u06cc \u0688\u06cc\u0679\u0627\u0633\u06cc\u0679 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0634\u0627\u0626\u0639 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u067e\u0631 \u0645\u0628\u0646\u06cc \u06c1\u06d2 \u062c\u0648 \u06c1\u0641\u062a\u06d2 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0634\u06cc\u0688\u0648\u0644 \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u0686\u0644\u062a\u06cc \u06c1\u06d2 \u0627\u0648\u0631 \u067e\u06cc\u0631\u0633 \u0633\u06cc\u0644\u0627\u0628 \u06a9\u06d2 \u0688\u06cc\u0679\u0627\u0633\u06cc\u0679 \u06a9\u0648 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0644\u06cc\u06a9\u0646 \u0622\u067e \u0635\u0631\u0641 \u06a9\u0648\u0688 \u06a9\u0648 \u06a9\u0627\u067e\u06cc \u0627\u0648\u0631 \u067e\u06cc\u0633\u0679 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u0635\u0644 \u0645\u0642\u0635\u062f \u0633\u0645\u062c\u06be\u0646\u0627 \u06c1\u06d2\u06d4 <em>\u06a9\u06cc\u0648\u06ba<\/em> \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u062a\u0648\u0642\u0639 \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4 \u0622\u0626\u06cc\u06d2 \u0627\u0633\u06a9\u0631\u067e\u0679\u0633 \u06a9\u0648 \u0627\u0644\u06af \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0688\u06cc\u0632\u0627\u0626\u0646 \u06a9\u06d2 \u0641\u06cc\u0635\u0644\u06d2 \u067e\u0631 \u0646\u0638\u0631 \u0688\u0627\u0644\u06cc\u06ba \u062c\u0633 \u06a9\u0627 \u0645\u0642\u0635\u062f \u0627\u0633\u06a9\u0631\u067e\u0679\u0633 \u0633\u06d2 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0686\u0644\u0646\u0627 \u06c1\u06d2 \u062c\u0648 \u0633\u0627\u0644\u0648\u06ba \u062a\u06a9 \u0628\u063a\u06cc\u0631 \u062a\u0648\u062c\u06c1 \u06a9\u06d2 \u0686\u0644\u062a\u06cc \u0631\u06c1\u06cc\u06ba \u06af\u06cc\u06d4<\/p>\n<p>\u0622\u067e \u0627\u0633 \u0644\u06cc\u067e \u0679\u0627\u067e \u0633\u06d2 \u06a9\u0648\u0688 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u0633\u0628\u0642 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0627\u0633 \u067e\u0631 \u0686\u0644\u062a\u06cc \u06c1\u06d2: <strong>\u0646\u0642\u0644\u06cc (\u0645\u0630\u0627\u0642) API \u0688\u06cc\u0679\u0627<\/strong>. \u06cc\u06c1 \u0622\u067e \u06a9\u0648 \u0627\u0635\u0644 \u0633\u0631\u0648\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06af\u0691\u0628\u0691 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0633\u06cc\u0644 \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u0628\u0639\u062f \u06a9\u0627 \u0633\u06cc\u06a9\u0634\u0646 \u0622\u067e \u06a9\u0648 \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0644\u0627\u0626\u06cc\u0648 API \u0645\u06cc\u06ba \u06a9\u06cc\u0633\u06d2 \u0645\u0646\u062a\u0642\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2\u06d4<\/p>\n<p>\u0622\u062e\u0631 \u0645\u06cc\u06ba\u060c \u0622\u067e \u0627\u0633 \u0642\u0627\u0628\u0644 \u06c1\u0648 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2:<\/p>\n<ul>\n<li>\n<p>\u0646\u06a9\u0627\u0644\u0646\u06d2\u060c \u062a\u0628\u062f\u06cc\u0644\u06cc\u060c \u0627\u0648\u0631 \u0628\u0648\u062c\u06be \u06a9\u06d2 \u0646\u0645\u0648\u0646\u0648\u06ba \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u0627\u0648\u0631 \u0646\u0641\u0627\u0630 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u0632\u06af\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 \u06a9\u0627 \u0627\u0646\u062a\u0638\u0627\u0645 <code>@dataclass<\/code> \u062c\u06af\u06c1 \u062c\u06af\u06c1 \u0645\u0633\u062a\u0642\u0644 \u0628\u06a9\u06be\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2<\/p>\n<\/li>\n<li>\n<p>API \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u0648\u0688 \u0644\u06a9\u06be\u06cc\u06ba \u062c\u0648 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u06cc \u0646\u0627\u06a9\u0627\u0645\u06cc\u0648\u06ba \u0627\u0648\u0631 \u0635\u0641\u062d\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u06d2 \u062c\u0648\u0627\u0628\u0627\u062a \u0633\u06d2 \u0628\u0686 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06a9\u0633\u06cc \u0627\u06cc\u06a9 \u063a\u0644\u0637 \u0642\u0637\u0627\u0631 \u06a9\u0648 \u067e\u0648\u0631\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u067e\u0631 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u0648 \u0631\u0648\u06a9\u0646\u06d2 \u0633\u06d2 \u0631\u0648\u06a9\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0633\u062e\u062a \u0642\u0633\u0645 \u06a9\u0627 \u062c\u0628\u0631 \u0646\u0627\u0641\u0630 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u0646\u06a9\u0631\u06cc\u0645\u0646\u0679\u0644 \u0688\u06cc\u0679\u0627 \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0627\u0648\u0631 \u0627\u0646\u0636\u0645\u0627\u0645 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u0648 \u0627\u06cc\u06a9 \u0642\u0627\u0628\u0644 \u062a\u0642\u0644\u06cc\u062f\u060c \u0634\u06cc\u0688\u0648\u0644 \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u06c1\u0633\u062a\u06cc \u0633\u06d2 \u062c\u0648\u0691\u0646\u0627 <code>main()<\/code> \u062f\u0627\u062e\u0644\u06c1 \u067e\u0648\u0627\u0626\u0646\u0679<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-table-of-contents\">\u0627\u0634\u0627\u0631\u06cc\u06c1:<\/h3>\n<h2 id=\"heading-prerequisites\">\u0634\u0631\u0637\u06cc\u06ba<\/h2>\n<ul>\n<li>\n<p><strong>Python 3.10+<\/strong>. \u06a9\u0648\u0688 \u0642\u0633\u0645 \u06a9\u06d2 \u0627\u0634\u0627\u0631\u06d2 \u0627\u0648\u0631 \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633\u0632 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 Python 3.7 \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 3.10+ \u0628\u06c1\u062a\u0631\u06cc\u0646 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u067e\u0627\u0646\u0688\u0627 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u06a9\u0627 \u0639\u0644\u0645<\/strong>: \u0688\u06cc\u0679\u0627 \u067e\u0691\u06be\u06cc\u06ba\u060c \u0642\u0637\u0627\u0631\u0648\u06ba \u06a9\u0648 \u0641\u0644\u0679\u0631 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0648\u0631 \u06a9\u0627\u0644\u0645 \u06a9\u06d2 \u0628\u0646\u06cc\u0627\u062f\u06cc \u06a9\u0627\u0645 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0622\u0631\u0627\u0645 <strong>\u0627\u0641\u0639\u0627\u0644 \u0627\u0648\u0631 \u0628\u0646\u06cc\u0627\u062f\u06cc OOP<\/strong> (\u0622\u0628\u062c\u06cc\u06a9\u0679 \u0627\u0648\u0631\u06cc\u0646\u0679\u0688 \u067e\u0631\u0648\u06af\u0631\u0627\u0645\u0646\u06af) \u0627\u0632\u06af\u0631\u06d4 \u0641\u06a9\u0631 \u0646\u06c1 \u06a9\u0631\u0648\u06d4 \u06cc\u06c1 \u06af\u0627\u0626\u06cc\u0688 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0627\u06cc\u0633\u06cc \u0686\u06cc\u0632 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u06d2 \u06af\u0627 \u062c\u0648 \u0622\u067e \u06a9\u06d2 \u062c\u0627\u062a\u06d2 \u0648\u0642\u062a \u0648\u0627\u0636\u062d \u0646\u06c1 \u06c1\u0648\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u062e\u062a\u06cc\u0627\u0631\u06cc: \u0627\u06cc\u06a9 \u0645\u0641\u062a Kaggle \u0627\u06a9\u0627\u0624\u0646\u0679 \u0627\u0648\u0631 Kaggle CLI (\u0635\u0631\u0641 \u0627\u0633 \u0635\u0648\u0631\u062a \u0645\u06cc\u06ba \u062c\u0628 \u0622\u067e \u062d\u062a\u0645\u06cc \u0627\u0634\u0627\u0639\u062a \u06a9\u06d2 \u0645\u0631\u0627\u062d\u0644 \u06a9\u0648 \u0686\u0644\u0627\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba)<\/p>\n<\/li>\n<\/ul>\n<p>\u0627\u0646\u062d\u0635\u0627\u0631 \u0627\u0646\u0633\u0679\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-bash\">pip install requests pandas numpy ipykernel\n<\/code><\/pre>\n<p>\u0622\u067e Jupyter \u0646\u0648\u0679 \u0628\u06a9 \u06a9\u06d2 \u0627\u0646\u062f\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4 \u0688\u0627\u0624\u0646 \u0644\u0648\u0688 \u06a9\u0631\u06cc\u06ba <code>.ipynb<\/code> \u0622\u067e Kaggle \u0633\u06d2 \u0641\u0627\u0626\u0644 \u0688\u0627\u0624\u0646 \u0644\u0648\u0688 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06cc\u0627 Kaggle \u067e\u0631 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u06a9\u0627\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 &quot;\u06a9\u0627\u067e\u06cc \u0627\u0648\u0631 \u062a\u0631\u0645\u06cc\u0645 \u06a9\u0631\u06cc\u06ba&#8221; \u067e\u0631 \u06a9\u0644\u06a9 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0627\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0622\u067e \u06a9\u0648 \u0627\u06cc\u06a9 Kaggle \u0627\u06a9\u0627\u0624\u0646\u0679 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06af\u06cc\u06d4<\/p>\n<p><strong>\u0627\u062e\u062a\u06cc\u0627\u0631\u06cc:<\/strong> \u0627\u06af\u0631 \u0622\u067e \u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0646\u0648\u0679 \u0628\u06a9 \u0686\u0644\u0627\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>notebook<\/code> \u067e\u06cc\u06a9\u06cc\u062c \u0628\u06be\u06cc:<\/p>\n<pre><code class=\"language-bash\">pip install notebook\n<\/code><\/pre>\n<h2 id=\"heading-part-1-the-design-logic\">\u062d\u0635\u06c1 1: \u0688\u06cc\u0632\u0627\u0626\u0646 \u0645\u0646\u0637\u0642<\/h2>\n<p>\u06a9\u0648\u0688 \u06a9\u06cc \u0627\u06cc\u06a9 \u0644\u0627\u0626\u0646 \u06a9\u0648 \u0686\u06be\u0648\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06c1\u0645 3 \u0645\u0646\u0679 \u06af\u0632\u0627\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <em>\u06a9\u06cc\u0648\u06ba<\/em> \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0627\u0633 \u0637\u0631\u062d \u0646\u0638\u0631 \u0622\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u06c1\u06d2 <strong>\u0628\u0691\u06cc \u062a\u0635\u0648\u06cc\u0631 \u062f\u06cc\u06a9\u06be\u06cc\u06ba<\/strong>. \u06a9\u0648\u0688 \u06a9\u06cc \u0633\u0637\u062d \u06a9\u0627 \u06c1\u0631 \u0641\u06cc\u0635\u0644\u06c1 \u0628\u0639\u062f \u0645\u06cc\u06ba \u0627\u0646 \u062e\u06cc\u0627\u0644\u0627\u062a \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0633\u06cc \u0627\u06cc\u06a9 \u06a9\u0627 \u067e\u062a\u06c1 \u0644\u06af\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u062d\u0635\u06d2 \u06a9\u0648 \u067e\u0691\u06be\u06cc\u06ba \u06cc\u06c1\u0627\u06ba \u062a\u06a9 \u06a9\u06c1 \u0627\u06af\u0631 \u0622\u067e \u0628\u0627\u0642\u06cc \u0633\u0628 \u06a9\u0686\u06be \u0686\u06be\u0648\u0691 \u062f\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-what-is-an-etl-pipeline\">ETL \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06cc\u0627 \u06c1\u06d2\u061f<\/h3>\n<p>ETL \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2\u06d4 <strong>\u0646\u06a9\u0627\u0644\u0646\u0627\u060c \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u0627\u060c \u0644\u0648\u0688 \u06a9\u0631\u0646\u0627<\/strong>. \u06cc\u06c1 \u0688\u06cc\u0679\u0627 \u06a9\u0648 \u0645\u0627\u062e\u0630 \u0633\u06d2 \u0645\u0646\u0632\u0644 \u062a\u06a9 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0627\u0646\u062f\u0627\u0632 \u0645\u06cc\u06ba \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0627\u06cc\u06a9 \u0645\u0639\u06cc\u0627\u0631\u06cc \u0646\u0645\u0648\u0646\u06c1 \u06c1\u06d2\u06d4<\/p>\n<ul>\n<li>\n<p><strong>\u0646\u06a9\u0627\u0644\u0646\u0627<\/strong>: APIs\u060c \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0627\u0648\u0631 \u0641\u0627\u0626\u0644\u0648\u06ba \u062c\u06cc\u0633\u06d2 \u0630\u0631\u0627\u0626\u0639 \u0633\u06d2 \u0688\u06cc\u0679\u0627 \u062f\u0631\u0622\u0645\u062f \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u062a\u0628\u062f\u06cc\u0644\u06cc<\/strong>: \u0627\u067e\u0646\u06d2 \u0688\u06cc\u0679\u0627 \u06a9\u0648 \u0635\u0627\u0641\u060c \u0645\u0639\u06cc\u0627\u0631\u06cc\u060c \u0627\u0641\u0632\u0648\u062f\u06c1 \u0627\u0648\u0631 \u062f\u0631\u0633\u062a \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p><strong>\u0644\u0648\u0688<\/strong>: \u0646\u062a\u0627\u0626\u062c \u06a9\u0648 \u06a9\u0633\u06cc \u0645\u0646\u0632\u0644 \u067e\u0631 \u0644\u0627\u06af \u0627\u0646 \u06a9\u0631\u06cc\u06ba \u062c\u06cc\u0633\u06d2 \u06af\u0648\u062f\u0627\u0645\u060c CSV\u060c \u06cc\u0627 \u0639\u0648\u0627\u0645\u06cc \u067e\u0644\u06cc\u0679 \u0641\u0627\u0631\u0645\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u06cc\u06c1\u0627\u06ba \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u062a\u06cc\u0646 \u0645\u0631\u0627\u062d\u0644 \u0627\u0633 \u0645\u0646\u0635\u0648\u0628\u06d2 \u06a9\u0627 \u0646\u0642\u0634\u06c1 \u06a9\u06cc\u0633\u06d2 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba:<\/p>\n<table>\n<thead>\n<tr>\n<th>\u0642\u062f\u0645<\/th>\n<th>\u06cc\u06c1\u0627\u06ba \u06a9\u06cc\u0627 \u06c1\u0648\u062a\u0627 \u06c1\u06d2<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>\u0646\u06a9\u0627\u0644\u0646\u0627<\/strong><\/td>\n<td>\u0627\u06af\u0631 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u0645\u0648\u062c\u0648\u062f\u06c1 \u0688\u06cc\u0679\u0627 \u06c1\u06d2 \u062a\u0648 \u0627\u0633\u06d2 \u0644\u0648\u0688 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u067e\u06be\u0631 (\u0628\u0630\u0631\u06cc\u0639\u06c1) Hub&#8217;Eau API \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>requests<\/code>) \u06c1\u0631 \u067e\u06cc\u0645\u0627\u0626\u0634\u06cc \u0627\u0633\u0679\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2<\/td>\n<\/tr>\n<tr>\n<td><strong>\u062a\u0628\u062f\u06cc\u0644\u06cc<\/strong><\/td>\n<td>\u0641\u0631\u0627\u0646\u0633\u06cc\u0633\u06cc \u06a9\u0627\u0644\u0645\u0648\u06ba \u0627\u0648\u0631 \u0622\u0626\u0679\u0645\u0632 \u06a9\u0627 \u0627\u0646\u06af\u0631\u06cc\u0632\u06cc \u0645\u06cc\u06ba \u062a\u0631\u062c\u0645\u06c1 \u06a9\u0631\u06cc\u06ba\u060c \u0688\u06cc\u0679\u0627 \u06a9\u06cc \u0642\u0633\u0645\u06cc\u06ba \u062f\u0631\u0633\u062a \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0646\u0642\u0644\u06cc\u06ba \u06c1\u0679\u0627 \u062f\u06cc\u06ba\u06d4<\/td>\n<\/tr>\n<tr>\n<td><strong>\u0644\u0648\u0688<\/strong><\/td>\n<td>CSV \u0627\u0648\u0631 \u0645\u06cc\u0679\u0627 \u0688\u06cc\u0679\u0627 \u0641\u0627\u0626\u0644\u06cc\u06ba \u0628\u0646\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0646\u06c1\u06cc\u06ba CLI \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 Kaggle \u067e\u0631 \u0634\u0627\u0626\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3 id=\"heading-the-architecture-at-a-glance\">\u0641\u0646 \u062a\u0639\u0645\u06cc\u0631 \u06a9\u0627 \u062c\u0627\u0626\u0632\u06c1<\/h3>\n<p><img decoding=\"async\" src=\"https:\/\/umang.pk\/wp-content\/uploads\/2026\/07\/1785237512_507_\u0627\u06cc-\u0679\u06cc-\u0627\u06cc\u0644-\u067e\u0627\u0626\u067e-\u0644\u0627\u0626\u0646\u0632-\u06c1\u06cc\u0646\u0688-\u0628\u06a9-\u0627\u0632\u06af\u0631-\u0645\u06cc\u06ba-\u067e\u0631\u0648\u0688\u06a9\u0634\u0646.png\" alt=\"\u0627\u06cc\u06a9 \u0633\u0627\u062f\u06c1 ETL \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0627 \u0633\u06a9\u06cc\u0645\u0627\u06d4\" style=\"display:block;margin:0 auto\" width=\"2040\" height=\"900\" loading=\"lazy\" title=\"\"><\/p>\n<p>&quot;\u0627\u0642\u062a\u0628\u0627\u0633&#8221; \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u062f\u0648 \u0645\u062e\u062a\u0644\u0641 \u0630\u0631\u0627\u0626\u0639 \u0633\u06d2 \u0645\u0646\u0633\u0644\u06a9 \u06c1\u06d2\u06d4 <em>\u0645\u0648\u062c\u0648\u062f\u06c1<\/em> \u0688\u06cc\u0679\u0627\u0633\u06cc\u0679 (\u062c\u0648 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u06c1\u06d2) <em>\u0646\u06cc\u0627<\/em> API \u0633\u06d2 \u0688\u06cc\u0679\u0627\u06d4 \u06cc\u06c1 \u0627\u0645\u062a\u06cc\u0627\u0632 \u0627\u06af\u0644\u06d2 \u062e\u06cc\u0627\u0644 \u06a9\u0627 \u0628\u06cc\u062c \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-two-patterns-that-make-it-production-grade\">\u0627\u0633\u06d2 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u06af\u0631\u06cc\u0688 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0648 \u067e\u06cc\u0679\u0631\u0646<\/h3>\n<p>\u062f\u0648 \u0646\u0645\u0648\u0646\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u0627\u0633 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0686\u0644\u0627\u0646\u0627 \u0645\u0645\u06a9\u0646 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0633\u0627\u0644\u0648\u06ba \u062a\u06a9 \u063a\u06cc\u0631 \u062a\u0648\u062c\u06c1 \u0634\u062f\u06c1 \u0634\u06cc\u0688\u0648\u0644\u0646\u06af \u06a9\u06d2 \u0633\u0627\u062a\u06be\u06d4<\/p>\n<h4 id=\"heading-1-idempotency\">1. \u0628\u06d2 \u062d\u0633\u06cc\u06d4<\/h4>\n<p><strong>\u0628\u06d2 \u062d\u0633\u06cc<\/strong> \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u0627\u06cc\u06a9 \u06c1\u06cc \u06a9\u0627\u0645 \u06a9\u0648 \u062f\u0648 \u0628\u0627\u0631 \u0686\u0644\u0627\u0646\u06d2 \u0633\u06d2 \u0648\u06c1\u06cc \u0646\u062a\u0627\u0626\u062c \u0628\u0631\u0622\u0645\u062f \u06c1\u0648\u06ba \u06af\u06d2 \u062c\u06cc\u0633\u06d2 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0686\u0644\u0627\u0626\u06d2 \u06af\u0626\u06d2 \u062a\u06be\u06d2\u06d4 \u0646\u0642\u0644 \u06c1\u06cc \u0648\u06c1 \u0686\u06cc\u0632 \u06c1\u06d2 \u062c\u0648 \u0627\u0633 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u06a9\u0645\u0632\u0648\u0631 \u0628\u0646\u0627\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0634\u06cc\u0688\u06cc\u0648\u0644\u0631 \u063a\u0644\u0637\u06cc \u0633\u06d2 \u062f\u0648 \u0628\u0627\u0631 \u0679\u0631\u06af\u0631 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2 \u06cc\u0627 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u06cc \u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0648\u0634\u0634 \u0627\u0633\u06cc \u062f\u0646 \u0627\u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0644\u0627\u062a\u06cc \u06c1\u06d2\u060c \u062a\u0648 \u062f\u0648\u0633\u0631\u06cc \u0631\u0646 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0642\u0637\u0627\u0631\u06cc\u06ba \u0646\u06c1\u06cc\u06ba \u0628\u0646\u0627\u0626\u06d2 \u06af\u06cc\u06d4 \u06cc\u06c1 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0686\u06cc\u0632 \u06a9\u06d2 \u0644\u0626\u06d2 \u0628\u06c1\u062a \u0627\u06c1\u0645 \u06c1\u06d2 \u062c\u0648 \u06a9\u0633\u06cc \u06a9\u06d2 \u062f\u06cc\u06a9\u06be\u06d2 \u0628\u063a\u06cc\u0631 \u0634\u06cc\u0688\u0648\u0644 \u067e\u0631 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-2-incremental-loading\">2. \u0627\u0636\u0627\u0641\u06cc \u0644\u0648\u0688\u0646\u06af<\/h4>\n<p>\u0628\u0648\u0644\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06c1\u06d2 <em>\u067e\u0648\u0631\u06cc<\/em> \u062a\u0645\u0627\u0645 \u0631\u0646\u0632 \u06a9\u0627 \u0631\u06cc\u06a9\u0627\u0631\u0688\u06d4 \u06cc\u06c1 \u0633\u0633\u062a \u06c1\u06d2\u060c API \u06a9\u0648\u0679\u06c1 \u0636\u0627\u0626\u0639 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u06a9\u0645\u0632\u0648\u0631 \u06c1\u06d2\u06d4 \u0622\u067e \u062c\u062a\u0646\u0627 \u0632\u06cc\u0627\u062f\u06c1 \u0688\u06cc\u0679\u0627 \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u060c \u0627\u0633 \u06a9\u06d2 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u0646\u06d2 \u06a9\u0627 \u0627\u0645\u06a9\u0627\u0646 \u0627\u062a\u0646\u0627 \u06c1\u06cc \u0632\u06cc\u0627\u062f\u06c1 \u06c1\u06d2\u06d4<\/p>\n<p>\u0646\u06c1\u06cc\u06ba <strong>\u0627\u0636\u0627\u0641\u06c1<\/strong> \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646\u06cc\u06ba \u0627\u0633 \u06a9\u0648 \u0631\u0648\u06a9\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0627\u0633 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u06cc\u06c1 \u06c1\u06d2:<\/p>\n<ul>\n<li>\n<p>\u0688\u06cc\u0679\u0627 \u0633\u06cc\u0679 \u0645\u06cc\u06ba \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u06c1\u06cc \u062a\u0627\u0632\u06c1 \u062a\u0631\u06cc\u0646 \u062a\u0627\u0631\u06cc\u062e \u06a9\u0648 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0635\u0631\u0641 \u0688\u06cc\u0679\u0627 \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0631\u06cc\u06ba\u06d4 <em>\u0627\u0633 \u062a\u0627\u0631\u06cc\u062e \u0633\u06d2<\/em><\/p>\n<\/li>\n<li>\n<p>\u0646\u0626\u06d2 \u0631\u06cc\u06a9\u0627\u0631\u0688\u0632 \u06a9\u0648 \u0645\u0648\u062c\u0648\u062f\u06c1 \u0688\u06cc\u0679\u0627\u0633\u06cc\u0679 \u0645\u06cc\u06ba \u0636\u0645 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u06cc\u06c1 \u0645\u0646\u0637\u0642 \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 \u0628\u0646\u0627\u0626\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4 <code>determine_update_range<\/code>.<\/p>\n<p>\u06c1\u0645\u06cc\u0634\u06c1 \u0627\u067e\u0646\u06d2 \u0622\u067e \u0633\u06d2 \u067e\u0648\u0686\u06be\u06cc\u06ba: <strong>&quot;\u06a9\u06cc\u0627 \u0645\u062c\u06be\u06d2 \u0648\u0627\u0642\u0639\u06cc \u06cc\u06c1 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u061f&#8221;<\/strong> \u0627\u0646 \u0639\u0627\u062f\u0627\u062a \u0645\u06cc\u06ba \u0633\u06d2 \u0627\u06cc\u06a9 \u06a9\u0645\u0632\u0648\u0631 \u0627\u0633\u06a9\u0631\u067e\u0679 \u06a9\u0648 \u067e\u0631\u0648\u0688\u06a9\u0634\u0646 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0633\u06d2 \u0627\u0644\u06af \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4 \u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631\u060c \u0627\u0633 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06d2 \u062a\u0645\u0627\u0645 &quot;\u0645\u06c1\u0646\u06af\u06d2&#8221; \u06cc\u0627 &quot;\u0628\u06cc\u0631\u0648\u0646\u06cc&#8221; \u0645\u0631\u0627\u062d\u0644 (\u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u0627\u0644\u0632\u060c \u0688\u0633\u06a9 \u0631\u0627\u0626\u0679\u060c \u067e\u0648\u0633\u0679\u0633) \u0633\u0628 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0633\u0633\u062a\u06d2 \u0645\u0642\u0627\u0645\u06cc \u0686\u06cc\u06a9 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0645\u062d\u0641\u0648\u0638 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<h2 id=\"heading-part-2-setup-and-dependencies\">\u062d\u0635\u06c1 2: \u062a\u0631\u062a\u06cc\u0628 \u0627\u0648\u0631 \u0627\u0646\u062d\u0635\u0627\u0631<\/h2>\n<p>\u06cc\u06c1\u0627\u06ba \u0627\u0645\u067e\u0648\u0631\u0679 \u0628\u0644\u0627\u06a9 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u063a\u06cc\u0631 \u0648\u0627\u0636\u062d \u0645\u0639\u0644\u0648\u0645 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u060c \u0644\u06cc\u06a9\u0646 \u062c\u0633 \u0637\u0631\u062d \u0633\u06d2 \u0627\u0633\u06d2 \u0645\u0646\u0638\u0645 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2 \u0648\u06c1 \u0642\u0627\u0628\u0644 \u0630\u06a9\u0631 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\"># Standard library imports\nimport json\nimport os\nimport random\nimport subprocess\nfrom dataclasses import dataclass, field\nfrom datetime import date, timedelta\nfrom pathlib import Path\nfrom typing import Dict, List, Optional, Set, Tuple\n\n# Third-party libraries\nimport numpy as np\nimport pandas as pd\nimport requests\n\n# Display config for notebooks\npd.set_option('display.max_columns', None)   # All columns will show\npd.set_option('display.max_colwidth', None)  # Prevents cutting long column text with ...\n<\/code><\/pre>\n<p><strong>\u06a9\u0648\u0688 \u06a9\u06cc \u0633\u0637\u062d \u06a9\u06d2 \u0646\u0648\u0679\u0633:<\/strong><\/p>\n<ul>\n<li>\n<p>\u062f\u0631\u0622\u0645\u062f\u0627\u062a \u06a9\u0648 \u062a\u06cc\u0646 \u0628\u0644\u0627\u06a9\u0633 \u0645\u06cc\u06ba \u062a\u0642\u0633\u06cc\u0645 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2: <strong>\u0645\u0639\u06cc\u0627\u0631\u06cc \u0644\u0627\u0626\u0628\u0631\u06cc\u0631\u06cc\u060c \u062a\u06cc\u0633\u0631\u06cc \u067e\u0627\u0631\u0679\u06cc\u060c \u0645\u0642\u0627\u0645\u06cc<\/strong>\u062f\u0631\u0645\u06cc\u0627\u0646 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u062e\u0627\u0644\u06cc \u0644\u06a9\u06cc\u0631 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u067e\u06cc \u0627\u06cc \u067e\u06cc 8 \u0633\u06d2 \u062f\u0631\u0622\u0645\u062f\u06cc \u0622\u0631\u0688\u0631 \u06a9\u06d2 \u0642\u0648\u0627\u0646\u06cc\u0646 \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0632\u06cc\u0627\u062f\u06c1 \u062a\u0631 \u062e\u0648\u062f\u06a9\u0627\u0631 \u0641\u0627\u0631\u0645\u06cc\u0679\u0631\u0632 (<code>isort<\/code>\u060c <code>ruff<\/code>) \u0627\u0633\u06cc \u06af\u0631\u0648\u067e \u0628\u0646\u062f\u06cc \u06a9\u0648 \u0644\u0627\u06af\u0648 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u06af\u0644\u0627\u060c \u06a9\u0686\u06be \u0628\u06be\u06cc \u062f\u0631\u0622\u0645\u062f \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627. <code>from module import *<\/code>. \u06cc\u06c1 \u0628\u06cc\u0627\u0646 \u0645\u0648\u062c\u0648\u062f\u06c1 \u0646\u0627\u0645 \u06a9\u06cc \u062c\u06af\u06c1 \u06a9\u0648 \u0622\u0644\u0648\u062f\u06c1 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u062c\u0628 \u06a9\u0648\u0626\u06cc \u0622\u067e \u06a9\u06d2 \u06a9\u0648\u0688 \u06a9\u0648 \u0686\u06be \u0645\u0627\u06c1 \u0628\u0639\u062f \u0688\u06cc\u0628\u06af \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u0633 \u06a9\u0627 \u067e\u062a\u06c1 \u0644\u06af\u0627\u0646\u0627 \u0645\u0634\u06a9\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0646\u0627\u0645 \u06a9\u06c1\u0627\u06ba \u0633\u06d2 \u0622\u06cc\u0627 \u06c1\u06d2\u06d4 Python \u0633\u0679\u0627\u0626\u0644 \u06af\u0627\u0626\u06cc\u0688\u0632 \u0627\u0633 \u0645\u0634\u0648\u0631\u06d2 \u06a9\u06cc \u0628\u0627\u0632\u06af\u0634\u062a \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0628\u0634\u0645\u0648\u0644 Google \u06a9\u06cc Python \u0633\u0679\u0627\u0626\u0644 \u06af\u0627\u0626\u06cc\u0688\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06a9\u06c1 <code>pd.set_option(...)<\/code> \u06a9\u0627\u0644 \u062e\u0627\u0644\u0635\u062a\u0627\u064b \u0648\u062c\u0648\u062f\u06cc \u06c1\u06d2\u06d4 <em>\u0644\u06cc\u067e \u0679\u0627\u067e \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06cc \u0627\u06c1\u0644\u06cc\u062a<\/em>\u0627\u062a\u0646\u06d2 \u0648\u0633\u06cc\u0639 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645\u0648\u06ba \u06a9\u0648 \u0686\u06be\u0648\u0679\u0627 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4 <code>...<\/code>. \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06cc \u0645\u0646\u0637\u0642 \u067e\u0631 \u0627\u0633 \u06a9\u0627 \u06a9\u0648\u0626\u06cc \u0627\u062b\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627\u06d4 \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u0622\u067e \u0627\u0633\u06d2 \u06a9\u0633\u06cc \u0627\u0648\u0631 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06c1\u0679\u0627 \u062f\u06cc\u06ba \u06af\u06d2 \u06cc\u0627 \u062f\u0627\u0626\u0631\u06c1 \u06a9\u0627\u0631 \u0628\u0646\u0627\u0626\u06cc\u06ba \u06af\u06d2\u06d4 <code>.py<\/code> \u0633\u06a9\u0631\u067e\u0679<\/p>\n<\/li>\n<\/ul>\n<h2 id=\"heading-part-3-manage-configuration-with-dataclasses\">\u062d\u0635\u06c1 3: \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633\u0632 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u06a9\u0648 \u0645\u0646\u0638\u0645 \u06a9\u0631\u0646\u0627<\/h2>\n<h3 id=\"heading-why-bother-with-a-config-layer-at-all\">\u0622\u067e \u06a9\u0648 \u06a9\u0645\u067e\u0648\u0632\u06cc\u0634\u0646 \u0644\u06cc\u0626\u0631\u0632 \u06a9\u0627 \u062e\u06cc\u0627\u0644 \u06a9\u06cc\u0648\u06ba \u0631\u06a9\u06be\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u061f<\/h3>\n<p>\u06c1\u0631 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0645\u06cc\u06ba <strong>\u062f\u0633\u062a\u06a9<\/strong>: \u0646\u06af\u0631\u0627\u0646\u06cc \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u0679\u06cc\u0634\u0646\u060c \u0633\u06cc\u0644\u0627\u0628 \u06a9\u06cc \u062d\u062f \u0627\u0648\u0631 \u067e\u0648\u0633\u0679\u0646\u06af \u06a9\u06d2 \u0645\u0642\u0627\u0645\u0627\u062a\u06d4 \u0627\u06cc\u06a9 \u0628\u0631\u0627 \u0637\u0631\u06cc\u0642\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u062c\u0628 \u0622\u067e \u0627\u0633\u06d2 \u0644\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba \u062a\u0648 \u0627\u0646 \u0627\u0642\u062f\u0627\u0631 \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u067e\u0648\u0631\u06d2 \u06a9\u0648\u0688 \u0645\u06cc\u06ba \u0644\u0641\u0638\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0686\u06be\u0691\u06a9\u0646\u0627 \u06c1\u06d2\u06d4 \u062a\u0645 \u062e\u062a\u0645 \u06a9\u0631\u0648 <code>if level > 6000:<\/code> \u062a\u06cc\u0646 \u0627\u0641\u0639\u0627\u0644 \u06af\u06c1\u0631\u0627\u0626\u06cc \u0645\u06cc\u06ba \u062f\u0628 \u06af\u0626\u06d2\u06d4 \u067e\u06be\u0631 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba <em>\u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc<\/em> \u0627\u0633\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0646\u06d2 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u067e\u0648\u0631\u06cc \u0641\u0627\u0626\u0644 \u06a9\u0648 \u0627\u0633\u06a9\u06cc\u0646 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u067e\u0648\u0627\u0626\u0646\u0679 \u06a9\u0648 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u0646\u0627 \u0627\u0648\u0631 \u062f\u0648\u0633\u0631\u06d2 \u06a9\u0648 \u06cc\u0627\u062f \u06a9\u0631\u0646\u0627 \u0622\u0633\u0627\u0646 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0635\u0644\u0627\u062d\u0627\u062a: <strong>\u0627\u067e\u0646\u06cc \u062a\u0645\u0627\u0645 \u062a\u0631\u062a\u06cc\u0628\u0627\u062a \u06a9\u0648 \u0627\u06cc\u06a9 \u062c\u06af\u06c1 \u067e\u0631 \u0633\u0646\u0679\u0631\u0644\u0627\u0626\u0632 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong> \u0627\u0632\u06af\u0631 \u06a9\u06cc <code>@dataclass<\/code> \u0688\u06cc\u06a9\u0648\u0631\u06cc\u0679\u0631 \u0627\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06c1\u062a\u0631\u06cc\u0646 \u06c1\u06cc\u06ba\u06d4<\/p>\n<table>\n<thead>\n<tr>\n<th>\u062e\u0635\u0648\u0635\u06cc\u062a<\/th>\n<th>\u06cc\u06c1 \u06a9\u06cc\u0648\u06ba \u0636\u0631\u0648\u0631\u06cc \u06c1\u06d2\u061f<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>\u062e\u0648\u062f \u06a9\u0627\u0631 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u067e\u06cc\u062f\u0627 <code>__init__<\/code>\u060c <code>__repr__<\/code>\u060c <code>__eq__<\/code><\/td>\n<td>\u0622\u067e \u06a9\u0648 \u062e\u0648\u062f \u0644\u06a9\u06be\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/td>\n<\/tr>\n<tr>\n<td>\u0627\u0634\u0627\u0631\u06c1 \u062f\u0631\u062c \u06a9\u0631\u06cc\u06ba\u06d4<\/td>\n<td>IDE \u062e\u0648\u062f\u06a9\u0627\u0631 \u062a\u06a9\u0645\u06cc\u0644 \u0627\u0648\u0631 \u062e\u0648\u062f \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u06cc \u06a9\u0648\u0688 \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/td>\n<\/tr>\n<tr>\n<td>\u0627\u062e\u062a\u06cc\u0627\u0631\u06cc <code>frozen=True<\/code><\/td>\n<td>\u0627\u06af\u0631 \u0622\u067e \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 \u0646\u0648\u0628\u0633 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0646\u06c1\u06cc\u06ba \u062a\u062e\u0644\u06cc\u0642 \u06a9\u06d2 \u0628\u0639\u062f \u062a\u0628\u062f\u06cc\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u062a\u0648 \u06cc\u06c1 \u062d\u0642\u06cc\u0642\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/td>\n<\/tr>\n<tr>\n<td><code>__post_init__<\/code>    \u06c1\u06a9<\/td>\n<td>\u062a\u062e\u0644\u06cc\u0642 \u06a9\u06d2 \u0641\u0648\u0631\u0627\u064b \u0628\u0639\u062f \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0627\u062e\u0630 \u06a9\u0631\u062f\u06c1 \u0641\u06cc\u0644\u0688\u0632 \u06a9\u06cc \u062a\u0648\u062b\u06cc\u0642 \u06cc\u0627 \u062d\u0633\u0627\u0628 \u0644\u06af\u0627\u0626\u06cc\u06ba\u06d4<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>\u0627\u0633 \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1 \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u0644\u06a9\u06be\u06cc \u06af\u0626\u06cc \u062a\u0631\u062a\u06cc\u0628 \u0633\u06d2 \u06a9\u0631\u06cc\u06ba\u06d4 <code>dict<\/code>:<\/p>\n<pre><code class=\"language-python\">config = {\n    \"stations\": [\"STN001\", \"STN002\"],\n    \"flood_threshold\": 6000,\n    \"publish_url\": \"https:\/\/example.com\/alerts\",\n    \"retry_count\": 2,\n    \"timeout_seconds\": 5,\n}\n<\/code><\/pre>\n<p>\u0628\u0627\u0642\u0627\u0639\u062f\u06af\u06cc \u0633\u06d2 \u0644\u063a\u0627\u062a \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644\u06cc\u060c \u0679\u0627\u0626\u067e \u0686\u06cc\u06a9\u0646\u06af\u060c \u0627\u0648\u0631 \u062e\u0648\u062f\u06a9\u0627\u0631 \u062a\u06a9\u0645\u06cc\u0644 \u06a9\u06cc \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u0641\u0631\u0627\u06c1\u0645 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<h3 id=\"heading-code-level-walkthrough\">\u06a9\u0648\u0688 \u0644\u06cc\u0648\u0644 \u0648\u0627\u06a9 \u062a\u06be\u0631\u0648<\/h3>\n<p>\u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u062a\u06cc\u0646 \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646 \u06a9\u0644\u0627\u0633\u0632 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u06cc \u06c1\u06d2: \u06c1\u0631 \u0634\u062e\u0635 \u06a9\u06d2 \u067e\u0627\u0633 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 <em>\u0627\u06cc\u06a9 \u0630\u0645\u06c1 \u062f\u0627\u0631\u06cc<\/em>: API \u062a\u0641\u0635\u06cc\u0644\u0627\u062a\u060c \u0627\u0633\u0679\u06cc\u0634\u0646 \u06a9\u06d2 \u0642\u0648\u0627\u0639\u062f \u0627\u0648\u0631 \u0627\u0634\u0627\u0639\u062a \u06a9\u06d2 \u0645\u0642\u0627\u0645\u0627\u062a\u06d4 \u06c1\u0631 \u0637\u0628\u0642\u06c1 \u0627\u06cc\u06a9 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <strong>\u0645\u0627\u0688\u06cc\u0648\u0644 \u0644\u06cc\u0648\u0644 \u0633\u0646\u06af\u0644\u0679\u0646 \u0645\u062b\u0627\u0644<\/strong>. \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0645\u06cc\u06ba \u062f\u06cc\u06af\u0631 \u062a\u0645\u0627\u0645 \u0641\u0646\u06a9\u0634\u0646\u0632 \u0627\u0646 \u0633\u0646\u06af\u0644 \u0679\u0646 \u0633\u06d2 \u067e\u0691\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">@dataclass\nclass APIConfig:\n    \"\"\"API configuration for HubEau data fetching.\n\n    Think of this as the \"address book\" for the API.\n    \"\"\"\n    use_mock: bool = True\n    base_url: str = \"https:\/\/hubeau.eaufrance.fr\/api\/v2\/hydrometrie\/obs_elab\"\n    metric: str = \"HIXnJ\"  # Daily max water level (elaborated observations)\n    # Pagination: fetch 20k records per request (API Limit)\n    max_per_page: int = 20000\n    timeout_seconds: int = 60  # Network timeout\n\n    def __post_init__(self):\n        \"\"\"Validate configuration after initialization.\"\"\"\n        if self.max_per_page <= 0:\n            raise ValueError(\"max_per_page must be positive\")\n        if self.timeout_seconds <= 0:\n            raise ValueError(\"timeout_seconds must be positive\")\n<\/code><\/pre>\n<p>\u0627\u0646\u062f\u0631\u0648\u0646\u06cc \u062a\u0648\u062b\u06cc\u0642 \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631\u06cc\u06ba\u06d4 <code>__post_init__<\/code>. \u06cc\u06c1 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0628\u0646\u0646\u06d2 \u06a9\u06d2 \u0641\u0648\u0631\u0627\u064b \u0628\u0639\u062f \u0639\u0645\u0644 \u0645\u06cc\u06ba \u0644\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>__init__<\/code>. \u0646\u0627\u0642\u0635 \u062a\u0639\u0645\u06cc\u0631 <code>APIConfig(max_per_page=-1)<\/code> \u0627\u0635\u0644 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u06d2 \u0639\u0645\u0644 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0628\u0639\u062f \u0645\u06cc\u06ba \u0628\u06af \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u06cc\u06c1 \u0634\u0631\u0648\u0639 \u06c1\u0648\u0646\u06d2 \u067e\u0631 \u0632\u0648\u0631 \u0633\u06d2 \u0627\u0648\u0631 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\">@dataclass\nclass StationConfig:\n    \"\"\"Station monitoring configuration.\n\n    The 'what' of data collection: which stations, what's a flood?\n    \"\"\"\n    station_codes: List[str] = field(default_factory=lambda: [\n        \"F700000109\", \"F700000110\", \"F700000111\",\n        \"F700000102\", \"F700000103\",\n    ])\n    flood_threshold_mm: int = 6000  # Flood alert threshold\n    earliest_date: str = \"1900-01-01\"  # How far back to go\n<\/code><\/pre>\n<p><strong>\u0642\u0627\u0628\u0644 \u062a\u0628\u062f\u06cc\u0644\u06cc \u0688\u06cc\u0641\u0627\u0644\u0679 \u0679\u0631\u06cc\u067e\u0633:<\/strong> \u0642\u0631\u06cc\u0628 \u0633\u06d2 \u062f\u06cc\u06a9\u06be\u06cc\u06ba <code>station_codes<\/code>. \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0646\u06c1\u06cc\u06ba \u0644\u06a9\u06be\u0627 \u06c1\u06d2\u06d4 <code>station_codes: List[str] = [...]<\/code>. \u06cc\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0632\u06af\u0631 \u06a9\u06d2 \u0633\u0628 \u0633\u06d2 \u0639\u0627\u0645 \u0645\u0633\u0627\u0626\u0644 \u0645\u06cc\u06ba \u0633\u06d2 \u0627\u06cc\u06a9 \u0633\u06d2 \u0628\u0686\u062a\u0627 \u06c1\u06d2\u06d4 \u0688\u06cc\u0641\u0627\u0644\u0679 \u0622\u0631\u06af\u06cc\u0648\u0645\u06cc\u0646\u0679\u0633 \u06cc\u0627 \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633 \u0641\u06cc\u0644\u0688\u0632 \u06a9\u06d2 \u0628\u0637\u0648\u0631 \u0628\u0627\u0642\u0627\u0639\u062f\u06c1 \u062a\u0628\u062f\u06cc\u0644 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06cc \u0627\u0634\u06cc\u0627\u0621 (\u0641\u06c1\u0631\u0633\u062a\u06cc\u06ba\u060c \u0644\u063a\u0627\u062a\u060c \u06cc\u0627 \u0633\u06cc\u0679) \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a\u060c <strong>\u062a\u0645\u0627\u0645 \u0645\u062b\u0627\u0644\u06cc\u06ba \u0627\u06cc\u06a9 \u06c1\u06cc \u0628\u0646\u06cc\u0627\u062f\u06cc \u0686\u06cc\u0632 \u06a9\u0627 \u0627\u0634\u062a\u0631\u0627\u06a9 \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/strong>. \u0627\u06af\u0631 \u0622\u067e \u0627\u0633\u06d2 \u0627\u06cc\u06a9 \u0645\u062b\u0627\u0644 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u06cc\u06c1 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u06c1\u0631 \u062c\u06af\u06c1 \u0628\u062f\u0644 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u0627\u0633\u0679\u06cc\u06a9 \u0627\u0648\u0648\u0631 \u0641\u0644\u0648 \u0627\u0633 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \"\u06a9\u0645 \u0633\u06d2 \u06a9\u0645 \u062d\u06cc\u0631\u0627\u0646 \u06a9\u0646\" \u0645\u062a\u063a\u06cc\u0631 \u0688\u06cc\u0641\u0627\u0644\u0679 \u062f\u0644\u0627\u0626\u0644 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0627\u0646 \u06a9\u06cc \u0628\u062d\u062b \u0645\u06cc\u06ba \u062a\u0641\u0635\u06cc\u0644 \u0633\u06d2 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062c\u06cc\u0633\u0627 \u06a9\u06c1 \u0627\u0635\u0644\u06cc \u0627\u0632\u06af\u0631 \u0645\u06cc\u06ba \u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u062f\u0644\u0627\u0626\u0644 \u06a9\u06d2 \u0644\u0626\u06d2 \u0627\u0646 \u06a9\u06cc \u0631\u06c1\u0646\u0645\u0627\u0626\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1\u0627\u06ba \u0627\u0635\u0644\u0627\u062d\u0627\u062a \u06c1\u06cc\u06ba: <code>field(default_factory=...)<\/code>. \u06a9\u06c1 <em>\u062a\u0627\u0632\u06c1<\/em> \u0641\u06cc\u06a9\u0679\u0631\u06cc \u0641\u0646\u06a9\u0634\u0646 (\u06cc\u06c1\u0627\u06ba: <code>lambda<\/code>) \u06c1\u0631 \u0646\u0626\u06cc \u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u06c1\u0631 \u0645\u062b\u0627\u0644 \u06a9\u0648 \u0627\u067e\u0646\u06cc \u0622\u0632\u0627\u062f \u0641\u06c1\u0631\u0633\u062a \u0645\u0644\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0648\u0636\u0627\u062d\u062a:<\/p>\n<pre><code class=\"language-python\"># Bad: shared mutable default\n@dataclass\nclass BadConfig:\n    station_codes: list[str] = []\n\na = BadConfig()\nb = BadConfig()\n\na.station_codes.append(\"ALERT\")\nprint(a.station_codes)  # ['ALERT']\nprint(b.station_codes)  # ['ALERT']  <-- same list!!\n\n\n# Good: fresh list per instance\n@dataclass\nclass GoodConfig:\n    station_codes: list[str] = field(default_factory=list)\n\nx = GoodConfig()\ny = GoodConfig()\n\nx.station_codes.append(\"ALERT\")\nprint(x.station_codes)  # ['ALERT']\nprint(y.station_codes)  # []  <-- independent list\n<\/code><\/pre>\n<p>\u0627\u0648\u0631 \u0641\u0627\u0626\u0646\u0644 \u06a9\u0646\u0641\u06cc\u06af \u0633\u0646\u06af\u0644\u0679\u0646\u060c \u06a9\u0627\u06af\u0644 \u06a9\u0646\u0641\u06cc\u06af\u0631\u06cc\u0634\u0646\u060c \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u06c1\u06d2:<\/p>\n<pre><code class=\"language-python\">@dataclass\nclass KaggleConfig:\n    \"\"\"Kaggle dataset publishing configuration.\"\"\"\n    dataset_slug: str = \"grimespoint\/paris-flood-dataset\"\n    input_csv: str = \"kaggle\/input\/datasets\/{slug}\/paris_flood_dataset.csv\"\n    output_dir: Path = field(default_factory=lambda: Path(\"kaggle\/working\/kaggle_dataset\"))\n    mock_output_dir: Path = field(default_factory=lambda: Path(\"mock_output\"))\n    output_filename: str = \"paris_flood_dataset.csv\"\n    mock_output_filename: str = \"mock_flood_dataset.csv\"\n    metadata_filename: str = \"dataset-metadata.json\"\n\n    # Metadata\n    title: str = \"Paris flood dataset\"\n    keywords: list = field(default_factory=lambda: [\n        \"tabular\", \"weather and climate\", \"environment\", \"europe\", \"time series analysis\"\n    ])\n    geospatial_coverage: str = \"Paris, France\"\n    update_frequency: str = \"Weekly\"\n    license_name: str = \"CC0-1.0\"\n\n    # Computed fields (set in __post_init__)\n    output_csv_path: Path = field(init=False)\n    metadata_path: Path = field(init=False)\n\n    def __post_init__(self):\n        \"\"\"Compute derived paths after initialization.\"\"\"\n        self.input_csv = self.input_csv.format(slug=self.dataset_slug)\n        self.output_csv_path = self.output_dir \/ self.output_filename\n        self.metadata_path = self.output_dir \/ self.metadata_filename\n        self.mock_output_filename = self.mock_output_dir \/ self.mock_output_filename\n\n# Initialize configs - module-level singletons\nAPI_CONFIG = APIConfig()\nSTATION_CONFIG = StationConfig()\nKAGGLE_CONFIG = KaggleConfig()\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 <code>__post_init__<\/code>. <code>output_csv_path<\/code> \u0627\u0648\u0631 <code>metadata_path<\/code> \u06cc\u06c1 \u0646\u0634\u0627\u0646 \u0632\u062f \u06c1\u06d2\u06d4 <code>field(init=False)<\/code>\u060c \u0644\u06c1\u0630\u0627 \u0627\u0633\u06d2 \u06a9\u0646\u0633\u0679\u0631\u06a9\u0679\u0631 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0633\u06cc\u0679 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u0633\u06a9\u062a\u0627\u06d4 \u0627\u0633 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c <code>__post_init__<\/code> \u062f\u0648\u0633\u0631\u06d2 \u0641\u06cc\u0644\u0688 \u0645\u06cc\u06ba \u0627\u0633 \u06a9\u0627 \u062d\u0633\u0627\u0628 \u0644\u06af\u0627\u0626\u06cc\u06ba (<code>output_dir<\/code> \u0627\u0648\u0631 <code>output_filename<\/code>)\u06d4<\/p>\n<p>\u0627\u0633 \u067e\u06cc\u0679\u0631\u0646 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba <strong>\u0627\u062e\u0630 \u06a9\u0631\u062f\u06c1\u060c \u062d\u0633\u0627\u0628\u06cc \u0642\u062f\u0631<\/strong>: \u062f\u0648\u0628\u0627\u0631\u06c1 \u062d\u0633\u0627\u0628 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u0622\u067e \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u062c\u06af\u06c1 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062d\u0633\u0627\u0628 \u0644\u06af\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>output_dir \/ output_filename<\/code> \u062c\u0628 \u0628\u06be\u06cc \u0622\u067e \u06a9\u0648 \u0627\u067e\u0646\u06d2 \u06a9\u0648\u0688 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u06a9\u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0631\u0627\u0633\u062a\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648\u06d4<\/p>\n<p>\u0627\u0635\u0644\u06cc \u067e\u0627\u0626\u062a\u06be\u0648\u0646 \u06a9\u06cc \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633\u0632 \u06af\u0627\u0626\u06cc\u0688 \u06cc\u0627 O'Reilly \u06a9\u06cc \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633\u0632 \u06a9\u0627 \u0628\u0627\u0628 \u062f\u06cc\u06a9\u06be\u06cc\u06ba\u06d4 <em>Python \u0645\u06cc\u06ba \u0631\u0648\u0627\u0646\u06cc<\/em> \u0627\u0633 \u067e\u06cc\u0679\u0631\u0646 \u06a9\u06d2 \u0628\u0627\u0631\u06d2 \u0645\u06cc\u06ba \u0645\u0632\u06cc\u062f \u062c\u0627\u0646\u06cc\u06ba\u06d4<\/p>\n<p><strong>\u0679\u067e:<\/strong> \u062e\u0648\u062f \u06a9\u0627\u0631 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u067e\u06cc\u062f\u0627 <code>__repr__<\/code> \u06c1\u0645 \u0645\u0641\u062a \u067e\u0691\u06be\u0646\u06d2 \u06a9\u0627 \u0645\u0648\u0627\u062f \u0641\u0631\u0627\u06c1\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06a9\u0627\u0644 <code>print(API_CONFIG)<\/code>: \u0641\u0627\u0631\u0645\u06cc\u0679\u0646\u06af \u06a9\u0648\u0688 \u06a9\u06cc \u0627\u06cc\u06a9 \u0644\u0627\u0626\u0646 \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u062a\u0645\u0627\u0645 \u0641\u06cc\u0644\u0688\u0632 \u0627\u0648\u0631 \u0627\u0642\u062f\u0627\u0631 \u062f\u06a9\u06be\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u067e\u0631 \u0639\u0645\u0644 \u062f\u0631\u0622\u0645\u062f \u06a9\u0648 \u0688\u06cc\u0628\u06af \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a \u0641\u0648\u0631\u06cc \u0633\u0646\u0679\u06cc \u0686\u06cc\u06a9\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0641\u06cc\u062f \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\">print(APIConfig)\n# prints APIConfig(use_mock=True, base_url=\"https:\/\/hubeau.eaufrance.fr\/api\/v2\/hydrometrie\/obs_elab\", ...)\n<\/code><\/pre>\n<p>\u0646\u06a9\u0627\u0644\u0646\u06d2 \u06a9\u0627 \u0645\u0631\u062d\u0644\u06c1 \u0633\u0648\u0631\u0633 \u0633\u0633\u0679\u0645 \u0633\u06d2 \u0688\u06cc\u0679\u0627 \u0644\u06cc\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0645\u06cc\u0645\u0648\u0631\u06cc \u0645\u06cc\u06ba \u067e\u0691\u06be\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1\u0627\u06ba\u060c \u0622\u067e \u06a9\u0627 \u0645\u062e\u0644\u0635 <strong>\u062f\u0648<\/strong> \u0646\u06a9\u0627\u0644\u0646\u06d2 \u06a9\u0627 \u0630\u0631\u06cc\u0639\u06c1: <em>\u0645\u0648\u062c\u0648\u062f\u06c1<\/em> \u0688\u06cc\u0679\u0627\u0633\u06cc\u0679 (\u062c\u0633\u06d2 \u0645\u06cc\u06ba \u0646\u06d2 \u067e\u0686\u06be\u0644\u06cc \u0628\u0627\u0631 \u067e\u0648\u0633\u0679 \u06a9\u06cc\u0627 \u062a\u06be\u0627) \u0627\u0648\u0631 <em>\u0646\u06cc\u0627<\/em> (\u062d\u0627\u0644\u06cc\u06c1) Hub'Eau API \u0633\u06d2 \u0688\u06cc\u0679\u0627\u06d4<\/p>\n<h3 id=\"heading-graceful-file-loading\">\u0633\u06cc\u0645\u0644\u06cc\u0633 \u0641\u0627\u0626\u0644 \u0644\u0648\u0688\u0646\u06af<\/h3>\n<h4 id=\"heading-design-logic\">\u0688\u06cc\u0632\u0627\u0626\u0646 \u0645\u0646\u0637\u0642<\/h4>\n<p>\u062c\u0628 \u06cc\u06c1 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u067e\u06c1\u0644\u06cc \u0628\u0627\u0631 \u0686\u0644\u0627\u0626\u06cc \u062c\u0627\u0626\u06d2 \u062a\u0648 \u06a9\u06cc\u0627 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2 (\u0627\u06af\u0631 \u0627\u0628\u06be\u06cc \u062a\u06a9 \u06a9\u0648\u0626\u06cc \u0645\u0648\u062c\u0648\u062f\u06c1 \u0688\u06cc\u0679\u0627 \u0633\u06cc\u0679 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2)\u061f \u0628\u0648\u0644\u06cc \u0646\u0641\u0627\u0630 \u06c1\u06d2 <code>FileNotFoundError<\/code>.<\/p>\n<p>\u06cc\u06c1 \u0631\u0627\u0632 \u06c1\u06d2: <code>load_csv()<\/code> \u062f\u0631\u062c \u0630\u06cc\u0644 \u067e\u0631 \u0639\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <strong>null \u0622\u0628\u062c\u06cc\u06a9\u0679 \u067e\u06cc\u0679\u0631\u0646<\/strong>. \u063a\u0644\u0637\u06cc \u067e\u06be\u06cc\u0646\u06a9\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 <em>\u0645\u0641\u062a<\/em> \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645\u06d4 \u062a\u0645\u0627\u0645 \u0688\u0627\u0648\u0646 \u0627\u0633\u0679\u0631\u06cc\u0645 \u0641\u0646\u06a9\u0634\u0646\u0632 \u067e\u06be\u0631 \"\u0645\u0648\u062c\u0648\u062f\u06c1 \u0688\u06cc\u0679\u0627 \u0646\u06c1\u06cc\u06ba\" \u0627\u0648\u0631 \"\u06a9\u0686\u06be \u0645\u0648\u062c\u0648\u062f\u06c1 \u0688\u06cc\u0679\u0627\" \u06a9\u0648 \u0627\u0633\u06cc \u0637\u0631\u062d \u0633\u0646\u0628\u06be\u0627\u0644 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u062e\u0627\u0635 \u06a9\u06cc\u0633 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-code-level-walkthrough\">\u06a9\u0648\u0688 \u06a9\u06cc \u0633\u0637\u062d \u06a9\u06cc \u0645\u0634\u0642\u06cc\u06ba\u06d4<\/h4>\n<p>\u06cc\u06c1 \u0641\u0646\u06a9\u0634\u0646 CSV \u0641\u0627\u0626\u0644 \u06a9\u0648 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u0645\u06cc\u06ba \u0644\u0648\u0688 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0641\u0627\u0626\u0644 \u0645\u0648\u062c\u0648\u062f \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u06a9\u0631\u06cc\u0634 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0627\u06cc\u06a9 \u062e\u0627\u0644\u06cc \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><code>low_memory=False<\/code>    \u067e\u0627\u0646\u0688\u0648\u06ba \u06a9\u0648 \u0641\u0627\u0626\u0644 \u06a9\u0648 \u063a\u0648\u0631 \u0633\u06d2 \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u06c1\u06c1 \u06a9\u0631 \u0645\u062e\u0644\u0648\u0637 \u0642\u0633\u0645 \u06a9\u06d2 \u0627\u0646\u062f\u0627\u0632\u0648\u06ba \u06a9\u0648 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 <code>parse_dates=True<\/code> \u062a\u0627\u0631\u06cc\u062e \u062c\u06cc\u0633\u06d2 \u06a9\u0627\u0644\u0645\u0648\u06ba \u06a9\u0648 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u062a\u0627\u0631\u06cc\u062e\u0648\u06ba \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634\u06d4 <code>delimiter=\",\"<\/code> \u06cc\u06c1 \u067e\u0627\u0646\u0688\u0648\u06ba \u06a9\u0648 \u0628\u062a\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0641\u0627\u0626\u0644\u0648\u06ba \u06a9\u0648 \u06a9\u0648\u0645\u0627 \u0633\u06d2 \u0627\u0644\u06af \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\">def load_csv(path: str) -> pd.DataFrame:\n    \"\"\"Load CSV file or return empty DataFrame if file does not exist.\n\n    Args:\n        path (str): Full path to the CSV file.\n\n    Returns:\n        pd.DataFrame: Loaded data, or empty DataFrame if file not found.\n\n    Raises:\n        pd.errors.ParserError: If the CSV is malformed.\n    \"\"\"\n    if os.path.exists(path):\n        return pd.read_csv(path, low_memory=False, parse_dates=True, delimiter=\",\")\n    return pd.DataFrame()   # Null Object: consistent return type\n<\/code><\/pre>\n<p>\u062c\u0627\u0646\u0686\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u063a\u06cc\u0631 \u0645\u0648\u062c\u0648\u062f \u0631\u0627\u0633\u062a\u06d2 \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u06a9\u0648\u0634\u0634 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">df_missing = load_csv(\"\/tmp\/does_not_exist.csv\")\nprint(df_missing.empty)  # True: no crash\n\n# Callers can always do this, instead of an `is None` check:\nif df_missing.empty:\n    print(\"No existing data. Will run a full fetch from earliest date.\")\n<\/code><\/pre>\n<p><strong>\u0628\u06c1\u062a\u0631\u06cc\u0646 \u0637\u0631\u0632 \u0639\u0645\u0644:<\/strong> \u0648\u0627\u067e\u0633\u06cc <strong>\u0645\u0633\u0644\u0633\u0644 \u0642\u0633\u0645<\/strong> \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06d2 \u062a\u0645\u0627\u0645 \u06a9\u0648\u0688 \u0631\u0627\u0633\u062a\u0648\u06ba \u0645\u06cc\u06ba\u06d4 \u0627\u06cc\u06a9 \u0641\u0646\u06a9\u0634\u0646 \u062c\u0648 \u06a9\u0628\u06be\u06cc \u06a9\u0628\u06be\u06cc \u0648\u0627\u067e\u0633 \u0622\u062a\u0627 \u06c1\u06d2: <code>DataFrame<\/code> \u0627\u0648\u0631 \u06a9\u0628\u06be\u06cc \u06a9\u0628\u06be\u06cc <code>None<\/code> \u062a\u0645\u0627\u0645 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 <code>None<\/code> \u0627\u0646 \u06a9\u0648 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0646\u062a\u0627\u0626\u062c \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u0648\u0627\u067e\u0633\u06cc <code>DataFrame<\/code>\u0686\u06cc\u0632\u06cc\u06ba \u0627\u0633 \u0628\u0627\u062a \u067e\u0631 \u0622\u0633\u0627\u0646 \u06c1\u0648 \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba \u06a9\u06c1 \u0622\u06cc\u0627 \u06cc\u06c1 \u062e\u0627\u0644\u06cc \u06c1\u06d2 \u06cc\u0627 \u0646\u06c1\u06cc\u06ba\u06d4 \u0622\u067e \u06a9\u0648 \u06a9\u0628\u06be\u06cc \u067e\u0648\u0686\u06be\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 <em>\"\u06a9\u06cc\u0627 \u0645\u062c\u06be\u06d2 \u062d\u0642\u06cc\u0642\u06cc \u0646\u062a\u0627\u0626\u062c \u0645\u0644\u06d2 \u06cc\u0627\u061f<\/em> <code>None<\/code><em>\u061f\"<\/em> \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u06d4<\/p>\n<h3 id=\"heading-incremental-update-logic\">\u0627\u0636\u0627\u0641\u06cc \u0627\u067e \u0688\u06cc\u0679 \u0645\u0646\u0637\u0642<\/h3>\n<h4 id=\"heading-design-logic\">\u0688\u06cc\u0632\u0627\u0626\u0646 \u0645\u0646\u0637\u0642<\/h4>\n<p>\u06cc\u06c1 \u062d\u0635\u06c1 1 \u06a9\u0627 \"\u0627\u0646\u06a9\u0631\u06cc\u0645\u0646\u0679\u0644 \u0644\u0648\u0688\u0646\u06af\" \u067e\u06cc\u0679\u0631\u0646 \u06c1\u06d2\u06d4 \u06a9\u0686\u06be \u0628\u06be\u06cc \u0644\u0627\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u06cc\u06c1 \u0633\u0648\u0627\u0644\u0627\u062a \u067e\u0648\u0686\u06be\u06cc\u06ba: <em>\"\u0645\u06cc\u0631\u06d2 \u067e\u0627\u0633 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u062d\u0627\u0644\u06cc\u06c1 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u0648\u0646 \u0633\u06d2 \u06c1\u06cc\u06ba\u061f \u06a9\u06cc\u0627 \u0645\u062c\u06be\u06d2 \u0648\u0627\u0642\u0639\u06cc \u0645\u0632\u06cc\u062f \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u061f\"<\/em><\/p>\n<p><strong>\u062d\u06a9\u0645\u062a \u0639\u0645\u0644\u06cc:<\/strong> \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u0622\u06cc\u0627 \u0645\u0648\u062c\u0648\u062f\u06c1 \u0688\u06cc\u0679\u0627 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0634\u0627\u0645\u0644 \u06c1\u06d2\u06d4 <em>\u06a9\u0644<\/em>.<\/p>\n<ul>\n<li>\n<p>\u0645\u062b\u0627\u0644: \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0686\u06be\u0648\u0691 \u062f\u06cc\u06ba\u06d4 \u06a9\u0631\u0646\u06d2 \u06a9\u0648 \u06a9\u0686\u06be \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0688\u06cc\u0679\u0627 \u0633\u06cc\u0679 \u0627\u067e \u0679\u0648 \u0688\u06cc\u0679 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0646\u06c1\u06cc\u06ba: \u0622\u062e\u0631\u06cc \u0645\u0639\u0644\u0648\u0645 \u062a\u0627\u0631\u06cc\u062e \u06a9\u06d2 \u0627\u06cc\u06a9 \u062f\u0646 \u0628\u0639\u062f \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"language-text\">Existing data: Jan. 1 \u2013 Jan. 15\nYesterday: Jan. 19\n\nDecision: fetch from Jan. 16 onwards (not from Jan. 1)\n<\/code><\/pre>\n<p>\u06a9\u06cc\u0648\u06ba <em>\u06a9\u0644<\/em> \u0627\u0648\u0631 \u067e\u06be\u0631 \u0646\u06c1\u06cc\u06ba\u06d4 <em>\u0622\u062c<\/em>? \u0622\u062c \u06a9\u06cc \u067e\u06cc\u0645\u0627\u0626\u0634 \u0627\u0628\u06be\u06cc \u062a\u06a9 \u0633\u0648\u0631\u0633 \u0633\u0633\u0679\u0645 \u067e\u0631 \u0645\u06a9\u0645\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u0626\u06cc \u06c1\u0648 \u06af\u06cc\u06d4 Hub'Eau \u06a9\u06d2 \"\u0646\u0641\u06cc\u0633 \u0645\u0634\u0627\u06c1\u062f\u0627\u062a\" \u067e\u0631 \u0631\u0648\u0632\u0627\u0646\u06c1 \u0645\u062c\u0645\u0648\u0639\u06cc \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u060c \u0644\u06c1\u0630\u0627 \u0633\u0628 \u0633\u06d2 \u0645\u062d\u0641\u0648\u0638 \u062c\u0627\u0646\u0686 \u0622\u062e\u0631\u06cc \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u06c1\u06d2\u06d4 <strong>\u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0645\u06a9\u0645\u0644<\/strong> \u062f\u0648\u067e\u06c1\u0631<\/p>\n<h4 id=\"heading-code-level-walkthrough\">\u06a9\u0648\u0688 \u0644\u06cc\u0648\u0644 \u0648\u0627\u06a9 \u062a\u06be\u0631\u0648<\/h4>\n<p><code>determine_update_range()<\/code>    \u062a\u0627\u0632\u06c1 \u062a\u0631\u06cc\u0646 \u0645\u062d\u0641\u0648\u0638 \u0634\u062f\u06c1 \u062a\u0627\u0631\u06cc\u062e \u06a9\u0648 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4 \u0622\u067e \u06a9\u0648 \u0627\u06cc\u06a9 \u067e\u06cc\u063a\u0627\u0645 \u0646\u0638\u0631 \u0622\u0626\u06d2 \u06af\u0627 \u06a9\u06c1 \"\u06cc\u06c1 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u06c1\u06cc \u0627\u067e \u0679\u0648 \u0688\u06cc\u0679 \u06c1\u06d2\" \u06cc\u0627 \"\u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u062a\u0627\u0631\u06cc\u062e \u0633\u06d2 \u0688\u0627\u0624\u0646 \u0644\u0648\u0688 \u06a9\u0631\u0646\u0627 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4\"<\/p>\n<p>\u0645\u0631\u062d\u0644\u06c1 \u0648\u0627\u0631:<\/p>\n<ol>\n<li>\n<p><strong>\u0641\u0646\u06a9\u0634\u0646 \u0645\u0648\u062c\u0648\u062f\u06c1 \u0688\u06cc\u0679\u0627 \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/strong><\/p>\n<ul>\n<li><code>existing<\/code>    \u06cc\u06c1 \u0627\u06cc\u06a9 \u067e\u0627\u0646\u0688\u0627 \u06c1\u06d2\u06d4 <code>DataFrame<\/code> \u0688\u06cc\u0679\u0627 \u06a9\u06cc \u06a9\u0686\u06be \u0642\u0637\u0627\u0631\u06cc\u06ba \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0645\u0648\u062c\u0648\u062f \u06c1\u06cc\u06ba\u06d4<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u0627\u06af\u0631 \u06a9\u0648\u0626\u06cc \u0688\u06cc\u0679\u0627 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>\u062a\u0627\u0631\u06cc\u062e \u06a9\u0627 \u06a9\u0627\u0644\u0645 \u062a\u0644\u0627\u0634 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong><\/p>\n<ul>\n<li>\n<p>\u06a9\u0648\u0688 \u0686\u06cc\u06a9 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06a9\u0648\u0646 \u0633\u0627 \u06a9\u0627\u0644\u0645 \u062a\u0627\u0631\u06cc\u062e\u0648\u06ba \u067e\u0631 \u0645\u0634\u062a\u0645\u0644 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u06af\u0631 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u062f\u0648\u0646\u0648\u06ba \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba \u062a\u0648 \u0622\u067e \u06a9\u0648 \u0627\u06cc\u06a9 \u062e\u0631\u0627\u0628\u06cc \u0645\u0644\u06d2 \u06af\u06cc \u06a9\u06cc\u0648\u0646\u06a9\u06c1 \u0622\u067e \u0646\u06c1\u06cc\u06ba \u062c\u0627\u0646\u062a\u06d2 \u06a9\u06c1 \u06a9\u0648\u0646 \u0633\u0627 \u06a9\u0627\u0644\u0645 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p><strong>\u062a\u0627\u0631\u06cc\u062e \u06a9\u06d2 \u06a9\u0627\u0644\u0645 \u06a9\u0648 \u0627\u0635\u0644 \u062a\u0627\u0631\u06cc\u062e\u0648\u06ba \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>\u0627\u067e\u0646\u06d2 \u0688\u06cc\u0679\u0627 \u0645\u06cc\u06ba \u062a\u0627\u0632\u06c1 \u062a\u0631\u06cc\u0646 \u062a\u0627\u0631\u06cc\u062e \u062a\u0644\u0627\u0634 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>\u06a9\u0644 \u0633\u06d2 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>\u0627\u06af\u0631 \u0622\u067e \u06a9\u0627 \u0688\u06cc\u0679\u0627 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u06c1\u06cc \u0627\u067e \u0679\u0648 \u0688\u06cc\u0679 \u06c1\u06d2\u06d4<\/strong><\/p>\n<\/li>\n<li>\n<p><strong>\u0627\u06af\u0631 \u0622\u067e \u06a9\u0627 \u0688\u06cc\u0679\u0627 \u067e\u06cc\u0686\u06be\u06d2 \u06c1\u06d2\u06d4<\/strong><\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"language-python\">def determine_update_range(existing: pd.DataFrame) -> Tuple[bool, Optional[str]]:\n    \"\"\"Determine whether an update is needed and from what date.\n\n    Logic:\n    1. Check if existing data covers yesterday's date\n    2. If yes \u2192 no update needed\n    3. If no \u2192 start fetching from day after last data\n\n    Returns:\n        Tuple[should_update, start_date]\n    \"\"\"\n    # Case 1: nothing on disk yet\n    if existing.empty:\n        print(\"No existing data found. Will fetch all data from earliest date.\")\n        return True, STATION_CONFIG.earliest_date\n\n    if \"date_obs_elab\" in existing.columns:\n        record_colname = \"date_obs_elab\"\n    elif \"record_date\" in existing.columns:\n        record_colname = \"record_date\"\n    else:\n        raise KeyError(\"Missing date column: expected 'date_obs_elab' or 'record_date'\")\n\n    s = pd.to_datetime(existing[record_colname], errors=\"coerce\")\n    last_day = s.max().date()\n    yesterday = date.today() - timedelta(days=1)\n\n    # Case 2: already current\n    if last_day >= yesterday:\n        print(\"nDataset already covers yesterday or later. No update needed.\")\n        return False, None\n\n    # Case 3: fetch the gap\n    next_day = (last_day + pd.Timedelta(days=1))\n    print(f\"nWill retrieve data starting from: {next_day}\")\n    return True, next_day.isoformat()\n<\/code><\/pre>\n<p>\u06cc\u06c1\u0627\u06ba \u0686\u0646\u062f \u0628\u0627\u062a\u06cc\u06ba \u0642\u0627\u0628\u0644 \u062a\u0648\u062c\u06c1 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0633\u0628 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0641\u0646\u06a9\u0634\u0646 \u0686\u06cc\u06a9 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <strong>\u06a9\u0627\u0644\u0645 \u06a9\u06d2 \u062f\u0648 \u0645\u0645\u06a9\u0646\u06c1 \u0646\u0627\u0645<\/strong>: <code>date_obs_elab<\/code>Raw API \u0646\u0627\u0645 \u06cc\u0627 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0646\u0627\u0645 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631 \u062f\u06cc\u0627 \u06af\u06cc\u0627 \u0627\u0646\u06af\u0631\u06cc\u0632\u06cc \u0646\u0627\u0645 <code>record_date<\/code>. \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u0686\u06cc\u0632 \u06a9\u0648 \u0641\u0631\u0636 \u0646\u06c1 \u06a9\u0631\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0627\u0633 \u0628\u0627\u062a \u06a9\u0648 \u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0627\u0645 \u06a9\u0631\u06d2 \u06af\u0627 \u0627\u0633 \u0633\u06d2 \u0642\u0637\u0639 \u0646\u0638\u0631 \u06a9\u06c1 \u0622\u067e \u0627\u0633\u06d2 \u0646\u0626\u06d2 \u062f\u0631\u0622\u0645\u062f \u0634\u062f\u06c1 \u062e\u0627\u0645 \u0688\u06cc\u0679\u0627 \u067e\u0631 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u06cc\u0627 \u0688\u0633\u06a9 \u0633\u06d2 \u0628\u06be\u0631\u06cc \u06c1\u0648\u0626\u06cc \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u067e\u0631\u0648\u0633\u06cc\u0633 \u0634\u062f\u06c1 CSV \u067e\u0631\u06d4<\/p>\n<p><code>errors=\"coerce\"<\/code>    \u06cc\u06c1 \u06cc\u06c1\u0627\u06ba \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u06af\u0627 (\u06c1\u0645 \u0627\u0633\u06d2 \u0645\u0632\u06cc\u062f \u062a\u0641\u0635\u06cc\u0644 \u0633\u06d2 \u062d\u0635\u06c1 5 \u0645\u06cc\u06ba \u062f\u06cc\u06a9\u06be\u06cc\u06ba \u06af\u06d2)\u06d4 \u067e\u0627\u0646\u0688\u0627 \u062c\u0646 \u062a\u0627\u0631\u06cc\u062e\u0648\u06ba \u06a9\u0648 \u067e\u0627\u0631\u0633 \u0646\u06c1\u06cc\u06ba \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u0627\u0646 \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba: <code>NaT<\/code> (\u0648\u0642\u062a \u0646\u06c1\u06cc\u06ba) \u0627\u06cc\u06a9 \u0627\u0633\u062a\u062b\u0646\u0627\u0621 \u06a9\u0648 \u0628\u0691\u06be\u0627\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u06d4<\/p>\n<p>\u0648\u0627\u067e\u0633\u06cc \u06a9\u06cc \u0627\u0642\u0633\u0627\u0645 \u06cc\u06c1 \u06c1\u06cc\u06ba: <code>Tuple[bool, Optional[str]]<\/code>. \u06cc\u06c1 \u0679\u06cc\u067e\u0644 \u062f\u0648 \u0645\u062a\u0639\u0644\u0642\u06c1 \u0646\u062a\u0627\u0626\u062c \u06a9\u0648 \u06af\u0631\u0648\u067e \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <em>\u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2\u061f \u0645\u062c\u06be\u06d2 \u06a9\u0628 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u061f<\/em> \u06cc\u06c1 \u062f\u0648 \u0627\u0644\u06af \u0627\u0644\u06af \u0627\u0642\u062f\u0627\u0631\u060c \u06cc\u0627 \u0627\u06cc\u06a9 \u0645\u0628\u06c1\u0645 \u0642\u062f\u0631 \u0648\u0627\u067e\u0633 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0628\u06c1\u062a\u0631 \u06c1\u06d2 \u062c\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u0633\u06cc\u0627\u0642 \u0648 \u0633\u0628\u0627\u0642 \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u0645\u062e\u062a\u0644\u0641 \u0686\u06cc\u0632\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><strong>\u0628\u06c1\u062a\u0631\u06cc\u0646 \u0637\u0631\u0632 \u0639\u0645\u0644:<\/strong> \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba <code>Tuple<\/code> \u0648\u0627\u067e\u0633\u06cc \u06a9\u06cc \u0642\u0633\u0645 (\u06cc\u0627 \u0645\u0632\u06cc\u062f \u0641\u06cc\u0644\u0688\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0686\u06be\u0648\u0679\u06cc \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633\u060c \u06cc\u0627 <code>NamedTuple<\/code>) \u0645\u062a\u0639\u0644\u0642\u06c1 \u0646\u062a\u0627\u0626\u062c \u06a9\u0648 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u06af\u0631\u0648\u067e \u06a9\u0631\u06cc\u06ba\u06d4 \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u06c1\u0631 \u067e\u0648\u0632\u06cc\u0634\u0646 \u06a9\u0627 \u06a9\u06cc\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u0686\u06be \u0645\u062e\u062a\u0644\u0641 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba <em>\u0642\u0633\u0645<\/em> \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u0627\u062a \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u0645\u062e\u062a\u0644\u0641 \u06a9\u0648\u0688 \u067e\u0627\u062a\u06be \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0646\u0641\u06cc\u0648\u0698\u0646 \u0627\u0648\u0631 \u06a9\u06cc\u0691\u06d2 \u06a9\u0627 \u0627\u06cc\u06a9 \u0639\u0627\u0645 \u0630\u0631\u06cc\u0639\u06c1 \u06c1\u06d2\u06d4 <em>\"\u0627\u0633 \u0645\u06cc\u06ba \u06a9\u06cc\u0627 \u062d\u0631\u062c \u06c1\u06d2\u061f<\/em> <code>None<\/code> <em>\"\u06a9\u0628\u06be\u06cc \u06cc\u06c1 \u0627\u06cc\u06a9 \u062a\u0627\u0631 \u06c1\u06d2 \u0627\u0648\u0631 \u06a9\u0628\u06be\u06cc \u06cc\u06c1 \u0627\u06cc\u06a9 \u062a\u0627\u0631 \u06c1\u06d2\u061f\"<\/em>.<\/p>\n<p>\u062a\u06cc\u0646 \u0645\u0646\u0638\u0631\u0646\u0627\u0645\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0641\u0648\u0631\u06cc \u0627\u0633\u06a9\u06cc\u0646 \u0686\u0644\u0627\u0626\u06cc\u06ba:<\/p>\n<pre><code class=\"language-python\"># Test 1: No existing data\nshould_update, start_date = determine_update_range(pd.DataFrame())\n# \u2192 True, \"1900-01-01\"\n\n# Test 2: Old existing data (covers only Jan 10-15)\n# \u2192 True, \"2026-01-16\"  (the day after the last known date)\n\n# Test 3: Recent data that already covers yesterday\n# \u2192 False, None\n<\/code><\/pre>\n<h3 id=\"heading-simulate-the-api\">API \u062a\u062e\u0631\u0648\u067e\u0646<\/h3>\n<h4 id=\"heading-design-logic\">\u0688\u06cc\u0632\u0627\u0626\u0646 \u0645\u0646\u0637\u0642<\/h4>\n<p>\u067e\u06cc\u062f\u0627\u0648\u0627\u0631 \u0645\u06cc\u06ba\u060c \u0628\u0627\u0632\u06cc\u0627\u0641\u062a \u06a9\u0627 \u0645\u0637\u0644\u0628 \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc HTTP \u06a9\u0627\u0644 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\">requests.get(\n    \"https:\/\/hubeau.eaufrance.fr\/api\/v2\/hydrometrie\/obs_elab\",\n    params={\"code_entite\": \"F700000109\", \"size\": 20000, ...}\n)\n<\/code><\/pre>\n<p>\u0627\u0635\u0644 API \u06a9\u0627\u0644\u06cc\u06ba \u062d\u0642\u06cc\u0642\u06cc \u0645\u0633\u0627\u0626\u0644 \u0644\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u0627\u0633 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0645\u06cc\u06ba\u060c \u06c1\u0645 \u0627\u0633\u06d2 \u067e\u06c1\u0644\u06cc \u0628\u0627\u0631 \u067e\u0691\u06be\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u06c1\u0631 \u0686\u06cc\u0632 \u06a9\u06cc \u062a\u0639\u0645\u06cc\u0631 \u0627\u0648\u0631 \u062c\u0627\u0646\u0686 \u06a9\u0631\u06cc\u06ba \u06af\u06d2\u06d4 <strong>\u062c\u0639\u0644\u06cc<\/strong> \u062c\u0646\u0631\u06cc\u0679\u0631 \u06cc\u06c1 \u0688\u06cc\u0679\u0627 \u0627\u0633\u06cc \u0641\u0627\u0631\u0645\u06cc\u0679 \u0645\u06cc\u06ba \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062c\u06cc\u0633\u0627 \u06a9\u06c1 \u0627\u0635\u0644 API\u06d4 \u0645\u0646\u0637\u0642 \u06a9\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u0639\u062f \u06c1\u06cc \u0627\u0646\u06c1\u06cc\u06ba \u0627\u0635\u0644 \u0627\u062e\u062a\u062a\u0627\u0645\u06cc \u0646\u0642\u0637\u06c1 \u067e\u0631 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u062a\u06a9\u0646\u06cc\u06a9 \u0627\u0633 \u0645\u0646\u0635\u0648\u0628\u06d2 \u0633\u06d2 \u0622\u06af\u06d2 \u0645\u0641\u06cc\u062f \u06c1\u06d2\u06d4 \u0633\u0628 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0627\u067e\u0646\u06d2 \u0641\u06a9\u0633\u0686\u0631 \u06cc\u0627 \u0641\u0631\u0636\u06cc \u0622\u0626\u0679\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u0628\u062f\u06cc\u0644\u06cc \u06a9\u06cc \u0645\u0646\u0637\u0642 \u0628\u0646\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u062c\u0627\u0646\u0686\u06cc\u06ba\u06d4 \u0627\u0633 \u0637\u0631\u062d \u0622\u067e \"\u06a9\u06cc\u0627 \u0645\u06cc\u0631\u06cc \u062a\u062c\u0632\u06cc\u06c1 \u063a\u0644\u0637 \u06c1\u06d2\u061f\" \u0645\u06cc\u06ba \u0646\u06c1\u06cc\u06ba \u067e\u06be\u0646\u0633\u06cc\u06ba \u06af\u06d2\u06d4 \u0627\u0648\u0631 \"\u06a9\u06cc\u0627 \u0622\u067e \u06a9\u0627 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u0627\u0628 \u063a\u06cc\u0631 \u0645\u0633\u062a\u062d\u06a9\u0645 \u06c1\u06d2\u061f\" \u0627\u06cc\u06a9 \u06c1\u06cc \u0648\u0642\u062a \u0645\u06cc\u06ba.<\/p>\n<h4 id=\"heading-code-level-walkthrough\">\u06a9\u0648\u0688 \u0644\u06cc\u0648\u0644 \u0648\u0627\u06a9 \u062a\u06be\u0631\u0648<\/h4>\n<p><code>generate_mock_api_data()<\/code>    \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2\u060c \u06c1\u0645 \u0627\u0633\u0679\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0631\u0648\u0632\u0627\u0646\u06c1 \u0627\u06cc\u06a9 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062c\u0639\u0644\u06cc \u0646\u0645\u0648\u0646\u06d2 \u06a9\u0627 \u0688\u06cc\u0679\u0627 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>start_date<\/code>.<\/p>\n<p>\u06cc\u06c1 \u06a9\u06cc\u0633\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/p>\n<ul>\n<li>\n<p>\u06cc\u06c1 \u0628\u062f\u0644\u062a\u0627 \u06c1\u06d2 <code>start_date<\/code> \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u062a\u0627\u0631\u06cc\u062e \u067e\u0631\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u06af\u0644\u06cc \u0628\u0627\u0631 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u06c1\u0631\u0627\u0626\u06cc\u06ba\u06d4 <code>num_days<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u06c1\u0645 \u06c1\u0631 \u0631\u0648\u0632 \u0627\u06cc\u06a9 \u0641\u0631\u0636\u06cc \u0645\u0634\u0627\u06c1\u062f\u0627\u062a\u06cc \u0644\u063a\u062a \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0688\u06cc\u0679\u0627 \u06a9\u0648 \u062d\u0642\u06cc\u0642\u062a \u067e\u0633\u0646\u062f\u0627\u0646\u06c1 \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u067e\u0627\u0646\u06cc \u06a9\u06cc \u0633\u0637\u062d \u0645\u06cc\u06ba \u0686\u06be\u0648\u0679\u06cc \u0628\u06d2 \u062a\u0631\u062a\u06cc\u0628 \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u0634\u0627\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u062d\u06cc\u062b\u06cc\u062a\u060c \u0645\u0639\u06cc\u0627\u0631\u060c \u0627\u0648\u0631 \u0637\u0631\u06cc\u0642\u06c1 \u06a9\u0627\u0631 \u06a9\u06d2 \u0644\u06cc\u0628\u0644 \u062a\u0635\u0627\u062f\u0641\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0645\u0646\u062a\u062e\u0628 \u06a9\u06cc\u06d2 \u06af\u0626\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06cc\u06c1 \u0644\u063a\u0627\u062a \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"language-python\">def generate_mock_api_data(station_code: str, start_date: str, num_days: int = 10) -> List[Dict]:\n    \"\"\"Generate realistic mock API data for demonstration.\n\n    Simulates what HubEau API would return: list of observation dicts.\n    \"\"\"\n    start = pd.to_datetime(start_date).date()\n    records = []\n\n    validation_statuses = [\"Donn\u00e9e valid\u00e9e\", \"Donn\u00e9e brute\", \"Donn\u00e9e pr\u00e9-valid\u00e9e\"]\n    qualities = [\"Bonne\", \"Non qualifi\u00e9e\", \"Douteuse\"]\n    methods = [\"Mesur\u00e9e\", \"Calcul\u00e9e\", \"Expertis\u00e9e\"]\n\n    for i in range(num_days):\n        obs_date = start + timedelta(days=i)\n        base_level = 5500 + int(station_code[-2:])  # Varies by station\n        noise = random.randint(-200, 200)\n        water_level = base_level + noise\n\n        record = {\n            \"code_site\": \"mock_\" + station_code[1:],\n            \"code_station\": \"mock_\" + station_code,\n            \"date_obs_elab\": obs_date.isoformat(),\n            \"resultat_obs_elab\": water_level,\n            \"date_prod\": (obs_date + timedelta(days=1)).isoformat(),\n            \"code_statut\": \"1\",\n            \"libelle_statut\": random.choice(validation_statuses),\n            \"code_methode\": \"1\",\n            \"libelle_methode\": random.choice(methods),\n            \"code_qualification\": \"1\",\n            \"libelle_qualification\": random.choice(qualities),\n            \"longitude\": 2.3522 + random.uniform(-0.01, 0.01),\n            \"latitude\": 48.8566 + random.uniform(-0.01, 0.01),\n            \"grandeur_hydro_elab\": \"mock_HIXnJ\",\n        }\n        records.append(record)\n\n    return records\n<\/code><\/pre>\n<h3 id=\"heading-fetch-data-for-real\">\u062d\u0642\u06cc\u0642\u06cc \u0688\u06cc\u0679\u0627 \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<h4 id=\"heading-design-logic\">\u0688\u06cc\u0632\u0627\u0626\u0646 \u0645\u0646\u0637\u0642<\/h4>\n<p>\u062f\u0648 \u0627\u0641\u0639\u0627\u0644 \u0646\u06a9\u0627\u0644\u0646\u06d2 \u06a9\u0648 \u0633\u0646\u0628\u06be\u0627\u0644\u062a\u06d2 \u06c1\u06cc\u06ba: \u0627\u0646\u06c1\u06cc\u06ba \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u0637\u0648\u0631 \u067e\u0631 \u062a\u0642\u0633\u06cc\u0645 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627: <strong>\u0648\u0627\u062d\u062f \u0630\u0645\u06c1 \u062f\u0627\u0631\u06cc \u06a9\u0627 \u0627\u0635\u0648\u0644<\/strong> (SRP): \u06c1\u0631 \u062e\u0635\u0648\u0635\u06cc\u062a \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u06cc\u06a9 \u0648\u062c\u06c1 \u06c1\u0648\u0646\u06cc \u0686\u0627\u06c1\u06cc\u06d2\u06d4<\/p>\n<pre><code class=\"language-text\">fetch_all_data() (orchestrator)\n    \u251c\u2500\u2500 fetch_single_station_data(station_1) \u2190 handles all complexity\n    \u251c\u2500\u2500 fetch_single_station_data(station_2) \u2190 handles all complexity\n    \u2514\u2500\u2500 fetch_single_station_data(station_n) \u2190 handles all complexity\n<\/code><\/pre>\n<ul>\n<li>\n<p><code>fetch_single_station_data()<\/code>    \u0645\u0627\u0644\u06a9 <em>\u06c1\u0631<\/em> \u06af\u0646\u062f\u0627 \u0627\u0633\u0679\u06cc\u0634\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062e\u0635\u0648\u0635 \u067e\u06cc\u0686\u06cc\u062f\u06af\u06cc\u0627\u06ba: \u0635\u0641\u062d\u06c1 \u0628\u0646\u062f\u06cc\u060c \u06a9\u0631\u0633\u0631 \u06a9\u06cc \u062a\u0631\u0642\u06cc\u060c \u0627\u0633\u0679\u0627\u067e \u06a9\u0646\u0688\u06cc\u0634\u0646\u0632\u060c \u0627\u0648\u0631 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u0627\u06cc\u0631\u0631 \u06c1\u06cc\u0646\u0688\u0644\u0646\u06af\u06d4<\/p>\n<\/li>\n<li>\n<p><code>fetch_all_data()<\/code>    \u0645\u06cc\u06ba \u0627\u0633 \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0633\u06cc \u06a9\u0627 \u0645\u0627\u0644\u06a9 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u06ba\u06d4 \u06cc\u06c1 \u0635\u0631\u0641 \u0627\u0633\u0679\u06cc\u0634\u0646\u0648\u06ba \u0627\u0648\u0631 \u0646\u0645\u0627\u0626\u0646\u062f\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u06c1\u0631\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u0627\u0633 \u062a\u0642\u0633\u06cc\u0645 \u06a9\u06d2 \u062f\u0648 \u0627\u0646\u0639\u0627\u0645\u0627\u062a \u06c1\u06cc\u06ba\u06d4 \u0633\u0628 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0622\u067e \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0634\u0646 \u06a9\u0648\u0688 \u06a9\u0648 \u0686\u06be\u0648\u0626\u06d2 \u0628\u063a\u06cc\u0631 \u0627\u06cc\u06a9 \u0627\u0633\u0679\u06cc\u0634\u0646 \u06a9\u06cc \u0635\u0641\u062d\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u06cc \u062d\u06a9\u0645\u062a \u0639\u0645\u0644\u06cc \u06a9\u0648 \u0688\u06cc\u0628\u06af \u06cc\u0627 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u062f\u0648\u0633\u0631\u0627\u060c \u0627\u06af\u0631 \u0622\u067e \u062f\u0631\u0622\u0645\u062f \u06a9\u0648 \u0645\u062a\u0648\u0627\u0632\u06cc \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba ( <code>concurrent.futures<\/code> \u06cc\u0627 <code>asyncio<\/code>\u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631) \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0679\u0631 <em>\u0635\u0631\u0641<\/em> \u0686\u06be\u0648\u0646\u06d2 \u06a9\u06cc \u062c\u06af\u06c1\u06d4<\/p>\n<h4 id=\"heading-code-level-walkthrough\">\u06a9\u0648\u0688 \u0644\u06cc\u0648\u0644 \u0648\u0627\u06a9 \u062a\u06be\u0631\u0648<\/h4>\n<p><code>fetch_single_station_data()<\/code>    \u0645\u0648\u06a9 \u0679\u06cc\u0633\u0679 \u0688\u06cc\u0679\u0627 \u06cc\u0627 \u0627\u0635\u0644\u06cc API \u0633\u06d2 \u0635\u0641\u062d\u06c1 \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2 \u0627\u0633\u0679\u06cc\u0634\u0646 \u0688\u06cc\u0679\u0627 \u0635\u0641\u062d\u06c1 \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba \u062c\u0628 \u062a\u06a9 \u06a9\u06c1 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u0627\u067e\u0646\u06cc \u0636\u0631\u0648\u0631\u062a \u06a9\u06cc \u06c1\u0631 \u0686\u06cc\u0632 \u0646\u06c1 \u06c1\u0648\u06d4<\/p>\n<ul>\n<li>\n<p><strong>\u0627\u06af\u0631<\/strong> <code>use_mock=True<\/code>\u06cc\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 <strong>\u062c\u0639\u0644\u06cc \u0688\u06cc\u0679\u0627<\/strong> \u0627\u0635\u0644 API \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u06d4<\/p>\n<ol>\n<li>\n<p>\u06cc\u06c1 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 <code>generate_mock_api_data()<\/code><\/p>\n<\/li>\n<li>\n<p>\u0646\u062a\u06cc\u062c\u06c1 \u06a9\u0648 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u062a\u0627\u0631\u06cc\u062e \u06a9\u06d2 \u06a9\u0627\u0644\u0645 \u06a9\u0648 \u067e\u0627\u0646\u0688\u0627 \u06a9\u06cc \u0627\u0635\u0644 \u062a\u0627\u0631\u06cc\u062e\u0648\u06ba \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0645\u062a\u0639\u0644\u0642\u06c1 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ol>\n<\/li>\n<li>\n<p><strong>\u0627\u06af\u0631<\/strong> <code>use_mock=False<\/code>\u06a9\u06c1 <strong>\u0627\u0635\u0644 API \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a<\/strong>:<\/p>\n<ol>\n<li>\n<p>\u062f\u0648\u0628\u0627\u0631\u06c1 \u0642\u0627\u0628\u0644 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 HTTP \u0633\u06cc\u0634\u0646 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0633\u06d2 \u0634\u0631\u0648\u0639 \u06a9\u0631\u06cc\u06ba\u06d4 <code>start_date<\/code><\/p>\n<\/li>\n<li>\n<p>API \u0633\u06d2 \u0628\u0627\u0631 \u0628\u0627\u0631 \u0688\u06cc\u0679\u0627 \u06a9\u06d2 \u0635\u0641\u062d\u0627\u062a \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06cc\u06c1 \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u0635\u0648\u0631\u062a\u0648\u06ba \u0645\u06cc\u06ba \u0631\u06a9 \u062c\u0627\u062a\u0627 \u06c1\u06d2:<\/p>\n<\/li>\n<li>\n<p>\u062a\u0645\u0627\u0645 \u0635\u0641\u062d\u0627\u062a \u06a9\u0648 \u0627\u06cc\u06a9 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u0645\u06cc\u06ba \u06cc\u06a9\u062c\u0627 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u06af\u0631 \u06a9\u0686\u06be \u062d\u0627\u0635\u0644 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u060c \u062a\u0648 \u06cc\u06c1 \u0627\u06cc\u06a9 \u062e\u0627\u0644\u06cc \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ol>\n<\/li>\n<\/ul>\n<pre><code class=\"language-python\">def fetch_single_station_data(station_code: str, start_date: str, use_mock: bool = True) -> pd.DataFrame:\n    \"\"\"Fetch all hydrometric data for a single station from mock API (default) or from the real endpoint.\n\n    In production (cursor based pagination strategy):\n    - Fetches max_per_page records per request\n    - Continues until no new data or yesterday's date reached\n    - Stop when: no data returned | last date >= yesterday | page was not full\n    - Handles network errors gracefully\n    \"\"\"\n    if use_mock:\n        data = generate_mock_api_data(station_code, start_date, num_days=7)\n        page_df = pd.DataFrame(data)\n        page_df[\"date_obs_elab\"] = pd.to_datetime(\n            page_df[\"date_obs_elab\"], errors=\"coerce\").dt.normalize()\n        return page_df\n\n    # Real implementation\n    else:\n        session = requests.Session()  # Reuse TCP connection across pages\n        frames = []\n        cursor = start_date\n\n        while True:\n            params = {\n                \"code_entite\": station_code,\n                \"grandeur_hydro_elab\": API_CONFIG.metric,\n                \"date_debut_obs_elab\": cursor,\n                \"size\": API_CONFIG.max_per_page,\n            }\n\n            try:\n                response = session.get(\n                    API_CONFIG.base_url,\n                    params=params,\n                    timeout=API_CONFIG.timeout_seconds  # Best practice, always set\n                )\n                response.raise_for_status()\n            except requests.RequestException as e:  # Don't let one station kill the whole pipeline\n                print(f\"Error fetching data for station {station_code}: {e}\")\n                break\n\n            data = response.json().get(\"data\", [])\n            if not data:  # Empty response: we've exhausted this station\n                break\n\n            page_df = pd.DataFrame(data)\n            page_df[\"date_obs_elab\"] = pd.to_datetime(\n                page_df[\"date_obs_elab\"], errors=\"coerce\").dt.normalize()\n            frames.append(page_df)\n\n            last_page_date = page_df[\"date_obs_elab\"].max()\n            yesterday = date.today() - timedelta(days=1)\n\n            # Prevent infinite loops\n            if pd.isna(last_page_date) or last_page_date.date() >= yesterday:\n                break\n\n            cursor = (last_page_date + pd.Timedelta(days=1)).strftime(\"%Y-%m-%d\")\n\n            if len(data) < API_CONFIG.max_per_page:\n                break\n\n    if frames:\n        return pd.concat(frames, ignore_index=True)\n    return pd.DataFrame()\n<\/code><\/pre>\n<p><strong>\u0635\u0641\u062d\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u06d2 \u0644\u0648\u067e \u062f\u0631\u0627\u0635\u0644 \u06a9\u06cc\u0633\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u061f<\/strong><\/p>\n<p>\u0622\u0626\u06cc\u06d2 \u0642\u062f\u0645 \u0628\u06c1 \u0642\u062f\u0645 \u0627\u0633 \u067e\u0631 \u0627\u06cc\u06a9 \u0646\u0638\u0631 \u0688\u0627\u0644\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u067e\u0648\u0631\u06d2 \u0644\u06cc\u067e \u0679\u0627\u067e \u0645\u06cc\u06ba \u0633\u0628 \u0633\u06d2 \u06af\u06be\u0646\u06cc \u0645\u0646\u0637\u0642 \u06c1\u06d2\u06d4<\/p>\n<ol>\n<li>\n<p>\u06a9\u0648 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0628\u06be\u06cc\u062c\u06cc\u06ba\u06d4 <code>date_debut_obs_elab=cursor<\/code>: \"\u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0645\u062c\u06be\u06d2 \u0627\u0633 \u062a\u0627\u0631\u06cc\u062e \u06a9\u0627 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u062f\u06cc\u06ba\u06d4\"<\/p>\n<\/li>\n<li>\n<p>\u0627\u06af\u0631 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062c\u0627\u062a\u06cc \u06c1\u06d2 (<code>requests.RequestException<\/code>)\u060c \u0627\u0633\u06d2 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 <code>break<\/code>. <code>break<\/code> \u0644\u0648\u067e \u06a9\u0648 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062c\u0627\u0631\u06cc \u0631\u06c1\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u0627\u0633\u0679\u06cc\u0634\u0646 \u067e\u0631 \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u0627 \u0645\u0633\u0626\u0644\u06c1 \u062f\u0648\u0633\u0631\u06d2 \u062a\u0645\u0627\u0645 \u0627\u0633\u0679\u06cc\u0634\u0646\u0648\u06ba \u067e\u0631 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0645\u06cc\u06ba \u062e\u0644\u0644 \u0646\u06c1\u06cc\u06ba \u0688\u0627\u0644\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u06af\u0631 \u062c\u0648\u0627\u0628 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u0688\u06cc\u0679\u0627 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2 \u062a\u0648\u060c \u0622\u067e \u0646\u06d2 \u067e\u06a9\u0691 \u0644\u06cc\u0627 \u06c1\u06d2\u06d4 <code>break<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u062f\u0648\u0633\u0631\u06cc \u0635\u0648\u0631\u062a \u0645\u06cc\u06ba\u060c \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u06a9\u0648 \u0630\u06c1\u0646 \u0645\u06cc\u06ba \u0631\u06a9\u06be\u06cc\u06ba: <em>\u062d\u0627\u0644\u06cc\u06c1<\/em> \u0627\u0633 \u0635\u0641\u062d\u06c1 \u067e\u0631 \u062f\u06a9\u06be\u0627\u0626\u06cc \u06af\u0626\u06cc \u062a\u0627\u0631\u06cc\u062e\u06cc\u06ba (<code>last_page_date<\/code>)\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u06af\u0631 \u062a\u0627\u0632\u06c1 \u062a\u0631\u06cc\u0646 \u062a\u0627\u0631\u06cc\u062e \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2\u06d4 <code>>= yesterday<\/code>\u0622\u067e \u0646\u06d2 \u067e\u06a9\u0691 \u0644\u06cc\u0627 \u06c1\u06d2: <code>break<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0628\u0635\u0648\u0631\u062a \u062f\u06cc\u06af\u0631\u060c \u06a9\u0631\u0633\u0631 \u06a9\u0648 \u0627\u0633 \u067e\u0631 \u0645\u0646\u062a\u0642\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>last_page_date + 1 day<\/code> \u0627\u06af\u0644\u06d2 \u0635\u0641\u062d\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062f\u06c1\u0631\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u062d\u0641\u0627\u0638\u062a\u06cc \u062c\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631: \u0627\u06af\u0631 \u0635\u0641\u062d\u06c1 \u0648\u0627\u067e\u0633 \u06a9\u0631 \u062f\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <em>\u06a9\u0645<\/em> \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u06d2 \u0645\u0642\u0627\u0628\u0644\u06d2 \u0645\u06cc\u06ba <code>max_per_page<\/code>\u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06cc\u06c1 \u0628\u06be\u06cc \u06c1\u06d2 \u06a9\u06c1 \u0627\u0646\u062c\u0627\u0645 \u06a9\u0648 \u067e\u06c1\u0646\u0686 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 API \u062c\u0632\u0648\u06cc \u0635\u0641\u062d\u06c1 \u0648\u0627\u067e\u0633 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u06d2 \u06af\u0627 \u062c\u0628 \u062a\u06a9 \u06a9\u06c1 \u0627\u0633 \u06a9\u0627 \u0688\u06cc\u0679\u0627 \u062e\u062a\u0645 \u0646\u06c1 \u06c1\u0648\u062c\u0627\u0626\u06d2\u060c \u0627\u0633 \u0644\u06cc\u06d2: <code>break<\/code>.<\/p>\n<\/li>\n<\/ol>\n<p>\u062d\u062a\u0645\u06cc \u062c\u0627\u0646\u0686 (\u0645\u0631\u062d\u0644\u06c1 7) \u06a9\u0644\u0627\u0633\u06a9 \u0637\u0631\u06cc\u0642\u06c1 \u06c1\u06d2\u06d4 <strong>\u0635\u0641\u062d\u06c1 \u0628\u0646\u062f\u06cc \u062e\u062a\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u062c\u0627\u0626\u0632\u06c1<\/strong>. \u06cc\u06c1 \u06c1\u0645\u06cc\u0634\u06c1 \u0636\u0631\u0648\u0631\u06cc \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 <code>next_page<\/code> API \u0633\u06d2 \u0679\u0648\u06a9\u0646\u06d4 \u0627\u06af\u0631 \u06cc\u06c1 \u067e\u0648\u0631\u0627 \u0635\u0641\u062d\u06c1 \u06c1\u06d2\u06d4 <code>size=20000<\/code> \u0627\u0648\u0631 \u0635\u0631\u0641 \u062a\u0645 \u0648\u0627\u067e\u0633 \u0622\u0624 <code>4213<\/code> \u0631\u06cc\u06a9\u0627\u0631\u0688 \u067e\u0631 \u0646\u0638\u0631 \u0688\u0627\u0644\u06cc\u06ba \u062a\u0648 \u0645\u0632\u06cc\u062f \u06a9\u0686\u06be \u0646\u06c1\u06cc\u06ba \u0644\u0627\u0646\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0627\u0633\u06d2 \u062a\u06cc\u0646 \u0645\u062e\u0635\u0648\u0635\u060c \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u0627\u0646\u062a\u062e\u0627\u0628 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2:<\/strong><\/p>\n<pre><code class=\"language-python\">session = requests.Session()\n<\/code><\/pre>\n<p>\u06a9\u0648\u0626\u06cc \u0631\u0627\u0633\u062a\u06c1 \u0646\u06c1\u06cc\u06ba <code>Session<\/code> \u0622\u0628\u062c\u06cc\u06a9\u0679 \u0627\u06cc\u06a9 \u06c1\u06cc \u0645\u06cc\u0632\u0628\u0627\u0646 \u06a9\u0648 \u0645\u062a\u0639\u062f\u062f \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u0648\u06ba \u067e\u0631 \u0628\u0646\u06cc\u0627\u062f\u06cc TCP \u06a9\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u06c1\u0631 \u0627\u06cc\u06a9 \u0635\u0641\u062d\u06d2 \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u067e\u0631 \u0627\u06cc\u06a9 \u0646\u06cc\u0627 TCP\/TLS \u06c1\u06cc\u0646\u0688 \u0634\u06cc\u06a9 \u06c1\u0648\u0646\u06d2 \u0633\u06d2 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u0645\u062e\u062a\u0635\u0631 \u06cc\u06c1 \u06a9\u06c1 \u06cc\u06c1 \u0622\u067e \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0632 \u062a\u0631 \u06c1\u06d2 \u0627\u0648\u0631 \u062d\u0628 \u0627\u06cc\u0648 \u06a9\u06d2 \u0633\u0631\u0648\u0631\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0634\u0627\u0626\u0633\u062a\u06c1 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0628\u06c1\u062a\u0631\u06cc\u0646 \u0637\u0631\u0632 \u0639\u0645\u0644:<\/strong> \u0645\u06cc\u06ba \u062c\u0628 \u0628\u06be\u06cc \u0641\u0648\u0646 \u06a9\u0631\u062a\u0627 \u06c1\u0648\u06ba\u06d4 <code>requests.get()<\/code> \u0627\u06cc\u06a9 \u0644\u0648\u067e \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u06c1\u06cc \u0645\u06cc\u0632\u0628\u0627\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0628\u0627\u0631 <code>Session<\/code>.<\/p>\n<pre><code class=\"language-python\">except requests.RequestException as e:\n<\/code><\/pre>\n<p><code>RequestException<\/code>    \u062a\u0645\u0627\u0645 \u0645\u0633\u062a\u062b\u0646\u06cc\u0627\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06cc\u0633 \u06a9\u0644\u0627\u0633\u06d4 <code>requests<\/code> \u0622\u067e \u06a9\u0648 \u062c\u0646 \u0645\u0633\u0627\u0626\u0644 \u06a9\u0627 \u0633\u0627\u0645\u0646\u0627 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2: \u0679\u0627\u0626\u0645 \u0622\u0624\u0679\u060c \u06a9\u0646\u06a9\u0634\u0646 \u06a9\u06cc \u062e\u0631\u0627\u0628\u06cc\u0627\u06ba\u060c HTTP \u06a9\u06cc \u062e\u0631\u0627\u0628\u06cc\u0627\u06ba <code>raise_for_status()<\/code> \u0627\u0648\u0631 \u0645\u0632\u06cc\u062f\u06d4 \u06cc\u06c1\u0627\u06ba\u060c \u0628\u06cc\u0633 \u06a9\u0644\u0627\u0633 \u06a9\u0648 \u067e\u06a9\u0691\u0646\u06d2 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 <em>\u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc<\/em> \u0646\u06cc\u0679 \u0648\u0631\u06a9 \u06a9\u06d2 \u0645\u0633\u0627\u0626\u0644 \u06a9\u0648 \u0627\u0633\u06cc \u0646\u0631\u0645\u06cc \u0633\u06d2 \u0646\u0645\u0679\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0646\u0648\u0679 \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0633 \u0627\u0633\u0679\u06cc\u0634\u0646 \u06a9\u0648 \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u0627 \u0628\u0646\u062f \u06a9\u0631\u06cc\u06ba\u060c \u0627\u0648\u0631 \u0622\u06af\u06d2 \u0628\u0691\u06be\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">timeout=API_CONFIG.timeout_seconds\n<\/code><\/pre>\n<p>\u0628\u0646\u06cc\u0627\u062f\u06cc \u0637\u0648\u0631 \u067e\u0631 <code>requests<\/code> \u0641\u0648\u0646 \u06a9\u0627\u0644 <strong>\u06a9\u0648\u0626\u06cc \u0679\u0627\u0626\u0645 \u0622\u0624\u0679 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/strong>. \u0648\u0627\u0636\u062d \u0679\u0627\u0626\u0645 \u0622\u0624\u0679 \u06a9\u06d2 \u0628\u063a\u06cc\u0631\u060c \u06c1\u06cc\u0646\u06af \u0633\u0631\u0648\u0631 \u067e\u0648\u0631\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u063a\u06cc\u0631 \u0645\u0639\u06cc\u0646\u06c1 \u0645\u062f\u062a \u062a\u06a9 \u0644\u0679\u06a9\u0627\u0646\u06d2 \u06a9\u0627 \u0633\u0628\u0628 \u0628\u0646 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u06d2 \u0627\u0639\u0644\u06cc \u062f\u0631\u062c\u06d2 \u06a9\u06d2 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06d2 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632 \u0645\u06cc\u06ba \u06a9\u06c1\u0627 \u06af\u06cc\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0628\u06cc\u0631\u0648\u0646\u06cc \u0633\u0631\u0648\u0631\u0632 \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u0679\u0627\u0626\u0645 \u0622\u0624\u0679 \u0645\u0646\u0633\u0644\u06a9 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4<\/p>\n<p><strong>\u0628\u06c1\u062a\u0631\u06cc\u0646 \u0637\u0631\u0632 \u0639\u0645\u0644:<\/strong> \u062a\u0645\u0627\u0645 \u0628\u06cc\u0631\u0648\u0646\u06cc I\/O \u06a9\u0627\u0644\u0648\u06ba \u06a9\u0648 \u0644\u067e\u06cc\u0679 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <code>try\/except<\/code>. \u06c1\u0645\u06cc\u0634\u06c1 \u062e\u0648\u0634 \u0627\u0633\u0644\u0648\u0628\u06cc \u0633\u06d2 \u0646\u0627\u06a9\u0627\u0645 \u0631\u06c1\u06cc\u06ba\u06d4 \u063a\u0644\u0637\u06cc \u06a9\u0648 \u0644\u0627\u06af \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u0628\u062d\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u06cc\u0627 \u062c\u0627\u0631\u06cc \u0631\u06a9\u06be\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u06ba\u06d4 \u06cc\u06c1 \u063a\u06cc\u0631 \u0645\u0633\u062a\u062d\u06a9\u0645 \u062f\u0631\u062e\u0648\u0627\u0633\u062a\u0648\u06ba \u06a9\u0648 \u062f\u0646 \u06a9\u06d2 \u0648\u0642\u062a \u06a9\u06cc \u06a9\u0627\u0631\u0631\u0648\u0627\u0626\u06cc\u0648\u06ba \u0645\u06cc\u06ba \u062e\u0644\u0644 \u0688\u0627\u0644\u0646\u06d2 \u0633\u06d2 \u0631\u0648\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0628 \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0679\u0631 <code>fetch_all_data()<\/code>\u06cc\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u0628\u06c1\u062a \u0622\u0633\u0627\u0646 \u06c1\u06d2\u06d4<\/p>\n<ol>\n<li>\n<p>\u062a\u0645\u0627\u0645 \u0631\u06cc\u0648\u0631\u0633 \u06a9\u0648\u0688\u0632 \u06a9\u0648 \u062f\u06c1\u0631\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u0646 \u06a9\u0648 \u0627\u06cc\u06a9 \u0628\u0691\u06d2 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u0645\u06cc\u06ba \u06cc\u06a9\u062c\u0627 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"language-python\">def fetch_all_data(start_date: str, use_mock: bool = True) -> pd.DataFrame:\n    \"\"\"Orchestrator: Fetch data for all configured stations.\"\"\"\n    frames = []\n\n    for station_code in STATION_CONFIG.station_codes:\n        print(f\"Fetching data for station {station_code}...\")\n        df_station = fetch_single_station_data(station_code, start_date, use_mock=use_mock)\n\n        if not df_station.empty:\n            print(f\"  Got {len(df_station)} records\")\n            frames.append(df_station)\n        else:\n            print(f\"  (no data)\")\n\n    if frames:\n        return pd.concat(frames, ignore_index=True)\n    return pd.DataFrame()\n<\/code><\/pre>\n<p>\u0628\u0633\u06d4 \u0644\u0648\u067e \u06a9\u06d2 \u0633\u0627\u062a\u06be <code>pd.concat<\/code>. \u0648\u06c1 \u062a\u0645\u0627\u0645 \u0645\u0634\u06a9\u0644 \u0633\u06d2 \u062c\u06cc\u062a\u06cc \u06af\u0626\u06cc \u067e\u06cc\u0686\u06cc\u062f\u06af\u06cc \u0627\u06cc\u0633 \u0622\u0631 \u067e\u06cc \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06c1 \u0628\u06cc\u0627\u0646 \u06a9\u0631\u062f\u06c1 \u0628\u06c1\u062a \u067e\u0631\u062a\u0648\u06ba \u06a9\u06d2 \u0646\u06cc\u0686\u06d2 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2\u06d4<\/p>\n<h2 id=\"heading-part-5-the-transform-step\">\u062d\u0635\u06c1 5: \u062a\u0628\u062f\u06cc\u0644\u06cc \u06a9\u06d2 \u0645\u0631\u0627\u062d\u0644<\/h2>\n<p>\u06cc\u06c1 \u0648\u06c1 \u062c\u06af\u06c1 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u0646\u06cc\u0627 \u062f\u0631\u0622\u0645\u062f \u0634\u062f\u06c1 \u062e\u0627\u0645 \u0688\u06cc\u0679\u0627 \u0642\u0627\u0628\u0644 \u0627\u0634\u0627\u0639\u062a \u0688\u06cc\u0679\u0627 \u0628\u0646 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u067e\u0648\u0631\u06d2 \u062d\u0635\u06d2 \u06a9\u0627 \u0688\u06cc\u0632\u0627\u0626\u0646 \u0641\u0644\u0633\u0641\u06c1 \u062d\u0633\u0628 \u0630\u06cc\u0644 \u06c1\u06d2: <strong>\u062e\u0627\u0644\u0635 \u062a\u0642\u0631\u06cc\u0628<\/strong>. \u06c1\u0631 \u0627\u06cc\u06a9 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u0644\u06cc\u062a\u0627 \u0627\u0648\u0631 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <em>\u0646\u06cc\u0627<\/em> \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u0628\u063a\u06cc\u0631 \u06a9\u0633\u06cc \u0636\u0645\u0646\u06cc \u0627\u062b\u0631\u0627\u062a \u06a9\u06d2 \u0622\u0624\u0679 \u067e\u0679 \u06c1\u06d2\u06d4 \u0627\u0633\u06d2 \u0627\u06cc\u06a9 \u0628\u0691\u0627 \u06a9\u0627\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u062c\u0627\u0644 \u0633\u06d2 \u0628\u0686\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-text\">    (EXTRACT)\n    Raw API Data\n    \u2193\n    (TRANSFORM)\n1. Type parsing (datetime, numeric)\n2. Column renaming (French \u2192 English)\n3. Categorical mapping (validation status, quality)\n4. Derived columns computation (flood alert flags)\n5. Column reordering (logical grouping)\n6. Sorting & index reset\n    \u2193\n    (LOAD)\n    Publication-ready dataset\n<\/code><\/pre>\n<p>\u0627\u0633\u06d2 \u0627\u06cc\u06a9 \u0628\u0691\u06d2 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 6 \u0686\u06be\u0648\u0679\u06d2 \u0645\u0631\u0627\u062d\u0644 \u0645\u06cc\u06ba \u06a9\u06cc\u0648\u06ba \u062a\u0648\u0691 \u062f\u06cc\u06ba\u061f \u06c1\u0631 \u062d\u0635\u06d2 \u06a9\u0627 \u062a\u062c\u0631\u0628\u06c1 \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u06af\u06be\u0631 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0637\u06d2 \u0634\u062f\u06c1 \u0631\u0646 \u06a9\u06d2 \u062f\u0648\u0631\u0627\u0646 \u0635\u0628\u062d 3 \u0628\u062c\u06d2 \u06a9\u0686\u06be \u063a\u0644\u0637 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0622\u067e \u06c1\u0631 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u0627\u0646\u0641\u0631\u0627\u062f\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0688\u06cc\u0628\u06af \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0622\u067e \u0627\u0633 \u0628\u0627\u062a \u06a9\u06cc \u0646\u0634\u0627\u0646\u062f\u06c1\u06cc \u06a9\u0631\u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06a9\u06c1 \u06a9\u0648\u0646 \u0633\u06d2 \u0642\u062f\u0645 \u0646\u06d2 \u063a\u0644\u0637 \u0622\u0624\u0679 \u067e\u0679 \u062a\u06cc\u0627\u0631 \u06a9\u06cc\u0627\u06d4 \u0627\u06cc\u06a9 200 \u0644\u0627\u0626\u0646 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u0645\u0646\u062a\u062e\u0628 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-type-parsing-and-graceful-coercion\">\u062a\u062c\u0632\u06cc\u06c1 \u0627\u0648\u0631 \u062e\u0648\u0628\u0635\u0648\u0631\u062a \u062c\u0628\u0631 \u0679\u0627\u0626\u067e \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<h4 id=\"heading-design-logic\">\u0688\u06cc\u0632\u0627\u0626\u0646 \u0645\u0646\u0637\u0642<\/h4>\n<p>CSV \u06cc\u0627 JSON API \u0645\u06cc\u06ba \u0688\u06cc\u0679\u0627 \u0628\u0637\u0648\u0631 \u0688\u06cc\u0641\u0627\u0644\u0679 \u0633\u0679\u0631\u0646\u06af \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0634\u0631\u0648\u0639 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u067e\u0627\u0646\u0688\u0627 \u062a\u0627\u0631\u06cc\u062e\u0648\u06ba \u06a9\u0648 \u062a\u0627\u0631\u06cc\u062e \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u062a\u0627\u0631\u06cc\u062e \u06a9\u06cc \u0631\u06cc\u0627\u0636\u06cc \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba (<code>last_date + timedelta(days=1)<\/code>) \u06cc\u0627 \u0639\u062f\u062f\u06cc \u0627\u0642\u062f\u0627\u0631 \u06a9\u0627 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0631\u06cc\u06ba (<code>water_level > 6000<\/code>)\u06d4 \u0642\u0633\u0645 \u06a9\u06cc \u0645\u0645\u0627\u062b\u0644\u062a \u0627\u06cc\u06a9 \u0639\u0627\u0645 \u063a\u0644\u0637\u06cc \u06c1\u06d2 \u062c\u0648 \u0628\u06cc\u0686 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u062a\u0648\u0691 \u062f\u06cc\u062a\u06cc \u06c1\u06d2\u06d4 \u0627\u0633 \u0637\u0631\u062d \u06a9\u06cc \u0627\u06cc\u06a9 \u063a\u0644\u0637 \u0644\u0627\u0626\u0646: <code>\"N\/A\"<\/code>\u0627\u06cc\u06a9 \u06a9\u0679\u06cc \u06c1\u0648\u0626\u06cc \u062a\u0627\u0631\u06cc\u062e\u060c \u0627\u06cc\u06a9 \u063a\u0644\u0637 \u062a\u0631\u062a\u06cc\u0628 \u0634\u062f\u06c1 \u0642\u062f\u0631\u060c \u06cc\u0627 \u0627\u06cc\u06a9 \u063a\u0644\u0637 \u06a9\u0631\u06cc\u06a9\u0679\u0631 \u0627\u0648\u0631 \u0633\u062e\u062a \u062a\u062c\u0632\u06cc\u06c1 \u06a9\u0627\u0631 \u0627\u06cc\u06a9 \u0627\u0633\u062a\u062b\u0646\u0627\u0621 \u0627\u0679\u06be\u0627\u0626\u06d2 \u06af\u0627 \u062c\u0648 \u067e\u0648\u0631\u06d2 \u0639\u0645\u0644 \u06a9\u0648 \u062e\u062a\u0645 \u06a9\u0631\u062f\u06d2 \u06af\u0627\u06d4<\/p>\n<p><strong>\u0628\u06c1\u062a\u0631\u06cc\u0646 \u0637\u0631\u0632 \u0639\u0645\u0644:<\/strong> \u0630\u06cc\u0644 \u0645\u06cc\u06ba \u062f\u0648\u0646\u0648\u06ba \u062a\u0628\u0627\u062f\u0644\u0648\u06ba \u06a9\u06d2 \u0627\u0641\u0639\u0627\u0644 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>errors=\"coerce\"<\/code>\u0644\u06c1\u0630\u0627 \u0648\u06c1 \u0627\u0642\u062f\u0627\u0631 \u062c\u0646 \u06a9\u06cc \u067e\u0627\u0646\u0688\u0627 \u062a\u062c\u0632\u06cc\u06c1 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba: <code>NaT<\/code> (\u0648\u0642\u062a \u0646\u06c1\u06cc\u06ba) \u06cc\u0627 <code>NaN<\/code> (\u0646\u0645\u0628\u0631 \u0646\u06c1\u06cc\u06ba) \u063a\u0644\u0637\u06cc \u067e\u06be\u06cc\u0646\u06a9\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u06d4 \u0627\u0633\u06d2 \u062e\u0648\u0628\u0635\u0648\u0631\u062a \u062c\u0628\u0631 \u06a9\u06c1\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-code-level-walkthrough\">\u06a9\u0648\u0688 \u0644\u06cc\u0648\u0644 \u0648\u0627\u06a9 \u062a\u06be\u0631\u0648<\/h4>\n<p><code>convert_to_date()<\/code>    \u0627\u0648\u0631 <code>convert_to_numeric()<\/code> \u06cc\u06c1 \u0627\u06cc\u06a9 \u0686\u06be\u0648\u0679\u0627 \u0645\u062f\u062f\u06af\u0627\u0631 \u0641\u0646\u06a9\u0634\u0646 \u06c1\u06d2 \u062c\u0648 \u0686\u06cc\u06a9 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u06cc\u0627 \u06a9\u0633\u06cc \u0645\u062e\u0635\u0648\u0635 \u06a9\u0627\u0644\u0645 \u0645\u06cc\u06ba \u0635\u062d\u06cc\u062d \u0642\u0633\u0645 \u06c1\u06d2\u06d4<\/p>\n<p>\u06a9\u06d2 \u0644\u06cc\u06d2 <code>convert_to_date()<\/code>:<\/p>\n<ol>\n<li>\n<p><code>df.copy()<\/code>    \u0686\u0648\u0646\u06a9\u06c1 \u06c1\u0645 \u0627\u06cc\u06a9 \u0627\u0644\u06af \u06a9\u0627\u067e\u06cc \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0635\u0644 \u062c\u062f\u0648\u0644 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06cc\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0644\u0648\u067e \u06c1\u0631 \u06a9\u0627\u0644\u0645 \u06a9\u06d2 \u0646\u0627\u0645 \u0633\u06d2 \u06af\u0632\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>columns<\/code><\/p>\n<ul>\n<li>\n<p><code>if col in df.columns<\/code>    \u062a\u0628\u0627\u062f\u0644\u0648\u06ba \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u0622\u06cc\u0627 \u06a9\u0627\u0644\u0645 \u0648\u0627\u0642\u0639\u06cc \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p><code>pd.to_datetime(...)<\/code>    \u0645\u062a\u0646 \u06a9\u0648 \u0627\u0633 \u0633\u06d2 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba: <code>\"2026-07-12\"<\/code> \u067e\u0627\u0646\u0688\u0627 \u06a9\u06cc \u0627\u0635\u0644 \u062a\u0627\u0631\u06cc\u062e\/\u0648\u0642\u062a \u06a9\u06cc \u0642\u062f\u0631\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be<\/p>\n<\/li>\n<li>\n<p><code>errors=\"coerce\"<\/code>    \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u0627\u06cc\u06a9 \u063a\u0644\u0637 \u0642\u062f\u0631 \u06c1\u0648\u06af\u06cc\u06d4 <code>NaT<\/code> (\u06af\u0645\u0634\u062f\u06c1 \u062a\u0627\u0631\u06cc\u062e) \u063a\u0644\u0637\u06cc \u06a9\u0648 \u0628\u0691\u06be\u0627\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2:<\/p>\n<\/li>\n<li>\n<p><code>.dt.normalize()<\/code>    \u0648\u0642\u062a \u06a9\u0627 \u062d\u0635\u06c1 \u06c1\u0679\u0627 \u062f\u06cc\u06ba \u0627\u0648\u0631 \u0635\u0631\u0641 \u0622\u062f\u06be\u06cc \u0631\u0627\u062a \u06a9\u06cc \u062a\u0627\u0631\u06cc\u062e \u0631\u06a9\u06be\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<p>\u06a9\u06d2 \u0644\u06cc\u06d2 <code>convert_to_numeric()<\/code>:<\/p>\n<ol>\n<li>\n<p><code>df.copy()<\/code>    \u06cc\u06c1\u0627\u06ba \u0628\u06be\u06cc \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0644\u0648\u067e \u06c1\u0631 \u06a9\u0627\u0644\u0645 \u06a9\u06d2 \u0646\u0627\u0645 \u0633\u06d2 \u06af\u0632\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>columns<\/code><\/p>\n<ul>\n<li>\n<p><code>if col in df.columns<\/code>    \u062a\u0628\u0627\u062f\u0644\u0648\u06ba \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u0622\u06cc\u0627 \u06a9\u0627\u0644\u0645 \u0648\u0627\u0642\u0639\u06cc \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0644\u0648\u067e \u06a9\u0627\u0644 <code>pd.to_numeric()<\/code> \u0645\u062a\u0646 \u06a9\u0648 \u0627\u0633 \u0633\u06d2 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba: <code>\"12.5\"<\/code> \u0646\u0645\u0628\u0631\u0648\u06ba \u0633\u06d2<\/p>\n<\/li>\n<li>\n<p><code>errors=\"coerce\"<\/code>    \u0628\u0631\u06cc \u0642\u062f\u0631 <code>NaN<\/code> \u06af\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ol>\n<pre><code class=\"language-python\">def convert_to_date(df: pd.DataFrame, columns: List[str]) -> pd.DataFrame:\n    \"\"\"Convert specified columns to pandas datetime type.\"\"\"\n    df = df.copy()  # Never modify the original!\n    for col in columns:\n        if col in df.columns:\n            df[col] = pd.to_datetime(df[col], errors=\"coerce\").dt.normalize()\n    return df\n\n\ndef convert_to_numeric(df: pd.DataFrame, columns: List[str]) -> pd.DataFrame:\n    \"\"\"Convert specified columns to numeric (float) type.\"\"\"\n    df = df.copy()\n    for col in columns:\n        if col in df.columns:\n            df[col] = pd.to_numeric(df[col], errors=\"coerce\")\n    return df\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u06a9\u06cc\u0648\u06ba \u0645\u0641\u06cc\u062f \u06c1\u06d2\u061f<\/p>\n<ul>\n<li>\n<p>\u0688\u06cc\u0679\u0627 \u06a9\u0648 \u062c\u0645\u0639 \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2: \u06af\u0631\u0648\u067e\u060c \u062e\u0644\u0627\u0635\u06c1\u060c \u0648\u063a\u06cc\u0631\u06c1...<\/p>\n<\/li>\n<li>\n<p>\u062a\u0627\u0631\u06cc\u062e\u0648\u06ba \u06a9\u0648 \u0627\u0628 \u0627\u0635\u0644 \u062a\u0627\u0631\u06cc\u062e \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u062a\u0631\u062a\u06cc\u0628 \u0627\u0648\u0631 \u0641\u0644\u0679\u0631 \u06a9\u06cc\u0627 \u062c\u0627 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u0639\u062f\u0627\u062f \u062d\u0633\u0627\u0628\u0627\u062a \u0645\u06cc\u06ba \u062f\u0631\u0633\u062a \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u06cc\u0633\u06d2 \u06a9\u06c1 \u0627\u0648\u0633\u0637\u060c \u0631\u0642\u0645 \u0627\u0648\u0631 \u0645\u0648\u0627\u0632\u0646\u06c1\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0645\u062e\u0644\u0648\u0637 \u0627\u0642\u0633\u0627\u0645 \u06a9\u06cc \u0648\u062c\u06c1 \u0633\u06d2 \u067e\u06cc\u062f\u0627 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u06cc\u0691\u0648\u06ba \u0633\u06d2 \u0628\u0686\u06cc\u06ba \u062c\u06cc\u0633\u06d2: <code>\"12\"<\/code> \u0627\u0648\u0631 <code>12<\/code>.<\/p>\n<\/li>\n<\/ul>\n<p>\u062f\u0648\u0646\u0648\u06ba <code>pd.to_datetime<\/code> \u0627\u0648\u0631 <code>pd.to_numeric<\/code> \u0633\u0631\u06a9\u0627\u0631\u06cc \u067e\u0627\u0646\u0688\u0627 \u062e\u0635\u0648\u0635\u06cc\u062a \u06c1\u06d2 <code>errors<\/code> \u067e\u06cc\u0631\u0627\u0645\u06cc\u0679\u0631\u0632 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0637\u06d2 \u0634\u062f\u06c1 \u0637\u0648\u0631 \u067e\u0631\u060c \u0648\u06c1 \u067e\u06cc\u0631\u0627\u0645\u06cc\u0679\u0631\u0632 \u0645\u0646\u062f\u0631\u062c\u06c1 \u0630\u06cc\u0644 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u0626\u06d2 \u06af\u0626\u06d2 \u06c1\u06cc\u06ba: <code>\"raise\"<\/code>\u063a\u0644\u0637 \u0627\u0646 \u067e\u0679 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u062f\u06cc\u06af\u0631 \u0627\u062e\u062a\u06cc\u0627\u0631\u0627\u062a \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba: <code>\"coerce\"<\/code> (null \u0633\u06d2 \u0628\u062f\u0644\u06cc\u06ba) \u06cc\u0627 <code>\"ignore\"<\/code> (\u0627\u0686\u06be\u0648\u0627 \u0686\u06be\u0648\u0691 \u062f\u06cc\u06ba)\u06d4 \u067e\u0627\u0646\u0688\u0627 \u06a9\u0627 \u0645\u0646\u0638\u0631 <code>to_datetime<\/code> \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u0627\u062a \u0627\u0648\u0631 <code>to_numeric<\/code> \u067e\u06cc\u0631\u0627\u0645\u06cc\u0679\u0631\u0632 \u06a9\u06cc \u0645\u06a9\u0645\u0644 \u0641\u06c1\u0631\u0633\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u0627\u062a \u062f\u06cc\u06a9\u06be\u06cc\u06ba\u06d4<\/p>\n<p>\u06af\u0646\u062f\u06d2 \u0627\u0646 \u067e\u0679 \u06a9\u06cc \u0645\u062b\u0627\u0644\u0648\u06ba \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u0679\u06cc\u0633\u0679 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">messy_df = pd.DataFrame({\n    \"date_obs_elab\": [\"2026-01-15\", \"2026-01-16\", \"not a date\", None],\n    \"resultat_obs_elab\": [5800.0, \"5900\", \"N\/A\", None],\n})\n\ntype_safe_df = convert_to_date(messy_df, [\"date_obs_elab\"])\ntype_safe_df = convert_to_numeric(type_safe_df, [\"resultat_obs_elab\"])\n\n# \"not a date\"  \u2192 NaT\n# \"N\/A\"         \u2192 NaN\n# Pipeline continues safely \u2014 nothing crashed.\n<\/code><\/pre>\n<p><strong>\u0628\u06c1\u062a\u0631\u06cc\u0646 \u0637\u0631\u0632 \u0639\u0645\u0644:<\/strong> \u0627\u06cc\u06a9 \u0628\u0631\u06cc \u0644\u0627\u0626\u0646 \u06a9\u0648 \u067e\u0648\u0631\u06cc \u067e\u06be\u0627\u0646\u0633\u06cc \u06a9\u0648 \u0631\u0648\u06a9\u0646\u06d2 \u0646\u06c1 \u062f\u06cc\u06ba\u06d4 \u0627\u06cc\u06a9 \u0627\u0633\u062a\u062b\u0646\u0627\u0621 \u06a9\u0648 \u0628\u0691\u06be\u0627\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u06cc\u06c1 \u063a\u0644\u0637 \u0688\u06cc\u0679\u0627 \u06a9\u0648 \u06a9\u0627\u0644\u0639\u062f\u0645 \u06a9\u0631\u0646\u06d2 \u067e\u0631 \u0645\u062c\u0628\u0648\u0631 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u0622\u067e \u06a9\u0648 \u0628\u0639\u062f \u0645\u06cc\u06ba \u0688\u06cc\u0679\u0627 \u06a9\u06d2 \u0645\u0639\u06cc\u0627\u0631 \u06a9\u06cc \u0686\u06be\u0627\u0646 \u0628\u06cc\u0646 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648 \u062a\u0648 \u0627\u0644\u06af \u0633\u06d2 \u0646\u0648\u0644\u0632 \u06a9\u0648 \u062c\u06be\u0646\u0688\u0627 \u0644\u06af\u0627\u0626\u06cc\u06ba \u06cc\u0627 \u0644\u0627\u06af \u0627\u0646 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u0633\u0645\u062c\u06be\u0648\u062a\u06c1 \u06c1\u06d2\u06d4 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0627\u0646\u062a\u062e\u0627\u0628 <em>\u062a\u0627\u062b\u06cc\u0631<\/em> (\u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0686\u0644\u062a\u06cc \u0631\u06c1\u062a\u06cc \u06c1\u06d2) \u062e\u062a\u0645 <em>\u0633\u062e\u062a\u06cc<\/em> (\u06cc\u06c1 \u062a\u0645\u0627\u0645 \u063a\u0644\u0637 \u0642\u0637\u0627\u0631\u0648\u06ba \u06a9\u0648 \u0641\u0648\u0631\u0627\u064b \u067e\u06a9\u0691 \u0644\u06cc\u062a\u0627 \u06c1\u06d2)\u06d4 \u06cc\u06c1 \u0639\u0627\u0645 \u0637\u0648\u0631 \u067e\u0631 \u0637\u06d2 \u0634\u062f\u06c1 \u063a\u06cc\u0631 \u062d\u0627\u0636\u0631 \u06a9\u0627\u0645 \u06a9\u06d2 \u0644\u0626\u06d2 \u0635\u062d\u06cc\u062d \u06a9\u0627\u0644 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-dfcopy-immutability-by-convention\"><code>df.copy()<\/code>: \u06a9\u0646\u0648\u0646\u0634\u0646 \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642 \u062a\u0628\u062f\u06cc\u0644\u06cc<\/h4>\n<p>\u0627\u0648\u067e\u0631 \u06a9\u06d2 \u062f\u0648 \u0641\u0646\u06a9\u0634\u0646\u0632 \u06a9\u06d2 \u0627\u0648\u067e\u0631\u06cc \u062d\u0635\u06d2 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062f\u06cc\u06a9\u06be\u06cc\u06ba\u06d4 <code>df = df.copy()<\/code>. \u06cc\u06c1 \u0627\u06cc\u06a9 \u0644\u0627\u0626\u0646 \u0634\u0631\u0648\u0639 \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2: <strong>\u062a\u0645\u0627\u0645 \u062a\u0628\u0627\u062f\u0644\u0648\u06ba \u06a9\u06d2 \u0627\u0641\u0639\u0627\u0644<\/strong> \u06cc\u06c1 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0645\u06cc\u06ba \u06c1\u06d2\u060c \u0627\u0648\u0631 \u06cc\u06c1 \u06a9\u0648\u0626\u06cc \u0627\u062a\u0641\u0627\u0642 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p>Python DataFrame \u062d\u0648\u0627\u0644\u06c1 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u067e\u0627\u0633 \u06a9\u0631\u062f\u06c1 \u0627\u06cc\u06a9 \u062a\u063a\u06cc\u0631 \u067e\u0630\u06cc\u0631 \u0634\u06d2 \u06c1\u06d2\u06d4 \u062c\u0628 \u06a9\u0633\u06cc \u0641\u0646\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u062a\u0631\u0645\u06cc\u0645 \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4 <code>df<\/code> \u0627\u06af\u0631 \u0622\u067e \u067e\u06c1\u0644\u06d2 \u0627\u0633\u06d2 \u06a9\u0627\u067e\u06cc \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u0627\u0633\u06d2 \u0627\u067e\u0646\u06cc \u062c\u06af\u06c1 \u067e\u0631 \u0686\u06be\u0648\u0691 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u06cc\u06c1 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u06d2 \u0627\u0635\u0644 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u06a9\u0648 \u0628\u06be\u06cc \u0628\u062f\u0644 \u062f\u06d2 \u06af\u0627\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u06a9\u0644\u0627\u0633\u06a9 \u0636\u0645\u0646\u06cc \u0627\u062b\u0631 \u06c1\u06d2 \u0627\u0648\u0631 \u06cc\u06c1 \u0648\u0627\u0642\u0639\u06cc \u0627\u0644\u062c\u06be\u0627 \u062f\u06cc\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u06cc\u0691\u06d2 \u067e\u06cc\u062f\u0627 \u06a9\u0631 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u0627\u0644 <code>.copy()<\/code> \u067e\u06c1\u0644\u06d2 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u06c1\u0631 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0627 \u0622\u0624\u0679 \u067e\u0679 \u0628\u0627\u0644\u06a9\u0644 \u0646\u06cc\u0627 \u0622\u0628\u062c\u06cc\u06a9\u0679 \u06c1\u06d2\u06d4 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 \u067e\u0627\u0633 \u06a9\u0631\u062f\u06c1 \u0627\u0646 \u067e\u0679 \u06a9\u0648 \u0628\u0631\u0642\u0631\u0627\u0631 \u0631\u06a9\u06be\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <em>\u0627\u0686\u06be\u0648\u062a \u06c1\u0648\u0646\u06d2 \u06a9\u06cc \u0636\u0645\u0627\u0646\u062a \u06c1\u06d2\u06d4<\/em>.<\/p>\n<p><strong>\u0628\u06c1\u062a\u0631\u06cc\u0646 \u0637\u0631\u0632 \u0639\u0645\u0644:<\/strong> \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0633 \u0637\u0631\u062d \u0633\u0644\u0648\u06a9 \u06a9\u0631\u06cc\u06ba: <strong>\u0646\u0627\u0642\u0627\u0628\u0644 \u062a\u0628\u062f\u06cc\u0644 \u0627\u0646 \u067e\u0679<\/strong>. \u0627\u0633 \u06a9\u06cc \u062c\u06af\u06c1 \u067e\u0631 \u062a\u0631\u0645\u06cc\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0627\u06cc\u06a9 \u0646\u06cc\u0627 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1\u0627\u06ba \u062a\u06a9 \u06a9\u06c1 \u0627\u06af\u0631 \u0627\u0633 \u06a9\u06cc \u062a\u06be\u0648\u0691\u06cc \u0645\u0642\u062f\u0627\u0631 \u0645\u06cc\u06ba \u0645\u06cc\u0645\u0648\u0631\u06cc \u06cc\u0627 CPU \u06a9\u06cc \u0644\u0627\u06af\u062a \u0622\u062a\u06cc \u06c1\u06d2\u060c \u0688\u06cc\u0628\u06af\u0646\u06af \u062c\u06cc\u062a \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u06c1\u0645\u06cc\u0634\u06c1 \u0627\u0646 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646\u0648\u06ba \u06a9\u06d2 \u0644\u06cc\u06d2 \u0642\u0627\u0628\u0644 \u0642\u062f\u0631 \u06c1\u0648\u062a\u06cc \u06c1\u06d2 \u062c\u0648 \u0627\u0646\u062a\u06c1\u0627\u0626\u06cc \u067e\u06cc\u0645\u0627\u0646\u06d2 \u067e\u0631 \u06a9\u0627\u0645 \u0646\u06c1\u06cc\u06ba \u06a9\u0631\u062a\u06cc \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0622\u062e\u0631 \u0645\u06cc\u06ba\u060c \u0627\u06cc\u06a9 \u062e\u0648\u062f \u06a9\u0627\u0631 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u067e\u062a\u06c1 \u0686\u0644\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0633\u06c1\u0648\u0644\u062a \u0641\u0646\u06a9\u0634\u0646 \u0627\u0646 \u062f\u0648 \u0646\u0686\u0644\u06d2 \u062f\u0631\u062c\u06d2 \u06a9\u06d2 \u0641\u0646\u06a9\u0634\u0646\u0632 \u06a9\u0648 \u0644\u067e\u06cc\u0679 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0645\u062a\u0646 \u06a9\u06d2 \u06a9\u0627\u0644\u0645 \u06a9\u0648 \u0627\u0633\u06a9\u06cc\u0646 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u0627\u0646\u062f\u0627\u0632\u06c1 \u0644\u06af\u0627\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u06cc\u0627 \u0627\u0633 \u0645\u06cc\u06ba \u062a\u0627\u0631\u06cc\u062e \u06cc\u0627 \u0646\u0645\u0628\u0631 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u0627\u0648\u067e\u0631 \u0645\u0645\u0627\u062b\u0644 \u067e\u0627\u0631\u0633 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><code>auto_convert_columns()<\/code>    \u0645\u06cc\u06ba \u06a9\u0648\u0634\u0634 \u06a9\u0631 \u0631\u06c1\u0627 \u06c1\u0648\u06ba ~ <strong>\u0627\u0646\u062f\u0627\u0632\u06c1 \u0644\u06af\u0627\u0626\u06cc\u06ba \u06a9\u06c1 \u06a9\u0648\u0646 \u0633\u0627 \u06a9\u0627\u0644\u0645 \u062a\u0627\u0631\u06cc\u062e \u06cc\u0627 \u0646\u0645\u0628\u0631 \u06c1\u06d2\u06d4<\/strong> \u06cc\u06c1 \u067e\u06be\u0631 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0627\u0646 \u0627\u0642\u0633\u0627\u0645 \u06a9\u0648 \u062f\u0631\u0633\u062a \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 \u06a9\u06cc\u0633\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/p>\n<p>\u06c1\u0645 \u062f\u0648 \u062e\u0627\u0644\u06cc \u0641\u06c1\u0631\u0633\u062a\u0648\u06ba \u0633\u06d2 \u0634\u0631\u0648\u0639 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u06cc\u06c1 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u06a9\u06d2 \u06c1\u0631 \u06a9\u0627\u0644\u0645 \u0633\u06d2 \u06af\u0632\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06af\u0631 \u06a9\u0627\u0644\u0645 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u06c1\u06cc \u0627\u06cc\u06a9 \u062d\u0642\u06cc\u0642\u06cc \u062a\u0627\u0631\u06cc\u062e\/\u0648\u0642\u062a \u06cc\u0627 \u0639\u062f\u062f\u06cc \u0642\u0633\u0645 \u06c1\u06d2 \u062a\u0648 \u0627\u0633\u06d2 \u0686\u06be\u0648\u0691 \u062f\u06cc\u06ba\u06d4 \u0627\u06af\u0631 \u06a9\u0627\u0644\u0645 \u0645\u062a\u0646 \u06a9\u06cc \u0637\u0631\u062d \u06c1\u06d2 (<code>object<\/code> \u06cc\u0627 <code>string<\/code>)\u060c 10 \u062a\u06a9 \u063a\u06cc\u0631 \u062e\u0627\u0644\u06cc \u0646\u0645\u0648\u0646\u06d2 \u06a9\u06cc \u0642\u062f\u0631\u0648\u06ba \u06a9\u0648 \u062f\u06cc\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u067e\u06c1\u0644\u06d2 \u06cc\u06c1 \u0627\u0633 \u0642\u062f\u0631 \u06a9\u0648 \u0628\u0637\u0648\u0631 \u062a\u0627\u0631\u06cc\u062e \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<ul>\n<li>\u0627\u06af\u0631 \u06cc\u06c1 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06a9\u0627\u0644\u0645 \u0627\u0633 \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06a9\u06cc\u06d2 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2: <code>datetime_cols<\/code><\/li>\n<\/ul>\n<p>\u0627\u06af\u0631 \u0646\u06c1\u06cc\u06ba\u060c \u062a\u0648 \u06cc\u06c1 \u0627\u0633\u06d2 \u0627\u06cc\u06a9 \u0646\u0645\u0628\u0631 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06cc \u06a9\u0648\u0634\u0634 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<ul>\n<li>\u0627\u06af\u0631 \u06cc\u06c1 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06a9\u0627\u0644\u0645 \u0627\u0633 \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06a9\u06cc\u06d2 \u062c\u0627\u0626\u06cc\u06ba \u06af\u06d2: <code>numeric_cols<\/code><\/li>\n<\/ul>\n<p>\u0622\u062e\u0631 \u0645\u06cc\u06ba \u06c1\u0645 \u062a\u0645\u0627\u0645 \u062a\u0627\u0631\u06cc\u062e \u06a9\u06d2 \u06a9\u0627\u0644\u0645\u0648\u06ba \u06a9\u0648 \u0627\u0633 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba: <code>convert_to_date()<\/code>. \u067e\u06be\u0631 \u062a\u0645\u0627\u0645 \u0639\u062f\u062f\u06cc \u06a9\u0627\u0644\u0645\u0648\u06ba \u06a9\u0648 \u0627\u0633 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba: <code>convert_to_numeric()<\/code><\/p>\n<pre><code class=\"language-python\">def auto_convert_columns(df: pd.DataFrame) -> pd.DataFrame:\n    \"\"\"Auto-detect and convert datetime and numeric columns to the correct type.\"\"\"\n    datetime_cols = []\n    numeric_cols = []\n\n    for col in df.columns:\n        if pd.api.types.is_datetime64_any_dtype(df[col]):\n            continue\n        if pd.api.types.is_numeric_dtype(df[col]):\n            continue\n\n        if pd.api.types.is_object_dtype(df[col]) or pd.api.types.is_string_dtype(df[col]):\n            sample = df[col].dropna().head(10)\n            if len(sample) == 0:\n                continue\n\n            try:\n                pd.to_datetime(sample, errors=\"raise\", format=\"mixed\")\n                datetime_cols.append(col)\n                continue\n            except (ValueError, TypeError):\n                pass\n\n            try:\n                pd.to_numeric(sample, errors=\"raise\")\n                numeric_cols.append(col)\n                continue\n            except (ValueError, TypeError):\n                pass\n\n    df = convert_to_date(df, datetime_cols)\n    df = convert_to_numeric(df, numeric_cols)\n    return df\n<\/code><\/pre>\n<p>\u0627\u067e\u0646\u06cc \u0637\u0631\u0641 \u062f\u06be\u06cc\u0627\u0646 \u062f\u0648 <code>try\/except<\/code> \u06cc\u06c1\u0627\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0634\u062f\u06c1 \u0628\u0644\u0627\u06a9\u0633 <code>errors=\"raise\"<\/code>. \u0628\u0633 <em>\u0627\u0633 \u06a9\u06d2 \u0628\u0631\u0639\u06a9\u0633<\/em> \u0627\u0648\u067e\u0631 \u062f\u06cc \u06af\u0626\u06cc \u0632\u0628\u0631\u062f\u0633\u062a\u06cc \u06a9\u06cc \u062d\u06a9\u0645\u062a \u0639\u0645\u0644\u06cc\u0648\u06ba \u0645\u06cc\u06ba \u0633\u06d2 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0635\u0631\u0641 \u0686\u06be\u0648\u0679\u06d2 \u0645\u0639\u0627\u0645\u0644\u0627\u062a \u0645\u06cc\u06ba \u06a9\u0627\u0645 \u06a9\u0631\u06d2 \u06af\u06cc\u06d4 <code>.head(10)<\/code> <strong>\u0646\u0645\u0648\u0646\u06c1<\/strong> \u06c1\u0631 \u06a9\u0627\u0644\u0645 \u06a9\u06d2.<\/p>\n<p>\u06cc\u06c1 \u0642\u0633\u0645 \u06c1\u06d2 -<em>\u0633\u0648\u0646\u06af\u06be\u0646\u0627<\/em> \u06cc\u06c1 \u0627\u06cc\u06a9 \u063a\u06cc\u0631 \u062d\u062a\u0645\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u06a9\u0627 \u0645\u0631\u062d\u0644\u06c1 \u06c1\u06d2\u06d4 \u0679\u06cc\u0633\u0679 <em>\"\u06a9\u06cc\u0627 \u06cc\u06c1 \u06a9\u0627\u0644\u0645 \u062a\u0627\u0631\u06cc\u062e\u0648\u06ba\u060c \u0646\u0645\u0628\u0631\u0648\u06ba\u060c \u06cc\u0627 \u062f\u0648\u0646\u0648\u06ba \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0638\u0627\u06c1\u0631 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u061f\"<\/em> \u0627\u0633 \u06a9\u06d2 \u0628\u0639\u062f \u0633\u0633\u062a\u06d2 \u0646\u0645\u0648\u0646\u06d2 \u062d\u0642\u06cc\u0642\u06cc \u0627\u0648\u0631 \u0645\u062d\u0627\u0648\u0631\u0627\u062a\u06cc \u062a\u0628\u0627\u062f\u0644\u0648\u06ba \u0645\u06cc\u06ba \u067e\u06c1\u0646\u0686\u0627\u0626\u06d2 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <em>\u067e\u0648\u0631\u06cc<\/em> \u06af\u0631\u0645\u06cc <code>convert_to_date()<\/code> \u06cc\u0627 <code>convert_to_numeric()<\/code>. \u062f\u0648 \u0645\u062e\u062a\u0644\u0641 <code>errors<\/code> \u062d\u06a9\u0645\u062a \u0639\u0645\u0644\u06cc\u060c \u062f\u0648 \u0645\u062e\u062a\u0644\u0641 \u06a9\u0627\u0645\u06d4<\/p>\n<h3 id=\"heading-schema-translation-with-bidirectional-mappings\">\u062f\u0648 \u0637\u0631\u0641\u06c1 \u0646\u0642\u0634\u06c1 \u0633\u0627\u0632\u06cc \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u06a9\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc<\/h3>\n<h4 id=\"heading-design-logic\">\u0688\u06cc\u0632\u0627\u0626\u0646 \u0645\u0646\u0637\u0642<\/h4>\n<p>Hub'Eau API \u062f\u0631\u062c \u0630\u06cc\u0644 \u0641\u0631\u0627\u0646\u0633\u06cc\u0633\u06cc \u06a9\u0627\u0644\u0645 \u06a9\u06d2 \u0646\u0627\u0645 \u0627\u0648\u0631 \u0641\u0631\u0627\u0646\u0633\u06cc\u0633\u06cc \u06a9\u06cc\u0679\u06cc\u06af\u0631\u06cc\u06a9\u0644 \u0627\u0642\u062f\u0627\u0631 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: <code>code_station<\/code> \u06cc\u0627 <code>\"Donn\u00e9e valid\u00e9e\"<\/code>. \u0639\u0627\u0644\u0645\u06cc \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u06cc\u0679\u0627 \u0633\u06cc\u0679 \u0627\u0646\u06af\u0631\u06cc\u0632\u06cc \u0645\u06cc\u06ba \u062f\u0633\u062a\u06cc\u0627\u0628 \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4 \u06a9\u0627\u0644\u0645 \u06a9\u06d2 \u0646\u0627\u0645\u0648\u06ba \u06a9\u0648 \u0627\u0646 \u0644\u0627\u0626\u0646 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u062c\u06c1\u0627\u06ba \u0628\u06be\u06cc \u06cc\u06c1 \u0622\u0633\u0627\u0646 \u06c1\u0648 \u0622\u067e \u06a9\u06d2 \u067e\u0648\u0631\u06d2 \u06a9\u0648\u0688 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u0641\u0631\u0627\u0646\u0633\u06cc\u0633\u06cc \u0627\u0648\u0631 \u0627\u0646\u06af\u0631\u06cc\u0632\u06cc \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0646\u0642\u0634\u06c1 \u0633\u0627\u0632\u06cc \u06a9\u0648 \u062c\u0627\u0631\u06cc \u0631\u06a9\u06be\u06d2 \u06af\u0627\u06d4 \u067e\u06be\u0631 \u0636\u0631\u0648\u0631\u062a \u067e\u0691\u0646\u06d2 \u067e\u0631 \u0627\u0633\u06d2 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u06a9\u0648\u0626\u06cc \u0637\u0631\u06cc\u0642\u06c1 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0627\u0635\u0644\u0627\u062d\u0627\u062a:<\/strong> \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u06cc\u06ba <strong>\u0627\u06cc\u06a9 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u0645\u06cc\u067e\u0646\u06af<\/strong> \u06cc\u06c1 \u0645\u0627\u0688\u06cc\u0648\u0644 \u06a9\u06d2 \u0633\u0628 \u0633\u06d2 \u0627\u0648\u067e\u0631 \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u0633 \u0633\u06d2 \u0628\u0627\u0642\u06cc \u0633\u0628 \u06a9\u0686\u06be \u0627\u062e\u0630 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-code-level-walkthrough\">\u06a9\u0648\u0688 \u0644\u06cc\u0648\u0644 \u0648\u0627\u06a9 \u062a\u06be\u0631\u0648<\/h4>\n<p><code>API_TO_EN<\/code>    Map API \u0641\u06cc\u0644\u0688 \u06a9\u06d2 \u0646\u0627\u0645 \u0627\u0646 \u06a9\u06d2 \u0627\u0646\u06af\u0631\u06cc\u0632\u06cc \u062a\u0631\u062c\u0645\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\"># Primary mapping: French API columns to English column names\nAPI_TO_EN = {\n    \"code_site\": \"location_code\",\n    \"code_station\": \"station_code\",\n    \"date_obs_elab\": \"record_date\",\n    \"resultat_obs_elab\": \"water_level_mm\",\n    \"date_prod\": \"data_production_date\",\n    \"code_statut\": \"validation_status_code\",\n    \"libelle_statut\": \"validation_status\",\n    \"code_methode\": \"production_method_code\",\n    \"libelle_methode\": \"production_method\",\n    \"code_qualification\": \"quality_code\",\n    \"libelle_qualification\": \"quality_assessment\",\n    \"longitude\": \"longitude\",\n    \"latitude\": \"latitude\",\n    \"grandeur_hydro_elab\": \"hubeau_elab_code\",\n}\n\n# Reverse mapping: English to French (computed automatically)\nEN_TO_API = {v: k for k, v in API_TO_EN.items()}\n<\/code><\/pre>\n<p>\u062f\u0648\u0633\u0631\u06cc \u0644\u0627\u0626\u0646 (<code>EN_TO_API<\/code>) \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u0634\u0627\u0631\u0679 \u06a9\u0679 \u06c1\u06d2\u06d4 \u06c1\u0631 \u06a9\u0644\u06cc\u062f \u0627\u0648\u0631 \u0642\u062f\u0631 <code>API_TO_EN<\/code>. \u067e\u06cc\u0634\u06af\u06cc \u0633\u0645\u062c\u06be \u0627\u0633\u06d2 \u0628\u0646\u0627\u062a\u06cc \u06c1\u06d2\u06d4 <strong>\u0627\u06c1\u0645 \u0688\u06cc\u0632\u0627\u0626\u0646 \u067e\u0648\u0627\u0626\u0646\u0679\u0633 \u06c1\u06cc\u06ba:<\/strong> <code>EN_TO_API<\/code>    \u0627\u0633 \u06a9\u0627 \u0627\u0646\u062a\u0638\u0627\u0645 \u06c1\u0627\u062a\u06be \u0633\u06d2 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627\u06d4 <em>\u0645\u0627\u062e\u0648\u0630<\/em>. \u0622\u0626\u0679\u0645\u0632 \u06a9\u0648 \u0634\u0627\u0645\u0644 \u06a9\u0631\u062a\u06d2\u060c \u06c1\u0679\u0627\u062a\u06d2 \u06cc\u0627 \u0646\u0627\u0645 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u062a\u06d2 \u0648\u0642\u062a <code>API_TO_EN<\/code>\u060c <code>EN_TO_API<\/code> \u0627\u06af\u0644\u06cc \u0628\u0627\u0631 \u062c\u0628 \u0645\u0627\u0688\u06cc\u0648\u0644 \u0686\u0644\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627 \u062a\u0648 \u06cc\u06c1 \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0627\u067e \u0688\u06cc\u0679 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u0648\u06c1\u0627\u06ba \u06c1\u06d2 <em>\u0628\u0627\u0644\u06a9\u0644 \u0627\u06cc\u06a9 \u062c\u06af\u06c1<\/em> \u067e\u0648\u0631\u06d2 \u06a9\u0648\u0688 \u0628\u06cc\u0633 \u0645\u06cc\u06ba \u062c\u06c1\u0627\u06ba \u0627\u0633\u06a9\u06cc\u0645\u0627 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644\u06cc\u0627\u06ba \u06c1\u0648\u0646\u06cc \u0686\u0627\u06c1\u0626\u06cc\u06ba\u06d4<\/p>\n<p>\u0648\u0627\u0636\u062d <em>\u0642\u062f\u0631<\/em> (\u0633\u0627\u062a\u06be \u06c1\u06cc \u06a9\u0627\u0644\u0645 \u06a9\u06d2 \u0646\u0627\u0645\u0648\u06ba \u06a9\u06d2 \u0633\u0627\u062a\u06be) \u0627\u06cc\u06a9 \u06c1\u06cc \u0633\u0644\u0648\u06a9 \u062d\u0627\u0635\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">CATEGORICAL_MAPPINGS = {\n    \"validation_status\": {\n        \"Donn\u00e9e valid\u00e9e\": \"validated\",\n        \"Donn\u00e9e brute\": \"raw\",\n        \"Donn\u00e9e pr\u00e9-valid\u00e9e\": \"pre-validated\",\n    },\n    \"quality_assessment\": {\n        \"Bonne\": \"good\",\n        \"Non qualifi\u00e9e\": \"unqualified\",\n        \"Douteuse\": \"dubious\",\n    },\n    \"production_method\": {\n        \"Calcul\u00e9e\": \"calculated\",\n        \"Mesur\u00e9e\": \"measured\",\n        \"Expertis\u00e9e\": \"expert-reviewed\",\n    },\n}\n<\/code><\/pre>\n<p>\u0630\u06cc\u0644 \u06a9\u0627 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0627\u0644\u0645 \u06a9\u06d2 \u0646\u0627\u0645\u0648\u06ba \u0627\u0648\u0631 \u0632\u0645\u0631\u06d2 \u06a9\u06cc \u0642\u062f\u0631\u0648\u06ba \u06a9\u0648 \u0645\u0639\u0645\u0648\u0644 \u067e\u0631 \u0644\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0646 \u0646\u0642\u0634\u0648\u06ba \u06a9\u0648 \u0644\u0627\u06af\u0648 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><code>rename_to_english()<\/code>:<\/p>\n<ol>\n<li>\n<p>\u0627\u06af\u0631 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u062e\u0627\u0644\u06cc \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u0641\u0648\u0631\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u06cc\u06a9 \u06a9\u0627\u067e\u06cc \u0648\u0627\u067e\u0633 \u06a9\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>API \u0646\u0627\u0645\u0648\u06ba \u0633\u06d2 \u0627\u0646\u06af\u0631\u06cc\u0632\u06cc \u0646\u0627\u0645\u0648\u06ba \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u06cc\u06d2 \u06af\u0626\u06d2 \u06a9\u0627\u0644\u0645\u0648\u06ba \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06cc\u06c1 \u067e\u06be\u0631 \u0646\u0627\u0645 \u062a\u0628\u062f\u06cc\u0644 \u0634\u062f\u06c1 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ol>\n<p><code>rename_to_api_schema()<\/code>:<\/p>\n<ol>\n<li>\n<p>\u06cc\u06c1 \u062e\u0627\u0644\u06cc \u0688\u06cc\u0679\u0627 \u06a9\u06cc \u0627\u06cc\u06a9 \u06a9\u0627\u067e\u06cc \u0628\u06be\u06cc \u0648\u0627\u067e\u0633 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0628\u0627\u0644\u06a9\u0644 \u0627\u0633 \u06a9\u06d2 \u0628\u0631\u0639\u06a9\u0633\u06d4 \u0627\u0646\u06af\u0631\u06cc\u0632\u06cc \u0646\u0627\u0645 API \u06a9\u06d2 \u0646\u0627\u0645\u0648\u06ba \u0645\u06cc\u06ba \u0644\u0648\u0679 \u062c\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ol>\n<p>(\u0627\u06af\u0631 \u0622\u067e \u06a9\u0648 API \u06a9\u06d2 \u0627\u0635\u0644 \u0641\u0627\u0631\u0645\u06cc\u0679 \u0645\u06cc\u06ba \u0688\u06cc\u0679\u0627 \u0648\u0627\u067e\u0633 \u0628\u06be\u06cc\u062c\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u0648 \u062a\u0648 \u06cc\u06c1 \u0645\u0641\u06cc\u062f \u06c1\u06d2)\u06d4<\/p>\n<p><code>apply_categorical_mappings()<\/code>:<\/p>\n<ol>\n<li>\n<p>\u0627\u0635\u0644 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u06a9\u06cc \u0627\u06cc\u06a9 \u06a9\u0627\u067e\u06cc \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2 \u062a\u0627\u06a9\u06c1 \u0627\u0633 \u0645\u06cc\u06ba \u06a9\u0648\u0626\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u0646\u06c1 \u06c1\u0648\u06d4<\/p>\n<\/li>\n<li>\n<p>\u06c1\u0631 \u06a9\u0627\u0644\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 <code>CATEGORICAL_MAPPINGS<\/code>\u0645\u06cc\u067e\u0646\u06af \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0627\u0642\u062f\u0627\u0631 \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"language-python\">def rename_to_english(df: pd.DataFrame) -> pd.DataFrame:\n    \"\"\"Rename API column names to English schema names.\"\"\"\n    if df.empty:\n        return df.copy()\n\n    columns_to_rename = {}\n    for src, dst in API_TO_EN.items():\n        if src in df.columns and dst not in df.columns:\n            columns_to_rename[src] = dst\n\n    return df.rename(columns=columns_to_rename)\n\ndef rename_to_api_schema(df: pd.DataFrame) -> pd.DataFrame:\n    \"\"\"Rename English column names back to API schema names (defensive\/reverse operation).\"\"\"\n    if df.empty:\n        return df.copy()\n\n    columns_to_rename = {k: v for k, v in EN_TO_API.items() if k in df.columns}\n    return df.rename(columns=columns_to_rename)\n<\/code><\/pre>\n<pre><code class=\"language-python\">def apply_categorical_mappings(df: pd.DataFrame) -> pd.DataFrame:\n    df = df.copy()\n    for col_name, mapping in CATEGORICAL_MAPPINGS.items():\n        if col_name in df.columns:\n            df[col_name] = df[col_name].map(mapping).fillna(df[col_name])\n    return df\n<\/code><\/pre>\n<p>\u06cc\u06c1\u0627\u06ba \u062f\u0648 \u062f\u0641\u0627\u0639\u06cc \u0639\u0627\u062f\u062a\u06cc\u06ba \u0642\u0627\u0628\u0644 \u062a\u0648\u062c\u06c1 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p><strong>\u062c\u0632\u0648\u06cc \u0627\u0646 \u067e\u0679 \u06a9\u06d2 \u062e\u0644\u0627\u0641 \u0645\u0636\u0628\u0648\u0637\u06cc:<\/strong> \u0646\u0627\u0645 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u062f\u0648\u0646\u0648\u06ba \u0641\u0646\u06a9\u0634\u0646\u0632 \u0635\u0631\u0641 \u0627\u0646 \u06a9\u0627\u0644\u0645\u0648\u06ba \u06a9\u0627 \u0646\u0627\u0645 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u062f\u0631\u062d\u0642\u06cc\u0642\u062a \u0627\u0646 \u067e\u0679 \u0645\u06cc\u06ba \u0645\u0648\u062c\u0648\u062f \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba (<code>if src in df.columns<\/code>)\u06d4<\/p>\n<p>\u0646\u0627\u0645 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0641\u0646\u06a9\u0634\u0646\u060c \u062c\u0648 \u0641\u0631\u0636 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u062a\u0645\u0627\u0645 \u0645\u06cc\u067e \u0634\u062f\u06c1 \u06a9\u0627\u0644\u0645 \u06c1\u0645\u06cc\u0634\u06c1 \u0645\u0648\u062c\u0648\u062f \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u0627\u0633 \u0648\u0642\u062a \u06a9\u0631\u06cc\u0634 \u06c1\u0648 \u062c\u0627\u0626\u06d2 \u06af\u0627 \u062c\u0628 \u0627\u0633\u06d2 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u067e\u0631 \u0628\u0644\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627 \u062c\u0648 \u062c\u0632\u0648\u06cc \u06c1\u06d2 \u06cc\u0627 \u0627\u0633 \u06a9\u06cc \u0634\u06a9\u0644 \u0645\u062e\u062a\u0644\u0641 \u06c1\u06d2\u06d4<\/p>\n<p><code>.map(mapping).fillna(df[col_name])<\/code>. <code>Series.map<\/code> \u0645\u06cc\u067e\u0646\u06af \u0688\u06a9\u0634\u0646\u0631\u06cc \u0645\u06cc\u06ba \u067e\u0627\u0626\u06cc \u062c\u0627\u0646\u06d2 \u0648\u0627\u0644\u06cc \u062a\u0645\u0627\u0645 \u0627\u0642\u062f\u0627\u0631 \u06a9\u0648 \u0628\u062f\u0644 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062a\u0645\u0627\u0645 \u0627\u0642\u062f\u0627\u0631 \u06a9\u0648 \u0628\u062f\u0644 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 <em>~ \u0646\u06c1\u06cc\u06ba<\/em> dict \u0645\u06cc\u06ba \u0645\u0644\u0627 <code>NaN<\/code>. \u0632\u0646\u062c\u06cc\u0631 <code>.fillna(df[col_name])<\/code> \u0628\u062d\u0627\u0644\u06cc \u06a9\u06d2 \u0641\u0648\u0631\u0627\u064b \u0628\u0639\u062f <em>\u0627\u0635\u0644<\/em> \u0627\u0646 \u062a\u0645\u0627\u0645 \u0645\u0642\u0627\u0645\u0627\u062a \u067e\u0631 \u0627\u0642\u062f\u0627\u0631 \u062f\u0631\u062c \u06a9\u0631\u06cc\u06ba \u062c\u06c1\u0627\u06ba \u06a9\u0648\u0626\u06cc \u0645\u06cc\u067e\u0646\u06af \u0644\u0627\u06af\u0648 \u0646\u06c1\u06cc\u06ba \u06a9\u06cc \u06af\u0626\u06cc \u06c1\u06d2\u06d4 \u0627\u0633 \u0637\u0631\u062d\u060c \u063a\u06cc\u0631 \u0645\u062a\u0648\u0642\u0639 \u062f\u0631\u062c\u06c1 \u0628\u0646\u062f\u06cc \u06a9\u06cc \u0642\u062f\u0631\u06cc\u06ba \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u06a9\u0627\u0644\u0639\u062f\u0645 \u06c1\u0648\u0646\u06d2 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2 \u0628\u063a\u06cc\u0631 \u062a\u0628\u062f\u06cc\u0644\u06cc \u06a9\u06d2 \u06af\u0632\u0631 \u062c\u0627\u062a\u06cc \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0627\u06cc\u06a9 \u0644\u0637\u06cc\u0641 \u0644\u06cc\u06a9\u0646 \u0627\u06c1\u0645 \u0645\u0636\u0628\u0648\u0637\u06cc \u06a9\u0627 \u0627\u0646\u062a\u062e\u0627\u0628 \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0633 \u06a9\u0648 \u0628\u0627\u0644\u06a9\u0644 \u062f\u06cc\u06a9\u06be\u0648 <code>.map()<\/code>\u067e\u06be\u0631-<code>.fillna()<\/code> \u0627\u0633\u0679\u06cc\u06a9 \u0627\u0648\u0648\u0631 \u0641\u0644\u0648 \u067e\u0631 \u0632\u06cc\u0631 \u0628\u062d\u062b \u0645\u062d\u0627\u0648\u0631\u0627\u062a: \u067e\u0627\u0646\u0688\u0627\u0633 \u0646\u0642\u0634\u06d2 \u0627\u0648\u0631 \u06a9\u0627\u0631\u06a9\u0631\u062f\u06af\u06cc \u06a9\u06cc \u0627\u06cc\u067e\u0644\u06cc \u06a9\u06cc\u0634\u0646\u0632\u06d4<\/p>\n<p>\u0627\u06cc\u06a9 \u0641\u0648\u0631\u06cc \u0631\u0627\u0624\u0646\u0688 \u0679\u0631\u067e \u0679\u06cc\u0633\u0679 \u0627\u0633 \u0628\u0627\u062a \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u062f\u0648 \u0637\u0631\u0641\u06c1 \u0646\u0642\u0634\u06c1 \u0633\u0627\u0632\u06cc \u062f\u0631\u0627\u0635\u0644 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\">sample_api_df = pd.DataFrame({\"code_station\": [\"F700000109\"], ...})\nrenamed_df = rename_to_english(sample_api_df)          # French \u2192 English\nreversed_df = rename_to_api_schema(renamed_df)          # English \u2192 French\n# reversed_df.columns.tolist() == sample_api_df.columns.tolist()  \u2192 True\n<\/code><\/pre>\n<h3 id=\"heading-compute-flood-alerts\">\u0633\u06cc\u0644\u0627\u0628 \u06a9\u06cc \u0648\u0627\u0631\u0646\u0646\u06af \u06a9\u0627 \u062d\u0633\u0627\u0628 \u06a9\u062a\u0627\u0628<\/h3>\n<p><code>add_derived_columns()<\/code>    \u06cc\u06c1 \u0627\u06cc\u06a9 \u0648\u0646 \u0644\u0627\u0626\u0646\u0631 \u06c1\u06d2\u06d4 \u0635\u0631\u0641 \u0631\u06cc\u0627\u0636\u06cc \u06a9\u0631 \u0631\u06c1\u06d2 \u06c1\u06cc\u06ba\u06d4 <code>flood_alert<\/code>. \u0627\u06af\u0631 \u067e\u0627\u0646\u06cc \u06a9\u06cc \u0633\u0637\u062d \u0637\u06d2 \u0634\u062f\u06c1 \u0633\u06cc\u0644\u0627\u0628 \u06a9\u06cc \u062d\u062f \u0633\u06d2 \u0627\u0648\u067e\u0631 \u06c1\u06d2\u06d4 <code>Config<\/code>\u0646\u062a\u06cc\u062c\u06c1 \u06cc\u06c1 \u06c1\u06d2\u06d4 <code>True<\/code>. \u0648\u0631\u0646\u06c1 \u0646\u062a\u06cc\u062c\u06c1 \u06cc\u06c1 \u06c1\u06d2: <code>False<\/code>.<\/p>\n<pre><code class=\"language-python\">def add_derived_columns(df: pd.DataFrame) -> pd.DataFrame:\n    \"\"\"Add a computed columns based on raw data.\n    \"\"\"\n    df = df.copy()\n\n    if \"water_level_mm\" in df.columns:\n        df[\"flood_alert\"] = df[\"water_level_mm\"] > STATION_CONFIG.flood_threshold_mm\n\n    return df\n<\/code><\/pre>\n<h3 id=\"heading-column-ordering\">\u06a9\u0627\u0644\u0645 \u062a\u0631\u062a\u06cc\u0628<\/h3>\n<p>\u06cc\u06c1\u0627\u06ba \u06a9\u0686\u06be \u0686\u06be\u0648\u0679\u06cc\u060c \u0644\u06cc\u06a9\u0646 \u0635\u0627\u0631\u0641\u06cc\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0646\u0638\u0631 \u0622\u0646\u06d2 \u0648\u0627\u0644\u06cc \u062a\u0641\u0635\u06cc\u0644\u0627\u062a \u06c1\u06cc\u06ba: \u0627\u067e\u0646\u06d2 \u0688\u06cc\u0679\u0627 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0688\u06cc\u0641\u0627\u0644\u0679 \u06a9\u0627\u0644\u0645 \u0622\u0631\u0688\u0631 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 \u06a9\u06c1\u06cc\u06ba \u0628\u06be\u06cc \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>COLUMN_ORDER<\/code> \u062a\u0631\u062c\u06cc\u062d\u06cc \u06a9\u0627\u0644\u0645 \u062a\u0631\u062a\u06cc\u0628 \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u0631\u06a9\u06be\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p><code>order_columns()<\/code>    \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u06a9\u0648 \u062f\u0648\u0628\u0627\u0631\u06c1 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u062a\u0627\u06a9\u06c1 \u0648\u06c1 \u06a9\u0627\u0644\u0645 \u067e\u06c1\u0644\u06d2 \u0622\u0626\u06d2 \u0627\u0648\u0631 \u0627\u0636\u0627\u0641\u06cc \u06a9\u0627\u0644\u0645 \u062e\u062a\u0645 \u06c1\u0648\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">COLUMN_ORDER = [\n    # Primary identifiers & measurements\n    \"station_code\", \"record_date\", \"water_level_mm\", \"flood_alert\",\n    # Metadata about the observation\n    \"hubeau_elab_code\", \"data_production_date\",\n    \"validation_status_code\", \"validation_status\",\n    \"production_method_code\", \"production_method\",\n    \"quality_code\", \"quality_assessment\",\n    # Geographic info (less important)\n    \"location_code\", \"longitude\", \"latitude\",\n]\n\ndef order_columns(df: pd.DataFrame) -> pd.DataFrame:\n    \"\"\"Reorder columns to preferred order.\"\"\"\n    present_cols = [c for c in COLUMN_ORDER if c in df.columns]\n    other_cols = [c for c in df.columns if c not in present_cols]\n    return df[present_cols + other_cols]\n<\/code><\/pre>\n<p><code>other_cols<\/code>    \u062d\u0641\u0627\u0638\u062a\u06cc \u062c\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2: \u062a\u0645\u0627\u0645 \u06a9\u0627\u0644\u0645 \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 \u062f\u0631\u062c \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba\u06d4 <code>COLUMN_ORDER<\/code> \u06cc\u06c1 \u0627\u0628 \u0628\u06be\u06cc \u0622\u062e\u0631\u06cc \u0645\u06cc\u06ba \u0634\u0627\u0645\u0644 \u06c1\u06d2\u06d4 \u0648\u06c1 \u062e\u0627\u0645\u0648\u0634\u06cc \u0633\u06d2 \u062d\u0630\u0641 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06d2\u06d4<\/p>\n<p>\u0642\u0648\u0627\u0639\u062f (\u062a\u0631\u062c\u06cc\u062d \u06a9\u06d2 \u0644\u062d\u0627\u0638 \u0633\u06d2):<\/p>\n<ul>\n<li>\n<p>\u0634\u0646\u0627\u062e\u062a \u06a9\u0646\u0646\u062f\u06c1 \u0627\u0648\u0631 \u06a9\u0644\u06cc\u062f\u06cc \u0641\u06cc\u0644\u0688\u0632 \u06a9\u0648 \u067e\u06c1\u0644\u06d2 \u0631\u06a9\u06be\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0633\u0628 \u0633\u06d2 \u0627\u06c1\u0645\u060c \u0627\u06a9\u062b\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06c1\u0648\u0646\u06d2 \u0648\u0627\u0644\u06d2\u060c \u0627\u0648\u0631 \u0633\u0628 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0642\u0627\u0628\u0644 \u0627\u0639\u062a\u0645\u0627\u062f \u06a9\u0627\u0644\u0645 \u067e\u06c1\u0644\u06d2 \u0631\u06a9\u06be\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0645\u062a\u0639\u0644\u0642\u06c1 \u0641\u06cc\u0644\u0688\u0632 \u06a9\u06cc \u06af\u0631\u0648\u067e \u0628\u0646\u062f\u06cc \u06a9\u0631 \u06a9\u06d2 \u0627\u067e\u0646\u06d2 \u0679\u06cc\u0628\u0644\u0632 \u06a9\u0648 \u0642\u062f\u0631\u062a\u06cc \u0637\u0648\u0631 \u067e\u0631 \u067e\u0691\u06be\u0646\u06d2 \u06a9\u0648 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u062e\u062a\u06cc\u0627\u0631\u06cc \u06cc\u0627 \u0634\u0627\u0630 \u0648 \u0646\u0627\u062f\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u0634\u062f\u06c1 \u0641\u06cc\u0644\u0688\u0632 \u06a9\u0648 \u0622\u062e\u0631 \u062a\u06a9 \u062f\u06be\u06a9\u06cc\u0644\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<h3 id=\"heading-deduplication\">\u0646\u0642\u0644 \u06a9\u0631\u0646\u0627<\/h3>\n<h4 id=\"heading-design-logic\">\u0688\u06cc\u0632\u0627\u0626\u0646 \u0645\u0646\u0637\u0642<\/h4>\n<p>\u062c\u0627\u062a\u06d2 \u062c\u0627\u062a\u06d2 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679\u0633 \u06a9\u0648 \u06c1\u0679\u0627 \u062f\u06cc\u06ba\u06d4 \u0627\u06cc\u06a9 \u0628\u0691\u06be\u062a\u06cc \u06c1\u0648\u0626\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0645\u06cc\u06ba\u060c \u062a\u0627\u0631\u06cc\u062e \u06a9\u06cc \u062d\u062f\u0648\u062f \u0627\u0648\u0631 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u0627\u0648\u0648\u0631\u0644\u06cc\u067e \u06c1\u0648 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<ul>\n<li>\n<p>\u0686\u0648\u0646\u06a9\u06c1 API \u0688\u06cc\u0679\u0627 \u062f\u06cc\u0631 \u0633\u06d2 \u0622\u062a\u0627 \u06c1\u06d2 \u06cc\u0627 \u0628\u0639\u062f \u0645\u06cc\u06ba \u0645\u06a9\u0645\u0644 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u0622\u067e \u0627\u0633\u06d2 \u0627\u0633\u06cc \u062f\u0646 \u0648\u0627\u067e\u0633 \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u06cc\u06a9 \u06c1\u06cc \u0645\u0634\u0627\u06c1\u062f\u06c1 \u0635\u0641\u062d\u06c1 \u0628\u0646\u062f \u062c\u0648\u0627\u0628 \u06a9\u06d2 \u062f\u0648 \u0645\u062e\u062a\u0644\u0641 \u0635\u0641\u062d\u0627\u062a \u067e\u0631 \u0638\u0627\u06c1\u0631 \u06c1\u0648 \u0633\u06a9\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<p>\u0688\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u06a9\u06d2 \u0628\u063a\u06cc\u0631\u060c \u06cc\u06c1 \u0645\u0646\u0638\u0631\u0646\u0627\u0645\u06d2 \u0648\u0642\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0633\u0627\u062a\u06be \u0622\u067e \u06a9\u06d2 \u0688\u06cc\u0679\u0627\u0633\u06cc\u0679 \u0645\u06cc\u06ba \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0642\u0637\u0627\u0631\u06cc\u06ba \u0628\u0646\u0627\u0646\u06d2 \u06a9\u0627 \u0633\u0628\u0628 \u0628\u0646 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0628\u06be\u06cc \u0627\u06cc\u06a9 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062c\u06cc\u0633\u0627 \u06a9\u06c1 \u062d\u0635\u06c1 1 \u0645\u06cc\u06ba \u0630\u06a9\u0631 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4 <strong>\u0628\u06d2 \u062d\u0633\u06cc<\/strong>: \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u0686\u0644\u0627\u0626\u06cc\u06ba \u06cc\u0627 \u067e\u0627\u0646\u0686 \u0628\u0627\u0631 \u0686\u0644\u0627\u0626\u06cc\u06ba \u0627\u0648\u0631 \u0646\u062a\u06cc\u062c\u06d2 \u0645\u06cc\u06ba \u0688\u06cc\u0679\u0627 \u0633\u06cc\u0679 \u0648\u06c1\u06cc \u0631\u06c1\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u062a\u0631\u0645\u06cc\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0622\u067e \u06a9\u0648 \u0627\u0633 \u0628\u0627\u062a \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u0646\u06cc \u0686\u0627\u06c1\u06cc\u06d2 \u06a9\u06c1 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u06cc\u0627 \u0628\u0646\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <strong>\u0645\u0646\u0641\u0631\u062f<\/strong>. \u0627\u06cc\u06a9 \u062c\u0627\u0645\u0639 \u06a9\u0644\u06cc\u062f \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-text\">key = (station_code, observation_date, water_level_value)\n<\/code><\/pre>\n<p>\u06cc\u06c1 \u062e\u0627\u0635 \u0627\u0645\u062a\u0632\u0627\u062c \u06a9\u06cc\u0648\u06ba\u061f \u062c\u0633\u0645\u0627\u0646\u06cc \u0637\u0648\u0631 \u067e\u0631\u060c \u0627\u06cc\u06a9 \u0633\u06cc\u0646\u0633\u0631 (<code>station_code<\/code>) \u0627\u06cc\u06a9 \u062f\u0646 \u06a9\u0627 \u06c1\u06d2 (<code>observation_date<\/code>\u0631\u0648\u0632\u0627\u0646\u06c1 \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06cc \u0632\u06cc\u0627\u062f\u06c1 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u0645\u0642\u062f\u0627\u0631 (<code>water_level_mm<\/code>) \u0627\u0648\u0631 \u06cc\u06c1 \u067e\u0691\u06be\u0646\u0627 \u0645\u0646\u0641\u0631\u062f \u06c1\u0648\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4<\/p>\n<ul>\n<li>\n<p>\u0645\u062e\u062a\u0644\u0641 \u0627\u0633\u0679\u06cc\u0634\u0646\u0648\u06ba \u06a9\u06d2 \u0631\u06cc\u06a9\u0627\u0631\u0688\u0632 \u0638\u0627\u06c1\u0631 \u06c1\u06d2 \u06a9\u06c1 \u0627\u06cc\u06a9 \u062f\u0648\u0633\u0631\u06d2 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0648\u0648\u0631\u0644\u06cc\u067e \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0645\u062e\u062a\u0644\u0641 \u062f\u0646\u0648\u06ba \u0645\u06cc\u06ba \u062f\u0648 \u067e\u0691\u06be\u0646\u06d2 \u06a9\u0648 \u0627\u0648\u0648\u0631\u0644\u06cc\u067e \u0646\u06c1\u06cc\u06ba \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0645\u0632\u06cc\u062f \u0644\u0637\u06cc\u0641 \u0646\u06a9\u062a\u06c1: <em>\u0627\u06cc\u06a9 \u06c1\u06cc<\/em> \u0646\u0634\u0631\u06cc\u0627\u062a\u06cc \u0627\u062f\u0627\u0631\u06d2 \u06a9\u06cc \u0631\u067e\u0648\u0631\u0679 <em>\u0627\u06cc\u06a9 \u06c1\u06cc<\/em> \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u062f\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 <em>\u0645\u062e\u062a\u0644\u0641<\/em> \u06cc\u06c1 \u0648\u06c1 \u0627\u0642\u062f\u0627\u0631 \u06c1\u06cc\u06ba \u062c\u0646\u06c1\u06cc\u06ba \u0627\u0644\u06af \u0645\u0634\u0627\u06c1\u062f\u06c1 \u0633\u0645\u062c\u06be\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u0645\u062b\u0627\u0644 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u062f\u0631\u0633\u062a \u06cc\u0627 \u0646\u0638\u0631 \u062b\u0627\u0646\u06cc \u0634\u062f\u06c1 \u067e\u06cc\u0645\u0627\u0626\u0634\u060c \u0627\u0648\u0631 \u06cc\u06c1 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0679 \u0627\u0642\u062f\u0627\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u06cc\u06ba \u062c\u0646\u06c1\u06cc\u06ba \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u0631\u062f \u06a9\u0631 \u062f\u06cc\u0627 \u062c\u0627\u0646\u0627 \u0686\u0627\u06c1\u06cc\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<h4 id=\"heading-code-level-walkthrough\">\u06a9\u0648\u0688 \u0644\u06cc\u0648\u0644 \u0648\u0627\u06a9 \u062a\u06be\u0631\u0648<\/h4>\n<p><code>create_dedup_key()<\/code>    \u06c1\u0631 \u0644\u0627\u0626\u0646 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u0645\u0646\u0641\u0631\u062f \u0679\u06cc\u06a9\u0633\u0679 ID \u0628\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062a\u06cc\u0646 \u062d\u0635\u0648\u06ba \u06a9\u0648 \u0627\u0646\u0688\u0631 \u0633\u06a9\u0648\u0631 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062c\u0648\u0691\u06cc\u06ba\u06d4<\/p>\n<ul>\n<li>\n<p>\u0627\u0633\u0679\u06cc\u0634\u0646 \u06a9\u0648\u0688<\/p>\n<\/li>\n<li>\n<p>\u062a\u0627\u0631\u06cc\u062e (\u062c\u06cc\u0633\u06d2 YYYY-MM-DD)<\/p>\n<\/li>\n<li>\n<p>\u067e\u0627\u0646\u06cc \u06a9\u06cc \u0633\u0637\u062d \u06a9\u06cc \u0642\u062f\u0631<\/p>\n<\/li>\n<\/ul>\n<p>\u0645\u062b\u0627\u0644 \u06a9\u0644\u06cc\u062f:<\/p>\n<pre><code class=\"language-text\">\"F700000109_2024-01-15_5800.0\"\n<\/code><\/pre>\n<pre><code class=\"language-python\">def create_dedup_key(df: pd.DataFrame) -> pd.Series:\n    \"\"\"Create unique deduplication key from station, day, and water level value.\n\n    Key format: \"station_code_YYYY-MM-DD_value\"\n    Example: \"F700000109_2024-01-15_5800.0\"\n    \"\"\"\n    parts = []\n\n    if \"code_station\" in df.columns:\n        parts.append(df[\"code_station\"].astype(str))\n\n    if \"date_obs_elab\" in df.columns:\n        parts.append(df[\"date_obs_elab\"].dt.strftime(\"%Y-%m-%d\"))\n\n    if \"resultat_obs_elab\" in df.columns:\n        parts.append(df[\"resultat_obs_elab\"].astype(str))\n\n    if not parts:\n        return pd.Series(index=df.index, dtype=\"object\")\n\n    return pd.Series(\n        [\"_\".join(row) for row in zip(*parts)],\n        index=df.index\n    )\n<\/code><\/pre>\n<p><strong>\u06a9\u0644\u06cc\u062f\u06cc \u0639\u0645\u0627\u0631\u062a \u06a9\u06cc\u0633\u06d2 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u06cc \u06c1\u06d2:<\/strong> <code>parts<\/code>    \u06cc\u06c1 \u0633\u06cc\u0631\u06cc\u0632 \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u062e\u062a\u0645 \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u060c \u06c1\u0631 \u0627\u06cc\u06a9 \u0627\u06c1\u0645 \u062c\u0632\u0648 (\u0627\u0633\u0679\u06cc\u0634\u0646\u060c \u062a\u0627\u0631\u06cc\u062e\u060c \u0642\u062f\u0631) \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9\u060c \u06c1\u0631 \u0627\u06cc\u06a9 \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645 \u06a9\u06cc \u0644\u0645\u0628\u0627\u0626\u06cc \u06a9\u06d2 \u0628\u0631\u0627\u0628\u0631\u06d4<\/p>\n<p>\u0622\u062e\u0631\u06cc \u0644\u0627\u0626\u0646 \u06a9\u0648 \u0627\u0646\u062f\u0631 \u0633\u06d2 \u067e\u0691\u06be\u06cc\u06ba\u06d4<\/p>\n<pre><code class=\"language-python\">    return pd.Series([\"_\".join(row) for row in zip(*parts)], index=df.index)\n<\/code><\/pre>\n<p><code>zip(*parts)<\/code>    \u06a9\u0627\u0644\u0645\u0648\u06ba \u06a9\u06cc \u0627\u0633 \u0641\u06c1\u0631\u0633\u062a \u06a9\u0648 \u0642\u0637\u0627\u0631 \u0648\u0627\u0631 \u0679\u0648\u067e\u0644\u0632 \u0645\u06cc\u06ba \u0628\u062f\u0644 \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u062d\u0627\u0635\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 <code>(station_1, date_1, value_1)<\/code>\u067e\u06be\u0631 <code>(station_2, date_2, value_2)<\/code>\u0648\u063a\u06cc\u0631\u06c1\u06d4 \u0641\u06c1\u0631\u0633\u062a \u06a9\u06cc \u062a\u0641\u06c1\u06cc\u0645 \u067e\u06be\u0631 \u06c1\u0631 \u0627\u0646\u0688\u0631 \u0633\u06a9\u0648\u0631 \u0634\u062f\u06c1 \u0642\u0637\u0627\u0631 \u06a9\u0648 \u0641\u06cc \u0642\u0637\u0627\u0631 \u0627\u06cc\u06a9 \u0633\u0679\u0631\u0646\u06af \u06a9\u0644\u06cc\u062f \u0645\u06cc\u06ba \u062c\u0648\u0691 \u062f\u06cc\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1 <em>\"\u06a9\u0627\u0644\u0645 \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a \u2192 \u0632\u067e \u2192 \u0642\u0637\u0627\u0631 \u0679\u0648\u067e\u0644\"<\/em> \u0645\u062d\u0627\u0648\u0631\u06d2 \u06a9\u0686\u06be \u0628\u06be\u06cc \u0644\u06a9\u06be\u06d2 \u0628\u063a\u06cc\u0631 \u0627\u06cc\u06a9 \u0633\u06d2 \u0627\u062e\u0630 \u06a9\u0631\u062f\u06c1 \u0633\u06cc\u0631\u06cc\u0632 \u0645\u06cc\u06ba \u0645\u062a\u0639\u062f\u062f \u0633\u06cc\u0631\u06cc\u0632 \u06a9\u0648 \u06cc\u06a9\u062c\u0627 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0627\u06cc\u06a9 \u0639\u0627\u0645 \u0627\u0648\u0631 \u0645\u0648\u062b\u0631 \u0637\u0631\u06cc\u0642\u06c1 \u06c1\u06d2\u06d4 <code>.apply(lambda row: ..., axis=1)<\/code>. \u0642\u0637\u0627\u0631 \u062f\u0631 \u0642\u0637\u0627\u0631 <code>.apply<\/code> \u0648\u06cc\u06a9\u0679\u0631\u0627\u0626\u0632\u0688 \u0633\u0679\u0631\u0646\u06af \u0622\u067e\u0631\u06cc\u0634\u0646\u0632 \u06a9\u06d2 \u0645\u0642\u0627\u0628\u0644\u06d2 \u0645\u06cc\u06ba\u060c \u06cc\u06c1 \u067e\u0627\u0646\u0688\u0648\u06ba \u0645\u06cc\u06ba \u0628\u06c1\u062a \u0633\u0633\u062a \u06c1\u06d2\u06d4<\/p>\n<p>\u0627\u0635\u0644 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u0627\u0633 \u0645\u06cc\u06ba \u06a9\u06cc \u062c\u0627\u062a\u06cc \u06c1\u06d2: <code>remove_duplicates()<\/code>. \u0627\u0633 \u0633\u06d2 \u0642\u0637\u0627\u0631\u06cc\u06ba \u06c1\u0679\u0627\u0626\u06cc\u06ba: <em>\"\u0646\u06cc\u0627\"<\/em> (\u0646\u06cc\u0627 \u062f\u0631\u0622\u0645\u062f \u0634\u062f\u06c1 \u0688\u06cc\u0679\u0627) \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2\u06d4 <em>\"\u0645\u0648\u062c\u0648\u062f\u06c1\"<\/em> (\u062a\u0627\u0631\u06cc\u062e\u06cc \u0627\u0639\u062f\u0627\u062f \u0648 \u0634\u0645\u0627\u0631)<\/p>\n<p>\u0645\u0631\u062d\u0644\u06c1 \u0648\u0627\u0631:<\/p>\n<ol>\n<li>\n<p>\u0627\u06af\u0631 \u0627\u06cc\u06a9 \u0645\u06cc\u0632 \u062e\u0627\u0644\u06cc \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u0635\u0631\u0641 \u0648\u0627\u067e\u0633 \u0622\u062a\u0627 \u06c1\u06d2. <code>new<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0642\u0633\u0645 \u06a9\u0648 \u062f\u0648\u0646\u0648\u06ba \u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645\u0632 \u067e\u0631 \u0644\u0627\u06af\u0648 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>auto_convert_columns()<\/code> \u0633\u0628 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u062a\u0627\u0631\u06cc\u062e\u0648\u06ba \u0627\u0648\u0631 \u0646\u0645\u0628\u0631\u0648\u06ba \u06a9\u0627 \u0635\u062d\u06cc\u062d \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u06cc\u0627 \u06af\u06cc\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u062f\u0648\u0646\u0648\u06ba \u062c\u062f\u0648\u0644\u0648\u06ba \u0645\u06cc\u06ba \u06c1\u0631 \u0642\u0637\u0627\u0631 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u06a9\u06cc\u0632 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 <code>create_dedup_key()<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u0627\u0633 \u0628\u0627\u062a \u06a9\u0627 \u062a\u0639\u06cc\u0646 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u062f\u0631\u0622\u0645\u062f \u0634\u062f\u06c1 \u0688\u06cc\u0679\u0627 \u0645\u06cc\u06ba \u06a9\u0648\u0646 \u0633\u06cc \u06a9\u0644\u06cc\u062f\u06cc\u06ba \u0645\u0648\u062c\u0648\u062f\u06c1 \u062a\u0627\u0631\u06cc\u062e\u06cc \u0688\u06cc\u0679\u0627 \u0633\u06cc\u0679 \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u06cc \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u0635\u0631\u0641 \u0628\u0627\u0644\u06a9\u0644 \u0646\u0626\u06cc \u0642\u0637\u0627\u0631\u06cc\u06ba \u0631\u06a9\u06be\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u0635\u0644 \u06a9\u0627\u0644\u0645\u0648\u06ba \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u0631\u06a9\u06be\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u0641\u0644\u0679\u0631 \u0634\u062f\u06c1 \u0646\u062a\u0627\u0626\u062c \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>new<\/code>.<\/p>\n<\/li>\n<\/ol>\n<pre><code class=\"language-python\">def remove_duplicates(existing: pd.DataFrame, new: pd.DataFrame) -> pd.DataFrame:\n    \"\"\"Remove rows from 'new' that already exist in 'existing'.\"\"\"\n    # Short-circuit: if either is empty, no work to do\n    if existing.empty or new.empty:\n        return new.copy()\n\n    # Parse types on both sides for a fair comparison\n    existing_std = auto_convert_columns(existing)\n    new_std = auto_convert_columns(new)\n\n    # Build the keys\n    existing_keys = set(create_dedup_key(existing_std).dropna())\n    new_keys = create_dedup_key(new_std)\n\n    # Boolean mask: True where the new row is genuinely new\n    mask = ~new_keys.isin(existing_keys)\n\n    # Index back into the ORIGINAL (non-standardized) 'new' to preserve all columns\n    result = new.iloc[new_keys[mask].index].copy()\n    return result\n<\/code><\/pre>\n<p>\u06a9\u0627\u0631\u06a9\u0631\u062f\u06af\u06cc \u0627\u0648\u0631 \u0645\u0636\u0628\u0648\u0637\u06cc \u06a9\u06cc \u062f\u0648 \u062a\u0641\u0635\u06cc\u0644\u0627\u062a \u0642\u0627\u0628\u0644 \u062a\u0648\u062c\u06c1 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0633\u0628 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 <code>existing_keys<\/code> <strong>\u06c1\u06d2<\/strong> <code>set<\/code><strong>\u0646\u06c1\u06cc\u06ba<\/strong> <code>list<\/code><strong>.<\/strong> \u0645\u0645\u0628\u0631\u0634\u067e \u0679\u06cc\u0633\u0679 (<code>in<\/code> \/ <code>.isin()<\/code>) \u0627\u0632\u06af\u0631 \u06a9\u06d2 \u0644\u06cc\u06d2 <code>set<\/code> \u06c1\u06d2 <strong>\u0627\u0648\u06c1 (1)<\/strong> \u0627\u0633 \u06a9\u06cc \u0648\u062c\u06c1 \u06cc\u06c1 \u06c1\u06d2 \u06a9\u06c1 \u0648\u06c1 \u06c1\u06cc\u0634 \u062a\u0644\u0627\u0634 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u062c\u0648\u0627\u0628 \u062f\u06cc\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062c\u0648 \u0627\u0648\u0633\u0637\u0627\u064b \u062a\u06cc\u0632 \u06c1\u0648\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <em>\u06a9\u06cc\u0627 \u06cc\u06c1 \u0622\u0626\u0679\u0645 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u06cc\u06c1\u0627\u06ba \u06c1\u06d2\u061f<\/em> \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a \u0679\u06cc\u0633\u0679 <code>list<\/code> \u06c1\u06d2 <strong>\u06a9\u0648)<\/strong>: \u0622\u067e \u06a9\u0648 \u0622\u0626\u0679\u0645 \u06a9\u06d2 \u062d\u0633\u0627\u0628 \u0633\u06d2 \u0622\u0626\u0679\u0645 \u0627\u0633\u06a9\u06cc\u0646 \u06a9\u0631\u0646\u0627 \u067e\u0691\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u06cc\u06c1 \u0622\u067e \u06a9\u06d2 \u0645\u0648\u062c\u0648\u062f\u06c1 \u0688\u06cc\u0679\u0627 \u0633\u06cc\u0679 \u06a9\u06d2 \u0628\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0622\u06c1\u0633\u062a\u06c1 \u06c1\u0648\u062a\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u062f\u0633\u06cc\u0648\u06ba \u06c1\u0632\u0627\u0631 \u0642\u0637\u0627\u0631\u0648\u06ba \u0648\u0627\u0644\u06d2 \u0688\u06cc\u0679\u0627 \u0633\u06cc\u0679\u0633 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u06c1\u0631 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0645\u06cc\u06ba \u0646\u0638\u0631 \u0622\u0646\u06d2 \u0648\u0627\u0644\u06d2 \u0641\u0631\u0642 \u0646\u0645\u0627\u06cc\u0627\u06ba \u06c1\u06cc\u06ba \u0627\u0648\u0631 \u06cc\u06c1 \u06a9\u0627\u0645 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0635\u062d\u06cc\u062d \u0688\u06cc\u0679\u0627 \u0688\u06be\u0627\u0646\u0686\u06c1 \u06a9\u0648 \u0645\u0646\u062a\u062e\u0628 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0627\u06cc\u06a9 \u062f\u0631\u0633\u06cc \u06a9\u062a\u0627\u0628 \u06a9\u06cc \u0645\u062b\u0627\u0644 \u06c1\u06cc\u06ba\u06d4 \u0641\u06c1\u0631\u0633\u062a \u067e\u0631 \u0627\u06cc\u06a9 \u0639\u0645\u0648\u0645\u06cc \u0628\u062d\u062b \u0627\u0648\u0631 \u0631\u06c1\u0646\u0645\u0627\u0626\u06cc \u062f\u06cc\u06a9\u06be\u06cc\u06ba \u0627\u0648\u0631 Python \u0645\u06cc\u06ba \u062a\u0644\u0627\u0634 \u06a9\u06cc \u06a9\u0627\u0631\u06a9\u0631\u062f\u06af\u06cc \u06a9\u0648 \u062a\u0631\u062a\u06cc\u0628 \u062f\u06cc\u06ba\u06d4 <code>.isin()<\/code> \u0641\u0644\u0679\u0631\u0646\u06af \u06a9\u06cc \u06a9\u0627\u0631\u06a9\u0631\u062f\u06af\u06cc\u06d4<\/p>\n<p><strong>\u0633\u0627\u062f\u06c1 \u0627\u0635\u0648\u0644:<\/strong> \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba <code>set<\/code> \u062c\u0628 \u0641\u0648\u0631\u06cc \u0631\u06a9\u0646\u06cc\u062a \u06a9\u06cc \u062a\u0635\u062f\u06cc\u0642 \u0636\u0631\u0648\u0631\u06cc \u06c1\u06d2\u06d4 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba <code>list<\/code> \u062c\u0628 \u0622\u067e \u0622\u0631\u0688\u0631 \u06cc\u0627 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u0645\u06cc\u06ba \u062f\u0644\u0686\u0633\u067e\u06cc \u0631\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u062f\u0648\u0633\u0631\u0627 <code>new.iloc[new_keys[mask].index]<\/code> <strong>\u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0634\u0627\u0631\u06cc\u06c1\u06d4 <em>\u0627\u0635\u0644<\/em>\u062a\u0635\u062f\u06cc\u0642 \u0634\u062f\u06c1 \u0646\u06c1\u06cc\u06ba\u06d4<\/strong> <code>new<\/code> <strong>\u0688\u06cc\u0679\u0627 \u0641\u0631\u06cc\u0645<\/strong>\u0646\u06c1\u06cc\u06ba <code>new_std<\/code>.<\/p>\n<p>\u06a9\u06cc\u0648\u06ba <code>auto_convert_columns()<\/code> \u0645\u06cc\u06ba \u0635\u0631\u0641 \u0627\u0633\u06d2 \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0628\u06be\u0627\u06af\u0627 \u062a\u06be\u0627\u06d4 <em>\u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u0633\u062a\u0642\u0644 \u0642\u0633\u0645<\/em>. \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0648\u0627\u0644\u0627 \u0627\u0628 \u0628\u06be\u06cc \u06a9\u0627\u0644 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u062a\u0627 \u06c1\u06d2\u06d4 <em>\u0627\u0635\u0644<\/em> \u06cc\u06c1 \u06c1\u0645\u06cc\u06ba \u06c1\u0631 \u0627\u0633 \u0686\u06cc\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u062e\u0627\u0645 \u0627\u0642\u062f\u0627\u0631 \u0627\u0648\u0631 \u0627\u0633\u06a9\u06cc\u0645\u0627 \u0648\u0627\u067e\u0633 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u062c\u0648 \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u0633\u06d2 \u0628\u0686 \u062c\u0627\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u062b\u0627\u0646\u0648\u06cc \u062d\u0633\u0627\u0628 \u0646\u06c1 \u0644\u06af\u0627\u0626\u06cc\u06ba\u06d4 <em>\u0627\u062a\u0641\u0627\u0642 \u0633\u06d2<\/em> \u0633\u0686\u0627\u0626\u06cc \u06a9\u0627 \u0630\u0631\u06cc\u0639\u06c1 \u0628\u0646\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0641\u06cc\u0635\u0644\u06c1 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u06c1 \u06a9\u06cc\u0627 \u0631\u06a9\u06be\u0646\u0627 \u06c1\u06d2 \u06cc\u0627 \u06c1\u0679\u0627\u0646\u0627 \u06c1\u06d2\u060c \u06c1\u0645\u06cc\u0634\u06c1 \u0627\u067e\u0646\u06cc \u06a9\u0627\u067e\u06cc \u0645\u06cc\u06ba \u062a\u0631\u0645\u06cc\u0645 \u06a9\u0631\u06cc\u06ba\u06d4 \u0627\u06cc\u06a9 \u0628\u0627\u0631 \u062c\u0628 \u0622\u067e \u0627\u067e\u0646\u0627 \u0641\u06cc\u0635\u0644\u06c1 \u06a9\u0631\u0644\u06cc\u06ba \u062a\u0648 \u0627\u0633\u06d2 \u0627\u067e\u0646\u06d2 \u0627\u0635\u0644 \u0688\u06cc\u0679\u0627 \u067e\u0631 \u0644\u0627\u06af\u0648 \u06a9\u0631\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0622\u067e \u06a9\u0648 \u0628\u0639\u062f \u06a9\u06d2 \u0645\u0631\u0627\u062d\u0644 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0635\u0644 \u0645\u0627\u062e\u0630 \u06a9\u06cc \u0627\u0642\u062f\u0627\u0631 \u06a9\u0648 \u0645\u062d\u0641\u0648\u0638 \u0631\u06a9\u06be\u0646\u06d2 \u06a9\u06cc \u0627\u062c\u0627\u0632\u062a \u062f\u06cc\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<p>\u0633\u06cc\u062f\u06be\u06d2 \u0627\u0644\u0641\u0627\u0638 \u0645\u06cc\u06ba:<\/p>\n<ol>\n<li>\n<p>\u067e\u06c1\u0644\u06cc \u062a\u0631\u0645\u06cc\u0645 \u0635\u0631\u0641 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u06d2 \u0645\u0642\u0627\u0635\u062f \u06a9\u06d2 \u0644\u06cc\u06d2 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u0635\u0644 \u0688\u06cc\u0679\u0627 \u06a9\u0648 \u0641\u0644\u0679\u0631 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633 \u0645\u0648\u0627\u0632\u0646\u06c1 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0628\u0639\u062f \u06a9\u06d2 \u0645\u0631\u0627\u062d\u0644 \u0645\u06cc\u06ba \u067e\u0631\u0648\u0633\u06cc\u0633\u0646\u06af \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0635\u0644 \u0642\u0637\u0627\u0631 \u06a9\u0648 \u0628\u063a\u06cc\u0631 \u062a\u0628\u062f\u06cc\u0644\u06cc \u06a9\u06d2 \u0644\u0648\u0679\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ol>\n<p><strong>\u0628\u06c1\u062a\u0631\u06cc\u0646 \u0637\u0631\u0632 \u0639\u0645\u0644:<\/strong> \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u06a9\u06cc\u0632 \u06a9\u0648 \u0633\u0627\u062f\u06c1\u060c \u0645\u0633\u062a\u062d\u06a9\u0645 (\u063a\u06cc\u0631 \u0645\u062a\u063a\u06cc\u0631) \u0627\u0648\u0631 \u06c1\u0645\u06cc\u0634\u06c1 \u0634\u0627\u0631\u0679 \u0633\u0631\u06a9\u06cc\u0679 \u0631\u06a9\u06be\u06cc\u06ba ( <code>if existing.empty or new.empty: return new.copy()<\/code>) \u0628\u06be\u0627\u0631\u06cc \u06a9\u0627\u0645\u0648\u06ba \u06a9\u0648 \u0627\u0646\u062c\u0627\u0645 \u062f\u06cc\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u06d4 \u06cc\u06c1 \u0633\u0633\u062a\u06cc \u062d\u0641\u0627\u0638\u062a\u06cc \u0634\u0642 \u0645\u06c1\u0646\u06af\u06cc \u0688\u067e\u0644\u06cc\u06a9\u06cc\u0634\u0646 \u0645\u0646\u0637\u0642 \u06a9\u0648 \u0686\u06be\u0648\u0691 \u062f\u06cc\u062a\u06cc \u06c1\u06d2 \u062c\u0628 \u067e\u0631\u0627\u0633\u06cc\u0633 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0648\u0626\u06cc \u0688\u06cc\u0679\u0627 \u0646\u06c1 \u06c1\u0648\u06d4<\/p>\n<h3 id=\"heading-put-it-all-together-in-postprocess\">\u06cc\u06c1 \u0633\u0628 \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0631\u06a9\u06be\u0648 <code>postprocess()<\/code><\/h3>\n<p>\u0645\u0646\u062f\u0631\u062c\u06c1 \u0628\u0627\u0644\u0627 \u062a\u0645\u0627\u0645 \u062d\u0635\u06d2 \u0686\u06be\u0648\u0679\u06d2 \u0627\u0648\u0631 \u062e\u0648\u062f \u0622\u0632\u0645\u0627\u0626\u0634\u06cc \u06c1\u06cc\u06ba\u06d4 \u0622\u062e\u0631\u06cc \u0645\u0631\u062d\u0644\u06c1 \u06c1\u06d2\u06d4 <strong>\u062a\u0628\u062f\u06cc\u0644\u06cc<\/strong> \u0627\u0646\u06c1\u06cc\u06ba \u0627\u06cc\u06a9 \u0633\u0627\u062a\u06be \u0686\u067e\u06a9\u0627\u0626\u06cc\u06ba\u06d4 <em>\u062a\u0631\u062a\u06cc\u0628 \u0645\u06cc\u06ba<\/em>\u0630\u06cc\u0644 \u0645\u06cc\u06ba \u0627\u06cc\u06a9 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06d2 \u0633\u0627\u062a\u06be:<\/p>\n<pre><code class=\"language-python\">def postprocess(df: pd.DataFrame) -> pd.DataFrame:\n    \"\"\"Apply all post-processing transformations.\"\"\"\n    if df.empty:\n        return df\n\n    df = df.copy()\n\n    print(\"  1. Converting types...\")\n    df = auto_convert_columns(df)\n\n    print(\"  2. Renaming columns (French \u2192 English)...\")\n    df = rename_to_english(df)\n\n    print(\"  3. Mapping categorical values...\")\n    df = apply_categorical_mappings(df)\n\n    print(\"  4. Adding derived columns...\")\n    df = add_derived_columns(df)\n\n    print(\"  5. Reordering columns...\")\n    df = order_columns(df)\n\n    print(\"  6. Sorting and resetting index...\")\n    df = df.sort_values([\"record_date\", \"station_code\"]).reset_index(drop=True)\n\n    return df\n<\/code><\/pre>\n<p>\u0627\u0633 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u06cc \u0634\u06a9\u0644 \u067e\u0631 \u063a\u0648\u0631 \u06a9\u0631\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0628\u0646\u06cc\u0627\u062f\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0627\u06cc\u06a9 \u0644\u06a9\u06cc\u0631\u06cc \u0627\u0633\u06a9\u0631\u067e\u0679 \u06c1\u06d2 \u062c\u0633 \u0645\u06cc\u06ba \u0686\u06be \u0646\u0645\u0628\u0631 \u0648\u0627\u0644\u06d2 \u067e\u0631\u0646\u0679 \u0634\u062f\u06c1 \u0645\u0631\u0627\u062d\u0644 \u06c1\u06cc\u06ba\u06d4 \u06c1\u0631 \u0627\u06cc\u06a9 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0637\u06d2 \u0634\u062f\u06c1 \u062e\u0627\u0644\u0635 \u0641\u0646\u06a9\u0634\u0646 \u06a9\u0648 \u06a9\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u06a9\u0648\u0626\u06cc \u0646\u0626\u06cc \u0628\u0627\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 <em>\u0645\u0646\u0637\u0642<\/em> \u0628\u0633 \u06cc\u06c1\u0627\u06ba <em>\u062a\u0631\u062a\u06cc\u0628<\/em>. \u06cc\u06c1 \u062c\u0627\u0646 \u0628\u0648\u062c\u06be \u06a9\u0631 \u06c1\u06d2\u06d4<\/p>\n<p><strong>\u0628\u06c1\u062a\u0631\u06cc\u0646 \u0637\u0631\u0632 \u0639\u0645\u0644:<\/strong> \u06c1\u0631 \u0642\u062f\u0645 \u067e\u0631 \u0627\u067e\u0646\u06cc \u067e\u06cc\u0634 \u0631\u0641\u062a \u06a9\u0648 \u0648\u0627\u0636\u062d \u0637\u0648\u0631 \u067e\u0631 \u0631\u06cc\u06a9\u0627\u0631\u0688 \u06a9\u0631\u06cc\u06ba\u06d4 \u062c\u0628 \u0635\u0628\u062d 3 \u0628\u062c\u06d2 \u0637\u06d2 \u0634\u062f\u06c1 \u06a9\u0627\u0645 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u0627\u06cc\u06a9 \u0648\u0627\u0636\u062d \u0645\u0631\u062d\u0644\u06c1 \u0648\u0627\u0631 \u0644\u0627\u06af \u062f\u0648 \u0645\u0646\u0679 \u06a9\u06cc \u062a\u0634\u062e\u06cc\u0635 \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u06af\u06be\u0646\u0679\u06d2 \u06a9\u06d2 \u0627\u0646\u062f\u0627\u0632\u06d2 \u06a9\u06d2 \u062f\u0631\u0645\u06cc\u0627\u0646 \u0641\u0631\u0642 \u067e\u06cc\u062f\u0627 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u06cc\u06a9 \u0627\u0686\u06be\u0627 \u0622\u067e\u0634\u0646 \u0644\u0627\u06af\u0631 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1\u0627\u06ba \u06cc\u06c1 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u06a9\u0644\u0627\u0633\u06a9 \u06a9\u0646\u0633\u0648\u0644 \u067e\u0631\u0646\u0679\u0646\u06af \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 (<code>print(f\" 1. Converting types...\")<\/code>)\u06d4<\/p>\n<h2 id=\"heading-part-6-the-load-step\">\u062d\u0635\u06c1 6: \u0644\u0648\u0688 \u0641\u06cc\u0632<\/h2>\n<h3 id=\"heading-design-logic\">\u0688\u06cc\u0632\u0627\u0626\u0646 \u0645\u0646\u0637\u0642<\/h3>\n<p><strong>\u0644\u0648\u0688<\/strong> \u0622\u062e\u0631\u06cc \u0645\u0631\u062d\u0644\u06c1: \u067e\u0631\u0648\u0633\u06cc\u0633 \u0634\u062f\u06c1 \u0688\u06cc\u0679\u0627 \u0644\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0627\u0633 \u06a9\u06cc \u0645\u0646\u0632\u0644 \u062a\u06a9 \u0644\u06d2 \u062c\u0627\u0626\u06cc\u06ba\u06d4 \u0645\u0634\u062a\u0631\u06a9\u06c1 \u0627\u06c1\u062f\u0627\u0641 \u0645\u06cc\u06ba \u0688\u06cc\u0679\u0627 \u06af\u0648\u062f\u0627\u0645\u060c \u0688\u06cc\u0679\u0627 \u0644\u06cc\u06a9\u0633\u060c \u0627\u0648\u0631 \u0688\u06cc\u0679\u0627 \u0628\u06cc\u0633 \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba\u06d4<\/p>\n<p>\u0634\u0627\u0626\u0639 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u062f\u0648 \u0686\u06cc\u0632\u06cc\u06ba \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u06cc \u06c1\u06d2: \u0622\u0624\u0679 \u067e\u0679 \u0641\u0648\u0644\u0688\u0631 \u062e\u0648\u062f \u0627\u0648\u0631 \u0627\u06cc\u06a9 \u0645\u06cc\u0679\u0627 \u0688\u06cc\u0679\u0627 \u0641\u0627\u0626\u0644 \u062c\u0648 \u0688\u06cc\u0679\u0627\u0633\u06cc\u0679 \u06a9\u06cc \u0648\u0636\u0627\u062d\u062a \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<h4 id=\"heading-code-level-walkthrough\">\u06a9\u0648\u0688 \u0644\u06cc\u0648\u0644 \u0648\u0627\u06a9 \u062a\u06be\u0631\u0648<\/h4>\n<p><code>create_output_dir()<\/code>    \u0686\u06cc\u06a9 \u06a9\u0631\u06cc\u06ba \u06a9\u06c1 \u0622\u06cc\u0627 \u0622\u0624\u0679 \u067e\u0679 \u0641\u0648\u0644\u0688\u0631 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2 \u0627\u0648\u0631 \u0627\u06af\u0631 \u0646\u06c1\u06cc\u06ba \u062a\u0648 \u0627\u0633\u06d2 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4<\/p>\n<ul>\n<li>\n<p>\u0627\u06af\u0631 <code>use_mock<\/code> \u06c1\u06d2 <code>True<\/code>\u06cc\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 <code>KAGGLE_CONFIG.mock_output_dir<\/code>\u062c\u0639\u0644\u06cc \u0688\u06cc\u0679\u0627 \u06a9\u06cc \u0688\u0627\u0626\u0631\u06a9\u0679\u0631\u06cc\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0628\u0635\u0648\u0631\u062a \u062f\u06cc\u06af\u0631\u060c \u06cc\u06c1 \u0627\u06af\u0644\u06cc \u0633\u06cc\u0679 \u06a9\u06cc \u0627\u0635\u0644 \u0622\u0624\u0679 \u067e\u0679 \u0688\u0627\u0626\u0631\u06a9\u0679\u0631\u06cc \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 <code>KAGGLE_CONFIG.output_dir<\/code>.<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"language-python\">def create_output_dir(use_mock: bool = False) -> None:\n    \"\"\"Create output directory (and parents) if it does not already exist.\"\"\"\n    output_dir = KAGGLE_CONFIG.mock_output_dir if use_mock else KAGGLE_CONFIG.output_dir\n    output_dir.mkdir(parents=True, exist_ok=True)\n    # exist_ok=True: idempotent, safe to call multiple times\n<\/code><\/pre>\n<p><code>exist_ok=True<\/code>    \u06cc\u06c1 \u0627\u06cc\u06a9 \u0686\u06be\u0648\u0679\u06cc \u0644\u06cc\u06a9\u0646 \u0627\u06c1\u0645 \u062a\u0641\u0635\u06cc\u0644 \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u06d2 \u0628\u063a\u06cc\u0631\u060c <code>Path.mkdir()<\/code> \u062a\u0627\u062b\u0631 <code>FileExistsError<\/code> \u0627\u06af\u0631 \u0688\u0627\u0626\u0631\u06cc\u06a9\u0679\u0631\u06cc \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u06c1\u0631 \u0628\u0627\u0631 \u0645\u0648\u062c\u0648\u062f \u0631\u06c1\u06d2 \u06af\u06cc \u062c\u0628 \u0627\u0633\u06d2 \u067e\u06c1\u0644\u06cc \u06a9\u06d2 \u0628\u0639\u062f \u0686\u0644\u0627\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<p>\u0645\u0627\u062d\u0648\u0644 <code>exist_ok=True<\/code> \u0688\u0627\u0626\u0631\u06cc\u06a9\u0679\u0631\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba <strong>\u0628\u06d2 \u062d\u0633\u06cc<\/strong>: 100 \u0628\u0627\u0631 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u0648\u06c1\u06cc \u0627\u062b\u0631 \u067e\u0691\u06d2 \u06af\u0627 \u062c\u0648 1 \u0628\u0627\u0631 \u06a9\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u06c1\u0648\u06af\u0627\u06d4 \u0641\u0627\u0626\u0644 \u0633\u0633\u0679\u0645\u0632 \u0645\u06cc\u06ba\u060c \u062d\u0635\u06c1 5 \u0645\u06cc\u06ba \u0646\u0642\u0644 \u06a9\u06cc \u0645\u0646\u0637\u0642 \u06a9\u06d2 \u067e\u06cc\u0686\u06be\u06d2 \u06cc\u06c1 \"\u062f\u0648\u0628\u0627\u0631\u06c1 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0645\u062d\u0641\u0648\u0638\" \u062e\u06cc\u0627\u0644 \u06c1\u06d2\u06d4<\/p>\n<p>Kaggle API \u0688\u06cc\u0679\u0627 \u067e\u06cc\u06a9\u06cc\u062c \u06a9\u06cc \u062a\u0641\u0635\u06cc\u0644\u0627\u062a \u06a9\u06cc \u067e\u06cc\u0631\u0648\u06cc \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0648\u0636\u0627\u062d\u062a \u062f\u0631\u06a9\u0627\u0631 \u06c1\u06d2\u06d4 <code>dataset-metadata.json<\/code> CSV \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u06cc\u06a9 \u0641\u0627\u0626\u0644 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 \u06cc\u06c1 \u067e\u06cc\u0631\u0633 \u0633\u06cc\u0644\u0627\u0628 \u0688\u06cc\u0679\u0627 \u0633\u06cc\u0679 \u06a9\u06cc \u062a\u0644\u0627\u0634 \u0627\u0648\u0631 \u062f\u0631\u06cc\u0627\u0641\u062a \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06c1\u0645 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\">def create_metadata(df: pd.DataFrame, config: KaggleConfig) -> Dict:\n    \"\"\"Generate Kaggle dataset metadata from DataFrame and config.\"\"\"\n    if df.empty or \"record_date\" not in df.columns:\n        first_date = \"unknown\"\n        last_date = \"unknown\"\n    else:\n        first_date = df[\"record_date\"].min().strftime(\"%Y-%m-%d\")\n        last_date = df[\"record_date\"].max().strftime(\"%Y-%m-%d\")\n\n    return {\n        \"title\": config.title,\n        \"id\": config.dataset_slug,\n        \"licenses\": [{\"name\": config.license_name}],\n        \"keywords\": config.keywords,\n        \"temporalCoverage\": {\"startDate\": first_date, \"endDate\": last_date},\n        \"geospatialCoverage\": config.geospatial_coverage,\n        \"updateFrequency\": config.update_frequency,\n    }\n<\/code><\/pre>\n<p>\u0645\u06cc\u0679\u0627 \u0688\u06cc\u0679\u0627 \u06c1\u06d2 <code>KaggleConfig<\/code> \u0688\u06cc\u0679\u0627 \u06a9\u0644\u0627\u0633\u06d4 \u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0627\u0633 \u06a9\u0627 \u062d\u0648\u0627\u0644\u06c1 \u062f\u06cc\u06ba\u06d4 <code>temporalCoverage<\/code> \u0634\u0645\u0627\u0631 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2 <em>\u0688\u06cc\u0679\u0627 \u0633\u06d2 \u06c1\u06cc<\/em> (<code>df[\"record_date\"].min()<\/code>\/<code>.max()<\/code>) \u06c1\u0627\u0631\u0688 \u06a9\u0648\u0688 \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u062c\u0628 \u0628\u06be\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0686\u0644\u062a\u06cc \u06c1\u06d2\u060c \u0645\u06cc\u0679\u0627 \u0688\u06cc\u0679\u0627 \u0645\u06cc\u06ba \u062a\u0627\u0631\u06cc\u062e \u06a9\u06cc \u062d\u062f \u062e\u0648\u062f \u0628\u062e\u0648\u062f \u062f\u0633\u062a\u06cc \u0628\u06a9 \u06a9\u06cc\u067e\u0646\u06af \u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u062d\u0642\u06cc\u0642\u062a \u06a9\u06cc \u0639\u06a9\u0627\u0633\u06cc \u06a9\u0631\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<p>\u0622\u062e\u0631 \u06a9\u0627\u0631 <code>publish_to_kaggle()<\/code> \u0627\u067e\u0646\u0627 \u0627\u067e \u0688\u06cc\u0679 \u06a9\u0631\u062f\u06c1 \u0688\u06cc\u0679\u0627\u0633\u06cc\u0679 Kaggle \u067e\u0631 \u0627\u067e \u0644\u0648\u0688 \u06a9\u0631\u06cc\u06ba\u06d4 Kaggle CLI \u06a9\u0648 \u0627\u06cc\u06a9 \u0628\u06cc\u0631\u0648\u0646\u06cc \u06a9\u0645\u0627\u0646\u0688 \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0637\u0644\u0628 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<p>\u0641\u0646\u06a9\u0634\u0646:<\/p>\n<ol>\n<li>\n<p>\u0645\u0648\u062c\u0648\u062f\u06c1 \u0648\u0642\u062a \u062d\u0627\u0635\u0644 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u0627\u0633\u06d2 \u0627\u0633 \u0637\u0631\u062d \u0679\u06cc\u06a9\u0633\u0679 \u0644\u06cc\u0628\u0644 \u0645\u06cc\u06ba \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u06cc\u06ba: <code>Weekly update: 2026-07-13 14:30:00<\/code><\/p>\n<\/li>\n<li>\n<p>\u062f\u0631\u062c \u0630\u06cc\u0644 Kaggle \u06a9\u0645\u0627\u0646\u0688 \u0644\u06a9\u06be\u06cc\u06ba:<\/p>\n<ul>\n<li>\n<p>\u0688\u06cc\u0679\u0627 \u0633\u06cc\u0679 \u06a9\u0627 \u0646\u06cc\u0627 \u0648\u0631\u0698\u0646 \u0634\u0627\u0626\u0639 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u062f\u0631\u062c \u0630\u06cc\u0644 \u0641\u0627\u0626\u0644\u06cc\u06ba \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u06cc\u06ba\u06d4 <code>KAGGLE_CONFIG.output_dir<\/code><\/p>\n<\/li>\n<li>\n<p>\u0627\u06cc\u06a9 \u067e\u06cc\u063a\u0627\u0645 \u0645\u0646\u0633\u0644\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0688\u0627\u0626\u0631\u06a9\u0679\u0631\u06cc \u06a9\u06d2 \u0645\u0648\u0627\u062f \u06a9\u0648 \u06a9\u0645\u067e\u0631\u06cc\u0633 \u06a9\u0631\u06cc\u06ba\u06d4<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<li>\n<p>\u06a9\u0645\u0627\u0646\u0688 \u067e\u0631\u0646\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 \u062a\u0627\u06a9\u06c1 \u0622\u067e \u062f\u06cc\u06a9\u06be \u0633\u06a9\u06cc\u06ba \u06a9\u06c1 \u06a9\u06cc\u0627 \u06a9\u06cc\u0627 \u062c\u0627\u0626\u06d2 \u06af\u0627\u06d4<\/p>\n<\/li>\n<li>\n<p>\u0627\u0633 \u06a9\u0627 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u062a\u06d2 \u06c1\u0648\u0626\u06d2 \u06a9\u0645\u0627\u0646\u0688 \u0686\u0644\u0627\u0626\u06cc\u06ba: <code>subprocess.run(...)<\/code><\/p>\n<\/li>\n<\/ol>\n<p>\u0627\u06af\u0631 \u0627\u067e \u0644\u0648\u0688 \u06a9\u0627\u0645 \u06a9\u0631\u062a\u0627 \u06c1\u06d2:<\/p>\n<ul>\n<li>\u06cc\u06c1 \u067e\u0631\u0646\u0679 \u06a9\u0631\u062a\u0627 \u06c1\u06d2 <code>Successfully published to Kaggle.<\/code><\/li>\n<\/ul>\n<p>\u0627\u06af\u0631 \u06cc\u06c1 \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648\u062c\u0627\u062a\u0627 \u06c1\u06d2:<\/p>\n<ul>\n<li>\u063a\u0644\u0637\u06cc \u06a9\u0648 \u067e\u0631\u0646\u0679 \u06a9\u0631\u06cc\u06ba \u0627\u0648\u0631 \u067e\u06be\u0631 \u063a\u0644\u0637\u06cc \u06a9\u0648 \u0686\u06be\u067e\u0627\u0646\u06d2 \u0633\u06d2 \u0631\u0648\u06a9\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u0633\u06d2 \u062f\u0648\u0628\u0627\u0631\u06c1 \u0628\u0691\u06be\u0627\u0626\u06cc\u06ba\u06d4<\/li>\n<\/ul>\n<pre><code class=\"language-python\">def publish_to_kaggle() -> None:\n    \"\"\"Publish the updated dataset to Kaggle using the Kaggle CLI.\"\"\"\n    timestamp = pd.Timestamp.now().strftime(\"%Y-%m-%d %H:%M:%S\")\n    message = f\"Weekly update: {timestamp}\"\n\n    cmd = [\n        \"kaggle\", \"datasets\", \"version\",\n        \"-p\", str(KAGGLE_CONFIG.output_dir),\n        \"-m\", message,\n        \"--dir-mode\", \"zip\",\n    ]\n\n    print(\"Publishing to Kaggle...\")\n    print(\"Command:\", \" \".join(cmd))\n\n    try:\n        subprocess.run(cmd, check=True)\n        print(\"Successfully published to Kaggle.\")\n    except subprocess.CalledProcessError as e:\n        print(f\"Error publishing to Kaggle: {e}\")\n        raise\n<\/code><\/pre>\n<p><code>publish_to_kaggle<\/code>    Python \u06a9\u06d2 \u0630\u0631\u06cc\u0639\u06d2 Kaggle \u06a9\u0645\u0627\u0646\u0688 \u0644\u0627\u0626\u0646 \u0627\u0646\u0679\u0631\u0641\u06cc\u0633 (CLI) \u06a9\u06cc \u062f\u0631\u062e\u0648\u0627\u0633\u062a \u06a9\u0631\u06cc\u06ba\u06d4 <code>subprocess<\/code> \u0645\u0627\u0688\u06cc\u0648\u0644 \u06cc\u06c1 \u0627\u06cc\u06a9 Python \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0645\u06cc\u06ba \u0628\u06cc\u0631\u0648\u0646\u06cc \u06a9\u0645\u0627\u0646\u0688 \u0644\u0627\u0626\u0646 \u0679\u0648\u0644\u0632 \u06a9\u0648 \u0686\u0644\u0627\u0646\u06d2 \u06a9\u0627 \u0645\u0639\u06cc\u0627\u0631\u06cc \u0637\u0631\u06cc\u0642\u06c1 \u06c1\u06d2\u06d4<\/p>\n<p>\u06cc\u06c1\u0627\u06ba \u062f\u0648 \u0627\u0646\u062a\u062e\u0627\u0628 \u0627\u06cc\u06a9 \u0639\u0627\u0645 \u0639\u0627\u062f\u062a \u06a9\u06d2 \u0637\u0648\u0631 \u067e\u0631 \u0627\u067e\u0646\u0627\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u06c1\u06cc\u06ba\u060c \u0646\u06c1 \u06a9\u06c1 \u0635\u0631\u0641 Kaggle \u06a9\u06d2 \u0644\u06cc\u06d2\u06d4<\/p>\n<ul>\n<li>\n<p><code>cmd<\/code> <strong>\u06a9\u06d2 \u0633\u0627\u062a\u06be \u0628\u0646\u0627\u06cc\u0627 \u06af\u06cc\u0627 \u062a\u06be\u0627\u06d4<\/strong> <code>list<\/code><strong>\u06cc\u06c1 \u06a9\u0628\u06be\u06cc \u0628\u06be\u06cc \u0645\u0631\u0628\u0648\u0637 \u062a\u0627\u0631 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4<\/strong> \u062f\u0644\u0627\u0626\u0644 \u06a9\u06cc \u0641\u06c1\u0631\u0633\u062a \u067e\u0627\u0633 \u06a9\u0631\u06cc\u06ba\u06d4 <code>subprocess.run<\/code> \u0634\u06cc\u0644 \u06a9\u0627\u0644 \u06a9\u0648 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0686\u06be\u0648\u0691 \u062f\u06cc\u06ba\u06d4 \u06cc\u06c1 \u0634\u06cc\u0644 \u0627\u0646\u062c\u06cc\u06a9\u0634\u0646 \u06a9\u06d2 \u062e\u0637\u0631\u0627\u062a \u0633\u06d2 \u0628\u0686\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u062e\u0627\u0644\u06cc \u062c\u06af\u06c1\u0648\u06ba \u06cc\u0627 \u062e\u0635\u0648\u0635\u06cc \u062d\u0631\u0648\u0641 \u067e\u0631 \u0645\u0634\u062a\u0645\u0644 \u062f\u0644\u0627\u0626\u0644 \u06a9\u0648 \u0645\u0646\u0627\u0633\u0628 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u06c1\u06cc\u0646\u0688\u0644 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 \u0622\u0641\u06cc\u0634\u0644 \u062f\u06cc\u06a9\u06be\u06cc\u06ba <code>subprocess<\/code> \u0633\u06cc\u06a9\u06cc\u0648\u0631\u0679\u06cc \u06a9\u06d2 \u062a\u062d\u0641\u0638\u0627\u062a\u06d4<\/p>\n<\/li>\n<li>\n<p><code>check=True<\/code>    \u06cc\u0639\u0646\u06cc\u060c \u0627\u06af\u0631 Kaggle CLI \u0646\u0627\u06a9\u0627\u0645 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u060c \u062a\u0648 \u06cc\u06c1 \u063a\u06cc\u0631 \u0635\u0641\u0631 \u06a9\u06cc \u062d\u06cc\u062b\u06cc\u062a \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0646\u06a9\u0644 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>subprocess.run<\/code> \u062a\u0627\u062b\u0631 <code>CalledProcessError<\/code> \u062e\u0627\u0645\u0648\u0634\u06cc \u0633\u06d2 \u0644\u0648\u0679\u0646\u06d2 \u06a9\u06cc \u0628\u062c\u0627\u0626\u06d2\u06d4 \u0628\u063a\u06cc\u0631 <code>check=True<\/code>\u0627\u06cc\u06a9 \u0646\u0627\u06a9\u0627\u0645 \u0627\u0634\u0627\u0639\u062a \u0628\u0627\u0644\u06a9\u0644 \u0628\u0642\u06cc\u06c1 \u06a9\u0648\u0688 \u0645\u06cc\u06ba \u06a9\u0627\u0645\u06cc\u0627\u0628 \u0627\u0634\u0627\u0639\u062a \u06a9\u06cc \u0637\u0631\u062d \u062f\u06a9\u06be\u0627\u0626\u06cc \u062f\u06cc\u062a\u06cc \u06c1\u06d2\u06d4<\/p>\n<\/li>\n<\/ul>\n<h2 id=\"heading-part-7-assemble-the-full-pipeline\">\u062d\u0635\u06c1 7: \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0627\u0633\u0645\u0628\u0644\u06cc \u0645\u06a9\u0645\u0644 \u06a9\u0631\u06cc\u06ba\u06d4<\/h2>\n<h3 id=\"heading-the-global-rehearsal-mock-mode\">\u0639\u0627\u0644\u0645\u06cc \u0631\u06cc\u06c1\u0631\u0633\u0644 (\u0645\u0630\u0627\u0642 \u0645\u0648\u0688)<\/h3>\n<p>\u067e\u0648\u0631\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u0622\u0632\u0627\u062f\u0627\u0646\u06c1 \u0637\u0648\u0631 \u067e\u0631 \u0628\u0646\u0627\u06cc\u0627 \u0627\u0648\u0631 \u062c\u0627\u0646\u0686\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0628 \u0628\u0644\u0627\u06a9\u0633 \u06a9\u0648 \u0627\u06cc\u06a9 \u0644\u06a9\u06cc\u0631\u06cc \u0641\u0646\u06a9\u0634\u0646 \u0645\u06cc\u06ba \u062c\u0648\u0691\u0646\u06d2 \u06a9\u0627 \u0648\u0642\u062a \u0622\u06af\u06cc\u0627 \u06c1\u06d2\u06d4 \u0633\u0628 \u0633\u06d2 \u067e\u06c1\u0644\u06d2\u060c \u0627\u0633\u06d2 \u0645\u06a9\u0645\u0644 \u0637\u0648\u0631 \u067e\u0631 \u0641\u0631\u0636\u06cc \u0688\u06cc\u0679\u0627 \u067e\u0631 \u0686\u0644\u0627\u0626\u06cc\u06ba\u06d4 \u0627\u0633 \u0637\u0631\u062d \u06a9\u0686\u06be \u0628\u06be\u06cc \u0634\u0627\u0626\u0639 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627\u06d4 \u0645\u0638\u0627\u06c1\u0631\u06d2 \u06a9\u06d2 \u0645\u0642\u0627\u0635\u062f \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0645\u0635\u0646\u0648\u0639\u06cc \u0688\u06cc\u0679\u0627 \u0633\u06d2 \u0628\u06be\u0631\u0627 \u06c1\u0648\u0627 CSV \u0645\u0642\u0627\u0645\u06cc \u0637\u0648\u0631 \u067e\u0631 \u0645\u062d\u0641\u0648\u0638 \u06a9\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 <code>mock_output<\/code> \u0641\u0648\u0644\u0688\u0631<\/p>\n<pre><code class=\"language-python\">def run_etl_pipeline(use_mock: bool = True) -> pd.DataFrame:\n    \"\"\"Run the complete ETL pipeline: Extract \u2192 Transform \u2192 Load to CSV.\"\"\"\n\n    # STEP 1: LOAD EXISTING DATA\n    if use_mock:\n        loaded_df = pd.DataFrame(mock_api_response)\n        loaded_df['date_obs_elab'] = pd.to_datetime(loaded_df['date_obs_elab'])\n        loaded_df = rename_to_english(loaded_df)\n    else:\n        loaded_df = load_csv(KAGGLE_CONFIG.input_csv)\n\n    # STEP 2: DETERMINE UPDATE RANGE\n    should_update, start_date = determine_update_range(loaded_df)\n    if not should_update:\n        return loaded_df   # already current: nothing more to do\n\n    # STEP 3: EXTRACT (FETCH DATA)\n    fetched_data = fetch_all_data(start_date, use_mock=use_mock)\n\n    # STEP 4: TRANSFORM I - DEDUPLICATE\n    deduped_fetched_data = remove_duplicates(loaded_df, fetched_data)\n\n    # STEP 5: TRANSFORM II - COMBINE (MERGE WITH EXISTING)\n    new_df_english = rename_to_english(deduped_fetched_data)\n    merged_historical_and_new = pd.concat([loaded_df, new_df_english], ignore_index=True)\n\n    # STEP 6: TRANSFORM III - POST-PROCESS\n    processed_records = postprocess(merged_historical_and_new)\n\n    # STEP 7: EXPORT (LOAD TO CSV)\n    create_output_dir(use_mock=use_mock)\n    output_path = KAGGLE_CONFIG.mock_output_filename if use_mock else KAGGLE_CONFIG.output_csv_path\n    processed_records.to_csv(output_path, index=False, sep=\",\")\n\n    return processed_records\n<\/code><\/pre>\n<p>\u0633\u0628 \u0633\u06d2 \u0627\u0648\u067e\u0631 \u06a9\u06d2 \u0633\u0627\u062a \u0645\u0631\u0627\u062d\u0644 \u0627\u0646 \u0641\u0646\u06a9\u0634\u0646\u0632 \u0633\u06d2 \u0645\u0637\u0627\u0628\u0642\u062a \u0631\u06a9\u06be\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u06c1\u0645 \u0646\u06d2 \u067e\u06c1\u0644\u06d2 \u06c1\u06cc \u0627\u0633 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0645\u06cc\u06ba \u0628\u0646\u0627\u0626\u06d2 \u0627\u0648\u0631 \u062c\u0627\u0646\u0686\u06d2 \u06c1\u06cc\u06ba\u06d4 <strong>\u0627\u0646 \u06a9\u0648 \u062c\u0645\u0639 \u06a9\u0631\u0646\u0627 \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u0645\u06a9\u06cc\u0646\u06cc\u06a9\u0644 \u06c1\u06d2\u06d4<\/strong> \u06cc\u06c1 \u06c1\u0645\u06cc\u0634\u06c1 \u0686\u06be\u0648\u0679\u06d2\u060c \u0648\u0627\u062d\u062f \u0630\u0645\u06c1 \u062f\u0627\u0631\u06cc \u06a9\u06d2 \u0627\u0641\u0639\u0627\u0644 \u06a9\u0648 \u0645\u0646\u0638\u0645 \u06a9\u0631\u0646\u06d2 \u06a9\u0627 \u0627\u06cc\u06a9 \u0641\u0627\u0626\u062f\u06c1 \u06c1\u06d2\u06d4<\/p>\n<pre><code class=\"language-python\">loaded_df                 = load_csv(...)                          # 1. load existing data\nshould_update, start_date = determine_update_range(...)            # 2. check what's needed\nfetched_data               = fetch_all_data(start_date)             # 3. fetch new records\ndeduped_fetched_data       = remove_duplicates(existing, new_raw)   # 4. deduplicate\nmerged_historical_and_new  = pd.concat([existing, new_clean])       # 5. merge\nprocessed_records          = postprocess(merged_historical_and_new) # 6. postprocess\nprocessed_records.to_csv(...)                                       # 7. save\nwrite_metadata() + publish_to_kaggle()                               # 8. publish\n<\/code><\/pre>\n<p>\u06c1\u0631 \u0633\u0637\u0631 \u06a9\u0627 \u0645\u0642\u0635\u062f \u0635\u0631\u0641 \u0628\u0627\u0626\u06cc\u06ba \u0633\u06d2 \u062f\u0627\u0626\u06cc\u06ba \u067e\u0691\u06be\u0646\u06d2 \u0633\u06d2 \u0648\u0627\u0636\u062d \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0648\u06c1 \u0645\u0642\u0627\u0645 \u06c1\u06d2 \u062c\u06c1\u0627\u06ba \u06af\u0644\u0646\u0627 \u0622\u0633\u0627\u0646 \u06c1\u0648 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4<\/p>\n<h3 id=\"heading-main-pipeline-orchestration\"><code>main()<\/code>: \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0622\u0631\u06a9\u06cc\u0633\u0679\u0631\u06cc\u0634\u0646<\/h3>\n<p><code>main()<\/code>    \u06cc\u06c1 \u0645\u0648\u0635\u0644 \u06c1\u06d2\u06d4 \u067e\u06c1\u0644\u06d2 \u0633\u06d2 \u0628\u0646\u0627\u0626\u06d2 \u06af\u0626\u06d2 \u062a\u0645\u0627\u0645 \u0627\u062c\u0632\u0627\u0621 \u06a9\u0648 \u0635\u062d\u06cc\u062d \u062a\u0631\u062a\u06cc\u0628 \u0645\u06cc\u06ba \u062c\u0648\u0691\u06cc\u06ba\u06d4 <code>postprocess()<\/code> \u0627\u06cc\u06a9 \u062f\u0631\u062c\u06d2 \u0646\u06cc\u0686\u06d2 \u0686\u0644\u0627 \u06af\u06cc\u0627\u06d4<\/p>\n<pre><code class=\"language-python\">def main() -> None:\n    \"\"\"Execute the full Paris Flood Monitoring ETL pipeline.\n\n    EXTRACT\n    1. Load the existing dataset from the Kaggle input mount\n    2. Determine whether an update is needed (and from what date)\n    3. Fetch new data from the Hub'Eau API\n\n    TRANSFORM\n    4. Deduplicate against the existing dataset\n    5. Combine and post-process (type parsing, translation, derived cols...)\n\n    LOAD\n    6. Write the updated CSV and metadata file\n    7. Publish the new dataset version to Kaggle\n\n    Exits early if the dataset is already up to date.\n    \"\"\"\n    final_dataset = run_etl_pipeline(use_mock=False)\n    final_dataset.to_csv(KAGGLE_CONFIG.output_csv_path, index=False)\n    write_metadata(final_dataset)\n\n    print(\"n[FINAL STEP] Publishing to Kaggle...\")\n    publish_to_kaggle()\n\n    print(\"Running post-run validation\")\n    validate_and_analyze(final_dataset)\n\n\nif __name__ == \"__main__\":\n    main()\n<\/code><\/pre>\n<h3 id=\"heading-the-if-name-main-guard\">\u06a9\u06c1 <code>if __name__ == \"__main__\":<\/code> \u0628\u0627\u0624\u0646\u0633\u0631<\/h3>\n<pre><code class=\"language-python\">if __name__ == \"__main__\":\n    main()\n<\/code><\/pre>\n<p>\u06cc\u06c1 Python \u06a9\u06d2 \u0633\u0628 \u0633\u06d2 \u0639\u0627\u0645 \u0645\u062d\u0627\u0648\u0631\u0648\u06ba \u0645\u06cc\u06ba \u0633\u06d2 \u0627\u06cc\u06a9 \u06c1\u06d2\u060c \u0627\u0648\u0631 \u06cc\u06c1 \u0633\u0645\u062c\u06be\u0646\u0627 \u0627\u0686\u06be\u0627 \u06c1\u06d2 \u06a9\u06c1 \u06cc\u06c1 \u06a9\u06cc\u0627 \u06a9\u0631\u062a\u0627 \u06c1\u06d2\u06d4 Python \u06a9\u06cc \u0633\u0631\u06a9\u0627\u0631\u06cc \u062f\u0633\u062a\u0627\u0648\u06cc\u0632\u0627\u062a \u06a9\u06d2 \u0645\u0637\u0627\u0628\u0642: <code>__main__<\/code>:<\/p>\n<p><strong>\u0628\u06c1\u062a\u0631\u06cc\u0646 \u0637\u0631\u0632 \u0639\u0645\u0644:<\/strong> \u0627\u067e\u0646\u06d2 \u062f\u0627\u062e\u0644\u06cc \u0645\u0642\u0627\u0645\u0627\u062a \u06a9\u0648 \u06c1\u0645\u06cc\u0634\u06c1 \u0627\u0633 \u0637\u0631\u062d \u0645\u062d\u0641\u0648\u0638 \u0631\u06a9\u06be\u06cc\u06ba\u06d4 \u06c1\u0645 \u0645\u062d\u0641\u0648\u0638 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0645\u0627\u0688\u06cc\u0648\u0644 \u062a\u06cc\u0627\u0631 \u06a9\u0631\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 <strong>\u062f\u0631\u0622\u0645\u062f \u06a9\u06d2 \u0644\u06cc\u06d2 \u062f\u0633\u062a\u06cc\u0627\u0628 \u06c1\u06d2\u06d4<\/strong> \u0635\u0631\u0641 \u062f\u0631\u0622\u0645\u062f \u06a9\u0631 \u06a9\u06d2\u060c \u0622\u067e \u067e\u0648\u0631\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u0645\u062a\u062d\u0631\u06a9 \u06a9\u06cc\u06d2 \u0628\u063a\u06cc\u0631 \u0627\u0646\u0641\u0631\u0627\u062f\u06cc \u062e\u0635\u0648\u0635\u06cc\u0627\u062a \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u06cc\u0627 \u0627\u0646\u06c1\u06cc\u06ba \u062f\u0648\u0633\u0631\u06cc \u0627\u0633\u06a9\u0631\u067e\u0679\u0633 \u0645\u06cc\u06ba \u062f\u0648\u0628\u0627\u0631\u06c1 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba (\u0628\u0634\u0645\u0648\u0644 Kaggle \u067e\u0631 \u0627\u0635\u0644 \u0627\u0634\u0627\u0639\u062a)\u06d4<\/p>\n<h2 id=\"heading-part-8-go-live-and-switch-to-the-real-api\">\u062d\u0635\u06c1 8: \u0644\u0627\u0626\u06cc\u0648 \u0633\u0679\u0631\u06cc\u0645\u0646\u06af \u0627\u0648\u0631 \u062d\u0642\u06cc\u0642\u06cc APIs \u06a9\u06cc \u0637\u0631\u0641 \u062c\u0627\u0646\u0627<\/h2>\n<p>\u0645\u0630\u06a9\u0648\u0631\u06c1 \u0628\u0627\u0644\u0627 \u0633\u0628\u06be\u06cc \u0641\u0631\u0636\u06cc \u0688\u06cc\u0679\u0627 \u067e\u0631 \u0645\u062d\u0641\u0648\u0638 \u0637\u0631\u06cc\u0642\u06d2 \u0633\u06d2 \u0686\u0644\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u06d2 \u0628\u062c\u0627\u0626\u06d2\u060c \u0627\u067e\u0646\u06cc \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u06a9\u0648 \u0627\u0635\u0644 Hub'Eau API \u06a9\u06cc \u0637\u0631\u0641 \u0627\u0634\u0627\u0631\u06c1 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2:<\/p>\n<ol>\n<li>\n<p>\u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 \u0627\u0633 \u06a9\u0627 \u062d\u0648\u0627\u0644\u06c1 \u062f\u06cc\u06ba\u06d4 <code>use_mock=False<\/code> \u0627\u0648\u067e\u0631 \u06a9\u06cc \u062a\u0631\u062a\u06cc\u0628\u0627\u062a\u06d4 \u06cc\u06c1 \u06af\u06be\u0633 \u062c\u0627\u062a\u0627 \u06c1\u06d2 <code>APIConfig.use_mock<\/code>\u0627\u0648\u0631 \u067e\u06be\u0631 \u0627\u06cc\u06a9 \u06a9\u0627\u0644 <code>run_etl_pipeline(use_mock=False)<\/code> \u0627\u0648\u0631 <code>main()<\/code>.<\/p>\n<\/li>\n<li>\n<p>\u06cc\u0642\u06cc\u0646\u06cc \u0628\u0646\u0627\u0626\u06cc\u06ba <code>KAGGLE_CONFIG.dataset_slug<\/code> \u0627\u0648\u0631 <code>input_csv<\/code> \u0627\u0634\u0627\u0631\u06c1 \u06a9\u0631\u06cc\u06ba <strong>\u0622\u067e \u06a9\u0627 \u0627\u067e\u0646\u0627<\/strong> Kaggle \u0688\u06cc\u0679\u0627\u0633\u06cc\u0679 \u06a9\u0648 \u0627\u0633\u062a\u0639\u0645\u0627\u0644 \u06a9\u0631\u0646\u06d2 \u0633\u06d2 \u067e\u06c1\u0644\u06d2 \u0627\u0633\u06d2 \u06a9\u0627\u067e\u06cc \u06a9\u0631\u06cc\u06ba\u06d4 \u0622\u067e \u0688\u06cc\u0679\u0627 \u0633\u06cc\u0679\u0633 \u06a9\u06d2 \u0635\u0631\u0641 \u0646\u0626\u06d2 \u0648\u0631\u0698\u0646 \u0634\u0627\u0626\u0639 \u06a9\u0631 \u0633\u06a9\u062a\u06d2 \u06c1\u06cc\u06ba \u062c\u0648 \u0622\u067e \u06a9\u06d2 \u067e\u0627\u0633 \u06c1\u06cc\u06ba\u06d4 \u067e\u06be\u0631\u060c \u0646\u0648\u0679 \u0628\u06a9 \u0627\u0648\u0631 \u0688\u06cc\u0679\u0627\u0633\u06cc\u0679 \u062f\u0648\u0646\u0648\u06ba \u06a9\u0648 \u0641\u0648\u0631\u06a9 \u06a9\u0631\u06cc\u06ba\u06d4 <code>KaggleConfig<\/code> \u067e\u0627\u0631\u0679 \u0679\u0627\u0626\u0645 \u0646\u0648\u06a9\u0631\u06cc.<\/p>\n<\/li>\n<li>\n<p>\u0627\u06af\u0631 \u0622\u067e \u06a9\u0627\u0644 \u06a9\u0631\u0646\u0627 \u0686\u0627\u06c1\u062a\u06d2 \u06c1\u06cc\u06ba\u060c \u062a\u0648 \u0628\u0631\u0627\u06c1 \u06a9\u0631\u0645 Kaggle CLI \u06a9\u06d2 \u0633\u0627\u062a\u06be \u0627\u0646\u0633\u0679\u0627\u0644 \u0627\u0648\u0631 \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u06cc\u06ba\u06d4 <code>publish_to_kaggle()<\/code> Google Colab \u06cc\u0627 Kaggle Notebooks \u06a9\u06d2 \u0628\u0627\u06c1\u0631\u06d4<\/p>\n<\/li>\n<\/ol>\n<p>\u0628\u0627\u0642\u06cc \u0633\u0628 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u06c1\u06d2 <strong>\u06a9\u0648\u0626\u06cc \u062a\u0628\u062f\u06cc\u0644\u06cc \u0646\u06c1\u06cc\u06ba<\/strong>.<\/p>\n<h3 id=\"heading-post-run-validation\">\u067e\u06be\u0627\u0646\u0633\u06cc \u06a9\u06d2 \u0628\u0639\u062f \u062a\u0635\u062f\u06cc\u0642 \u06a9\u0631\u06cc\u06ba\u06d4<\/h3>\n<p><code>validate_and_analyze()<\/code>    \u06cc\u06c1 \u0644\u0648\u067e \u06a9\u0648 \u0628\u0646\u062f \u06a9\u0631 \u062f\u06cc\u062a\u0627 \u06c1\u06d2 \u0627\u0648\u0631 \u06cc\u06c1 \u0635\u0631\u0641 \u0627\u06cc\u06a9 \u0627\u0686\u06be\u06cc \u0686\u06cc\u0632 \u0633\u06d2 \u0632\u06cc\u0627\u062f\u06c1 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0686\u0644\u0646\u0627 \u062e\u0648\u0634 \u0622\u0626\u0646\u062f \u0633\u0645\u062c\u06be\u062f\u0627\u0631\u06cc \u06a9\u06cc \u062c\u0627\u0646\u0686 \u06c1\u06d2\u06d4 <em>~ \u0628\u0639\u062f<\/em> \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0645\u06a9\u0645\u0644 \u06c1\u0648 \u0686\u06a9\u06cc \u06c1\u06d2\u06d4 \u0622\u0624\u0679 \u067e\u0679 \u0627\u06cc\u06a9 \u0627\u0646\u0633\u0627\u0646\u06cc \u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0642\u0627\u0628\u0644 \u0631\u067e\u0648\u0631\u0679 \u06c1\u06d2 \u062c\u0633 \u0645\u06cc\u06ba \u0638\u0627\u06c1\u0631\u06cc \u0634\u06a9\u0644\u060c \u0688\u06cc\u0679\u0627 \u06a9\u06cc \u0642\u0633\u0645\u060c \u0635\u0641\u0631 \u0634\u0645\u0627\u0631\u060c \u0627\u0648\u0631 \u062e\u0644\u0627\u0635\u06c1 \u06a9\u06d2 \u0627\u0639\u062f\u0627\u062f \u0648 \u0634\u0645\u0627\u0631 \u0634\u0627\u0645\u0644 \u06c1\u06cc\u06ba\u06d4 <code>water_level_mm<\/code>\u0633\u06cc\u0644\u0627\u0628 \u06a9\u06cc \u0648\u0627\u0631\u0646\u0646\u06af \u0631\u06cc\u06a9\u0627\u0631\u0688\u0632 \u06a9\u06cc \u062a\u0639\u062f\u0627\u062f\u060c \u0639\u0627\u0631\u0636\u06cc \u06a9\u0648\u0631\u06cc\u062c \u0627\u0648\u0631 \u0641\u06cc \u0627\u0633\u0679\u06cc\u0634\u0646 \u0631\u06cc\u06a9\u0627\u0631\u0688\u0632 \u06a9\u06cc \u062a\u0639\u062f\u0627\u062f\u06d4<\/p>\n<p>\u0688\u06cc\u0679\u0627 \u062a\u0628\u062f\u06cc\u0644 \u0646\u06c1\u06cc\u06ba \u06c1\u0648\u062a\u0627 \u06c1\u06d2\u06d4 \u06cc\u06c1 \u0627\u0633 \u0644\u06cc\u06d2 \u0645\u0648\u062c\u0648\u062f \u06c1\u06d2 \u06a9\u06c1 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc\u060c \u06cc\u0627 \u06a9\u0648\u0626\u06cc \u0628\u06be\u06cc \u0645\u0627\u0646\u06cc\u0679\u0631\u0646\u06af \u0633\u0633\u0679\u0645\u060c \u0631\u0646 \u06a9\u06d2 \u0644\u0627\u06af \u0622\u0624\u0679 \u067e\u0679 \u06a9\u0648 \u067e\u0691\u06be \u06a9\u0631 \u0641\u0648\u0631\u0627\u064b \u062f\u06cc\u06a9\u06be \u0633\u06a9\u062a\u0627 \u06c1\u06d2 \u06a9\u06c1 \u0622\u06cc\u0627 \u0627\u0633 \u06c1\u0641\u062a\u06d2 \u06a9\u06d2 \u0646\u0645\u0628\u0631 \u0646\u0627\u0631\u0645\u0644 \u06c1\u06cc\u06ba\u06d4 \u0628\u0631\u0627\u06c1 \u0631\u0627\u0633\u062a CSV \u06a9\u0627 \u062a\u062c\u0632\u06cc\u06c1 \u06a9\u0631\u0646\u06d2 \u06a9\u06cc \u0636\u0631\u0648\u0631\u062a \u0646\u06c1\u06cc\u06ba \u06c1\u06d2\u06d4 \u0627\u0633\u06d2 \u0622\u0632\u0645\u0627\u0626\u06cc\u06ba!<\/p>\n<h2 id=\"heading-summary\">\u062e\u0644\u0627\u0635\u06c1<\/h2>\n<p>\u062a\u0645 \u0635\u0631\u0641 <em>\u0648\u0627\u0679\u0631 \u0679\u0627\u0626\u0679<\/em> \u0627\u06cc\u06a9 ETL \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u062c\u0648 \u06a9\u0633\u06cc \u0628\u06be\u06cc \u0686\u06cc\u0632 \u06a9\u0648 \u0631\u0648\u06a9\u06d2 \u0628\u063a\u06cc\u0631 \u0628\u0627\u0631 \u0628\u0627\u0631 \u0686\u0644 \u0633\u06a9\u062a\u06cc \u06c1\u06d2\u06d4 \u06a9\u0646\u06a9\u0627\u0644 \u06cc\u06c1\u0627\u06ba \u06c1\u06d2\u060c \u0627\u0648\u0631 \u062a\u0642\u0631\u06cc\u0628\u0627\u064b \u062a\u0645\u0627\u0645 \u0637\u06d2 \u0634\u062f\u06c1 \u0688\u06cc\u0679\u0627 \u0622\u067e\u0631\u06cc\u0634\u0646\u0632 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0627\u06cc\u06a9 \u06c1\u06cc \u067e\u06cc\u0679\u0631\u0646 \u06a9\u0648 \u062f\u06c1\u0631\u0627\u06cc\u0627 \u062c\u0627\u062a\u0627 \u06c1\u06d2\u06d4 \u0627\u0633 \u06a9\u0627 \u0645\u0637\u0644\u0628 \u06c1\u06d2 APIs\u060c \u0641\u06cc\u0644\u0688 \u0645\u06cc\u067e\u0646\u06af \u0627\u0648\u0631 \u0627\u06c1\u062f\u0627\u0641 \u06a9\u0648 \u062a\u0628\u062f\u06cc\u0644 \u06a9\u0631\u0646\u0627\u06d4<\/p>\n<p>\u0627\u0633 \u0637\u0631\u062d \u06a9\u06d2 \u0645\u0632\u06cc\u062f \u0633\u0628\u0642 \u06a9\u06d2 \u0644\u06cc\u06d2\u060c \u0645\u06cc\u0631\u06d2 GitHub \u06cc\u0627 Kaggle \u067e\u0631\u0648\u0641\u0627\u0626\u0644\u0632 \u06a9\u0648 \u062f\u06cc\u06a9\u06be\u06cc\u06ba\u06d4<\/p>\n<p>\u067e\u0691\u06be\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u0634\u06a9\u0631\u06cc\u06c1!<\/p>\n<h2 id=\"heading-references\">\u062d\u0648\u0627\u0644\u06c1 \u062c\u0627\u062a<\/h2>\n<\/p><\/div>\n","protected":false},"excerpt":{"rendered":"<p>\u0633\u06cc\u0644\u0627\u0628 \u06a9\u06d2 \u062e\u0637\u0631\u06d2 \u0633\u06d2 \u0628\u0627\u062e\u0628\u0631 \u0631\u06c1\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 \u06a9\u0686\u06be \u063a\u06cc\u0631 \u0648\u0627\u0636\u062d \u0644\u06cc\u06a9\u0646 \u0636\u0631\u0648\u0631\u06cc \u06c1\u06d2: \u0635\u0627\u0641\u060c \u0645\u0646\u0638\u0645 \u0688\u06cc\u0679\u0627\u06d4 \u0627\u0633 \u0679\u06cc\u0648\u0679\u0648\u0631\u06cc\u0644 \u0645\u06cc\u06ba\u060c \u0622\u067e \u0627\u067e\u0646\u0627 \u0688\u06cc\u0679\u0627 \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0628\u0646\u0627\u062a\u06d2 \u06c1\u06cc\u06ba\u06d4 \u0641\u0631\u0627\u0646\u0633 \u06a9\u06d2 \u0622\u0641\u06cc\u0634\u0644 \u0627\u0648\u067e\u0646 \u0648\u0627\u0679\u0631 \u0688\u06cc\u0679\u0627 API Hub&#8217;Eau \u0633\u06d2 \u0631\u0648\u0632\u0627\u0646\u06c1 \u067e\u0627\u0646\u06cc \u06a9\u06cc \u0633\u0637\u062d \u06a9\u06cc \u0631\u06cc\u0688\u0646\u06af \u062d\u0627\u0635\u0644 \u06a9\u0631\u0646\u06d2 \u06a9\u06d2 \u0644\u06cc\u06d2 Python ETL (\u0627\u06cc\u06a9\u0633\u0679\u0631\u06cc\u06a9\u0679\u060c \u0679\u0631\u0627\u0646\u0633\u0641\u0627\u0631\u0645\u060c \u0644\u0648\u0688) \u067e\u0627\u0626\u067e \u0644\u0627\u0626\u0646 \u0628\u0646\u0627\u0626\u06cc\u06ba\u06d4 \u067e\u06be\u0631 [&hellip;]<\/p>\n","protected":false},"author":7,"featured_media":27386,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"default","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","ast-disable-related-posts":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-opacity":"","overlay-gradient":""}},"footnotes":""},"categories":[1],"tags":[],"class_list":["post-27385","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-blog"],"_links":{"self":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/27385","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/users\/7"}],"replies":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/comments?post=27385"}],"version-history":[{"count":1,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/27385\/revisions"}],"predecessor-version":[{"id":27387,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/posts\/27385\/revisions\/27387"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/media\/27386"}],"wp:attachment":[{"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/media?parent=27385"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/categories?post=27385"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/umang.pk\/ur\/wp-json\/wp\/v2\/tags?post=27385"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}