Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
57 commits
Select commit Hold shift + click to select a range
746ae21
Calculer la longueur des montants abérrants à partir des entiers
ColinMaudry Nov 26, 2025
ddd456e
Ajout du champ durée restante en mois #135
ColinMaudry Nov 26, 2025
68de248
Tests unitaires pour clean.py (Gemini 3 pro) #148
ColinMaudry Nov 27, 2025
5f5bc3c
Déplacement de process_string_lists vers clean.py #148
ColinMaudry Nov 27, 2025
9a9f009
Amélioration des données de test #148
ColinMaudry Nov 27, 2025
dc82b6f
Docstring
ColinMaudry Nov 27, 2025
f90f525
Gestion des cas où tous les modification_titulaires sont null #148
ColinMaudry Nov 27, 2025
129e2b1
On ne teste pas les modifications ici #148
ColinMaudry Nov 27, 2025
14d058d
Amélioration de replace_with_modification_data #148
ColinMaudry Nov 27, 2025
2ee2ea8
Ménage dans test_transform.py et suppression de test_get.py #148
ColinMaudry Nov 27, 2025
e3e8ca6
Correction du datatype de donneesActuelles
ColinMaudry Nov 27, 2025
6a98e02
Simplification des données de test de transformation #148
ColinMaudry Nov 27, 2025
e262bbf
Ajout d'un simple test_enrich, suppression de test_sirene_preprocess.…
ColinMaudry Nov 27, 2025
20898b2
Plus de test_sirene_preprocess, udpate du README, plus de log
ColinMaudry Nov 27, 2025
be82e6b
Ménage dans transform.py sur les fonctions non-utilisées
ColinMaudry Nov 27, 2025
d9c625c
Merge branch 'feature/148_unit_tests' into dev
ColinMaudry Nov 27, 2025
80d8fd3
Execution des tests unitaires automatiques lors des push #148
ColinMaudry Nov 27, 2025
fcb61de
Ajout de colonnes "nom" supplémentaires dans les données SIRENE récup…
ColinMaudry Nov 27, 2025
4dbe785
Gestion des UL ND, intégration des prénom+nom avec gestion nom d'usag…
ColinMaudry Dec 1, 2025
dec72da
Amélioration de la prep des données établissements, avec enseigne et …
ColinMaudry Dec 1, 2025
7beef61
Refacto get_etablissements #145
ColinMaudry Dec 1, 2025
e7e5875
Augmentation du timeout pour le test harness
ColinMaudry Dec 1, 2025
5c15093
Refactor des tests d'enrichissement SIRENE #145
ColinMaudry Dec 2, 2025
2e06b61
Ajout de enseigne1/denominationUsuelle dans le nom d'acheteur/titulai…
ColinMaudry Dec 2, 2025
40f8010
Resilience if modifications is a string
ColinMaudry Dec 3, 2025
c1079bf
Ajout des données Xmarchés #151
ColinMaudry Dec 4, 2025
23f1b82
Réactivation du traitement en parallèle #113
ColinMaudry Dec 5, 2025
ea01b2d
Suppression du dataset MINEF consolidé #151
ColinMaudry Dec 5, 2025
46ad32c
Ajout des données PES (depuis 2024) #151
ColinMaudry Dec 5, 2025
b9d18ff
Ajout des données AWS legacy (avant 2023) #151
ColinMaudry Dec 5, 2025
cac8189
Ajout des données Dematis/e-marchespublics.com #151
ColinMaudry Dec 5, 2025
cca2b2e
Ajout des données PES marché avant 2024 #151
ColinMaudry Dec 5, 2025
6ecad0f
Correction des dates avec indication de fuseau horaire (PES marché)
ColinMaudry Dec 5, 2025
c24c380
Merge branch 'hotfix/2.5.1' into dev
ColinMaudry Dec 5, 2025
c6ac5c0
Application des modifications le plus tôt possible pour que les fonct…
ColinMaudry Dec 5, 2025
5b0463f
Tentative de stream to parquet avant de concat (et profilage mémoire)
ColinMaudry Dec 5, 2025
b9c7848
Ça stream presque tout mais nafcpv a besoin de collect...
ColinMaudry Dec 5, 2025
33215ab
Tentatives d'optimisation de la mémoire
ColinMaudry Dec 5, 2025
0c3a8ef
Refonte de generate_stats() en Lazy #153
ColinMaudry Dec 6, 2025
8cdb15a
Avancer sinle premier k_to_files() plus près de enrich_from_sirene() …
ColinMaudry Dec 6, 2025
588687f
Matérialisation de lfs dans enrich_from_sirene() pour réduire la comp…
ColinMaudry Dec 6, 2025
be95e1e
Traiter les futures et la concaténation des parquets pour réduire la …
ColinMaudry Dec 7, 2025
53c1baa
Meilleurs commentaires
ColinMaudry Dec 7, 2025
d982d81
Utilisation d'un système de cache custom
ColinMaudry Dec 8, 2025
ffaf053
Pour ne pas publier un petit dataset par erreur
ColinMaudry Dec 8, 2025
b49f80d
cleanup > removal
ColinMaudry Dec 8, 2025
044118b
Changelog 2.6.0
ColinMaudry Dec 8, 2025
b56b014
System cystom de cache parquet et vérification des fichiers avant con…
ColinMaudry Dec 9, 2025
abfded6
Merge branch 'feature/145_siret_empty_names' into dev
ColinMaudry Dec 9, 2025
a6837c8
Envoi d'email en cas d'échec (tentative) #150
ColinMaudry Dec 10, 2025
ed226cd
Bugs de typage avec raw_mods, plus de timeout dans get_etablissements
ColinMaudry Dec 10, 2025
4e618d3
Bon enchaînment ul/etab dans enrich
ColinMaudry Dec 10, 2025
45d8198
Coquille
ColinMaudry Dec 10, 2025
32c3ccf
polars 1.36.1 fait bugger, peut-être à cause de polars-ds
ColinMaudry Dec 12, 2025
be0de28
Changelog 2.6.0
ColinMaudry Dec 12, 2025
47d8907
Suppression de memory profiler
ColinMaudry Dec 12, 2025
1dccb7f
get dir dans DATA_DIR
ColinMaudry Dec 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Tests et couverture

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.10'
- name: Install dependencies
run: |
pip install -e .[dev]
- name: Run tests with coverage
run: pytest --cov=src --cov-report=term
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ logs
.venv
*.egg-info
*.parquet
!tests/data/sirene/*.parquet
!code_officiel_geographique.parquet
*.gz
*.zip
Expand Down
19 changes: 18 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,23 @@
### 2.6.0 2025-12-12

- Abandon des données consolidées par le MINEF, récupération des données à la source ([#151](https://github.com/ColinMaudry/decp-processing/issues/151))
- Xmarchés
- AWS (officiel et legacy)
- PES marché (avant et après 2024)
- Dematis / e-marchespublics
- Ajout du champ `dureeRestanteMois` ([#135](https://github.com/ColinMaudry/decp-processing/issues/135))
- Amélioration des noms des titulaires (personnes physiques et non-diffusibles) ([#145](https://github.com/ColinMaudry/decp-processing/issues/145))
- Ajout de nombreux tests unitaires
- Amélioration de la gestion des modifications ([#148](https://github.com/ColinMaudry/decp-processing/issues/148))
- Traitement des ressources en parallèle ([#113](https://github.com/ColinMaudry/decp-processing/issues/113))
- Optimisation de la consommation de mémoire (matérialisation en parquet) ([#153](https://github.com/ColinMaudry/decp-processing/issues/153))
- Résilience contre les erreurs pendant get_clean (seule la ressource échoue, pas tout le process)
- Mise en place d'un système de cache custom (parquet)
- Protection contre la publication par erreur sur data.gouv.fr ([ffaf0535](https://github.com/ColinMaudry/decp-processing/commit/ffaf0535))
- Utilisation de polars 1.35.2 plutôt que 1.36.1 qui semble ne pas marcher avec polars-ds

### 2.5.0 2025-11-21

- Ajout de la durée restante dans le marché en mois ([#35](https://github.com/ColinMaudry/decp-processing/issues/135))
- Amélioration de la conso mémoire de la correction des titulaires ([#146](https://github.com/ColinMaudry/decp-processing/issues/146))
- Vérfication de la structude des données scrapées (AWS)
- Gestion propre des erreurs 429 Too Many Redirects ([6fbd71e0](https://github.com/ColinMaudry/decp-processing/commit/6fbd71e0bca0534ee360dc172f3565607dac5bef))
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# DECP processing

> version 2.5.0 ([notes de version](https://github.com/ColinMaudry/decp-processing/blob/main/CHANGELOG.md))
> version 2.6.0 ([notes de version](https://github.com/ColinMaudry/decp-processing/blob/main/CHANGELOG.md))

Projet de traitement et de publication de meilleures données sur les marchés publics attribués en France. Vous pouvez consulter, filtrer et télécharger
ces données sur le site [decp.info](https://decp.info). Enfin la section [À propos](https://decp.info/a-propos) décrit les objectifs du projet et regroupe toutes les informations clés.
Expand Down Expand Up @@ -59,7 +59,7 @@ source .venv/bin/activate
Installez les dépendances :

```bash
pip install .
pip install -e .
```

Pour les contributeurices, installez les dépendances de développement et l'auto-formatage au moment des commits :
Expand Down Expand Up @@ -110,7 +110,7 @@ Déploiement des flows (exécution programmée de main ou ponctuelle de dev) :
Le pré-traitement des données SIRENE doit être fait une fois pour que le traitement principal soit fonctionnel.

```bash
pytest tests/test_sirene_preprocess.py
python run_flow.py sirene_preprocess
```

Lancement du traitement principal (data_tables + decp.info) via un serveur prefect à usage unique
Expand Down
42 changes: 36 additions & 6 deletions data/source_datasets.json
Original file line number Diff line number Diff line change
Expand Up @@ -239,12 +239,6 @@
"owner_org_name": "ATEXO - DECP",
"code": "atexo_mp_596280"
},
{
"id": "5cd57bf68b4c4179299eb0e9",
"name": "Données essentielles de la commande publique - fichiers consolidés",
"owner_org_name": "Ministère de l'économie, des Finances et de l'Industrie",
"code": "decp_minef"
},
{
"id": "65f18014e9923e9e71f5f258",
"name": "Données essentielles du profil acheteur Mégalis Bretagne - schéma arrêtés 2022",
Expand Down Expand Up @@ -275,10 +269,46 @@
"code": "aws_marches-publics.info",
"owner_org_name": "AWSolutions"
},
{
"id": "5cdb1722634f41416ffe90e2",
"name": "Données de marches-publics.info (AWS) - legacy",
"code": "aws_marches-publics.info_legacy",
"owner_org_name": "MINEF"
},
{
"id": "68caf6b135f19236a4f37a32",
"name": "Données de marches-publics.info (AWS) - scraping",
"code": "scrap_marches-publics.info",
"owner_org_name": "Colin Maudry"
},
{
"id": "651eb149add2f419788c36ef",
"name": "Données essentielles des marchés publics - Xmarchés",
"code": "xmarches",
"owner_org_name": "SPL-XDEMAT"
},
{
"id": "65cf3c55ec910b5a8e2fc084",
"name": "Données essentielles PES marché depuis 2024",
"code": "pes_marche_2024",
"owner_org_name": "MINEF"
},
{
"id": "6932eab9f5ef60c27eba22ff",
"name": "Données essentielles PES marché avant 2024 (legacy)",
"code": "pes_marche_legacy",
"owner_org_name": "Colin Maudry"
},
{
"id": "5c0a7845634f4139b2ee8883",
"name": "Données essentielles des marchés publics - e-marchespublics.com",
"code": "e-marchespublics.com_dematis",
"owner_org_name": "Dematis"
},
{
"id": "6780e55f813a85efbd2c6557",
"name": "Les Personnes placées sous main de justice - IDF 2024",
"code": "ppsmj",
"owner_org_name": "Yael Siksik"
}
]
9 changes: 6 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ authors = [
dependencies = [
"python-dotenv",
"pandas", # nécessaire pour l'écriture en base de données
"polars==1.33.1",
"polars==1.35.2",
"pyarrow",
"frictionless",
"ipykernel",
"prefect==3.4.17",
"prefect==3.6.6",
"prefect[email]==3.6.6",
"orjson",
"ijson==3.4.0",
"lxml",
Expand All @@ -29,6 +30,7 @@ dev = [
"pre-commit",
"pytest-env",
"pytest",
"pytest-cov"
]

[tool.pytest.ini_options]
Expand All @@ -40,9 +42,10 @@ testpaths = [
]
env = [
"DATASETS_REFERENCE_FILEPATH=tests/data/source_datasets_test.json",
"SIRENE_DATA_DIR=tests/data/sirene",
"PREFECT_API_URL=",
"DECP_PROCESSING_PUBLISH=",
"PREFECT_TASKS_REFRESH_CACHE=true"
"DECP_USE_CACHE=false"
]
addopts = "-p no:warnings"

Expand Down
24 changes: 17 additions & 7 deletions src/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@
from dotenv import find_dotenv, load_dotenv
from ijson import sendable_list

from src.schemas import SCHEMA_MARCHE_2019, SCHEMA_MARCHE_2022

dotenv_path = find_dotenv()
if dotenv_path == "":
print("Création du fichier .env à partir de template.env")
Expand Down Expand Up @@ -71,6 +69,9 @@ def make_path_from_env(env: str, alternative_path: Path) -> Path:
# Clé d'API data.gouv.fr
DATAGOUVFR_API_KEY = os.getenv("DATAGOUVFR_API_KEY", "")

# URL API Prefect
PREFECT_API_URL = os.getenv("PREFECT_API_URL")

# Dossier racine
BASE_DIR = make_path_from_env("DECP_BASE_DIR", Path(__file__).absolute().parent.parent)
print(f"{'BASE_DIR':<40}", BASE_DIR)
Expand All @@ -80,6 +81,9 @@ def make_path_from_env(env: str, alternative_path: Path) -> Path:
DATA_DIR.mkdir(exist_ok=True, parents=True)
print(f"{'DATA_DIR':<40}", DATA_DIR)

RESOURCE_CACHE_DIR = DATA_DIR / "resource_cache"
RESOURCE_CACHE_DIR.mkdir(exist_ok=True, parents=True)

DIST_DIR = make_path_from_env("DECP_DIST_DIR", BASE_DIR / "dist")
DIST_DIR.mkdir(exist_ok=True, parents=True, mode=777)
print(f"{'DIST_DIR':<40}", DIST_DIR)
Expand All @@ -97,7 +101,15 @@ def make_sirene_data_dir(sirene_data_parent_dir) -> Path:


SIRENE_DATA_PARENT_DIR = make_path_from_env("SIRENE_DATA_PARENT_DIR", DATA_DIR)
SIRENE_DATA_DIR = make_sirene_data_dir(SIRENE_DATA_PARENT_DIR)

# SIRENE_DATA_DIR ne doit être spécifié que pour les tests. Laisser vide dans .env et laisser make_sirene_data_dir
# le déterminer
SIRENE_DATA_DIR = os.getenv(
"SIRENE_DATA_DIR", make_sirene_data_dir(SIRENE_DATA_PARENT_DIR)
)
if isinstance(SIRENE_DATA_DIR, str):
SIRENE_DATA_DIR = Path(os.path.join(BASE_DIR, SIRENE_DATA_DIR))

# SIRENE_DATA_DIR on ne le crée que si nécessaire, dans flows.py
print(f"{'SIRENE_DATA_PARENT_DIR':<40}", SIRENE_DATA_PARENT_DIR)
print(f"{'SIRENE_DATA_DIR':<40}", SIRENE_DATA_DIR)
Expand All @@ -113,6 +125,8 @@ def make_sirene_data_dir(sirene_data_parent_dir) -> Path:
SCRAPING_TARGET = os.getenv("SCRAPING_TARGET")
print(f"{'SCRAPING_TARGET':<40}", SCRAPING_TARGET)

# Lecture ou non des ressource en cache
DECP_USE_CACHE = os.getenv("DECP_USE_CACHE", "false").lower() == "true"

# Dossier de stockage des résultats de tâches et du cache
# https://docs.prefect.io/v3/advanced/results#default-persistence-configuration
Expand Down Expand Up @@ -204,8 +218,4 @@ class DecpFormat:
coroutine_ijson: Coroutine | None = None


DECP_FORMAT_2019 = DecpFormat("DECP 2019", SCHEMA_MARCHE_2019, "marches")
DECP_FORMAT_2022 = DecpFormat("DECP 2022", SCHEMA_MARCHE_2022, "marches.marche")
DECP_FORMATS = [DECP_FORMAT_2019, DECP_FORMAT_2022]

print("")
Loading