Site citoyen non officiel — sans lien avec l'Assemblée nationale ni le Conseil constitutionnel.

Comment ce chiffre est produit : Contrôle des lois par le Conseil constitutionnel

Chaque étape, de la source primaire jusqu'au chiffre affiché sur la page Contrôle des lois par le Conseil constitutionnel. Les volumes sont lus dans la base au moment de l'affichage ; le code est celui qui tourne sur le serveur (version 4aabd6c).

Parcours des données

  1. 1. Fichiers sources5 fichiers publiés par l'Assemblée nationale et la DILA, téléchargés avec leur date de publication et contrôlés par leur empreinte MD5.
  2. 2. Données brutes versionnéesCONSTIT : 7 423 enregistrements courants (7 518 versions conservées).DOLE : 3 600 enregistrements courants (5 088 versions conservées).AN_DOSSIERS : 35 600 enregistrements courants (35 725 versions conservées).
  3. 3. Lecture et transformationdécisions DC lues dans le fonds CONSTIT : 457écartées : traités (DC01) : 6écartées : règlements des assemblées (DC02) : 30écartées : décisions annexes sur une loi : 5écartées : hors période (15e à 17e législature) : 266retenues : lois ordinaires et organiques : 150lois promulguées, dénominateur (15e à 17e législature, hors traités et lois constitutionnelles) : 463Corrections justifiées : 8 (détail).
  4. 4. CalculMéthode I3 version 1 (définition), par législature, année parlementaire et session.
  5. 5. Résultats figés657 valeurs, calculées le 6 novembre 2026 (lot 400c1859), servies par l'API (/api/indicateurs/I3).
  6. 6. AffichageGraphiques et tableaux de la page Contrôle des lois par le Conseil constitutionnel, avec la source de chaque élément.

Fichiers sources

Dernière version intégrée de chaque fichier
SourceFichierLégislaturePublié leCollecté leMD5 (publié / calculé)
AN_DOSSIERSDossiers_Legislatifs_XV.json.zip1509/06/202206/11/202608f79aa683f73dbfe43b96c3eff0a64d
08f79aa683f73dbfe43b96c3eff0a64d
AN_DOSSIERSDossiers_Legislatifs.json.zip1628/06/202406/11/2026e7eb837f9ff3128e3dcbcdeddf6a12d4
e7eb837f9ff3128e3dcbcdeddf6a12d4
AN_DOSSIERSDossiers_Legislatifs.json.zip1706/11/202606/11/2026c3f6a8e8a40d8fe716a8ceee5f5129e1
c3f6a8e8a40d8fe716a8ceee5f5129e1
CONSTITCONSTIT_20261019-211152.tar.gz—19/10/202603/11/2026—
9da7ffecffff62d6136458490e3e97a9
DOLEDOLE_20261104-214059.tar.gz—04/11/202604/11/2026—
6cb0262f0dfabeefd40a296b3f1b7fcb

Code du calcul

Fonctions exécutées par le serveur pour produire ce chiffre, dans l'ordre : lecture des sources, puis calcul. Le texte est extrait du programme en cours d'exécution (version 4aabd6c).

Transformation.classer_solution — donnees.transformation, lignes 548-563
@staticmethod
def classer_solution(solution: str) -> dict:
    parties = [p.strip().lower() for p in solution.split(" - ")]
    principale = parties[0]
    issue = {
        "conformité": DecisionCC.Issue.CONFORMITE,
        "non conformité partielle": DecisionCC.Issue.NC_PARTIELLE,
        "non conformité totale": DecisionCC.Issue.NC_TOTALE,
    }.get(principale, DecisionCC.Issue.AUTRE)
    return {
        "issue_principale": issue,
        "reserves": "réserve" in parties[1:],
        "declassement_organique": "déclassement organique" in parties[1:],
        "effet_differe": "effet différé" in parties[1:],
        "annexe": principale if issue == DecisionCC.Issue.AUTRE else "",
    }
Transformation.decisions — donnees.transformation, lignes 565-599
def decisions(self):
    objets = []
    for brut in _bruts(Source.CONSTIT, "xml"):
        r = ET.fromstring(brut.contenu["xml"])
        if (r.findtext(".//NATURE") or "").strip() != "DC":
            continue
        jour = _jour((r.findtext(".//DATE_DEC") or "").strip())
        leg = self.legislature_a_la_date(jour) if jour else None
        if leg is None:
            self.rapport.comptes["decisions_hors_legislatures_connues"] += 1
            continue
        numero = (r.findtext(".//NUMERO") or "").strip()
        classement = self.classer_solution((r.findtext(".//SOLUTION") or "").strip())
        if re.search(r"-\d+-\d+$", numero):
            classement["annexe"] = classement["annexe"] or "récusation"
        loi = self._loi_deferee(r.find(".//LOI_DEF"), numero)
        objets.append(
            DecisionCC(
                ecli=(r.findtext(".//ECLI") or "").strip(),
                numero=numero,
                nature_qualifiee=(r.findtext(".//NATURE_QUALIFIEE") or "").strip(),
                date=jour,
                titre=(r.findtext(".//TITRE") or "").strip(),
                solution_brute=(r.findtext(".//SOLUTION") or "").strip(),
                loi=loi,
                url_cc=(r.findtext(".//URL_CC") or "").strip(),
                legislature=leg,
                **classement,
                **_trace(
                    brut, (r.findtext(".//ID") or "").strip(), (r.findtext(".//URL_CC") or "").strip()
                ),
            )
        )
    DecisionCC.objects.bulk_create(objets)
    self.rapport.comptes["decisions_dc"] = len(objets)
Transformation._loi_deferee — donnees.transformation, lignes 601-639
def _loi_deferee(self, loi_def, numero_decision: str) -> Loi | None:
    if loi_def is None or not (loi_def.get("num") or "").strip():
        return None
    brut_num = loi_def.get("num")
    num = brut_num.strip()
    if num != brut_num:
        self._correction(
            "DecisionCC",
            numero_decision,
            "loi",
            brut_num,
            num,
            "Espaces superflus dans le numéro de loi (CONSTIT)",
            "",
        )
    if num in self.lois_par_numero:
        return self.lois_par_numero[num]
    # Numéro introuvable : loi promulguée le même jour, de titre proche (contrôle publié)
    jour = _jour(loi_def.get("date"))
    titre = _normaliser_titre(loi_def.text or "")[:40]
    candidates = [
        lo
        for lo in self.lois_par_numero.values()
        if lo.date_promulgation == jour and titre and titre in _normaliser_titre(lo.titre)
    ]
    if len(candidates) == 1:
        loi = candidates[0]
        self._correction(
            "DecisionCC",
            numero_decision,
            "loi",
            num,
            loi.numero,
            "Numéro de loi introuvable ; loi unique promulguée le même jour, de même titre",
            f"Loi {loi.numero} du {jour} : « {loi.titre[:100]} »",
        )
        return loi
    self.rapport.alerte(f"Décision {numero_decision} : loi déférée {num} introuvable")
    return None
periodes — indicateurs.calcul, lignes 73-81
def periodes(jour: dt.date, legislature: int) -> list[tuple[str, str]]:
    annee = annee_parlementaire(jour)
    return [
        (ResultatIndicateur.PeriodeType.LEGISLATURE, str(legislature)),
        (ResultatIndicateur.PeriodeType.ANNEE_PARLEMENTAIRE, annee),
        (ResultatIndicateur.PeriodeType.SESSION, f"{annee}/{type_session(jour)}"),
        (ResultatIndicateur.PeriodeType.LEGISLATURE_ANNEE, f"{legislature}/{annee}"),
        (ResultatIndicateur.PeriodeType.LEGISLATURE_SESSION, f"{legislature}/{annee}/{type_session(jour)}"),
    ]
_compter — indicateurs.calcul, lignes 93-103
def _compter(elements, cle_legislature, cle_date, ventilations) -> dict:
    """{(periode_type, periode): Counter(ventilation)}"""
    comptes = defaultdict(Counter)
    for e in elements:
        leg = cle_legislature(e)
        if leg not in LEGISLATURES_JALON:
            continue
        for periode in periodes(cle_date(e), leg):
            for v in ventilations(e):
                comptes[periode][v] += 1
    return comptes
calculer() — bloc I3 — indicateurs.calcul
# I3 — décisions DC sur les lois ; dénominateur : lois promulguées hors traités et constitutionnelles
decisions = DecisionCC.objects.filter(nature_qualifiee__in=["DC03", "DC04"], annexe="")

def vent_decision(d):
    v = ["deferees", d.issue_principale, f"deferees_{d.nature_qualifiee}"]
    if d.issue_principale in (DecisionCC.Issue.NC_PARTIELLE, DecisionCC.Issue.NC_TOTALE):
        v.append("censures")
    if d.reserves:
        v.append("avec_reserves")
    return v

comptes_dc = _compter(decisions, lambda d: d.legislature_id, lambda d: d.date, vent_decision)
lois = Loi.objects.exclude(nature__in=[Loi.Nature.TRAITE, Loi.Nature.CONSTITUTIONNELLE])
comptes_lois = _compter(
    lois,
    lambda lo: legs.a_la_date(lo.date_promulgation),
    lambda lo: lo.date_promulgation,
    lambda lo: ["promulguees"],
)
for periode, c in comptes_lois.items():
    comptes_dc[periode]["lois_promulguees"] += c["promulguees"]
traites = _compter(
    Loi.objects.filter(nature=Loi.Nature.TRAITE),
    lambda lo: legs.a_la_date(lo.date_promulgation),
    lambda lo: lo.date_promulgation,
    lambda lo: ["lois_traites_promulguees"],
)
for periode, c in traites.items():
    comptes_dc[periode].update(c)
ajouter(
    "I3",
    comptes_dc,
    ratios=[
        ("part_censures_deferees", "censures", "deferees", None),
        ("part_censures_promulguees", "censures", "lois_promulguees", None),
    ],
)