Implement configuration management, drag-and-drop functionality, and logging utilities for WebDrop Bridge

This commit is contained in:
claudi 2026-01-28 11:21:11 +01:00
parent 04ef84cf9a
commit 6bef2f6119
9 changed files with 1154 additions and 0 deletions

View file

@ -0,0 +1,100 @@
"""Logging configuration and utilities for WebDrop Bridge."""
import logging
import logging.handlers
from pathlib import Path
from typing import Optional
def setup_logging(
name: str = "webdrop_bridge",
level: str = "INFO",
log_file: Optional[Path] = None,
fmt: Optional[str] = None,
) -> logging.Logger:
"""Configure application-wide logging.
Sets up both console and file logging (if enabled). All loggers in the
application should use this configured root logger.
Args:
name: Logger name (typically module name or app name)
level: Logging level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
log_file: Optional path to log file. If provided, logs will be written
to this file in addition to console
fmt: Optional custom format string. If None, uses default format.
Default: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
Returns:
logging.Logger: Configured logger instance
Raises:
ValueError: If log_file path is invalid or can't be created
KeyError: If level is not a valid logging level
"""
# Validate logging level
try:
numeric_level = getattr(logging, level.upper())
except AttributeError as e:
raise KeyError(f"Invalid logging level: {level}") from e
# Use default format if not provided
if fmt is None:
fmt = "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
# Create formatter
formatter = logging.Formatter(fmt)
# Get or create logger
logger = logging.getLogger(name)
logger.setLevel(numeric_level)
# Remove existing handlers to avoid duplicates
logger.handlers.clear()
# Add console handler
console_handler = logging.StreamHandler()
console_handler.setLevel(numeric_level)
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
# Add file handler if log file specified
if log_file:
try:
# Create parent directories if needed
log_file.parent.mkdir(parents=True, exist_ok=True)
# Use rotating file handler to manage log file size
# Max 10 MB per file, keep 5 backups
file_handler = logging.handlers.RotatingFileHandler(
log_file,
maxBytes=10 * 1024 * 1024, # 10 MB
backupCount=5,
encoding="utf-8",
)
file_handler.setLevel(numeric_level)
file_handler.setFormatter(formatter)
logger.addHandler(file_handler)
except (OSError, IOError) as e:
raise ValueError(f"Cannot write to log file {log_file}: {e}") from e
return logger
def get_logger(name: str = __name__) -> logging.Logger:
"""Get a logger instance for a module.
Convenience function to get a logger for a specific module.
Use this in your modules to get properly named loggers.
Example:
logger = get_logger(__name__)
Args:
name: Logger name, typically __name__ of the calling module
Returns:
logging.Logger: Logger instance for the given name
"""
return logging.getLogger(name)