Stickum

Python code pasted @ 05:08 on Mon, 08 Jan 07
Copy & Paste Plain Text
1
# middleware.py
2
3
from paste.deploy.config import ConfigMiddleware
4
5
def make_config_filter(app, global_conf, **local_conf):
6
    conf = build_app_config(global_conf, local_conf)
7
    conf.push_as_process_config()
8
    return ConfigMiddleware(app, conf)
9
10
### _cpconfig.py
11
import sys, os, glob, re
12
13
import turbogears
14
from paste.deploy.config import CONFIG
15
from configobj import ConfigObj
16
import pkg_resources
17
import logging
18
import logging.handlers
19
import cherrypy
20
21
__all__ = [
22
    "TGConfig",
23
    "build_app_config",
24
    ]
25
26
# Monkey-path CP's config with a multi-wsgi app aware one
27
# and make it availbale at the turbogears namespace
28
cherrypy.config = turbogears.config = CONFIG
29
30
class ConfigError(Exception):
31
    pass
32
33
34
def build_app_config(global_conf, local_conf):
35
    deploy_config = global_conf.copy()
36
    deploy_config.update(local_conf)
37
    deploy_config.update(dict(global_conf=global_conf, local_conf=local_conf))
38
    cp_configfile = deploy_config.get('cp_configfile', None)
39
    cp_configmodule = deploy_config.get('cp_configmodule', None)
40
    config = TGConfig(cp_configfile, cp_configmodule)
41
    # Options passed from deployment config override those at app config
42
    config.update(deploy_config)
43
    return config
44
45
46
def config_defaults():    
47
    current_dir_uri = os.path.abspath(os.getcwd())
48
    if not current_dir_uri.startswith("/"):
49
        current_dir_uri = "/" + current_dir_uri
50
    defaults = {'current_dir_uri' : current_dir_uri}
51
    return defaults
52
53
def non_interpolating_config_obj(configfile={}, defaults={}):
54
    """ Returns a ConfigObj instance that doesn't preform interpolation.
55
    Can optionally pass defaults which will be merged with DEFAULT."""
56
    configdata = ConfigObj(configfile, unrepr=True)
57
    configdata.interpolation = False
58
    configdata.merge(dict(DEFAULT=defaults))
59
    return configdata
60
61
class TGConfig(cherrypy._cpconfig.Config):
62
    def __init__(self, configfile = None, modulename = None):
63
        defaults = config_defaults()
64
        configdata = non_interpolating_config_obj(defaults=defaults)
65
        if modulename:
66
            lastdot = modulename.rfind(".")
67
            firstdot = modulename.find(".")
68
            packagename = modulename[:lastdot]
69
            top_level_package = modulename[:firstdot]
70
            
71
            modname = modulename[lastdot+1:]
72
            modfile = pkg_resources.resource_filename(packagename, 
73
                                            modname + ".cfg")
74
            if not os.path.exists(modfile):
75
                modfile = pkg_resources.resource_filename(packagename, 
76
                                                modname)
77
            if os.path.isdir(modfile):
78
                configfiles = glob.glob(os.path.join(modfile, "*.cfg"))
79
            else:
80
                configfiles = [modfile]
81
            top_level_dir = pkg_resources.resource_filename(
82
                            top_level_package, "")[:-1].replace("\\", "/")
83
            package_dir = pkg_resources.resource_filename(
84
                            packagename, "")[:-1].replace("\\", "/")
85
            defaults.update(dict(top_level_dir=top_level_dir,
86
                                 package_dir=package_dir))
87
            configdata.merge(defaults)
88
            for file in configfiles:
89
                configdata2 = non_interpolating_config_obj(file, defaults)
90
                configdata.merge(configdata2)
91
92
        if configfile:
93
            configdata2 = non_interpolating_config_obj(configfile, defaults)
94
            configdata.merge(configdata2)
95
96
        configdata.merge(configdata.pop('global', {}))
97
        configdict = ConfigObj(configdata, unrepr=True).dict()
98
        #configure_loggers(configdict)
99
        self.update(configdict)
100
101
    def update_config(self, configfile = None, modulename = None):
102
        """Updates 'config' (or apps's global config if omitted)  either from a 
103
        ConfigObj (INI-style) config file, a module name specified in dotted 
104
        notation or both (the module name is assumed to have a ".cfg" extension). 
105
        If both are specified, the module is called first, 
106
        followed by the config file. This means that the config file's options
107
        override the options in the module file."""
108
        new = self.__class__(configfile, modulename)
109
        self.update(new)
110
111
    def get(self, key, default_value=None):
112
        """Retrieves a config value"""
113
        value = super(TGConfig, self).get(key, default_value)
114
        if value and key == 'sqlobject.dburi' and os.name == "nt":
115
            value = re.sub('///(\w):', '///\\1|', value)
116
        return value
117
118
    def push_as_process_config(self):
119
        """Sets a process-wide config."""
120
        return CONFIG.push_process_config(self)
121