""" Proper way to intercept stdlib logging: https://github.com/Delgan/loguru/issues/78 """ import io import sys import os.path import traceback import logging from attrdict import AttrDict from loguru import logger from loguru._logger import parse_ansi class InterceptHandler(logging.Handler): def emit(self, record): logger_opt = logger.opt(depth=6, exception=record.exc_info) logger_opt.log(record.levelname, record.getMessage()) if hasattr(sys, '_getframe'): def currentframe(): return sys._getframe(3) else: # pragma: no cover def currentframe(): """Return the frame object for the caller's stack frame.""" try: raise Exception except Exception: return sys.exc_info()[2].tb_frame.f_back _srcfile = ( logging._srcfile, os.path.normcase(parse_ansi.__code__.co_filename), os.path.normcase(currentframe.__code__.co_filename), ) try: import sentry_sdk.integrations.logging except ImportError: pass # ignore else: _srcfile = (sentry_sdk.integrations.logging.__file__, *_srcfile) def findCaller(stack_info=False): """ Find the stack frame of the caller so that we can note the source file name, line number and function name. """ f = currentframe() # On some versions of IronPython, currentframe() returns None if # IronPython isn't run with -X:Frames. if f is not None: f = f.f_back rv = "(unknown file)", 0, "(unknown function)", None while hasattr(f, "f_code"): co = f.f_code filename = os.path.normcase(co.co_filename) if filename in _srcfile: f = f.f_back continue sinfo = None if stack_info: sio = io.StringIO() sio.write('Stack (most recent call last):\n') traceback.print_stack(f, file=sio) sinfo = sio.getvalue() if sinfo[-1] == '\n': sinfo = sinfo[:-1] sio.close() rv = (co.co_filename, f.f_lineno, co.co_name, sinfo) break try: name = f.f_globals["__name__"] except KeyError: name = rv[3] return (name, *rv) def fixed_get_frame(depth=None): try: name, fn, lno, func, sinfo = findCaller(stack_info=False) except ValueError: # pragma: no cover fn, lno, func = "(unknown file)", 0, "(unknown function)" name = func frame = AttrDict( f_globals=dict(__name__=name), f_lineno=lno, f_code=AttrDict( co_filename=fn, co_name=func, ) ) return frame def loguru_patch(): import loguru._logger import loguru._get_frame loguru._get_frame.get_frame = fixed_get_frame loguru._logger.get_frame = fixed_get_frame