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>
82 lines
2.7 KiB
Python
82 lines
2.7 KiB
Python
"""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"
|