Skip to content

logging

napt.logging

Logging interface for NAPT.

This module provides a configurable logging interface that all NAPT modules use for output. The logger can be configured globally by the CLI or passed as a parameter for better isolation in tests.

The logger supports six output levels:

  • Step: Always printed (for major pipeline stages)
  • Info: Always printed (for notable events that are not warnings)
  • Warning: Always printed (for important warnings that users should see)
  • Progress: Always printed with carriage return (for download/upload progress)
  • Verbose: Only printed when verbose mode is enabled
  • Debug: Only printed when debug mode is enabled (implies verbose)
Example

Configure global logger:

from napt.logging import get_logger, set_global_logger

logger = get_logger(verbose=True, debug=False)
set_global_logger(logger)

Use in a module:

from napt.logging import get_logger

logger = get_logger()
logger.step(1, 4, "Loading configuration...")
logger.info("PACKAGE", "Removing previous package: 144.0.0")
logger.warning("DETECTION", "Could not extract MSI metadata")
logger.progress("DOWNLOAD", "42%")
logger.verbose("STATE", "Loaded state from file")
logger.debug("VERSION", "Trying backend: msilib...")

Use with dependency injection:

def my_function(logger=None):
    if logger is None:
        logger = get_logger()
    logger.verbose("MODULE", "Processing...")
Note

The CLI configures the global logger when commands are executed. The default logger is non-verbose, so verbose and debug messages are suppressed unless explicitly enabled.

Logger

Bases: Protocol

Protocol for logger implementations.

Source code in napt/logging.py
class Logger(Protocol):
    """Protocol for logger implementations."""

    def step(self, step: int, total: int, message: str) -> None:
        """Print a step indicator for non-verbose mode.

        Args:
            step: Current step number (1-based).
            total: Total number of steps.
            message: Step description.
        """
        ...

    def info(self, prefix: str, message: str) -> None:
        """Print an informational message (always visible).

        Use for notable events that are not warnings — e.g., replacing a
        previous artifact, skipping a step for a known reason.

        Args:
            prefix: Message prefix (e.g., "PACKAGE", "BUILD").
            message: Informational message.
        """
        ...

    def warning(self, prefix: str, message: str) -> None:
        """Print a warning message (always visible).

        Args:
            prefix: Message prefix (e.g., "DETECTION", "BUILD").
            message: Warning message.
        """
        ...

    def progress(self, prefix: str, message: str) -> None:
        """Print a progress message, overwriting the current line.

        Used for download and upload progress that updates in place.
        Always visible regardless of verbosity settings.

        Args:
            prefix: Message prefix (e.g., "DOWNLOAD", "UPLOAD").
            message: Progress message (e.g., "42%").
        """
        ...

    def verbose(self, prefix: str, message: str) -> None:
        """Print a verbose log message.

        Args:
            prefix: Message prefix (e.g., "STATE", "BUILD").
            message: Log message.
        """
        ...

    def debug(self, prefix: str, message: str) -> None:
        """Print a debug log message.

        Args:
            prefix: Message prefix (e.g., "VERSION", "HTTP").
            message: Log message.
        """
        ...

step

step(step: int, total: int, message: str) -> None

Print a step indicator for non-verbose mode.

Parameters:

Name Type Description Default
step int

Current step number (1-based).

required
total int

Total number of steps.

required
message str

Step description.

required
Source code in napt/logging.py
def step(self, step: int, total: int, message: str) -> None:
    """Print a step indicator for non-verbose mode.

    Args:
        step: Current step number (1-based).
        total: Total number of steps.
        message: Step description.
    """
    ...

info

info(prefix: str, message: str) -> None

Print an informational message (always visible).

Use for notable events that are not warnings — e.g., replacing a previous artifact, skipping a step for a known reason.

Parameters:

Name Type Description Default
prefix str

Message prefix (e.g., "PACKAGE", "BUILD").

required
message str

Informational message.

required
Source code in napt/logging.py
def info(self, prefix: str, message: str) -> None:
    """Print an informational message (always visible).

    Use for notable events that are not warnings — e.g., replacing a
    previous artifact, skipping a step for a known reason.

    Args:
        prefix: Message prefix (e.g., "PACKAGE", "BUILD").
        message: Informational message.
    """
    ...

warning

warning(prefix: str, message: str) -> None

Print a warning message (always visible).

