class Test(unittest.TestCase):

    def line(self, text):
        print "--------------------- %s -------------------" %text

    def setUp(self):
        import inspect
        import os.path
        self.filename=os.path.join(os.path.dirname(inspect.getfile(self.__class__)), "loggingconfig.xml")
        self.cp=ConfigParser()
        self.cp.read(self.filename)
        self.loggers=["atix", "atix.atix1", "atix.atix2"]
        ComLog.fileConfig(self.filename)
        
    def testSections(self):
        sections=self.cp._sections.keys()
        sections.sort()
        expectedsections=[u'formatter_form01', u'formatter_form02', u'formatter_form03', u'formatter_form04', 'formatters', u'handler_atix', u'handler_atix1', u'handler_atix2', u'handler_root', 'handlers', u'logger_atix', u'logger_atix1', u'logger_root', 'loggers']
        self.assertEquals(sections, expectedsections, "Expected sections are different from sections %s!=%s" %(sections, expectedsections))

    def testKeys(self):
        expectedsections={ ConfigParser.LOGGERS_TAGNAME: "atix1,root,atix", ConfigParser.HANDLERS_TAGNAME: "atix1,atix2,root,atix", ConfigParser.FORMATTERS_TAGNAME: "form02,form01,form04,form03"}
        for section in (ConfigParser.LOGGERS_TAGNAME, ConfigParser.HANDLERS_TAGNAME, ConfigParser.FORMATTERS_TAGNAME):
            _keys=self.cp.get(section, "keys")
            expectedkeys=expectedsections[section]
            self.assertEquals(_keys,expectedkeys, "Keys and expected keys for section %s are different %s!= %s" %(section, _keys, expectedkeys))
 def setUp(self):
     import inspect
     import os.path
     self.filename=os.path.join(os.path.dirname(inspect.getfile(self.__class__)), "loggingconfig.xml")
     self.cp=ConfigParser()
     self.cp.read(self.filename)
     self.loggers=["atix", "atix.atix1", "atix.atix2"]
     ComLog.fileConfig(self.filename)
