Source code for arcade._logging

"""Centralized logging and progress-bar utilities for ARCADE.

Usage in any ARCADE module::

    from arcade._logging import get_logger, tqdm
    log = get_logger(__name__)

    log.info("Starting sweep with %d lengths", n)
    for length in tqdm(lengths, desc="Sweep"):
        ...
"""

from __future__ import annotations

import logging
import sys

try:
    from tqdm.auto import tqdm as _tqdm_auto
except ImportError:

    def _tqdm_auto(iterable=None, **kwargs):
        """Fallback identity wrapper when tqdm is not installed."""
        return iterable if iterable is not None else iter(())


__all__ = ["get_logger", "tqdm", "configure_logging"]

_ROOT_LOGGER_NAME = "arcade"

_root = logging.getLogger(_ROOT_LOGGER_NAME)
if not _root.handlers:
    _handler = logging.StreamHandler(sys.stderr)
    _handler.setFormatter(
        logging.Formatter(
            "[%(levelname)s] %(name)s: %(message)s",
        )
    )
    _root.addHandler(_handler)
    _root.setLevel(logging.WARNING)


def get_logger(name: str) -> logging.Logger:
    """Return a child logger under the ``arcade`` namespace.

    Args:
        name: Typically ``__name__`` of the calling module. If it already
            starts with ``arcade.``, it is used as-is; otherwise it is
            prefixed with ``arcade.``.

    Returns:
        A ``logging.Logger`` instance.
    """
    if name.startswith(f"{_ROOT_LOGGER_NAME}."):
        return logging.getLogger(name)
    return logging.getLogger(f"{_ROOT_LOGGER_NAME}.{name}")


[docs] def configure_logging(level: int | str = logging.INFO) -> None: """Set the ARCADE root logger level for convenience. Args: level: A ``logging`` level (e.g. ``logging.DEBUG``, ``"INFO"``). """ if isinstance(level, str): level = getattr(logging, level.upper()) _root.setLevel(level)
tqdm = _tqdm_auto