17db96d56Sopenharmony_ci# Copyright 2001-2019 by Vinay Sajip. All Rights Reserved. 27db96d56Sopenharmony_ci# 37db96d56Sopenharmony_ci# Permission to use, copy, modify, and distribute this software and its 47db96d56Sopenharmony_ci# documentation for any purpose and without fee is hereby granted, 57db96d56Sopenharmony_ci# provided that the above copyright notice appear in all copies and that 67db96d56Sopenharmony_ci# both that copyright notice and this permission notice appear in 77db96d56Sopenharmony_ci# supporting documentation, and that the name of Vinay Sajip 87db96d56Sopenharmony_ci# not be used in advertising or publicity pertaining to distribution 97db96d56Sopenharmony_ci# of the software without specific, written prior permission. 107db96d56Sopenharmony_ci# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 117db96d56Sopenharmony_ci# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL 127db96d56Sopenharmony_ci# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 137db96d56Sopenharmony_ci# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 147db96d56Sopenharmony_ci# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 157db96d56Sopenharmony_ci# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 167db96d56Sopenharmony_ci 177db96d56Sopenharmony_ci""" 187db96d56Sopenharmony_ciLogging package for Python. Based on PEP 282 and comments thereto in 197db96d56Sopenharmony_cicomp.lang.python. 207db96d56Sopenharmony_ci 217db96d56Sopenharmony_ciCopyright (C) 2001-2019 Vinay Sajip. All Rights Reserved. 227db96d56Sopenharmony_ci 237db96d56Sopenharmony_ciTo use, simply 'import logging' and log away! 247db96d56Sopenharmony_ci""" 257db96d56Sopenharmony_ci 267db96d56Sopenharmony_ciimport sys, os, time, io, re, traceback, warnings, weakref, collections.abc 277db96d56Sopenharmony_ci 287db96d56Sopenharmony_cifrom types import GenericAlias 297db96d56Sopenharmony_cifrom string import Template 307db96d56Sopenharmony_cifrom string import Formatter as StrFormatter 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ci 337db96d56Sopenharmony_ci__all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR', 347db96d56Sopenharmony_ci 'FATAL', 'FileHandler', 'Filter', 'Formatter', 'Handler', 'INFO', 357db96d56Sopenharmony_ci 'LogRecord', 'Logger', 'LoggerAdapter', 'NOTSET', 'NullHandler', 367db96d56Sopenharmony_ci 'StreamHandler', 'WARN', 'WARNING', 'addLevelName', 'basicConfig', 377db96d56Sopenharmony_ci 'captureWarnings', 'critical', 'debug', 'disable', 'error', 387db96d56Sopenharmony_ci 'exception', 'fatal', 'getLevelName', 'getLogger', 'getLoggerClass', 397db96d56Sopenharmony_ci 'info', 'log', 'makeLogRecord', 'setLoggerClass', 'shutdown', 407db96d56Sopenharmony_ci 'warn', 'warning', 'getLogRecordFactory', 'setLogRecordFactory', 417db96d56Sopenharmony_ci 'lastResort', 'raiseExceptions', 'getLevelNamesMapping'] 427db96d56Sopenharmony_ci 437db96d56Sopenharmony_ciimport threading 447db96d56Sopenharmony_ci 457db96d56Sopenharmony_ci__author__ = "Vinay Sajip <vinay_sajip@red-dove.com>" 467db96d56Sopenharmony_ci__status__ = "production" 477db96d56Sopenharmony_ci# The following module attributes are no longer updated. 487db96d56Sopenharmony_ci__version__ = "0.5.1.2" 497db96d56Sopenharmony_ci__date__ = "07 February 2010" 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 527db96d56Sopenharmony_ci# Miscellaneous module data 537db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 547db96d56Sopenharmony_ci 557db96d56Sopenharmony_ci# 567db96d56Sopenharmony_ci#_startTime is used as the base when calculating the relative time of events 577db96d56Sopenharmony_ci# 587db96d56Sopenharmony_ci_startTime = time.time() 597db96d56Sopenharmony_ci 607db96d56Sopenharmony_ci# 617db96d56Sopenharmony_ci#raiseExceptions is used to see if exceptions during handling should be 627db96d56Sopenharmony_ci#propagated 637db96d56Sopenharmony_ci# 647db96d56Sopenharmony_ciraiseExceptions = True 657db96d56Sopenharmony_ci 667db96d56Sopenharmony_ci# 677db96d56Sopenharmony_ci# If you don't want threading information in the log, set this to zero 687db96d56Sopenharmony_ci# 697db96d56Sopenharmony_cilogThreads = True 707db96d56Sopenharmony_ci 717db96d56Sopenharmony_ci# 727db96d56Sopenharmony_ci# If you don't want multiprocessing information in the log, set this to zero 737db96d56Sopenharmony_ci# 747db96d56Sopenharmony_cilogMultiprocessing = True 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_ci# 777db96d56Sopenharmony_ci# If you don't want process information in the log, set this to zero 787db96d56Sopenharmony_ci# 797db96d56Sopenharmony_cilogProcesses = True 807db96d56Sopenharmony_ci 817db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 827db96d56Sopenharmony_ci# Level related stuff 837db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 847db96d56Sopenharmony_ci# 857db96d56Sopenharmony_ci# Default levels and level names, these can be replaced with any positive set 867db96d56Sopenharmony_ci# of values having corresponding names. There is a pseudo-level, NOTSET, which 877db96d56Sopenharmony_ci# is only really there as a lower limit for user-defined levels. Handlers and 887db96d56Sopenharmony_ci# loggers are initialized with NOTSET so that they will log all messages, even 897db96d56Sopenharmony_ci# at user-defined levels. 907db96d56Sopenharmony_ci# 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ciCRITICAL = 50 937db96d56Sopenharmony_ciFATAL = CRITICAL 947db96d56Sopenharmony_ciERROR = 40 957db96d56Sopenharmony_ciWARNING = 30 967db96d56Sopenharmony_ciWARN = WARNING 977db96d56Sopenharmony_ciINFO = 20 987db96d56Sopenharmony_ciDEBUG = 10 997db96d56Sopenharmony_ciNOTSET = 0 1007db96d56Sopenharmony_ci 1017db96d56Sopenharmony_ci_levelToName = { 1027db96d56Sopenharmony_ci CRITICAL: 'CRITICAL', 1037db96d56Sopenharmony_ci ERROR: 'ERROR', 1047db96d56Sopenharmony_ci WARNING: 'WARNING', 1057db96d56Sopenharmony_ci INFO: 'INFO', 1067db96d56Sopenharmony_ci DEBUG: 'DEBUG', 1077db96d56Sopenharmony_ci NOTSET: 'NOTSET', 1087db96d56Sopenharmony_ci} 1097db96d56Sopenharmony_ci_nameToLevel = { 1107db96d56Sopenharmony_ci 'CRITICAL': CRITICAL, 1117db96d56Sopenharmony_ci 'FATAL': FATAL, 1127db96d56Sopenharmony_ci 'ERROR': ERROR, 1137db96d56Sopenharmony_ci 'WARN': WARNING, 1147db96d56Sopenharmony_ci 'WARNING': WARNING, 1157db96d56Sopenharmony_ci 'INFO': INFO, 1167db96d56Sopenharmony_ci 'DEBUG': DEBUG, 1177db96d56Sopenharmony_ci 'NOTSET': NOTSET, 1187db96d56Sopenharmony_ci} 1197db96d56Sopenharmony_ci 1207db96d56Sopenharmony_cidef getLevelNamesMapping(): 1217db96d56Sopenharmony_ci return _nameToLevel.copy() 1227db96d56Sopenharmony_ci 1237db96d56Sopenharmony_cidef getLevelName(level): 1247db96d56Sopenharmony_ci """ 1257db96d56Sopenharmony_ci Return the textual or numeric representation of logging level 'level'. 1267db96d56Sopenharmony_ci 1277db96d56Sopenharmony_ci If the level is one of the predefined levels (CRITICAL, ERROR, WARNING, 1287db96d56Sopenharmony_ci INFO, DEBUG) then you get the corresponding string. If you have 1297db96d56Sopenharmony_ci associated levels with names using addLevelName then the name you have 1307db96d56Sopenharmony_ci associated with 'level' is returned. 1317db96d56Sopenharmony_ci 1327db96d56Sopenharmony_ci If a numeric value corresponding to one of the defined levels is passed 1337db96d56Sopenharmony_ci in, the corresponding string representation is returned. 1347db96d56Sopenharmony_ci 1357db96d56Sopenharmony_ci If a string representation of the level is passed in, the corresponding 1367db96d56Sopenharmony_ci numeric value is returned. 1377db96d56Sopenharmony_ci 1387db96d56Sopenharmony_ci If no matching numeric or string value is passed in, the string 1397db96d56Sopenharmony_ci 'Level %s' % level is returned. 1407db96d56Sopenharmony_ci """ 1417db96d56Sopenharmony_ci # See Issues #22386, #27937 and #29220 for why it's this way 1427db96d56Sopenharmony_ci result = _levelToName.get(level) 1437db96d56Sopenharmony_ci if result is not None: 1447db96d56Sopenharmony_ci return result 1457db96d56Sopenharmony_ci result = _nameToLevel.get(level) 1467db96d56Sopenharmony_ci if result is not None: 1477db96d56Sopenharmony_ci return result 1487db96d56Sopenharmony_ci return "Level %s" % level 1497db96d56Sopenharmony_ci 1507db96d56Sopenharmony_cidef addLevelName(level, levelName): 1517db96d56Sopenharmony_ci """ 1527db96d56Sopenharmony_ci Associate 'levelName' with 'level'. 1537db96d56Sopenharmony_ci 1547db96d56Sopenharmony_ci This is used when converting levels to text during message formatting. 1557db96d56Sopenharmony_ci """ 1567db96d56Sopenharmony_ci _acquireLock() 1577db96d56Sopenharmony_ci try: #unlikely to cause an exception, but you never know... 1587db96d56Sopenharmony_ci _levelToName[level] = levelName 1597db96d56Sopenharmony_ci _nameToLevel[levelName] = level 1607db96d56Sopenharmony_ci finally: 1617db96d56Sopenharmony_ci _releaseLock() 1627db96d56Sopenharmony_ci 1637db96d56Sopenharmony_ciif hasattr(sys, "_getframe"): 1647db96d56Sopenharmony_ci currentframe = lambda: sys._getframe(1) 1657db96d56Sopenharmony_cielse: #pragma: no cover 1667db96d56Sopenharmony_ci def currentframe(): 1677db96d56Sopenharmony_ci """Return the frame object for the caller's stack frame.""" 1687db96d56Sopenharmony_ci try: 1697db96d56Sopenharmony_ci raise Exception 1707db96d56Sopenharmony_ci except Exception: 1717db96d56Sopenharmony_ci return sys.exc_info()[2].tb_frame.f_back 1727db96d56Sopenharmony_ci 1737db96d56Sopenharmony_ci# 1747db96d56Sopenharmony_ci# _srcfile is used when walking the stack to check when we've got the first 1757db96d56Sopenharmony_ci# caller stack frame, by skipping frames whose filename is that of this 1767db96d56Sopenharmony_ci# module's source. It therefore should contain the filename of this module's 1777db96d56Sopenharmony_ci# source file. 1787db96d56Sopenharmony_ci# 1797db96d56Sopenharmony_ci# Ordinarily we would use __file__ for this, but frozen modules don't always 1807db96d56Sopenharmony_ci# have __file__ set, for some reason (see Issue #21736). Thus, we get the 1817db96d56Sopenharmony_ci# filename from a handy code object from a function defined in this module. 1827db96d56Sopenharmony_ci# (There's no particular reason for picking addLevelName.) 1837db96d56Sopenharmony_ci# 1847db96d56Sopenharmony_ci 1857db96d56Sopenharmony_ci_srcfile = os.path.normcase(addLevelName.__code__.co_filename) 1867db96d56Sopenharmony_ci 1877db96d56Sopenharmony_ci# _srcfile is only used in conjunction with sys._getframe(). 1887db96d56Sopenharmony_ci# Setting _srcfile to None will prevent findCaller() from being called. This 1897db96d56Sopenharmony_ci# way, you can avoid the overhead of fetching caller information. 1907db96d56Sopenharmony_ci 1917db96d56Sopenharmony_ci# The following is based on warnings._is_internal_frame. It makes sure that 1927db96d56Sopenharmony_ci# frames of the import mechanism are skipped when logging at module level and 1937db96d56Sopenharmony_ci# using a stacklevel value greater than one. 1947db96d56Sopenharmony_cidef _is_internal_frame(frame): 1957db96d56Sopenharmony_ci """Signal whether the frame is a CPython or logging module internal.""" 1967db96d56Sopenharmony_ci filename = os.path.normcase(frame.f_code.co_filename) 1977db96d56Sopenharmony_ci return filename == _srcfile or ( 1987db96d56Sopenharmony_ci "importlib" in filename and "_bootstrap" in filename 1997db96d56Sopenharmony_ci ) 2007db96d56Sopenharmony_ci 2017db96d56Sopenharmony_ci 2027db96d56Sopenharmony_cidef _checkLevel(level): 2037db96d56Sopenharmony_ci if isinstance(level, int): 2047db96d56Sopenharmony_ci rv = level 2057db96d56Sopenharmony_ci elif str(level) == level: 2067db96d56Sopenharmony_ci if level not in _nameToLevel: 2077db96d56Sopenharmony_ci raise ValueError("Unknown level: %r" % level) 2087db96d56Sopenharmony_ci rv = _nameToLevel[level] 2097db96d56Sopenharmony_ci else: 2107db96d56Sopenharmony_ci raise TypeError("Level not an integer or a valid string: %r" 2117db96d56Sopenharmony_ci % (level,)) 2127db96d56Sopenharmony_ci return rv 2137db96d56Sopenharmony_ci 2147db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 2157db96d56Sopenharmony_ci# Thread-related stuff 2167db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_ci# 2197db96d56Sopenharmony_ci#_lock is used to serialize access to shared data structures in this module. 2207db96d56Sopenharmony_ci#This needs to be an RLock because fileConfig() creates and configures 2217db96d56Sopenharmony_ci#Handlers, and so might arbitrary user threads. Since Handler code updates the 2227db96d56Sopenharmony_ci#shared dictionary _handlers, it needs to acquire the lock. But if configuring, 2237db96d56Sopenharmony_ci#the lock would already have been acquired - so we need an RLock. 2247db96d56Sopenharmony_ci#The same argument applies to Loggers and Manager.loggerDict. 2257db96d56Sopenharmony_ci# 2267db96d56Sopenharmony_ci_lock = threading.RLock() 2277db96d56Sopenharmony_ci 2287db96d56Sopenharmony_cidef _acquireLock(): 2297db96d56Sopenharmony_ci """ 2307db96d56Sopenharmony_ci Acquire the module-level lock for serializing access to shared data. 2317db96d56Sopenharmony_ci 2327db96d56Sopenharmony_ci This should be released with _releaseLock(). 2337db96d56Sopenharmony_ci """ 2347db96d56Sopenharmony_ci if _lock: 2357db96d56Sopenharmony_ci _lock.acquire() 2367db96d56Sopenharmony_ci 2377db96d56Sopenharmony_cidef _releaseLock(): 2387db96d56Sopenharmony_ci """ 2397db96d56Sopenharmony_ci Release the module-level lock acquired by calling _acquireLock(). 2407db96d56Sopenharmony_ci """ 2417db96d56Sopenharmony_ci if _lock: 2427db96d56Sopenharmony_ci _lock.release() 2437db96d56Sopenharmony_ci 2447db96d56Sopenharmony_ci 2457db96d56Sopenharmony_ci# Prevent a held logging lock from blocking a child from logging. 2467db96d56Sopenharmony_ci 2477db96d56Sopenharmony_ciif not hasattr(os, 'register_at_fork'): # Windows and friends. 2487db96d56Sopenharmony_ci def _register_at_fork_reinit_lock(instance): 2497db96d56Sopenharmony_ci pass # no-op when os.register_at_fork does not exist. 2507db96d56Sopenharmony_cielse: 2517db96d56Sopenharmony_ci # A collection of instances with a _at_fork_reinit method (logging.Handler) 2527db96d56Sopenharmony_ci # to be called in the child after forking. The weakref avoids us keeping 2537db96d56Sopenharmony_ci # discarded Handler instances alive. 2547db96d56Sopenharmony_ci _at_fork_reinit_lock_weakset = weakref.WeakSet() 2557db96d56Sopenharmony_ci 2567db96d56Sopenharmony_ci def _register_at_fork_reinit_lock(instance): 2577db96d56Sopenharmony_ci _acquireLock() 2587db96d56Sopenharmony_ci try: 2597db96d56Sopenharmony_ci _at_fork_reinit_lock_weakset.add(instance) 2607db96d56Sopenharmony_ci finally: 2617db96d56Sopenharmony_ci _releaseLock() 2627db96d56Sopenharmony_ci 2637db96d56Sopenharmony_ci def _after_at_fork_child_reinit_locks(): 2647db96d56Sopenharmony_ci for handler in _at_fork_reinit_lock_weakset: 2657db96d56Sopenharmony_ci handler._at_fork_reinit() 2667db96d56Sopenharmony_ci 2677db96d56Sopenharmony_ci # _acquireLock() was called in the parent before forking. 2687db96d56Sopenharmony_ci # The lock is reinitialized to unlocked state. 2697db96d56Sopenharmony_ci _lock._at_fork_reinit() 2707db96d56Sopenharmony_ci 2717db96d56Sopenharmony_ci os.register_at_fork(before=_acquireLock, 2727db96d56Sopenharmony_ci after_in_child=_after_at_fork_child_reinit_locks, 2737db96d56Sopenharmony_ci after_in_parent=_releaseLock) 2747db96d56Sopenharmony_ci 2757db96d56Sopenharmony_ci 2767db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 2777db96d56Sopenharmony_ci# The logging record 2787db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 2797db96d56Sopenharmony_ci 2807db96d56Sopenharmony_ciclass LogRecord(object): 2817db96d56Sopenharmony_ci """ 2827db96d56Sopenharmony_ci A LogRecord instance represents an event being logged. 2837db96d56Sopenharmony_ci 2847db96d56Sopenharmony_ci LogRecord instances are created every time something is logged. They 2857db96d56Sopenharmony_ci contain all the information pertinent to the event being logged. The 2867db96d56Sopenharmony_ci main information passed in is in msg and args, which are combined 2877db96d56Sopenharmony_ci using str(msg) % args to create the message field of the record. The 2887db96d56Sopenharmony_ci record also includes information such as when the record was created, 2897db96d56Sopenharmony_ci the source line where the logging call was made, and any exception 2907db96d56Sopenharmony_ci information to be logged. 2917db96d56Sopenharmony_ci """ 2927db96d56Sopenharmony_ci def __init__(self, name, level, pathname, lineno, 2937db96d56Sopenharmony_ci msg, args, exc_info, func=None, sinfo=None, **kwargs): 2947db96d56Sopenharmony_ci """ 2957db96d56Sopenharmony_ci Initialize a logging record with interesting information. 2967db96d56Sopenharmony_ci """ 2977db96d56Sopenharmony_ci ct = time.time() 2987db96d56Sopenharmony_ci self.name = name 2997db96d56Sopenharmony_ci self.msg = msg 3007db96d56Sopenharmony_ci # 3017db96d56Sopenharmony_ci # The following statement allows passing of a dictionary as a sole 3027db96d56Sopenharmony_ci # argument, so that you can do something like 3037db96d56Sopenharmony_ci # logging.debug("a %(a)d b %(b)s", {'a':1, 'b':2}) 3047db96d56Sopenharmony_ci # Suggested by Stefan Behnel. 3057db96d56Sopenharmony_ci # Note that without the test for args[0], we get a problem because 3067db96d56Sopenharmony_ci # during formatting, we test to see if the arg is present using 3077db96d56Sopenharmony_ci # 'if self.args:'. If the event being logged is e.g. 'Value is %d' 3087db96d56Sopenharmony_ci # and if the passed arg fails 'if self.args:' then no formatting 3097db96d56Sopenharmony_ci # is done. For example, logger.warning('Value is %d', 0) would log 3107db96d56Sopenharmony_ci # 'Value is %d' instead of 'Value is 0'. 3117db96d56Sopenharmony_ci # For the use case of passing a dictionary, this should not be a 3127db96d56Sopenharmony_ci # problem. 3137db96d56Sopenharmony_ci # Issue #21172: a request was made to relax the isinstance check 3147db96d56Sopenharmony_ci # to hasattr(args[0], '__getitem__'). However, the docs on string 3157db96d56Sopenharmony_ci # formatting still seem to suggest a mapping object is required. 3167db96d56Sopenharmony_ci # Thus, while not removing the isinstance check, it does now look 3177db96d56Sopenharmony_ci # for collections.abc.Mapping rather than, as before, dict. 3187db96d56Sopenharmony_ci if (args and len(args) == 1 and isinstance(args[0], collections.abc.Mapping) 3197db96d56Sopenharmony_ci and args[0]): 3207db96d56Sopenharmony_ci args = args[0] 3217db96d56Sopenharmony_ci self.args = args 3227db96d56Sopenharmony_ci self.levelname = getLevelName(level) 3237db96d56Sopenharmony_ci self.levelno = level 3247db96d56Sopenharmony_ci self.pathname = pathname 3257db96d56Sopenharmony_ci try: 3267db96d56Sopenharmony_ci self.filename = os.path.basename(pathname) 3277db96d56Sopenharmony_ci self.module = os.path.splitext(self.filename)[0] 3287db96d56Sopenharmony_ci except (TypeError, ValueError, AttributeError): 3297db96d56Sopenharmony_ci self.filename = pathname 3307db96d56Sopenharmony_ci self.module = "Unknown module" 3317db96d56Sopenharmony_ci self.exc_info = exc_info 3327db96d56Sopenharmony_ci self.exc_text = None # used to cache the traceback text 3337db96d56Sopenharmony_ci self.stack_info = sinfo 3347db96d56Sopenharmony_ci self.lineno = lineno 3357db96d56Sopenharmony_ci self.funcName = func 3367db96d56Sopenharmony_ci self.created = ct 3377db96d56Sopenharmony_ci self.msecs = int((ct - int(ct)) * 1000) + 0.0 # see gh-89047 3387db96d56Sopenharmony_ci self.relativeCreated = (self.created - _startTime) * 1000 3397db96d56Sopenharmony_ci if logThreads: 3407db96d56Sopenharmony_ci self.thread = threading.get_ident() 3417db96d56Sopenharmony_ci self.threadName = threading.current_thread().name 3427db96d56Sopenharmony_ci else: # pragma: no cover 3437db96d56Sopenharmony_ci self.thread = None 3447db96d56Sopenharmony_ci self.threadName = None 3457db96d56Sopenharmony_ci if not logMultiprocessing: # pragma: no cover 3467db96d56Sopenharmony_ci self.processName = None 3477db96d56Sopenharmony_ci else: 3487db96d56Sopenharmony_ci self.processName = 'MainProcess' 3497db96d56Sopenharmony_ci mp = sys.modules.get('multiprocessing') 3507db96d56Sopenharmony_ci if mp is not None: 3517db96d56Sopenharmony_ci # Errors may occur if multiprocessing has not finished loading 3527db96d56Sopenharmony_ci # yet - e.g. if a custom import hook causes third-party code 3537db96d56Sopenharmony_ci # to run when multiprocessing calls import. See issue 8200 3547db96d56Sopenharmony_ci # for an example 3557db96d56Sopenharmony_ci try: 3567db96d56Sopenharmony_ci self.processName = mp.current_process().name 3577db96d56Sopenharmony_ci except Exception: #pragma: no cover 3587db96d56Sopenharmony_ci pass 3597db96d56Sopenharmony_ci if logProcesses and hasattr(os, 'getpid'): 3607db96d56Sopenharmony_ci self.process = os.getpid() 3617db96d56Sopenharmony_ci else: 3627db96d56Sopenharmony_ci self.process = None 3637db96d56Sopenharmony_ci 3647db96d56Sopenharmony_ci def __repr__(self): 3657db96d56Sopenharmony_ci return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno, 3667db96d56Sopenharmony_ci self.pathname, self.lineno, self.msg) 3677db96d56Sopenharmony_ci 3687db96d56Sopenharmony_ci def getMessage(self): 3697db96d56Sopenharmony_ci """ 3707db96d56Sopenharmony_ci Return the message for this LogRecord. 3717db96d56Sopenharmony_ci 3727db96d56Sopenharmony_ci Return the message for this LogRecord after merging any user-supplied 3737db96d56Sopenharmony_ci arguments with the message. 3747db96d56Sopenharmony_ci """ 3757db96d56Sopenharmony_ci msg = str(self.msg) 3767db96d56Sopenharmony_ci if self.args: 3777db96d56Sopenharmony_ci msg = msg % self.args 3787db96d56Sopenharmony_ci return msg 3797db96d56Sopenharmony_ci 3807db96d56Sopenharmony_ci# 3817db96d56Sopenharmony_ci# Determine which class to use when instantiating log records. 3827db96d56Sopenharmony_ci# 3837db96d56Sopenharmony_ci_logRecordFactory = LogRecord 3847db96d56Sopenharmony_ci 3857db96d56Sopenharmony_cidef setLogRecordFactory(factory): 3867db96d56Sopenharmony_ci """ 3877db96d56Sopenharmony_ci Set the factory to be used when instantiating a log record. 3887db96d56Sopenharmony_ci 3897db96d56Sopenharmony_ci :param factory: A callable which will be called to instantiate 3907db96d56Sopenharmony_ci a log record. 3917db96d56Sopenharmony_ci """ 3927db96d56Sopenharmony_ci global _logRecordFactory 3937db96d56Sopenharmony_ci _logRecordFactory = factory 3947db96d56Sopenharmony_ci 3957db96d56Sopenharmony_cidef getLogRecordFactory(): 3967db96d56Sopenharmony_ci """ 3977db96d56Sopenharmony_ci Return the factory to be used when instantiating a log record. 3987db96d56Sopenharmony_ci """ 3997db96d56Sopenharmony_ci 4007db96d56Sopenharmony_ci return _logRecordFactory 4017db96d56Sopenharmony_ci 4027db96d56Sopenharmony_cidef makeLogRecord(dict): 4037db96d56Sopenharmony_ci """ 4047db96d56Sopenharmony_ci Make a LogRecord whose attributes are defined by the specified dictionary, 4057db96d56Sopenharmony_ci This function is useful for converting a logging event received over 4067db96d56Sopenharmony_ci a socket connection (which is sent as a dictionary) into a LogRecord 4077db96d56Sopenharmony_ci instance. 4087db96d56Sopenharmony_ci """ 4097db96d56Sopenharmony_ci rv = _logRecordFactory(None, None, "", 0, "", (), None, None) 4107db96d56Sopenharmony_ci rv.__dict__.update(dict) 4117db96d56Sopenharmony_ci return rv 4127db96d56Sopenharmony_ci 4137db96d56Sopenharmony_ci 4147db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 4157db96d56Sopenharmony_ci# Formatter classes and functions 4167db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 4177db96d56Sopenharmony_ci_str_formatter = StrFormatter() 4187db96d56Sopenharmony_cidel StrFormatter 4197db96d56Sopenharmony_ci 4207db96d56Sopenharmony_ci 4217db96d56Sopenharmony_ciclass PercentStyle(object): 4227db96d56Sopenharmony_ci 4237db96d56Sopenharmony_ci default_format = '%(message)s' 4247db96d56Sopenharmony_ci asctime_format = '%(asctime)s' 4257db96d56Sopenharmony_ci asctime_search = '%(asctime)' 4267db96d56Sopenharmony_ci validation_pattern = re.compile(r'%\(\w+\)[#0+ -]*(\*|\d+)?(\.(\*|\d+))?[diouxefgcrsa%]', re.I) 4277db96d56Sopenharmony_ci 4287db96d56Sopenharmony_ci def __init__(self, fmt, *, defaults=None): 4297db96d56Sopenharmony_ci self._fmt = fmt or self.default_format 4307db96d56Sopenharmony_ci self._defaults = defaults 4317db96d56Sopenharmony_ci 4327db96d56Sopenharmony_ci def usesTime(self): 4337db96d56Sopenharmony_ci return self._fmt.find(self.asctime_search) >= 0 4347db96d56Sopenharmony_ci 4357db96d56Sopenharmony_ci def validate(self): 4367db96d56Sopenharmony_ci """Validate the input format, ensure it matches the correct style""" 4377db96d56Sopenharmony_ci if not self.validation_pattern.search(self._fmt): 4387db96d56Sopenharmony_ci raise ValueError("Invalid format '%s' for '%s' style" % (self._fmt, self.default_format[0])) 4397db96d56Sopenharmony_ci 4407db96d56Sopenharmony_ci def _format(self, record): 4417db96d56Sopenharmony_ci if defaults := self._defaults: 4427db96d56Sopenharmony_ci values = defaults | record.__dict__ 4437db96d56Sopenharmony_ci else: 4447db96d56Sopenharmony_ci values = record.__dict__ 4457db96d56Sopenharmony_ci return self._fmt % values 4467db96d56Sopenharmony_ci 4477db96d56Sopenharmony_ci def format(self, record): 4487db96d56Sopenharmony_ci try: 4497db96d56Sopenharmony_ci return self._format(record) 4507db96d56Sopenharmony_ci except KeyError as e: 4517db96d56Sopenharmony_ci raise ValueError('Formatting field not found in record: %s' % e) 4527db96d56Sopenharmony_ci 4537db96d56Sopenharmony_ci 4547db96d56Sopenharmony_ciclass StrFormatStyle(PercentStyle): 4557db96d56Sopenharmony_ci default_format = '{message}' 4567db96d56Sopenharmony_ci asctime_format = '{asctime}' 4577db96d56Sopenharmony_ci asctime_search = '{asctime' 4587db96d56Sopenharmony_ci 4597db96d56Sopenharmony_ci fmt_spec = re.compile(r'^(.?[<>=^])?[+ -]?#?0?(\d+|{\w+})?[,_]?(\.(\d+|{\w+}))?[bcdefgnosx%]?$', re.I) 4607db96d56Sopenharmony_ci field_spec = re.compile(r'^(\d+|\w+)(\.\w+|\[[^]]+\])*$') 4617db96d56Sopenharmony_ci 4627db96d56Sopenharmony_ci def _format(self, record): 4637db96d56Sopenharmony_ci if defaults := self._defaults: 4647db96d56Sopenharmony_ci values = defaults | record.__dict__ 4657db96d56Sopenharmony_ci else: 4667db96d56Sopenharmony_ci values = record.__dict__ 4677db96d56Sopenharmony_ci return self._fmt.format(**values) 4687db96d56Sopenharmony_ci 4697db96d56Sopenharmony_ci def validate(self): 4707db96d56Sopenharmony_ci """Validate the input format, ensure it is the correct string formatting style""" 4717db96d56Sopenharmony_ci fields = set() 4727db96d56Sopenharmony_ci try: 4737db96d56Sopenharmony_ci for _, fieldname, spec, conversion in _str_formatter.parse(self._fmt): 4747db96d56Sopenharmony_ci if fieldname: 4757db96d56Sopenharmony_ci if not self.field_spec.match(fieldname): 4767db96d56Sopenharmony_ci raise ValueError('invalid field name/expression: %r' % fieldname) 4777db96d56Sopenharmony_ci fields.add(fieldname) 4787db96d56Sopenharmony_ci if conversion and conversion not in 'rsa': 4797db96d56Sopenharmony_ci raise ValueError('invalid conversion: %r' % conversion) 4807db96d56Sopenharmony_ci if spec and not self.fmt_spec.match(spec): 4817db96d56Sopenharmony_ci raise ValueError('bad specifier: %r' % spec) 4827db96d56Sopenharmony_ci except ValueError as e: 4837db96d56Sopenharmony_ci raise ValueError('invalid format: %s' % e) 4847db96d56Sopenharmony_ci if not fields: 4857db96d56Sopenharmony_ci raise ValueError('invalid format: no fields') 4867db96d56Sopenharmony_ci 4877db96d56Sopenharmony_ci 4887db96d56Sopenharmony_ciclass StringTemplateStyle(PercentStyle): 4897db96d56Sopenharmony_ci default_format = '${message}' 4907db96d56Sopenharmony_ci asctime_format = '${asctime}' 4917db96d56Sopenharmony_ci asctime_search = '${asctime}' 4927db96d56Sopenharmony_ci 4937db96d56Sopenharmony_ci def __init__(self, *args, **kwargs): 4947db96d56Sopenharmony_ci super().__init__(*args, **kwargs) 4957db96d56Sopenharmony_ci self._tpl = Template(self._fmt) 4967db96d56Sopenharmony_ci 4977db96d56Sopenharmony_ci def usesTime(self): 4987db96d56Sopenharmony_ci fmt = self._fmt 4997db96d56Sopenharmony_ci return fmt.find('$asctime') >= 0 or fmt.find(self.asctime_search) >= 0 5007db96d56Sopenharmony_ci 5017db96d56Sopenharmony_ci def validate(self): 5027db96d56Sopenharmony_ci pattern = Template.pattern 5037db96d56Sopenharmony_ci fields = set() 5047db96d56Sopenharmony_ci for m in pattern.finditer(self._fmt): 5057db96d56Sopenharmony_ci d = m.groupdict() 5067db96d56Sopenharmony_ci if d['named']: 5077db96d56Sopenharmony_ci fields.add(d['named']) 5087db96d56Sopenharmony_ci elif d['braced']: 5097db96d56Sopenharmony_ci fields.add(d['braced']) 5107db96d56Sopenharmony_ci elif m.group(0) == '$': 5117db96d56Sopenharmony_ci raise ValueError('invalid format: bare \'$\' not allowed') 5127db96d56Sopenharmony_ci if not fields: 5137db96d56Sopenharmony_ci raise ValueError('invalid format: no fields') 5147db96d56Sopenharmony_ci 5157db96d56Sopenharmony_ci def _format(self, record): 5167db96d56Sopenharmony_ci if defaults := self._defaults: 5177db96d56Sopenharmony_ci values = defaults | record.__dict__ 5187db96d56Sopenharmony_ci else: 5197db96d56Sopenharmony_ci values = record.__dict__ 5207db96d56Sopenharmony_ci return self._tpl.substitute(**values) 5217db96d56Sopenharmony_ci 5227db96d56Sopenharmony_ci 5237db96d56Sopenharmony_ciBASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s" 5247db96d56Sopenharmony_ci 5257db96d56Sopenharmony_ci_STYLES = { 5267db96d56Sopenharmony_ci '%': (PercentStyle, BASIC_FORMAT), 5277db96d56Sopenharmony_ci '{': (StrFormatStyle, '{levelname}:{name}:{message}'), 5287db96d56Sopenharmony_ci '$': (StringTemplateStyle, '${levelname}:${name}:${message}'), 5297db96d56Sopenharmony_ci} 5307db96d56Sopenharmony_ci 5317db96d56Sopenharmony_ciclass Formatter(object): 5327db96d56Sopenharmony_ci """ 5337db96d56Sopenharmony_ci Formatter instances are used to convert a LogRecord to text. 5347db96d56Sopenharmony_ci 5357db96d56Sopenharmony_ci Formatters need to know how a LogRecord is constructed. They are 5367db96d56Sopenharmony_ci responsible for converting a LogRecord to (usually) a string which can 5377db96d56Sopenharmony_ci be interpreted by either a human or an external system. The base Formatter 5387db96d56Sopenharmony_ci allows a formatting string to be specified. If none is supplied, the 5397db96d56Sopenharmony_ci style-dependent default value, "%(message)s", "{message}", or 5407db96d56Sopenharmony_ci "${message}", is used. 5417db96d56Sopenharmony_ci 5427db96d56Sopenharmony_ci The Formatter can be initialized with a format string which makes use of 5437db96d56Sopenharmony_ci knowledge of the LogRecord attributes - e.g. the default value mentioned 5447db96d56Sopenharmony_ci above makes use of the fact that the user's message and arguments are pre- 5457db96d56Sopenharmony_ci formatted into a LogRecord's message attribute. Currently, the useful 5467db96d56Sopenharmony_ci attributes in a LogRecord are described by: 5477db96d56Sopenharmony_ci 5487db96d56Sopenharmony_ci %(name)s Name of the logger (logging channel) 5497db96d56Sopenharmony_ci %(levelno)s Numeric logging level for the message (DEBUG, INFO, 5507db96d56Sopenharmony_ci WARNING, ERROR, CRITICAL) 5517db96d56Sopenharmony_ci %(levelname)s Text logging level for the message ("DEBUG", "INFO", 5527db96d56Sopenharmony_ci "WARNING", "ERROR", "CRITICAL") 5537db96d56Sopenharmony_ci %(pathname)s Full pathname of the source file where the logging 5547db96d56Sopenharmony_ci call was issued (if available) 5557db96d56Sopenharmony_ci %(filename)s Filename portion of pathname 5567db96d56Sopenharmony_ci %(module)s Module (name portion of filename) 5577db96d56Sopenharmony_ci %(lineno)d Source line number where the logging call was issued 5587db96d56Sopenharmony_ci (if available) 5597db96d56Sopenharmony_ci %(funcName)s Function name 5607db96d56Sopenharmony_ci %(created)f Time when the LogRecord was created (time.time() 5617db96d56Sopenharmony_ci return value) 5627db96d56Sopenharmony_ci %(asctime)s Textual time when the LogRecord was created 5637db96d56Sopenharmony_ci %(msecs)d Millisecond portion of the creation time 5647db96d56Sopenharmony_ci %(relativeCreated)d Time in milliseconds when the LogRecord was created, 5657db96d56Sopenharmony_ci relative to the time the logging module was loaded 5667db96d56Sopenharmony_ci (typically at application startup time) 5677db96d56Sopenharmony_ci %(thread)d Thread ID (if available) 5687db96d56Sopenharmony_ci %(threadName)s Thread name (if available) 5697db96d56Sopenharmony_ci %(process)d Process ID (if available) 5707db96d56Sopenharmony_ci %(message)s The result of record.getMessage(), computed just as 5717db96d56Sopenharmony_ci the record is emitted 5727db96d56Sopenharmony_ci """ 5737db96d56Sopenharmony_ci 5747db96d56Sopenharmony_ci converter = time.localtime 5757db96d56Sopenharmony_ci 5767db96d56Sopenharmony_ci def __init__(self, fmt=None, datefmt=None, style='%', validate=True, *, 5777db96d56Sopenharmony_ci defaults=None): 5787db96d56Sopenharmony_ci """ 5797db96d56Sopenharmony_ci Initialize the formatter with specified format strings. 5807db96d56Sopenharmony_ci 5817db96d56Sopenharmony_ci Initialize the formatter either with the specified format string, or a 5827db96d56Sopenharmony_ci default as described above. Allow for specialized date formatting with 5837db96d56Sopenharmony_ci the optional datefmt argument. If datefmt is omitted, you get an 5847db96d56Sopenharmony_ci ISO8601-like (or RFC 3339-like) format. 5857db96d56Sopenharmony_ci 5867db96d56Sopenharmony_ci Use a style parameter of '%', '{' or '$' to specify that you want to 5877db96d56Sopenharmony_ci use one of %-formatting, :meth:`str.format` (``{}``) formatting or 5887db96d56Sopenharmony_ci :class:`string.Template` formatting in your format string. 5897db96d56Sopenharmony_ci 5907db96d56Sopenharmony_ci .. versionchanged:: 3.2 5917db96d56Sopenharmony_ci Added the ``style`` parameter. 5927db96d56Sopenharmony_ci """ 5937db96d56Sopenharmony_ci if style not in _STYLES: 5947db96d56Sopenharmony_ci raise ValueError('Style must be one of: %s' % ','.join( 5957db96d56Sopenharmony_ci _STYLES.keys())) 5967db96d56Sopenharmony_ci self._style = _STYLES[style][0](fmt, defaults=defaults) 5977db96d56Sopenharmony_ci if validate: 5987db96d56Sopenharmony_ci self._style.validate() 5997db96d56Sopenharmony_ci 6007db96d56Sopenharmony_ci self._fmt = self._style._fmt 6017db96d56Sopenharmony_ci self.datefmt = datefmt 6027db96d56Sopenharmony_ci 6037db96d56Sopenharmony_ci default_time_format = '%Y-%m-%d %H:%M:%S' 6047db96d56Sopenharmony_ci default_msec_format = '%s,%03d' 6057db96d56Sopenharmony_ci 6067db96d56Sopenharmony_ci def formatTime(self, record, datefmt=None): 6077db96d56Sopenharmony_ci """ 6087db96d56Sopenharmony_ci Return the creation time of the specified LogRecord as formatted text. 6097db96d56Sopenharmony_ci 6107db96d56Sopenharmony_ci This method should be called from format() by a formatter which 6117db96d56Sopenharmony_ci wants to make use of a formatted time. This method can be overridden 6127db96d56Sopenharmony_ci in formatters to provide for any specific requirement, but the 6137db96d56Sopenharmony_ci basic behaviour is as follows: if datefmt (a string) is specified, 6147db96d56Sopenharmony_ci it is used with time.strftime() to format the creation time of the 6157db96d56Sopenharmony_ci record. Otherwise, an ISO8601-like (or RFC 3339-like) format is used. 6167db96d56Sopenharmony_ci The resulting string is returned. This function uses a user-configurable 6177db96d56Sopenharmony_ci function to convert the creation time to a tuple. By default, 6187db96d56Sopenharmony_ci time.localtime() is used; to change this for a particular formatter 6197db96d56Sopenharmony_ci instance, set the 'converter' attribute to a function with the same 6207db96d56Sopenharmony_ci signature as time.localtime() or time.gmtime(). To change it for all 6217db96d56Sopenharmony_ci formatters, for example if you want all logging times to be shown in GMT, 6227db96d56Sopenharmony_ci set the 'converter' attribute in the Formatter class. 6237db96d56Sopenharmony_ci """ 6247db96d56Sopenharmony_ci ct = self.converter(record.created) 6257db96d56Sopenharmony_ci if datefmt: 6267db96d56Sopenharmony_ci s = time.strftime(datefmt, ct) 6277db96d56Sopenharmony_ci else: 6287db96d56Sopenharmony_ci s = time.strftime(self.default_time_format, ct) 6297db96d56Sopenharmony_ci if self.default_msec_format: 6307db96d56Sopenharmony_ci s = self.default_msec_format % (s, record.msecs) 6317db96d56Sopenharmony_ci return s 6327db96d56Sopenharmony_ci 6337db96d56Sopenharmony_ci def formatException(self, ei): 6347db96d56Sopenharmony_ci """ 6357db96d56Sopenharmony_ci Format and return the specified exception information as a string. 6367db96d56Sopenharmony_ci 6377db96d56Sopenharmony_ci This default implementation just uses 6387db96d56Sopenharmony_ci traceback.print_exception() 6397db96d56Sopenharmony_ci """ 6407db96d56Sopenharmony_ci sio = io.StringIO() 6417db96d56Sopenharmony_ci tb = ei[2] 6427db96d56Sopenharmony_ci # See issues #9427, #1553375. Commented out for now. 6437db96d56Sopenharmony_ci #if getattr(self, 'fullstack', False): 6447db96d56Sopenharmony_ci # traceback.print_stack(tb.tb_frame.f_back, file=sio) 6457db96d56Sopenharmony_ci traceback.print_exception(ei[0], ei[1], tb, None, sio) 6467db96d56Sopenharmony_ci s = sio.getvalue() 6477db96d56Sopenharmony_ci sio.close() 6487db96d56Sopenharmony_ci if s[-1:] == "\n": 6497db96d56Sopenharmony_ci s = s[:-1] 6507db96d56Sopenharmony_ci return s 6517db96d56Sopenharmony_ci 6527db96d56Sopenharmony_ci def usesTime(self): 6537db96d56Sopenharmony_ci """ 6547db96d56Sopenharmony_ci Check if the format uses the creation time of the record. 6557db96d56Sopenharmony_ci """ 6567db96d56Sopenharmony_ci return self._style.usesTime() 6577db96d56Sopenharmony_ci 6587db96d56Sopenharmony_ci def formatMessage(self, record): 6597db96d56Sopenharmony_ci return self._style.format(record) 6607db96d56Sopenharmony_ci 6617db96d56Sopenharmony_ci def formatStack(self, stack_info): 6627db96d56Sopenharmony_ci """ 6637db96d56Sopenharmony_ci This method is provided as an extension point for specialized 6647db96d56Sopenharmony_ci formatting of stack information. 6657db96d56Sopenharmony_ci 6667db96d56Sopenharmony_ci The input data is a string as returned from a call to 6677db96d56Sopenharmony_ci :func:`traceback.print_stack`, but with the last trailing newline 6687db96d56Sopenharmony_ci removed. 6697db96d56Sopenharmony_ci 6707db96d56Sopenharmony_ci The base implementation just returns the value passed in. 6717db96d56Sopenharmony_ci """ 6727db96d56Sopenharmony_ci return stack_info 6737db96d56Sopenharmony_ci 6747db96d56Sopenharmony_ci def format(self, record): 6757db96d56Sopenharmony_ci """ 6767db96d56Sopenharmony_ci Format the specified record as text. 6777db96d56Sopenharmony_ci 6787db96d56Sopenharmony_ci The record's attribute dictionary is used as the operand to a 6797db96d56Sopenharmony_ci string formatting operation which yields the returned string. 6807db96d56Sopenharmony_ci Before formatting the dictionary, a couple of preparatory steps 6817db96d56Sopenharmony_ci are carried out. The message attribute of the record is computed 6827db96d56Sopenharmony_ci using LogRecord.getMessage(). If the formatting string uses the 6837db96d56Sopenharmony_ci time (as determined by a call to usesTime(), formatTime() is 6847db96d56Sopenharmony_ci called to format the event time. If there is exception information, 6857db96d56Sopenharmony_ci it is formatted using formatException() and appended to the message. 6867db96d56Sopenharmony_ci """ 6877db96d56Sopenharmony_ci record.message = record.getMessage() 6887db96d56Sopenharmony_ci if self.usesTime(): 6897db96d56Sopenharmony_ci record.asctime = self.formatTime(record, self.datefmt) 6907db96d56Sopenharmony_ci s = self.formatMessage(record) 6917db96d56Sopenharmony_ci if record.exc_info: 6927db96d56Sopenharmony_ci # Cache the traceback text to avoid converting it multiple times 6937db96d56Sopenharmony_ci # (it's constant anyway) 6947db96d56Sopenharmony_ci if not record.exc_text: 6957db96d56Sopenharmony_ci record.exc_text = self.formatException(record.exc_info) 6967db96d56Sopenharmony_ci if record.exc_text: 6977db96d56Sopenharmony_ci if s[-1:] != "\n": 6987db96d56Sopenharmony_ci s = s + "\n" 6997db96d56Sopenharmony_ci s = s + record.exc_text 7007db96d56Sopenharmony_ci if record.stack_info: 7017db96d56Sopenharmony_ci if s[-1:] != "\n": 7027db96d56Sopenharmony_ci s = s + "\n" 7037db96d56Sopenharmony_ci s = s + self.formatStack(record.stack_info) 7047db96d56Sopenharmony_ci return s 7057db96d56Sopenharmony_ci 7067db96d56Sopenharmony_ci# 7077db96d56Sopenharmony_ci# The default formatter to use when no other is specified 7087db96d56Sopenharmony_ci# 7097db96d56Sopenharmony_ci_defaultFormatter = Formatter() 7107db96d56Sopenharmony_ci 7117db96d56Sopenharmony_ciclass BufferingFormatter(object): 7127db96d56Sopenharmony_ci """ 7137db96d56Sopenharmony_ci A formatter suitable for formatting a number of records. 7147db96d56Sopenharmony_ci """ 7157db96d56Sopenharmony_ci def __init__(self, linefmt=None): 7167db96d56Sopenharmony_ci """ 7177db96d56Sopenharmony_ci Optionally specify a formatter which will be used to format each 7187db96d56Sopenharmony_ci individual record. 7197db96d56Sopenharmony_ci """ 7207db96d56Sopenharmony_ci if linefmt: 7217db96d56Sopenharmony_ci self.linefmt = linefmt 7227db96d56Sopenharmony_ci else: 7237db96d56Sopenharmony_ci self.linefmt = _defaultFormatter 7247db96d56Sopenharmony_ci 7257db96d56Sopenharmony_ci def formatHeader(self, records): 7267db96d56Sopenharmony_ci """ 7277db96d56Sopenharmony_ci Return the header string for the specified records. 7287db96d56Sopenharmony_ci """ 7297db96d56Sopenharmony_ci return "" 7307db96d56Sopenharmony_ci 7317db96d56Sopenharmony_ci def formatFooter(self, records): 7327db96d56Sopenharmony_ci """ 7337db96d56Sopenharmony_ci Return the footer string for the specified records. 7347db96d56Sopenharmony_ci """ 7357db96d56Sopenharmony_ci return "" 7367db96d56Sopenharmony_ci 7377db96d56Sopenharmony_ci def format(self, records): 7387db96d56Sopenharmony_ci """ 7397db96d56Sopenharmony_ci Format the specified records and return the result as a string. 7407db96d56Sopenharmony_ci """ 7417db96d56Sopenharmony_ci rv = "" 7427db96d56Sopenharmony_ci if len(records) > 0: 7437db96d56Sopenharmony_ci rv = rv + self.formatHeader(records) 7447db96d56Sopenharmony_ci for record in records: 7457db96d56Sopenharmony_ci rv = rv + self.linefmt.format(record) 7467db96d56Sopenharmony_ci rv = rv + self.formatFooter(records) 7477db96d56Sopenharmony_ci return rv 7487db96d56Sopenharmony_ci 7497db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 7507db96d56Sopenharmony_ci# Filter classes and functions 7517db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 7527db96d56Sopenharmony_ci 7537db96d56Sopenharmony_ciclass Filter(object): 7547db96d56Sopenharmony_ci """ 7557db96d56Sopenharmony_ci Filter instances are used to perform arbitrary filtering of LogRecords. 7567db96d56Sopenharmony_ci 7577db96d56Sopenharmony_ci Loggers and Handlers can optionally use Filter instances to filter 7587db96d56Sopenharmony_ci records as desired. The base filter class only allows events which are 7597db96d56Sopenharmony_ci below a certain point in the logger hierarchy. For example, a filter 7607db96d56Sopenharmony_ci initialized with "A.B" will allow events logged by loggers "A.B", 7617db96d56Sopenharmony_ci "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If 7627db96d56Sopenharmony_ci initialized with the empty string, all events are passed. 7637db96d56Sopenharmony_ci """ 7647db96d56Sopenharmony_ci def __init__(self, name=''): 7657db96d56Sopenharmony_ci """ 7667db96d56Sopenharmony_ci Initialize a filter. 7677db96d56Sopenharmony_ci 7687db96d56Sopenharmony_ci Initialize with the name of the logger which, together with its 7697db96d56Sopenharmony_ci children, will have its events allowed through the filter. If no 7707db96d56Sopenharmony_ci name is specified, allow every event. 7717db96d56Sopenharmony_ci """ 7727db96d56Sopenharmony_ci self.name = name 7737db96d56Sopenharmony_ci self.nlen = len(name) 7747db96d56Sopenharmony_ci 7757db96d56Sopenharmony_ci def filter(self, record): 7767db96d56Sopenharmony_ci """ 7777db96d56Sopenharmony_ci Determine if the specified record is to be logged. 7787db96d56Sopenharmony_ci 7797db96d56Sopenharmony_ci Returns True if the record should be logged, or False otherwise. 7807db96d56Sopenharmony_ci If deemed appropriate, the record may be modified in-place. 7817db96d56Sopenharmony_ci """ 7827db96d56Sopenharmony_ci if self.nlen == 0: 7837db96d56Sopenharmony_ci return True 7847db96d56Sopenharmony_ci elif self.name == record.name: 7857db96d56Sopenharmony_ci return True 7867db96d56Sopenharmony_ci elif record.name.find(self.name, 0, self.nlen) != 0: 7877db96d56Sopenharmony_ci return False 7887db96d56Sopenharmony_ci return (record.name[self.nlen] == ".") 7897db96d56Sopenharmony_ci 7907db96d56Sopenharmony_ciclass Filterer(object): 7917db96d56Sopenharmony_ci """ 7927db96d56Sopenharmony_ci A base class for loggers and handlers which allows them to share 7937db96d56Sopenharmony_ci common code. 7947db96d56Sopenharmony_ci """ 7957db96d56Sopenharmony_ci def __init__(self): 7967db96d56Sopenharmony_ci """ 7977db96d56Sopenharmony_ci Initialize the list of filters to be an empty list. 7987db96d56Sopenharmony_ci """ 7997db96d56Sopenharmony_ci self.filters = [] 8007db96d56Sopenharmony_ci 8017db96d56Sopenharmony_ci def addFilter(self, filter): 8027db96d56Sopenharmony_ci """ 8037db96d56Sopenharmony_ci Add the specified filter to this handler. 8047db96d56Sopenharmony_ci """ 8057db96d56Sopenharmony_ci if not (filter in self.filters): 8067db96d56Sopenharmony_ci self.filters.append(filter) 8077db96d56Sopenharmony_ci 8087db96d56Sopenharmony_ci def removeFilter(self, filter): 8097db96d56Sopenharmony_ci """ 8107db96d56Sopenharmony_ci Remove the specified filter from this handler. 8117db96d56Sopenharmony_ci """ 8127db96d56Sopenharmony_ci if filter in self.filters: 8137db96d56Sopenharmony_ci self.filters.remove(filter) 8147db96d56Sopenharmony_ci 8157db96d56Sopenharmony_ci def filter(self, record): 8167db96d56Sopenharmony_ci """ 8177db96d56Sopenharmony_ci Determine if a record is loggable by consulting all the filters. 8187db96d56Sopenharmony_ci 8197db96d56Sopenharmony_ci The default is to allow the record to be logged; any filter can veto 8207db96d56Sopenharmony_ci this and the record is then dropped. Returns a zero value if a record 8217db96d56Sopenharmony_ci is to be dropped, else non-zero. 8227db96d56Sopenharmony_ci 8237db96d56Sopenharmony_ci .. versionchanged:: 3.2 8247db96d56Sopenharmony_ci 8257db96d56Sopenharmony_ci Allow filters to be just callables. 8267db96d56Sopenharmony_ci """ 8277db96d56Sopenharmony_ci rv = True 8287db96d56Sopenharmony_ci for f in self.filters: 8297db96d56Sopenharmony_ci if hasattr(f, 'filter'): 8307db96d56Sopenharmony_ci result = f.filter(record) 8317db96d56Sopenharmony_ci else: 8327db96d56Sopenharmony_ci result = f(record) # assume callable - will raise if not 8337db96d56Sopenharmony_ci if not result: 8347db96d56Sopenharmony_ci rv = False 8357db96d56Sopenharmony_ci break 8367db96d56Sopenharmony_ci return rv 8377db96d56Sopenharmony_ci 8387db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 8397db96d56Sopenharmony_ci# Handler classes and functions 8407db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 8417db96d56Sopenharmony_ci 8427db96d56Sopenharmony_ci_handlers = weakref.WeakValueDictionary() #map of handler names to handlers 8437db96d56Sopenharmony_ci_handlerList = [] # added to allow handlers to be removed in reverse of order initialized 8447db96d56Sopenharmony_ci 8457db96d56Sopenharmony_cidef _removeHandlerRef(wr): 8467db96d56Sopenharmony_ci """ 8477db96d56Sopenharmony_ci Remove a handler reference from the internal cleanup list. 8487db96d56Sopenharmony_ci """ 8497db96d56Sopenharmony_ci # This function can be called during module teardown, when globals are 8507db96d56Sopenharmony_ci # set to None. It can also be called from another thread. So we need to 8517db96d56Sopenharmony_ci # pre-emptively grab the necessary globals and check if they're None, 8527db96d56Sopenharmony_ci # to prevent race conditions and failures during interpreter shutdown. 8537db96d56Sopenharmony_ci acquire, release, handlers = _acquireLock, _releaseLock, _handlerList 8547db96d56Sopenharmony_ci if acquire and release and handlers: 8557db96d56Sopenharmony_ci acquire() 8567db96d56Sopenharmony_ci try: 8577db96d56Sopenharmony_ci handlers.remove(wr) 8587db96d56Sopenharmony_ci except ValueError: 8597db96d56Sopenharmony_ci pass 8607db96d56Sopenharmony_ci finally: 8617db96d56Sopenharmony_ci release() 8627db96d56Sopenharmony_ci 8637db96d56Sopenharmony_cidef _addHandlerRef(handler): 8647db96d56Sopenharmony_ci """ 8657db96d56Sopenharmony_ci Add a handler to the internal cleanup list using a weak reference. 8667db96d56Sopenharmony_ci """ 8677db96d56Sopenharmony_ci _acquireLock() 8687db96d56Sopenharmony_ci try: 8697db96d56Sopenharmony_ci _handlerList.append(weakref.ref(handler, _removeHandlerRef)) 8707db96d56Sopenharmony_ci finally: 8717db96d56Sopenharmony_ci _releaseLock() 8727db96d56Sopenharmony_ci 8737db96d56Sopenharmony_ciclass Handler(Filterer): 8747db96d56Sopenharmony_ci """ 8757db96d56Sopenharmony_ci Handler instances dispatch logging events to specific destinations. 8767db96d56Sopenharmony_ci 8777db96d56Sopenharmony_ci The base handler class. Acts as a placeholder which defines the Handler 8787db96d56Sopenharmony_ci interface. Handlers can optionally use Formatter instances to format 8797db96d56Sopenharmony_ci records as desired. By default, no formatter is specified; in this case, 8807db96d56Sopenharmony_ci the 'raw' message as determined by record.message is logged. 8817db96d56Sopenharmony_ci """ 8827db96d56Sopenharmony_ci def __init__(self, level=NOTSET): 8837db96d56Sopenharmony_ci """ 8847db96d56Sopenharmony_ci Initializes the instance - basically setting the formatter to None 8857db96d56Sopenharmony_ci and the filter list to empty. 8867db96d56Sopenharmony_ci """ 8877db96d56Sopenharmony_ci Filterer.__init__(self) 8887db96d56Sopenharmony_ci self._name = None 8897db96d56Sopenharmony_ci self.level = _checkLevel(level) 8907db96d56Sopenharmony_ci self.formatter = None 8917db96d56Sopenharmony_ci self._closed = False 8927db96d56Sopenharmony_ci # Add the handler to the global _handlerList (for cleanup on shutdown) 8937db96d56Sopenharmony_ci _addHandlerRef(self) 8947db96d56Sopenharmony_ci self.createLock() 8957db96d56Sopenharmony_ci 8967db96d56Sopenharmony_ci def get_name(self): 8977db96d56Sopenharmony_ci return self._name 8987db96d56Sopenharmony_ci 8997db96d56Sopenharmony_ci def set_name(self, name): 9007db96d56Sopenharmony_ci _acquireLock() 9017db96d56Sopenharmony_ci try: 9027db96d56Sopenharmony_ci if self._name in _handlers: 9037db96d56Sopenharmony_ci del _handlers[self._name] 9047db96d56Sopenharmony_ci self._name = name 9057db96d56Sopenharmony_ci if name: 9067db96d56Sopenharmony_ci _handlers[name] = self 9077db96d56Sopenharmony_ci finally: 9087db96d56Sopenharmony_ci _releaseLock() 9097db96d56Sopenharmony_ci 9107db96d56Sopenharmony_ci name = property(get_name, set_name) 9117db96d56Sopenharmony_ci 9127db96d56Sopenharmony_ci def createLock(self): 9137db96d56Sopenharmony_ci """ 9147db96d56Sopenharmony_ci Acquire a thread lock for serializing access to the underlying I/O. 9157db96d56Sopenharmony_ci """ 9167db96d56Sopenharmony_ci self.lock = threading.RLock() 9177db96d56Sopenharmony_ci _register_at_fork_reinit_lock(self) 9187db96d56Sopenharmony_ci 9197db96d56Sopenharmony_ci def _at_fork_reinit(self): 9207db96d56Sopenharmony_ci self.lock._at_fork_reinit() 9217db96d56Sopenharmony_ci 9227db96d56Sopenharmony_ci def acquire(self): 9237db96d56Sopenharmony_ci """ 9247db96d56Sopenharmony_ci Acquire the I/O thread lock. 9257db96d56Sopenharmony_ci """ 9267db96d56Sopenharmony_ci if self.lock: 9277db96d56Sopenharmony_ci self.lock.acquire() 9287db96d56Sopenharmony_ci 9297db96d56Sopenharmony_ci def release(self): 9307db96d56Sopenharmony_ci """ 9317db96d56Sopenharmony_ci Release the I/O thread lock. 9327db96d56Sopenharmony_ci """ 9337db96d56Sopenharmony_ci if self.lock: 9347db96d56Sopenharmony_ci self.lock.release() 9357db96d56Sopenharmony_ci 9367db96d56Sopenharmony_ci def setLevel(self, level): 9377db96d56Sopenharmony_ci """ 9387db96d56Sopenharmony_ci Set the logging level of this handler. level must be an int or a str. 9397db96d56Sopenharmony_ci """ 9407db96d56Sopenharmony_ci self.level = _checkLevel(level) 9417db96d56Sopenharmony_ci 9427db96d56Sopenharmony_ci def format(self, record): 9437db96d56Sopenharmony_ci """ 9447db96d56Sopenharmony_ci Format the specified record. 9457db96d56Sopenharmony_ci 9467db96d56Sopenharmony_ci If a formatter is set, use it. Otherwise, use the default formatter 9477db96d56Sopenharmony_ci for the module. 9487db96d56Sopenharmony_ci """ 9497db96d56Sopenharmony_ci if self.formatter: 9507db96d56Sopenharmony_ci fmt = self.formatter 9517db96d56Sopenharmony_ci else: 9527db96d56Sopenharmony_ci fmt = _defaultFormatter 9537db96d56Sopenharmony_ci return fmt.format(record) 9547db96d56Sopenharmony_ci 9557db96d56Sopenharmony_ci def emit(self, record): 9567db96d56Sopenharmony_ci """ 9577db96d56Sopenharmony_ci Do whatever it takes to actually log the specified logging record. 9587db96d56Sopenharmony_ci 9597db96d56Sopenharmony_ci This version is intended to be implemented by subclasses and so 9607db96d56Sopenharmony_ci raises a NotImplementedError. 9617db96d56Sopenharmony_ci """ 9627db96d56Sopenharmony_ci raise NotImplementedError('emit must be implemented ' 9637db96d56Sopenharmony_ci 'by Handler subclasses') 9647db96d56Sopenharmony_ci 9657db96d56Sopenharmony_ci def handle(self, record): 9667db96d56Sopenharmony_ci """ 9677db96d56Sopenharmony_ci Conditionally emit the specified logging record. 9687db96d56Sopenharmony_ci 9697db96d56Sopenharmony_ci Emission depends on filters which may have been added to the handler. 9707db96d56Sopenharmony_ci Wrap the actual emission of the record with acquisition/release of 9717db96d56Sopenharmony_ci the I/O thread lock. Returns whether the filter passed the record for 9727db96d56Sopenharmony_ci emission. 9737db96d56Sopenharmony_ci """ 9747db96d56Sopenharmony_ci rv = self.filter(record) 9757db96d56Sopenharmony_ci if rv: 9767db96d56Sopenharmony_ci self.acquire() 9777db96d56Sopenharmony_ci try: 9787db96d56Sopenharmony_ci self.emit(record) 9797db96d56Sopenharmony_ci finally: 9807db96d56Sopenharmony_ci self.release() 9817db96d56Sopenharmony_ci return rv 9827db96d56Sopenharmony_ci 9837db96d56Sopenharmony_ci def setFormatter(self, fmt): 9847db96d56Sopenharmony_ci """ 9857db96d56Sopenharmony_ci Set the formatter for this handler. 9867db96d56Sopenharmony_ci """ 9877db96d56Sopenharmony_ci self.formatter = fmt 9887db96d56Sopenharmony_ci 9897db96d56Sopenharmony_ci def flush(self): 9907db96d56Sopenharmony_ci """ 9917db96d56Sopenharmony_ci Ensure all logging output has been flushed. 9927db96d56Sopenharmony_ci 9937db96d56Sopenharmony_ci This version does nothing and is intended to be implemented by 9947db96d56Sopenharmony_ci subclasses. 9957db96d56Sopenharmony_ci """ 9967db96d56Sopenharmony_ci pass 9977db96d56Sopenharmony_ci 9987db96d56Sopenharmony_ci def close(self): 9997db96d56Sopenharmony_ci """ 10007db96d56Sopenharmony_ci Tidy up any resources used by the handler. 10017db96d56Sopenharmony_ci 10027db96d56Sopenharmony_ci This version removes the handler from an internal map of handlers, 10037db96d56Sopenharmony_ci _handlers, which is used for handler lookup by name. Subclasses 10047db96d56Sopenharmony_ci should ensure that this gets called from overridden close() 10057db96d56Sopenharmony_ci methods. 10067db96d56Sopenharmony_ci """ 10077db96d56Sopenharmony_ci #get the module data lock, as we're updating a shared structure. 10087db96d56Sopenharmony_ci _acquireLock() 10097db96d56Sopenharmony_ci try: #unlikely to raise an exception, but you never know... 10107db96d56Sopenharmony_ci self._closed = True 10117db96d56Sopenharmony_ci if self._name and self._name in _handlers: 10127db96d56Sopenharmony_ci del _handlers[self._name] 10137db96d56Sopenharmony_ci finally: 10147db96d56Sopenharmony_ci _releaseLock() 10157db96d56Sopenharmony_ci 10167db96d56Sopenharmony_ci def handleError(self, record): 10177db96d56Sopenharmony_ci """ 10187db96d56Sopenharmony_ci Handle errors which occur during an emit() call. 10197db96d56Sopenharmony_ci 10207db96d56Sopenharmony_ci This method should be called from handlers when an exception is 10217db96d56Sopenharmony_ci encountered during an emit() call. If raiseExceptions is false, 10227db96d56Sopenharmony_ci exceptions get silently ignored. This is what is mostly wanted 10237db96d56Sopenharmony_ci for a logging system - most users will not care about errors in 10247db96d56Sopenharmony_ci the logging system, they are more interested in application errors. 10257db96d56Sopenharmony_ci You could, however, replace this with a custom handler if you wish. 10267db96d56Sopenharmony_ci The record which was being processed is passed in to this method. 10277db96d56Sopenharmony_ci """ 10287db96d56Sopenharmony_ci if raiseExceptions and sys.stderr: # see issue 13807 10297db96d56Sopenharmony_ci t, v, tb = sys.exc_info() 10307db96d56Sopenharmony_ci try: 10317db96d56Sopenharmony_ci sys.stderr.write('--- Logging error ---\n') 10327db96d56Sopenharmony_ci traceback.print_exception(t, v, tb, None, sys.stderr) 10337db96d56Sopenharmony_ci sys.stderr.write('Call stack:\n') 10347db96d56Sopenharmony_ci # Walk the stack frame up until we're out of logging, 10357db96d56Sopenharmony_ci # so as to print the calling context. 10367db96d56Sopenharmony_ci frame = tb.tb_frame 10377db96d56Sopenharmony_ci while (frame and os.path.dirname(frame.f_code.co_filename) == 10387db96d56Sopenharmony_ci __path__[0]): 10397db96d56Sopenharmony_ci frame = frame.f_back 10407db96d56Sopenharmony_ci if frame: 10417db96d56Sopenharmony_ci traceback.print_stack(frame, file=sys.stderr) 10427db96d56Sopenharmony_ci else: 10437db96d56Sopenharmony_ci # couldn't find the right stack frame, for some reason 10447db96d56Sopenharmony_ci sys.stderr.write('Logged from file %s, line %s\n' % ( 10457db96d56Sopenharmony_ci record.filename, record.lineno)) 10467db96d56Sopenharmony_ci # Issue 18671: output logging message and arguments 10477db96d56Sopenharmony_ci try: 10487db96d56Sopenharmony_ci sys.stderr.write('Message: %r\n' 10497db96d56Sopenharmony_ci 'Arguments: %s\n' % (record.msg, 10507db96d56Sopenharmony_ci record.args)) 10517db96d56Sopenharmony_ci except RecursionError: # See issue 36272 10527db96d56Sopenharmony_ci raise 10537db96d56Sopenharmony_ci except Exception: 10547db96d56Sopenharmony_ci sys.stderr.write('Unable to print the message and arguments' 10557db96d56Sopenharmony_ci ' - possible formatting error.\nUse the' 10567db96d56Sopenharmony_ci ' traceback above to help find the error.\n' 10577db96d56Sopenharmony_ci ) 10587db96d56Sopenharmony_ci except OSError: #pragma: no cover 10597db96d56Sopenharmony_ci pass # see issue 5971 10607db96d56Sopenharmony_ci finally: 10617db96d56Sopenharmony_ci del t, v, tb 10627db96d56Sopenharmony_ci 10637db96d56Sopenharmony_ci def __repr__(self): 10647db96d56Sopenharmony_ci level = getLevelName(self.level) 10657db96d56Sopenharmony_ci return '<%s (%s)>' % (self.__class__.__name__, level) 10667db96d56Sopenharmony_ci 10677db96d56Sopenharmony_ciclass StreamHandler(Handler): 10687db96d56Sopenharmony_ci """ 10697db96d56Sopenharmony_ci A handler class which writes logging records, appropriately formatted, 10707db96d56Sopenharmony_ci to a stream. Note that this class does not close the stream, as 10717db96d56Sopenharmony_ci sys.stdout or sys.stderr may be used. 10727db96d56Sopenharmony_ci """ 10737db96d56Sopenharmony_ci 10747db96d56Sopenharmony_ci terminator = '\n' 10757db96d56Sopenharmony_ci 10767db96d56Sopenharmony_ci def __init__(self, stream=None): 10777db96d56Sopenharmony_ci """ 10787db96d56Sopenharmony_ci Initialize the handler. 10797db96d56Sopenharmony_ci 10807db96d56Sopenharmony_ci If stream is not specified, sys.stderr is used. 10817db96d56Sopenharmony_ci """ 10827db96d56Sopenharmony_ci Handler.__init__(self) 10837db96d56Sopenharmony_ci if stream is None: 10847db96d56Sopenharmony_ci stream = sys.stderr 10857db96d56Sopenharmony_ci self.stream = stream 10867db96d56Sopenharmony_ci 10877db96d56Sopenharmony_ci def flush(self): 10887db96d56Sopenharmony_ci """ 10897db96d56Sopenharmony_ci Flushes the stream. 10907db96d56Sopenharmony_ci """ 10917db96d56Sopenharmony_ci self.acquire() 10927db96d56Sopenharmony_ci try: 10937db96d56Sopenharmony_ci if self.stream and hasattr(self.stream, "flush"): 10947db96d56Sopenharmony_ci self.stream.flush() 10957db96d56Sopenharmony_ci finally: 10967db96d56Sopenharmony_ci self.release() 10977db96d56Sopenharmony_ci 10987db96d56Sopenharmony_ci def emit(self, record): 10997db96d56Sopenharmony_ci """ 11007db96d56Sopenharmony_ci Emit a record. 11017db96d56Sopenharmony_ci 11027db96d56Sopenharmony_ci If a formatter is specified, it is used to format the record. 11037db96d56Sopenharmony_ci The record is then written to the stream with a trailing newline. If 11047db96d56Sopenharmony_ci exception information is present, it is formatted using 11057db96d56Sopenharmony_ci traceback.print_exception and appended to the stream. If the stream 11067db96d56Sopenharmony_ci has an 'encoding' attribute, it is used to determine how to do the 11077db96d56Sopenharmony_ci output to the stream. 11087db96d56Sopenharmony_ci """ 11097db96d56Sopenharmony_ci try: 11107db96d56Sopenharmony_ci msg = self.format(record) 11117db96d56Sopenharmony_ci stream = self.stream 11127db96d56Sopenharmony_ci # issue 35046: merged two stream.writes into one. 11137db96d56Sopenharmony_ci stream.write(msg + self.terminator) 11147db96d56Sopenharmony_ci self.flush() 11157db96d56Sopenharmony_ci except RecursionError: # See issue 36272 11167db96d56Sopenharmony_ci raise 11177db96d56Sopenharmony_ci except Exception: 11187db96d56Sopenharmony_ci self.handleError(record) 11197db96d56Sopenharmony_ci 11207db96d56Sopenharmony_ci def setStream(self, stream): 11217db96d56Sopenharmony_ci """ 11227db96d56Sopenharmony_ci Sets the StreamHandler's stream to the specified value, 11237db96d56Sopenharmony_ci if it is different. 11247db96d56Sopenharmony_ci 11257db96d56Sopenharmony_ci Returns the old stream, if the stream was changed, or None 11267db96d56Sopenharmony_ci if it wasn't. 11277db96d56Sopenharmony_ci """ 11287db96d56Sopenharmony_ci if stream is self.stream: 11297db96d56Sopenharmony_ci result = None 11307db96d56Sopenharmony_ci else: 11317db96d56Sopenharmony_ci result = self.stream 11327db96d56Sopenharmony_ci self.acquire() 11337db96d56Sopenharmony_ci try: 11347db96d56Sopenharmony_ci self.flush() 11357db96d56Sopenharmony_ci self.stream = stream 11367db96d56Sopenharmony_ci finally: 11377db96d56Sopenharmony_ci self.release() 11387db96d56Sopenharmony_ci return result 11397db96d56Sopenharmony_ci 11407db96d56Sopenharmony_ci def __repr__(self): 11417db96d56Sopenharmony_ci level = getLevelName(self.level) 11427db96d56Sopenharmony_ci name = getattr(self.stream, 'name', '') 11437db96d56Sopenharmony_ci # bpo-36015: name can be an int 11447db96d56Sopenharmony_ci name = str(name) 11457db96d56Sopenharmony_ci if name: 11467db96d56Sopenharmony_ci name += ' ' 11477db96d56Sopenharmony_ci return '<%s %s(%s)>' % (self.__class__.__name__, name, level) 11487db96d56Sopenharmony_ci 11497db96d56Sopenharmony_ci __class_getitem__ = classmethod(GenericAlias) 11507db96d56Sopenharmony_ci 11517db96d56Sopenharmony_ci 11527db96d56Sopenharmony_ciclass FileHandler(StreamHandler): 11537db96d56Sopenharmony_ci """ 11547db96d56Sopenharmony_ci A handler class which writes formatted logging records to disk files. 11557db96d56Sopenharmony_ci """ 11567db96d56Sopenharmony_ci def __init__(self, filename, mode='a', encoding=None, delay=False, errors=None): 11577db96d56Sopenharmony_ci """ 11587db96d56Sopenharmony_ci Open the specified file and use it as the stream for logging. 11597db96d56Sopenharmony_ci """ 11607db96d56Sopenharmony_ci # Issue #27493: add support for Path objects to be passed in 11617db96d56Sopenharmony_ci filename = os.fspath(filename) 11627db96d56Sopenharmony_ci #keep the absolute path, otherwise derived classes which use this 11637db96d56Sopenharmony_ci #may come a cropper when the current directory changes 11647db96d56Sopenharmony_ci self.baseFilename = os.path.abspath(filename) 11657db96d56Sopenharmony_ci self.mode = mode 11667db96d56Sopenharmony_ci self.encoding = encoding 11677db96d56Sopenharmony_ci if "b" not in mode: 11687db96d56Sopenharmony_ci self.encoding = io.text_encoding(encoding) 11697db96d56Sopenharmony_ci self.errors = errors 11707db96d56Sopenharmony_ci self.delay = delay 11717db96d56Sopenharmony_ci # bpo-26789: FileHandler keeps a reference to the builtin open() 11727db96d56Sopenharmony_ci # function to be able to open or reopen the file during Python 11737db96d56Sopenharmony_ci # finalization. 11747db96d56Sopenharmony_ci self._builtin_open = open 11757db96d56Sopenharmony_ci if delay: 11767db96d56Sopenharmony_ci #We don't open the stream, but we still need to call the 11777db96d56Sopenharmony_ci #Handler constructor to set level, formatter, lock etc. 11787db96d56Sopenharmony_ci Handler.__init__(self) 11797db96d56Sopenharmony_ci self.stream = None 11807db96d56Sopenharmony_ci else: 11817db96d56Sopenharmony_ci StreamHandler.__init__(self, self._open()) 11827db96d56Sopenharmony_ci 11837db96d56Sopenharmony_ci def close(self): 11847db96d56Sopenharmony_ci """ 11857db96d56Sopenharmony_ci Closes the stream. 11867db96d56Sopenharmony_ci """ 11877db96d56Sopenharmony_ci self.acquire() 11887db96d56Sopenharmony_ci try: 11897db96d56Sopenharmony_ci try: 11907db96d56Sopenharmony_ci if self.stream: 11917db96d56Sopenharmony_ci try: 11927db96d56Sopenharmony_ci self.flush() 11937db96d56Sopenharmony_ci finally: 11947db96d56Sopenharmony_ci stream = self.stream 11957db96d56Sopenharmony_ci self.stream = None 11967db96d56Sopenharmony_ci if hasattr(stream, "close"): 11977db96d56Sopenharmony_ci stream.close() 11987db96d56Sopenharmony_ci finally: 11997db96d56Sopenharmony_ci # Issue #19523: call unconditionally to 12007db96d56Sopenharmony_ci # prevent a handler leak when delay is set 12017db96d56Sopenharmony_ci # Also see Issue #42378: we also rely on 12027db96d56Sopenharmony_ci # self._closed being set to True there 12037db96d56Sopenharmony_ci StreamHandler.close(self) 12047db96d56Sopenharmony_ci finally: 12057db96d56Sopenharmony_ci self.release() 12067db96d56Sopenharmony_ci 12077db96d56Sopenharmony_ci def _open(self): 12087db96d56Sopenharmony_ci """ 12097db96d56Sopenharmony_ci Open the current base file with the (original) mode and encoding. 12107db96d56Sopenharmony_ci Return the resulting stream. 12117db96d56Sopenharmony_ci """ 12127db96d56Sopenharmony_ci open_func = self._builtin_open 12137db96d56Sopenharmony_ci return open_func(self.baseFilename, self.mode, 12147db96d56Sopenharmony_ci encoding=self.encoding, errors=self.errors) 12157db96d56Sopenharmony_ci 12167db96d56Sopenharmony_ci def emit(self, record): 12177db96d56Sopenharmony_ci """ 12187db96d56Sopenharmony_ci Emit a record. 12197db96d56Sopenharmony_ci 12207db96d56Sopenharmony_ci If the stream was not opened because 'delay' was specified in the 12217db96d56Sopenharmony_ci constructor, open it before calling the superclass's emit. 12227db96d56Sopenharmony_ci 12237db96d56Sopenharmony_ci If stream is not open, current mode is 'w' and `_closed=True`, record 12247db96d56Sopenharmony_ci will not be emitted (see Issue #42378). 12257db96d56Sopenharmony_ci """ 12267db96d56Sopenharmony_ci if self.stream is None: 12277db96d56Sopenharmony_ci if self.mode != 'w' or not self._closed: 12287db96d56Sopenharmony_ci self.stream = self._open() 12297db96d56Sopenharmony_ci if self.stream: 12307db96d56Sopenharmony_ci StreamHandler.emit(self, record) 12317db96d56Sopenharmony_ci 12327db96d56Sopenharmony_ci def __repr__(self): 12337db96d56Sopenharmony_ci level = getLevelName(self.level) 12347db96d56Sopenharmony_ci return '<%s %s (%s)>' % (self.__class__.__name__, self.baseFilename, level) 12357db96d56Sopenharmony_ci 12367db96d56Sopenharmony_ci 12377db96d56Sopenharmony_ciclass _StderrHandler(StreamHandler): 12387db96d56Sopenharmony_ci """ 12397db96d56Sopenharmony_ci This class is like a StreamHandler using sys.stderr, but always uses 12407db96d56Sopenharmony_ci whatever sys.stderr is currently set to rather than the value of 12417db96d56Sopenharmony_ci sys.stderr at handler construction time. 12427db96d56Sopenharmony_ci """ 12437db96d56Sopenharmony_ci def __init__(self, level=NOTSET): 12447db96d56Sopenharmony_ci """ 12457db96d56Sopenharmony_ci Initialize the handler. 12467db96d56Sopenharmony_ci """ 12477db96d56Sopenharmony_ci Handler.__init__(self, level) 12487db96d56Sopenharmony_ci 12497db96d56Sopenharmony_ci @property 12507db96d56Sopenharmony_ci def stream(self): 12517db96d56Sopenharmony_ci return sys.stderr 12527db96d56Sopenharmony_ci 12537db96d56Sopenharmony_ci 12547db96d56Sopenharmony_ci_defaultLastResort = _StderrHandler(WARNING) 12557db96d56Sopenharmony_cilastResort = _defaultLastResort 12567db96d56Sopenharmony_ci 12577db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 12587db96d56Sopenharmony_ci# Manager classes and functions 12597db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 12607db96d56Sopenharmony_ci 12617db96d56Sopenharmony_ciclass PlaceHolder(object): 12627db96d56Sopenharmony_ci """ 12637db96d56Sopenharmony_ci PlaceHolder instances are used in the Manager logger hierarchy to take 12647db96d56Sopenharmony_ci the place of nodes for which no loggers have been defined. This class is 12657db96d56Sopenharmony_ci intended for internal use only and not as part of the public API. 12667db96d56Sopenharmony_ci """ 12677db96d56Sopenharmony_ci def __init__(self, alogger): 12687db96d56Sopenharmony_ci """ 12697db96d56Sopenharmony_ci Initialize with the specified logger being a child of this placeholder. 12707db96d56Sopenharmony_ci """ 12717db96d56Sopenharmony_ci self.loggerMap = { alogger : None } 12727db96d56Sopenharmony_ci 12737db96d56Sopenharmony_ci def append(self, alogger): 12747db96d56Sopenharmony_ci """ 12757db96d56Sopenharmony_ci Add the specified logger as a child of this placeholder. 12767db96d56Sopenharmony_ci """ 12777db96d56Sopenharmony_ci if alogger not in self.loggerMap: 12787db96d56Sopenharmony_ci self.loggerMap[alogger] = None 12797db96d56Sopenharmony_ci 12807db96d56Sopenharmony_ci# 12817db96d56Sopenharmony_ci# Determine which class to use when instantiating loggers. 12827db96d56Sopenharmony_ci# 12837db96d56Sopenharmony_ci 12847db96d56Sopenharmony_cidef setLoggerClass(klass): 12857db96d56Sopenharmony_ci """ 12867db96d56Sopenharmony_ci Set the class to be used when instantiating a logger. The class should 12877db96d56Sopenharmony_ci define __init__() such that only a name argument is required, and the 12887db96d56Sopenharmony_ci __init__() should call Logger.__init__() 12897db96d56Sopenharmony_ci """ 12907db96d56Sopenharmony_ci if klass != Logger: 12917db96d56Sopenharmony_ci if not issubclass(klass, Logger): 12927db96d56Sopenharmony_ci raise TypeError("logger not derived from logging.Logger: " 12937db96d56Sopenharmony_ci + klass.__name__) 12947db96d56Sopenharmony_ci global _loggerClass 12957db96d56Sopenharmony_ci _loggerClass = klass 12967db96d56Sopenharmony_ci 12977db96d56Sopenharmony_cidef getLoggerClass(): 12987db96d56Sopenharmony_ci """ 12997db96d56Sopenharmony_ci Return the class to be used when instantiating a logger. 13007db96d56Sopenharmony_ci """ 13017db96d56Sopenharmony_ci return _loggerClass 13027db96d56Sopenharmony_ci 13037db96d56Sopenharmony_ciclass Manager(object): 13047db96d56Sopenharmony_ci """ 13057db96d56Sopenharmony_ci There is [under normal circumstances] just one Manager instance, which 13067db96d56Sopenharmony_ci holds the hierarchy of loggers. 13077db96d56Sopenharmony_ci """ 13087db96d56Sopenharmony_ci def __init__(self, rootnode): 13097db96d56Sopenharmony_ci """ 13107db96d56Sopenharmony_ci Initialize the manager with the root node of the logger hierarchy. 13117db96d56Sopenharmony_ci """ 13127db96d56Sopenharmony_ci self.root = rootnode 13137db96d56Sopenharmony_ci self.disable = 0 13147db96d56Sopenharmony_ci self.emittedNoHandlerWarning = False 13157db96d56Sopenharmony_ci self.loggerDict = {} 13167db96d56Sopenharmony_ci self.loggerClass = None 13177db96d56Sopenharmony_ci self.logRecordFactory = None 13187db96d56Sopenharmony_ci 13197db96d56Sopenharmony_ci @property 13207db96d56Sopenharmony_ci def disable(self): 13217db96d56Sopenharmony_ci return self._disable 13227db96d56Sopenharmony_ci 13237db96d56Sopenharmony_ci @disable.setter 13247db96d56Sopenharmony_ci def disable(self, value): 13257db96d56Sopenharmony_ci self._disable = _checkLevel(value) 13267db96d56Sopenharmony_ci 13277db96d56Sopenharmony_ci def getLogger(self, name): 13287db96d56Sopenharmony_ci """ 13297db96d56Sopenharmony_ci Get a logger with the specified name (channel name), creating it 13307db96d56Sopenharmony_ci if it doesn't yet exist. This name is a dot-separated hierarchical 13317db96d56Sopenharmony_ci name, such as "a", "a.b", "a.b.c" or similar. 13327db96d56Sopenharmony_ci 13337db96d56Sopenharmony_ci If a PlaceHolder existed for the specified name [i.e. the logger 13347db96d56Sopenharmony_ci didn't exist but a child of it did], replace it with the created 13357db96d56Sopenharmony_ci logger and fix up the parent/child references which pointed to the 13367db96d56Sopenharmony_ci placeholder to now point to the logger. 13377db96d56Sopenharmony_ci """ 13387db96d56Sopenharmony_ci rv = None 13397db96d56Sopenharmony_ci if not isinstance(name, str): 13407db96d56Sopenharmony_ci raise TypeError('A logger name must be a string') 13417db96d56Sopenharmony_ci _acquireLock() 13427db96d56Sopenharmony_ci try: 13437db96d56Sopenharmony_ci if name in self.loggerDict: 13447db96d56Sopenharmony_ci rv = self.loggerDict[name] 13457db96d56Sopenharmony_ci if isinstance(rv, PlaceHolder): 13467db96d56Sopenharmony_ci ph = rv 13477db96d56Sopenharmony_ci rv = (self.loggerClass or _loggerClass)(name) 13487db96d56Sopenharmony_ci rv.manager = self 13497db96d56Sopenharmony_ci self.loggerDict[name] = rv 13507db96d56Sopenharmony_ci self._fixupChildren(ph, rv) 13517db96d56Sopenharmony_ci self._fixupParents(rv) 13527db96d56Sopenharmony_ci else: 13537db96d56Sopenharmony_ci rv = (self.loggerClass or _loggerClass)(name) 13547db96d56Sopenharmony_ci rv.manager = self 13557db96d56Sopenharmony_ci self.loggerDict[name] = rv 13567db96d56Sopenharmony_ci self._fixupParents(rv) 13577db96d56Sopenharmony_ci finally: 13587db96d56Sopenharmony_ci _releaseLock() 13597db96d56Sopenharmony_ci return rv 13607db96d56Sopenharmony_ci 13617db96d56Sopenharmony_ci def setLoggerClass(self, klass): 13627db96d56Sopenharmony_ci """ 13637db96d56Sopenharmony_ci Set the class to be used when instantiating a logger with this Manager. 13647db96d56Sopenharmony_ci """ 13657db96d56Sopenharmony_ci if klass != Logger: 13667db96d56Sopenharmony_ci if not issubclass(klass, Logger): 13677db96d56Sopenharmony_ci raise TypeError("logger not derived from logging.Logger: " 13687db96d56Sopenharmony_ci + klass.__name__) 13697db96d56Sopenharmony_ci self.loggerClass = klass 13707db96d56Sopenharmony_ci 13717db96d56Sopenharmony_ci def setLogRecordFactory(self, factory): 13727db96d56Sopenharmony_ci """ 13737db96d56Sopenharmony_ci Set the factory to be used when instantiating a log record with this 13747db96d56Sopenharmony_ci Manager. 13757db96d56Sopenharmony_ci """ 13767db96d56Sopenharmony_ci self.logRecordFactory = factory 13777db96d56Sopenharmony_ci 13787db96d56Sopenharmony_ci def _fixupParents(self, alogger): 13797db96d56Sopenharmony_ci """ 13807db96d56Sopenharmony_ci Ensure that there are either loggers or placeholders all the way 13817db96d56Sopenharmony_ci from the specified logger to the root of the logger hierarchy. 13827db96d56Sopenharmony_ci """ 13837db96d56Sopenharmony_ci name = alogger.name 13847db96d56Sopenharmony_ci i = name.rfind(".") 13857db96d56Sopenharmony_ci rv = None 13867db96d56Sopenharmony_ci while (i > 0) and not rv: 13877db96d56Sopenharmony_ci substr = name[:i] 13887db96d56Sopenharmony_ci if substr not in self.loggerDict: 13897db96d56Sopenharmony_ci self.loggerDict[substr] = PlaceHolder(alogger) 13907db96d56Sopenharmony_ci else: 13917db96d56Sopenharmony_ci obj = self.loggerDict[substr] 13927db96d56Sopenharmony_ci if isinstance(obj, Logger): 13937db96d56Sopenharmony_ci rv = obj 13947db96d56Sopenharmony_ci else: 13957db96d56Sopenharmony_ci assert isinstance(obj, PlaceHolder) 13967db96d56Sopenharmony_ci obj.append(alogger) 13977db96d56Sopenharmony_ci i = name.rfind(".", 0, i - 1) 13987db96d56Sopenharmony_ci if not rv: 13997db96d56Sopenharmony_ci rv = self.root 14007db96d56Sopenharmony_ci alogger.parent = rv 14017db96d56Sopenharmony_ci 14027db96d56Sopenharmony_ci def _fixupChildren(self, ph, alogger): 14037db96d56Sopenharmony_ci """ 14047db96d56Sopenharmony_ci Ensure that children of the placeholder ph are connected to the 14057db96d56Sopenharmony_ci specified logger. 14067db96d56Sopenharmony_ci """ 14077db96d56Sopenharmony_ci name = alogger.name 14087db96d56Sopenharmony_ci namelen = len(name) 14097db96d56Sopenharmony_ci for c in ph.loggerMap.keys(): 14107db96d56Sopenharmony_ci #The if means ... if not c.parent.name.startswith(nm) 14117db96d56Sopenharmony_ci if c.parent.name[:namelen] != name: 14127db96d56Sopenharmony_ci alogger.parent = c.parent 14137db96d56Sopenharmony_ci c.parent = alogger 14147db96d56Sopenharmony_ci 14157db96d56Sopenharmony_ci def _clear_cache(self): 14167db96d56Sopenharmony_ci """ 14177db96d56Sopenharmony_ci Clear the cache for all loggers in loggerDict 14187db96d56Sopenharmony_ci Called when level changes are made 14197db96d56Sopenharmony_ci """ 14207db96d56Sopenharmony_ci 14217db96d56Sopenharmony_ci _acquireLock() 14227db96d56Sopenharmony_ci for logger in self.loggerDict.values(): 14237db96d56Sopenharmony_ci if isinstance(logger, Logger): 14247db96d56Sopenharmony_ci logger._cache.clear() 14257db96d56Sopenharmony_ci self.root._cache.clear() 14267db96d56Sopenharmony_ci _releaseLock() 14277db96d56Sopenharmony_ci 14287db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 14297db96d56Sopenharmony_ci# Logger classes and functions 14307db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 14317db96d56Sopenharmony_ci 14327db96d56Sopenharmony_ciclass Logger(Filterer): 14337db96d56Sopenharmony_ci """ 14347db96d56Sopenharmony_ci Instances of the Logger class represent a single logging channel. A 14357db96d56Sopenharmony_ci "logging channel" indicates an area of an application. Exactly how an 14367db96d56Sopenharmony_ci "area" is defined is up to the application developer. Since an 14377db96d56Sopenharmony_ci application can have any number of areas, logging channels are identified 14387db96d56Sopenharmony_ci by a unique string. Application areas can be nested (e.g. an area 14397db96d56Sopenharmony_ci of "input processing" might include sub-areas "read CSV files", "read 14407db96d56Sopenharmony_ci XLS files" and "read Gnumeric files"). To cater for this natural nesting, 14417db96d56Sopenharmony_ci channel names are organized into a namespace hierarchy where levels are 14427db96d56Sopenharmony_ci separated by periods, much like the Java or Python package namespace. So 14437db96d56Sopenharmony_ci in the instance given above, channel names might be "input" for the upper 14447db96d56Sopenharmony_ci level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels. 14457db96d56Sopenharmony_ci There is no arbitrary limit to the depth of nesting. 14467db96d56Sopenharmony_ci """ 14477db96d56Sopenharmony_ci def __init__(self, name, level=NOTSET): 14487db96d56Sopenharmony_ci """ 14497db96d56Sopenharmony_ci Initialize the logger with a name and an optional level. 14507db96d56Sopenharmony_ci """ 14517db96d56Sopenharmony_ci Filterer.__init__(self) 14527db96d56Sopenharmony_ci self.name = name 14537db96d56Sopenharmony_ci self.level = _checkLevel(level) 14547db96d56Sopenharmony_ci self.parent = None 14557db96d56Sopenharmony_ci self.propagate = True 14567db96d56Sopenharmony_ci self.handlers = [] 14577db96d56Sopenharmony_ci self.disabled = False 14587db96d56Sopenharmony_ci self._cache = {} 14597db96d56Sopenharmony_ci 14607db96d56Sopenharmony_ci def setLevel(self, level): 14617db96d56Sopenharmony_ci """ 14627db96d56Sopenharmony_ci Set the logging level of this logger. level must be an int or a str. 14637db96d56Sopenharmony_ci """ 14647db96d56Sopenharmony_ci self.level = _checkLevel(level) 14657db96d56Sopenharmony_ci self.manager._clear_cache() 14667db96d56Sopenharmony_ci 14677db96d56Sopenharmony_ci def debug(self, msg, *args, **kwargs): 14687db96d56Sopenharmony_ci """ 14697db96d56Sopenharmony_ci Log 'msg % args' with severity 'DEBUG'. 14707db96d56Sopenharmony_ci 14717db96d56Sopenharmony_ci To pass exception information, use the keyword argument exc_info with 14727db96d56Sopenharmony_ci a true value, e.g. 14737db96d56Sopenharmony_ci 14747db96d56Sopenharmony_ci logger.debug("Houston, we have a %s", "thorny problem", exc_info=1) 14757db96d56Sopenharmony_ci """ 14767db96d56Sopenharmony_ci if self.isEnabledFor(DEBUG): 14777db96d56Sopenharmony_ci self._log(DEBUG, msg, args, **kwargs) 14787db96d56Sopenharmony_ci 14797db96d56Sopenharmony_ci def info(self, msg, *args, **kwargs): 14807db96d56Sopenharmony_ci """ 14817db96d56Sopenharmony_ci Log 'msg % args' with severity 'INFO'. 14827db96d56Sopenharmony_ci 14837db96d56Sopenharmony_ci To pass exception information, use the keyword argument exc_info with 14847db96d56Sopenharmony_ci a true value, e.g. 14857db96d56Sopenharmony_ci 14867db96d56Sopenharmony_ci logger.info("Houston, we have a %s", "interesting problem", exc_info=1) 14877db96d56Sopenharmony_ci """ 14887db96d56Sopenharmony_ci if self.isEnabledFor(INFO): 14897db96d56Sopenharmony_ci self._log(INFO, msg, args, **kwargs) 14907db96d56Sopenharmony_ci 14917db96d56Sopenharmony_ci def warning(self, msg, *args, **kwargs): 14927db96d56Sopenharmony_ci """ 14937db96d56Sopenharmony_ci Log 'msg % args' with severity 'WARNING'. 14947db96d56Sopenharmony_ci 14957db96d56Sopenharmony_ci To pass exception information, use the keyword argument exc_info with 14967db96d56Sopenharmony_ci a true value, e.g. 14977db96d56Sopenharmony_ci 14987db96d56Sopenharmony_ci logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1) 14997db96d56Sopenharmony_ci """ 15007db96d56Sopenharmony_ci if self.isEnabledFor(WARNING): 15017db96d56Sopenharmony_ci self._log(WARNING, msg, args, **kwargs) 15027db96d56Sopenharmony_ci 15037db96d56Sopenharmony_ci def warn(self, msg, *args, **kwargs): 15047db96d56Sopenharmony_ci warnings.warn("The 'warn' method is deprecated, " 15057db96d56Sopenharmony_ci "use 'warning' instead", DeprecationWarning, 2) 15067db96d56Sopenharmony_ci self.warning(msg, *args, **kwargs) 15077db96d56Sopenharmony_ci 15087db96d56Sopenharmony_ci def error(self, msg, *args, **kwargs): 15097db96d56Sopenharmony_ci """ 15107db96d56Sopenharmony_ci Log 'msg % args' with severity 'ERROR'. 15117db96d56Sopenharmony_ci 15127db96d56Sopenharmony_ci To pass exception information, use the keyword argument exc_info with 15137db96d56Sopenharmony_ci a true value, e.g. 15147db96d56Sopenharmony_ci 15157db96d56Sopenharmony_ci logger.error("Houston, we have a %s", "major problem", exc_info=1) 15167db96d56Sopenharmony_ci """ 15177db96d56Sopenharmony_ci if self.isEnabledFor(ERROR): 15187db96d56Sopenharmony_ci self._log(ERROR, msg, args, **kwargs) 15197db96d56Sopenharmony_ci 15207db96d56Sopenharmony_ci def exception(self, msg, *args, exc_info=True, **kwargs): 15217db96d56Sopenharmony_ci """ 15227db96d56Sopenharmony_ci Convenience method for logging an ERROR with exception information. 15237db96d56Sopenharmony_ci """ 15247db96d56Sopenharmony_ci self.error(msg, *args, exc_info=exc_info, **kwargs) 15257db96d56Sopenharmony_ci 15267db96d56Sopenharmony_ci def critical(self, msg, *args, **kwargs): 15277db96d56Sopenharmony_ci """ 15287db96d56Sopenharmony_ci Log 'msg % args' with severity 'CRITICAL'. 15297db96d56Sopenharmony_ci 15307db96d56Sopenharmony_ci To pass exception information, use the keyword argument exc_info with 15317db96d56Sopenharmony_ci a true value, e.g. 15327db96d56Sopenharmony_ci 15337db96d56Sopenharmony_ci logger.critical("Houston, we have a %s", "major disaster", exc_info=1) 15347db96d56Sopenharmony_ci """ 15357db96d56Sopenharmony_ci if self.isEnabledFor(CRITICAL): 15367db96d56Sopenharmony_ci self._log(CRITICAL, msg, args, **kwargs) 15377db96d56Sopenharmony_ci 15387db96d56Sopenharmony_ci def fatal(self, msg, *args, **kwargs): 15397db96d56Sopenharmony_ci """ 15407db96d56Sopenharmony_ci Don't use this method, use critical() instead. 15417db96d56Sopenharmony_ci """ 15427db96d56Sopenharmony_ci self.critical(msg, *args, **kwargs) 15437db96d56Sopenharmony_ci 15447db96d56Sopenharmony_ci def log(self, level, msg, *args, **kwargs): 15457db96d56Sopenharmony_ci """ 15467db96d56Sopenharmony_ci Log 'msg % args' with the integer severity 'level'. 15477db96d56Sopenharmony_ci 15487db96d56Sopenharmony_ci To pass exception information, use the keyword argument exc_info with 15497db96d56Sopenharmony_ci a true value, e.g. 15507db96d56Sopenharmony_ci 15517db96d56Sopenharmony_ci logger.log(level, "We have a %s", "mysterious problem", exc_info=1) 15527db96d56Sopenharmony_ci """ 15537db96d56Sopenharmony_ci if not isinstance(level, int): 15547db96d56Sopenharmony_ci if raiseExceptions: 15557db96d56Sopenharmony_ci raise TypeError("level must be an integer") 15567db96d56Sopenharmony_ci else: 15577db96d56Sopenharmony_ci return 15587db96d56Sopenharmony_ci if self.isEnabledFor(level): 15597db96d56Sopenharmony_ci self._log(level, msg, args, **kwargs) 15607db96d56Sopenharmony_ci 15617db96d56Sopenharmony_ci def findCaller(self, stack_info=False, stacklevel=1): 15627db96d56Sopenharmony_ci """ 15637db96d56Sopenharmony_ci Find the stack frame of the caller so that we can note the source 15647db96d56Sopenharmony_ci file name, line number and function name. 15657db96d56Sopenharmony_ci """ 15667db96d56Sopenharmony_ci f = currentframe() 15677db96d56Sopenharmony_ci #On some versions of IronPython, currentframe() returns None if 15687db96d56Sopenharmony_ci #IronPython isn't run with -X:Frames. 15697db96d56Sopenharmony_ci if f is None: 15707db96d56Sopenharmony_ci return "(unknown file)", 0, "(unknown function)", None 15717db96d56Sopenharmony_ci while stacklevel > 0: 15727db96d56Sopenharmony_ci next_f = f.f_back 15737db96d56Sopenharmony_ci if next_f is None: 15747db96d56Sopenharmony_ci ## We've got options here. 15757db96d56Sopenharmony_ci ## If we want to use the last (deepest) frame: 15767db96d56Sopenharmony_ci break 15777db96d56Sopenharmony_ci ## If we want to mimic the warnings module: 15787db96d56Sopenharmony_ci #return ("sys", 1, "(unknown function)", None) 15797db96d56Sopenharmony_ci ## If we want to be pedantic: 15807db96d56Sopenharmony_ci #raise ValueError("call stack is not deep enough") 15817db96d56Sopenharmony_ci f = next_f 15827db96d56Sopenharmony_ci if not _is_internal_frame(f): 15837db96d56Sopenharmony_ci stacklevel -= 1 15847db96d56Sopenharmony_ci co = f.f_code 15857db96d56Sopenharmony_ci sinfo = None 15867db96d56Sopenharmony_ci if stack_info: 15877db96d56Sopenharmony_ci with io.StringIO() as sio: 15887db96d56Sopenharmony_ci sio.write("Stack (most recent call last):\n") 15897db96d56Sopenharmony_ci traceback.print_stack(f, file=sio) 15907db96d56Sopenharmony_ci sinfo = sio.getvalue() 15917db96d56Sopenharmony_ci if sinfo[-1] == '\n': 15927db96d56Sopenharmony_ci sinfo = sinfo[:-1] 15937db96d56Sopenharmony_ci return co.co_filename, f.f_lineno, co.co_name, sinfo 15947db96d56Sopenharmony_ci 15957db96d56Sopenharmony_ci def makeRecord(self, name, level, fn, lno, msg, args, exc_info, 15967db96d56Sopenharmony_ci func=None, extra=None, sinfo=None): 15977db96d56Sopenharmony_ci """ 15987db96d56Sopenharmony_ci A factory method which can be overridden in subclasses to create 15997db96d56Sopenharmony_ci specialized LogRecords. 16007db96d56Sopenharmony_ci """ 16017db96d56Sopenharmony_ci rv = _logRecordFactory(name, level, fn, lno, msg, args, exc_info, func, 16027db96d56Sopenharmony_ci sinfo) 16037db96d56Sopenharmony_ci if extra is not None: 16047db96d56Sopenharmony_ci for key in extra: 16057db96d56Sopenharmony_ci if (key in ["message", "asctime"]) or (key in rv.__dict__): 16067db96d56Sopenharmony_ci raise KeyError("Attempt to overwrite %r in LogRecord" % key) 16077db96d56Sopenharmony_ci rv.__dict__[key] = extra[key] 16087db96d56Sopenharmony_ci return rv 16097db96d56Sopenharmony_ci 16107db96d56Sopenharmony_ci def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False, 16117db96d56Sopenharmony_ci stacklevel=1): 16127db96d56Sopenharmony_ci """ 16137db96d56Sopenharmony_ci Low-level logging routine which creates a LogRecord and then calls 16147db96d56Sopenharmony_ci all the handlers of this logger to handle the record. 16157db96d56Sopenharmony_ci """ 16167db96d56Sopenharmony_ci sinfo = None 16177db96d56Sopenharmony_ci if _srcfile: 16187db96d56Sopenharmony_ci #IronPython doesn't track Python frames, so findCaller raises an 16197db96d56Sopenharmony_ci #exception on some versions of IronPython. We trap it here so that 16207db96d56Sopenharmony_ci #IronPython can use logging. 16217db96d56Sopenharmony_ci try: 16227db96d56Sopenharmony_ci fn, lno, func, sinfo = self.findCaller(stack_info, stacklevel) 16237db96d56Sopenharmony_ci except ValueError: # pragma: no cover 16247db96d56Sopenharmony_ci fn, lno, func = "(unknown file)", 0, "(unknown function)" 16257db96d56Sopenharmony_ci else: # pragma: no cover 16267db96d56Sopenharmony_ci fn, lno, func = "(unknown file)", 0, "(unknown function)" 16277db96d56Sopenharmony_ci if exc_info: 16287db96d56Sopenharmony_ci if isinstance(exc_info, BaseException): 16297db96d56Sopenharmony_ci exc_info = (type(exc_info), exc_info, exc_info.__traceback__) 16307db96d56Sopenharmony_ci elif not isinstance(exc_info, tuple): 16317db96d56Sopenharmony_ci exc_info = sys.exc_info() 16327db96d56Sopenharmony_ci record = self.makeRecord(self.name, level, fn, lno, msg, args, 16337db96d56Sopenharmony_ci exc_info, func, extra, sinfo) 16347db96d56Sopenharmony_ci self.handle(record) 16357db96d56Sopenharmony_ci 16367db96d56Sopenharmony_ci def handle(self, record): 16377db96d56Sopenharmony_ci """ 16387db96d56Sopenharmony_ci Call the handlers for the specified record. 16397db96d56Sopenharmony_ci 16407db96d56Sopenharmony_ci This method is used for unpickled records received from a socket, as 16417db96d56Sopenharmony_ci well as those created locally. Logger-level filtering is applied. 16427db96d56Sopenharmony_ci """ 16437db96d56Sopenharmony_ci if (not self.disabled) and self.filter(record): 16447db96d56Sopenharmony_ci self.callHandlers(record) 16457db96d56Sopenharmony_ci 16467db96d56Sopenharmony_ci def addHandler(self, hdlr): 16477db96d56Sopenharmony_ci """ 16487db96d56Sopenharmony_ci Add the specified handler to this logger. 16497db96d56Sopenharmony_ci """ 16507db96d56Sopenharmony_ci _acquireLock() 16517db96d56Sopenharmony_ci try: 16527db96d56Sopenharmony_ci if not (hdlr in self.handlers): 16537db96d56Sopenharmony_ci self.handlers.append(hdlr) 16547db96d56Sopenharmony_ci finally: 16557db96d56Sopenharmony_ci _releaseLock() 16567db96d56Sopenharmony_ci 16577db96d56Sopenharmony_ci def removeHandler(self, hdlr): 16587db96d56Sopenharmony_ci """ 16597db96d56Sopenharmony_ci Remove the specified handler from this logger. 16607db96d56Sopenharmony_ci """ 16617db96d56Sopenharmony_ci _acquireLock() 16627db96d56Sopenharmony_ci try: 16637db96d56Sopenharmony_ci if hdlr in self.handlers: 16647db96d56Sopenharmony_ci self.handlers.remove(hdlr) 16657db96d56Sopenharmony_ci finally: 16667db96d56Sopenharmony_ci _releaseLock() 16677db96d56Sopenharmony_ci 16687db96d56Sopenharmony_ci def hasHandlers(self): 16697db96d56Sopenharmony_ci """ 16707db96d56Sopenharmony_ci See if this logger has any handlers configured. 16717db96d56Sopenharmony_ci 16727db96d56Sopenharmony_ci Loop through all handlers for this logger and its parents in the 16737db96d56Sopenharmony_ci logger hierarchy. Return True if a handler was found, else False. 16747db96d56Sopenharmony_ci Stop searching up the hierarchy whenever a logger with the "propagate" 16757db96d56Sopenharmony_ci attribute set to zero is found - that will be the last logger which 16767db96d56Sopenharmony_ci is checked for the existence of handlers. 16777db96d56Sopenharmony_ci """ 16787db96d56Sopenharmony_ci c = self 16797db96d56Sopenharmony_ci rv = False 16807db96d56Sopenharmony_ci while c: 16817db96d56Sopenharmony_ci if c.handlers: 16827db96d56Sopenharmony_ci rv = True 16837db96d56Sopenharmony_ci break 16847db96d56Sopenharmony_ci if not c.propagate: 16857db96d56Sopenharmony_ci break 16867db96d56Sopenharmony_ci else: 16877db96d56Sopenharmony_ci c = c.parent 16887db96d56Sopenharmony_ci return rv 16897db96d56Sopenharmony_ci 16907db96d56Sopenharmony_ci def callHandlers(self, record): 16917db96d56Sopenharmony_ci """ 16927db96d56Sopenharmony_ci Pass a record to all relevant handlers. 16937db96d56Sopenharmony_ci 16947db96d56Sopenharmony_ci Loop through all handlers for this logger and its parents in the 16957db96d56Sopenharmony_ci logger hierarchy. If no handler was found, output a one-off error 16967db96d56Sopenharmony_ci message to sys.stderr. Stop searching up the hierarchy whenever a 16977db96d56Sopenharmony_ci logger with the "propagate" attribute set to zero is found - that 16987db96d56Sopenharmony_ci will be the last logger whose handlers are called. 16997db96d56Sopenharmony_ci """ 17007db96d56Sopenharmony_ci c = self 17017db96d56Sopenharmony_ci found = 0 17027db96d56Sopenharmony_ci while c: 17037db96d56Sopenharmony_ci for hdlr in c.handlers: 17047db96d56Sopenharmony_ci found = found + 1 17057db96d56Sopenharmony_ci if record.levelno >= hdlr.level: 17067db96d56Sopenharmony_ci hdlr.handle(record) 17077db96d56Sopenharmony_ci if not c.propagate: 17087db96d56Sopenharmony_ci c = None #break out 17097db96d56Sopenharmony_ci else: 17107db96d56Sopenharmony_ci c = c.parent 17117db96d56Sopenharmony_ci if (found == 0): 17127db96d56Sopenharmony_ci if lastResort: 17137db96d56Sopenharmony_ci if record.levelno >= lastResort.level: 17147db96d56Sopenharmony_ci lastResort.handle(record) 17157db96d56Sopenharmony_ci elif raiseExceptions and not self.manager.emittedNoHandlerWarning: 17167db96d56Sopenharmony_ci sys.stderr.write("No handlers could be found for logger" 17177db96d56Sopenharmony_ci " \"%s\"\n" % self.name) 17187db96d56Sopenharmony_ci self.manager.emittedNoHandlerWarning = True 17197db96d56Sopenharmony_ci 17207db96d56Sopenharmony_ci def getEffectiveLevel(self): 17217db96d56Sopenharmony_ci """ 17227db96d56Sopenharmony_ci Get the effective level for this logger. 17237db96d56Sopenharmony_ci 17247db96d56Sopenharmony_ci Loop through this logger and its parents in the logger hierarchy, 17257db96d56Sopenharmony_ci looking for a non-zero logging level. Return the first one found. 17267db96d56Sopenharmony_ci """ 17277db96d56Sopenharmony_ci logger = self 17287db96d56Sopenharmony_ci while logger: 17297db96d56Sopenharmony_ci if logger.level: 17307db96d56Sopenharmony_ci return logger.level 17317db96d56Sopenharmony_ci logger = logger.parent 17327db96d56Sopenharmony_ci return NOTSET 17337db96d56Sopenharmony_ci 17347db96d56Sopenharmony_ci def isEnabledFor(self, level): 17357db96d56Sopenharmony_ci """ 17367db96d56Sopenharmony_ci Is this logger enabled for level 'level'? 17377db96d56Sopenharmony_ci """ 17387db96d56Sopenharmony_ci if self.disabled: 17397db96d56Sopenharmony_ci return False 17407db96d56Sopenharmony_ci 17417db96d56Sopenharmony_ci try: 17427db96d56Sopenharmony_ci return self._cache[level] 17437db96d56Sopenharmony_ci except KeyError: 17447db96d56Sopenharmony_ci _acquireLock() 17457db96d56Sopenharmony_ci try: 17467db96d56Sopenharmony_ci if self.manager.disable >= level: 17477db96d56Sopenharmony_ci is_enabled = self._cache[level] = False 17487db96d56Sopenharmony_ci else: 17497db96d56Sopenharmony_ci is_enabled = self._cache[level] = ( 17507db96d56Sopenharmony_ci level >= self.getEffectiveLevel() 17517db96d56Sopenharmony_ci ) 17527db96d56Sopenharmony_ci finally: 17537db96d56Sopenharmony_ci _releaseLock() 17547db96d56Sopenharmony_ci return is_enabled 17557db96d56Sopenharmony_ci 17567db96d56Sopenharmony_ci def getChild(self, suffix): 17577db96d56Sopenharmony_ci """ 17587db96d56Sopenharmony_ci Get a logger which is a descendant to this one. 17597db96d56Sopenharmony_ci 17607db96d56Sopenharmony_ci This is a convenience method, such that 17617db96d56Sopenharmony_ci 17627db96d56Sopenharmony_ci logging.getLogger('abc').getChild('def.ghi') 17637db96d56Sopenharmony_ci 17647db96d56Sopenharmony_ci is the same as 17657db96d56Sopenharmony_ci 17667db96d56Sopenharmony_ci logging.getLogger('abc.def.ghi') 17677db96d56Sopenharmony_ci 17687db96d56Sopenharmony_ci It's useful, for example, when the parent logger is named using 17697db96d56Sopenharmony_ci __name__ rather than a literal string. 17707db96d56Sopenharmony_ci """ 17717db96d56Sopenharmony_ci if self.root is not self: 17727db96d56Sopenharmony_ci suffix = '.'.join((self.name, suffix)) 17737db96d56Sopenharmony_ci return self.manager.getLogger(suffix) 17747db96d56Sopenharmony_ci 17757db96d56Sopenharmony_ci def __repr__(self): 17767db96d56Sopenharmony_ci level = getLevelName(self.getEffectiveLevel()) 17777db96d56Sopenharmony_ci return '<%s %s (%s)>' % (self.__class__.__name__, self.name, level) 17787db96d56Sopenharmony_ci 17797db96d56Sopenharmony_ci def __reduce__(self): 17807db96d56Sopenharmony_ci if getLogger(self.name) is not self: 17817db96d56Sopenharmony_ci import pickle 17827db96d56Sopenharmony_ci raise pickle.PicklingError('logger cannot be pickled') 17837db96d56Sopenharmony_ci return getLogger, (self.name,) 17847db96d56Sopenharmony_ci 17857db96d56Sopenharmony_ci 17867db96d56Sopenharmony_ciclass RootLogger(Logger): 17877db96d56Sopenharmony_ci """ 17887db96d56Sopenharmony_ci A root logger is not that different to any other logger, except that 17897db96d56Sopenharmony_ci it must have a logging level and there is only one instance of it in 17907db96d56Sopenharmony_ci the hierarchy. 17917db96d56Sopenharmony_ci """ 17927db96d56Sopenharmony_ci def __init__(self, level): 17937db96d56Sopenharmony_ci """ 17947db96d56Sopenharmony_ci Initialize the logger with the name "root". 17957db96d56Sopenharmony_ci """ 17967db96d56Sopenharmony_ci Logger.__init__(self, "root", level) 17977db96d56Sopenharmony_ci 17987db96d56Sopenharmony_ci def __reduce__(self): 17997db96d56Sopenharmony_ci return getLogger, () 18007db96d56Sopenharmony_ci 18017db96d56Sopenharmony_ci_loggerClass = Logger 18027db96d56Sopenharmony_ci 18037db96d56Sopenharmony_ciclass LoggerAdapter(object): 18047db96d56Sopenharmony_ci """ 18057db96d56Sopenharmony_ci An adapter for loggers which makes it easier to specify contextual 18067db96d56Sopenharmony_ci information in logging output. 18077db96d56Sopenharmony_ci """ 18087db96d56Sopenharmony_ci 18097db96d56Sopenharmony_ci def __init__(self, logger, extra=None): 18107db96d56Sopenharmony_ci """ 18117db96d56Sopenharmony_ci Initialize the adapter with a logger and a dict-like object which 18127db96d56Sopenharmony_ci provides contextual information. This constructor signature allows 18137db96d56Sopenharmony_ci easy stacking of LoggerAdapters, if so desired. 18147db96d56Sopenharmony_ci 18157db96d56Sopenharmony_ci You can effectively pass keyword arguments as shown in the 18167db96d56Sopenharmony_ci following example: 18177db96d56Sopenharmony_ci 18187db96d56Sopenharmony_ci adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2")) 18197db96d56Sopenharmony_ci """ 18207db96d56Sopenharmony_ci self.logger = logger 18217db96d56Sopenharmony_ci self.extra = extra 18227db96d56Sopenharmony_ci 18237db96d56Sopenharmony_ci def process(self, msg, kwargs): 18247db96d56Sopenharmony_ci """ 18257db96d56Sopenharmony_ci Process the logging message and keyword arguments passed in to 18267db96d56Sopenharmony_ci a logging call to insert contextual information. You can either 18277db96d56Sopenharmony_ci manipulate the message itself, the keyword args or both. Return 18287db96d56Sopenharmony_ci the message and kwargs modified (or not) to suit your needs. 18297db96d56Sopenharmony_ci 18307db96d56Sopenharmony_ci Normally, you'll only need to override this one method in a 18317db96d56Sopenharmony_ci LoggerAdapter subclass for your specific needs. 18327db96d56Sopenharmony_ci """ 18337db96d56Sopenharmony_ci kwargs["extra"] = self.extra 18347db96d56Sopenharmony_ci return msg, kwargs 18357db96d56Sopenharmony_ci 18367db96d56Sopenharmony_ci # 18377db96d56Sopenharmony_ci # Boilerplate convenience methods 18387db96d56Sopenharmony_ci # 18397db96d56Sopenharmony_ci def debug(self, msg, *args, **kwargs): 18407db96d56Sopenharmony_ci """ 18417db96d56Sopenharmony_ci Delegate a debug call to the underlying logger. 18427db96d56Sopenharmony_ci """ 18437db96d56Sopenharmony_ci self.log(DEBUG, msg, *args, **kwargs) 18447db96d56Sopenharmony_ci 18457db96d56Sopenharmony_ci def info(self, msg, *args, **kwargs): 18467db96d56Sopenharmony_ci """ 18477db96d56Sopenharmony_ci Delegate an info call to the underlying logger. 18487db96d56Sopenharmony_ci """ 18497db96d56Sopenharmony_ci self.log(INFO, msg, *args, **kwargs) 18507db96d56Sopenharmony_ci 18517db96d56Sopenharmony_ci def warning(self, msg, *args, **kwargs): 18527db96d56Sopenharmony_ci """ 18537db96d56Sopenharmony_ci Delegate a warning call to the underlying logger. 18547db96d56Sopenharmony_ci """ 18557db96d56Sopenharmony_ci self.log(WARNING, msg, *args, **kwargs) 18567db96d56Sopenharmony_ci 18577db96d56Sopenharmony_ci def warn(self, msg, *args, **kwargs): 18587db96d56Sopenharmony_ci warnings.warn("The 'warn' method is deprecated, " 18597db96d56Sopenharmony_ci "use 'warning' instead", DeprecationWarning, 2) 18607db96d56Sopenharmony_ci self.warning(msg, *args, **kwargs) 18617db96d56Sopenharmony_ci 18627db96d56Sopenharmony_ci def error(self, msg, *args, **kwargs): 18637db96d56Sopenharmony_ci """ 18647db96d56Sopenharmony_ci Delegate an error call to the underlying logger. 18657db96d56Sopenharmony_ci """ 18667db96d56Sopenharmony_ci self.log(ERROR, msg, *args, **kwargs) 18677db96d56Sopenharmony_ci 18687db96d56Sopenharmony_ci def exception(self, msg, *args, exc_info=True, **kwargs): 18697db96d56Sopenharmony_ci """ 18707db96d56Sopenharmony_ci Delegate an exception call to the underlying logger. 18717db96d56Sopenharmony_ci """ 18727db96d56Sopenharmony_ci self.log(ERROR, msg, *args, exc_info=exc_info, **kwargs) 18737db96d56Sopenharmony_ci 18747db96d56Sopenharmony_ci def critical(self, msg, *args, **kwargs): 18757db96d56Sopenharmony_ci """ 18767db96d56Sopenharmony_ci Delegate a critical call to the underlying logger. 18777db96d56Sopenharmony_ci """ 18787db96d56Sopenharmony_ci self.log(CRITICAL, msg, *args, **kwargs) 18797db96d56Sopenharmony_ci 18807db96d56Sopenharmony_ci def log(self, level, msg, *args, **kwargs): 18817db96d56Sopenharmony_ci """ 18827db96d56Sopenharmony_ci Delegate a log call to the underlying logger, after adding 18837db96d56Sopenharmony_ci contextual information from this adapter instance. 18847db96d56Sopenharmony_ci """ 18857db96d56Sopenharmony_ci if self.isEnabledFor(level): 18867db96d56Sopenharmony_ci msg, kwargs = self.process(msg, kwargs) 18877db96d56Sopenharmony_ci self.logger.log(level, msg, *args, **kwargs) 18887db96d56Sopenharmony_ci 18897db96d56Sopenharmony_ci def isEnabledFor(self, level): 18907db96d56Sopenharmony_ci """ 18917db96d56Sopenharmony_ci Is this logger enabled for level 'level'? 18927db96d56Sopenharmony_ci """ 18937db96d56Sopenharmony_ci return self.logger.isEnabledFor(level) 18947db96d56Sopenharmony_ci 18957db96d56Sopenharmony_ci def setLevel(self, level): 18967db96d56Sopenharmony_ci """ 18977db96d56Sopenharmony_ci Set the specified level on the underlying logger. 18987db96d56Sopenharmony_ci """ 18997db96d56Sopenharmony_ci self.logger.setLevel(level) 19007db96d56Sopenharmony_ci 19017db96d56Sopenharmony_ci def getEffectiveLevel(self): 19027db96d56Sopenharmony_ci """ 19037db96d56Sopenharmony_ci Get the effective level for the underlying logger. 19047db96d56Sopenharmony_ci """ 19057db96d56Sopenharmony_ci return self.logger.getEffectiveLevel() 19067db96d56Sopenharmony_ci 19077db96d56Sopenharmony_ci def hasHandlers(self): 19087db96d56Sopenharmony_ci """ 19097db96d56Sopenharmony_ci See if the underlying logger has any handlers. 19107db96d56Sopenharmony_ci """ 19117db96d56Sopenharmony_ci return self.logger.hasHandlers() 19127db96d56Sopenharmony_ci 19137db96d56Sopenharmony_ci def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False): 19147db96d56Sopenharmony_ci """ 19157db96d56Sopenharmony_ci Low-level log implementation, proxied to allow nested logger adapters. 19167db96d56Sopenharmony_ci """ 19177db96d56Sopenharmony_ci return self.logger._log( 19187db96d56Sopenharmony_ci level, 19197db96d56Sopenharmony_ci msg, 19207db96d56Sopenharmony_ci args, 19217db96d56Sopenharmony_ci exc_info=exc_info, 19227db96d56Sopenharmony_ci extra=extra, 19237db96d56Sopenharmony_ci stack_info=stack_info, 19247db96d56Sopenharmony_ci ) 19257db96d56Sopenharmony_ci 19267db96d56Sopenharmony_ci @property 19277db96d56Sopenharmony_ci def manager(self): 19287db96d56Sopenharmony_ci return self.logger.manager 19297db96d56Sopenharmony_ci 19307db96d56Sopenharmony_ci @manager.setter 19317db96d56Sopenharmony_ci def manager(self, value): 19327db96d56Sopenharmony_ci self.logger.manager = value 19337db96d56Sopenharmony_ci 19347db96d56Sopenharmony_ci @property 19357db96d56Sopenharmony_ci def name(self): 19367db96d56Sopenharmony_ci return self.logger.name 19377db96d56Sopenharmony_ci 19387db96d56Sopenharmony_ci def __repr__(self): 19397db96d56Sopenharmony_ci logger = self.logger 19407db96d56Sopenharmony_ci level = getLevelName(logger.getEffectiveLevel()) 19417db96d56Sopenharmony_ci return '<%s %s (%s)>' % (self.__class__.__name__, logger.name, level) 19427db96d56Sopenharmony_ci 19437db96d56Sopenharmony_ci __class_getitem__ = classmethod(GenericAlias) 19447db96d56Sopenharmony_ci 19457db96d56Sopenharmony_ciroot = RootLogger(WARNING) 19467db96d56Sopenharmony_ciLogger.root = root 19477db96d56Sopenharmony_ciLogger.manager = Manager(Logger.root) 19487db96d56Sopenharmony_ci 19497db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 19507db96d56Sopenharmony_ci# Configuration classes and functions 19517db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 19527db96d56Sopenharmony_ci 19537db96d56Sopenharmony_cidef basicConfig(**kwargs): 19547db96d56Sopenharmony_ci """ 19557db96d56Sopenharmony_ci Do basic configuration for the logging system. 19567db96d56Sopenharmony_ci 19577db96d56Sopenharmony_ci This function does nothing if the root logger already has handlers 19587db96d56Sopenharmony_ci configured, unless the keyword argument *force* is set to ``True``. 19597db96d56Sopenharmony_ci It is a convenience method intended for use by simple scripts 19607db96d56Sopenharmony_ci to do one-shot configuration of the logging package. 19617db96d56Sopenharmony_ci 19627db96d56Sopenharmony_ci The default behaviour is to create a StreamHandler which writes to 19637db96d56Sopenharmony_ci sys.stderr, set a formatter using the BASIC_FORMAT format string, and 19647db96d56Sopenharmony_ci add the handler to the root logger. 19657db96d56Sopenharmony_ci 19667db96d56Sopenharmony_ci A number of optional keyword arguments may be specified, which can alter 19677db96d56Sopenharmony_ci the default behaviour. 19687db96d56Sopenharmony_ci 19697db96d56Sopenharmony_ci filename Specifies that a FileHandler be created, using the specified 19707db96d56Sopenharmony_ci filename, rather than a StreamHandler. 19717db96d56Sopenharmony_ci filemode Specifies the mode to open the file, if filename is specified 19727db96d56Sopenharmony_ci (if filemode is unspecified, it defaults to 'a'). 19737db96d56Sopenharmony_ci format Use the specified format string for the handler. 19747db96d56Sopenharmony_ci datefmt Use the specified date/time format. 19757db96d56Sopenharmony_ci style If a format string is specified, use this to specify the 19767db96d56Sopenharmony_ci type of format string (possible values '%', '{', '$', for 19777db96d56Sopenharmony_ci %-formatting, :meth:`str.format` and :class:`string.Template` 19787db96d56Sopenharmony_ci - defaults to '%'). 19797db96d56Sopenharmony_ci level Set the root logger level to the specified level. 19807db96d56Sopenharmony_ci stream Use the specified stream to initialize the StreamHandler. Note 19817db96d56Sopenharmony_ci that this argument is incompatible with 'filename' - if both 19827db96d56Sopenharmony_ci are present, 'stream' is ignored. 19837db96d56Sopenharmony_ci handlers If specified, this should be an iterable of already created 19847db96d56Sopenharmony_ci handlers, which will be added to the root handler. Any handler 19857db96d56Sopenharmony_ci in the list which does not have a formatter assigned will be 19867db96d56Sopenharmony_ci assigned the formatter created in this function. 19877db96d56Sopenharmony_ci force If this keyword is specified as true, any existing handlers 19887db96d56Sopenharmony_ci attached to the root logger are removed and closed, before 19897db96d56Sopenharmony_ci carrying out the configuration as specified by the other 19907db96d56Sopenharmony_ci arguments. 19917db96d56Sopenharmony_ci encoding If specified together with a filename, this encoding is passed to 19927db96d56Sopenharmony_ci the created FileHandler, causing it to be used when the file is 19937db96d56Sopenharmony_ci opened. 19947db96d56Sopenharmony_ci errors If specified together with a filename, this value is passed to the 19957db96d56Sopenharmony_ci created FileHandler, causing it to be used when the file is 19967db96d56Sopenharmony_ci opened in text mode. If not specified, the default value is 19977db96d56Sopenharmony_ci `backslashreplace`. 19987db96d56Sopenharmony_ci 19997db96d56Sopenharmony_ci Note that you could specify a stream created using open(filename, mode) 20007db96d56Sopenharmony_ci rather than passing the filename and mode in. However, it should be 20017db96d56Sopenharmony_ci remembered that StreamHandler does not close its stream (since it may be 20027db96d56Sopenharmony_ci using sys.stdout or sys.stderr), whereas FileHandler closes its stream 20037db96d56Sopenharmony_ci when the handler is closed. 20047db96d56Sopenharmony_ci 20057db96d56Sopenharmony_ci .. versionchanged:: 3.2 20067db96d56Sopenharmony_ci Added the ``style`` parameter. 20077db96d56Sopenharmony_ci 20087db96d56Sopenharmony_ci .. versionchanged:: 3.3 20097db96d56Sopenharmony_ci Added the ``handlers`` parameter. A ``ValueError`` is now thrown for 20107db96d56Sopenharmony_ci incompatible arguments (e.g. ``handlers`` specified together with 20117db96d56Sopenharmony_ci ``filename``/``filemode``, or ``filename``/``filemode`` specified 20127db96d56Sopenharmony_ci together with ``stream``, or ``handlers`` specified together with 20137db96d56Sopenharmony_ci ``stream``. 20147db96d56Sopenharmony_ci 20157db96d56Sopenharmony_ci .. versionchanged:: 3.8 20167db96d56Sopenharmony_ci Added the ``force`` parameter. 20177db96d56Sopenharmony_ci 20187db96d56Sopenharmony_ci .. versionchanged:: 3.9 20197db96d56Sopenharmony_ci Added the ``encoding`` and ``errors`` parameters. 20207db96d56Sopenharmony_ci """ 20217db96d56Sopenharmony_ci # Add thread safety in case someone mistakenly calls 20227db96d56Sopenharmony_ci # basicConfig() from multiple threads 20237db96d56Sopenharmony_ci _acquireLock() 20247db96d56Sopenharmony_ci try: 20257db96d56Sopenharmony_ci force = kwargs.pop('force', False) 20267db96d56Sopenharmony_ci encoding = kwargs.pop('encoding', None) 20277db96d56Sopenharmony_ci errors = kwargs.pop('errors', 'backslashreplace') 20287db96d56Sopenharmony_ci if force: 20297db96d56Sopenharmony_ci for h in root.handlers[:]: 20307db96d56Sopenharmony_ci root.removeHandler(h) 20317db96d56Sopenharmony_ci h.close() 20327db96d56Sopenharmony_ci if len(root.handlers) == 0: 20337db96d56Sopenharmony_ci handlers = kwargs.pop("handlers", None) 20347db96d56Sopenharmony_ci if handlers is None: 20357db96d56Sopenharmony_ci if "stream" in kwargs and "filename" in kwargs: 20367db96d56Sopenharmony_ci raise ValueError("'stream' and 'filename' should not be " 20377db96d56Sopenharmony_ci "specified together") 20387db96d56Sopenharmony_ci else: 20397db96d56Sopenharmony_ci if "stream" in kwargs or "filename" in kwargs: 20407db96d56Sopenharmony_ci raise ValueError("'stream' or 'filename' should not be " 20417db96d56Sopenharmony_ci "specified together with 'handlers'") 20427db96d56Sopenharmony_ci if handlers is None: 20437db96d56Sopenharmony_ci filename = kwargs.pop("filename", None) 20447db96d56Sopenharmony_ci mode = kwargs.pop("filemode", 'a') 20457db96d56Sopenharmony_ci if filename: 20467db96d56Sopenharmony_ci if 'b' in mode: 20477db96d56Sopenharmony_ci errors = None 20487db96d56Sopenharmony_ci else: 20497db96d56Sopenharmony_ci encoding = io.text_encoding(encoding) 20507db96d56Sopenharmony_ci h = FileHandler(filename, mode, 20517db96d56Sopenharmony_ci encoding=encoding, errors=errors) 20527db96d56Sopenharmony_ci else: 20537db96d56Sopenharmony_ci stream = kwargs.pop("stream", None) 20547db96d56Sopenharmony_ci h = StreamHandler(stream) 20557db96d56Sopenharmony_ci handlers = [h] 20567db96d56Sopenharmony_ci dfs = kwargs.pop("datefmt", None) 20577db96d56Sopenharmony_ci style = kwargs.pop("style", '%') 20587db96d56Sopenharmony_ci if style not in _STYLES: 20597db96d56Sopenharmony_ci raise ValueError('Style must be one of: %s' % ','.join( 20607db96d56Sopenharmony_ci _STYLES.keys())) 20617db96d56Sopenharmony_ci fs = kwargs.pop("format", _STYLES[style][1]) 20627db96d56Sopenharmony_ci fmt = Formatter(fs, dfs, style) 20637db96d56Sopenharmony_ci for h in handlers: 20647db96d56Sopenharmony_ci if h.formatter is None: 20657db96d56Sopenharmony_ci h.setFormatter(fmt) 20667db96d56Sopenharmony_ci root.addHandler(h) 20677db96d56Sopenharmony_ci level = kwargs.pop("level", None) 20687db96d56Sopenharmony_ci if level is not None: 20697db96d56Sopenharmony_ci root.setLevel(level) 20707db96d56Sopenharmony_ci if kwargs: 20717db96d56Sopenharmony_ci keys = ', '.join(kwargs.keys()) 20727db96d56Sopenharmony_ci raise ValueError('Unrecognised argument(s): %s' % keys) 20737db96d56Sopenharmony_ci finally: 20747db96d56Sopenharmony_ci _releaseLock() 20757db96d56Sopenharmony_ci 20767db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 20777db96d56Sopenharmony_ci# Utility functions at module level. 20787db96d56Sopenharmony_ci# Basically delegate everything to the root logger. 20797db96d56Sopenharmony_ci#--------------------------------------------------------------------------- 20807db96d56Sopenharmony_ci 20817db96d56Sopenharmony_cidef getLogger(name=None): 20827db96d56Sopenharmony_ci """ 20837db96d56Sopenharmony_ci Return a logger with the specified name, creating it if necessary. 20847db96d56Sopenharmony_ci 20857db96d56Sopenharmony_ci If no name is specified, return the root logger. 20867db96d56Sopenharmony_ci """ 20877db96d56Sopenharmony_ci if not name or isinstance(name, str) and name == root.name: 20887db96d56Sopenharmony_ci return root 20897db96d56Sopenharmony_ci return Logger.manager.getLogger(name) 20907db96d56Sopenharmony_ci 20917db96d56Sopenharmony_cidef critical(msg, *args, **kwargs): 20927db96d56Sopenharmony_ci """ 20937db96d56Sopenharmony_ci Log a message with severity 'CRITICAL' on the root logger. If the logger 20947db96d56Sopenharmony_ci has no handlers, call basicConfig() to add a console handler with a 20957db96d56Sopenharmony_ci pre-defined format. 20967db96d56Sopenharmony_ci """ 20977db96d56Sopenharmony_ci if len(root.handlers) == 0: 20987db96d56Sopenharmony_ci basicConfig() 20997db96d56Sopenharmony_ci root.critical(msg, *args, **kwargs) 21007db96d56Sopenharmony_ci 21017db96d56Sopenharmony_cidef fatal(msg, *args, **kwargs): 21027db96d56Sopenharmony_ci """ 21037db96d56Sopenharmony_ci Don't use this function, use critical() instead. 21047db96d56Sopenharmony_ci """ 21057db96d56Sopenharmony_ci critical(msg, *args, **kwargs) 21067db96d56Sopenharmony_ci 21077db96d56Sopenharmony_cidef error(msg, *args, **kwargs): 21087db96d56Sopenharmony_ci """ 21097db96d56Sopenharmony_ci Log a message with severity 'ERROR' on the root logger. If the logger has 21107db96d56Sopenharmony_ci no handlers, call basicConfig() to add a console handler with a pre-defined 21117db96d56Sopenharmony_ci format. 21127db96d56Sopenharmony_ci """ 21137db96d56Sopenharmony_ci if len(root.handlers) == 0: 21147db96d56Sopenharmony_ci basicConfig() 21157db96d56Sopenharmony_ci root.error(msg, *args, **kwargs) 21167db96d56Sopenharmony_ci 21177db96d56Sopenharmony_cidef exception(msg, *args, exc_info=True, **kwargs): 21187db96d56Sopenharmony_ci """ 21197db96d56Sopenharmony_ci Log a message with severity 'ERROR' on the root logger, with exception 21207db96d56Sopenharmony_ci information. If the logger has no handlers, basicConfig() is called to add 21217db96d56Sopenharmony_ci a console handler with a pre-defined format. 21227db96d56Sopenharmony_ci """ 21237db96d56Sopenharmony_ci error(msg, *args, exc_info=exc_info, **kwargs) 21247db96d56Sopenharmony_ci 21257db96d56Sopenharmony_cidef warning(msg, *args, **kwargs): 21267db96d56Sopenharmony_ci """ 21277db96d56Sopenharmony_ci Log a message with severity 'WARNING' on the root logger. If the logger has 21287db96d56Sopenharmony_ci no handlers, call basicConfig() to add a console handler with a pre-defined 21297db96d56Sopenharmony_ci format. 21307db96d56Sopenharmony_ci """ 21317db96d56Sopenharmony_ci if len(root.handlers) == 0: 21327db96d56Sopenharmony_ci basicConfig() 21337db96d56Sopenharmony_ci root.warning(msg, *args, **kwargs) 21347db96d56Sopenharmony_ci 21357db96d56Sopenharmony_cidef warn(msg, *args, **kwargs): 21367db96d56Sopenharmony_ci warnings.warn("The 'warn' function is deprecated, " 21377db96d56Sopenharmony_ci "use 'warning' instead", DeprecationWarning, 2) 21387db96d56Sopenharmony_ci warning(msg, *args, **kwargs) 21397db96d56Sopenharmony_ci 21407db96d56Sopenharmony_cidef info(msg, *args, **kwargs): 21417db96d56Sopenharmony_ci """ 21427db96d56Sopenharmony_ci Log a message with severity 'INFO' on the root logger. If the logger has 21437db96d56Sopenharmony_ci no handlers, call basicConfig() to add a console handler with a pre-defined 21447db96d56Sopenharmony_ci format. 21457db96d56Sopenharmony_ci """ 21467db96d56Sopenharmony_ci if len(root.handlers) == 0: 21477db96d56Sopenharmony_ci basicConfig() 21487db96d56Sopenharmony_ci root.info(msg, *args, **kwargs) 21497db96d56Sopenharmony_ci 21507db96d56Sopenharmony_cidef debug(msg, *args, **kwargs): 21517db96d56Sopenharmony_ci """ 21527db96d56Sopenharmony_ci Log a message with severity 'DEBUG' on the root logger. If the logger has 21537db96d56Sopenharmony_ci no handlers, call basicConfig() to add a console handler with a pre-defined 21547db96d56Sopenharmony_ci format. 21557db96d56Sopenharmony_ci """ 21567db96d56Sopenharmony_ci if len(root.handlers) == 0: 21577db96d56Sopenharmony_ci basicConfig() 21587db96d56Sopenharmony_ci root.debug(msg, *args, **kwargs) 21597db96d56Sopenharmony_ci 21607db96d56Sopenharmony_cidef log(level, msg, *args, **kwargs): 21617db96d56Sopenharmony_ci """ 21627db96d56Sopenharmony_ci Log 'msg % args' with the integer severity 'level' on the root logger. If 21637db96d56Sopenharmony_ci the logger has no handlers, call basicConfig() to add a console handler 21647db96d56Sopenharmony_ci with a pre-defined format. 21657db96d56Sopenharmony_ci """ 21667db96d56Sopenharmony_ci if len(root.handlers) == 0: 21677db96d56Sopenharmony_ci basicConfig() 21687db96d56Sopenharmony_ci root.log(level, msg, *args, **kwargs) 21697db96d56Sopenharmony_ci 21707db96d56Sopenharmony_cidef disable(level=CRITICAL): 21717db96d56Sopenharmony_ci """ 21727db96d56Sopenharmony_ci Disable all logging calls of severity 'level' and below. 21737db96d56Sopenharmony_ci """ 21747db96d56Sopenharmony_ci root.manager.disable = level 21757db96d56Sopenharmony_ci root.manager._clear_cache() 21767db96d56Sopenharmony_ci 21777db96d56Sopenharmony_cidef shutdown(handlerList=_handlerList): 21787db96d56Sopenharmony_ci """ 21797db96d56Sopenharmony_ci Perform any cleanup actions in the logging system (e.g. flushing 21807db96d56Sopenharmony_ci buffers). 21817db96d56Sopenharmony_ci 21827db96d56Sopenharmony_ci Should be called at application exit. 21837db96d56Sopenharmony_ci """ 21847db96d56Sopenharmony_ci for wr in reversed(handlerList[:]): 21857db96d56Sopenharmony_ci #errors might occur, for example, if files are locked 21867db96d56Sopenharmony_ci #we just ignore them if raiseExceptions is not set 21877db96d56Sopenharmony_ci try: 21887db96d56Sopenharmony_ci h = wr() 21897db96d56Sopenharmony_ci if h: 21907db96d56Sopenharmony_ci try: 21917db96d56Sopenharmony_ci h.acquire() 21927db96d56Sopenharmony_ci h.flush() 21937db96d56Sopenharmony_ci h.close() 21947db96d56Sopenharmony_ci except (OSError, ValueError): 21957db96d56Sopenharmony_ci # Ignore errors which might be caused 21967db96d56Sopenharmony_ci # because handlers have been closed but 21977db96d56Sopenharmony_ci # references to them are still around at 21987db96d56Sopenharmony_ci # application exit. 21997db96d56Sopenharmony_ci pass 22007db96d56Sopenharmony_ci finally: 22017db96d56Sopenharmony_ci h.release() 22027db96d56Sopenharmony_ci except: # ignore everything, as we're shutting down 22037db96d56Sopenharmony_ci if raiseExceptions: 22047db96d56Sopenharmony_ci raise 22057db96d56Sopenharmony_ci #else, swallow 22067db96d56Sopenharmony_ci 22077db96d56Sopenharmony_ci#Let's try and shutdown automatically on application exit... 22087db96d56Sopenharmony_ciimport atexit 22097db96d56Sopenharmony_ciatexit.register(shutdown) 22107db96d56Sopenharmony_ci 22117db96d56Sopenharmony_ci# Null handler 22127db96d56Sopenharmony_ci 22137db96d56Sopenharmony_ciclass NullHandler(Handler): 22147db96d56Sopenharmony_ci """ 22157db96d56Sopenharmony_ci This handler does nothing. It's intended to be used to avoid the 22167db96d56Sopenharmony_ci "No handlers could be found for logger XXX" one-off warning. This is 22177db96d56Sopenharmony_ci important for library code, which may contain code to log events. If a user 22187db96d56Sopenharmony_ci of the library does not configure logging, the one-off warning might be 22197db96d56Sopenharmony_ci produced; to avoid this, the library developer simply needs to instantiate 22207db96d56Sopenharmony_ci a NullHandler and add it to the top-level logger of the library module or 22217db96d56Sopenharmony_ci package. 22227db96d56Sopenharmony_ci """ 22237db96d56Sopenharmony_ci def handle(self, record): 22247db96d56Sopenharmony_ci """Stub.""" 22257db96d56Sopenharmony_ci 22267db96d56Sopenharmony_ci def emit(self, record): 22277db96d56Sopenharmony_ci """Stub.""" 22287db96d56Sopenharmony_ci 22297db96d56Sopenharmony_ci def createLock(self): 22307db96d56Sopenharmony_ci self.lock = None 22317db96d56Sopenharmony_ci 22327db96d56Sopenharmony_ci def _at_fork_reinit(self): 22337db96d56Sopenharmony_ci pass 22347db96d56Sopenharmony_ci 22357db96d56Sopenharmony_ci# Warnings integration 22367db96d56Sopenharmony_ci 22377db96d56Sopenharmony_ci_warnings_showwarning = None 22387db96d56Sopenharmony_ci 22397db96d56Sopenharmony_cidef _showwarning(message, category, filename, lineno, file=None, line=None): 22407db96d56Sopenharmony_ci """ 22417db96d56Sopenharmony_ci Implementation of showwarnings which redirects to logging, which will first 22427db96d56Sopenharmony_ci check to see if the file parameter is None. If a file is specified, it will 22437db96d56Sopenharmony_ci delegate to the original warnings implementation of showwarning. Otherwise, 22447db96d56Sopenharmony_ci it will call warnings.formatwarning and will log the resulting string to a 22457db96d56Sopenharmony_ci warnings logger named "py.warnings" with level logging.WARNING. 22467db96d56Sopenharmony_ci """ 22477db96d56Sopenharmony_ci if file is not None: 22487db96d56Sopenharmony_ci if _warnings_showwarning is not None: 22497db96d56Sopenharmony_ci _warnings_showwarning(message, category, filename, lineno, file, line) 22507db96d56Sopenharmony_ci else: 22517db96d56Sopenharmony_ci s = warnings.formatwarning(message, category, filename, lineno, line) 22527db96d56Sopenharmony_ci logger = getLogger("py.warnings") 22537db96d56Sopenharmony_ci if not logger.handlers: 22547db96d56Sopenharmony_ci logger.addHandler(NullHandler()) 22557db96d56Sopenharmony_ci # bpo-46557: Log str(s) as msg instead of logger.warning("%s", s) 22567db96d56Sopenharmony_ci # since some log aggregation tools group logs by the msg arg 22577db96d56Sopenharmony_ci logger.warning(str(s)) 22587db96d56Sopenharmony_ci 22597db96d56Sopenharmony_cidef captureWarnings(capture): 22607db96d56Sopenharmony_ci """ 22617db96d56Sopenharmony_ci If capture is true, redirect all warnings to the logging package. 22627db96d56Sopenharmony_ci If capture is False, ensure that warnings are not redirected to logging 22637db96d56Sopenharmony_ci but to their original destinations. 22647db96d56Sopenharmony_ci """ 22657db96d56Sopenharmony_ci global _warnings_showwarning 22667db96d56Sopenharmony_ci if capture: 22677db96d56Sopenharmony_ci if _warnings_showwarning is None: 22687db96d56Sopenharmony_ci _warnings_showwarning = warnings.showwarning 22697db96d56Sopenharmony_ci warnings.showwarning = _showwarning 22707db96d56Sopenharmony_ci else: 22717db96d56Sopenharmony_ci if _warnings_showwarning is not None: 22727db96d56Sopenharmony_ci warnings.showwarning = _warnings_showwarning 22737db96d56Sopenharmony_ci _warnings_showwarning = None 2274