# middleware.py from paste.deploy.config import ConfigMiddleware def make_config_filter(app, global_conf, **local_conf): conf = build_app_config(global_conf, local_conf) conf.push_as_process_config() return ConfigMiddleware(app, conf) ### _cpconfig.py import sys, os, glob, re import turbogears from paste.deploy.config import CONFIG from configobj import ConfigObj import pkg_resources import logging import logging.handlers import cherrypy __all__ = [ "TGConfig", "build_app_config", ] # Monkey-path CP's config with a multi-wsgi app aware one # and make it availbale at the turbogears namespace cherrypy.config = turbogears.config = CONFIG class ConfigError(Exception): pass def build_app_config(global_conf, local_conf): deploy_config = global_conf.copy() deploy_config.update(local_conf) deploy_config.update(dict(global_conf=global_conf, local_conf=local_conf)) cp_configfile = deploy_config.get('cp_configfile', None) cp_configmodule = deploy_config.get('cp_configmodule', None) config = TGConfig(cp_configfile, cp_configmodule) # Options passed from deployment config override those at app config config.update(deploy_config) return config def config_defaults(): current_dir_uri = os.path.abspath(os.getcwd()) if not current_dir_uri.startswith("/"): current_dir_uri = "/" + current_dir_uri defaults = {'current_dir_uri' : current_dir_uri} return defaults def non_interpolating_config_obj(configfile={}, defaults={}): """ Returns a ConfigObj instance that doesn't preform interpolation. Can optionally pass defaults which will be merged with DEFAULT.""" configdata = ConfigObj(configfile, unrepr=True) configdata.interpolation = False configdata.merge(dict(DEFAULT=defaults)) return configdata class TGConfig(cherrypy._cpconfig.Config): def __init__(self, configfile = None, modulename = None): defaults = config_defaults() configdata = non_interpolating_config_obj(defaults=defaults) if modulename: lastdot = modulename.rfind(".") firstdot = modulename.find(".") packagename = modulename[:lastdot] top_level_package = modulename[:firstdot] modname = modulename[lastdot+1:] modfile = pkg_resources.resource_filename(packagename, modname + ".cfg") if not os.path.exists(modfile): modfile = pkg_resources.resource_filename(packagename, modname) if os.path.isdir(modfile): configfiles = glob.glob(os.path.join(modfile, "*.cfg")) else: configfiles = [modfile] top_level_dir = pkg_resources.resource_filename( top_level_package, "")[:-1].replace("\\", "/") package_dir = pkg_resources.resource_filename( packagename, "")[:-1].replace("\\", "/") defaults.update(dict(top_level_dir=top_level_dir, package_dir=package_dir)) configdata.merge(defaults) for file in configfiles: configdata2 = non_interpolating_config_obj(file, defaults) configdata.merge(configdata2) if configfile: configdata2 = non_interpolating_config_obj(configfile, defaults) configdata.merge(configdata2) configdata.merge(configdata.pop('global', {})) configdict = ConfigObj(configdata, unrepr=True).dict() #configure_loggers(configdict) self.update(configdict) def update_config(self, configfile = None, modulename = None): """Updates 'config' (or apps's global config if omitted) either from a ConfigObj (INI-style) config file, a module name specified in dotted notation or both (the module name is assumed to have a ".cfg" extension). If both are specified, the module is called first, followed by the config file. This means that the config file's options override the options in the module file.""" new = self.__class__(configfile, modulename) self.update(new) def get(self, key, default_value=None): """Retrieves a config value""" value = super(TGConfig, self).get(key, default_value) if value and key == 'sqlobject.dburi' and os.name == "nt": value = re.sub('///(\w):', '///\\1|', value) return value def push_as_process_config(self): """Sets a process-wide config.""" return CONFIG.push_process_config(self)