From 6798d355722cf0520888ee08aa648c2bc3941e35 Mon Sep 17 00:00:00 2001 From: Meryemel-gham Date: Thu, 17 Sep 2026 10:41:18 +0200 Subject: [PATCH] fix(data): corrige le typage de l'import historique --- apps/backend/app/etl/historical_import.py | 21 ++++++++++++++++----- apps/backend/pyproject.toml | 1 + apps/backend/uv.lock | 14 ++++++++++++++ 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/apps/backend/app/etl/historical_import.py b/apps/backend/app/etl/historical_import.py index b4f2089..22d9b03 100644 --- a/apps/backend/app/etl/historical_import.py +++ b/apps/backend/app/etl/historical_import.py @@ -5,7 +5,7 @@ import asyncio import hashlib import json from pathlib import Path -from typing import Any +from typing import Any, cast import pandas as pd from sqlalchemy import text @@ -56,7 +56,12 @@ def compute_sha256(path: Path) -> str: def load_metadata(path: Path) -> dict[str, Any]: """Charge les métadonnées fournies avec le dataset.""" with path.open("r", encoding="utf-8") as source: - return json.load(source) + metadata = json.load(source) + + if not isinstance(metadata, dict): + raise ValueError("Le fichier de métadonnées doit contenir un objet JSON.") + + return cast(dict[str, Any], metadata) def classify_quality( @@ -260,7 +265,8 @@ async def upsert_sites( frame: pd.DataFrame, ) -> None: """Insère ou met à jour les sites du dataset.""" - sites = ( + sites = cast( + list[dict[str, Any]], frame[ [ "site_id", @@ -269,7 +275,7 @@ async def upsert_sites( ] ] .drop_duplicates(subset=["site_id"]) - .to_dict(orient="records") + .to_dict(orient="records"), ) await connection.execute( @@ -305,7 +311,12 @@ def build_reading_batch( """ rows: list[dict[str, Any]] = [] - for record in chunk.to_dict(orient="records"): + records = cast( + list[dict[str, Any]], + chunk.to_dict(orient="records"), + ) + + for record in records: quality, reasons = classify_quality(record) raw_data = { diff --git a/apps/backend/pyproject.toml b/apps/backend/pyproject.toml index 6cf42a5..c330c8d 100644 --- a/apps/backend/pyproject.toml +++ b/apps/backend/pyproject.toml @@ -27,6 +27,7 @@ dev = [ "pytest-asyncio>=1.4.0", "pytest-cov>=7.1.0", "httpx>=0.28.1", + "pandas-stubs>=3.0.5.260914", ] [build-system] diff --git a/apps/backend/uv.lock b/apps/backend/uv.lock index fb43797..6836990 100644 --- a/apps/backend/uv.lock +++ b/apps/backend/uv.lock @@ -330,6 +330,7 @@ dependencies = [ dev = [ { name = "httpx" }, { name = "mypy" }, + { name = "pandas-stubs" }, { name = "pytest" }, { name = "pytest-asyncio" }, { name = "pytest-cov" }, @@ -357,6 +358,7 @@ requires-dist = [ dev = [ { name = "httpx", specifier = ">=0.28.1" }, { name = "mypy", specifier = ">=2.3.1" }, + { name = "pandas-stubs", specifier = ">=3.0.5.260914" }, { name = "pytest", specifier = ">=9.1.1" }, { name = "pytest-asyncio", specifier = ">=1.4.0" }, { name = "pytest-cov", specifier = ">=7.1.0" }, @@ -669,6 +671,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d2/cf/6a51b2c38980e04c279fd2fa908a1b0982064e860444acfca4ec2e2c8359/pandas-3.0.5-cp314-cp314t-win_arm64.whl", hash = "sha256:3c5015fd1730fbf883647e88068176c839c102cea883ba1769a6f4593bfc1f8c", size = 9509776, upload-time = "2026-07-22T22:19:26.694Z" }, ] +[[package]] +name = "pandas-stubs" +version = "3.0.5.260914" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c1/93/8948ae6c1e1e3d6833596fd266f7be2d27c1451b8be094975ad42c5e842e/pandas_stubs-3.0.5.260914.tar.gz", hash = "sha256:3f6fc1f147f68fd89c007105e7c94a948acb4ecd7eb20dc1c02e153c4ed5c250", size = 117622, upload-time = "2026-09-14T16:42:35.065Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/cb/5ad79e02a556cc23fed5816de0109fa8af660c66cfa5f4af74c3e8d4cd26/pandas_stubs-3.0.5.260914-py3-none-any.whl", hash = "sha256:39a1300c5c5c55fdf609e3476805decce5d5015539a4dcb683449f8feaeee2fb", size = 177344, upload-time = "2026-09-14T16:42:33.771Z" }, +] + [[package]] name = "pathspec" version = "1.1.1"