supaernova.logging
[docs]
module
supaernova.logging
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 | # Copyright 2025 Patrick Armstrong
import sys
from typing import TYPE_CHECKING
import logging
import coloredlogs
if TYPE_CHECKING:
from pathlib import Path
def setup_logging(
module: str,
*, # Force keyword-only arguments
log_path: "Path | None" = None,
verbose: bool = False,
) -> logging.Logger:
logger = logging.getLogger(module)
logger.setLevel(logging.DEBUG)
logger.propagate = False
# Clear existing handlers
while logger.handlers:
logger.handlers.pop()
# --- Formatting ---
debug_fmt = "[%(levelname)8s] %(filename)10s | %(message)s"
info_fmt = "%(message)s"
level_styles = coloredlogs.parse_encoded_styles(
"debug=8;info=green;warning=yellow;error=red,bold;critical=red,inverse"
)
# --- Stream Handler ---
# Set level and formatting
stream_level = logging.DEBUG if verbose else logging.INFO
stream_fmt = coloredlogs.ColoredFormatter(
debug_fmt if verbose else info_fmt, level_styles=level_styles
)
# Initialise file handler
stream_handler = logging.StreamHandler(stream=sys.stdout)
stream_handler.setLevel(stream_level)
stream_handler.setFormatter(stream_fmt)
logger.addHandler(stream_handler)
# --- File Handler ---
if log_path is not None:
# Determine output log file
if log_path.is_dir():
log_path /= f"{module}.log"
# Ensure directory exists
log_path.parent.mkdir(parents=True, exist_ok=True)
# Set level and formatting
file_level = logging.DEBUG
file_fmt = logging.Formatter(debug_fmt)
# Initialise file handler
file_handler = logging.FileHandler(log_path, mode="w")
file_handler.setLevel(file_level)
file_handler.setFormatter(file_fmt)
logger.addHandler(file_handler)
return logger
|