Code/batch_ia/utils/sections_utils.py
2025-05-28 14:36:30 +02:00

93 lines
3.5 KiB
Python
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import re
from pathlib import Path
from collections import defaultdict
from utils.config import (
CORPUS_DIR
)
def composant_match(nom_composant, nom_dossier):
"""
Vérifie si le nom du composant correspond approximativement à un nom de dossier (lettres et chiffres dans le même ordre).
"""
def clean(s):
return ''.join(c.lower() for c in s if c.isalnum())
cleaned_comp = clean(nom_composant)
cleaned_dir = clean(nom_dossier)
# Vérifie que chaque caractère de cleaned_comp est présent dans cleaned_dir dans le bon ordre
it = iter(cleaned_dir)
return all(c in it for c in cleaned_comp)
def trouver_dossier_composant(nom_composant, base_path, prefixe):
"""
Parcourt les sous-répertoires de base_path et retourne celui qui correspond au composant.
"""
search_path = os.path.join(CORPUS_DIR, base_path)
if not os.path.exists(search_path):
return None
for d in os.listdir(search_path):
if os.path.isdir(os.path.join(search_path, d)):
if composant_match(f"{prefixe}{nom_composant}", d):
return os.path.join(base_path, d)
return None
def extraire_sections_par_mot_cle(fichier_markdown: Path) -> dict:
"""
Extrait les sections de niveau 3 uniquement dans la section
'## Chaînes avec risque critique' du fichier Markdown,
et les regroupe par mot-clé (ce qui se trouve entre '### ' et '').
Réduit chaque titre dun niveau (#).
"""
with fichier_markdown.open(encoding="utf-8") as f:
contenu = f.read()
# Extraire uniquement la section '## Chaînes avec risque critique'
match_section = re.search(
r"## Chaînes avec risque critique(.*?)(?=\n## |\Z)", contenu, re.DOTALL
)
if not match_section:
return {}
section_critique = match_section.group(1)
# Extraire les mots-clés entre '### ' et ' →'
mots_cles = set(re.findall(r"^### (.+?) →", section_critique, re.MULTILINE))
# Extraire tous les blocs de niveau 3 dans cette section uniquement
blocs_sections = re.findall(r"(### .+?)(?=\n### |\n## |\Z)", section_critique, re.DOTALL)
# Regrouper les blocs par mot-clé
regroupement = defaultdict(list)
for bloc in blocs_sections:
match = re.match(r"### (.+?) →", bloc)
if match:
mot = match.group(1)
if mot in mots_cles:
# Réduction du niveau des titres
bloc_modifie = re.sub(r"^###", "##", bloc, flags=re.MULTILINE)
bloc_modifie = re.sub(r"^###", "##", bloc_modifie, flags=re.MULTILINE)
regroupement[mot].append(bloc_modifie)
return {mot: "\n\n".join(blocs) for mot, blocs in regroupement.items()}
def nettoyer_texte_fr(texte: str) -> str:
# Apostrophes droites -> typographiques
texte = texte.replace("'", "")
# Guillemets droits -> guillemets français (avec espace fine insécable)
texte = re.sub(r'"(.*?)"', r'« \1»', texte)
# Espaces fines insécables avant : ; ! ?
texte = re.sub(r' (?=[:;!?])', '\u202F', texte)
# Unités : espace insécable entre chiffre et unité
texte = re.sub(r'(\d) (?=\w+)', lambda m: f"{m.group(1)}\u202F", texte)
# Suppression des doubles espaces
texte = re.sub(r' {2,}', ' ', texte)
# Remplacement optionnel des tirets simples (optionnel)
texte = texte.replace(" - ", " ")
# Nettoyage ponctuation multiple accidentelle
texte = re.sub(r'\s+([.,;!?])', r'\1', texte)
return texte