Source code for univention.debug

#!/usr/bin/python3
#
# Univention Debug
#  debug.py
#
# SPDX-FileCopyrightText: 2004-2025 Univention GmbH
# SPDX-License-Identifier: AGPL-3.0-only
"""
Univention debugging and logging library.

example:

>>> f = init('stdout', NO_FLUSH, FUNCTION) #doctest: +ELLIPSIS
... ...  DEBUG_INIT
>>> set_level(LISTENER, ERROR)
"""


import sys
from functools import wraps
from itertools import chain
from warnings import warn

from univention import _debug
from univention._debug import (
    ACL, ADMIN, ALL, AUTH, CONFIG, DEBUG, DHCP, ERROR, FLUSH, FUNCTION, INFO, KERBEROS, LDAP, LICENSE, LISTENER, LOCALE,
    MAIN, MODULE, NETWORK, NO_FLUSH, NO_FUNCTION, PARSER, POLICY, PROCESS, PROTOCOL, RESOURCES, SEARCH, SLAPD, SSL,
    TRACE, TRANSFILE, USERS, WARN, begin, end, exit, get_level, init, reopen, set_function, set_level, set_structured,
)


__all__ = ('ACL', 'ADMIN', 'ALL', 'AUTH', 'CONFIG', 'DEBUG', 'DHCP', 'ERROR', 'FLUSH', 'FUNCTION', 'INFO', 'KERBEROS', 'LDAP', 'LICENSE', 'LISTENER', 'LOCALE', 'MAIN', 'MODULE', 'NETWORK', 'NO_FLUSH', 'NO_FUNCTION', 'PARSER', 'POLICY', 'PROCESS', 'PROTOCOL', 'RESOURCES', 'SEARCH', 'SLAPD', 'SSL', 'TRACE', 'TRANSFILE', 'USERS', 'WARN', 'begin', 'debug', 'debug', 'end', 'exit', 'function', 'get_level', 'init', 'reopen', 'set_function', 'set_level', 'set_structured', 'trace')


[docs] def debug(category, level, message, utf8=True): """ Log message 'message' of severity 'level' to facility 'category'. :param int category: ID of the category, e.g. MAIN, LDAP, USERS, ... :param int level: Level of logging, e.g. ERROR, WARN, PROCESS, INFO, ALL :param str message: The message to log. :param bool utf8: Assume the message is UTF-8 encoded. >>> debug(LISTENER, ERROR, 'Fatal error: var=%s' % 42) #doctest: +ELLIPSIS ... ... LISTENER ( ERROR ) : Fatal error: var=42 """ _debug.debug(category, level, message)
[docs] class function: """ Log function call begin and end. :param str fname: name of the function starting. :param bool utf8: Assume the message is UTF-8 encoded. .. deprecated:: 4.4 Use function decorator :py:func:`trace` instead. >>> def my_func(agr1, agr2=None): ... _d = function('my_func(...)') # noqa: F841 ... return 'yes' >>> my_func(42) 'yes' """ def __init__(self, fname, utf8=True): warn('univention.debug.function is deprecated and will be removed with UCS-5', PendingDeprecationWarning, stacklevel=2) self.fname = fname _debug.begin(self.fname) def __del__(self): """Log the end of function.""" _debug.end(self.fname)
[docs] def trace(with_args=True, with_return=False, repr=object.__repr__): """ Log function call, optional with arguments and result. :param bool with_args: Log function arguments. :param bool with_return: Log function result. :param repr: Function accepting a single object and returing a string representation for the given object. Defaults to :py:func:`object.__repr__`, alternative :py:func:`repr`. >>> @trace(with_args=True, with_return=True) ... def my_func(arg1, arg2=None): ... return 'yes' >>> my_func(42) 'yes' >>> class MyClass(object): ... @trace(with_args=True, with_return=True, repr=repr) ... def my_meth(self, arg1, arg2=None): ... return 'yes' >>> MyClass().my_meth(42) 'yes' >>> @trace() ... def my_bug(): ... 1 / 0 >>> my_bug() Traceback (most recent call last): ... ZeroDivisionError: integer division or modulo by zero """ def decorator(f): @wraps(f) def wrapper(*args, **kwargs): fname = '%s.%s' % (f.__module__, f.__name__) _args = ', '.join( chain( (repr(arg) for arg in args), ('%s=%s' % (k, repr(v)) for (k, v) in kwargs.items()), ), ) if with_args else '...' _debug.begin('%s(%s): ...' % (fname, _args)) try: ret = f(*args, **kwargs) except BaseException: try: (exctype, value) = sys.exc_info()[:2] _debug.end('%s(...): %s(%s)' % (fname, exctype, value)) finally: exctype = value = None raise else: _debug.end('%s(...): %s' % (fname, repr(ret) if with_return else '...')) return ret return wrapper return decorator
if __name__ == '__main__': # pragma: no cover import doctest doctest.testmod()