symbian-qemu-0.9.1-12/python-2.6.1/Lib/logging/config.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 # Copyright 2001-2007 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 Configuration functions for the logging package for Python. The core package
       
    19 is based on PEP 282 and comments thereto in comp.lang.python, and influenced
       
    20 by Apache's log4j system.
       
    21 
       
    22 Should work under Python versions >= 1.5.2, except that source line
       
    23 information is not available unless 'sys._getframe()' is.
       
    24 
       
    25 Copyright (C) 2001-2008 Vinay Sajip. All Rights Reserved.
       
    26 
       
    27 To use, simply 'import logging' and log away!
       
    28 """
       
    29 
       
    30 import sys, logging, logging.handlers, string, socket, struct, os, traceback, types
       
    31 
       
    32 try:
       
    33     import thread
       
    34     import threading
       
    35 except ImportError:
       
    36     thread = None
       
    37 
       
    38 from SocketServer import ThreadingTCPServer, StreamRequestHandler
       
    39 
       
    40 
       
    41 DEFAULT_LOGGING_CONFIG_PORT = 9030
       
    42 
       
    43 if sys.platform == "win32":
       
    44     RESET_ERROR = 10054   #WSAECONNRESET
       
    45 else:
       
    46     RESET_ERROR = 104     #ECONNRESET
       
    47 
       
    48 #
       
    49 #   The following code implements a socket listener for on-the-fly
       
    50 #   reconfiguration of logging.
       
    51 #
       
    52 #   _listener holds the server object doing the listening
       
    53 _listener = None
       
    54 
       
    55 def fileConfig(fname, defaults=None, disable_existing_loggers=1):
       
    56     """
       
    57     Read the logging configuration from a ConfigParser-format file.
       
    58 
       
    59     This can be called several times from an application, allowing an end user
       
    60     the ability to select from various pre-canned configurations (if the
       
    61     developer provides a mechanism to present the choices and load the chosen
       
    62     configuration).
       
    63     In versions of ConfigParser which have the readfp method [typically
       
    64     shipped in 2.x versions of Python], you can pass in a file-like object
       
    65     rather than a filename, in which case the file-like object will be read
       
    66     using readfp.
       
    67     """
       
    68     import ConfigParser
       
    69 
       
    70     cp = ConfigParser.ConfigParser(defaults)
       
    71     if hasattr(cp, 'readfp') and hasattr(fname, 'readline'):
       
    72         cp.readfp(fname)
       
    73     else:
       
    74         cp.read(fname)
       
    75 
       
    76     formatters = _create_formatters(cp)
       
    77 
       
    78     # critical section
       
    79     logging._acquireLock()
       
    80     try:
       
    81         logging._handlers.clear()
       
    82         del logging._handlerList[:]
       
    83         # Handlers add themselves to logging._handlers
       
    84         handlers = _install_handlers(cp, formatters)
       
    85         _install_loggers(cp, handlers, disable_existing_loggers)
       
    86     finally:
       
    87         logging._releaseLock()
       
    88 
       
    89 
       
    90 def _resolve(name):
       
    91     """Resolve a dotted name to a global object."""
       
    92     name = string.split(name, '.')
       
    93     used = name.pop(0)
       
    94     found = __import__(used)
       
    95     for n in name:
       
    96         used = used + '.' + n
       
    97         try:
       
    98             found = getattr(found, n)
       
    99         except AttributeError:
       
   100             __import__(used)
       
   101             found = getattr(found, n)
       
   102     return found
       
   103 
       
   104 def _strip_spaces(alist):
       
   105     return map(lambda x: string.strip(x), alist)
       
   106 
       
   107 def _create_formatters(cp):
       
   108     """Create and return formatters"""
       
   109     flist = cp.get("formatters", "keys")
       
   110     if not len(flist):
       
   111         return {}
       
   112     flist = string.split(flist, ",")
       
   113     flist = _strip_spaces(flist)
       
   114     formatters = {}
       
   115     for form in flist:
       
   116         sectname = "formatter_%s" % form
       
   117         opts = cp.options(sectname)
       
   118         if "format" in opts:
       
   119             fs = cp.get(sectname, "format", 1)
       
   120         else:
       
   121             fs = None
       
   122         if "datefmt" in opts:
       
   123             dfs = cp.get(sectname, "datefmt", 1)
       
   124         else:
       
   125             dfs = None
       
   126         c = logging.Formatter
       
   127         if "class" in opts:
       
   128             class_name = cp.get(sectname, "class")
       
   129             if class_name:
       
   130                 c = _resolve(class_name)
       
   131         f = c(fs, dfs)
       
   132         formatters[form] = f
       
   133     return formatters
       
   134 
       
   135 
       
   136 def _install_handlers(cp, formatters):
       
   137     """Install and return handlers"""
       
   138     hlist = cp.get("handlers", "keys")
       
   139     if not len(hlist):
       
   140         return {}
       
   141     hlist = string.split(hlist, ",")
       
   142     hlist = _strip_spaces(hlist)
       
   143     handlers = {}
       
   144     fixups = [] #for inter-handler references
       
   145     for hand in hlist:
       
   146         sectname = "handler_%s" % hand
       
   147         klass = cp.get(sectname, "class")
       
   148         opts = cp.options(sectname)
       
   149         if "formatter" in opts:
       
   150             fmt = cp.get(sectname, "formatter")
       
   151         else:
       
   152             fmt = ""
       
   153         try:
       
   154             klass = eval(klass, vars(logging))
       
   155         except (AttributeError, NameError):
       
   156             klass = _resolve(klass)
       
   157         args = cp.get(sectname, "args")
       
   158         args = eval(args, vars(logging))
       
   159         h = klass(*args)
       
   160         if "level" in opts:
       
   161             level = cp.get(sectname, "level")
       
   162             h.setLevel(logging._levelNames[level])
       
   163         if len(fmt):
       
   164             h.setFormatter(formatters[fmt])
       
   165         if issubclass(klass, logging.handlers.MemoryHandler):
       
   166             if "target" in opts:
       
   167                 target = cp.get(sectname,"target")
       
   168             else:
       
   169                 target = ""
       
   170             if len(target): #the target handler may not be loaded yet, so keep for later...
       
   171                 fixups.append((h, target))
       
   172         handlers[hand] = h
       
   173     #now all handlers are loaded, fixup inter-handler references...
       
   174     for h, t in fixups:
       
   175         h.setTarget(handlers[t])
       
   176     return handlers
       
   177 
       
   178 
       
   179 def _install_loggers(cp, handlers, disable_existing_loggers):
       
   180     """Create and install loggers"""
       
   181 
       
   182     # configure the root first
       
   183     llist = cp.get("loggers", "keys")
       
   184     llist = string.split(llist, ",")
       
   185     llist = map(lambda x: string.strip(x), llist)
       
   186     llist.remove("root")
       
   187     sectname = "logger_root"
       
   188     root = logging.root
       
   189     log = root
       
   190     opts = cp.options(sectname)
       
   191     if "level" in opts:
       
   192         level = cp.get(sectname, "level")
       
   193         log.setLevel(logging._levelNames[level])
       
   194     for h in root.handlers[:]:
       
   195         root.removeHandler(h)
       
   196     hlist = cp.get(sectname, "handlers")
       
   197     if len(hlist):
       
   198         hlist = string.split(hlist, ",")
       
   199         hlist = _strip_spaces(hlist)
       
   200         for hand in hlist:
       
   201             log.addHandler(handlers[hand])
       
   202 
       
   203     #and now the others...
       
   204     #we don't want to lose the existing loggers,
       
   205     #since other threads may have pointers to them.
       
   206     #existing is set to contain all existing loggers,
       
   207     #and as we go through the new configuration we
       
   208     #remove any which are configured. At the end,
       
   209     #what's left in existing is the set of loggers
       
   210     #which were in the previous configuration but
       
   211     #which are not in the new configuration.
       
   212     existing = root.manager.loggerDict.keys()
       
   213     #The list needs to be sorted so that we can
       
   214     #avoid disabling child loggers of explicitly
       
   215     #named loggers. With a sorted list it is easier
       
   216     #to find the child loggers.
       
   217     existing.sort()
       
   218     #We'll keep the list of existing loggers
       
   219     #which are children of named loggers here...
       
   220     child_loggers = []
       
   221     #now set up the new ones...
       
   222     for log in llist:
       
   223         sectname = "logger_%s" % log
       
   224         qn = cp.get(sectname, "qualname")
       
   225         opts = cp.options(sectname)
       
   226         if "propagate" in opts:
       
   227             propagate = cp.getint(sectname, "propagate")
       
   228         else:
       
   229             propagate = 1
       
   230         logger = logging.getLogger(qn)
       
   231         if qn in existing:
       
   232             i = existing.index(qn)
       
   233             prefixed = qn + "."
       
   234             pflen = len(prefixed)
       
   235             num_existing = len(existing)
       
   236             i = i + 1 # look at the entry after qn
       
   237             while (i < num_existing) and (existing[i][:pflen] == prefixed):
       
   238                 child_loggers.append(existing[i])
       
   239                 i = i + 1
       
   240             existing.remove(qn)
       
   241         if "level" in opts:
       
   242             level = cp.get(sectname, "level")
       
   243             logger.setLevel(logging._levelNames[level])
       
   244         for h in logger.handlers[:]:
       
   245             logger.removeHandler(h)
       
   246         logger.propagate = propagate
       
   247         logger.disabled = 0
       
   248         hlist = cp.get(sectname, "handlers")
       
   249         if len(hlist):
       
   250             hlist = string.split(hlist, ",")
       
   251             hlist = _strip_spaces(hlist)
       
   252             for hand in hlist:
       
   253                 logger.addHandler(handlers[hand])
       
   254 
       
   255     #Disable any old loggers. There's no point deleting
       
   256     #them as other threads may continue to hold references
       
   257     #and by disabling them, you stop them doing any logging.
       
   258     #However, don't disable children of named loggers, as that's
       
   259     #probably not what was intended by the user.
       
   260     for log in existing:
       
   261         logger = root.manager.loggerDict[log]
       
   262         if log in child_loggers:
       
   263             logger.level = logging.NOTSET
       
   264             logger.handlers = []
       
   265             logger.propagate = 1
       
   266         elif disable_existing_loggers:
       
   267             logger.disabled = 1
       
   268 
       
   269 
       
   270 def listen(port=DEFAULT_LOGGING_CONFIG_PORT):
       
   271     """
       
   272     Start up a socket server on the specified port, and listen for new
       
   273     configurations.
       
   274 
       
   275     These will be sent as a file suitable for processing by fileConfig().
       
   276     Returns a Thread object on which you can call start() to start the server,
       
   277     and which you can join() when appropriate. To stop the server, call
       
   278     stopListening().
       
   279     """
       
   280     if not thread:
       
   281         raise NotImplementedError, "listen() needs threading to work"
       
   282 
       
   283     class ConfigStreamHandler(StreamRequestHandler):
       
   284         """
       
   285         Handler for a logging configuration request.
       
   286 
       
   287         It expects a completely new logging configuration and uses fileConfig
       
   288         to install it.
       
   289         """
       
   290         def handle(self):
       
   291             """
       
   292             Handle a request.
       
   293 
       
   294             Each request is expected to be a 4-byte length, packed using
       
   295             struct.pack(">L", n), followed by the config file.
       
   296             Uses fileConfig() to do the grunt work.
       
   297             """
       
   298             import tempfile
       
   299             try:
       
   300                 conn = self.connection
       
   301                 chunk = conn.recv(4)
       
   302                 if len(chunk) == 4:
       
   303                     slen = struct.unpack(">L", chunk)[0]
       
   304                     chunk = self.connection.recv(slen)
       
   305                     while len(chunk) < slen:
       
   306                         chunk = chunk + conn.recv(slen - len(chunk))
       
   307                     #Apply new configuration. We'd like to be able to
       
   308                     #create a StringIO and pass that in, but unfortunately
       
   309                     #1.5.2 ConfigParser does not support reading file
       
   310                     #objects, only actual files. So we create a temporary
       
   311                     #file and remove it later.
       
   312                     file = tempfile.mktemp(".ini")
       
   313                     f = open(file, "w")
       
   314                     f.write(chunk)
       
   315                     f.close()
       
   316                     try:
       
   317                         fileConfig(file)
       
   318                     except (KeyboardInterrupt, SystemExit):
       
   319                         raise
       
   320                     except:
       
   321                         traceback.print_exc()
       
   322                     os.remove(file)
       
   323             except socket.error, e:
       
   324                 if type(e.args) != types.TupleType:
       
   325                     raise
       
   326                 else:
       
   327                     errcode = e.args[0]
       
   328                     if errcode != RESET_ERROR:
       
   329                         raise
       
   330 
       
   331     class ConfigSocketReceiver(ThreadingTCPServer):
       
   332         """
       
   333         A simple TCP socket-based logging config receiver.
       
   334         """
       
   335 
       
   336         allow_reuse_address = 1
       
   337 
       
   338         def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT,
       
   339                      handler=None):
       
   340             ThreadingTCPServer.__init__(self, (host, port), handler)
       
   341             logging._acquireLock()
       
   342             self.abort = 0
       
   343             logging._releaseLock()
       
   344             self.timeout = 1
       
   345 
       
   346         def serve_until_stopped(self):
       
   347             import select
       
   348             abort = 0
       
   349             while not abort:
       
   350                 rd, wr, ex = select.select([self.socket.fileno()],
       
   351                                            [], [],
       
   352                                            self.timeout)
       
   353                 if rd:
       
   354                     self.handle_request()
       
   355                 logging._acquireLock()
       
   356                 abort = self.abort
       
   357                 logging._releaseLock()
       
   358 
       
   359     def serve(rcvr, hdlr, port):
       
   360         server = rcvr(port=port, handler=hdlr)
       
   361         global _listener
       
   362         logging._acquireLock()
       
   363         _listener = server
       
   364         logging._releaseLock()
       
   365         server.serve_until_stopped()
       
   366 
       
   367     return threading.Thread(target=serve,
       
   368                             args=(ConfigSocketReceiver,
       
   369                                   ConfigStreamHandler, port))
       
   370 
       
   371 def stopListening():
       
   372     """
       
   373     Stop the listening server which was created with a call to listen().
       
   374     """
       
   375     global _listener
       
   376     if _listener:
       
   377         logging._acquireLock()
       
   378         _listener.abort = 1
       
   379         _listener = None
       
   380         logging._releaseLock()