Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 36 additions & 5 deletions scripts/notebook_tools/repair_morpho.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,18 @@
# port des tests CI, c.1415).
LOCUTIONS_DONNE_MARKERS = re.compile(r"\b(?:etant|tant)\b")

# #17523 : la locution ne legitime QUE dans la phrase courante -- meme invariant
# que ``is_prouve_legitimate`` (auxiliaire coupe au dernier separateur, c.1415).
# Ancre = dernier ``.``/``!``/``?`` ou ligne BLANCHE. Mesure corpus (1383
# notebooks, 198 ``donné`` accentués hors backticks, 59 préservés) :
# - borner aux seuls ``[.!?]`` : 0 verdict change ;
# - y ajouter la ligne blanche : 0 verdict change ;
# - y ajouter le saut de ligne SIMPLE : 1 verdict change, et c'est une
# locution REELLE coupée par un retour a la ligne
# (``PyMC-10-Model-Selection`` : « l'inférence bayésienne : étant\ndonné un
# jeu de données ») -- le saut simple reste donc DANS la phrase.
_SENTENCE_BOUND = re.compile(r"[.!?]|\n\s*\n")


# --- Discrimination 'decide' / 'verifier' (reconciliation c.1415) ------------
#
Expand Down Expand Up @@ -177,12 +189,17 @@ def is_donne_legitimate(ctx_before: str) -> bool:
"""Verifie si 'donne' est dans une locution figee (etant donne / tant donne).

Fenetre 60 chars avant (Tell c.1317-L7 ★★★★ fondateur -- mots intercalés
OK). Detection par marqueurs a bordure de mot (cf LOCUTIONS_DONNE_MARKERS).
OK), **bornee a la phrase courante** (#17523, cf ``_SENTENCE_BOUND``) :
sans cette borne, une locution d'une phrase anterieure legitimisait un
« donné » fautif de la phrase suivante (defaut que documentait le skip de
``test_notebook_contamine``). Detection par marqueurs a bordure de mot
(cf LOCUTIONS_DONNE_MARKERS).
"""
ctx = _strip_accents(_normalize(ctx_before))
if not ctx:
return False
return bool(LOCUTIONS_DONNE_MARKERS.search(ctx[-60:]))
segment = _SENTENCE_BOUND.split(ctx)[-1]
return bool(LOCUTIONS_DONNE_MARKERS.search(segment[-60:]))


def is_verifie_legitimate(ctx_before: str) -> bool:
Expand Down Expand Up @@ -418,11 +435,22 @@ def _self_test() -> int:
if is_prouve_legitimate("se "):
failures.append("'se prouve' devrait etre fautif (cf Tell c.1315-L15)")

# Locution "etant donne" : legitime
if not is_donne_legitimate("Etant donne les contraintes, le probleme est complexe. On "):
# Locution "etant donne" : legitime DANS la phrase courante (#17523)
if not is_donne_legitimate("Etant donne les contraintes, le probleme est complexe pour "):
failures.append("'Etant donne' devrait etre legitime (locution figee)")
if not is_donne_legitimate("Pour un theoreme qui est tant donne, le cluster "):
failures.append("'tant donne' devrait etre legitime (mots intercalés OK)")
# Witness corpus : un saut de ligne SIMPLE ne borne pas la phrase (PyMC-10)
if not is_donne_legitimate("l'inference bayesienne : etant\n"):
failures.append("un saut de ligne simple ne doit PAS borner la phrase "
"(locution reelle coupee, PyMC-10)")
# Frontiere de phrase (#17523) : une locution d'une phrase ANTERIEURE ne
# legitimise PAS l'occurrence suivante.
if is_donne_legitimate("Etant donne les contraintes, le probleme est complexe. Le sup "):
failures.append("une locution avant le point ne doit PAS legitimiser "
"l'occurrence apres la frontiere de phrase (#17523)")
if is_donne_legitimate("Etant donne les contraintes, on propose X.\n\nLe sup "):
failures.append("une ligne blanche borne la phrase (#17523)")

