1##############################################################################
2#
3# Copyright (c) 2003 Zope Foundation and Contributors.
4# All Rights Reserved.
5#
6# This software is subject to the provisions of the Zope Public License,
7# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
8# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11# FOR A PARTICULAR PURPOSE.
12#
13##############################################################################
14"""ZConfig factory datatypes for loggers."""
15
16from ZConfig.components.logger.factory import Factory
17
18
19class LoggerFactoryBase(Factory):
20    """Base class for logger factories.
21
22    Factory used to create loggers while delaying actual logger
23    instance construction.  We need to do this because we may want to
24    reference a logger before actually instantiating it (for example,
25    to allow the app time to set an effective user).  An instance of
26    this wrapper is a callable which, when called, returns a logger
27    object.
28    """
29
30    def __init__(self, section):
31        Factory.__init__(self)
32        self.level = section.level
33        self.handler_factories = section.handlers
34
35    def create(self):
36        # set the logger up
37        import logging
38        logger = logging.getLogger(self.name)
39        logger.setLevel(self.level)
40        if self.handler_factories:
41            for handler_factory in self.handler_factories:
42                handler = handler_factory()
43                logger.addHandler(handler)
44        else:
45            from ZConfig.components.logger import loghandler
46            logger.addHandler(loghandler.NullHandler())
47        return logger
48
49    def startup(self):
50        # make sure we've instantiated the logger
51        self()
52
53    def getLowestHandlerLevel(self):
54        """Return the lowest log level provided by any configured handler.
55
56        If all handlers and the logger itself have level==NOTSET, this
57        returns NOTSET.
58        """
59        import logging
60        lowest = self.level
61        for factory in self.handler_factories:
62            level = factory.getLevel()
63            if level != logging.NOTSET:
64                if lowest == logging.NOTSET:
65                    lowest = level
66                else:
67                    lowest = min(lowest, level)
68        return lowest
69
70    def reopen(self):
71        """Re-open any handlers for which this is a meaningful operation.
72
73        This only works on handlers on the logger provided by this
74        factory directly; handlers for child loggers are not affected.
75        (This can be considered a bug, but is sufficient at the
76        moment.)
77        """
78        logger = self()
79        for handler in logger.handlers:
80            reopen = getattr(handler, "reopen", None)
81            if reopen is not None and callable(reopen):
82                reopen()
83
84
85class EventLogFactory(LoggerFactoryBase):
86    """Logger factory that returns the root logger."""
87
88    name = None
89
90
91class LoggerFactory(LoggerFactoryBase):
92    """Logger factory that returns the named logger."""
93
94    def __init__(self, section):
95        LoggerFactoryBase.__init__(self, section)
96        self.name = section.name
97        self.propagate = section.propagate
98
99    def create(self):
100        logger = LoggerFactoryBase.create(self)
101        logger.propagate = self.propagate
102        return logger
103