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()