mirror of
https://github.com/Alex38Lyon/Synthese-PSM_LARRA.git
synced 2026-06-01 13:59:13 +00:00
289 lines
12 KiB
Python
289 lines
12 KiB
Python
"""
|
|
#############################################################################################
|
|
general_fonctions.py for pyCreateTh.py
|
|
#############################################################################################
|
|
"""
|
|
import os, logging, sys, re, configparser
|
|
import Lib.global_data as global_data
|
|
import tkinter as tk
|
|
from tkinter import filedialog
|
|
|
|
#################################################################################################
|
|
# Couleurs ANSI par niveau de log
|
|
#################################################################################################
|
|
COLOR_CODES = {
|
|
logging.DEBUG: "\033[94m", # Bleu
|
|
logging.INFO: "\033[92m", # Vert
|
|
logging.WARNING: "\033[95m", # MAGENTA
|
|
logging.ERROR: "\033[91m", # Rouge
|
|
logging.CRITICAL: "\033[1;91m", # Rouge vif
|
|
}
|
|
RESET = "\033[0m"
|
|
|
|
#################################################################################################
|
|
# Codes de couleur ANSI
|
|
class Colors:
|
|
BLACK = '\033[90m'
|
|
RED = '\033[91m'
|
|
GREEN = '\033[92m'
|
|
YELLOW = '\033[93m'
|
|
BLUE = '\033[94m'
|
|
MAGENTA = '\033[95m'
|
|
CYAN = '\033[96m'
|
|
WHITE = '\033[97m'
|
|
|
|
ERROR = '\033[91m'
|
|
WARNING = '\033[95m'
|
|
HEADER = '\033[96m'
|
|
DEBUG = '\033[94m' # Bleu
|
|
INFO = '\033[92m' # Vert
|
|
CRITICAL = '\033[1;91m', # Rouge vif
|
|
|
|
ENDC = '\033[0m'
|
|
BOLD = '\033[1m'
|
|
UNDERLINE = '\033[4m'
|
|
|
|
|
|
#################################################################################################
|
|
def safe_relpath(path):
|
|
"""
|
|
Renvoie un chemin relatif si possible, sinon un chemin partiel à partir du dossier de référence.
|
|
"""
|
|
|
|
abs_path = os.path.abspath(path)
|
|
ref_path = os.path.abspath(os.getcwd())
|
|
|
|
try:
|
|
valeur = "~\\" + os.path.relpath(path, ref_path)
|
|
return valeur
|
|
|
|
except ValueError:
|
|
max_depth = 4 # Profondeur maximale pour tronquer le chemin
|
|
|
|
# Disques différents, afficher le chemin relatif partiel depuis la racine commune
|
|
path_parts = abs_path.split(os.sep)
|
|
ref_parts = ref_path.split(os.sep)
|
|
while path_parts and ref_parts and path_parts[0] == ref_parts[0]:
|
|
path_parts.pop(0)
|
|
ref_parts.pop(0)
|
|
result = os.path.join(*path_parts) if path_parts else os.path.basename(path)
|
|
|
|
# Si max_depth est défini, tronque le chemin
|
|
if max_depth is not None:
|
|
parts = result.split(os.sep)
|
|
if len(parts) > max_depth:
|
|
result = os.path.join("~\\" , *parts[-max_depth:])
|
|
|
|
return result
|
|
|
|
|
|
#################################################################################################
|
|
# Coloration des messages d'aide d'arg #
|
|
#################################################################################################
|
|
def colored_help(parser):
|
|
"""
|
|
Affiche l'aide colorée pour les arguments de la ligne de commande.
|
|
|
|
Args:
|
|
parser (argparse.ArgumentParser): Le parseur d'arguments.
|
|
Returns:
|
|
None
|
|
|
|
"""
|
|
# Captures the help output
|
|
help_text = parser.format_help()
|
|
|
|
# Coloration des différentes parties
|
|
colored_help_text = help_text.replace(
|
|
'usage:', f'{Colors.ERROR}usage:{Colors.ENDC}'
|
|
).replace(
|
|
'options:', f'{Colors.GREEN}options:{Colors.ENDC}'
|
|
).replace('positional arguments:', f'{Colors.BLUE}positional arguments:{Colors.ENDC}'
|
|
).replace(', --help', f'{Colors.BLUE}, --help:{Colors.ENDC}'
|
|
).replace('elp:', f'{Colors.BLUE}elp{Colors.ENDC}')
|
|
|
|
# Surligner les arguments
|
|
for action in parser._actions:
|
|
if action.option_strings:
|
|
# Colorer les options (--xyz)
|
|
for opt in action.option_strings:
|
|
colored_help_text = colored_help_text.replace(opt, f'{Colors.BLUE}{opt}{Colors.ENDC}').replace('--help', f'{Colors.BLUE}--help:{Colors.ENDC}')
|
|
|
|
# Imprimer le texte coloré
|
|
print(colored_help_text)
|
|
sys.exit(1)
|
|
|
|
|
|
#################################################################################################
|
|
def select_file_tk_window():
|
|
"""
|
|
Ouvre une boite de dialogue tkinter pour sélectionner un fichier.
|
|
|
|
Returns:
|
|
str: Le chemin complet du fichier sélectionné.
|
|
"""
|
|
# Créer une instance de la fenêtre tkinter
|
|
root = tk.Tk()
|
|
|
|
# Cacher la fenêtre principale
|
|
root.withdraw()
|
|
|
|
# Afficher la boite de dialogue de sélection de fichier
|
|
file_path = filedialog.askopenfilename(
|
|
title="Select your file",
|
|
filetypes=[("MAK files", "*.mak"), ("Compatibles files", "*.th *.mak *.dat"), ("TH files", "*.th"), ("DAT files", "*.dat"), ("All files", "*.*")]
|
|
)
|
|
|
|
|
|
return file_path # Retourner le chemin complet du fichier sélectionné
|
|
|
|
|
|
#################################################################################################
|
|
def read_config(config_file):
|
|
"""
|
|
Lit le fichier de configuration et initialise les variables globales.
|
|
|
|
Args:
|
|
config_file (str): Le chemin vers le fichier de configuration.
|
|
|
|
Returns:
|
|
None
|
|
|
|
"""
|
|
|
|
# Initialize the configparser to read .ini files
|
|
config = configparser.ConfigParser()
|
|
config.read(config_file, encoding="utf-8")
|
|
|
|
if 'Survey_Data' in config and 'Author' in config['Survey_Data']:
|
|
global_data.Author = config['Survey_Data']['Author']
|
|
|
|
if 'Survey_Data' in config and 'Copyright1' in config['Survey_Data']:
|
|
global_data.Copyright = config['Survey_Data']['Copyright1'] + "\n" + config['Survey_Data']['Copyright2'] + "\n" + config['Survey_Data']['Copyright3'] + "\n"
|
|
|
|
if 'Survey_Data' in config and 'Copyright_Short' in config['Survey_Data']:
|
|
global_data.CopyrightShort = config['Survey_Data']['Copyright_Short']
|
|
|
|
if 'Survey_Data' in config and 'map_comment' in config['Survey_Data']:
|
|
global_data.mapComment = config['Survey_Data']['map_comment']
|
|
|
|
if 'Survey_Data' in config and 'club' in config['Survey_Data']:
|
|
global_data.club = config['Survey_Data']['club']
|
|
|
|
if 'Survey_Data' in config and 'thanksto' in config['Survey_Data']:
|
|
global_data.thanksto = config['Survey_Data']['thanksto']
|
|
|
|
if 'Survey_Data' in config and 'datat' in config['Survey_Data']:
|
|
global_data.datat = config['Survey_Data']['datat']
|
|
|
|
if 'Survey_Data' in config and 'wpage' in config['Survey_Data']:
|
|
global_data.wpage = config['Survey_Data']['wpage']
|
|
|
|
if 'Survey_Data' in config and 'cs' in config['Survey_Data']:
|
|
global_data.cs = config['Survey_Data']['cs']
|
|
|
|
if 'Application_Data' in config and 'template_path' in config['Application_Data']:
|
|
global_data.templatePath = config['Application_Data']['template_path']
|
|
|
|
if 'Application_Data' in config and 'station_by_scrap' in config['Application_Data']:
|
|
global_data.stationByScrap = int(config['Application_Data']['station_by_scrap'])
|
|
|
|
if 'Application_Data' in config and 'final_therion_exe' in config['Application_Data']:
|
|
global_data.finalTherionExe = bool(config['Application_Data']['final_therion_exe'])
|
|
|
|
if 'Application_Data' in config and 'therion_path' in config['Application_Data']:
|
|
global_data.therionPath = config['Application_Data']['therion_path']
|
|
|
|
if 'Application_Data' in config and 'therion_path' in config['Application_Data']:
|
|
global_data.SurveyPrefixName = config['Application_Data']['survey_prefix_name']
|
|
|
|
if global_data.linesInTh2 == -1 :
|
|
if 'Application_Data' in config and 'shot_lines_in_th2_files' in config['Application_Data']:
|
|
global_data.linesInTh2 = 0 if config['Application_Data']['shot_lines_in_th2_files'] == "False" else 1
|
|
|
|
if global_data.stationNamesInTh2 == -1 :
|
|
if 'Application_Data' in config and 'station_name_in_th2_files' in config['Application_Data']:
|
|
global_data.stationNamesInTh2 = 0 if config['Application_Data']['station_name_in_th2_files'] == "False" else 1
|
|
|
|
if global_data.wallLineInTh2 == -1 :
|
|
if 'Application_Data' in config and 'wall_lines_in_th2_files' in config['Application_Data']:
|
|
global_data.wallLineInTh2 = 0 if config['Application_Data']['wall_lines_in_th2_files'] == "False" else 1
|
|
|
|
|
|
#################################################################################################
|
|
# Supprime les codes ANSI (pour l'écriture dans les fichiers)
|
|
#################################################################################################
|
|
def strip_ansi_codes(text):
|
|
ansi_escape = re.compile(r'\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])')
|
|
return ansi_escape.sub('', text)
|
|
|
|
|
|
#################################################################################################
|
|
# Formatter pour la console avec couleurs
|
|
#################################################################################################
|
|
class ConsoleFormatter(logging.Formatter):
|
|
def format(self, record):
|
|
color = COLOR_CODES.get(record.levelno, "")
|
|
message = super().format(record)
|
|
return f"{color}{message}{RESET}"
|
|
|
|
|
|
#################################################################################################
|
|
# Formatter pour le fichier avec "!!!" sur les erreurs
|
|
#################################################################################################
|
|
class FileFormatter(logging.Formatter):
|
|
def format(self, record):
|
|
clean_msg = strip_ansi_codes(record.getMessage())
|
|
prefix = "!!! " if record.levelno >= logging.ERROR else ""
|
|
record_copy = logging.LogRecord(
|
|
name=record.name,
|
|
level=record.levelno,
|
|
pathname=record.pathname,
|
|
lineno=record.lineno,
|
|
msg=f"{prefix}{clean_msg}",
|
|
args=(),
|
|
exc_info=record.exc_info,
|
|
func=record.funcName,
|
|
sinfo=record.stack_info
|
|
)
|
|
return super().format(record_copy)
|
|
|
|
|
|
#################################################################################################
|
|
# Fonction de configuration du logger
|
|
#################################################################################################
|
|
def setup_logger(logfile="app.log", debug_log=False):
|
|
logger = logging.getLogger("Logger")
|
|
logger.setLevel(logging.DEBUG)
|
|
logger.handlers.clear()
|
|
|
|
|
|
|
|
min_level = logging.DEBUG if debug_log else logging.INFO
|
|
|
|
|
|
# Console stderr handler — affichage à l'écran avec couleurs
|
|
stderr_handler = logging.StreamHandler(sys.stderr)
|
|
stderr_handler.setLevel(min_level)
|
|
stderr_formatter = ConsoleFormatter("%(levelname)s: %(message)s") # <-- Ta classe personnalisée
|
|
stderr_handler.setFormatter(stderr_formatter)
|
|
logger.addHandler(stderr_handler)
|
|
|
|
# File handler — fichier de log
|
|
file_handler = logging.FileHandler(logfile, encoding="utf-8")
|
|
file_handler.setLevel(min_level)
|
|
file_formatter = FileFormatter("%(asctime)s - %(levelname)s - %(message)s") # <-- Ta classe personnalisée
|
|
file_handler.setFormatter(file_formatter)
|
|
logger.addHandler(file_handler)
|
|
|
|
return logger
|
|
|
|
|
|
#################################################################################################
|
|
def release_log_file(logger):
|
|
handlers = logger.handlers[:]
|
|
for handler in handlers:
|
|
if isinstance(handler, logging.FileHandler):
|
|
handler.close()
|
|
logger.removeHandler(handler)
|