Skip to content

naneos.logger.custom_logger

Logging setup of the naneos package.

The package follows the library convention: every module logs to a logger below "naneos" and the package itself installs only a NullHandler, so nothing is printed unless the application configures logging. Two helpers make the common cases one call: enable_console_logging() and enable_file_logging().

CustomFormatter

Bases: Formatter

The naneos log line, optionally coloured by level for terminals.

Source code in src/naneos/logger/custom_logger.py
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class CustomFormatter(logging.Formatter):
    """The naneos log line, optionally coloured by level for terminals."""

    def __init__(self, terminal: bool = False, fmt: str | None = None) -> None:
        fmt = fmt or _FORMAT
        super().__init__(fmt=fmt)
        self._by_level: dict[int, logging.Formatter] = {}
        if terminal:
            self._by_level = {
                level: logging.Formatter(f"{color} {fmt} {_RESET}")
                for level, color in _COLORS.items()
            }

    def format(self, record: logging.LogRecord) -> str:
        formatter = self._by_level.get(record.levelno)
        if formatter is None:
            return super().format(record)
        return formatter.format(record)

enable_console_logging(level=logging.INFO, colored=True)

Print naneos log messages of at least level to stderr.

Calling it again replaces the previous console handler, so the output is never duplicated. Returns the "naneos" logger.

Source code in src/naneos/logger/custom_logger.py
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
def enable_console_logging(level: int = logging.INFO, colored: bool = True) -> logging.Logger:
    """Print naneos log messages of at least `level` to stderr.

    Calling it again replaces the previous console handler, so the output is
    never duplicated. Returns the "naneos" logger.
    """
    root = logging.getLogger(ROOT_LOGGER_NAME)
    for handler in list(root.handlers):
        if isinstance(handler, _NaneosConsoleHandler):
            root.removeHandler(handler)

    handler = _NaneosConsoleHandler()
    handler.setLevel(level)
    handler.setFormatter(CustomFormatter(terminal=colored))
    root.addHandler(handler)
    _lower_level_to(root, level)
    return root

enable_file_logging(path, level=logging.INFO)

Append naneos log messages of at least level to a file.

path may be a directory, in which case naneos-devices.log is created in it. Calling it again replaces the previous file handler. Returns the "naneos" logger.

Source code in src/naneos/logger/custom_logger.py
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
def enable_file_logging(path: str | Path, level: int = logging.INFO) -> logging.Logger:
    """Append naneos log messages of at least `level` to a file.

    `path` may be a directory, in which case naneos-devices.log is created in
    it. Calling it again replaces the previous file handler. Returns the
    "naneos" logger.
    """
    path = Path(path).resolve()
    if path.is_dir():
        path = path / DEFAULT_LOG_FILE_NAME
    path.parent.mkdir(parents=True, exist_ok=True)

    root = logging.getLogger(ROOT_LOGGER_NAME)
    for handler in list(root.handlers):
        if isinstance(handler, _NaneosFileHandler):
            handler.close()
            root.removeHandler(handler)

    handler = _NaneosFileHandler(str(path))
    handler.setLevel(level)
    handler.setFormatter(CustomFormatter(terminal=False))
    root.addHandler(handler)
    _lower_level_to(root, level)
    return root

get_naneos_logger(name, level=None)

The logger for a naneos module. Handlers and levels are configured by the application (or the enable_* helpers), not by the module.

Parameters:

Name Type Description Default
name str

Usually name of the calling module.

required
level int | None

Optional level for this one logger. Library modules leave it unset so that one setting on the "naneos" logger controls them all.

None
Source code in src/naneos/logger/custom_logger.py
54
55
56
57
58
59
60
61
62
63
64
65
66
def get_naneos_logger(name: str, level: int | None = None) -> logging.Logger:
    """The logger for a naneos module. Handlers and levels are configured by
    the application (or the enable_* helpers), not by the module.

    Args:
        name: Usually __name__ of the calling module.
        level: Optional level for this one logger. Library modules leave it
            unset so that one setting on the "naneos" logger controls them all.
    """
    logger = logging.getLogger(name)
    if level is not None:
        logger.setLevel(level)
    return logger

set_naneos_logger_save_path(path)

Deprecated alias of enable_file_logging(), kept for naneos-devices <= 1.1.x.

Source code in src/naneos/logger/custom_logger.py
114
115
116
def set_naneos_logger_save_path(path: str | Path) -> None:
    """Deprecated alias of enable_file_logging(), kept for naneos-devices <= 1.1.x."""
    enable_file_logging(path)