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