ยปCore Development>Code coverage>Lib/logging/__init__.py

Python code coverage for Lib/logging/__init__.py

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