Skip to content
Merged

MEP v12 #1444

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
5acd621
feat: Ajoute un paramètre utilisateur optionnel aux constructeurs des…
alexisig Jan 26, 2026
c3f1063
Merge pull request #1420 from MTES-MCT/fix-artif
alexisig Jan 26, 2026
9fabd3d
fix: Supprime les références à l'année 2023 dans le rapport local
alexisig Jan 27, 2026
813f901
Merge pull request #1423 from MTES-MCT/fix-annee-rapport-local
alexisig Jan 27, 2026
10bfc71
fix: Utilise COALESCE pour l'email utilisateur et modifie le type de …
alexisig Jan 27, 2026
c1391c5
Merge pull request #1425 from MTES-MCT/fix-suv-brevo-fallback
alexisig Jan 27, 2026
1b6f5e4
fix: Met à jour la planification du DAG pour s'exécuter à 4h00 chaque…
alexisig Jan 27, 2026
219a6f3
fix: Utilise COALESCE pour l'email utilisateur et modifie le type de …
alexisig Jan 27, 2026
fb7c0b1
Add new models and SQL queries for exporting imper and artif data by …
alexisig Jan 21, 2026
6303f05
Refactor SQL models for export: Update commune, departement, epci, re…
alexisig Jan 22, 2026
cfdafb8
Refactor SQL models for export of imper and artif data by usage and c…
alexisig Jan 22, 2026
174b928
Ajout d'un DAG pour supprimer tous les datasets de data.gouv.fr et mi…
alexisig Jan 26, 2026
a8e27f7
Mise à jour des tests pour utiliser get_dataset_configs et vérificati…
alexisig Jan 27, 2026
c9e778b
Merge branch 'staging' into hotfix-merge
alexisig Jan 27, 2026
675a68b
Merge pull request #1431 from MTES-MCT/hotfix-merge
alexisig Jan 27, 2026
0e8c9ff
Merge pull request #1417 from MTES-MCT/feat-data-gouv
alexisig Jan 28, 2026
1ee58ea
Ajout de la journalisation pour la création et la mise à jour des dat…
alexisig Jan 29, 2026
644034f
Merge pull request #1436 from MTES-MCT/fix-data-gouv
alexisig Jan 29, 2026
b3ec960
Modification de la structure du payload dans la méthode create_datase…
alexisig Jan 29, 2026
092dfe8
Merge pull request #1437 from MTES-MCT/fix-data-gouv
alexisig Jan 29, 2026
7ddb714
Ajout de la journalisation des réponses lors de la création et de la …
alexisig Jan 29, 2026
2e5ec87
Suppression des colonnes target_2031 et target_2031_modified dans le …
alexisig Jan 29, 2026
74dce52
Refactor urbanisme charts and add LogementVacantMap
alexisig Feb 4, 2026
d67a900
feat: Add LogementVacantTaux component and related chart for vacancy …
alexisig Feb 6, 2026
bde6a14
f
alexisig Feb 6, 2026
4191ebd
Refactor LogementVacant components for improved data handling and dis…
alexisig Feb 9, 2026
c3f002c
Refactor tests for LogementVacant charts: rename and update initializ…
alexisig Feb 9, 2026
c2a41e2
fix: Update formatNumber tests to return - for undefined, null, and N…
alexisig Feb 9, 2026
80f5f39
Merge pull request #1439 from MTES-MCT/feat-lovac-2025
alexisig Feb 9, 2026
eb88a4f
fix: Update ratio handling and improve interpretation messages in Log…
alexisig Feb 9, 2026
8263f55
feat: Add Carroyage Lea layer and map integration
alexisig Jan 28, 2026
4939230
feat: Update CarroyageLeaMap and Consommation components for improved…
alexisig Feb 10, 2026
83875dc
feat: Ajouter une description pour le carroyage de la consommation d'…
alexisig Feb 10, 2026
8fb8976
feat: Ajouter la vue CarroyageDestinationConfig et intégrer la config…
alexisig Feb 10, 2026
093623e
Merge pull request #1434 from MTES-MCT/feat-carroyage
alexisig Feb 10, 2026
745437a
f
alexisig Feb 12, 2026
5d939f9
Merge pull request #1442 from MTES-MCT/feat-land-single-view
alexisig Feb 12, 2026
4249ef0
f
alexisig Feb 12, 2026
4cb80ca
Merge pull request #1443 from MTES-MCT/feat-land-single-view
alexisig Feb 12, 2026
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
4 changes: 2 additions & 2 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ docxtpl = "*"
geopandas = "*"
gunicorn = "*"
jenkspy = "*"
josepy = "==1.15.0"
josepy = "*"
mapclassify = "*"
matplotlib = "*"
matplotlib-scalebar = "*"
Expand All @@ -74,4 +74,4 @@ django-webpack-loader = "*"
django-two-factor-auth = "*"
qrcode = "*"
phonenumbers = "*"
mozilla-django-oidc = "*"
mozilla-django-oidc = "5.0.2"
2,519 changes: 1,275 additions & 1,244 deletions Pipfile.lock

