Package turbogears :: Module config
[hide private]

Source Code for Module turbogears.config

  1  import sys, os, glob, re 
  2   
  3  from cherrypy import config 
  4  from configobj import ConfigObj 
  5  import pkg_resources 
  6  import logging 
  7  import logging.handlers 
  8   
  9  __all__ = ["update_config", "get", "update"] 
 10   
 11  try: 
 12      set 
 13  except NameError: # Python 2.3 
 14      from sets import Set as set 
 15   
16 -class ConfigError(Exception):
17 pass
18
19 -def _get_formatters(formatters):
20 for key, formatter in formatters.items(): 21 kw = {} 22 fmt = formatter.get("format", None) 23 if fmt: 24 fmt = fmt.replace("*(", "%(") 25 kw["fmt"] = fmt 26 datefmt = formatter.get("datefmt", None) 27 if datefmt: 28 kw["datefmt"] = datefmt 29 formatter = logging.Formatter(**kw) 30 formatters[key] = formatter
31
32 -def _get_handlers(handlers, formatters):
33 for key, handler in handlers.items(): 34 kw = {} 35 try: 36 cls = handler.get("class") 37 args = handler.get("args", tuple()) 38 level = handler.get("level", None) 39 try: 40 cls = eval(cls, logging.__dict__) 41 except NameError: 42 try: 43 cls = eval(cls, logging.handlers.__dict__) 44 except NameError, err: 45 raise ConfigError("Specified class in handler " 46 "%s is not a recognizable logger name" % key) 47 try: 48 handler_obj = cls(*eval(args, logging.__dict__)) 49 except IOError,err: 50 raise ConfigError("Missing or wrong argument to " 51 "%s in handler %s -> %s " % (cls.__name__,key,err)) 52 except TypeError,err: 53 raise ConfigError("Wrong format for arguments " 54 "to %s in handler %s -> %s" % (cls.__name__,key,err)) 55 if level: 56 level = eval(level, logging.__dict__) 57 handler_obj.setLevel(level) 58 except KeyError: 59 raise ConfigError("No class specified for logging " 60 "handler %s" % key) 61 formatter = handler.get("formatter", None) 62 if formatter: 63 try: 64 formatter = formatters[formatter] 65 except KeyError: 66 raise ConfigError("Handler %s references unknown " 67 "formatter %s" % (key, formatter)) 68 handler_obj.setFormatter(formatter) 69 handlers[key] = handler_obj
70
71 -def _get_loggers(loggers, handlers):
72 for key, logger in loggers.items(): 73 qualname = logger.get("qualname", None) 74 if qualname: 75 log = logging.getLogger(qualname) 76 else: 77 log = logging.getLogger() 78 79 level = logger.get("level", None) 80 if level: 81 level = eval(level, logging.__dict__) 82 else: 83 level = logging.NOTSET 84 log.setLevel(level) 85 86 propagate = logger.get("propagate", None) 87 if propagate is not None: 88 log.propagate = propagate 89 90 cfghandlers = logger.get("handlers", None) 91 if cfghandlers: 92 if isinstance(cfghandlers, basestring): 93 cfghandlers = [cfghandlers] 94 for handler in cfghandlers: 95 try: 96 handler = handlers[handler] 97 except KeyError: 98 raise ConfigError("Logger %s references unknown " 99 "handler %s" % (key, handler)) 100 log.addHandler(handler)
101
102 -def configure_loggers(config):
103 """Configures the Python logging module, using options that are very 104 similar to the ones listed in the Python documentation. This also 105 removes the logging configuration from the configuration dictionary 106 because CherryPy doesn't like it there. Here are some of the Python 107 examples converted to the format used here: 108 109 [logging] 110 [[loggers]] 111 [[[parser]]] 112 [logger_parser] 113 level="DEBUG" 114 handlers="hand01" 115 propagate=1 116 qualname="compiler.parser" 117 118 [[handlers]] 119 [[[hand01]]] 120 class="StreamHandler" 121 level="NOTSET" 122 formatter="form01" 123 args="(sys.stdout,)" 124 125 [[formatters]] 126 [[[form01]]] 127 format="F1 *(asctime)s *(levelname)s *(message)s" 128 datefmt= 129 130 131 One notable format difference is that *() is used in the formatter 132 instead of %() because %() is already used for config file 133 interpolation. 134 """ 135 if not config.has_key("logging"): 136 config["global"]["tg.new_style_logging"] = False 137 return 138 logcfg = config["logging"] 139 formatters = logcfg.get("formatters", {}) 140 _get_formatters(formatters) 141 142 handlers = logcfg.get("handlers", {}) 143 _get_handlers(handlers, formatters) 144 145 loggers = logcfg.get("loggers", {}) 146 _get_loggers(loggers, handlers) 147 148 del config["logging"] 149 config["global"]["tg.new_style_logging"] = True
150
151 -def config_defaults():
152 current_dir_uri = os.path.abspath(os.getcwd()) 153 if not current_dir_uri.startswith("/"): 154 current_dir_uri = "/" + current_dir_uri 155 defaults = {'current_dir_uri' : current_dir_uri} 156 return defaults
157
158 -def config_obj(configfile = None, modulename = None):
159 defaults = config_defaults() 160 if modulename: 161 mod_globals = dict() 162 lastdot = modulename.rfind(".") 163 firstdot = modulename.find(".") 164 packagename = modulename[:lastdot] 165 top_level_package = modulename[:firstdot] 166 167 modname = modulename[lastdot+1:] 168 modfile = pkg_resources.resource_filename(packagename, 169 modname + ".cfg") 170 if not os.path.exists(modfile): 171 modfile = pkg_resources.resource_filename(packagename, 172 modname) 173 if os.path.isdir(modfile): 174 configfiles = glob.glob(os.path.join(modfile, "*.cfg")) 175 else: 176 configfiles = [modfile] 177 configdata = ConfigObj(unrepr=True) 178 top_level_dir = pkg_resources.resource_filename( 179 top_level_package, "")[:-1].replace("\\", "/") 180 package_dir = pkg_resources.resource_filename( 181 packagename, "")[:-1].replace("\\", "/") 182 defaults.update(dict(top_level_dir=top_level_dir, 183 package_dir=package_dir)) 184 configdata.merge(dict(DEFAULT=defaults)) 185 for file in configfiles: 186 configdata2 = ConfigObj(file, unrepr=True) 187 configdata2.merge(dict(DEFAULT=defaults)) 188 configdata.merge(configdata2) 189 190 if configfile: 191 if modulename: 192 configdata2 = ConfigObj(configfile, unrepr=True) 193 configdata2.merge(dict(DEFAULT=defaults)) 194 configdata.merge(configdata2) 195 else: 196 configdata = ConfigObj(configfile, unrepr=True) 197 return configdata
198
199 -def update_config(configfile=None, modulename=None):
200 """Updates the system configuration either from a ConfigObj 201 (INI-style) config file, a module name specified in dotted notation 202 or both (the module name is assumed to have a ".cfg" extension). 203 If both are specified, the module is called first, 204 followed by the config file. This means that the config file's options 205 override the options in the module file.""" 206 configdict = config_obj(configfile, modulename).dict() 207 configure_loggers(configdict) 208 config.update(configdict)
209
210 -def get(key, default_value=None, return_section=False, path=None):
211 """Retrieves a config value""" 212 value = config.get(key, default_value, return_section, path) 213 if value and key == 'sqlobject.dburi' and os.name == "nt": 214 value = re.sub('///(\w):', '///\\1|', value) 215 return value
216
217 -def update(configvalues):
218 """Updates the configuration with the values from the dictionary.""" 219 return config.update(configvalues)
220