Files
veye-lalwa/tests/test_dates_fr.py
T
Cyber MawonajandClaude Opus 5 c36b8dc631 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>
2026-07-25 18:22:18 -04:00

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"