autocaption-app / generer_doc.py
Ludovic
V2
04969c3
import os
# --- Fonctions Auxiliaires ---
def _ecrire_structure_partie(f_out, chemin_a_parcourir, chemin_base_relativisation, exclusions_dossiers, exclusions_fichiers, exclusions_extensions):
"""
Écrit la structure des dossiers/fichiers pour un chemin donné.
L'indentation est relative à chemin_a_parcourir.
Les chemins affichés sont relatifs à chemin_base_relativisation.
"""
for root, dirs, files in os.walk(chemin_a_parcourir, topdown=True):
# Exclure les dossiers spécifiés
dirs[:] = [d for d in dirs if d not in exclusions_dossiers]
dirs.sort() # Trier les dossiers pour un ordre cohérent
# Calcul de l'indentation
if root == chemin_a_parcourir:
level = 0
# Nom à afficher pour le dossier racine de cette section
current_dir_display_name = os.path.relpath(root, chemin_base_relativisation)
if current_dir_display_name == ".": # chemin_a_parcourir == chemin_base_relativisation
current_dir_display_name = os.path.basename(root)
else:
# Calculer le niveau de profondeur par rapport à chemin_a_parcourir
relative_to_scan_root = os.path.relpath(root, chemin_a_parcourir)
level = relative_to_scan_root.count(os.sep) + 1 if relative_to_scan_root != "." else 1
current_dir_display_name = os.path.basename(root)
indent = ' ' * 4 * level
f_out.write(f"{indent}{current_dir_display_name}/\n")
sub_indent = ' ' * 4 * (level + 1)
for file_name in sorted(files): # Trier les fichiers
if file_name not in exclusions_fichiers and not any(file_name.endswith(ext) for ext in exclusions_extensions):
f_out.write(f"{sub_indent}{file_name}\n")
def _ecrire_contenu_partie(f_out, chemin_a_parcourir, chemin_base_relativisation, exclusions_dossiers, exclusions_fichiers, exclusions_extensions):
"""
Écrit le contenu des fichiers pour un chemin donné.
Les chemins des fichiers sont relatifs à chemin_base_relativisation.
"""
for root, dirs, files in os.walk(chemin_a_parcourir, topdown=True):
dirs[:] = [d for d in dirs if d not in exclusions_dossiers]
for file_name in sorted(files): # Trier les fichiers
if file_name not in exclusions_fichiers and not any(file_name.endswith(ext) for ext in exclusions_extensions):
chemin_fichier_absolu = os.path.join(root, file_name)
chemin_fichier_relatif_display = os.path.relpath(chemin_fichier_absolu, chemin_base_relativisation)
# Construction du chemin affiché pour qu'il commence par / s'il n'est pas à la racine immédiate.
# os.path.relpath peut retourner "fichier.txt" ou "dossier/fichier.txt"
if chemin_fichier_relatif_display == "." or chemin_fichier_relatif_display == os.path.basename(chemin_fichier_relatif_display):
# Fichier à la racine de chemin_base_relativisation
display_path_final = os.path.join(os.path.sep, os.path.basename(chemin_fichier_absolu))
else:
# Fichier dans un sous-dossier de chemin_base_relativisation
display_path_final = os.path.join(os.path.sep, chemin_fichier_relatif_display)
# Nettoyage pour éviter les "./" au début après la jointure
if display_path_final.startswith(os.path.sep + '.' + os.path.sep):
display_path_final = display_path_final.replace(os.path.sep + '.' + os.path.sep, os.path.sep, 1)
elif display_path_final == os.path.sep + '.': # cas où chemin_fichier_relatif_display était '.'
display_path_final = os.path.join(os.path.sep, os.path.basename(chemin_fichier_absolu))
f_out.write("-" * 30 + "\n")
f_out.write(f"Fichier : {display_path_final}\n")
f_out.write("-" * 30 + "\n")
try:
with open(chemin_fichier_absolu, 'r', encoding='utf-8', errors='ignore') as f_in:
contenu = f_in.read()
f_out.write(contenu)
f_out.write("\n\n")
except Exception as e:
f_out.write(f"Erreur lors de la lecture du fichier {file_name}: {e}\n\n")
# --- Fonctions de Génération de Document ---
def generer_document_unique(nom_section_document, chemin_a_scanner, chemin_base_relativisation, fichier_sortie, exclusions_dossiers, exclusions_fichiers, exclusions_extensions):
"""
Génère un document (structure et contenu) pour un seul chemin racine.
"""
if not os.path.isdir(chemin_a_scanner):
print(f"AVERTISSEMENT : Le dossier '{chemin_a_scanner}' pour la section '{nom_section_document}' est introuvable. Le fichier '{fichier_sortie}' ne sera pas généré.")
return
with open(fichier_sortie, 'w', encoding='utf-8') as f_out:
f_out.write(f"Structure pour : {nom_section_document}\n")
f_out.write(f"(Chemin de base pour l'analyse : {chemin_a_scanner})\n")
f_out.write(f"(Chemins affichés relatifs à : {chemin_base_relativisation})\n")
f_out.write("=" * 50 + "\n\n")
_ecrire_structure_partie(f_out, chemin_a_scanner, chemin_base_relativisation, exclusions_dossiers, exclusions_fichiers, exclusions_extensions)
f_out.write("\n\n" + "=" * 50 + "\n")
f_out.write(f"Contenu des fichiers pour : {nom_section_document}\n")
f_out.write("=" * 50 + "\n\n")
_ecrire_contenu_partie(f_out, chemin_a_scanner, chemin_base_relativisation, exclusions_dossiers, exclusions_fichiers, exclusions_extensions)
print(f"Le fichier '{fichier_sortie}' ({nom_section_document}) a été généré avec succès !")
def generer_document_combine(titre_global_document, liste_dossiers_sources_avec_noms, chemin_base_relativisation_global, fichier_sortie, exclusions_dossiers, exclusions_fichiers, exclusions_extensions):
"""
Génère un document combinant la structure et le contenu de plusieurs dossiers sources.
liste_dossiers_sources_avec_noms: une liste de tuples [("Nom Section", "/chemin/vers/dossier"), ...]
Les chemins dans le document sont relatifs à chemin_base_relativisation_global.
"""
with open(fichier_sortie, 'w', encoding='utf-8') as f_out:
f_out.write(f"{titre_global_document}\n")
f_out.write(f"(Chemins affichés relatifs à : {chemin_base_relativisation_global})\n")
f_out.write("=" * 50 + "\n\n")
f_out.write("Structure des dossiers :\n")
f_out.write("-" * 50 + "\n\n")
for nom_section, chemin_a_scanner in liste_dossiers_sources_avec_noms:
if not os.path.isdir(chemin_a_scanner):
f_out.write(f"--- Dossier '{nom_section}' ({chemin_a_scanner}) introuvable. Section de structure ignorée. ---\n\n")
continue
f_out.write(f"--- Structure pour : {nom_section} (depuis {chemin_a_scanner}) ---\n")
_ecrire_structure_partie(f_out, chemin_a_scanner, chemin_base_relativisation_global, exclusions_dossiers, exclusions_fichiers, exclusions_extensions)
f_out.write(f"--- Fin Structure pour : {nom_section} ---\n\n")
f_out.write("\n\n" + "=" * 50 + "\n")
f_out.write("Contenu des fichiers :\n")
f_out.write("=" * 50 + "\n\n")
for nom_section, chemin_a_scanner in liste_dossiers_sources_avec_noms:
if not os.path.isdir(chemin_a_scanner):
f_out.write(f"--- Dossier '{nom_section}' ({chemin_a_scanner}) introuvable. Section de contenu ignorée. ---\n\n")
continue
f_out.write(f"--- Contenu pour : {nom_section} (depuis {chemin_a_scanner}) ---\n")
_ecrire_contenu_partie(f_out, chemin_a_scanner, chemin_base_relativisation_global, exclusions_dossiers, exclusions_fichiers, exclusions_extensions)
f_out.write(f"--- Fin Contenu pour : {nom_section} ---\n\n")
print(f"Le fichier combiné '{fichier_sortie}' ({titre_global_document}) a été généré avec succès !")
if __name__ == "__main__":
# --- Configuration ---
home_dir = os.path.expanduser("~")
# Nom du dossier de votre projet cible
nom_dossier_projet = "autocaption-hf-space"
# Chemin de base où se trouve votre dossier de projet (Documents sur Mac)
# Si "autocaption-hf-space" est directement dans "Documents"
chemin_base_parent_projet = os.path.join(home_dir, "Documents")
# Chemin complet vers le dossier du projet cible
chemin_projet_cible = os.path.join(chemin_base_parent_projet, nom_dossier_projet)
# Chemins spécifiques pour d'éventuels sous-dossiers src et backend (si votre projet les utilise)
# Si votre projet "autocaption-hf-space" n'a pas ces sous-dossiers distincts,
# les rapports pour "SRC" et "BACKEND" ne seront simplement pas générés (ou seront vides).
chemin_src = os.path.join(chemin_projet_cible, "src")
chemin_backend = os.path.join(chemin_projet_cible, "backend")
# Dossiers à exclure (vous pouvez personnaliser cette liste)
dossiers_a_exclure = [
"node_modules", "venv", ".venv", "__pycache__", ".git", ".vscode",
".idea", "dist", "build", "target", "docs", "coverage", "logs",
"temp", "tmp", "env",
# Ajoutez "cesium" ou tout autre dossier spécifique à "autocaption-hf-space" que vous souhaitez exclure
# "nom_dossier_specifique_a_exclure_dans_autocaption"
]
# Fichiers spécifiques à exclure (vous pouvez personnaliser cette liste)
fichiers_a_exclure = [
"package-lock.json", "yarn.lock", "composer.lock", ".env",
".DS_Store", "Thumbs.db", "npm-debug.log", "yarn-debug.log",
"yarn-error.log"
]
# Extensions de fichiers à exclure (vous pouvez personnaliser cette liste)
extensions_a_exclure = [
".pyc", ".pyo", ".o", ".so", ".dll", ".exe", ".jar", ".war", ".ear",
".class", ".zip", ".tar", ".gz", ".rar", ".7z", ".pdf", ".doc",
".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".odt", ".ods", ".odp",
".img", ".iso", ".dmg", ".mp3", ".mp4", ".avi", ".mov", ".wav",
".jpg", ".jpeg", ".png", ".gif", ".bmp", ".tiff", ".lock",
# ".xml" # Décommentez si vous souhaitez exclure les fichiers XML, sinon laissez commenté
]
# --- Fin de la configuration ---
if not os.path.isdir(chemin_projet_cible):
print(f"ERREUR : Le dossier du projet '{chemin_projet_cible}' n'a pas été trouvé.")
print("Veuillez vérifier le chemin et la configuration 'nom_dossier_projet' et 'chemin_base_parent_projet' dans le script.")
else:
# Les fichiers de sortie seront sauvegardés dans le dossier "Documents" (le parent de votre projet)
dossier_de_sortie = chemin_base_parent_projet # Ou os.path.dirname(chemin_projet_cible)
# 1. Document pour le dossier SRC uniquement (si ce sous-dossier existe dans autocaption-hf-space)
nom_fichier_src = f"structure_et_contenu_{nom_dossier_projet}_SRC.txt"
fichier_sortie_src = os.path.join(dossier_de_sortie, nom_fichier_src)
if os.path.isdir(chemin_src):
generer_document_unique(
nom_section_document=f"Dossier SRC de {nom_dossier_projet}",
chemin_a_scanner=chemin_src,
chemin_base_relativisation=chemin_src, # Chemins relatifs à la racine de SRC
fichier_sortie=fichier_sortie_src,
exclusions_dossiers=dossiers_a_exclure,
exclusions_fichiers=fichiers_a_exclure,
exclusions_extensions=extensions_a_exclure
)
else:
print(f"INFO : Sous-dossier SRC '{chemin_src}' non trouvé dans '{nom_dossier_projet}'. Le fichier '{nom_fichier_src}' ne sera pas généré.")
# 2. Document pour le dossier BACKEND uniquement (si ce sous-dossier existe dans autocaption-hf-space)
nom_fichier_backend = f"structure_et_contenu_{nom_dossier_projet}_BACKEND.txt"
fichier_sortie_backend = os.path.join(dossier_de_sortie, nom_fichier_backend)
if os.path.isdir(chemin_backend):
generer_document_unique(
nom_section_document=f"Dossier BACKEND de {nom_dossier_projet}",
chemin_a_scanner=chemin_backend,
chemin_base_relativisation=chemin_backend, # Chemins relatifs à la racine de BACKEND
fichier_sortie=fichier_sortie_backend,
exclusions_dossiers=dossiers_a_exclure,
exclusions_fichiers=fichiers_a_exclure,
exclusions_extensions=extensions_a_exclure
)
else:
print(f"INFO : Sous-dossier BACKEND '{chemin_backend}' non trouvé dans '{nom_dossier_projet}'. Le fichier '{nom_fichier_backend}' ne sera pas généré.")
# 3. Document combinant SRC et Backend (si ces sous-dossiers existent)
nom_fichier_combine = f"structure_et_contenu_{nom_dossier_projet}_SRC_ET_BACKEND.txt"
fichier_sortie_combine = os.path.join(dossier_de_sortie, nom_fichier_combine)
dossiers_a_combiner = []
if os.path.isdir(chemin_src):
dossiers_a_combiner.append((f"SRC ({nom_dossier_projet})", chemin_src))
else:
print(f"INFO : Sous-dossier SRC '{chemin_src}' non trouvé. Ne sera pas inclus dans le fichier combiné '{nom_fichier_combine}'.")
if os.path.isdir(chemin_backend):
dossiers_a_combiner.append((f"BACKEND ({nom_dossier_projet})", chemin_backend))
else:
print(f"INFO : Sous-dossier BACKEND '{chemin_backend}' non trouvé. Ne sera pas inclus dans le fichier combiné '{nom_fichier_combine}'.")
if dossiers_a_combiner:
generer_document_combine(
titre_global_document=f"Combinaison des dossiers SRC et BACKEND de {nom_dossier_projet}",
liste_dossiers_sources_avec_noms=dossiers_a_combiner,
chemin_base_relativisation_global=chemin_projet_cible, # Chemins relatifs à la racine du projet
fichier_sortie=fichier_sortie_combine,
exclusions_dossiers=dossiers_a_exclure,
exclusions_fichiers=fichiers_a_exclure,
exclusions_extensions=extensions_a_exclure
)
elif not os.path.isdir(chemin_src) and not os.path.isdir(chemin_backend) and (os.path.exists(fichier_sortie_combine) or (not os.path.exists(fichier_sortie_combine) and (os.path.isdir(chemin_src) or os.path.isdir(chemin_backend)))): # Condition pour éviter message si aucun des deux n'est attendu
print(f"INFO : Ni le sous-dossier SRC ni le sous-dossier BACKEND n'ont été trouvés pour {nom_dossier_projet}. Le fichier combiné '{nom_fichier_combine}' ne sera pas généré.")
# 4. Document pour le projet complet "autocaption-hf-space"
nom_fichier_complet = f"structure_et_contenu_{nom_dossier_projet}_COMPLET.txt"
fichier_sortie_complet = os.path.join(dossier_de_sortie, nom_fichier_complet)
generer_document_unique(
nom_section_document=f"Projet Complet : {nom_dossier_projet}",
chemin_a_scanner=chemin_projet_cible,
chemin_base_relativisation=chemin_projet_cible, # Chemins relatifs à la racine du projet
fichier_sortie=fichier_sortie_complet,
exclusions_dossiers=dossiers_a_exclure,
exclusions_fichiers=fichiers_a_exclure,
exclusions_extensions=extensions_a_exclure
)