Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / tools / src / nas,5.n2.os.2 / lib / python / lib / python2.4 / logging / __init__.py
CommitLineData
86530b38
AT
1# Copyright 2001-2005 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, and influenced by Apache's log4j system.
20
21Should work under Python versions >= 1.5.2, except that source line
22information is not available unless 'sys._getframe()' is.
23
24Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved.
25
26To use, simply 'import logging' and log away!
27"""
28
29import sys, os, types, time, string, cStringIO, traceback
30
31try:
32 import codecs
33except ImportError:
34 codecs = None
35
36try:
37 import thread
38 import threading
39except ImportError:
40 thread = None
41
42__author__ = "Vinay Sajip <vinay_sajip@red-dove.com>"
43__status__ = "beta"
44__version__ = "0.4.9.6"
45__date__ = "27 March 2005"
46
47#---------------------------------------------------------------------------
48# Miscellaneous module data
49#---------------------------------------------------------------------------
50
51#
52# _srcfile is used when walking the stack to check when we've got the first
53# caller stack frame.
54#
55if hasattr(sys, 'frozen'): #support for py2exe
56 _srcfile = "logging%s__init__%s" % (os.sep, __file__[-4:])
57elif string.lower(__file__[-4:]) in ['.pyc', '.pyo']:
58 _srcfile = __file__[:-4] + '.py'
59else:
60 _srcfile = __file__
61_srcfile = os.path.normcase(_srcfile)
62
63# next bit filched from 1.5.2's inspect.py
64def currentframe():
65 """Return the frame object for the caller's stack frame."""
66 try:
67 raise 'catch me'
68 except:
69 return sys.exc_traceback.tb_frame.f_back
70
71if hasattr(sys, '_getframe'): currentframe = sys._getframe
72# done filching
73
74# _srcfile is only used in conjunction with sys._getframe().
75# To provide compatibility with older versions of Python, set _srcfile
76# to None if _getframe() is not available; this value will prevent
77# findCaller() from being called.
78#if not hasattr(sys, "_getframe"):
79# _srcfile = None
80
81#
82#_startTime is used as the base when calculating the relative time of events
83#
84_startTime = time.time()
85
86#
87#raiseExceptions is used to see if exceptions during handling should be
88#propagated
89#
90raiseExceptions = 1
91
92#---------------------------------------------------------------------------
93# Level related stuff
94#---------------------------------------------------------------------------
95#
96# Default levels and level names, these can be replaced with any positive set
97# of values having corresponding names. There is a pseudo-level, NOTSET, which
98# is only really there as a lower limit for user-defined levels. Handlers and
99# loggers are initialized with NOTSET so that they will log all messages, even
100# at user-defined levels.
101#
102
103CRITICAL = 50
104FATAL = CRITICAL
105ERROR = 40
106WARNING = 30
107WARN = WARNING
108INFO = 20
109DEBUG = 10
110NOTSET = 0
111
112_levelNames = {
113 CRITICAL : 'CRITICAL',
114 ERROR : 'ERROR',
115 WARNING : 'WARNING',
116 INFO : 'INFO',
117 DEBUG : 'DEBUG',
118 NOTSET : 'NOTSET',
119 'CRITICAL' : CRITICAL,
120 'ERROR' : ERROR,
121 'WARN' : WARNING,
122 'WARNING' : WARNING,
123 'INFO' : INFO,
124 'DEBUG' : DEBUG,
125 'NOTSET' : NOTSET,
126}
127
128def getLevelName(level):
129 """
130 Return the textual representation of logging level 'level'.
131
132 If the level is one of the predefined levels (CRITICAL, ERROR, WARNING,
133 INFO, DEBUG) then you get the corresponding string. If you have
134 associated levels with names using addLevelName then the name you have
135 associated with 'level' is returned.
136
137 If a numeric value corresponding to one of the defined levels is passed
138 in, the corresponding string representation is returned.
139
140 Otherwise, the string "Level %s" % level is returned.
141 """
142 return _levelNames.get(level, ("Level %s" % level))
143
144def addLevelName(level, levelName):
145 """
146 Associate 'levelName' with 'level'.
147
148 This is used when converting levels to text during message formatting.
149 """
150 _acquireLock()
151 try: #unlikely to cause an exception, but you never know...
152 _levelNames[level] = levelName
153 _levelNames[levelName] = level
154 finally:
155 _releaseLock()
156
157#---------------------------------------------------------------------------
158# Thread-related stuff
159#---------------------------------------------------------------------------
160
161#
162#_lock is used to serialize access to shared data structures in this module.
163#This needs to be an RLock because fileConfig() creates Handlers and so
164#might arbitrary user threads. Since Handler.__init__() updates the shared
165#dictionary _handlers, it needs to acquire the lock. But if configuring,
166#the lock would already have been acquired - so we need an RLock.
167#The same argument applies to Loggers and Manager.loggerDict.
168#
169_lock = None
170
171def _acquireLock():
172 """
173 Acquire the module-level lock for serializing access to shared data.
174
175 This should be released with _releaseLock().
176 """
177 global _lock
178 if (not _lock) and thread:
179 _lock = threading.RLock()
180 if _lock:
181 _lock.acquire()
182
183def _releaseLock():
184 """
185 Release the module-level lock acquired by calling _acquireLock().
186 """
187 if _lock:
188 _lock.release()
189
190#---------------------------------------------------------------------------
191# The logging record
192#---------------------------------------------------------------------------
193
194class LogRecord:
195 """
196 A LogRecord instance represents an event being logged.
197
198 LogRecord instances are created every time something is logged. They
199 contain all the information pertinent to the event being logged. The
200 main information passed in is in msg and args, which are combined
201 using str(msg) % args to create the message field of the record. The
202 record also includes information such as when the record was created,
203 the source line where the logging call was made, and any exception
204 information to be logged.
205 """
206 def __init__(self, name, level, pathname, lineno, msg, args, exc_info):
207 """
208 Initialize a logging record with interesting information.
209 """
210 ct = time.time()
211 self.name = name
212 self.msg = msg
213 #
214 # The following statement allows passing of a dictionary as a sole
215 # argument, so that you can do something like
216 # logging.debug("a %(a)d b %(b)s", {'a':1, 'b':2})
217 # Suggested by Stefan Behnel.
218 # Note that without the test for args[0], we get a problem because
219 # during formatting, we test to see if the arg is present using
220 # 'if self.args:'. If the event being logged is e.g. 'Value is %d'
221 # and if the passed arg fails 'if self.args:' then no formatting
222 # is done. For example, logger.warn('Value is %d', 0) would log
223 # 'Value is %d' instead of 'Value is 0'.
224 # For the use case of passing a dictionary, this should not be a
225 # problem.
226 if args and (len(args) == 1) and args[0] and (type(args[0]) == types.DictType):
227 args = args[0]
228 self.args = args
229 self.levelname = getLevelName(level)
230 self.levelno = level
231 self.pathname = pathname
232 try:
233 self.filename = os.path.basename(pathname)
234 self.module = os.path.splitext(self.filename)[0]
235 except:
236 self.filename = pathname
237 self.module = "Unknown module"
238 self.exc_info = exc_info
239 self.exc_text = None # used to cache the traceback text
240 self.lineno = lineno
241 self.created = ct
242 self.msecs = (ct - long(ct)) * 1000
243 self.relativeCreated = (self.created - _startTime) * 1000
244 if thread:
245 self.thread = thread.get_ident()
246 self.threadName = threading.currentThread().getName()
247 else:
248 self.thread = None
249 self.threadName = None
250 if hasattr(os, 'getpid'):
251 self.process = os.getpid()
252 else:
253 self.process = None
254
255 def __str__(self):
256 return '<LogRecord: %s, %s, %s, %s, "%s">'%(self.name, self.levelno,
257 self.pathname, self.lineno, self.msg)
258
259 def getMessage(self):
260 """
261 Return the message for this LogRecord.
262
263 Return the message for this LogRecord after merging any user-supplied
264 arguments with the message.
265 """
266 if not hasattr(types, "UnicodeType"): #if no unicode support...
267 msg = str(self.msg)
268 else:
269 try:
270 msg = str(self.msg)
271 except UnicodeError:
272 msg = self.msg #Defer encoding till later
273 if self.args:
274 msg = msg % self.args
275 return msg
276
277def makeLogRecord(dict):
278 """
279 Make a LogRecord whose attributes are defined by the specified dictionary,
280 This function is useful for converting a logging event received over
281 a socket connection (which is sent as a dictionary) into a LogRecord
282 instance.
283 """
284 rv = LogRecord(None, None, "", 0, "", (), None)
285 rv.__dict__.update(dict)
286 return rv
287
288#---------------------------------------------------------------------------
289# Formatter classes and functions
290#---------------------------------------------------------------------------
291
292class Formatter:
293 """
294 Formatter instances are used to convert a LogRecord to text.
295
296 Formatters need to know how a LogRecord is constructed. They are
297 responsible for converting a LogRecord to (usually) a string which can
298 be interpreted by either a human or an external system. The base Formatter
299 allows a formatting string to be specified. If none is supplied, the
300 default value of "%s(message)\\n" is used.
301
302 The Formatter can be initialized with a format string which makes use of
303 knowledge of the LogRecord attributes - e.g. the default value mentioned
304 above makes use of the fact that the user's message and arguments are pre-
305 formatted into a LogRecord's message attribute. Currently, the useful
306 attributes in a LogRecord are described by:
307
308 %(name)s Name of the logger (logging channel)
309 %(levelno)s Numeric logging level for the message (DEBUG, INFO,
310 WARNING, ERROR, CRITICAL)
311 %(levelname)s Text logging level for the message ("DEBUG", "INFO",
312 "WARNING", "ERROR", "CRITICAL")
313 %(pathname)s Full pathname of the source file where the logging
314 call was issued (if available)
315 %(filename)s Filename portion of pathname
316 %(module)s Module (name portion of filename)
317 %(lineno)d Source line number where the logging call was issued
318 (if available)
319 %(created)f Time when the LogRecord was created (time.time()
320 return value)
321 %(asctime)s Textual time when the LogRecord was created
322 %(msecs)d Millisecond portion of the creation time
323 %(relativeCreated)d Time in milliseconds when the LogRecord was created,
324 relative to the time the logging module was loaded
325 (typically at application startup time)
326 %(thread)d Thread ID (if available)
327 %(threadName)s Thread name (if available)
328 %(process)d Process ID (if available)
329 %(message)s The result of record.getMessage(), computed just as
330 the record is emitted
331 """
332
333 converter = time.localtime
334
335 def __init__(self, fmt=None, datefmt=None):
336 """
337 Initialize the formatter with specified format strings.
338
339 Initialize the formatter either with the specified format string, or a
340 default as described above. Allow for specialized date formatting with
341 the optional datefmt argument (if omitted, you get the ISO8601 format).
342 """
343 if fmt:
344 self._fmt = fmt
345 else:
346 self._fmt = "%(message)s"
347 self.datefmt = datefmt
348
349 def formatTime(self, record, datefmt=None):
350 """
351 Return the creation time of the specified LogRecord as formatted text.
352
353 This method should be called from format() by a formatter which
354 wants to make use of a formatted time. This method can be overridden
355 in formatters to provide for any specific requirement, but the
356 basic behaviour is as follows: if datefmt (a string) is specified,
357 it is used with time.strftime() to format the creation time of the
358 record. Otherwise, the ISO8601 format is used. The resulting
359 string is returned. This function uses a user-configurable function
360 to convert the creation time to a tuple. By default, time.localtime()
361 is used; to change this for a particular formatter instance, set the
362 'converter' attribute to a function with the same signature as
363 time.localtime() or time.gmtime(). To change it for all formatters,
364 for example if you want all logging times to be shown in GMT,
365 set the 'converter' attribute in the Formatter class.
366 """
367 ct = self.converter(record.created)
368 if datefmt:
369 s = time.strftime(datefmt, ct)
370 else:
371 t = time.strftime("%Y-%m-%d %H:%M:%S", ct)
372 s = "%s,%03d" % (t, record.msecs)
373 return s
374
375 def formatException(self, ei):
376 """
377 Format and return the specified exception information as a string.
378
379 This default implementation just uses
380 traceback.print_exception()
381 """
382 sio = cStringIO.StringIO()
383 traceback.print_exception(ei[0], ei[1], ei[2], None, sio)
384 s = sio.getvalue()
385 sio.close()
386 if s[-1] == "\n":
387 s = s[:-1]
388 return s
389
390 def format(self, record):
391 """
392 Format the specified record as text.
393
394 The record's attribute dictionary is used as the operand to a
395 string formatting operation which yields the returned string.
396 Before formatting the dictionary, a couple of preparatory steps
397 are carried out. The message attribute of the record is computed
398 using LogRecord.getMessage(). If the formatting string contains
399 "%(asctime)", formatTime() is called to format the event time.
400 If there is exception information, it is formatted using
401 formatException() and appended to the message.
402 """
403 record.message = record.getMessage()
404 if string.find(self._fmt,"%(asctime)") >= 0:
405 record.asctime = self.formatTime(record, self.datefmt)
406 s = self._fmt % record.__dict__
407 if record.exc_info:
408 # Cache the traceback text to avoid converting it multiple times
409 # (it's constant anyway)
410 if not record.exc_text:
411 record.exc_text = self.formatException(record.exc_info)
412 if record.exc_text:
413 if s[-1] != "\n":
414 s = s + "\n"
415 s = s + record.exc_text
416 return s
417
418#
419# The default formatter to use when no other is specified
420#
421_defaultFormatter = Formatter()
422
423class BufferingFormatter:
424 """
425 A formatter suitable for formatting a number of records.
426 """
427 def __init__(self, linefmt=None):
428 """
429 Optionally specify a formatter which will be used to format each
430 individual record.
431 """
432 if linefmt:
433 self.linefmt = linefmt
434 else:
435 self.linefmt = _defaultFormatter
436
437 def formatHeader(self, records):
438 """
439 Return the header string for the specified records.
440 """
441 return ""
442
443 def formatFooter(self, records):
444 """
445 Return the footer string for the specified records.
446 """
447 return ""
448
449 def format(self, records):
450 """
451 Format the specified records and return the result as a string.
452 """
453 rv = ""
454 if len(records) > 0:
455 rv = rv + self.formatHeader(records)
456 for record in records:
457 rv = rv + self.linefmt.format(record)
458 rv = rv + self.formatFooter(records)
459 return rv
460
461#---------------------------------------------------------------------------
462# Filter classes and functions
463#---------------------------------------------------------------------------
464
465class Filter:
466 """
467 Filter instances are used to perform arbitrary filtering of LogRecords.
468
469 Loggers and Handlers can optionally use Filter instances to filter
470 records as desired. The base filter class only allows events which are
471 below a certain point in the logger hierarchy. For example, a filter
472 initialized with "A.B" will allow events logged by loggers "A.B",
473 "A.B.C", "A.B.C.D", "A.B.D" etc. but not "A.BB", "B.A.B" etc. If
474 initialized with the empty string, all events are passed.
475 """
476 def __init__(self, name=''):
477 """
478 Initialize a filter.
479
480 Initialize with the name of the logger which, together with its
481 children, will have its events allowed through the filter. If no
482 name is specified, allow every event.
483 """
484 self.name = name
485 self.nlen = len(name)
486
487 def filter(self, record):
488 """
489 Determine if the specified record is to be logged.
490
491 Is the specified record to be logged? Returns 0 for no, nonzero for
492 yes. If deemed appropriate, the record may be modified in-place.
493 """
494 if self.nlen == 0:
495 return 1
496 elif self.name == record.name:
497 return 1
498 elif string.find(record.name, self.name, 0, self.nlen) != 0:
499 return 0
500 return (record.name[self.nlen] == ".")
501
502class Filterer:
503 """
504 A base class for loggers and handlers which allows them to share
505 common code.
506 """
507 def __init__(self):
508 """
509 Initialize the list of filters to be an empty list.
510 """
511 self.filters = []
512
513 def addFilter(self, filter):
514 """
515 Add the specified filter to this handler.
516 """
517 if not (filter in self.filters):
518 self.filters.append(filter)
519
520 def removeFilter(self, filter):
521 """
522 Remove the specified filter from this handler.
523 """
524 if filter in self.filters:
525 self.filters.remove(filter)
526
527 def filter(self, record):
528 """
529 Determine if a record is loggable by consulting all the filters.
530
531 The default is to allow the record to be logged; any filter can veto
532 this and the record is then dropped. Returns a zero value if a record
533 is to be dropped, else non-zero.
534 """
535 rv = 1
536 for f in self.filters:
537 if not f.filter(record):
538 rv = 0
539 break
540 return rv
541
542#---------------------------------------------------------------------------
543# Handler classes and functions
544#---------------------------------------------------------------------------
545
546_handlers = {} #repository of handlers (for flushing when shutdown called)
547_handlerList = [] # added to allow handlers to be removed in reverse of order initialized
548
549class Handler(Filterer):
550 """
551 Handler instances dispatch logging events to specific destinations.
552
553 The base handler class. Acts as a placeholder which defines the Handler
554 interface. Handlers can optionally use Formatter instances to format
555 records as desired. By default, no formatter is specified; in this case,
556 the 'raw' message as determined by record.message is logged.
557 """
558 def __init__(self, level=NOTSET):
559 """
560 Initializes the instance - basically setting the formatter to None
561 and the filter list to empty.
562 """
563 Filterer.__init__(self)
564 self.level = level
565 self.formatter = None
566 #get the module data lock, as we're updating a shared structure.
567 _acquireLock()
568 try: #unlikely to raise an exception, but you never know...
569 _handlers[self] = 1
570 _handlerList.insert(0, self)
571 finally:
572 _releaseLock()
573 self.createLock()
574
575 def createLock(self):
576 """
577 Acquire a thread lock for serializing access to the underlying I/O.
578 """
579 if thread:
580 self.lock = threading.RLock()
581 else:
582 self.lock = None
583
584 def acquire(self):
585 """
586 Acquire the I/O thread lock.
587 """
588 if self.lock:
589 self.lock.acquire()
590
591 def release(self):
592 """
593 Release the I/O thread lock.
594 """
595 if self.lock:
596 self.lock.release()
597
598 def setLevel(self, level):
599 """
600 Set the logging level of this handler.
601 """
602 self.level = level
603
604 def format(self, record):
605 """
606 Format the specified record.
607
608 If a formatter is set, use it. Otherwise, use the default formatter
609 for the module.
610 """
611 if self.formatter:
612 fmt = self.formatter
613 else:
614 fmt = _defaultFormatter
615 return fmt.format(record)
616
617 def emit(self, record):
618 """
619 Do whatever it takes to actually log the specified logging record.
620
621 This version is intended to be implemented by subclasses and so
622 raises a NotImplementedError.
623 """
624 raise NotImplementedError, 'emit must be implemented '\
625 'by Handler subclasses'
626
627 def handle(self, record):
628 """
629 Conditionally emit the specified logging record.
630
631 Emission depends on filters which may have been added to the handler.
632 Wrap the actual emission of the record with acquisition/release of
633 the I/O thread lock. Returns whether the filter passed the record for
634 emission.
635 """
636 rv = self.filter(record)
637 if rv:
638 self.acquire()
639 try:
640 self.emit(record)
641 finally:
642 self.release()
643 return rv
644
645 def setFormatter(self, fmt):
646 """
647 Set the formatter for this handler.
648 """
649 self.formatter = fmt
650
651 def flush(self):
652 """
653 Ensure all logging output has been flushed.
654
655 This version does nothing and is intended to be implemented by
656 subclasses.
657 """
658 pass
659
660 def close(self):
661 """
662 Tidy up any resources used by the handler.
663
664 This version does removes the handler from an internal list
665 of handlers which is closed when shutdown() is called. Subclasses
666 should ensure that this gets called from overridden close()
667 methods.
668 """
669 #get the module data lock, as we're updating a shared structure.
670 _acquireLock()
671 try: #unlikely to raise an exception, but you never know...
672 del _handlers[self]
673 _handlerList.remove(self)
674 finally:
675 _releaseLock()
676
677 def handleError(self, record):
678 """
679 Handle errors which occur during an emit() call.
680
681 This method should be called from handlers when an exception is
682 encountered during an emit() call. If raiseExceptions is false,
683 exceptions get silently ignored. This is what is mostly wanted
684 for a logging system - most users will not care about errors in
685 the logging system, they are more interested in application errors.
686 You could, however, replace this with a custom handler if you wish.
687 The record which was being processed is passed in to this method.
688 """
689 if raiseExceptions:
690 ei = sys.exc_info()
691 traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
692 del ei
693
694class StreamHandler(Handler):
695 """
696 A handler class which writes logging records, appropriately formatted,
697 to a stream. Note that this class does not close the stream, as
698 sys.stdout or sys.stderr may be used.
699 """
700 def __init__(self, strm=None):
701 """
702 Initialize the handler.
703
704 If strm is not specified, sys.stderr is used.
705 """
706 Handler.__init__(self)
707 if not strm:
708 strm = sys.stderr
709 self.stream = strm
710 self.formatter = None
711
712 def flush(self):
713 """
714 Flushes the stream.
715 """
716 self.stream.flush()
717
718 def emit(self, record):
719 """
720 Emit a record.
721
722 If a formatter is specified, it is used to format the record.
723 The record is then written to the stream with a trailing newline
724 [N.B. this may be removed depending on feedback]. If exception
725 information is present, it is formatted using
726 traceback.print_exception and appended to the stream.
727 """
728 try:
729 msg = self.format(record)
730 fs = "%s\n"
731 if not hasattr(types, "UnicodeType"): #if no unicode support...
732 self.stream.write(fs % msg)
733 else:
734 try:
735 self.stream.write(fs % msg)
736 except UnicodeError:
737 self.stream.write(fs % msg.encode("UTF-8"))
738 self.flush()
739 except:
740 self.handleError(record)
741
742class FileHandler(StreamHandler):
743 """
744 A handler class which writes formatted logging records to disk files.
745 """
746 def __init__(self, filename, mode='a', encoding=None):
747 """
748 Open the specified file and use it as the stream for logging.
749 """
750 if codecs is None:
751 encoding = None
752 if encoding is None:
753 stream = open(filename, mode)
754 else:
755 stream = codecs.open(filename, mode, encoding)
756 StreamHandler.__init__(self, stream)
757 #keep the absolute path, otherwise derived classes which use this
758 #may come a cropper when the current directory changes
759 self.baseFilename = os.path.abspath(filename)
760 self.mode = mode
761
762 def close(self):
763 """
764 Closes the stream.
765 """
766 self.flush()
767 self.stream.close()
768 StreamHandler.close(self)
769
770#---------------------------------------------------------------------------
771# Manager classes and functions
772#---------------------------------------------------------------------------
773
774class PlaceHolder:
775 """
776 PlaceHolder instances are used in the Manager logger hierarchy to take
777 the place of nodes for which no loggers have been defined. This class is
778 intended for internal use only and not as part of the public API.
779 """
780 def __init__(self, alogger):
781 """
782 Initialize with the specified logger being a child of this placeholder.
783 """
784 self.loggers = [alogger]
785
786 def append(self, alogger):
787 """
788 Add the specified logger as a child of this placeholder.
789 """
790 if alogger not in self.loggers:
791 self.loggers.append(alogger)
792
793#
794# Determine which class to use when instantiating loggers.
795#
796_loggerClass = None
797
798def setLoggerClass(klass):
799 """
800 Set the class to be used when instantiating a logger. The class should
801 define __init__() such that only a name argument is required, and the
802 __init__() should call Logger.__init__()
803 """
804 if klass != Logger:
805 if not issubclass(klass, Logger):
806 raise TypeError, "logger not derived from logging.Logger: " + \
807 klass.__name__
808 global _loggerClass
809 _loggerClass = klass
810
811def getLoggerClass():
812 """
813 Return the class to be used when instantiating a logger.
814 """
815
816 return _loggerClass
817
818class Manager:
819 """
820 There is [under normal circumstances] just one Manager instance, which
821 holds the hierarchy of loggers.
822 """
823 def __init__(self, rootnode):
824 """
825 Initialize the manager with the root node of the logger hierarchy.
826 """
827 self.root = rootnode
828 self.disable = 0
829 self.emittedNoHandlerWarning = 0
830 self.loggerDict = {}
831
832 def getLogger(self, name):
833 """
834 Get a logger with the specified name (channel name), creating it
835 if it doesn't yet exist. This name is a dot-separated hierarchical
836 name, such as "a", "a.b", "a.b.c" or similar.
837
838 If a PlaceHolder existed for the specified name [i.e. the logger
839 didn't exist but a child of it did], replace it with the created
840 logger and fix up the parent/child references which pointed to the
841 placeholder to now point to the logger.
842 """
843 rv = None
844 _acquireLock()
845 try:
846 if self.loggerDict.has_key(name):
847 rv = self.loggerDict[name]
848 if isinstance(rv, PlaceHolder):
849 ph = rv
850 rv = _loggerClass(name)
851 rv.manager = self
852 self.loggerDict[name] = rv
853 self._fixupChildren(ph, rv)
854 self._fixupParents(rv)
855 else:
856 rv = _loggerClass(name)
857 rv.manager = self
858 self.loggerDict[name] = rv
859 self._fixupParents(rv)
860 finally:
861 _releaseLock()
862 return rv
863
864 def _fixupParents(self, alogger):
865 """
866 Ensure that there are either loggers or placeholders all the way
867 from the specified logger to the root of the logger hierarchy.
868 """
869 name = alogger.name
870 i = string.rfind(name, ".")
871 rv = None
872 while (i > 0) and not rv:
873 substr = name[:i]
874 if not self.loggerDict.has_key(substr):
875 self.loggerDict[substr] = PlaceHolder(alogger)
876 else:
877 obj = self.loggerDict[substr]
878 if isinstance(obj, Logger):
879 rv = obj
880 else:
881 assert isinstance(obj, PlaceHolder)
882 obj.append(alogger)
883 i = string.rfind(name, ".", 0, i - 1)
884 if not rv:
885 rv = self.root
886 alogger.parent = rv
887
888 def _fixupChildren(self, ph, alogger):
889 """
890 Ensure that children of the placeholder ph are connected to the
891 specified logger.
892 """
893 for c in ph.loggers:
894 if string.find(c.parent.name, alogger.name) <> 0:
895 alogger.parent = c.parent
896 c.parent = alogger
897
898#---------------------------------------------------------------------------
899# Logger classes and functions
900#---------------------------------------------------------------------------
901
902class Logger(Filterer):
903 """
904 Instances of the Logger class represent a single logging channel. A
905 "logging channel" indicates an area of an application. Exactly how an
906 "area" is defined is up to the application developer. Since an
907 application can have any number of areas, logging channels are identified
908 by a unique string. Application areas can be nested (e.g. an area
909 of "input processing" might include sub-areas "read CSV files", "read
910 XLS files" and "read Gnumeric files"). To cater for this natural nesting,
911 channel names are organized into a namespace hierarchy where levels are
912 separated by periods, much like the Java or Python package namespace. So
913 in the instance given above, channel names might be "input" for the upper
914 level, and "input.csv", "input.xls" and "input.gnu" for the sub-levels.
915 There is no arbitrary limit to the depth of nesting.
916 """
917 def __init__(self, name, level=NOTSET):
918 """
919 Initialize the logger with a name and an optional level.
920 """
921 Filterer.__init__(self)
922 self.name = name
923 self.level = level
924 self.parent = None
925 self.propagate = 1
926 self.handlers = []
927 self.disabled = 0
928
929 def setLevel(self, level):
930 """
931 Set the logging level of this logger.
932 """
933 self.level = level
934
935 def debug(self, msg, *args, **kwargs):
936 """
937 Log 'msg % args' with severity 'DEBUG'.
938
939 To pass exception information, use the keyword argument exc_info with
940 a true value, e.g.
941
942 logger.debug("Houston, we have a %s", "thorny problem", exc_info=1)
943 """
944 if self.manager.disable >= DEBUG:
945 return
946 if DEBUG >= self.getEffectiveLevel():
947 apply(self._log, (DEBUG, msg, args), kwargs)
948
949 def info(self, msg, *args, **kwargs):
950 """
951 Log 'msg % args' with severity 'INFO'.
952
953 To pass exception information, use the keyword argument exc_info with
954 a true value, e.g.
955
956 logger.info("Houston, we have a %s", "interesting problem", exc_info=1)
957 """
958 if self.manager.disable >= INFO:
959 return
960 if INFO >= self.getEffectiveLevel():
961 apply(self._log, (INFO, msg, args), kwargs)
962
963 def warning(self, msg, *args, **kwargs):
964 """
965 Log 'msg % args' with severity 'WARNING'.
966
967 To pass exception information, use the keyword argument exc_info with
968 a true value, e.g.
969
970 logger.warning("Houston, we have a %s", "bit of a problem", exc_info=1)
971 """
972 if self.manager.disable >= WARNING:
973 return
974 if self.isEnabledFor(WARNING):
975 apply(self._log, (WARNING, msg, args), kwargs)
976
977 warn = warning
978
979 def error(self, msg, *args, **kwargs):
980 """
981 Log 'msg % args' with severity 'ERROR'.
982
983 To pass exception information, use the keyword argument exc_info with
984 a true value, e.g.
985
986 logger.error("Houston, we have a %s", "major problem", exc_info=1)
987 """
988 if self.manager.disable >= ERROR:
989 return
990 if self.isEnabledFor(ERROR):
991 apply(self._log, (ERROR, msg, args), kwargs)
992
993 def exception(self, msg, *args):
994 """
995 Convenience method for logging an ERROR with exception information.
996 """
997 apply(self.error, (msg,) + args, {'exc_info': 1})
998
999 def critical(self, msg, *args, **kwargs):
1000 """
1001 Log 'msg % args' with severity 'CRITICAL'.
1002
1003 To pass exception information, use the keyword argument exc_info with
1004 a true value, e.g.
1005
1006 logger.critical("Houston, we have a %s", "major disaster", exc_info=1)
1007 """
1008 if self.manager.disable >= CRITICAL:
1009 return
1010 if CRITICAL >= self.getEffectiveLevel():
1011 apply(self._log, (CRITICAL, msg, args), kwargs)
1012
1013 fatal = critical
1014
1015 def log(self, level, msg, *args, **kwargs):
1016 """
1017 Log 'msg % args' with the integer severity 'level'.
1018
1019 To pass exception information, use the keyword argument exc_info with
1020 a true value, e.g.
1021
1022 logger.log(level, "We have a %s", "mysterious problem", exc_info=1)
1023 """
1024 if type(level) != types.IntType:
1025 if raiseExceptions:
1026 raise TypeError, "level must be an integer"
1027 else:
1028 return
1029 if self.manager.disable >= level:
1030 return
1031 if self.isEnabledFor(level):
1032 apply(self._log, (level, msg, args), kwargs)
1033
1034 def findCaller(self):
1035 """
1036 Find the stack frame of the caller so that we can note the source
1037 file name, line number and function name.
1038 """
1039 f = currentframe().f_back
1040 while 1:
1041 co = f.f_code
1042 filename = os.path.normcase(co.co_filename)
1043 if filename == _srcfile:
1044 f = f.f_back
1045 continue
1046 return filename, f.f_lineno, co.co_name
1047
1048 def makeRecord(self, name, level, fn, lno, msg, args, exc_info):
1049 """
1050 A factory method which can be overridden in subclasses to create
1051 specialized LogRecords.
1052 """
1053 return LogRecord(name, level, fn, lno, msg, args, exc_info)
1054
1055 def _log(self, level, msg, args, exc_info=None):
1056 """
1057 Low-level logging routine which creates a LogRecord and then calls
1058 all the handlers of this logger to handle the record.
1059 """
1060 if _srcfile:
1061 fn, lno, func = self.findCaller()
1062 else:
1063 fn, lno, func = "(unknown file)", 0, "(unknown function)"
1064 if exc_info:
1065 if type(exc_info) != types.TupleType:
1066 exc_info = sys.exc_info()
1067 record = self.makeRecord(self.name, level, fn, lno, msg, args, exc_info)
1068 self.handle(record)
1069
1070 def handle(self, record):
1071 """
1072 Call the handlers for the specified record.
1073
1074 This method is used for unpickled records received from a socket, as
1075 well as those created locally. Logger-level filtering is applied.
1076 """
1077 if (not self.disabled) and self.filter(record):
1078 self.callHandlers(record)
1079
1080 def addHandler(self, hdlr):
1081 """
1082 Add the specified handler to this logger.
1083 """
1084 if not (hdlr in self.handlers):
1085 self.handlers.append(hdlr)
1086
1087 def removeHandler(self, hdlr):
1088 """
1089 Remove the specified handler from this logger.
1090 """
1091 if hdlr in self.handlers:
1092 #hdlr.close()
1093 hdlr.acquire()
1094 try:
1095 self.handlers.remove(hdlr)
1096 finally:
1097 hdlr.release()
1098
1099 def callHandlers(self, record):
1100 """
1101 Pass a record to all relevant handlers.
1102
1103 Loop through all handlers for this logger and its parents in the
1104 logger hierarchy. If no handler was found, output a one-off error
1105 message to sys.stderr. Stop searching up the hierarchy whenever a
1106 logger with the "propagate" attribute set to zero is found - that
1107 will be the last logger whose handlers are called.
1108 """
1109 c = self
1110 found = 0
1111 while c:
1112 for hdlr in c.handlers:
1113 found = found + 1
1114 if record.levelno >= hdlr.level:
1115 hdlr.handle(record)
1116 if not c.propagate:
1117 c = None #break out
1118 else:
1119 c = c.parent
1120 if (found == 0) and not self.manager.emittedNoHandlerWarning:
1121 sys.stderr.write("No handlers could be found for logger"
1122 " \"%s\"\n" % self.name)
1123 self.manager.emittedNoHandlerWarning = 1
1124
1125 def getEffectiveLevel(self):
1126 """
1127 Get the effective level for this logger.
1128
1129 Loop through this logger and its parents in the logger hierarchy,
1130 looking for a non-zero logging level. Return the first one found.
1131 """
1132 logger = self
1133 while logger:
1134 if logger.level:
1135 return logger.level
1136 logger = logger.parent
1137 return NOTSET
1138
1139 def isEnabledFor(self, level):
1140 """
1141 Is this logger enabled for level 'level'?
1142 """
1143 if self.manager.disable >= level:
1144 return 0
1145 return level >= self.getEffectiveLevel()
1146
1147class RootLogger(Logger):
1148 """
1149 A root logger is not that different to any other logger, except that
1150 it must have a logging level and there is only one instance of it in
1151 the hierarchy.
1152 """
1153 def __init__(self, level):
1154 """
1155 Initialize the logger with the name "root".
1156 """
1157 Logger.__init__(self, "root", level)
1158
1159_loggerClass = Logger
1160
1161root = RootLogger(WARNING)
1162Logger.root = root
1163Logger.manager = Manager(Logger.root)
1164
1165#---------------------------------------------------------------------------
1166# Configuration classes and functions
1167#---------------------------------------------------------------------------
1168
1169BASIC_FORMAT = "%(levelname)s:%(name)s:%(message)s"
1170
1171def basicConfig(**kwargs):
1172 """
1173 Do basic configuration for the logging system.
1174
1175 This function does nothing if the root logger already has handlers
1176 configured. It is a convenience method intended for use by simple scripts
1177 to do one-shot configuration of the logging package.
1178
1179 The default behaviour is to create a StreamHandler which writes to
1180 sys.stderr, set a formatter using the BASIC_FORMAT format string, and
1181 add the handler to the root logger.
1182
1183 A number of optional keyword arguments may be specified, which can alter
1184 the default behaviour.
1185
1186 filename Specifies that a FileHandler be created, using the specified
1187 filename, rather than a StreamHandler.
1188 filemode Specifies the mode to open the file, if filename is specified
1189 (if filemode is unspecified, it defaults to 'a').
1190 format Use the specified format string for the handler.
1191 datefmt Use the specified date/time format.
1192 level Set the root logger level to the specified level.
1193 stream Use the specified stream to initialize the StreamHandler. Note
1194 that this argument is incompatible with 'filename' - if both
1195 are present, 'stream' is ignored.
1196
1197 Note that you could specify a stream created using open(filename, mode)
1198 rather than passing the filename and mode in. However, it should be
1199 remembered that StreamHandler does not close its stream (since it may be
1200 using sys.stdout or sys.stderr), whereas FileHandler closes its stream
1201 when the handler is closed.
1202 """
1203 if len(root.handlers) == 0:
1204 filename = kwargs.get("filename")
1205 if filename:
1206 mode = kwargs.get("filemode", 'a')
1207 hdlr = FileHandler(filename, mode)
1208 else:
1209 stream = kwargs.get("stream")
1210 hdlr = StreamHandler(stream)
1211 fs = kwargs.get("format", BASIC_FORMAT)
1212 dfs = kwargs.get("datefmt", None)
1213 fmt = Formatter(fs, dfs)
1214 hdlr.setFormatter(fmt)
1215 root.addHandler(hdlr)
1216 level = kwargs.get("level")
1217 if level:
1218 root.setLevel(level)
1219
1220#---------------------------------------------------------------------------
1221# Utility functions at module level.
1222# Basically delegate everything to the root logger.
1223#---------------------------------------------------------------------------
1224
1225def getLogger(name=None):
1226 """
1227 Return a logger with the specified name, creating it if necessary.
1228
1229 If no name is specified, return the root logger.
1230 """
1231 if name:
1232 return Logger.manager.getLogger(name)
1233 else:
1234 return root
1235
1236#def getRootLogger():
1237# """
1238# Return the root logger.
1239#
1240# Note that getLogger('') now does the same thing, so this function is
1241# deprecated and may disappear in the future.
1242# """
1243# return root
1244
1245def critical(msg, *args, **kwargs):
1246 """
1247 Log a message with severity 'CRITICAL' on the root logger.
1248 """
1249 if len(root.handlers) == 0:
1250 basicConfig()
1251 apply(root.critical, (msg,)+args, kwargs)
1252
1253fatal = critical
1254
1255def error(msg, *args, **kwargs):
1256 """
1257 Log a message with severity 'ERROR' on the root logger.
1258 """
1259 if len(root.handlers) == 0:
1260 basicConfig()
1261 apply(root.error, (msg,)+args, kwargs)
1262
1263def exception(msg, *args):
1264 """
1265 Log a message with severity 'ERROR' on the root logger,
1266 with exception information.
1267 """
1268 apply(error, (msg,)+args, {'exc_info': 1})
1269
1270def warning(msg, *args, **kwargs):
1271 """
1272 Log a message with severity 'WARNING' on the root logger.
1273 """
1274 if len(root.handlers) == 0:
1275 basicConfig()
1276 apply(root.warning, (msg,)+args, kwargs)
1277
1278warn = warning
1279
1280def info(msg, *args, **kwargs):
1281 """
1282 Log a message with severity 'INFO' on the root logger.
1283 """
1284 if len(root.handlers) == 0:
1285 basicConfig()
1286 apply(root.info, (msg,)+args, kwargs)
1287
1288def debug(msg, *args, **kwargs):
1289 """
1290 Log a message with severity 'DEBUG' on the root logger.
1291 """
1292 if len(root.handlers) == 0:
1293 basicConfig()
1294 apply(root.debug, (msg,)+args, kwargs)
1295
1296def log(level, msg, *args, **kwargs):
1297 """
1298 Log 'msg % args' with the integer severity 'level' on the root logger.
1299 """
1300 if len(root.handlers) == 0:
1301 basicConfig()
1302 apply(root.log, (level, msg)+args, kwargs)
1303
1304def disable(level):
1305 """
1306 Disable all logging calls less severe than 'level'.
1307 """
1308 root.manager.disable = level
1309
1310def shutdown():
1311 """
1312 Perform any cleanup actions in the logging system (e.g. flushing
1313 buffers).
1314
1315 Should be called at application exit.
1316 """
1317 for h in _handlerList[:]: # was _handlers.keys():
1318 #errors might occur, for example, if files are locked
1319 #we just ignore them
1320 try:
1321 h.flush()
1322 h.close()
1323 except:
1324 pass
1325
1326#Let's try and shutdown automatically on application exit...
1327try:
1328 import atexit
1329 atexit.register(shutdown)
1330except ImportError: # for Python versions < 2.0
1331 def exithook(status, old_exit=sys.exit):
1332 try:
1333 shutdown()
1334 finally:
1335 old_exit(status)
1336
1337 sys.exit = exithook