Large diffs are not rendered by default.

46 changes: 34 additions & 12 deletions airflow/dags/data_gouv/Config.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,39 +2,61 @@


@dataclass(frozen=True, kw_only=True)
class BaseConfig:
frequency: str = "@once"
dag_id: str
class ResourceConfig:
format: str
filename: str
data_gouv_dataset: str
data_gouv_resource: str
resource_slug: str
resource_title: str


@dataclass(frozen=True, kw_only=True)
class GeopackageConfig(BaseConfig):
class GeopackageResourceConfig(ResourceConfig):
sql_to_layer_name_mapping: dict


@dataclass(frozen=True, kw_only=True)
class CSVConfig(BaseConfig):
class CSVResourceConfig(ResourceConfig):
sql: str


@dataclass(frozen=True, kw_only=True)
class DatasetConfig:
dataset_slug: str
dataset_title: str
frequency: str = "@once"
resources: tuple[ResourceConfig, ...] = ()


class ConfigParser:
def __get_config_class(self, format: str):
def __get_resource_config_class(self, format: str):
parser_map = {
"csv": CSVConfig,
"gpkg": GeopackageConfig,
"csv": CSVResourceConfig,
"gpkg": GeopackageResourceConfig,
}

if format not in parser_map:
raise ValueError(f"Le format {format} n'est pas pris en charge")

return parser_map[format]

def parse_config(self, data: dict):
def parse_resource(self, data: dict) -> ResourceConfig:
if "format" not in data:
raise ValueError("Le format est manquant dans la configuration", data)

return self.__get_config_class(data["format"])(**data)
return self.__get_resource_config_class(data["format"])(**data)

def parse_config(self, data: dict) -> DatasetConfig:
if "dataset_title" not in data:
raise ValueError("Le dataset_title est manquant dans la configuration", data)

if "dataset_slug" not in data:
raise ValueError("Le dataset_slug est manquant dans la configuration", data)

resources = tuple(self.parse_resource(resource_data) for resource_data in data.get("resources", []))

return DatasetConfig(
dataset_slug=data["dataset_slug"],
dataset_title=data["dataset_title"],
frequency=data.get("frequency", "@once"),
resources=resources,
)
5 changes: 2 additions & 3 deletions airflow/dags/data_gouv/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
from .csv_exports import * # noqa: F403, F401
from .geopackage_exports import * # noqa: F403, F401
from .utils import get_configs # noqa: F403, F401
from .export_all_to_data_gouv import * # noqa: F403, F401
from .utils import get_dataset_configs # noqa: F403, F401
42 changes: 42 additions & 0 deletions airflow/dags/data_gouv/archive_all_from_data_gouv.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
"""
DAG pour supprimer tous les datasets de data.gouv.fr.

Ce DAG récupère tous les datasets de l'organisation sur data.gouv.fr
et les supprime.
"""

import pendulum
from include.container import DomainContainer as Container

from airflow.decorators import dag, task


@dag(
dag_id="archive_all_from_data_gouv",
start_date=pendulum.datetime(2024, 1, 1),
schedule="@once",
catchup=False,
doc_md=__doc__,
max_active_runs=1,
default_args={"owner": "Alexis Athlani", "retries": 3},
max_active_tasks=10,
tags=["data_gouv", "archive"],
)
def archive_all_from_data_gouv():
@task.python
def get_all_dataset_ids() -> list[str]:
"""Récupère tous les IDs de datasets depuis data.gouv.fr."""
datasets = Container().data_gouv().get_organization_datasets()
return [ds["id"] for ds in datasets]

@task.python
def delete_dataset(dataset_id: str) -> str:
"""Supprime un dataset de data.gouv.fr."""
Container().data_gouv().delete_dataset(dataset_id)
return dataset_id

dataset_ids = get_all_dataset_ids()
delete_dataset.expand(dataset_id=dataset_ids)


archive_all_from_data_gouv()
259 changes: 206 additions & 53 deletions airflow/dags/data_gouv/configs.py
Original file line number Diff line number Diff line change
@@ -1,53 +1,206 @@
from os import getenv