# Verbe 3e pers. : "le sup donne" -> fautif
if is_donne_legitimate("Le sup "):
Expand Down Expand Up @@ -495,7 +523,10 @@ def _self_test() -> int:
for f in failures:
print(f" - {f}")
return 1
print("[OK] repair_morpho self-test (20 invariants verifies)")
# Compte = branchements `failures.append` du self-test (mesure :
# `grep -c` sur le corps de _self_test). #17523 en ajoute 3 a la famille
# locution ; HEAD en imprimait 20 pour 19 controles.
print("[OK] repair_morpho self-test (22 invariants verifies)")
return 0


Expand Down
42 changes: 36 additions & 6 deletions scripts/notebook_tools/tests/test_repair_morpho.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,38 @@ def test_le_verifie_fautif(self):
self.assertFalse(is_verifie_legitimate("Tao le "))

def test_etant_donne_legitime(self):
"""Locution legitime : meme phrase, fenetre 60 chars.

#17523 : l'assertion d'origine franchissait un point
(« ...est complexe. On ») -- elle encodait le defaut corrige. La borne
de phrase ne change aucun verdict sur le corpus mesure (0 verdict sur
1383 notebooks), mais elle rend la locution inter-phrase inoperante
(cf test_locution_inter_phrase_ne_legitime_plus).
"""
self.assertTrue(is_donne_legitimate(
"Etant donne les contraintes, le probleme est complexe pour "))

def test_locution_inter_phrase_ne_legitime_plus(self):
"""#17523 : la locution d'une phrase ANTERIEURE ne legitime plus un
« donné » fautif de la phrase suivante (defaut documente par le skip de
test_notebook_contamine, desormais leve). Symetrique de l'invariant
'auxiliaire' de is_prouve_legitimate (self-test multi-occurrences)."""
self.assertFalse(is_donne_legitimate(
"Etant donne les contraintes, le probleme est complexe. Le sup "))

def test_ligne_blanche_borne_la_phrase(self):
"""#17523 : une ligne BLANCHE borne la phrase (mesure corpus : aucune
locution n'est coupee par une ligne blanche -> zero faux positif)."""
self.assertFalse(is_donne_legitimate(
"Etant donne les contraintes, on propose X.\n\nLe sup "))

def test_locution_coupee_par_saut_de_ligne_simple(self):
"""Witness corpus ``PyMC-10-Model-Selection`` : « l'inférence bayésienne :
étant\\ndonne un jeu de données ». Un saut de ligne SIMPLE reste dans la
phrase -- le borner casserait une locution reelle (1 cas mesure, legitime,
le seul verdict que le saut simple changerait sur le corpus)."""
self.assertTrue(is_donne_legitimate(
"Etant donne les contraintes, le probleme est complexe. On "))
"L'un des problemes centraux de l'inference bayesienne : etant\n"))

def test_tant_donne_avec_intercalation(self):
"""'tant donne' avec mots intercalés OK (Tell c.1317-L7)."""
Expand Down Expand Up @@ -367,12 +397,12 @@ class TestControlePositifReaccentUpstream(unittest.TestCase):
"""Controle positif : un notebook contamine par REACCENT upstream fautif
doit etre detecte + repare, avec preservation des formes legitimes."""

@unittest.skip("bug organe is_donne_legitimate fenetre 60 chars (Tell c.1349-L1) -- "
"une locution 'Etant donne' anterieure masque un 'sup donné' fautif "
"dans la meme fenetre. La borne phrase-courante n'est pas appliquee "
"aux locutions (la locution inter-phrase est un cas reel, cf "
"test_etant_donne_legitime). Fix a suivre ; le test documente le defect.")
def test_notebook_contamine(self):
"""Le defaut que documentait le skip (#17523) est corrige : la locution
ne franchit plus la frontiere de phrase. La borne retenue est mesurée
sur le corpus -- terminateurs ``[.!?]`` et ligne blanche ; le saut de
ligne simple reste dans la phrase (witness PyMC-10, cf
test_locution_coupee_par_saut_de_ligne_simple)."""
cell = _md_str(
"Tao le prouvé en passant. "
"Le theoreme localement prouvé est interessant. "
Expand Down
Loading