Source code for finesse.utilities.logging

"""Loging utilities."""

import logging
from contextlib import contextmanager
from fnmatch import fnmatch


[docs]@contextmanager def logs(logger, level=None, handler=None, close=True): """Emit logs at or above `level` in the encapsulated context, optionally using the specified `handler`. See `the Python logging cookbook <https://docs.python.org/3/howto/logging-cookbook.html#using-a-context-manager-for-selective-logging>`__ for more information. Parameters ---------- logger : :class:`logging.Logger` The logger to use for the encapsulated context. level : str or int, optional The minimum log levels to emit. The standard log levels "debug", "info", "warning", "error" and "critical" are supported, as are their corresponding level numbers (see :mod:`logging`). handler : :class:`logging.LogHandler`, optional The handler to add to `logger` for the encapsulated context. close : bool, optional Close `handler` once finished. Defaults to `True`. Examples -------- Print debug logs during parsing, excluding compilation messages. >>> import logging >>> from finesse import Model >>> from finesse.utilities import logs >>> from finesse.utilities.logging import FinesseStreamHandler >>> handler = FinesseStreamHandler() >>> handler.exclude("finesse.script.compiler") >>> model = Model() >>> with logs(logging.getLogger(), level="debug", handler=handler): >>> model.parse("laser l1 P=1") """ old_level = None if level is not None: try: # Convert level name to uppercase. level = level.upper() except AttributeError: # Probably a number. pass old_level = logger.level logger.setLevel(level) if handler: logger.addHandler(handler) yield if level is not None: logger.setLevel(old_level) if handler: logger.removeHandler(handler) if close: handler.close()
[docs]@contextmanager def tracebacks(tracebacks=True): """Show or hide tracebacks in the encapsulated context. Some environments, such as Jupyterlab, hide tracebacks by default. This context allows tracebacks to be forcefully shown or hidden temporarily. Parameters ---------- tracebacks : bool, optional Show tracebacks. Defaults to True. Examples -------- Print tracebacks during a run. >>> from finesse import Model >>> from finesse.utilities import tracebacks >>> model = Model() >>> with tracebacks(): >>> model.parse("laser l1 L=1") """ from .. import show_tracebacks old_tracebacks = show_tracebacks(tracebacks) yield show_tracebacks(old_tracebacks)
[docs]class FinesseStreamHandler(logging.StreamHandler): """Finesse stream handler. This class provides a mechanism to exclude displayed log channels by wildcard. It is otherwise identical to :class:`logging.StreamHandler`. """
[docs] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.__excluded_channels = None self.reset_exclude_patterns()
[docs] def exclude(self, pattern): self.__excluded_channels.add(pattern)
[docs] def reset_exclude_patterns(self): """Empty the configured log channel exclude patterns, and return what was there.""" old_excludes = set(self.__excluded_channels or []) self.__excluded_channels = set() return old_excludes
[docs] def filter(self, record): for pattern in self.__excluded_channels: if fnmatch(record.name, pattern): # Skip the record. return return record