Crée l'ETL complet : dossiers, amendements, acteurs...#8
Open
DavidNO wants to merge 12 commits into
Open
Conversation
Introduce the raw `amendements` table (fields sourced directly from the Tricoteuses /amendements endpoint, grouped into identity, text, author, attachment, status and dates). Column names mirror the JSON keys so the existing schema-driven ETL loads them without changes. Scope the rebuild to ETL-managed tables (ETL_TABLES) so future analysis tables are neither dropped by `create_db` nor treated as source files by the ETL loop. This lets analysis results survive a re-download without introducing Alembic. Add `.env.example` wiring the ETL to the local docker-compose Postgres.
getenv returns a string, so bool(getenv("PG_ECHO", False)) was truthy for
any non-empty value including "False", leaving SQL echo permanently on.
Parse the flag explicitly instead.
# Conflicts: # models/__init__.py
…égés, textes) Charge depuis l'API des tricoteuses les objets permettant les recoupements « qui propose / porte quel texte, via quel groupe, et comment c'est voté » : - acteurs, organes, mandats (référentiels + jointure acteur↔groupe) - scrutins (résultat agrégé des votes, lien natif amendementRefUid) - documents (textes de loi, lien dossierRefUid) - auteursDocument, coSignatairesDocument (qui dépose/co-signe un texte) Modèles typés d'après le profilage des types JSON réels, colonnes RefUid indexées pour les jointures. download.py devient robuste (retries, timeout long, plus de cap de pages) et gère un filtre legislature configurable par endpoint. loading.py insère par lots pour rester sous la limite de 65 535 paramètres de Postgres (indispensable pour mandats/coSignatairesDocument). Périmètre législature 17 ; votes nominatifs individuels laissés de côté (pas de filtre legislature côté API, résultat agrégé par scrutin suffisant).
5 tasks
This was referenced Jul 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contexte
Socle DB complet pour le POC d'analyse des amendements. Objectif : ingérer les données brutes de l'API des tricoteuses et pouvoir y greffer plus tard des tables d'analyse (mentions « travaillé avec… », similarité, sémantique).
Tables chargées (législature 17)
dossiersamendementsacteursorganesmandatsscrutinsgroupesVotantsdocumentsauteursDocumentcoSignatairesDocument*
groupesVotantsn'expose pas de filtrelegislature: la table couvre toutes les législatures. ~98 300 lignes se rattachent à un scrutin L17 (12 groupes pour chacun des 8 192 scrutins concernés) ; se scoper par jointure surscrutins.Changements
Amendement(models/amendement.py) : table bruteamendements, champs issus directement de l'endpoint/amendements, regroupés en catégories (identité, texte, auteur/signataires, rattachement, statut/sort, dates). Colonnes en camelCase pour matcher 1:1 les clés JSON. Seuluidest non nullable ; le reste est nullable (amendements hétérogènes : budgétaires, sous-amendements).models/acteur.py,organe.py,mandat.py,scrutin.py,document.py,auteur_document.py,cosignataire_document.py) : mêmes conventions. Modèles typés d'après un profilage des types JSON réels (int / bool / str) ; artefacts de recherche (vecteurRecherche,embedding) ignorés ; colonnes…RefUidindexées pour les jointures.etl/database.py) :create_db()ne drop/recrée que les tables listées dansETL_TABLES(désormais les 10 tables sources). Les futures tables d'analyse ne sont ni détruites au rebuild, ni parcourues par la boucle ETL.etl/download.pyretries, timeout 90...) + filtrelegislatureconfigurable par endpoint :dossiers,documents,amendements,scrutins,mandats;acteurs(renvoie une 500 avec le filtre),organes;auteursDocument/coSignatairesDocument/groupesVotants: l'API n'expose pas de filtrelegislature→ scopés L17 par jointure (surdocumentsouscrutins).etl/loading.py) : insertion par lots (1 000 lignes, pour rester sous la limite de 65 535 paramètres de Postgres) avec déduplication paruid(la pagination de l'API sert parfois deux fois la même ligne) puis upserton_conflict_do_update. Un rechargement met donc à jour les lignes modifiées et n'en réécrit aucune si rien n'a changé (WHERE ... IS DISTINCT FROM, horsdateMajqui est l'horodatage d'export du lot, identique pour toutes les lignes et changeant à chaque téléchargement).models/groupe_votant.py: nouvelle tablegroupesVotants, le résultat de chaque scrutin ventilé par groupe politique (une ligne par couple scrutin × groupe :pour,contre,abstentions,nonVotants,positionMajoritaire). 1:1 avec l'endpoint, sans transformation.Schéma de la base
Diagramme entité-relation : les 10 tables, leurs colonnes clés (PK + FK + les champs les plus parlants) et les relations principales. La liste complète des 269 colonnes est dans les modèles
models/.Les relations sont des références molles (nullable, sans
ForeignKey) ; leurs cibles ont été établies en mesurant le taux de résolution des valeurs réelles dans les données, et non déduites des noms de colonnes. Quelques colonnes…RefUidne sont pas représentées ici parce qu'elles pointent vers des objets dont l'endpoint n'est pas chargé (étapes législatives, articles, séances, points d'ordre du jour).erDiagram dossiers { string uid PK string titre string libelleProcedure string statut } documents { string uid PK string dossierRefUid FK string auteurPrincipalUid FK text titrePrincipal string classeLibelle bool texteLoi string dateDepot } amendements { string uid PK string acteurRefUid FK string groupePolitiqueRefUid FK string dossierRefUid FK string documentRefUid FK string scrutinRefUid FK string numeroLong string divisionArticleDesignation text exposeSommaire string sortAmendement string dateDepot } acteurs { string uid PK string groupeParlementaireUid FK string nom string prenom string chambre bool actif } organes { string uid PK string codeType string libelleAbrev string positionPolitique } mandats { string uid PK string acteurRefUid FK string organeRefUid FK string typeOrgane string libQualite string dateDebut string dateFin } scrutins { string uid PK string dossierRefUid FK string documentRefUid FK string amendementRefUid FK string dateScrutin text objet string code int pour int contre int abstentions } groupesVotants { string uid PK string scrutinRefUid FK string organeRefUid FK string positionMajoritaire int pour int contre int abstentions } auteursDocument { string uid PK string documentRefUid FK string acteurRefUid FK string qualite } coSignatairesDocument { string uid PK string documentRefUid FK string acteurRefUid FK string dateCosignature } dossiers ||--o{ documents : "dossierRefUid" dossiers ||--o{ amendements : "dossierRefUid" dossiers ||--o{ scrutins : "dossierRefUid" documents ||--o{ amendements : "documentRefUid" documents ||--o{ scrutins : "documentRefUid" documents ||--o{ auteursDocument : "documentRefUid" documents ||--o{ coSignatairesDocument : "documentRefUid" acteurs ||--o{ documents : "auteurPrincipalUid" acteurs ||--o{ amendements : "acteurRefUid" acteurs ||--o{ mandats : "acteurRefUid" acteurs ||--o{ auteursDocument : "acteurRefUid" acteurs ||--o{ coSignatairesDocument : "acteurRefUid" organes ||--o{ acteurs : "groupeParlementaireUid" organes ||--o{ amendements : "groupePolitiqueRefUid" organes ||--o{ mandats : "organeRefUid" organes ||--o{ groupesVotants : "organeRefUid" amendements ||--o{ scrutins : "amendementRefUid" scrutins ||--o{ amendements : "scrutinRefUid" scrutins ||--o{ groupesVotants : "scrutinRefUid"Notes
/votes) ne sont pas chargés. A faire si besoin.