if getenv("ENVIRONMENT") == "production":
configs = [
{
"dag_id": "create_and_publish_france_impermeabilisation_communes_geopackage",
"format": "gpkg",
"filename": "france_impermeabilisation_communes.gpkg",
"sql_to_layer_name_mapping": {
"impermeabilisation": "SELECT * FROM public_for_export.commune_imper_by_year"
},
"data_gouv_dataset": "67bddc715e3badfc49d5df9b",
"data_gouv_resource": "b0bbf493-a078-46eb-b901-7d0754bf6e77",
},
{
"dag_id": "create_and_publish_france_impermeabilisation_communes_csv",
"format": "csv",
"filename": "france_impermeabilisation_communes.csv",
"sql": "SELECT * FROM public_for_export.commune_imper_by_year",
"data_gouv_dataset": "67bddc715e3badfc49d5df9b",
"data_gouv_resource": "800c36e1-8c12-46af-b495-4689edc40c3b",
},
{
"dag_id": "create_and_publish_france_artificialisation_communes_geopackage",
"format": "gpkg",
"filename": "france_artificialisation_communes.gpkg",
"sql_to_layer_name_mapping": {
"impermeabilisation": "SELECT * FROM public_for_export.commune_artif_by_year"
},
"data_gouv_dataset": "67daf7413e4c8cbd0ff2da24",
"data_gouv_resource": "7bf29725-6cdc-4f68-a10f-b9a99bf6365e",
},
{
"dag_id": "create_and_publish_part_territoire_francais_couvert_par_ocsge_csv",
"format": "csv",
"filename": "part_territoire_francais_couvert_par_ocsge.csv",
"sql": "SELECT * FROM public_for_export.ocsge_surface_cover_percent",
"data_gouv_dataset": "68348c9afa867945df5968e5",
"data_gouv_resource": "3a37cc78-4aa7-4a8e-814f-4e3714eb9a90",
"frequency": "@weekly",
},
{
"dag_id": "create_and_publish_trajectoires_communes_csv",
"format": "csv",
"filename": "trajectoires_communes.csv",
"sql": "SELECT * FROM public_for_export.trajectoires_communes",
"data_gouv_dataset": "688a1dcd9eaa8e9b2bd6bfc6",
"data_gouv_resource": "e4fa6a1d-48f1-44dd-bde9-b3c7814487bd",
"frequency": "@once",
},
]
else:
configs = []
configs = [
{
"dataset_slug": "ocsge-coverage-2026",
"dataset_title": "Part du territoire Francais couvert par OCS GE",
"frequency": "@weekly",
"resources": [
{
"format": "csv",
"filename": "part_territoire_francais_couvert_par_ocsge.csv",
"sql": "SELECT * FROM public_for_export.ocsge_surface_cover_percent",
"resource_slug": "ocsge-coverage-csv-2026",
"resource_title": "part_territoire_francais_couvert_par_ocsge.csv",
},
],
},
{
"dataset_slug": "trajectoires-zan-2031-2026",
"dataset_title": "Etat des lieux national de la trajectoire de consommation d'espaces NAF (naturels, agricoles et forestiers) à horizon 2031", # noqa: E501
"frequency": "@once",
"resources": [
{
"format": "csv",
"filename": "trajectoires_communes.csv",
"sql": "SELECT * FROM public_for_export.trajectoires_communes",
"resource_slug": "trajectoires-communes-csv-2026",
"resource_title": "trajectoires_communes.csv",
},
],
},
# === ARTIFICIALISATION ===
{
"dataset_slug": "artificialisation-collectivites-2026",
"dataset_title": "Artificialisation des collectivites de France",
"resources": [
# Commune
{
"format": "csv",
"filename": "artif_commune.csv",
"sql": "SELECT * FROM public_for_export.for_export_artif_commune",
"resource_slug": "artif-commune-csv-2026",
"resource_title": "Artificialisation par commune (CSV)",
},
{
"format": "gpkg",
"filename": "artif_commune.gpkg",
"sql_to_layer_name_mapping": {
"artif_commune": "SELECT * FROM public_for_export.for_export_artif_commune"
},
"resource_slug": "artif-commune-gpkg-2026",
"resource_title": "Artificialisation par commune (GeoPackage)",
},
# EPCI
{
"format": "csv",
"filename": "artif_epci.csv",
"sql": "SELECT * FROM public_for_export.for_export_artif_epci",
"resource_slug": "artif-epci-csv-2026",
"resource_title": "Artificialisation par EPCI (CSV)",
},
{
"format": "gpkg",
"filename": "artif_epci.gpkg",
"sql_to_layer_name_mapping": {"artif_epci": "SELECT * FROM public_for_export.for_export_artif_epci"},
"resource_slug": "artif-epci-gpkg-2026",
"resource_title": "Artificialisation par EPCI (GeoPackage)",
},
# SCOT
{
"format": "csv",
"filename": "artif_scot.csv",
"sql": "SELECT * FROM public_for_export.for_export_artif_scot",
"resource_slug": "artif-scot-csv-2026",
"resource_title": "Artificialisation par SCOT (CSV)",
},
{
"format": "gpkg",
"filename": "artif_scot.gpkg",
"sql_to_layer_name_mapping": {"artif_scot": "SELECT * FROM public_for_export.for_export_artif_scot"},
"resource_slug": "artif-scot-gpkg-2026",
"resource_title": "Artificialisation par SCOT (GeoPackage)",
},
# Departement
{
"format": "csv",
"filename": "artif_departement.csv",
"sql": "SELECT * FROM public_for_export.for_export_artif_departement",
"resource_slug": "artif-departement-csv-2026",
"resource_title": "Artificialisation par departement (CSV)",
},
{
"format": "gpkg",
"filename": "artif_departement.gpkg",
"sql_to_layer_name_mapping": {
"artif_departement": "SELECT * FROM public_for_export.for_export_artif_departement"
},
"resource_slug": "artif-departement-gpkg-2026",
"resource_title": "Artificialisation par departement (GeoPackage)",
},
# Region
{
"format": "csv",
"filename": "artif_region.csv",
"sql": "SELECT * FROM public_for_export.for_export_artif_region",
"resource_slug": "artif-region-csv-2026",
"resource_title": "Artificialisation par region (CSV)",
},
{
"format": "gpkg",
"filename": "artif_region.gpkg",
"sql_to_layer_name_mapping": {
"artif_region": "SELECT * FROM public_for_export.for_export_artif_region"
},
"resource_slug": "artif-region-gpkg-2026",
"resource_title": "Artificialisation par region (GeoPackage)",
},
],
},
# === IMPERMEABILISATION ===
{
"dataset_slug": "impermeabilisation-collectivites-2026",
"dataset_title": "Impermeabilisation des collectivites de France",
"resources": [
# Commune
{
"format": "csv",
"filename": "imper_commune.csv",
"sql": "SELECT * FROM public_for_export.for_export_imper_commune",
"resource_slug": "imper-commune-csv-2026",
"resource_title": "Impermeabilisation par commune (CSV)",
},
{
"format": "gpkg",
"filename": "imper_commune.gpkg",
"sql_to_layer_name_mapping": {
"imper_commune": "SELECT * FROM public_for_export.for_export_imper_commune"
},
"resource_slug": "imper-commune-gpkg-2026",
"resource_title": "Impermeabilisation par commune (GeoPackage)",
},
# EPCI
{
"format": "csv",
"filename": "imper_epci.csv",
"sql": "SELECT * FROM public_for_export.for_export_imper_epci",
"resource_slug": "imper-epci-csv-2026",
"resource_title": "Impermeabilisation par EPCI (CSV)",
},
{
"format": "gpkg",
"filename": "imper_epci.gpkg",
"sql_to_layer_name_mapping": {"imper_epci": "SELECT * FROM public_for_export.for_export_imper_epci"},
"resource_slug": "imper-epci-gpkg-2026",
"resource_title": "Impermeabilisation par EPCI (GeoPackage)",
},
# SCOT
{
"format": "csv",
"filename": "imper_scot.csv",
"sql": "SELECT * FROM public_for_export.for_export_imper_scot",
"resource_slug": "imper-scot-csv-2026",
"resource_title": "Impermeabilisation par SCOT (CSV)",
},
{
"format": "gpkg",
"filename": "imper_scot.gpkg",
"sql_to_layer_name_mapping": {"imper_scot": "SELECT * FROM public_for_export.for_export_imper_scot"},
"resource_slug": "imper-scot-gpkg-2026",
"resource_title": "Impermeabilisation par SCOT (GeoPackage)",
},
# Departement
{
"format": "csv",
"filename": "imper_departement.csv",
"sql": "SELECT * FROM public_for_export.for_export_imper_departement",
"resource_slug": "imper-departement-csv-2026",
"resource_title": "Impermeabilisation par departement (CSV)",
},
{
"format": "gpkg",
"filename": "imper_departement.gpkg",
"sql_to_layer_name_mapping": {
"imper_departement": "SELECT * FROM public_for_export.for_export_imper_departement"
},
"resource_slug": "imper-departement-gpkg-2026",
"resource_title": "Impermeabilisation par departement (GeoPackage)",
},
# Region
{
"format": "csv",
"filename": "imper_region.csv",
"sql": "SELECT * FROM public_for_export.for_export_imper_region",
"resource_slug": "imper-region-csv-2026",
"resource_title": "Impermeabilisation par region (CSV)",
},
{
"format": "gpkg",
"filename": "imper_region.gpkg",
"sql_to_layer_name_mapping": {
"imper_region": "SELECT * FROM public_for_export.for_export_imper_region"
},
"resource_slug": "imper-region-gpkg-2026",
"resource_title": "Impermeabilisation par region (GeoPackage)",
},
],
},
]
Loading
Loading