source: tailor/vcpx/config.py @ 1617

Revision 1617, 10.0 KB checked in by lele@…, 5 years ago (diff)

Fix the usage of the debug option value

Line 
1# -*- mode: python; coding: utf-8 -*-
2# :Progetto: vcpx -- Configuration bits
3# :Creato:   sab 30 lug 2005 20:51:28 CEST
4# :Autore:   Lele Gaifax <lele@nautilus.homeip.net>
5# :Licenza:  GNU General Public License
6#
7
8"""
9Handle the configuration details.
10"""
11
12__docformat__ = 'reStructuredText'
13
14from cStringIO import StringIO
15from ConfigParser import SafeConfigParser, NoSectionError, DEFAULTSECT
16from vcpx import TailorException
17
18
19class ConfigurationError(TailorException):
20    """Configuration error"""
21
22
23LOGGING_SUPER_SECTION = '[[logging]]'
24BASIC_LOGGING_CONFIG = """\
25[formatters]
26keys = console
27
28[formatter_console]
29format =  %(asctime)s [%(levelname).1s] %(message)s
30datefmt = %H:%M:%S
31
32[loggers]
33keys = root
34
35[logger_root]
36level = INFO
37handlers = console
38
39[handlers]
40keys = console
41
42[handler_console]
43class = StreamHandler
44formatter = console
45args = (sys.stdout,)
46level = INFO
47"""
48
49
50class Config(SafeConfigParser):
51    '''
52    Syntactic sugar around standard ConfigParser, for easier access to
53    the configuration. To access any single project use the configuration
54    as a dictionary.
55
56    The file may be a full fledged Python script, starting
57    with the usual ``"#!..."`` notation: in this case, it gets evaluated and
58    its documentation becomes the actual configuration, while the functions
59    it defines may be referenced by the `before-commit` and `after-commit`
60    slots.
61
62    This is where the logging system gets initialized, possibly merging a
63    logging specific configuration section, introduced by a *supersection*
64    ``[[logging]]``.
65    '''
66
67    def __init__(self, fp, defaults):
68        SafeConfigParser.__init__(self)
69        self.namespace = {}
70
71        loggingcfg = None
72        if fp:
73            if fp.read(2) == '#!':
74                fp.seek(0)
75                exec fp.read() in globals(), self.namespace
76                config = self.namespace['__doc__']
77            else:
78                fp.seek(0)
79                config = fp.read()
80
81            # Look for a [[logging]] separator, that introduce a
82            # standard logging  section
83            cfgs = config.split(LOGGING_SUPER_SECTION)
84            if len(cfgs) == 2:
85                tailorcfg, loggingcfg = cfgs
86            else:
87                tailorcfg = cfgs[0]
88
89            self.readfp(StringIO(tailorcfg))
90
91        # Override the defaults with the command line options
92        if defaults:
93            self._defaults.update(defaults)
94
95        self._setupLogging(loggingcfg and loggingcfg or BASIC_LOGGING_CONFIG)
96
97    def _setupLogging(self, config):
98        """
99        Tailor own's approach at file based logging configuration.
100        """
101
102        import logging, logging.handlers
103
104        cp = SafeConfigParser()
105        cp.readfp(StringIO(config), self._defaults)
106
107        #first, do the formatters...
108        flist = cp.get("formatters", "keys")
109        if flist:
110            flist = flist.split(',')
111            formatters = {}
112            for form in flist:
113                sectname = "formatter_%s" % form
114                opts = cp.options(sectname)
115                if "format" in opts:
116                    fs = cp.get(sectname, "format", 1)
117                else:
118                    fs = None
119                if "datefmt" in opts:
120                    dfs = cp.get(sectname, "datefmt", 1)
121                else:
122                    dfs = None
123                f = logging.Formatter(fs, dfs)
124                formatters[form] = f
125        #next, do the handlers...
126        dbg = self._defaults.get('debug', False)
127        if dbg == 'False':
128            dbg = False
129        dbglevel = dbg and 'DEBUG' or None
130        try:
131            hlist = cp.get("handlers", "keys")
132            if hlist:
133                handlers = {}
134                fixups = [] #for inter-handler references
135                for hand in hlist.split(','):
136                    try:
137                        sectname = "handler_%s" % hand
138                        klass = cp.get(sectname, "class")
139                        opts = cp.options(sectname)
140                        if "formatter" in opts:
141                            fmt = cp.get(sectname, "formatter")
142                        else:
143                            fmt = None
144                        klass = eval(klass, vars(logging))
145                        args = cp.get(sectname, "args")
146                        args = eval(args, vars(logging))
147                        h = apply(klass, args)
148                        if dbglevel:
149                            level = dbglevel
150                        elif "level" in opts:
151                            level = cp.get(sectname, "level")
152                        else:
153                            level = None
154                        if level:
155                            h.setLevel(logging._levelNames[level])
156                        if fmt:
157                            h.setFormatter(formatters[fmt])
158                        #temporary hack for FileHandler and MemoryHandler.
159                        if klass == logging.handlers.MemoryHandler:
160                            if "target" in opts:
161                                target = cp.get(sectname,"target")
162                            else:
163                                target = ""
164                            if len(target):
165                                # the target handler may not be loaded
166                                # yet, so keep for later...
167                                fixups.append((h, target))
168                        handlers[hand] = h
169                    except:
170                        #if an error occurs when instantiating a
171                        #handler, too bad this could happen
172                        #e.g. because of lack of privileges
173                        raise #pass
174                #now all handlers are loaded, fixup inter-handler references...
175                for h,t in fixups:
176                    h.setTarget(handlers[t])
177            #at last, the loggers...first the root...
178            llist = cp.get("loggers", "keys")
179            if llist:
180                llist = llist.split(',')
181            llist.remove("root")
182            sectname = "logger_root"
183            root = logging.root
184            opts = cp.options(sectname)
185            if dbglevel:
186                level = dbglevel
187            elif "level" in opts:
188                level = cp.get(sectname, "level")
189            else:
190                level = None
191            if level:
192                root.setLevel(logging._levelNames[level])
193            for h in root.handlers[:]:
194                root.removeHandler(h)
195            hlist = cp.get(sectname, "handlers")
196            if hlist:
197                for h in hlist.split(','):
198                    root.addHandler(handlers[h])
199            #and now the others...
200            for log in llist:
201                sectname = "logger_%s" % log
202                qn = cp.get(sectname, "qualname", log)
203                opts = cp.options(sectname)
204                if "propagate" in opts:
205                    propagate = cp.getint(sectname, "propagate")
206                else:
207                    propagate = 1
208                logger = logging.getLogger(qn)
209                if dbglevel:
210                    level = dbglevel
211                elif "level" in opts:
212                    level = cp.get(sectname, "level")
213                else:
214                    level = None
215                if level:
216                    logger.setLevel(logging._levelNames[level])
217                for h in logger.handlers[:]:
218                    logger.removeHandler(h)
219                logger.propagate = propagate
220                logger.disabled = 0
221                hlist = cp.get(sectname, "handlers")
222                if hlist:
223                    for h in hlist.split(','):
224                        logger.addHandler(handlers[h])
225        except:
226            from sys import exc_info, stderr
227            from traceback import print_exception
228            ei = exc_info()
229            print_exception(ei[0], ei[1], ei[2], None, stderr)
230            del ei
231
232    def projects(self):
233        """
234        Return either the default projects or all the projects in the
235        in the configuration.
236        """
237
238        defaultp = self.getTuple('DEFAULT', 'projects')
239        return defaultp or [s for s in self.sections() if not ':' in s]
240
241    def get(self, section, option, default=None, raw=False, vars=None):
242        """Get an option value for a given section or the default value.
243
244        All % interpolations are expanded in the return values, based on the
245        defaults passed into the constructor, unless the optional argument
246        `raw` is true.  Additional substitutions may be provided using the
247        `vars` argument, which must be a dictionary whose contents overrides
248        any pre-existing defaults, but not those in the given section.
249
250        The section DEFAULT is special.
251        """
252
253        # Reimplement parent behaviour, that uses `vars` to override even
254        # the value in the specific section... Overriding the defaults
255        # seems a better idea
256
257        d = self._defaults.copy()
258        # Update with the entry specific variables
259        if vars is not None:
260            d.update(vars)
261        try:
262            d.update(self._sections[section])
263        except KeyError:
264            pass
265        option = self.optionxform(option)
266        try:
267            value = d[option]
268        except KeyError:
269            value = default
270
271        if not raw:
272            value = self._interpolate(section, option, str(value), d)
273
274        if value == 'None':
275            return default
276        elif value == 'True':
277            return True
278        elif value == 'False':
279            return False
280        else:
281            return value
282
283    def getTuple(self, section, option, default=None):
284        """
285        Parse the requested option as a tuple, if its value starts with
286        an open bracket, otherwise consider the value a single item
287        tuple.
288        """
289
290        value = self.get(section, option, default)
291        if value:
292            if value.startswith('('):
293                items = value.strip()[1:-1]
294            else:
295                items = value
296            return [i.strip() for i in items.split(',')]
297        else:
298            return []
Note: See TracBrowser for help on using the repository browser.