def fileConfig(fname, defaults=None, _vars=None):
    """
    Read the logging configuration from a ConfigParser-format file.

    This can be called several times from an application, allowing an end user
    the ability to select from various pre-canned configurations (if the
    developer provides a mechanism to present the choices and load the chosen
    configuration).
    In versions of ConfigParser which have the readfp method [typically
    shipped in 2.x versions of Python], you can pass in a file-like object
    rather than a filename, in which case the file-like object will be read
    using readfp.

    Derived from python 2.4.4 but extended with _vars so that additional classes from
    other sides can be loaded. Just give _vars as dict with name->class.
    Also this method support xml config files (see XMLConfigParser) if fname ends with
    extension xml.
    """
    #global _classregistry
    #print os.path.splitext(fname)
    from xml.dom import Node
    if isinstance(fname, Node) or os.path.splitext(fname)[1] == ".xml":
        from comoonics.tools.XMLConfigParser import ConfigParser
    else:
        from ConfigParser import ConfigParser

    logging.shutdown()
    cp = ConfigParser(defaults)
    if hasattr(cp, 'readfp') and hasattr(fname, 'readline'):
        cp.readfp(fname)
    else:
        cp.read(fname)
    #first, do the formatters...
    if cp.has_section("formatters"):
        flist = cp.get("formatters", "keys")
        if len(flist):
            flist = string.split(flist, ",")
            formatters = {}
            for form in flist:
                sectname = "formatter_%s" % form
                opts = cp.options(sectname)
                if "format" in opts:
                    fs = cp.get(sectname, "format", 1)
                else:
                    fs = None
                if "datefmt" in opts:
                    dfs = cp.get(sectname, "datefmt", 1)
                else:
                    dfs = None
                f = logging.Formatter(fs, dfs)
                formatters[form] = f
    #next, do the handlers...
    #critical section...
    logging._acquireLock()
    try:
        try:
            #first, lose the existing handlers...
            logging._handlers.clear()
            del logging._handlerList[:]
            #now set up the new ones...
            hlist = cp.get("handlers", "keys")
            _mylogger.debug("handlers: %s, %u" %(hlist, len(hlist)))
            if len(hlist):
                hlist = string.split(hlist, ",")
                handlers = {}
                fixups = [] #for inter-handler references
                for hand in hlist:
                    try:
                        hand=hand.strip()
                        sectname = "handler_%s" % hand
                        klass = cp.get(sectname, "class")
                        opts = cp.options(sectname)
                        if "formatter" in opts:
                            fmt = cp.get(sectname, "formatter")
                        else:
                            fmt = ""
                        if not _vars:
                            _vars=vars(logging)
                        else:
                            _vars.update(vars(logging))
                        _vars.update(_classregistry)

                        klass=eval(klass, _vars)
                        args = cp.get(sectname, "args")
                        #_mylogger.debug("comoonics.ComLog.fileConfig(_classregistry: %s)" %_classregistry)
                        #_mylogger.debug("comoonics.ComLog.fileConfig(_vars: %s)" %_vars.keys())
                        args = eval(args, _vars)
                        h = apply(klass, args)
                        if "level" in opts:
                            level = cp.get(sectname, "level")
                            h.setLevel(logging._levelNames[level])
                        if len(fmt):
                            h.setFormatter(formatters[fmt])
                        #temporary hack for FileHandler and MemoryHandler.
                        if klass == logging.handlers.MemoryHandler:
                            if "target" in opts:
                                target = cp.get(sectname,"target")
                            else:
                                target = ""
                            if len(target): #the target handler may not be loaded yet, so keep for later...
                                fixups.append((h, target))
                        _mylogger.debug("handlers[%s]=%s" %(hand, h))
                        handlers[hand] = h
                    except:     #if an error occurs when instantiating a handler, too bad
                        import warnings
                        _mylogger.exception("Could not create handler: %s" %klass)
                        #this could happen e.g. because of lack of privileges
                #now all handlers are loaded, fixup inter-handler references...
                for fixup in fixups:
                    h = fixup[0]
                    t = fixup[1]
                    h.setTarget(handlers[t])
            #at last, the loggers...first the root...
            llist = cp.get("loggers", "keys")
            llist = string.split(llist, ",")
            llist.remove("root")
            sectname = "logger_root"
            root = logging.root
            log = root
            opts = cp.options(sectname)
            if "level" in opts:
                level = cp.get(sectname, "level")
                log.setLevel(logging._levelNames[level])
            for h in root.handlers[:]:
                root.removeHandler(h)
            hlist = cp.get(sectname, "handlers")
            if len(hlist):
                hlist = string.split(hlist, ",")
                for hand in hlist:
                    hand=hand.strip()
                    log.addHandler(handlers[hand])
            #and now the others...
            #we don't want to lose the existing loggers,
            #since other threads may have pointers to them.
            #existing is set to contain all existing loggers,
            #and as we go through the new configuration we
            #remove any which are configured. At the end,
            #what's left in existing is the set of loggers
            #which were in the previous configuration but
            #which are not in the new configuration.
            existing = root.manager.loggerDict.keys()
            #now set up the new ones...
            for log in llist:
                sectname = "logger_%s" % log
                qn = cp.get(sectname, "qualname")
                opts = cp.options(sectname)
                if "propagate" in opts:
                    propagate = cp.getint(sectname, "propagate")
                else:
                    propagate = 1
                logger = logging.getLogger(qn)
                if qn in existing:
                    existing.remove(qn)
                if "level" in opts:
                    level = cp.get(sectname, "level")
                    logger.setLevel(logging._levelNames[level])
                for h in logger.handlers[:]:
                    logger.removeHandler(h)
                logger.propagate = propagate
                logger.disabled = 0
                hlist = cp.get(sectname, "handlers")
                if len(hlist):
                    hlist = string.split(hlist, ",")
                    for hand in hlist:
                        hand=hand.strip()
                        logger.addHandler(handlers[hand])
            #Disable any old loggers. There's no point deleting
            #them as other threads may continue to hold references
            #and by disabling them, you stop them doing any logging.
            # MARC: I don't understand the following two lines why disabling the loggers if they might be used
            #       or referenced again and are disabled then.
            #for log in existing:
            #    root.manager.loggerDict[log].disabled = 1
        except:
            ei = sys.exc_info()
            traceback.print_exception(ei[0], ei[1], ei[2], None, sys.stderr)
            del ei
    finally:
        logging._releaseLock()