"feat: Implement UNICODE encoding fix for database operations"

This commit is contained in:
Till Tomczak 2025-05-29 10:07:11 +02:00
parent fd9e51b291
commit cdf7a27f23
5 changed files with 89 additions and 39 deletions

View File

@ -0,0 +1 @@

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@

View File

@ -82,10 +82,20 @@ EMOJI_FALLBACK = {
def safe_emoji(emoji: str) -> str:
"""Gibt ein Emoji zurück oder einen ASCII-Fallback bei Encoding-Problemen."""
try:
# Teste, ob das Emoji dargestellt werden kann
emoji.encode(sys.stdout.encoding or 'utf-8')
# Erste Priorität: Teste, ob das Emoji dargestellt werden kann
test_encoding = sys.stdout.encoding or 'utf-8'
emoji.encode(test_encoding)
# Zweite Prüfung: Windows-spezifische cp1252-Codierung
if os.name == 'nt':
try:
emoji.encode('cp1252')
except UnicodeEncodeError:
# Wenn cp1252 fehlschlägt, verwende Fallback
return EMOJI_FALLBACK.get(emoji, '[?]')
return emoji
except (UnicodeEncodeError, LookupError):
except (UnicodeEncodeError, LookupError, AttributeError):
return EMOJI_FALLBACK.get(emoji, '[?]')
# Prüfen, ob das Terminal ANSI-Farben unterstützt
@ -135,39 +145,61 @@ class ColoredFormatter(logging.Formatter):
}
def format(self, record):
# Basis-Format erstellen
log_fmt = LOG_FORMAT
date_fmt = LOG_DATE_FORMAT
# Emoji dem Level und der Kategorie hinzufügen
level_name = record.levelname
category_name = record.name.split('.')[-1] if '.' in record.name else record.name
level_emoji = safe_emoji(LOG_EMOJIS.get(level_name, ''))
category_emoji = safe_emoji(LOG_EMOJIS.get(category_name, ''))
# Record-Objekt modifizieren (aber temporär)
original_levelname = record.levelname
original_name = record.name
# Emojis hinzufügen
record.levelname = f"{level_emoji} {level_name}"
record.name = f"{category_emoji} {category_name}"
# Farbe hinzufügen wenn unterstützt
if USE_COLORS:
level_color = self.level_colors.get(original_levelname, ANSI_COLORS['RESET'])
record.levelname = f"{level_color}{record.levelname}{ANSI_COLORS['RESET']}"
record.name = f"{ANSI_COLORS['BOLD']}{record.name}{ANSI_COLORS['RESET']}"
# Formatieren
result = super().format(record)
# Originale Werte wiederherstellen
record.levelname = original_levelname
record.name = original_name
return result
try:
# Basis-Format erstellen
log_fmt = LOG_FORMAT
date_fmt = LOG_DATE_FORMAT
# Emoji dem Level und der Kategorie hinzufügen
level_name = record.levelname
category_name = record.name.split('.')[-1] if '.' in record.name else record.name
level_emoji = safe_emoji(LOG_EMOJIS.get(level_name, ''))
category_emoji = safe_emoji(LOG_EMOJIS.get(category_name, ''))
# Record-Objekt modifizieren (aber temporär)
original_levelname = record.levelname
original_name = record.name
# Emojis hinzufügen
record.levelname = f"{level_emoji} {level_name}"
record.name = f"{category_emoji} {category_name}"
# Farbe hinzufügen wenn unterstützt
if USE_COLORS:
level_color = self.level_colors.get(original_levelname, ANSI_COLORS['RESET'])
record.levelname = f"{level_color}{record.levelname}{ANSI_COLORS['RESET']}"
record.name = f"{ANSI_COLORS['BOLD']}{record.name}{ANSI_COLORS['RESET']}"
# Formatieren
result = super().format(record)
# Originale Werte wiederherstellen
record.levelname = original_levelname
record.name = original_name
return result
except (UnicodeEncodeError, UnicodeDecodeError, AttributeError) as e:
# Fallback bei Unicode-Problemen: Verwende nur ASCII-Text
original_levelname = record.levelname
original_name = record.name
# Emojis durch ASCII-Fallbacks ersetzen
level_fallback = EMOJI_FALLBACK.get(LOG_EMOJIS.get(original_levelname, ''), '[LOG]')
category_name = record.name.split('.')[-1] if '.' in record.name else record.name
category_fallback = EMOJI_FALLBACK.get(LOG_EMOJIS.get(category_name, ''), '[CAT]')
record.levelname = f"{level_fallback} {original_levelname}"
record.name = f"{category_fallback} {category_name}"
# Basis-Formatierung ohne Farben
result = super().format(record)
# Originale Werte wiederherstellen
record.levelname = original_levelname
record.name = original_name
return result
class DebugInfoFilter(logging.Filter):
"""Filter, der Debug-Informationen zu jedem Log-Eintrag hinzufügt."""
@ -228,12 +260,20 @@ def setup_logging(debug_mode: bool = False):
console_handler.setLevel(log_level)
console_handler.setFormatter(colored_formatter)
console_handler.addFilter(debug_filter)
# Windows PowerShell UTF-8 Encoding-Unterstützung
if os.name == 'nt' and hasattr(console_handler.stream, 'reconfigure'):
try:
console_handler.stream.reconfigure(encoding='utf-8')
except:
pass
root_logger.addHandler(console_handler)
# File Handler für allgemeine App-Logs
app_log_file = get_log_file("app")
app_handler = logging.handlers.RotatingFileHandler(
app_log_file, maxBytes=10*1024*1024, backupCount=5
app_log_file, maxBytes=10*1024*1024, backupCount=5, encoding='utf-8'
)
app_handler.setLevel(log_level)
app_handler.setFormatter(file_formatter)
@ -276,12 +316,20 @@ def get_logger(category: str) -> logging.Logger:
console_handler.setLevel(getattr(logging, LOG_LEVEL))
console_handler.setFormatter(colored_formatter)
console_handler.addFilter(debug_filter)
# Windows PowerShell UTF-8 Encoding-Unterstützung
if os.name == 'nt' and hasattr(console_handler.stream, 'reconfigure'):
try:
console_handler.stream.reconfigure(encoding='utf-8')
except:
pass
logger.addHandler(console_handler)
# File Handler für spezifische Kategorie
log_file = get_log_file(category)
file_handler = logging.handlers.RotatingFileHandler(
log_file, maxBytes=10*1024*1024, backupCount=5
log_file, maxBytes=10*1024*1024, backupCount=5, encoding='utf-8'
)
file_handler.setLevel(getattr(logging, LOG_LEVEL))
file_handler.setFormatter(file_formatter)
@ -291,7 +339,7 @@ def get_logger(category: str) -> logging.Logger:
if category != "errors":
error_log_file = get_log_file("errors")
error_handler = logging.handlers.RotatingFileHandler(
error_log_file, maxBytes=10*1024*1024, backupCount=5
error_log_file, maxBytes=10*1024*1024, backupCount=5, encoding='utf-8'
)
error_handler.setLevel(logging.ERROR)
error_handler.setFormatter(file_formatter)