]> git.proxmox.com Git - mirror_edk2.git/blobdiff - AppPkg/Applications/Python/Python-2.7.2/Lib/logging/config.py
AppPkg/Applications/Python: Add Python 2.7.2 sources since the release of Python...
[mirror_edk2.git] / AppPkg / Applications / Python / Python-2.7.2 / Lib / logging / config.py
diff --git a/AppPkg/Applications/Python/Python-2.7.2/Lib/logging/config.py b/AppPkg/Applications/Python/Python-2.7.2/Lib/logging/config.py
new file mode 100644 (file)
index 0000000..12d42bd
--- /dev/null
@@ -0,0 +1,905 @@
+# Copyright 2001-2010 by Vinay Sajip. All Rights Reserved.\r
+#\r
+# Permission to use, copy, modify, and distribute this software and its\r
+# documentation for any purpose and without fee is hereby granted,\r
+# provided that the above copyright notice appear in all copies and that\r
+# both that copyright notice and this permission notice appear in\r
+# supporting documentation, and that the name of Vinay Sajip\r
+# not be used in advertising or publicity pertaining to distribution\r
+# of the software without specific, written prior permission.\r
+# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\r
+# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL\r
+# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\r
+# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER\r
+# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT\r
+# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\r
+\r
+"""\r
+Configuration functions for the logging package for Python. The core package\r
+is based on PEP 282 and comments thereto in comp.lang.python, and influenced\r
+by Apache's log4j system.\r
+\r
+Copyright (C) 2001-2010 Vinay Sajip. All Rights Reserved.\r
+\r
+To use, simply 'import logging' and log away!\r
+"""\r
+\r
+import sys, logging, logging.handlers, socket, struct, os, traceback, re\r
+import types, cStringIO\r
+\r
+try:\r
+    import thread\r
+    import threading\r
+except ImportError:\r
+    thread = None\r
+\r
+from SocketServer import ThreadingTCPServer, StreamRequestHandler\r
+\r
+\r
+DEFAULT_LOGGING_CONFIG_PORT = 9030\r
+\r
+if sys.platform == "win32":\r
+    RESET_ERROR = 10054   #WSAECONNRESET\r
+else:\r
+    RESET_ERROR = 104     #ECONNRESET\r
+\r
+#\r
+#   The following code implements a socket listener for on-the-fly\r
+#   reconfiguration of logging.\r
+#\r
+#   _listener holds the server object doing the listening\r
+_listener = None\r
+\r
+def fileConfig(fname, defaults=None, disable_existing_loggers=True):\r
+    """\r
+    Read the logging configuration from a ConfigParser-format file.\r
+\r
+    This can be called several times from an application, allowing an end user\r
+    the ability to select from various pre-canned configurations (if the\r
+    developer provides a mechanism to present the choices and load the chosen\r
+    configuration).\r
+    """\r
+    import ConfigParser\r
+\r
+    cp = ConfigParser.ConfigParser(defaults)\r
+    if hasattr(fname, 'readline'):\r
+        cp.readfp(fname)\r
+    else:\r
+        cp.read(fname)\r
+\r
+    formatters = _create_formatters(cp)\r
+\r
+    # critical section\r
+    logging._acquireLock()\r
+    try:\r
+        logging._handlers.clear()\r
+        del logging._handlerList[:]\r
+        # Handlers add themselves to logging._handlers\r
+        handlers = _install_handlers(cp, formatters)\r
+        _install_loggers(cp, handlers, disable_existing_loggers)\r
+    finally:\r
+        logging._releaseLock()\r
+\r
+\r
+def _resolve(name):\r
+    """Resolve a dotted name to a global object."""\r
+    name = name.split('.')\r
+    used = name.pop(0)\r
+    found = __import__(used)\r
+    for n in name:\r
+        used = used + '.' + n\r
+        try:\r
+            found = getattr(found, n)\r
+        except AttributeError:\r
+            __import__(used)\r
+            found = getattr(found, n)\r
+    return found\r
+\r
+def _strip_spaces(alist):\r
+    return map(lambda x: x.strip(), alist)\r
+\r
+def _encoded(s):\r
+    return s if isinstance(s, str) else s.encode('utf-8')\r
+\r
+def _create_formatters(cp):\r
+    """Create and return formatters"""\r
+    flist = cp.get("formatters", "keys")\r
+    if not len(flist):\r
+        return {}\r
+    flist = flist.split(",")\r
+    flist = _strip_spaces(flist)\r
+    formatters = {}\r
+    for form in flist:\r
+        sectname = "formatter_%s" % form\r
+        opts = cp.options(sectname)\r
+        if "format" in opts:\r
+            fs = cp.get(sectname, "format", 1)\r
+        else:\r
+            fs = None\r
+        if "datefmt" in opts:\r
+            dfs = cp.get(sectname, "datefmt", 1)\r
+        else:\r
+            dfs = None\r
+        c = logging.Formatter\r
+        if "class" in opts:\r
+            class_name = cp.get(sectname, "class")\r
+            if class_name:\r
+                c = _resolve(class_name)\r
+        f = c(fs, dfs)\r
+        formatters[form] = f\r
+    return formatters\r
+\r
+\r
+def _install_handlers(cp, formatters):\r
+    """Install and return handlers"""\r
+    hlist = cp.get("handlers", "keys")\r
+    if not len(hlist):\r
+        return {}\r
+    hlist = hlist.split(",")\r
+    hlist = _strip_spaces(hlist)\r
+    handlers = {}\r
+    fixups = [] #for inter-handler references\r
+    for hand in hlist:\r
+        sectname = "handler_%s" % hand\r
+        klass = cp.get(sectname, "class")\r
+        opts = cp.options(sectname)\r
+        if "formatter" in opts:\r
+            fmt = cp.get(sectname, "formatter")\r
+        else:\r
+            fmt = ""\r
+        try:\r
+            klass = eval(klass, vars(logging))\r
+        except (AttributeError, NameError):\r
+            klass = _resolve(klass)\r
+        args = cp.get(sectname, "args")\r
+        args = eval(args, vars(logging))\r
+        h = klass(*args)\r
+        if "level" in opts:\r
+            level = cp.get(sectname, "level")\r
+            h.setLevel(logging._levelNames[level])\r
+        if len(fmt):\r
+            h.setFormatter(formatters[fmt])\r
+        if issubclass(klass, logging.handlers.MemoryHandler):\r
+            if "target" in opts:\r
+                target = cp.get(sectname,"target")\r
+            else:\r
+                target = ""\r
+            if len(target): #the target handler may not be loaded yet, so keep for later...\r
+                fixups.append((h, target))\r
+        handlers[hand] = h\r
+    #now all handlers are loaded, fixup inter-handler references...\r
+    for h, t in fixups:\r
+        h.setTarget(handlers[t])\r
+    return handlers\r
+\r
+\r
+def _install_loggers(cp, handlers, disable_existing_loggers):\r
+    """Create and install loggers"""\r
+\r
+    # configure the root first\r
+    llist = cp.get("loggers", "keys")\r
+    llist = llist.split(",")\r
+    llist = list(map(lambda x: x.strip(), llist))\r
+    llist.remove("root")\r
+    sectname = "logger_root"\r
+    root = logging.root\r
+    log = root\r
+    opts = cp.options(sectname)\r
+    if "level" in opts:\r
+        level = cp.get(sectname, "level")\r
+        log.setLevel(logging._levelNames[level])\r
+    for h in root.handlers[:]:\r
+        root.removeHandler(h)\r
+    hlist = cp.get(sectname, "handlers")\r
+    if len(hlist):\r
+        hlist = hlist.split(",")\r
+        hlist = _strip_spaces(hlist)\r
+        for hand in hlist:\r
+            log.addHandler(handlers[hand])\r
+\r
+    #and now the others...\r
+    #we don't want to lose the existing loggers,\r
+    #since other threads may have pointers to them.\r
+    #existing is set to contain all existing loggers,\r
+    #and as we go through the new configuration we\r
+    #remove any which are configured. At the end,\r
+    #what's left in existing is the set of loggers\r
+    #which were in the previous configuration but\r
+    #which are not in the new configuration.\r
+    existing = list(root.manager.loggerDict.keys())\r
+    #The list needs to be sorted so that we can\r
+    #avoid disabling child loggers of explicitly\r
+    #named loggers. With a sorted list it is easier\r
+    #to find the child loggers.\r
+    existing.sort(key=_encoded)\r
+    #We'll keep the list of existing loggers\r
+    #which are children of named loggers here...\r
+    child_loggers = []\r
+    #now set up the new ones...\r
+    for log in llist:\r
+        sectname = "logger_%s" % log\r
+        qn = cp.get(sectname, "qualname")\r
+        opts = cp.options(sectname)\r
+        if "propagate" in opts:\r
+            propagate = cp.getint(sectname, "propagate")\r
+        else:\r
+            propagate = 1\r
+        logger = logging.getLogger(qn)\r
+        if qn in existing:\r
+            i = existing.index(qn) + 1 # start with the entry after qn\r
+            prefixed = qn + "."\r
+            pflen = len(prefixed)\r
+            num_existing = len(existing)\r
+            while i < num_existing:\r
+                if existing[i][:pflen] == prefixed:\r
+                    child_loggers.append(existing[i])\r
+                i += 1\r
+            existing.remove(qn)\r
+        if "level" in opts:\r
+            level = cp.get(sectname, "level")\r
+            logger.setLevel(logging._levelNames[level])\r
+        for h in logger.handlers[:]:\r
+            logger.removeHandler(h)\r
+        logger.propagate = propagate\r
+        logger.disabled = 0\r
+        hlist = cp.get(sectname, "handlers")\r
+        if len(hlist):\r
+            hlist = hlist.split(",")\r
+            hlist = _strip_spaces(hlist)\r
+            for hand in hlist:\r
+                logger.addHandler(handlers[hand])\r
+\r
+    #Disable any old loggers. There's no point deleting\r
+    #them as other threads may continue to hold references\r
+    #and by disabling them, you stop them doing any logging.\r
+    #However, don't disable children of named loggers, as that's\r
+    #probably not what was intended by the user.\r
+    for log in existing:\r
+        logger = root.manager.loggerDict[log]\r
+        if log in child_loggers:\r
+            logger.level = logging.NOTSET\r
+            logger.handlers = []\r
+            logger.propagate = 1\r
+        elif disable_existing_loggers:\r
+            logger.disabled = 1\r
+\r
+\r
+\r
+IDENTIFIER = re.compile('^[a-z_][a-z0-9_]*$', re.I)\r
+\r
+\r
+def valid_ident(s):\r
+    m = IDENTIFIER.match(s)\r
+    if not m:\r
+        raise ValueError('Not a valid Python identifier: %r' % s)\r
+    return True\r
+\r
+\r
+# The ConvertingXXX classes are wrappers around standard Python containers,\r
+# and they serve to convert any suitable values in the container. The\r
+# conversion converts base dicts, lists and tuples to their wrapped\r
+# equivalents, whereas strings which match a conversion format are converted\r
+# appropriately.\r
+#\r
+# Each wrapper should have a configurator attribute holding the actual\r
+# configurator to use for conversion.\r
+\r
+class ConvertingDict(dict):\r
+    """A converting dictionary wrapper."""\r
+\r
+    def __getitem__(self, key):\r
+        value = dict.__getitem__(self, key)\r
+        result = self.configurator.convert(value)\r
+        #If the converted value is different, save for next time\r
+        if value is not result:\r
+            self[key] = result\r
+            if type(result) in (ConvertingDict, ConvertingList,\r
+                                ConvertingTuple):\r
+                result.parent = self\r
+                result.key = key\r
+        return result\r
+\r
+    def get(self, key, default=None):\r
+        value = dict.get(self, key, default)\r
+        result = self.configurator.convert(value)\r
+        #If the converted value is different, save for next time\r
+        if value is not result:\r
+            self[key] = result\r
+            if type(result) in (ConvertingDict, ConvertingList,\r
+                                ConvertingTuple):\r
+                result.parent = self\r
+                result.key = key\r
+        return result\r
+\r
+    def pop(self, key, default=None):\r
+        value = dict.pop(self, key, default)\r
+        result = self.configurator.convert(value)\r
+        if value is not result:\r
+            if type(result) in (ConvertingDict, ConvertingList,\r
+                                ConvertingTuple):\r
+                result.parent = self\r
+                result.key = key\r
+        return result\r
+\r
+class ConvertingList(list):\r
+    """A converting list wrapper."""\r
+    def __getitem__(self, key):\r
+        value = list.__getitem__(self, key)\r
+        result = self.configurator.convert(value)\r
+        #If the converted value is different, save for next time\r
+        if value is not result:\r
+            self[key] = result\r
+            if type(result) in (ConvertingDict, ConvertingList,\r
+                                ConvertingTuple):\r
+                result.parent = self\r
+                result.key = key\r
+        return result\r
+\r
+    def pop(self, idx=-1):\r
+        value = list.pop(self, idx)\r
+        result = self.configurator.convert(value)\r
+        if value is not result:\r
+            if type(result) in (ConvertingDict, ConvertingList,\r
+                                ConvertingTuple):\r
+                result.parent = self\r
+        return result\r
+\r
+class ConvertingTuple(tuple):\r
+    """A converting tuple wrapper."""\r
+    def __getitem__(self, key):\r
+        value = tuple.__getitem__(self, key)\r
+        result = self.configurator.convert(value)\r
+        if value is not result:\r
+            if type(result) in (ConvertingDict, ConvertingList,\r
+                                ConvertingTuple):\r
+                result.parent = self\r
+                result.key = key\r
+        return result\r
+\r
+class BaseConfigurator(object):\r
+    """\r
+    The configurator base class which defines some useful defaults.\r
+    """\r
+\r
+    CONVERT_PATTERN = re.compile(r'^(?P<prefix>[a-z]+)://(?P<suffix>.*)$')\r
+\r
+    WORD_PATTERN = re.compile(r'^\s*(\w+)\s*')\r
+    DOT_PATTERN = re.compile(r'^\.\s*(\w+)\s*')\r
+    INDEX_PATTERN = re.compile(r'^\[\s*(\w+)\s*\]\s*')\r
+    DIGIT_PATTERN = re.compile(r'^\d+$')\r
+\r
+    value_converters = {\r
+        'ext' : 'ext_convert',\r
+        'cfg' : 'cfg_convert',\r
+    }\r
+\r
+    # We might want to use a different one, e.g. importlib\r
+    importer = __import__\r
+\r
+    def __init__(self, config):\r
+        self.config = ConvertingDict(config)\r
+        self.config.configurator = self\r
+\r
+    def resolve(self, s):\r
+        """\r
+        Resolve strings to objects using standard import and attribute\r
+        syntax.\r
+        """\r
+        name = s.split('.')\r
+        used = name.pop(0)\r
+        try:\r
+            found = self.importer(used)\r
+            for frag in name:\r
+                used += '.' + frag\r
+                try:\r
+                    found = getattr(found, frag)\r
+                except AttributeError:\r
+                    self.importer(used)\r
+                    found = getattr(found, frag)\r
+            return found\r
+        except ImportError:\r
+            e, tb = sys.exc_info()[1:]\r
+            v = ValueError('Cannot resolve %r: %s' % (s, e))\r
+            v.__cause__, v.__traceback__ = e, tb\r
+            raise v\r
+\r
+    def ext_convert(self, value):\r
+        """Default converter for the ext:// protocol."""\r
+        return self.resolve(value)\r
+\r
+    def cfg_convert(self, value):\r
+        """Default converter for the cfg:// protocol."""\r
+        rest = value\r
+        m = self.WORD_PATTERN.match(rest)\r
+        if m is None:\r
+            raise ValueError("Unable to convert %r" % value)\r
+        else:\r
+            rest = rest[m.end():]\r
+            d = self.config[m.groups()[0]]\r
+            #print d, rest\r
+            while rest:\r
+                m = self.DOT_PATTERN.match(rest)\r
+                if m:\r
+                    d = d[m.groups()[0]]\r
+                else:\r
+                    m = self.INDEX_PATTERN.match(rest)\r
+                    if m:\r
+                        idx = m.groups()[0]\r
+                        if not self.DIGIT_PATTERN.match(idx):\r
+                            d = d[idx]\r
+                        else:\r
+                            try:\r
+                                n = int(idx) # try as number first (most likely)\r
+                                d = d[n]\r
+                            except TypeError:\r
+                                d = d[idx]\r
+                if m:\r
+                    rest = rest[m.end():]\r
+                else:\r
+                    raise ValueError('Unable to convert '\r
+                                     '%r at %r' % (value, rest))\r
+        #rest should be empty\r
+        return d\r
+\r
+    def convert(self, value):\r
+        """\r
+        Convert values to an appropriate type. dicts, lists and tuples are\r
+        replaced by their converting alternatives. Strings are checked to\r
+        see if they have a conversion format and are converted if they do.\r
+        """\r
+        if not isinstance(value, ConvertingDict) and isinstance(value, dict):\r
+            value = ConvertingDict(value)\r
+            value.configurator = self\r
+        elif not isinstance(value, ConvertingList) and isinstance(value, list):\r
+            value = ConvertingList(value)\r
+            value.configurator = self\r
+        elif not isinstance(value, ConvertingTuple) and\\r
+                 isinstance(value, tuple):\r
+            value = ConvertingTuple(value)\r
+            value.configurator = self\r
+        elif isinstance(value, basestring): # str for py3k\r
+            m = self.CONVERT_PATTERN.match(value)\r
+            if m:\r
+                d = m.groupdict()\r
+                prefix = d['prefix']\r
+                converter = self.value_converters.get(prefix, None)\r
+                if converter:\r
+                    suffix = d['suffix']\r
+                    converter = getattr(self, converter)\r
+                    value = converter(suffix)\r
+        return value\r
+\r
+    def configure_custom(self, config):\r
+        """Configure an object with a user-supplied factory."""\r
+        c = config.pop('()')\r
+        if not hasattr(c, '__call__') and hasattr(types, 'ClassType') and type(c) != types.ClassType:\r
+            c = self.resolve(c)\r
+        props = config.pop('.', None)\r
+        # Check for valid identifiers\r
+        kwargs = dict([(k, config[k]) for k in config if valid_ident(k)])\r
+        result = c(**kwargs)\r
+        if props:\r
+            for name, value in props.items():\r
+                setattr(result, name, value)\r
+        return result\r
+\r
+    def as_tuple(self, value):\r
+        """Utility function which converts lists to tuples."""\r
+        if isinstance(value, list):\r
+            value = tuple(value)\r
+        return value\r
+\r
+class DictConfigurator(BaseConfigurator):\r
+    """\r
+    Configure logging using a dictionary-like object to describe the\r
+    configuration.\r
+    """\r
+\r
+    def configure(self):\r
+        """Do the configuration."""\r
+\r
+        config = self.config\r
+        if 'version' not in config:\r
+            raise ValueError("dictionary doesn't specify a version")\r
+        if config['version'] != 1:\r
+            raise ValueError("Unsupported version: %s" % config['version'])\r
+        incremental = config.pop('incremental', False)\r
+        EMPTY_DICT = {}\r
+        logging._acquireLock()\r
+        try:\r
+            if incremental:\r
+                handlers = config.get('handlers', EMPTY_DICT)\r
+                for name in handlers:\r
+                    if name not in logging._handlers:\r
+                        raise ValueError('No handler found with '\r
+                                         'name %r'  % name)\r
+                    else:\r
+                        try:\r
+                            handler = logging._handlers[name]\r
+                            handler_config = handlers[name]\r
+                            level = handler_config.get('level', None)\r
+                            if level:\r
+                                handler.setLevel(logging._checkLevel(level))\r
+                        except StandardError, e:\r
+                            raise ValueError('Unable to configure handler '\r
+                                             '%r: %s' % (name, e))\r
+                loggers = config.get('loggers', EMPTY_DICT)\r
+                for name in loggers:\r
+                    try:\r
+                        self.configure_logger(name, loggers[name], True)\r
+                    except StandardError, e:\r
+                        raise ValueError('Unable to configure logger '\r
+                                         '%r: %s' % (name, e))\r
+                root = config.get('root', None)\r
+                if root:\r
+                    try:\r
+                        self.configure_root(root, True)\r
+                    except StandardError, e:\r
+                        raise ValueError('Unable to configure root '\r
+                                         'logger: %s' % e)\r
+            else:\r
+                disable_existing = config.pop('disable_existing_loggers', True)\r
+\r
+                logging._handlers.clear()\r
+                del logging._handlerList[:]\r
+\r
+                # Do formatters first - they don't refer to anything else\r
+                formatters = config.get('formatters', EMPTY_DICT)\r
+                for name in formatters:\r
+                    try:\r
+                        formatters[name] = self.configure_formatter(\r
+                                                            formatters[name])\r
+                    except StandardError, e:\r
+                        raise ValueError('Unable to configure '\r
+                                         'formatter %r: %s' % (name, e))\r
+                # Next, do filters - they don't refer to anything else, either\r
+                filters = config.get('filters', EMPTY_DICT)\r
+                for name in filters:\r
+                    try:\r
+                        filters[name] = self.configure_filter(filters[name])\r
+                    except StandardError, e:\r
+                        raise ValueError('Unable to configure '\r
+                                         'filter %r: %s' % (name, e))\r
+\r
+                # Next, do handlers - they refer to formatters and filters\r
+                # As handlers can refer to other handlers, sort the keys\r
+                # to allow a deterministic order of configuration\r
+                handlers = config.get('handlers', EMPTY_DICT)\r
+                for name in sorted(handlers):\r
+                    try:\r
+                        handler = self.configure_handler(handlers[name])\r
+                        handler.name = name\r
+                        handlers[name] = handler\r
+                    except StandardError, e:\r
+                        raise ValueError('Unable to configure handler '\r
+                                         '%r: %s' % (name, e))\r
+                # Next, do loggers - they refer to handlers and filters\r
+\r
+                #we don't want to lose the existing loggers,\r
+                #since other threads may have pointers to them.\r
+                #existing is set to contain all existing loggers,\r
+                #and as we go through the new configuration we\r
+                #remove any which are configured. At the end,\r
+                #what's left in existing is the set of loggers\r
+                #which were in the previous configuration but\r
+                #which are not in the new configuration.\r
+                root = logging.root\r
+                existing = root.manager.loggerDict.keys()\r
+                #The list needs to be sorted so that we can\r
+                #avoid disabling child loggers of explicitly\r
+                #named loggers. With a sorted list it is easier\r
+                #to find the child loggers.\r
+                existing.sort(key=_encoded)\r
+                #We'll keep the list of existing loggers\r
+                #which are children of named loggers here...\r
+                child_loggers = []\r
+                #now set up the new ones...\r
+                loggers = config.get('loggers', EMPTY_DICT)\r
+                for name in loggers:\r
+                    if name in existing:\r
+                        i = existing.index(name)\r
+                        prefixed = name + "."\r
+                        pflen = len(prefixed)\r
+                        num_existing = len(existing)\r
+                        i = i + 1 # look at the entry after name\r
+                        while (i < num_existing) and\\r
+                              (existing[i][:pflen] == prefixed):\r
+                            child_loggers.append(existing[i])\r
+                            i = i + 1\r
+                        existing.remove(name)\r
+                    try:\r
+                        self.configure_logger(name, loggers[name])\r
+                    except StandardError, e:\r
+                        raise ValueError('Unable to configure logger '\r
+                                         '%r: %s' % (name, e))\r
+\r
+                #Disable any old loggers. There's no point deleting\r
+                #them as other threads may continue to hold references\r
+                #and by disabling them, you stop them doing any logging.\r
+                #However, don't disable children of named loggers, as that's\r
+                #probably not what was intended by the user.\r
+                for log in existing:\r
+                    logger = root.manager.loggerDict[log]\r
+                    if log in child_loggers:\r
+                        logger.level = logging.NOTSET\r
+                        logger.handlers = []\r
+                        logger.propagate = True\r
+                    elif disable_existing:\r
+                        logger.disabled = True\r
+\r
+                # And finally, do the root logger\r
+                root = config.get('root', None)\r
+                if root:\r
+                    try:\r
+                        self.configure_root(root)\r
+                    except StandardError, e:\r
+                        raise ValueError('Unable to configure root '\r
+                                         'logger: %s' % e)\r
+        finally:\r
+            logging._releaseLock()\r
+\r
+    def configure_formatter(self, config):\r
+        """Configure a formatter from a dictionary."""\r
+        if '()' in config:\r
+            factory = config['()'] # for use in exception handler\r
+            try:\r
+                result = self.configure_custom(config)\r
+            except TypeError, te:\r
+                if "'format'" not in str(te):\r
+                    raise\r
+                #Name of parameter changed from fmt to format.\r
+                #Retry with old name.\r
+                #This is so that code can be used with older Python versions\r
+                #(e.g. by Django)\r
+                config['fmt'] = config.pop('format')\r
+                config['()'] = factory\r
+                result = self.configure_custom(config)\r
+        else:\r
+            fmt = config.get('format', None)\r
+            dfmt = config.get('datefmt', None)\r
+            result = logging.Formatter(fmt, dfmt)\r
+        return result\r
+\r
+    def configure_filter(self, config):\r
+        """Configure a filter from a dictionary."""\r
+        if '()' in config:\r
+            result = self.configure_custom(config)\r
+        else:\r
+            name = config.get('name', '')\r
+            result = logging.Filter(name)\r
+        return result\r
+\r
+    def add_filters(self, filterer, filters):\r
+        """Add filters to a filterer from a list of names."""\r
+        for f in filters:\r
+            try:\r
+                filterer.addFilter(self.config['filters'][f])\r
+            except StandardError, e:\r
+                raise ValueError('Unable to add filter %r: %s' % (f, e))\r
+\r
+    def configure_handler(self, config):\r
+        """Configure a handler from a dictionary."""\r
+        formatter = config.pop('formatter', None)\r
+        if formatter:\r
+            try:\r
+                formatter = self.config['formatters'][formatter]\r
+            except StandardError, e:\r
+                raise ValueError('Unable to set formatter '\r
+                                 '%r: %s' % (formatter, e))\r
+        level = config.pop('level', None)\r
+        filters = config.pop('filters', None)\r
+        if '()' in config:\r
+            c = config.pop('()')\r
+            if not hasattr(c, '__call__') and hasattr(types, 'ClassType') and type(c) != types.ClassType:\r
+                c = self.resolve(c)\r
+            factory = c\r
+        else:\r
+            klass = self.resolve(config.pop('class'))\r
+            #Special case for handler which refers to another handler\r
+            if issubclass(klass, logging.handlers.MemoryHandler) and\\r
+                'target' in config:\r
+                try:\r
+                    config['target'] = self.config['handlers'][config['target']]\r
+                except StandardError, e:\r
+                    raise ValueError('Unable to set target handler '\r
+                                     '%r: %s' % (config['target'], e))\r
+            elif issubclass(klass, logging.handlers.SMTPHandler) and\\r
+                'mailhost' in config:\r
+                config['mailhost'] = self.as_tuple(config['mailhost'])\r
+            elif issubclass(klass, logging.handlers.SysLogHandler) and\\r
+                'address' in config:\r
+                config['address'] = self.as_tuple(config['address'])\r
+            factory = klass\r
+        kwargs = dict([(k, config[k]) for k in config if valid_ident(k)])\r
+        try:\r
+            result = factory(**kwargs)\r
+        except TypeError, te:\r
+            if "'stream'" not in str(te):\r
+                raise\r
+            #The argument name changed from strm to stream\r
+            #Retry with old name.\r
+            #This is so that code can be used with older Python versions\r
+            #(e.g. by Django)\r
+            kwargs['strm'] = kwargs.pop('stream')\r
+            result = factory(**kwargs)\r
+        if formatter:\r
+            result.setFormatter(formatter)\r
+        if level is not None:\r
+            result.setLevel(logging._checkLevel(level))\r
+        if filters:\r
+            self.add_filters(result, filters)\r
+        return result\r
+\r
+    def add_handlers(self, logger, handlers):\r
+        """Add handlers to a logger from a list of names."""\r
+        for h in handlers:\r
+            try:\r
+                logger.addHandler(self.config['handlers'][h])\r
+            except StandardError, e:\r
+                raise ValueError('Unable to add handler %r: %s' % (h, e))\r
+\r
+    def common_logger_config(self, logger, config, incremental=False):\r
+        """\r
+        Perform configuration which is common to root and non-root loggers.\r
+        """\r
+        level = config.get('level', None)\r
+        if level is not None:\r
+            logger.setLevel(logging._checkLevel(level))\r
+        if not incremental:\r
+            #Remove any existing handlers\r
+            for h in logger.handlers[:]:\r
+                logger.removeHandler(h)\r
+            handlers = config.get('handlers', None)\r
+            if handlers:\r
+                self.add_handlers(logger, handlers)\r
+            filters = config.get('filters', None)\r
+            if filters:\r
+                self.add_filters(logger, filters)\r
+\r
+    def configure_logger(self, name, config, incremental=False):\r
+        """Configure a non-root logger from a dictionary."""\r
+        logger = logging.getLogger(name)\r
+        self.common_logger_config(logger, config, incremental)\r
+        propagate = config.get('propagate', None)\r
+        if propagate is not None:\r
+            logger.propagate = propagate\r
+\r
+    def configure_root(self, config, incremental=False):\r
+        """Configure a root logger from a dictionary."""\r
+        root = logging.getLogger()\r
+        self.common_logger_config(root, config, incremental)\r
+\r
+dictConfigClass = DictConfigurator\r
+\r
+def dictConfig(config):\r
+    """Configure logging using a dictionary."""\r
+    dictConfigClass(config).configure()\r
+\r
+\r
+def listen(port=DEFAULT_LOGGING_CONFIG_PORT):\r
+    """\r
+    Start up a socket server on the specified port, and listen for new\r
+    configurations.\r
+\r
+    These will be sent as a file suitable for processing by fileConfig().\r
+    Returns a Thread object on which you can call start() to start the server,\r
+    and which you can join() when appropriate. To stop the server, call\r
+    stopListening().\r
+    """\r
+    if not thread:\r
+        raise NotImplementedError("listen() needs threading to work")\r
+\r
+    class ConfigStreamHandler(StreamRequestHandler):\r
+        """\r
+        Handler for a logging configuration request.\r
+\r
+        It expects a completely new logging configuration and uses fileConfig\r
+        to install it.\r
+        """\r
+        def handle(self):\r
+            """\r
+            Handle a request.\r
+\r
+            Each request is expected to be a 4-byte length, packed using\r
+            struct.pack(">L", n), followed by the config file.\r
+            Uses fileConfig() to do the grunt work.\r
+            """\r
+            import tempfile\r
+            try:\r
+                conn = self.connection\r
+                chunk = conn.recv(4)\r
+                if len(chunk) == 4:\r
+                    slen = struct.unpack(">L", chunk)[0]\r
+                    chunk = self.connection.recv(slen)\r
+                    while len(chunk) < slen:\r
+                        chunk = chunk + conn.recv(slen - len(chunk))\r
+                    try:\r
+                        import json\r
+                        d =json.loads(chunk)\r
+                        assert isinstance(d, dict)\r
+                        dictConfig(d)\r
+                    except:\r
+                        #Apply new configuration.\r
+\r
+                        file = cStringIO.StringIO(chunk)\r
+                        try:\r
+                            fileConfig(file)\r
+                        except (KeyboardInterrupt, SystemExit):\r
+                            raise\r
+                        except:\r
+                            traceback.print_exc()\r
+                    if self.server.ready:\r
+                        self.server.ready.set()\r
+            except socket.error, e:\r
+                if not isinstance(e.args, tuple):\r
+                    raise\r
+                else:\r
+                    errcode = e.args[0]\r
+                    if errcode != RESET_ERROR:\r
+                        raise\r
+\r
+    class ConfigSocketReceiver(ThreadingTCPServer):\r
+        """\r
+        A simple TCP socket-based logging config receiver.\r
+        """\r
+\r
+        allow_reuse_address = 1\r
+\r
+        def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT,\r
+                     handler=None, ready=None):\r
+            ThreadingTCPServer.__init__(self, (host, port), handler)\r
+            logging._acquireLock()\r
+            self.abort = 0\r
+            logging._releaseLock()\r
+            self.timeout = 1\r
+            self.ready = ready\r
+\r
+        def serve_until_stopped(self):\r
+            import select\r
+            abort = 0\r
+            while not abort:\r
+                rd, wr, ex = select.select([self.socket.fileno()],\r
+                                           [], [],\r
+                                           self.timeout)\r
+                if rd:\r
+                    self.handle_request()\r
+                logging._acquireLock()\r
+                abort = self.abort\r
+                logging._releaseLock()\r
+            self.socket.close()\r
+\r
+    class Server(threading.Thread):\r
+\r
+        def __init__(self, rcvr, hdlr, port):\r
+            super(Server, self).__init__()\r
+            self.rcvr = rcvr\r
+            self.hdlr = hdlr\r
+            self.port = port\r
+            self.ready = threading.Event()\r
+\r
+        def run(self):\r
+            server = self.rcvr(port=self.port, handler=self.hdlr,\r
+                               ready=self.ready)\r
+            if self.port == 0:\r
+                self.port = server.server_address[1]\r
+            self.ready.set()\r
+            global _listener\r
+            logging._acquireLock()\r
+            _listener = server\r
+            logging._releaseLock()\r
+            server.serve_until_stopped()\r
+\r
+    return Server(ConfigSocketReceiver, ConfigStreamHandler, port)\r
+\r
+def stopListening():\r
+    """\r
+    Stop the listening server which was created with a call to listen().\r
+    """\r
+    global _listener\r
+    logging._acquireLock()\r
+    try:\r
+        if _listener:\r
+            _listener.abort = 1\r
+            _listener = None\r
+    finally:\r
+        logging._releaseLock()\r