Parameters:

Name Type Description Default
prefix str

Message prefix (e.g., "DETECTION", "BUILD").

required
message str

Warning message.

required
Source code in napt/logging.py
def warning(self, prefix: str, message: str) -> None:
    """Print a warning message (always visible).

    Args:
        prefix: Message prefix (e.g., "DETECTION", "BUILD").
        message: Warning message.
    """
    ...

progress

progress(prefix: str, message: str) -> None

Print a progress message, overwriting the current line.

Used for download and upload progress that updates in place. Always visible regardless of verbosity settings.

Parameters:

Name Type Description Default
prefix str

Message prefix (e.g., "DOWNLOAD", "UPLOAD").

required
message str

Progress message (e.g., "42%").

required
Source code in napt/logging.py
def progress(self, prefix: str, message: str) -> None:
    """Print a progress message, overwriting the current line.

    Used for download and upload progress that updates in place.
    Always visible regardless of verbosity settings.

    Args:
        prefix: Message prefix (e.g., "DOWNLOAD", "UPLOAD").
        message: Progress message (e.g., "42%").
    """
    ...

verbose

verbose(prefix: str, message: str) -> None

Print a verbose log message.

Parameters:

Name Type Description Default
prefix str

Message prefix (e.g., "STATE", "BUILD").

required
message str

Log message.

required
Source code in napt/logging.py
def verbose(self, prefix: str, message: str) -> None:
    """Print a verbose log message.

    Args:
        prefix: Message prefix (e.g., "STATE", "BUILD").
        message: Log message.
    """
    ...

debug

debug(prefix: str, message: str) -> None

Print a debug log message.

Parameters:

Name Type Description Default
prefix str

Message prefix (e.g., "VERSION", "HTTP").

required
message str

Log message.

required
Source code in napt/logging.py
def debug(self, prefix: str, message: str) -> None:
    """Print a debug log message.

    Args:
        prefix: Message prefix (e.g., "VERSION", "HTTP").
        message: Log message.
    """
    ...

DefaultLogger

Default logger implementation that prints to stdout.

This logger respects verbose and debug flags and formats output consistently with the CLI output format.

Source code in napt/logging.py
class DefaultLogger:
    """Default logger implementation that prints to stdout.

    This logger respects verbose and debug flags and formats output
    consistently with the CLI output format.
    """

    def __init__(self, verbose: bool = False, debug: bool = False) -> None:
        """Initialize logger with verbosity settings.

        Args:
            verbose: If True, print verbose messages.
            debug: If True, print debug messages (implies verbose).
        """
        self._verbose = verbose or debug
        self._debug = debug

    def step(self, step: int, total: int, message: str) -> None:
        """Print a step indicator for non-verbose mode."""
        print(f"[{step}/{total}] {message}")

    def info(self, prefix: str, message: str) -> None:
        """Print an informational message (always visible)."""
        print(f"[{prefix}] {message}")

    def warning(self, prefix: str, message: str) -> None:
        """Print a warning message (always visible)."""
        print(f"[{prefix}] {message}")

    def progress(self, prefix: str, message: str) -> None:
        """Print a progress message, overwriting the current line."""
        print(f"[{prefix}] {message}", end="\r")

    def verbose(self, prefix: str, message: str) -> None:
        """Print a verbose log message (only when verbose mode is active)."""
        if self._verbose:
            print(f"[{prefix}] {message}")

    def debug(self, prefix: str, message: str) -> None:
        """Print a debug log message (only when debug mode is active)."""
        if self._debug:
            print(f"[{prefix}] {message}")

__init__

__init__(verbose: bool = False, debug: bool = False) -> None

Initialize logger with verbosity settings.

Parameters:

Name Type Description Default
verbose bool

If True, print verbose messages.

False
debug bool

If True, print debug messages (implies verbose).

False
Source code in napt/logging.py
def __init__(self, verbose: bool = False, debug: bool = False) -> None:
    """Initialize logger with verbosity settings.

    Args:
        verbose: If True, print verbose messages.
        debug: If True, print debug messages (implies verbose).
    """
    self._verbose = verbose or debug
    self._debug = debug

step

step(step: int, total: int, message: str) -> None

Print a step indicator for non-verbose mode.

Source code in napt/logging.py
def step(self, step: int, total: int, message: str) -> None:
    """Print a step indicator for non-verbose mode."""
    print(f"[{step}/{total}] {message}")

