Index: third_party/cherrypy/_cpconfig.py |
=================================================================== |
--- third_party/cherrypy/_cpconfig.py (revision 0) |
+++ third_party/cherrypy/_cpconfig.py (revision 0) |
@@ -0,0 +1,295 @@ |
+""" |
+Configuration system for CherryPy. |
+ |
+Configuration in CherryPy is implemented via dictionaries. Keys are strings |
+which name the mapped value, which may be of any type. |
+ |
+ |
+Architecture |
+------------ |
+ |
+CherryPy Requests are part of an Application, which runs in a global context, |
+and configuration data may apply to any of those three scopes: |
+ |
+Global |
+ Configuration entries which apply everywhere are stored in |
+ cherrypy.config. |
+ |
+Application |
+ Entries which apply to each mounted application are stored |
+ on the Application object itself, as 'app.config'. This is a two-level |
+ dict where each key is a path, or "relative URL" (for example, "/" or |
+ "/path/to/my/page"), and each value is a config dict. Usually, this |
+ data is provided in the call to tree.mount(root(), config=conf), |
+ although you may also use app.merge(conf). |
+ |
+Request |
+ Each Request object possesses a single 'Request.config' dict. |
+ Early in the request process, this dict is populated by merging global |
+ config entries, Application entries (whose path equals or is a parent |
+ of Request.path_info), and any config acquired while looking up the |
+ page handler (see next). |
+ |
+ |
+Declaration |
+----------- |
+ |
+Configuration data may be supplied as a Python dictionary, as a filename, |
+or as an open file object. When you supply a filename or file, CherryPy |
+uses Python's builtin ConfigParser; you declare Application config by |
+writing each path as a section header:: |
+ |
+ [/path/to/my/page] |
+ request.stream = True |
+ |
+To declare global configuration entries, place them in a [global] section. |
+ |
+You may also declare config entries directly on the classes and methods |
+(page handlers) that make up your CherryPy application via the ``_cp_config`` |
+attribute. For example:: |
+ |
+ class Demo: |
+ _cp_config = {'tools.gzip.on': True} |
+ |
+ def index(self): |
+ return "Hello world" |
+ index.exposed = True |
+ index._cp_config = {'request.show_tracebacks': False} |
+ |
+.. note:: |
+ |
+ This behavior is only guaranteed for the default dispatcher. |
+ Other dispatchers may have different restrictions on where |
+ you can attach _cp_config attributes. |
+ |
+ |
+Namespaces |
+---------- |
+ |
+Configuration keys are separated into namespaces by the first "." in the key. |
+Current namespaces: |
+ |
+engine |
+ Controls the 'application engine', including autoreload. |
+ These can only be declared in the global config. |
+ |
+tree |
+ Grafts cherrypy.Application objects onto cherrypy.tree. |
+ These can only be declared in the global config. |
+ |
+hooks |
+ Declares additional request-processing functions. |
+ |
+log |
+ Configures the logging for each application. |
+ These can only be declared in the global or / config. |
+ |
+request |
+ Adds attributes to each Request. |
+ |
+response |
+ Adds attributes to each Response. |
+ |
+server |
+ Controls the default HTTP server via cherrypy.server. |
+ These can only be declared in the global config. |
+ |
+tools |
+ Runs and configures additional request-processing packages. |
+ |
+wsgi |
+ Adds WSGI middleware to an Application's "pipeline". |
+ These can only be declared in the app's root config ("/"). |
+ |
+checker |
+ Controls the 'checker', which looks for common errors in |
+ app state (including config) when the engine starts. |
+ Global config only. |
+ |
+The only key that does not exist in a namespace is the "environment" entry. |
+This special entry 'imports' other config entries from a template stored in |
+cherrypy._cpconfig.environments[environment]. It only applies to the global |
+config, and only when you use cherrypy.config.update. |
+ |
+You can define your own namespaces to be called at the Global, Application, |
+or Request level, by adding a named handler to cherrypy.config.namespaces, |
+app.namespaces, or app.request_class.namespaces. The name can |
+be any string, and the handler must be either a callable or a (Python 2.5 |
+style) context manager. |
+""" |
+ |
+import cherrypy |
+from cherrypy._cpcompat import set, basestring |
+from cherrypy.lib import reprconf |
+ |
+# Deprecated in CherryPy 3.2--remove in 3.3 |
+NamespaceSet = reprconf.NamespaceSet |
+ |
+def merge(base, other): |
+ """Merge one app config (from a dict, file, or filename) into another. |
+ |
+ If the given config is a filename, it will be appended to |
+ the list of files to monitor for "autoreload" changes. |
+ """ |
+ if isinstance(other, basestring): |
+ cherrypy.engine.autoreload.files.add(other) |
+ |
+ # Load other into base |
+ for section, value_map in reprconf.as_dict(other).items(): |
+ if not isinstance(value_map, dict): |
+ raise ValueError( |
+ "Application config must include section headers, but the " |
+ "config you tried to merge doesn't have any sections. " |
+ "Wrap your config in another dict with paths as section " |
+ "headers, for example: {'/': config}.") |
+ base.setdefault(section, {}).update(value_map) |
+ |
+ |
+class Config(reprconf.Config): |
+ """The 'global' configuration data for the entire CherryPy process.""" |
+ |
+ def update(self, config): |
+ """Update self from a dict, file or filename.""" |
+ if isinstance(config, basestring): |
+ # Filename |
+ cherrypy.engine.autoreload.files.add(config) |
+ reprconf.Config.update(self, config) |
+ |
+ def _apply(self, config): |
+ """Update self from a dict.""" |
+ if isinstance(config.get("global", None), dict): |
+ if len(config) > 1: |
+ cherrypy.checker.global_config_contained_paths = True |
+ config = config["global"] |
+ if 'tools.staticdir.dir' in config: |
+ config['tools.staticdir.section'] = "global" |
+ reprconf.Config._apply(self, config) |
+ |
+ def __call__(self, *args, **kwargs): |
+ """Decorator for page handlers to set _cp_config.""" |
+ if args: |
+ raise TypeError( |
+ "The cherrypy.config decorator does not accept positional " |
+ "arguments; you must use keyword arguments.") |
+ def tool_decorator(f): |
+ if not hasattr(f, "_cp_config"): |
+ f._cp_config = {} |
+ for k, v in kwargs.items(): |
+ f._cp_config[k] = v |
+ return f |
+ return tool_decorator |
+ |
+ |
+Config.environments = environments = { |
+ "staging": { |
+ 'engine.autoreload_on': False, |
+ 'checker.on': False, |
+ 'tools.log_headers.on': False, |
+ 'request.show_tracebacks': False, |
+ 'request.show_mismatched_params': False, |
+ }, |
+ "production": { |
+ 'engine.autoreload_on': False, |
+ 'checker.on': False, |
+ 'tools.log_headers.on': False, |
+ 'request.show_tracebacks': False, |
+ 'request.show_mismatched_params': False, |
+ 'log.screen': False, |
+ }, |
+ "embedded": { |
+ # For use with CherryPy embedded in another deployment stack. |
+ 'engine.autoreload_on': False, |
+ 'checker.on': False, |
+ 'tools.log_headers.on': False, |
+ 'request.show_tracebacks': False, |
+ 'request.show_mismatched_params': False, |
+ 'log.screen': False, |
+ 'engine.SIGHUP': None, |
+ 'engine.SIGTERM': None, |
+ }, |
+ "test_suite": { |
+ 'engine.autoreload_on': False, |
+ 'checker.on': False, |
+ 'tools.log_headers.on': False, |
+ 'request.show_tracebacks': True, |
+ 'request.show_mismatched_params': True, |
+ 'log.screen': False, |
+ }, |
+ } |
+ |
+ |
+def _server_namespace_handler(k, v): |
+ """Config handler for the "server" namespace.""" |
+ atoms = k.split(".", 1) |
+ if len(atoms) > 1: |
+ # Special-case config keys of the form 'server.servername.socket_port' |
+ # to configure additional HTTP servers. |
+ if not hasattr(cherrypy, "servers"): |
+ cherrypy.servers = {} |
+ |
+ servername, k = atoms |
+ if servername not in cherrypy.servers: |
+ from cherrypy import _cpserver |
+ cherrypy.servers[servername] = _cpserver.Server() |
+ # On by default, but 'on = False' can unsubscribe it (see below). |
+ cherrypy.servers[servername].subscribe() |
+ |
+ if k == 'on': |
+ if v: |
+ cherrypy.servers[servername].subscribe() |
+ else: |
+ cherrypy.servers[servername].unsubscribe() |
+ else: |
+ setattr(cherrypy.servers[servername], k, v) |
+ else: |
+ setattr(cherrypy.server, k, v) |
+Config.namespaces["server"] = _server_namespace_handler |
+ |
+def _engine_namespace_handler(k, v): |
+ """Backward compatibility handler for the "engine" namespace.""" |
+ engine = cherrypy.engine |
+ if k == 'autoreload_on': |
+ if v: |
+ engine.autoreload.subscribe() |
+ else: |
+ engine.autoreload.unsubscribe() |
+ elif k == 'autoreload_frequency': |
+ engine.autoreload.frequency = v |
+ elif k == 'autoreload_match': |
+ engine.autoreload.match = v |
+ elif k == 'reload_files': |
+ engine.autoreload.files = set(v) |
+ elif k == 'deadlock_poll_freq': |
+ engine.timeout_monitor.frequency = v |
+ elif k == 'SIGHUP': |
+ engine.listeners['SIGHUP'] = set([v]) |
+ elif k == 'SIGTERM': |
+ engine.listeners['SIGTERM'] = set([v]) |
+ elif "." in k: |
+ plugin, attrname = k.split(".", 1) |
+ plugin = getattr(engine, plugin) |
+ if attrname == 'on': |
+ if v and hasattr(getattr(plugin, 'subscribe', None), '__call__'): |
+ plugin.subscribe() |
+ return |
+ elif (not v) and hasattr(getattr(plugin, 'unsubscribe', None), '__call__'): |
+ plugin.unsubscribe() |
+ return |
+ setattr(plugin, attrname, v) |
+ else: |
+ setattr(engine, k, v) |
+Config.namespaces["engine"] = _engine_namespace_handler |
+ |
+ |
+def _tree_namespace_handler(k, v): |
+ """Namespace handler for the 'tree' config namespace.""" |
+ if isinstance(v, dict): |
+ for script_name, app in v.items(): |
+ cherrypy.tree.graft(app, script_name) |
+ cherrypy.engine.log("Mounted: %s on %s" % (app, script_name or "/")) |
+ else: |
+ cherrypy.tree.graft(v, v.script_name) |
+ cherrypy.engine.log("Mounted: %s on %s" % (v, v.script_name or "/")) |
+Config.namespaces["tree"] = _tree_namespace_handler |
+ |
+ |
Property changes on: third_party/cherrypy/_cpconfig.py |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |