Phase 2 : parseur de l'annexe sec10 — 52 textes, 12 affaires CC
Briques réutilisables : - dates_fr : lit les formes réelles du corpus (« 23 avr. 2026 (JO 24 avr.) », « 1er juill. », « 24.07.2026 ») et distingue une date exacte d'une échéance prévisionnelle (« Fin août 2026 » → situé au 25, libellé conservé, jamais présenté comme un fait) - markdown : découpage des tableaux (barres échappées, lignes courtes), nettoyage, extraction des marqueurs [^dim07-24^] / [^phase5-3.1^] Parseur sec10 : - 27 lois promulguées + 21 lignes simples + 2 lignes éclatées en 4 textes = 52 - éclatement justifié : les lignes « accords Kazakhstan et Colombie » et « MACF » décrivent chacune deux textes de statuts différents - migration 002 : regime_libertes stocké à part, faute de savoir quel public la cotation globale du rapport vise — dérouler « droits+ » sur les trois publics aurait inventé une ventilation absente de la source - migration 003 : la facette « devant le CC » couvre aussi les saisines sans numéro d'affaire (programmation militaire), sinon 6 textes au lieu de 7 Trois pièges du corpus, corrigés et couverts par des tests : - « eau » matchait comme sous-chaîne dans réseaux / drapeau / Retailleau - une décision citée sans saisine créait une fausse saisine (loi Philippine) - la date de saisine était pêchée dans la colonne « échéance », datant la saisine de l'aide à mourir du mois suivant 72 tests, 90 % de couverture sur pipeline/. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
31d3935bce
commit
c36b8dc631
@@ -0,0 +1,81 @@
|
||||
"""Lecture des dates françaises du corpus."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import date
|
||||
|
||||
import pytest
|
||||
|
||||
from pipeline.parseurs.dates_fr import lire_date, lire_echeance, sans_accents, toutes_les_dates
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("fragment", "attendu"),
|
||||
[
|
||||
# Formes réelles de la colonne « Promulgation / JO » du tableau A.
|
||||
("23 avr. 2026 (JO 24 avr.)", date(2026, 4, 23)),
|
||||
("29 avr. 2026 (JO 30 avr.)", date(2026, 4, 29)),
|
||||
("9 mai 2026 (JO 10 mai)", date(2026, 5, 9)),
|
||||
("12 juin 2026 (JO 13 juin)", date(2026, 6, 12)),
|
||||
("30 juin 2026 (JO 1er juill.)", date(2026, 6, 30)),
|
||||
("13 juill. 2026 (JO 14 juill.)", date(2026, 7, 13)),
|
||||
("1er juill. 2026", date(2026, 7, 1)),
|
||||
# Formes numériques du fichier de validation de phase 5.
|
||||
("24.07.2026", date(2026, 7, 24)),
|
||||
("22/07/2026", date(2026, 7, 22)),
|
||||
("2026-07-25", date(2026, 7, 25)),
|
||||
],
|
||||
)
|
||||
def test_lire_date_formes_du_corpus(fragment: str, attendu: date) -> None:
|
||||
assert lire_date(fragment) == attendu
|
||||
|
||||
|
||||
def test_lire_date_sans_annee_utilise_le_defaut() -> None:
|
||||
assert lire_date("6 juill.", annee_defaut=2026) == date(2026, 7, 6)
|
||||
assert lire_date("6 juill.") is None
|
||||
|
||||
|
||||
def test_lire_date_ignore_les_fragments_sans_jour() -> None:
|
||||
assert lire_date("Fin août 2026") is None
|
||||
assert lire_date("Automne 2026") is None
|
||||
|
||||
|
||||
def test_toutes_les_dates_conserve_l_ordre() -> None:
|
||||
assert toutes_les_dates("23 avr. 2026 (JO 24 avr.)", annee_defaut=2026) == [
|
||||
date(2026, 4, 23),
|
||||
date(2026, 4, 24),
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("fragment", "attendu"),
|
||||
[
|
||||
("~24 août 2026", date(2026, 8, 24)),
|
||||
("Début août 2026", date(2026, 8, 5)),
|
||||
("Fin août 2026", date(2026, 8, 25)),
|
||||
("Oct. 2026 ; adoption visée fin 2026", date(2026, 10, 15)),
|
||||
("Automne 2026", date(2026, 10, 1)),
|
||||
("Rentrée 2026", date(2026, 9, 1)),
|
||||
],
|
||||
)
|
||||
def test_lire_echeance_situe_les_previsions(fragment: str, attendu: date) -> None:
|
||||
approchee, libelle = lire_echeance(fragment)
|
||||
assert approchee == attendu
|
||||
# Le libellé d'origine est toujours conservé : c'est lui qui est affiché.
|
||||
assert libelle == fragment
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"fragment",
|
||||
["Indéterminée", "Sans échéance", "Sans date fixée", "Session ordinaire 2026-2027"],
|
||||
)
|
||||
def test_lire_echeance_refuse_d_inventer(fragment: str) -> None:
|
||||
approchee, libelle = lire_echeance(fragment)
|
||||
assert approchee is None
|
||||
assert libelle == fragment
|
||||
|
||||
|
||||
def test_sans_accents() -> None:
|
||||
assert sans_accents("août") == "aout"
|
||||
assert sans_accents("Échéance probable") == "Echeance probable"
|
||||
assert sans_accents("chlordécone") == "chlordecone"
|
||||
Reference in New Issue
Block a user