• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2001-2019 by Vinay Sajip. All Rights Reserved.
2#
3# Permission to use, copy, modify, and distribute this software and its
4# documentation for any purpose and without fee is hereby granted,
5# provided that the above copyright notice appear in all copies and that
6# both that copyright notice and this permission notice appear in
7# supporting documentation, and that the name of Vinay Sajip
8# not be used in advertising or publicity pertaining to distribution
9# of the software without specific, written prior permission.
10# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
11# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
12# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
13# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
14# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
15# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
17"""
18Logging package for Python. Based on PEP 282 and comments thereto in
19comp.lang.python.
20
21Copyright (C) 2001-2019 Vinay Sajip. All Rights Reserved.
22
23To use, simply 'import logging' and log away!
24"""
25
26import sys, os, time, io, re, traceback, warnings, weakref, collections.abc
27
28from string import Template
29from string import Formatter as StrFormatter
30
31
32__all__ = ['BASIC_FORMAT', 'BufferingFormatter', 'CRITICAL', 'DEBUG', 'ERROR',
33           'FATAL', 'FileHandler', 'Filter', 'Formatter', 'Handler', 'INFO',
34           'LogRecord', 'Logger', 'LoggerAdapter', 'NOTSET', 'NullHandler',
35           'StreamHandler', 'WARN', 'WARNING', 'addLevelName', 'basicConfig',
36           'captureWarnings', 'critical', 'debug', 'disable', 'error',
37           'exception', 'fatal', 'getLevelName', 'getLogger', 'getLoggerClass',
38           'info', 'log', 'makeLogRecord', 'setLoggerClass', 'shutdown',
39           'warn', 'warning', 'getLogRecordFactory', 'setLogRecordFactory',
40           'lastResort', 'raiseExceptions']
41
42import threading
43
44__author__  = "Vinay Sajip <vinay_sajip@red-dove.com>"
45__status__  = "production"
46# The following module attributes are no longer updated.
47__version__ = "0.5.1.2"
48__date__    = "07 February 2010"
49
50#---------------------------------------------------------------------------
51#   Miscellaneous module data
52#---------------------------------------------------------------------------
53
54#
55#_startTime is used as the base when calculating the relative time of events
56#
57_startTime = time.time()
58
59#
60#raiseExceptions is used to see if exceptions during handling should be
61#propagated
62#
63raiseExceptions = True
64
65#
66# If you don't want threading information in the log, set this to zero
67#
68logThreads = True
69
70#
71# If you don't want multiprocessing information in the log, set this to zero
72#
73logMultiprocessing = True
74
75#
76# If you don't want process information in the log, set this to zero
77#
78logProcesses = True
79
80#---------------------------------------------------------------------------
81#   Level related stuff
82#---------------------------------------------------------------------------
83#
84# Default levels and level names, these can be replaced with any positive set
85# of values having corresponding names. There is a pseudo-level, NOTSET, which
86# is only really there as a lower limit for user-defined levels. Handlers and
87# loggers are initialized with NOTSET so that they will log all messages, even
88# at user-defined levels.
89#
90
91CRITICAL = 50
92FATAL = CRITICAL
93ERROR = 40
94WARNING = 30
95WARN = WARNING
96INFO = 20
97DEBUG = 10
98NOTSET = 0
99
100_levelToName = {
101    CRITICAL: 'CRITICAL',
102    ERROR: 'ERROR',
103    WARNING: 'WARNING',
104    INFO: 'INFO',
105    DEBUG: 'DEBUG',
106    NOTSET: 'NOTSET',
107}
108_nameToLevel = {
109    'CRITICAL': CRITICAL,
110    'FATAL': FATAL,
111    'ERROR': ERROR,
112    'WARN': WARNING,
113    'WARNING': WARNING,
114    'INFO': INFO,
115    'DEBUG': DEBUG,
116    'NOTSET': NOTSET,
117}
118
119def getLevelName(level):
120    """
121    Return the textual or numeric representation of logging level 'level'.
122
123    If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
124    INFO, DEBUG) then you get the corresponding string. If you have
125    associated levels with names using addLevelName then the name you have
126    associated with 'level' is returned.
127
128    If a numeric value corresponding to one of the defined levels is passed
129    in, the corresponding string representation is returned.
130
131    If a string representation of the level is passed in, the corresponding
132    numeric value is returned.
133
134    If no matching numeric or string value is passed in, the string
135    'Level %s' % level is returned.
136    """
137    # See Issues #22386, #27937 and #29220 for why it's this way
138    result = _levelToName.get(level)
139    if result is not None:
140        return result
141    result = _nameToLevel.get(level)
142    if result is not None:
143        return result
144    return "Level %s" % level
145
146def addLevelName(level, levelName):
147    """
148    Associate 'levelName' with 'level'.
149
150    This is used when converting levels to text during message formatting.
151    """
152    _acquireLock()
153    try:    #unlikely to cause an exception, but you never know...
154        _levelToName[level] = levelName
155        _nameToLevel[levelName] = level
156    finally:
157        _releaseLock()
158
159if hasattr(sys, '_getframe'):
160    currentframe = lambda: sys._getframe(3)
161else: #pragma: no cover
162    def currentframe():
163        """Return the frame object for the caller's stack frame."""
164        try:
165            raise Exception
166        except Exception:
167            return sys.exc_info()[2].tb_frame.f_back
168
169#
170# _srcfile is used when walking the stack to check when we've got the first
171# caller stack frame, by skipping frames whose filename is that of this
172# module's source. It therefore should contain the filename of this module's
173# source file.
174#
175# Ordinarily we would use __file__ for this, but frozen modules don't always
176# have __file__ set, for some reason (see Issue #21736). Thus, we get the
177# filename from a handy code object from a function defined in this module.
178# (There's no particular reason for picking addLevelName.)
179#
180
181_srcfile = os.path.normcase(addLevelName.__code__.co_filename)
182
183# _srcfile is only used in conjunction with sys._getframe().
184# To provide compatibility with older versions of Python, set _srcfile
185# to None if _getframe() is not available; this value will prevent
186# findCaller() from being called. You can also do this if you want to avoid
187# the overhead of fetching caller information, even when _getframe() is
188# available.
189#if not hasattr(sys, '_getframe'):
190#    _srcfile = None
191
192
193def _checkLevel(level):
194    if isinstance(level, int):
195        rv = level
196    elif str(level) == level:
197        if level not in _nameToLevel:
198            raise ValueError("Unknown level: %r" % level)
199        rv = _nameToLevel[level]
200    else:
201        raise TypeError("Level not an integer or a valid string: %r"
202                        % (level,))
203    return rv
204
205#---------------------------------------------------------------------------
206#   Thread-related stuff
207#---------------------------------------------------------------------------
208
209#
210#_lock is used to serialize access to shared data structures in this module.
211#This needs to be an RLock because fileConfig() creates and configures
212#Handlers, and so might arbitrary user threads. Since Handler code updates the
213#shared dictionary _handlers, it needs to acquire the lock. But if configuring,
214#the lock would already have been acquired - so we need an RLock.
215#The same argument applies to Loggers and Manager.loggerDict.
216#
217_lock = threading.RLock()
218
219def _acquireLock():
220    """
221    Acquire the module-level lock for serializing access to shared data.
222
223    This should be released with _releaseLock().
224    """
225    if _lock:
226        _lock.acquire()
227
228def _releaseLock():
229    """
230    Release the module-level lock acquired by calling _acquireLock().
231    """
232    if _lock:
233        _lock.release()
234
235
236# Prevent a held logging lock from blocking a child from logging.
237
238if not hasattr(os, 'register_at_fork'):  # Windows and friends.
239    def _register_at_fork_reinit_lock(instance):
240        pass  # no-op when os.register_at_fork does not exist.
241else:
242    # A collection of instances with a _at_fork_reinit method (logging.Handler)
243    # to be called in the child after forking.  The weakref avoids us keeping
244    # discarded Handler instances alive.
245    _at_fork_reinit_lock_weakset = weakref.WeakSet()
246
247    def _register_at_fork_reinit_lock(instance):
248        _acquireLock()
249        try:
250            _at_fork_reinit_lock_weakset.add(instance)
251        finally:
252            _releaseLock()
253
254    def _after_at_fork_child_reinit_locks():
255        for handler in _at_fork_reinit_lock_weakset:
256            handler._at_fork_reinit()
257
258        # _acquireLock() was called in the parent before forking.
259        # The lock is reinitialized to unlocked state.
260        _lock._at_fork_reinit()
261
262    os.register_at_fork(before=_acquireLock,
263                        after_in_child=_after_at_fork_child_reinit_locks,
264                        after_in_parent=_releaseLock)
265
266
267#---------------------------------------------------------------------------
268#   The logging record
269#---------------------------------------------------------------------------
270
271class LogRecord(object):
272    """
273    A LogRecord instance represents an event being logged.
274
275    LogRecord instances are created every time something is logged. They
276    contain all the information pertinent to the event being logged. The
277    main information passed in is in msg and args, which are combined
278    using str(msg) % args to create the message field of the record. The
279    record also includes information such as when the record was created,
280    the source line where the logging call was made, and any exception
281    information to be logged.
282    """
283    def __init__(self, name, level, pathname, lineno,
284                 msg, args, exc_info, func=None, sinfo=None, **kwargs):
285        """
286        Initialize a logging record with interesting information.
287        """
288        ct = time.time()
289        self.name = name
290        self.msg = msg
291        #
292        # The following statement allows passing of a dictionary as a sole
293        # argument, so that you can do something like
294        #  logging.debug("a %(a)d b %(b)s", {'a':1, 'b':2})
295        # Suggested by Stefan Behnel.
296        # Note that without the test for args[0], we get a problem because
297        # during formatting, we test to see if the arg is present using
298        # 'if self.args:'. If the event being logged is e.g. 'Value is %d'
299        # and if the passed arg fails 'if self.args:' then no formatting
300        # is done. For example, logger.warning('Value is %d', 0) would log
301        # 'Value is %d' instead of 'Value is 0'.
302        # For the use case of passing a dictionary, this should not be a
303        # problem.
304        # Issue #21172: a request was made to relax the isinstance check
305        # to hasattr(args[0], '__getitem__'). However, the docs on string
306        # formatting still seem to suggest a mapping object is required.
307        # Thus, while not removing the isinstance check, it does now look
308        # for collections.abc.Mapping rather than, as before, dict.
309        if (args and len(args) == 1 and isinstance(args[0], collections.abc.Mapping)
310            and args[0]):
311            args = args[0]
312        self.args = args
313        self.levelname = getLevelName(level)
314        self.levelno = level
315        self.pathname = pathname
316        try:
317            self.filename = os.path.basename(pathname)
318            self.module = os.path.splitext(self.filename)[0]
319        except (TypeError, ValueError, AttributeError):
320            self.filename = pathname
321            self.module = "Unknown module"
322        self.exc_info = exc_info
323        self.exc_text = None      # used to cache the traceback text
324        self.stack_info = sinfo
325        self.lineno = lineno
326        self.funcName = func
327        self.created = ct
328        self.msecs = (ct - int(ct)) * 1000
329        self.relativeCreated = (self.created - _startTime) * 1000
330        if logThreads:
331            self.thread = threading.get_ident()
332            self.threadName = threading.current_thread().name
333        else: # pragma: no cover
334            self.thread = None
335            self.threadName = None
336        if not logMultiprocessing: # pragma: no cover
337            self.processName = None
338        else:
339            self.processName = 'MainProcess'
340            mp = sys.modules.get('multiprocessing')
341            if mp is not None:
342                # Errors may occur if multiprocessing has not finished loading
343                # yet - e.g. if a custom import hook causes third-party code
344                # to run when multiprocessing calls import. See issue 8200
345                # for an example
346                try:
347                    self.processName = mp.current_process().name
348                except Exception: #pragma: no cover
349                    pass
350        if logProcesses and hasattr(os, 'getpid'):
351            self.process = os.getpid()
352        else:
353            self.process = None
354
355    def __repr__(self):
356        return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
357            self.pathname, self.lineno, self.msg)
358
359    def getMessage(self):
360        """
361        Return the message for this LogRecord.
362
363        Return the message for this LogRecord after merging any user-supplied
364        arguments with the message.
365        """
366        msg = str(self.msg)
367        if self.args:
368            msg = msg % self.args
369        return msg
370
371#
372#   Determine which class to use when instantiating log records.
373#
374_logRecordFactory = LogRecord
375
376def setLogRecordFactory(factory):
377    """
378    Set the factory to be used when instantiating a log record.
379
380    :param factory: A callable which will be called to instantiate
381    a log record.
382    """
383    global _logRecordFactory
384    _logRecordFactory = factory
385
386def getLogRecordFactory():
387    """
388    Return the factory to be used when instantiating a log record.
389    """
390
391    return _logRecordFactory
392
393def makeLogRecord(dict):
394    """
395    Make a LogRecord whose attributes are defined by the specified dictionary,
396    This function is useful for converting a logging event received over
397    a socket connection (which is sent as a dictionary) into a LogRecord
398    instance.
399    """
400    rv = _logRecordFactory(None, None, "", 0, "", (), None, None)
401    rv.__dict__.update(dict)
402    return rv
403
404
405#---------------------------------------------------------------------------
406#   Formatter classes and functions
407#---------------------------------------------------------------------------
408_str_formatter = StrFormatter()
409del StrFormatter
410
411
412class PercentStyle(object):
413
414    default_format = '%(message)s'
415    asctime_format = '%(asctime)s'
416    asctime_search = '%(asctime)'
417    validation_pattern = re.compile(r'%\(\w+\)[#0+ -]*(\*|\d+)?(\.(\*|\d+))?[diouxefgcrsa%]', re.I)
418
419    def __init__(self, fmt, *, defaults=None):
420        self._fmt = fmt or self.default_format
421        self._defaults = defaults
422
423    def usesTime(self):
424        return self._fmt.find(self.asctime_search) >= 0
425
426    def validate(self):
427        """Validate the input format, ensure it matches the correct style"""
428        if not self.validation_pattern.search(self._fmt):
429            raise ValueError("Invalid format '%s' for '%s' style" % (self._fmt, self.default_format[0]))
430
431    def _format(self, record):
432        if defaults := self._defaults:
433            values = defaults | record.__dict__
434        else:
435            values = record.__dict__
436        return self._fmt % values
437
438    def format(self, record):
439        try:
440            return self._format(record)
441        except KeyError as e:
442            raise ValueError('Formatting field not found in record: %s' % e)
443
444
445class StrFormatStyle(PercentStyle):
446    default_format = '{message}'
447    asctime_format = '{asctime}'
448    asctime_search = '{asctime'
449
450    fmt_spec = re.compile(r'^(.?[<>=^])?[+ -]?#?0?(\d+|{\w+})?[,_]?(\.(\d+|{\w+}))?[bcdefgnosx%]?$', re.I)
451    field_spec = re.compile(r'^(\d+|\w+)(\.\w+|\[[^]]+\])*$')
452
453    def _format(self, record):
454        if defaults := self._defaults:
455            values = defaults | record.__dict__
456        else:
457            values = record.__dict__
458        return self._fmt.format(**values)
459
460    def validate(self):
461        """Validate the input format, ensure it is the correct string formatting style"""
462        fields = set()
463        try:
464            for _, fieldname, spec, conversion in _str_formatter.parse(self._fmt):
465                if fieldname:
466                    if not self.field_spec.match(fieldname):
467                        raise ValueError('invalid field name/expression: %r' % fieldname)
468                    fields.add(fieldname)
469                if conversion and conversion not in 'rsa':
470                    raise ValueError('invalid conversion: %r' % conversion)
471                if spec and not self.fmt_spec.match(spec):
472                    raise ValueError('bad specifier: %r' % spec)
473        except ValueError as e:
474            raise ValueError('invalid format: %s' % e)
475        if not fields:
476            raise ValueError('invalid format: no fields')
477
478
479class StringTemplateStyle(PercentStyle):
480    default_format = '${message}'
481    asctime_format = '${asctime}'
482    asctime_search = '${asctime}'
483
484    def __init__(self, *args, **kwargs):
485        super().__init__(*args, **kwargs)
486        self._tpl = Template(self._fmt)
487
488    def usesTime(self):
489        fmt = self._fmt
490        return fmt.find('$asctime') >= 0 or fmt.find(self.asctime_format) >= 0
491
492    def validate(self):
493        pattern = Template.pattern
494        fields = set()
495        for m in pattern.finditer(self._fmt):
496            d = m.groupdict()
497            if d['named']:
498                fields.add(d['named'])
499            elif d['braced']:
500                fields.add(d['braced'])
501            elif m.group(0) == '$':
502                raise ValueError('invalid format: bare \'$\' not allowed')
503        if not fields:
504            raise ValueError('invalid format: no fields')
505
506    def _format(self, record):
507        if defaults := self._defaults:
508            values = defaults | record.__dict__
509        else:
510            values = record.__dict__
511        return self._tpl.substitute(**values)
512
513
514BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
515
516_STYLES = {
517    '%': (PercentStyle, BASIC_FORMAT),
518    '{': (StrFormatStyle, '{levelname}:{name}:{message}'),
519    '$': (StringTemplateStyle, '${levelname}:${name}:${message}'),
520}
521
522class Formatter(object):
523    """
524    Formatter instances are used to convert a LogRecord to text.
525
526    Formatters need to know how a LogRecord is constructed. They are
527    responsible for converting a LogRecord to (usually) a string which can
528    be interpreted by either a human or an external system. The base Formatter
529    allows a formatting string to be specified. If none is supplied, the
530    style-dependent default value, "%(message)s", "{message}", or
531    "${message}", is used.
532
533    The Formatter can be initialized with a format string which makes use of
534    knowledge of the LogRecord attributes - e.g. the default value mentioned
535    above makes use of the fact that the user's message and arguments are pre-
536    formatted into a LogRecord's message attribute. Currently, the useful
537    attributes in a LogRecord are described by:
538
539    %(name)s            Name of the logger (logging channel)
540    %(levelno)s         Numeric logging level for the message (DEBUG, INFO,
541                        WARNING, ERROR, CRITICAL)
542    %(levelname)s       Text logging level for the message ("DEBUG", "INFO",
543                        "WARNING", "ERROR", "CRITICAL")
544    %(pathname)s        Full pathname of the source file where the logging
545                        call was issued (if available)
546    %(filename)s        Filename portion of pathname
547    %(module)s          Module (name portion of filename)
548    %(lineno)d          Source line number where the logging call was issued
549                        (if available)
550    %(funcName)s        Function name
551    %(created)f         Time when the LogRecord was created (time.time()
552                        return value)
553    %(asctime)s         Textual time when the LogRecord was created
554    %(msecs)d           Millisecond portion of the creation time
555    %(relativeCreated)d Time in milliseconds when the LogRecord was created,
556                        relative to the time the logging module was loaded
557                        (typically at application startup time)
558    %(thread)d          Thread ID (if available)
559    %(threadName)s      Thread name (if available)
560    %(process)d         Process ID (if available)
561    %(message)s         The result of record.getMessage(), computed just as
562                        the record is emitted
563    """
564
565    converter = time.localtime
566
567    def __init__(self, fmt=None, datefmt=None, style='%', validate=True, *,
568                 defaults=None):
569        """
570        Initialize the formatter with specified format strings.
571
572        Initialize the formatter either with the specified format string, or a
573        default as described above. Allow for specialized date formatting with
574        the optional datefmt argument. If datefmt is omitted, you get an
575        ISO8601-like (or RFC 3339-like) format.
576
577        Use a style parameter of '%', '{' or '$' to specify that you want to
578        use one of %-formatting, :meth:`str.format` (``{}``) formatting or
579        :class:`string.Template` formatting in your format string.
580
581        .. versionchanged:: 3.2
582           Added the ``style`` parameter.
583        """
584        if style not in _STYLES:
585            raise ValueError('Style must be one of: %s' % ','.join(
586                             _STYLES.keys()))
587        self._style = _STYLES[style][0](fmt, defaults=defaults)
588        if validate:
589            self._style.validate()
590
591        self._fmt = self._style._fmt
592        self.datefmt = datefmt
593
594    default_time_format = '%Y-%m-%d %H:%M:%S'
595    default_msec_format = '%s,%03d'
596
597    def formatTime(self, record, datefmt=None):
598        """
599        Return the creation time of the specified LogRecord as formatted text.
600
601        This method should be called from format() by a formatter which
602        wants to make use of a formatted time. This method can be overridden
603        in formatters to provide for any specific requirement, but the
604        basic behaviour is as follows: if datefmt (a string) is specified,
605        it is used with time.strftime() to format the creation time of the
606        record. Otherwise, an ISO8601-like (or RFC 3339-like) format is used.
607        The resulting string is returned. This function uses a user-configurable
608        function to convert the creation time to a tuple. By default,
609        time.localtime() is used; to change this for a particular formatter
610        instance, set the 'converter' attribute to a function with the same
611        signature as time.localtime() or time.gmtime(). To change it for all
612        formatters, for example if you want all logging times to be shown in GMT,
613        set the 'converter' attribute in the Formatter class.
614        """
615        ct = self.converter(record.created)
616        if datefmt:
617            s = time.strftime(datefmt, ct)
618        else:
619            s = time.strftime(self.default_time_format, ct)
620            if self.default_msec_format:
621                s = self.default_msec_format % (s, record.msecs)
622        return s
623
624    def formatException(self, ei):
625        """
626        Format and return the specified exception information as a string.
627
628        This default implementation just uses
629        traceback.print_exception()
630        """
631        sio = io.StringIO()
632        tb = ei[2]
633        # See issues #9427, #1553375. Commented out for now.
634        #if getattr(self, 'fullstack', False):
635        #    traceback.print_stack(tb.tb_frame.f_back, file=sio)
636        traceback.print_exception(ei[0], ei[1], tb, None, sio)
637        s = sio.getvalue()
638        sio.close()
639        if s[-1:] == "\n":
640            s = s[:-1]
641        return s
642
643    def usesTime(self):
644        """
645        Check if the format uses the creation time of the record.
646        """
647        return self._style.usesTime()
648
649    def formatMessage(self, record):
650        return self._style.format(record)
651
652    def formatStack(self, stack_info):
653        """
654        This method is provided as an extension point for specialized
655        formatting of stack information.
656
657        The input data is a string as returned from a call to
658        :func:`traceback.print_stack`, but with the last trailing newline
659        removed.
660
661        The base implementation just returns the value passed in.
662        """
663        return stack_info
664
665    def format(self, record):
666        """
667        Format the specified record as text.
668
669        The record's attribute dictionary is used as the operand to a
670        string formatting operation which yields the returned string.
671        Before formatting the dictionary, a couple of preparatory steps
672        are carried out. The message attribute of the record is computed
673        using LogRecord.getMessage(). If the formatting string uses the
674        time (as determined by a call to usesTime(), formatTime() is
675        called to format the event time. If there is exception information,
676        it is formatted using formatException() and appended to the message.
677        """
678        record.message = record.getMessage()
679        if self.usesTime():
680            record.asctime = self.formatTime(record, self.datefmt)
681        s = self.formatMessage(record)
682        if record.exc_info:
683            # Cache the traceback text to avoid converting it multiple times
684            # (it's constant anyway)
685            if not record.exc_text:
686                record.exc_text = self.formatException(record.exc_info)
687        if record.exc_text:
688            if s[-1:] != "\n":
689                s = s + "\n"
690            s = s + record.exc_text
691        if record.stack_info:
692            if s[-1:] != "\n":
693                s = s + "\n"
694            s = s + self.formatStack(record.stack_info)
695        return s
696
697#
698#   The default formatter to use when no other is specified
699#
700_defaultFormatter = Formatter()
701
702class BufferingFormatter(object):
703    """
704    A formatter suitable for formatting a number of records.
705    """
706    def __init__(self, linefmt=None):
707        """
708        Optionally specify a formatter which will be used to format each
709        individual record.
710        """
711        if linefmt:
712            self.linefmt = linefmt
713        else:
714            self.linefmt = _defaultFormatter
715
716    def formatHeader(self, records):
717        """
718        Return the header string for the specified records.
719        """
720        return ""
721
722    def formatFooter(self, records):
723        """
724        Return the footer string for the specified records.
725        """
726        return ""
727
728    def format(self, records):
729        """
730        Format the specified records and return the result as a string.
731        """
732        rv = ""
733        if len(records) > 0:
734            rv = rv + self.formatHeader(records)
735            for record in records:
736                rv = rv + self.linefmt.format(record)
737            rv = rv + self.formatFooter(records)
738        return rv
739
740#---------------------------------------------------------------------------
741#   Filter classes and functions
742#---------------------------------------------------------------------------
743
744class Filter(object):
745    """
746    Filter instances are used to perform arbitrary filtering of LogRecords.
747
748    Loggers and Handlers can optionally use Filter instances to filter
749    records as desired. The base filter class only allows events which are
750    below a certain point in the logger hierarchy. For example, a filter
751    initialized with "A.B" will allow events logged by loggers "A.B",
752    "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
753    initialized with the empty string, all events are passed.
754    """
755    def __init__(self, name=''):
756        """
757        Initialize a filter.
758
759        Initialize with the name of the logger which, together with its
760        children, will have its events allowed through the filter. If no
761        name is specified, allow every event.
762        """
763        self.name = name
764        self.nlen = len(name)
765
766    def filter(self, record):
767        """
768        Determine if the specified record is to be logged.
769
770        Returns True if the record should be logged, or False otherwise.
771        If deemed appropriate, the record may be modified in-place.
772        """
773        if self.nlen == 0:
774            return True
775        elif self.name == record.name:
776            return True
777        elif record.name.find(self.name, 0, self.nlen) != 0:
778            return False
779        return (record.name[self.nlen] == ".")
780
781class Filterer(object):
782    """
783    A base class for loggers and handlers which allows them to share
784    common code.
785    """
786    def __init__(self):
787        """
788        Initialize the list of filters to be an empty list.
789        """
790        self.filters = []
791
792    def addFilter(self, filter):
793        """
794        Add the specified filter to this handler.
795        """
796        if not (filter in self.filters):
797            self.filters.append(filter)
798
799    def removeFilter(self, filter):
800        """
801        Remove the specified filter from this handler.
802        """
803        if filter in self.filters:
804            self.filters.remove(filter)
805
806    def filter(self, record):
807        """
808        Determine if a record is loggable by consulting all the filters.
809
810        The default is to allow the record to be logged; any filter can veto
811        this and the record is then dropped. Returns a zero value if a record
812        is to be dropped, else non-zero.
813
814        .. versionchanged:: 3.2
815
816           Allow filters to be just callables.
817        """
818        rv = True
819        for f in self.filters:
820            if hasattr(f, 'filter'):
821                result = f.filter(record)
822            else:
823                result = f(record) # assume callable - will raise if not
824            if not result:
825                rv = False
826                break
827        return rv
828
829#---------------------------------------------------------------------------
830#   Handler classes and functions
831#---------------------------------------------------------------------------
832
833_handlers = weakref.WeakValueDictionary()  #map of handler names to handlers
834_handlerList = [] # added to allow handlers to be removed in reverse of order initialized
835
836def _removeHandlerRef(wr):
837    """
838    Remove a handler reference from the internal cleanup list.
839    """
840    # This function can be called during module teardown, when globals are
841    # set to None. It can also be called from another thread. So we need to
842    # pre-emptively grab the necessary globals and check if they're None,
843    # to prevent race conditions and failures during interpreter shutdown.
844    acquire, release, handlers = _acquireLock, _releaseLock, _handlerList
845    if acquire and release and handlers:
846        acquire()
847        try:
848            if wr in handlers:
849                handlers.remove(wr)
850        finally:
851            release()
852
853def _addHandlerRef(handler):
854    """
855    Add a handler to the internal cleanup list using a weak reference.
856    """
857    _acquireLock()
858    try:
859        _handlerList.append(weakref.ref(handler, _removeHandlerRef))
860    finally:
861        _releaseLock()
862
863class Handler(Filterer):
864    """
865    Handler instances dispatch logging events to specific destinations.
866
867    The base handler class. Acts as a placeholder which defines the Handler
868    interface. Handlers can optionally use Formatter instances to format
869    records as desired. By default, no formatter is specified; in this case,
870    the 'raw' message as determined by record.message is logged.
871    """
872    def __init__(self, level=NOTSET):
873        """
874        Initializes the instance - basically setting the formatter to None
875        and the filter list to empty.
876        """
877        Filterer.__init__(self)
878        self._name = None
879        self.level = _checkLevel(level)
880        self.formatter = None
881        self._closed = False
882        # Add the handler to the global _handlerList (for cleanup on shutdown)
883        _addHandlerRef(self)
884        self.createLock()
885
886    def get_name(self):
887        return self._name
888
889    def set_name(self, name):
890        _acquireLock()
891        try:
892            if self._name in _handlers:
893                del _handlers[self._name]
894            self._name = name
895            if name:
896                _handlers[name] = self
897        finally:
898            _releaseLock()
899
900    name = property(get_name, set_name)
901
902    def createLock(self):
903        """
904        Acquire a thread lock for serializing access to the underlying I/O.
905        """
906        self.lock = threading.RLock()
907        _register_at_fork_reinit_lock(self)
908
909    def _at_fork_reinit(self):
910        self.lock._at_fork_reinit()
911
912    def acquire(self):
913        """
914        Acquire the I/O thread lock.
915        """
916        if self.lock:
917            self.lock.acquire()
918
919    def release(self):
920        """
921        Release the I/O thread lock.
922        """
923        if self.lock:
924            self.lock.release()
925
926    def setLevel(self, level):
927        """
928        Set the logging level of this handler.  level must be an int or a str.
929        """
930        self.level = _checkLevel(level)
931
932    def format(self, record):
933        """
934        Format the specified record.
935
936        If a formatter is set, use it. Otherwise, use the default formatter
937        for the module.
938        """
939        if self.formatter:
940            fmt = self.formatter
941        else:
942            fmt = _defaultFormatter
943        return fmt.format(record)
944
945    def emit(self, record):
946        """
947        Do whatever it takes to actually log the specified logging record.
948
949        This version is intended to be implemented by subclasses and so
950        raises a NotImplementedError.
951        """
952        raise NotImplementedError('emit must be implemented '
953                                  'by Handler subclasses')
954
955    def handle(self, record):
956        """
957        Conditionally emit the specified logging record.
958
959        Emission depends on filters which may have been added to the handler.
960        Wrap the actual emission of the record with acquisition/release of
961        the I/O thread lock. Returns whether the filter passed the record for
962        emission.
963        """
964        rv = self.filter(record)
965        if rv:
966            self.acquire()
967            try:
968                self.emit(record)
969            finally:
970                self.release()
971        return rv
972
973    def setFormatter(self, fmt):
974        """
975        Set the formatter for this handler.
976        """
977        self.formatter = fmt
978
979    def flush(self):
980        """
981        Ensure all logging output has been flushed.
982
983        This version does nothing and is intended to be implemented by
984        subclasses.
985        """
986        pass
987
988    def close(self):
989        """
990        Tidy up any resources used by the handler.
991
992        This version removes the handler from an internal map of handlers,
993        _handlers, which is used for handler lookup by name. Subclasses
994        should ensure that this gets called from overridden close()
995        methods.
996        """
997        #get the module data lock, as we're updating a shared structure.
998        _acquireLock()
999        try:    #unlikely to raise an exception, but you never know...
1000            self._closed = True
1001            if self._name and self._name in _handlers:
1002                del _handlers[self._name]
1003        finally:
1004            _releaseLock()
1005
1006    def handleError(self, record):
1007        """
1008        Handle errors which occur during an emit() call.
1009
1010        This method should be called from handlers when an exception is
1011        encountered during an emit() call. If raiseExceptions is false,
1012        exceptions get silently ignored. This is what is mostly wanted
1013        for a logging system - most users will not care about errors in
1014        the logging system, they are more interested in application errors.
1015        You could, however, replace this with a custom handler if you wish.
1016        The record which was being processed is passed in to this method.
1017        """
1018        if raiseExceptions and sys.stderr:  # see issue 13807
1019            t, v, tb = sys.exc_info()
1020            try:
1021                sys.stderr.write('--- Logging error ---\n')
1022                traceback.print_exception(t, v, tb, None, sys.stderr)
1023                sys.stderr.write('Call stack:\n')
1024                # Walk the stack frame up until we're out of logging,
1025                # so as to print the calling context.
1026                frame = tb.tb_frame
1027                while (frame and os.path.dirname(frame.f_code.co_filename) ==
1028                       __path__[0]):
1029                    frame = frame.f_back
1030                if frame:
1031                    traceback.print_stack(frame, file=sys.stderr)
1032                else:
1033                    # couldn't find the right stack frame, for some reason
1034                    sys.stderr.write('Logged from file %s, line %s\n' % (
1035                                     record.filename, record.lineno))
1036                # Issue 18671: output logging message and arguments
1037                try:
1038                    sys.stderr.write('Message: %r\n'
1039                                     'Arguments: %s\n' % (record.msg,
1040                                                          record.args))
1041                except RecursionError:  # See issue 36272
1042                    raise
1043                except Exception:
1044                    sys.stderr.write('Unable to print the message and arguments'
1045                                     ' - possible formatting error.\nUse the'
1046                                     ' traceback above to help find the error.\n'
1047                                    )
1048            except OSError: #pragma: no cover
1049                pass    # see issue 5971
1050            finally:
1051                del t, v, tb
1052
1053    def __repr__(self):
1054        level = getLevelName(self.level)
1055        return '<%s (%s)>' % (self.__class__.__name__, level)
1056
1057class StreamHandler(Handler):
1058    """
1059    A handler class which writes logging records, appropriately formatted,
1060    to a stream. Note that this class does not close the stream, as
1061    sys.stdout or sys.stderr may be used.
1062    """
1063
1064    terminator = '\n'
1065
1066    def __init__(self, stream=None):
1067        """
1068        Initialize the handler.
1069
1070        If stream is not specified, sys.stderr is used.
1071        """
1072        Handler.__init__(self)
1073        if stream is None:
1074            stream = sys.stderr
1075        self.stream = stream
1076
1077    def flush(self):
1078        """
1079        Flushes the stream.
1080        """
1081        self.acquire()
1082        try:
1083            if self.stream and hasattr(self.stream, "flush"):
1084                self.stream.flush()
1085        finally:
1086            self.release()
1087
1088    def emit(self, record):
1089        """
1090        Emit a record.
1091
1092        If a formatter is specified, it is used to format the record.
1093        The record is then written to the stream with a trailing newline.  If
1094        exception information is present, it is formatted using
1095        traceback.print_exception and appended to the stream.  If the stream
1096        has an 'encoding' attribute, it is used to determine how to do the
1097        output to the stream.
1098        """
1099        try:
1100            msg = self.format(record)
1101            stream = self.stream
1102            # issue 35046: merged two stream.writes into one.
1103            stream.write(msg + self.terminator)
1104            self.flush()
1105        except RecursionError:  # See issue 36272
1106            raise
1107        except Exception:
1108            self.handleError(record)
1109
1110    def setStream(self, stream):
1111        """
1112        Sets the StreamHandler's stream to the specified value,
1113        if it is different.
1114
1115        Returns the old stream, if the stream was changed, or None
1116        if it wasn't.
1117        """
1118        if stream is self.stream:
1119            result = None
1120        else:
1121            result = self.stream
1122            self.acquire()
1123            try:
1124                self.flush()
1125                self.stream = stream
1126            finally:
1127                self.release()
1128        return result
1129
1130    def __repr__(self):
1131        level = getLevelName(self.level)
1132        name = getattr(self.stream, 'name', '')
1133        #  bpo-36015: name can be an int
1134        name = str(name)
1135        if name:
1136            name += ' '
1137        return '<%s %s(%s)>' % (self.__class__.__name__, name, level)
1138
1139
1140class FileHandler(StreamHandler):
1141    """
1142    A handler class which writes formatted logging records to disk files.
1143    """
1144    def __init__(self, filename, mode='a', encoding=None, delay=False, errors=None):
1145        """
1146        Open the specified file and use it as the stream for logging.
1147        """
1148        # Issue #27493: add support for Path objects to be passed in
1149        filename = os.fspath(filename)
1150        #keep the absolute path, otherwise derived classes which use this
1151        #may come a cropper when the current directory changes
1152        self.baseFilename = os.path.abspath(filename)
1153        self.mode = mode
1154        self.encoding = encoding
1155        if "b" not in mode:
1156            self.encoding = io.text_encoding(encoding)
1157        self.errors = errors
1158        self.delay = delay
1159        # bpo-26789: FileHandler keeps a reference to the builtin open()
1160        # function to be able to open or reopen the file during Python
1161        # finalization.
1162        self._builtin_open = open
1163        if delay:
1164            #We don't open the stream, but we still need to call the
1165            #Handler constructor to set level, formatter, lock etc.
1166            Handler.__init__(self)
1167            self.stream = None
1168        else:
1169            StreamHandler.__init__(self, self._open())
1170
1171    def close(self):
1172        """
1173        Closes the stream.
1174        """
1175        self.acquire()
1176        try:
1177            try:
1178                if self.stream:
1179                    try:
1180                        self.flush()
1181                    finally:
1182                        stream = self.stream
1183                        self.stream = None
1184                        if hasattr(stream, "close"):
1185                            stream.close()
1186            finally:
1187                # Issue #19523: call unconditionally to
1188                # prevent a handler leak when delay is set
1189                # Also see Issue #42378: we also rely on
1190                # self._closed being set to True there
1191                StreamHandler.close(self)
1192        finally:
1193            self.release()
1194
1195    def _open(self):
1196        """
1197        Open the current base file with the (original) mode and encoding.
1198        Return the resulting stream.
1199        """
1200        open_func = self._builtin_open
1201        return open_func(self.baseFilename, self.mode,
1202                         encoding=self.encoding, errors=self.errors)
1203
1204    def emit(self, record):
1205        """
1206        Emit a record.
1207
1208        If the stream was not opened because 'delay' was specified in the
1209        constructor, open it before calling the superclass's emit.
1210
1211        If stream is not open, current mode is 'w' and `_closed=True`, record
1212        will not be emitted (see Issue #42378).
1213        """
1214        if self.stream is None:
1215            if self.mode != 'w' or not self._closed:
1216                self.stream = self._open()
1217        if self.stream:
1218            StreamHandler.emit(self, record)
1219
1220    def __repr__(self):
1221        level = getLevelName(self.level)
1222        return '<%s %s (%s)>' % (self.__class__.__name__, self.baseFilename, level)
1223
1224
1225class _StderrHandler(StreamHandler):
1226    """
1227    This class is like a StreamHandler using sys.stderr, but always uses
1228    whatever sys.stderr is currently set to rather than the value of
1229    sys.stderr at handler construction time.
1230    """
1231    def __init__(self, level=NOTSET):
1232        """
1233        Initialize the handler.
1234        """
1235        Handler.__init__(self, level)
1236
1237    @property
1238    def stream(self):
1239        return sys.stderr
1240
1241
1242_defaultLastResort = _StderrHandler(WARNING)
1243lastResort = _defaultLastResort
1244
1245#---------------------------------------------------------------------------
1246#   Manager classes and functions
1247#---------------------------------------------------------------------------
1248
1249class PlaceHolder(object):
1250    """
1251    PlaceHolder instances are used in the Manager logger hierarchy to take
1252    the place of nodes for which no loggers have been defined. This class is
1253    intended for internal use only and not as part of the public API.
1254    """
1255    def __init__(self, alogger):
1256        """
1257        Initialize with the specified logger being a child of this placeholder.
1258        """
1259        self.loggerMap = { alogger : None }
1260
1261    def append(self, alogger):
1262        """
1263        Add the specified logger as a child of this placeholder.
1264        """
1265        if alogger not in self.loggerMap:
1266            self.loggerMap[alogger] = None
1267
1268#
1269#   Determine which class to use when instantiating loggers.
1270#
1271
1272def setLoggerClass(klass):
1273    """
1274    Set the class to be used when instantiating a logger. The class should
1275    define __init__() such that only a name argument is required, and the
1276    __init__() should call Logger.__init__()
1277    """
1278    if klass != Logger:
1279        if not issubclass(klass, Logger):
1280            raise TypeError("logger not derived from logging.Logger: "
1281                            + klass.__name__)
1282    global _loggerClass
1283    _loggerClass = klass
1284
1285def getLoggerClass():
1286    """
1287    Return the class to be used when instantiating a logger.
1288    """
1289    return _loggerClass
1290
1291class Manager(object):
1292    """
1293    There is [under normal circumstances] just one Manager instance, which
1294    holds the hierarchy of loggers.
1295    """
1296    def __init__(self, rootnode):
1297        """
1298        Initialize the manager with the root node of the logger hierarchy.
1299        """
1300        self.root = rootnode
1301        self.disable = 0
1302        self.emittedNoHandlerWarning = False
1303        self.loggerDict = {}
1304        self.loggerClass = None
1305        self.logRecordFactory = None
1306
1307    @property
1308    def disable(self):
1309        return self._disable
1310
1311    @disable.setter
1312    def disable(self, value):
1313        self._disable = _checkLevel(value)
1314
1315    def getLogger(self, name):
1316        """
1317        Get a logger with the specified name (channel name), creating it
1318        if it doesn't yet exist. This name is a dot-separated hierarchical
1319        name, such as "a", "a.b", "a.b.c" or similar.
1320
1321        If a PlaceHolder existed for the specified name [i.e. the logger
1322        didn't exist but a child of it did], replace it with the created
1323        logger and fix up the parent/child references which pointed to the
1324        placeholder to now point to the logger.
1325        """
1326        rv = None
1327        if not isinstance(name, str):
1328            raise TypeError('A logger name must be a string')
1329        _acquireLock()
1330        try:
1331            if name in self.loggerDict:
1332                rv = self.loggerDict[name]
1333                if isinstance(rv, PlaceHolder):
1334                    ph = rv
1335                    rv = (self.loggerClass or _loggerClass)(name)
1336                    rv.manager = self
1337                    self.loggerDict[name] = rv
1338                    self._fixupChildren(ph, rv)
1339                    self._fixupParents(rv)
1340            else:
1341                rv = (self.loggerClass or _loggerClass)(name)
1342                rv.manager = self
1343                self.loggerDict[name] = rv
1344                self._fixupParents(rv)
1345        finally:
1346            _releaseLock()
1347        return rv
1348
1349    def setLoggerClass(self, klass):
1350        """
1351        Set the class to be used when instantiating a logger with this Manager.
1352        """
1353        if klass != Logger:
1354            if not issubclass(klass, Logger):
1355                raise TypeError("logger not derived from logging.Logger: "
1356                                + klass.__name__)
1357        self.loggerClass = klass
1358
1359    def setLogRecordFactory(self, factory):
1360        """
1361        Set the factory to be used when instantiating a log record with this
1362        Manager.
1363        """
1364        self.logRecordFactory = factory
1365
1366    def _fixupParents(self, alogger):
1367        """
1368        Ensure that there are either loggers or placeholders all the way
1369        from the specified logger to the root of the logger hierarchy.
1370        """
1371        name = alogger.name
1372        i = name.rfind(".")
1373        rv = None
1374        while (i > 0) and not rv:
1375            substr = name[:i]
1376            if substr not in self.loggerDict:
1377                self.loggerDict[substr] = PlaceHolder(alogger)
1378            else:
1379                obj = self.loggerDict[substr]
1380                if isinstance(obj, Logger):
1381                    rv = obj
1382                else:
1383                    assert isinstance(obj, PlaceHolder)
1384                    obj.append(alogger)
1385            i = name.rfind(".", 0, i - 1)
1386        if not rv:
1387            rv = self.root
1388        alogger.parent = rv
1389
1390    def _fixupChildren(self, ph, alogger):
1391        """
1392        Ensure that children of the placeholder ph are connected to the
1393        specified logger.
1394        """
1395        name = alogger.name
1396        namelen = len(name)
1397        for c in ph.loggerMap.keys():
1398            #The if means ... if not c.parent.name.startswith(nm)
1399            if c.parent.name[:namelen] != name:
1400                alogger.parent = c.parent
1401                c.parent = alogger
1402
1403    def _clear_cache(self):
1404        """
1405        Clear the cache for all loggers in loggerDict
1406        Called when level changes are made
1407        """
1408
1409        _acquireLock()
1410        for logger in self.loggerDict.values():
1411            if isinstance(logger, Logger):
1412                logger._cache.clear()
1413        self.root._cache.clear()
1414        _releaseLock()
1415
1416#---------------------------------------------------------------------------
1417#   Logger classes and functions
1418#---------------------------------------------------------------------------
1419
1420class Logger(Filterer):
1421    """
1422    Instances of the Logger class represent a single logging channel. A
1423    "logging channel" indicates an area of an application. Exactly how an
1424    "area" is defined is up to the application developer. Since an
1425    application can have any number of areas, logging channels are identified
1426    by a unique string. Application areas can be nested (e.g. an area
1427    of "input processing" might include sub-areas "read CSV files", "read
1428    XLS files" and "read Gnumeric files"). To cater for this natural nesting,
1429    channel names are organized into a namespace hierarchy where levels are
1430    separated by periods, much like the Java or Python package namespace. So
1431    in the instance given above, channel names might be "input" for the upper
1432    level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
1433    There is no arbitrary limit to the depth of nesting.
1434    """
1435    def __init__(self, name, level=NOTSET):
1436        """
1437        Initialize the logger with a name and an optional level.
1438        """
1439        Filterer.__init__(self)
1440        self.name = name
1441        self.level = _checkLevel(level)
1442        self.parent = None
1443        self.propagate = True
1444        self.handlers = []
1445        self.disabled = False
1446        self._cache = {}
1447
1448    def setLevel(self, level):
1449        """
1450        Set the logging level of this logger.  level must be an int or a str.
1451        """
1452        self.level = _checkLevel(level)
1453        self.manager._clear_cache()
1454
1455    def debug(self, msg, *args, **kwargs):
1456        """
1457        Log 'msg % args' with severity 'DEBUG'.
1458
1459        To pass exception information, use the keyword argument exc_info with
1460        a true value, e.g.
1461
1462        logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
1463        """
1464        if self.isEnabledFor(DEBUG):
1465            self._log(DEBUG, msg, args, **kwargs)
1466
1467    def info(self, msg, *args, **kwargs):
1468        """
1469        Log 'msg % args' with severity 'INFO'.
1470
1471        To pass exception information, use the keyword argument exc_info with
1472        a true value, e.g.
1473
1474        logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
1475        """
1476        if self.isEnabledFor(INFO):
1477            self._log(INFO, msg, args, **kwargs)
1478
1479    def warning(self, msg, *args, **kwargs):
1480        """
1481        Log 'msg % args' with severity 'WARNING'.
1482
1483        To pass exception information, use the keyword argument exc_info with
1484        a true value, e.g.
1485
1486        logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
1487        """
1488        if self.isEnabledFor(WARNING):
1489            self._log(WARNING, msg, args, **kwargs)
1490
1491    def warn(self, msg, *args, **kwargs):
1492        warnings.warn("The 'warn' method is deprecated, "
1493            "use 'warning' instead", DeprecationWarning, 2)
1494        self.warning(msg, *args, **kwargs)
1495
1496    def error(self, msg, *args, **kwargs):
1497        """
1498        Log 'msg % args' with severity 'ERROR'.
1499
1500        To pass exception information, use the keyword argument exc_info with
1501        a true value, e.g.
1502
1503        logger.error("Houston, we have a %s", "major problem", exc_info=1)
1504        """
1505        if self.isEnabledFor(ERROR):
1506            self._log(ERROR, msg, args, **kwargs)
1507
1508    def exception(self, msg, *args, exc_info=True, **kwargs):
1509        """
1510        Convenience method for logging an ERROR with exception information.
1511        """
1512        self.error(msg, *args, exc_info=exc_info, **kwargs)
1513
1514    def critical(self, msg, *args, **kwargs):
1515        """
1516        Log 'msg % args' with severity 'CRITICAL'.
1517
1518        To pass exception information, use the keyword argument exc_info with
1519        a true value, e.g.
1520
1521        logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
1522        """
1523        if self.isEnabledFor(CRITICAL):
1524            self._log(CRITICAL, msg, args, **kwargs)
1525
1526    def fatal(self, msg, *args, **kwargs):
1527        """
1528        Don't use this method, use critical() instead.
1529        """
1530        self.critical(msg, *args, **kwargs)
1531
1532    def log(self, level, msg, *args, **kwargs):
1533        """
1534        Log 'msg % args' with the integer severity 'level'.
1535
1536        To pass exception information, use the keyword argument exc_info with
1537        a true value, e.g.
1538
1539        logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
1540        """
1541        if not isinstance(level, int):
1542            if raiseExceptions:
1543                raise TypeError("level must be an integer")
1544            else:
1545                return
1546        if self.isEnabledFor(level):
1547            self._log(level, msg, args, **kwargs)
1548
1549    def findCaller(self, stack_info=False, stacklevel=1):
1550        """
1551        Find the stack frame of the caller so that we can note the source
1552        file name, line number and function name.
1553        """
1554        f = currentframe()
1555        #On some versions of IronPython, currentframe() returns None if
1556        #IronPython isn't run with -X:Frames.
1557        if f is not None:
1558            f = f.f_back
1559        orig_f = f
1560        while f and stacklevel > 1:
1561            f = f.f_back
1562            stacklevel -= 1
1563        if not f:
1564            f = orig_f
1565        rv = "(unknown file)", 0, "(unknown function)", None
1566        while hasattr(f, "f_code"):
1567            co = f.f_code
1568            filename = os.path.normcase(co.co_filename)
1569            if filename == _srcfile:
1570                f = f.f_back
1571                continue
1572            sinfo = None
1573            if stack_info:
1574                sio = io.StringIO()
1575                sio.write('Stack (most recent call last):\n')
1576                traceback.print_stack(f, file=sio)
1577                sinfo = sio.getvalue()
1578                if sinfo[-1] == '\n':
1579                    sinfo = sinfo[:-1]
1580                sio.close()
1581            rv = (co.co_filename, f.f_lineno, co.co_name, sinfo)
1582            break
1583        return rv
1584
1585    def makeRecord(self, name, level, fn, lno, msg, args, exc_info,
1586                   func=None, extra=None, sinfo=None):
1587        """
1588        A factory method which can be overridden in subclasses to create
1589        specialized LogRecords.
1590        """
1591        rv = _logRecordFactory(name, level, fn, lno, msg, args, exc_info, func,
1592                             sinfo)
1593        if extra is not None:
1594            for key in extra:
1595                if (key in ["message", "asctime"]) or (key in rv.__dict__):
1596                    raise KeyError("Attempt to overwrite %r in LogRecord" % key)
1597                rv.__dict__[key] = extra[key]
1598        return rv
1599
1600    def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False,
1601             stacklevel=1):
1602        """
1603        Low-level logging routine which creates a LogRecord and then calls
1604        all the handlers of this logger to handle the record.
1605        """
1606        sinfo = None
1607        if _srcfile:
1608            #IronPython doesn't track Python frames, so findCaller raises an
1609            #exception on some versions of IronPython. We trap it here so that
1610            #IronPython can use logging.
1611            try:
1612                fn, lno, func, sinfo = self.findCaller(stack_info, stacklevel)
1613            except ValueError: # pragma: no cover
1614                fn, lno, func = "(unknown file)", 0, "(unknown function)"
1615        else: # pragma: no cover
1616            fn, lno, func = "(unknown file)", 0, "(unknown function)"
1617        if exc_info:
1618            if isinstance(exc_info, BaseException):
1619                exc_info = (type(exc_info), exc_info, exc_info.__traceback__)
1620            elif not isinstance(exc_info, tuple):
1621                exc_info = sys.exc_info()
1622        record = self.makeRecord(self.name, level, fn, lno, msg, args,
1623                                 exc_info, func, extra, sinfo)
1624        self.handle(record)
1625
1626    def handle(self, record):
1627        """
1628        Call the handlers for the specified record.
1629
1630        This method is used for unpickled records received from a socket, as
1631        well as those created locally. Logger-level filtering is applied.
1632        """
1633        if (not self.disabled) and self.filter(record):
1634            self.callHandlers(record)
1635
1636    def addHandler(self, hdlr):
1637        """
1638        Add the specified handler to this logger.
1639        """
1640        _acquireLock()
1641        try:
1642            if not (hdlr in self.handlers):
1643                self.handlers.append(hdlr)
1644        finally:
1645            _releaseLock()
1646
1647    def removeHandler(self, hdlr):
1648        """
1649        Remove the specified handler from this logger.
1650        """
1651        _acquireLock()
1652        try:
1653            if hdlr in self.handlers:
1654                self.handlers.remove(hdlr)
1655        finally:
1656            _releaseLock()
1657
1658    def hasHandlers(self):
1659        """
1660        See if this logger has any handlers configured.
1661
1662        Loop through all handlers for this logger and its parents in the
1663        logger hierarchy. Return True if a handler was found, else False.
1664        Stop searching up the hierarchy whenever a logger with the "propagate"
1665        attribute set to zero is found - that will be the last logger which
1666        is checked for the existence of handlers.
1667        """
1668        c = self
1669        rv = False
1670        while c:
1671            if c.handlers:
1672                rv = True
1673                break
1674            if not c.propagate:
1675                break
1676            else:
1677                c = c.parent
1678        return rv
1679
1680    def callHandlers(self, record):
1681        """
1682        Pass a record to all relevant handlers.
1683
1684        Loop through all handlers for this logger and its parents in the
1685        logger hierarchy. If no handler was found, output a one-off error
1686        message to sys.stderr. Stop searching up the hierarchy whenever a
1687        logger with the "propagate" attribute set to zero is found - that
1688        will be the last logger whose handlers are called.
1689        """
1690        c = self
1691        found = 0
1692        while c:
1693            for hdlr in c.handlers:
1694                found = found + 1
1695                if record.levelno >= hdlr.level:
1696                    hdlr.handle(record)
1697            if not c.propagate:
1698                c = None    #break out
1699            else:
1700                c = c.parent
1701        if (found == 0):
1702            if lastResort:
1703                if record.levelno >= lastResort.level:
1704                    lastResort.handle(record)
1705            elif raiseExceptions and not self.manager.emittedNoHandlerWarning:
1706                sys.stderr.write("No handlers could be found for logger"
1707                                 " \"%s\"\n" % self.name)
1708                self.manager.emittedNoHandlerWarning = True
1709
1710    def getEffectiveLevel(self):
1711        """
1712        Get the effective level for this logger.
1713
1714        Loop through this logger and its parents in the logger hierarchy,
1715        looking for a non-zero logging level. Return the first one found.
1716        """
1717        logger = self
1718        while logger:
1719            if logger.level:
1720                return logger.level
1721            logger = logger.parent
1722        return NOTSET
1723
1724    def isEnabledFor(self, level):
1725        """
1726        Is this logger enabled for level 'level'?
1727        """
1728        if self.disabled:
1729            return False
1730
1731        try:
1732            return self._cache[level]
1733        except KeyError:
1734            _acquireLock()
1735            try:
1736                if self.manager.disable >= level:
1737                    is_enabled = self._cache[level] = False
1738                else:
1739                    is_enabled = self._cache[level] = (
1740                        level >= self.getEffectiveLevel()
1741                    )
1742            finally:
1743                _releaseLock()
1744            return is_enabled
1745
1746    def getChild(self, suffix):
1747        """
1748        Get a logger which is a descendant to this one.
1749
1750        This is a convenience method, such that
1751
1752        logging.getLogger('abc').getChild('def.ghi')
1753
1754        is the same as
1755
1756        logging.getLogger('abc.def.ghi')
1757
1758        It's useful, for example, when the parent logger is named using
1759        __name__ rather than a literal string.
1760        """
1761        if self.root is not self:
1762            suffix = '.'.join((self.name, suffix))
1763        return self.manager.getLogger(suffix)
1764
1765    def __repr__(self):
1766        level = getLevelName(self.getEffectiveLevel())
1767        return '<%s %s (%s)>' % (self.__class__.__name__, self.name, level)
1768
1769    def __reduce__(self):
1770        # In general, only the root logger will not be accessible via its name.
1771        # However, the root logger's class has its own __reduce__ method.
1772        if getLogger(self.name) is not self:
1773            import pickle
1774            raise pickle.PicklingError('logger cannot be pickled')
1775        return getLogger, (self.name,)
1776
1777
1778class RootLogger(Logger):
1779    """
1780    A root logger is not that different to any other logger, except that
1781    it must have a logging level and there is only one instance of it in
1782    the hierarchy.
1783    """
1784    def __init__(self, level):
1785        """
1786        Initialize the logger with the name "root".
1787        """
1788        Logger.__init__(self, "root", level)
1789
1790    def __reduce__(self):
1791        return getLogger, ()
1792
1793_loggerClass = Logger
1794
1795class LoggerAdapter(object):
1796    """
1797    An adapter for loggers which makes it easier to specify contextual
1798    information in logging output.
1799    """
1800
1801    def __init__(self, logger, extra=None):
1802        """
1803        Initialize the adapter with a logger and a dict-like object which
1804        provides contextual information. This constructor signature allows
1805        easy stacking of LoggerAdapters, if so desired.
1806
1807        You can effectively pass keyword arguments as shown in the
1808        following example:
1809
1810        adapter = LoggerAdapter(someLogger, dict(p1=v1, p2="v2"))
1811        """
1812        self.logger = logger
1813        self.extra = extra
1814
1815    def process(self, msg, kwargs):
1816        """
1817        Process the logging message and keyword arguments passed in to
1818        a logging call to insert contextual information. You can either
1819        manipulate the message itself, the keyword args or both. Return
1820        the message and kwargs modified (or not) to suit your needs.
1821
1822        Normally, you'll only need to override this one method in a
1823        LoggerAdapter subclass for your specific needs.
1824        """
1825        kwargs["extra"] = self.extra
1826        return msg, kwargs
1827
1828    #
1829    # Boilerplate convenience methods
1830    #
1831    def debug(self, msg, *args, **kwargs):
1832        """
1833        Delegate a debug call to the underlying logger.
1834        """
1835        self.log(DEBUG, msg, *args, **kwargs)
1836
1837    def info(self, msg, *args, **kwargs):
1838        """
1839        Delegate an info call to the underlying logger.
1840        """
1841        self.log(INFO, msg, *args, **kwargs)
1842
1843    def warning(self, msg, *args, **kwargs):
1844        """
1845        Delegate a warning call to the underlying logger.
1846        """
1847        self.log(WARNING, msg, *args, **kwargs)
1848
1849    def warn(self, msg, *args, **kwargs):
1850        warnings.warn("The 'warn' method is deprecated, "
1851            "use 'warning' instead", DeprecationWarning, 2)
1852        self.warning(msg, *args, **kwargs)
1853
1854    def error(self, msg, *args, **kwargs):
1855        """
1856        Delegate an error call to the underlying logger.
1857        """
1858        self.log(ERROR, msg, *args, **kwargs)
1859
1860    def exception(self, msg, *args, exc_info=True, **kwargs):
1861        """
1862        Delegate an exception call to the underlying logger.
1863        """
1864        self.log(ERROR, msg, *args, exc_info=exc_info, **kwargs)
1865
1866    def critical(self, msg, *args, **kwargs):
1867        """
1868        Delegate a critical call to the underlying logger.
1869        """
1870        self.log(CRITICAL, msg, *args, **kwargs)
1871
1872    def log(self, level, msg, *args, **kwargs):
1873        """
1874        Delegate a log call to the underlying logger, after adding
1875        contextual information from this adapter instance.
1876        """
1877        if self.isEnabledFor(level):
1878            msg, kwargs = self.process(msg, kwargs)
1879            self.logger.log(level, msg, *args, **kwargs)
1880
1881    def isEnabledFor(self, level):
1882        """
1883        Is this logger enabled for level 'level'?
1884        """
1885        return self.logger.isEnabledFor(level)
1886
1887    def setLevel(self, level):
1888        """
1889        Set the specified level on the underlying logger.
1890        """
1891        self.logger.setLevel(level)
1892
1893    def getEffectiveLevel(self):
1894        """
1895        Get the effective level for the underlying logger.
1896        """
1897        return self.logger.getEffectiveLevel()
1898
1899    def hasHandlers(self):
1900        """
1901        See if the underlying logger has any handlers.
1902        """
1903        return self.logger.hasHandlers()
1904
1905    def _log(self, level, msg, args, exc_info=None, extra=None, stack_info=False):
1906        """
1907        Low-level log implementation, proxied to allow nested logger adapters.
1908        """
1909        return self.logger._log(
1910            level,
1911            msg,
1912            args,
1913            exc_info=exc_info,
1914            extra=extra,
1915            stack_info=stack_info,
1916        )
1917
1918    @property
1919    def manager(self):
1920        return self.logger.manager
1921
1922    @manager.setter
1923    def manager(self, value):
1924        self.logger.manager = value
1925
1926    @property
1927    def name(self):
1928        return self.logger.name
1929
1930    def __repr__(self):
1931        logger = self.logger
1932        level = getLevelName(logger.getEffectiveLevel())
1933        return '<%s %s (%s)>' % (self.__class__.__name__, logger.name, level)
1934
1935root = RootLogger(WARNING)
1936Logger.root = root
1937Logger.manager = Manager(Logger.root)
1938
1939#---------------------------------------------------------------------------
1940# Configuration classes and functions
1941#---------------------------------------------------------------------------
1942
1943def basicConfig(**kwargs):
1944    """
1945    Do basic configuration for the logging system.
1946
1947    This function does nothing if the root logger already has handlers
1948    configured, unless the keyword argument *force* is set to ``True``.
1949    It is a convenience method intended for use by simple scripts
1950    to do one-shot configuration of the logging package.
1951
1952    The default behaviour is to create a StreamHandler which writes to
1953    sys.stderr, set a formatter using the BASIC_FORMAT format string, and
1954    add the handler to the root logger.
1955
1956    A number of optional keyword arguments may be specified, which can alter
1957    the default behaviour.
1958
1959    filename  Specifies that a FileHandler be created, using the specified
1960              filename, rather than a StreamHandler.
1961    filemode  Specifies the mode to open the file, if filename is specified
1962              (if filemode is unspecified, it defaults to 'a').
1963    format    Use the specified format string for the handler.
1964    datefmt   Use the specified date/time format.
1965    style     If a format string is specified, use this to specify the
1966              type of format string (possible values '%', '{', '$', for
1967              %-formatting, :meth:`str.format` and :class:`string.Template`
1968              - defaults to '%').
1969    level     Set the root logger level to the specified level.
1970    stream    Use the specified stream to initialize the StreamHandler. Note
1971              that this argument is incompatible with 'filename' - if both
1972              are present, 'stream' is ignored.
1973    handlers  If specified, this should be an iterable of already created
1974              handlers, which will be added to the root handler. Any handler
1975              in the list which does not have a formatter assigned will be
1976              assigned the formatter created in this function.
1977    force     If this keyword  is specified as true, any existing handlers
1978              attached to the root logger are removed and closed, before
1979              carrying out the configuration as specified by the other
1980              arguments.
1981    encoding  If specified together with a filename, this encoding is passed to
1982              the created FileHandler, causing it to be used when the file is
1983              opened.
1984    errors    If specified together with a filename, this value is passed to the
1985              created FileHandler, causing it to be used when the file is
1986              opened in text mode. If not specified, the default value is
1987              `backslashreplace`.
1988
1989    Note that you could specify a stream created using open(filename, mode)
1990    rather than passing the filename and mode in. However, it should be
1991    remembered that StreamHandler does not close its stream (since it may be
1992    using sys.stdout or sys.stderr), whereas FileHandler closes its stream
1993    when the handler is closed.
1994
1995    .. versionchanged:: 3.2
1996       Added the ``style`` parameter.
1997
1998    .. versionchanged:: 3.3
1999       Added the ``handlers`` parameter. A ``ValueError`` is now thrown for
2000       incompatible arguments (e.g. ``handlers`` specified together with
2001       ``filename``/``filemode``, or ``filename``/``filemode`` specified
2002       together with ``stream``, or ``handlers`` specified together with
2003       ``stream``.
2004
2005    .. versionchanged:: 3.8
2006       Added the ``force`` parameter.
2007
2008    .. versionchanged:: 3.9
2009       Added the ``encoding`` and ``errors`` parameters.
2010    """
2011    # Add thread safety in case someone mistakenly calls
2012    # basicConfig() from multiple threads
2013    _acquireLock()
2014    try:
2015        force = kwargs.pop('force', False)
2016        encoding = kwargs.pop('encoding', None)
2017        errors = kwargs.pop('errors', 'backslashreplace')
2018        if force:
2019            for h in root.handlers[:]:
2020                root.removeHandler(h)
2021                h.close()
2022        if len(root.handlers) == 0:
2023            handlers = kwargs.pop("handlers", None)
2024            if handlers is None:
2025                if "stream" in kwargs and "filename" in kwargs:
2026                    raise ValueError("'stream' and 'filename' should not be "
2027                                     "specified together")
2028            else:
2029                if "stream" in kwargs or "filename" in kwargs:
2030                    raise ValueError("'stream' or 'filename' should not be "
2031                                     "specified together with 'handlers'")
2032            if handlers is None:
2033                filename = kwargs.pop("filename", None)
2034                mode = kwargs.pop("filemode", 'a')
2035                if filename:
2036                    if 'b' in mode:
2037                        errors = None
2038                    else:
2039                        encoding = io.text_encoding(encoding)
2040                    h = FileHandler(filename, mode,
2041                                    encoding=encoding, errors=errors)
2042                else:
2043                    stream = kwargs.pop("stream", None)
2044                    h = StreamHandler(stream)
2045                handlers = [h]
2046            dfs = kwargs.pop("datefmt", None)
2047            style = kwargs.pop("style", '%')
2048            if style not in _STYLES:
2049                raise ValueError('Style must be one of: %s' % ','.join(
2050                                 _STYLES.keys()))
2051            fs = kwargs.pop("format", _STYLES[style][1])
2052            fmt = Formatter(fs, dfs, style)
2053            for h in handlers:
2054                if h.formatter is None:
2055                    h.setFormatter(fmt)
2056                root.addHandler(h)
2057            level = kwargs.pop("level", None)
2058            if level is not None:
2059                root.setLevel(level)
2060            if kwargs:
2061                keys = ', '.join(kwargs.keys())
2062                raise ValueError('Unrecognised argument(s): %s' % keys)
2063    finally:
2064        _releaseLock()
2065
2066#---------------------------------------------------------------------------
2067# Utility functions at module level.
2068# Basically delegate everything to the root logger.
2069#---------------------------------------------------------------------------
2070
2071def getLogger(name=None):
2072    """
2073    Return a logger with the specified name, creating it if necessary.
2074
2075    If no name is specified, return the root logger.
2076    """
2077    if not name or isinstance(name, str) and name == root.name:
2078        return root
2079    return Logger.manager.getLogger(name)
2080
2081def critical(msg, *args, **kwargs):
2082    """
2083    Log a message with severity 'CRITICAL' on the root logger. If the logger
2084    has no handlers, call basicConfig() to add a console handler with a
2085    pre-defined format.
2086    """
2087    if len(root.handlers) == 0:
2088        basicConfig()
2089    root.critical(msg, *args, **kwargs)
2090
2091def fatal(msg, *args, **kwargs):
2092    """
2093    Don't use this function, use critical() instead.
2094    """
2095    critical(msg, *args, **kwargs)
2096
2097def error(msg, *args, **kwargs):
2098    """
2099    Log a message with severity 'ERROR' on the root logger. If the logger has
2100    no handlers, call basicConfig() to add a console handler with a pre-defined
2101    format.
2102    """
2103    if len(root.handlers) == 0:
2104        basicConfig()
2105    root.error(msg, *args, **kwargs)
2106
2107def exception(msg, *args, exc_info=True, **kwargs):
2108    """
2109    Log a message with severity 'ERROR' on the root logger, with exception
2110    information. If the logger has no handlers, basicConfig() is called to add
2111    a console handler with a pre-defined format.
2112    """
2113    error(msg, *args, exc_info=exc_info, **kwargs)
2114
2115def warning(msg, *args, **kwargs):
2116    """
2117    Log a message with severity 'WARNING' on the root logger. If the logger has
2118    no handlers, call basicConfig() to add a console handler with a pre-defined
2119    format.
2120    """
2121    if len(root.handlers) == 0:
2122        basicConfig()
2123    root.warning(msg, *args, **kwargs)
2124
2125def warn(msg, *args, **kwargs):
2126    warnings.warn("The 'warn' function is deprecated, "
2127        "use 'warning' instead", DeprecationWarning, 2)
2128    warning(msg, *args, **kwargs)
2129
2130def info(msg, *args, **kwargs):
2131    """
2132    Log a message with severity 'INFO' on the root logger. If the logger has
2133    no handlers, call basicConfig() to add a console handler with a pre-defined
2134    format.
2135    """
2136    if len(root.handlers) == 0:
2137        basicConfig()
2138    root.info(msg, *args, **kwargs)
2139
2140def debug(msg, *args, **kwargs):
2141    """
2142    Log a message with severity 'DEBUG' on the root logger. If the logger has
2143    no handlers, call basicConfig() to add a console handler with a pre-defined
2144    format.
2145    """
2146    if len(root.handlers) == 0:
2147        basicConfig()
2148    root.debug(msg, *args, **kwargs)
2149
2150def log(level, msg, *args, **kwargs):
2151    """
2152    Log 'msg % args' with the integer severity 'level' on the root logger. If
2153    the logger has no handlers, call basicConfig() to add a console handler
2154    with a pre-defined format.
2155    """
2156    if len(root.handlers) == 0:
2157        basicConfig()
2158    root.log(level, msg, *args, **kwargs)
2159
2160def disable(level=CRITICAL):
2161    """
2162    Disable all logging calls of severity 'level' and below.
2163    """
2164    root.manager.disable = level
2165    root.manager._clear_cache()
2166
2167def shutdown(handlerList=_handlerList):
2168    """
2169    Perform any cleanup actions in the logging system (e.g. flushing
2170    buffers).
2171
2172    Should be called at application exit.
2173    """
2174    for wr in reversed(handlerList[:]):
2175        #errors might occur, for example, if files are locked
2176        #we just ignore them if raiseExceptions is not set
2177        try:
2178            h = wr()
2179            if h:
2180                try:
2181                    h.acquire()
2182                    h.flush()
2183                    h.close()
2184                except (OSError, ValueError):
2185                    # Ignore errors which might be caused
2186                    # because handlers have been closed but
2187                    # references to them are still around at
2188                    # application exit.
2189                    pass
2190                finally:
2191                    h.release()
2192        except: # ignore everything, as we're shutting down
2193            if raiseExceptions:
2194                raise
2195            #else, swallow
2196
2197#Let's try and shutdown automatically on application exit...
2198import atexit
2199atexit.register(shutdown)
2200
2201# Null handler
2202
2203class NullHandler(Handler):
2204    """
2205    This handler does nothing. It's intended to be used to avoid the
2206    "No handlers could be found for logger XXX" one-off warning. This is
2207    important for library code, which may contain code to log events. If a user
2208    of the library does not configure logging, the one-off warning might be
2209    produced; to avoid this, the library developer simply needs to instantiate
2210    a NullHandler and add it to the top-level logger of the library module or
2211    package.
2212    """
2213    def handle(self, record):
2214        """Stub."""
2215
2216    def emit(self, record):
2217        """Stub."""
2218
2219    def createLock(self):
2220        self.lock = None
2221
2222    def _at_fork_reinit(self):
2223        pass
2224
2225# Warnings integration
2226
2227_warnings_showwarning = None
2228
2229def _showwarning(message, category, filename, lineno, file=None, line=None):
2230    """
2231    Implementation of showwarnings which redirects to logging, which will first
2232    check to see if the file parameter is None. If a file is specified, it will
2233    delegate to the original warnings implementation of showwarning. Otherwise,
2234    it will call warnings.formatwarning and will log the resulting string to a
2235    warnings logger named "py.warnings" with level logging.WARNING.
2236    """
2237    if file is not None:
2238        if _warnings_showwarning is not None:
2239            _warnings_showwarning(message, category, filename, lineno, file, line)
2240    else:
2241        s = warnings.formatwarning(message, category, filename, lineno, line)
2242        logger = getLogger("py.warnings")
2243        if not logger.handlers:
2244            logger.addHandler(NullHandler())
2245        logger.warning("%s", s)
2246
2247def captureWarnings(capture):
2248    """
2249    If capture is true, redirect all warnings to the logging package.
2250    If capture is False, ensure that warnings are not redirected to logging
2251    but to their original destinations.
2252    """
2253    global _warnings_showwarning
2254    if capture:
2255        if _warnings_showwarning is None:
2256            _warnings_showwarning = warnings.showwarning
2257            warnings.showwarning = _showwarning
2258    else:
2259        if _warnings_showwarning is not None:
2260            warnings.showwarning = _warnings_showwarning
2261            _warnings_showwarning = None
2262