info

info(prefix: str, message: str) -> None

Print an informational message (always visible).

Source code in napt/logging.py
def info(self, prefix: str, message: str) -> None:
    """Print an informational message (always visible)."""
    print(f"[{prefix}] {message}")

warning

warning(prefix: str, message: str) -> None

Print a warning message (always visible).

Source code in napt/logging.py
def warning(self, prefix: str, message: str) -> None:
    """Print a warning message (always visible)."""
    print(f"[{prefix}] {message}")

progress

progress(prefix: str, message: str) -> None

Print a progress message, overwriting the current line.

Source code in napt/logging.py
def progress(self, prefix: str, message: str) -> None:
    """Print a progress message, overwriting the current line."""
    print(f"[{prefix}] {message}", end="\r")

verbose

verbose(prefix: str, message: str) -> None

Print a verbose log message (only when verbose mode is active).

Source code in napt/logging.py
def verbose(self, prefix: str, message: str) -> None:
    """Print a verbose log message (only when verbose mode is active)."""
    if self._verbose:
        print(f"[{prefix}] {message}")

debug

debug(prefix: str, message: str) -> None

Print a debug log message (only when debug mode is active).

Source code in napt/logging.py
def debug(self, prefix: str, message: str) -> None:
    """Print a debug log message (only when debug mode is active)."""
    if self._debug:
        print(f"[{prefix}] {message}")

get_logger

get_logger(verbose: bool = False, debug: bool = False) -> Logger

Get a logger instance with specified verbosity.

Parameters:

Name Type Description Default
verbose bool

If True, logger will print verbose messages.

False
debug bool

If True, logger will print debug messages (implies verbose).

False

Returns:

Type Description
Logger

A logger instance configured with the specified verbosity.

Example

Get a verbose logger:

logger = get_logger(verbose=True)
logger.verbose("MODULE", "Processing...")

Get a debug logger:

logger = get_logger(debug=True)
logger.debug("MODULE", "Debug info...")

Source code in napt/logging.py
def get_logger(verbose: bool = False, debug: bool = False) -> Logger:
    """Get a logger instance with specified verbosity.

    Args:
        verbose: If True, logger will print verbose messages.
        debug: If True, logger will print debug messages (implies verbose).

    Returns:
        A logger instance configured with the specified verbosity.

    Example:
        Get a verbose logger:
            ```python
            logger = get_logger(verbose=True)
            logger.verbose("MODULE", "Processing...")
            ```

        Get a debug logger:
            ```python
            logger = get_logger(debug=True)
            logger.debug("MODULE", "Debug info...")
            ```
    """
    return DefaultLogger(verbose=verbose, debug=debug)

get_global_logger

get_global_logger() -> Logger

Get the global logger instance.

Returns:

Type Description
Logger

The current global logger instance.

Note

The default global logger is silent. Use set_global_logger() to configure it, or pass a logger instance directly to functions.

Source code in napt/logging.py
def get_global_logger() -> Logger:
    """Get the global logger instance.

    Returns:
        The current global logger instance.

    Note:
        The default global logger is silent. Use set_global_logger() to
        configure it, or pass a logger instance directly to functions.
    """
    return _global_logger

set_global_logger

set_global_logger(logger: Logger) -> None

Set the global logger instance.

Parameters:

Name Type Description Default
logger Logger

Logger instance to use as the global logger.

required
Example

Configure global logger from CLI:

from napt.logging import get_logger, set_global_logger

logger = get_logger(verbose=args.verbose, debug=args.debug)
set_global_logger(logger)

Note

This affects all library functions that use get_logger() without passing a logger instance. For better isolation, pass logger instances directly to functions instead of using the global logger.

Source code in napt/logging.py
def set_global_logger(logger: Logger) -> None:
    """Set the global logger instance.

    Args:
        logger: Logger instance to use as the global logger.

    Example:
        Configure global logger from CLI:
            ```python
            from napt.logging import get_logger, set_global_logger

            logger = get_logger(verbose=args.verbose, debug=args.debug)
            set_global_logger(logger)
            ```

    Note:
        This affects all library functions that use get_logger() without
        passing a logger instance. For better isolation, pass logger
        instances directly to functions instead of using the global logger.
    """
    global _global_logger
    _global_logger = logger