Changeset 1275
- Timestamp:
- 08/24/06 02:02:42
- Files:
-
- trunk/cherrypy/__init__.py (modified) (1 diff)
- trunk/cherrypy/_cpengine.py (modified) (3 diffs)
- trunk/cherrypy/_cperror.py (modified) (1 diff)
- trunk/cherrypy/_cpmodpy.py (modified) (1 diff)
- trunk/cherrypy/_cprequest.py (modified) (17 diffs)
- trunk/cherrypy/_cptools.py (modified) (1 diff)
- trunk/cherrypy/_cptree.py (modified) (1 diff)
- trunk/cherrypy/_cpwsgi.py (modified) (2 diffs)
- trunk/cherrypy/config.py (modified) (11 diffs)
- trunk/cherrypy/lib/encoding.py (modified) (1 diff)
- trunk/cherrypy/lib/static.py (modified) (1 diff)
- trunk/cherrypy/lib/wsgiapp.py (modified) (1 diff)
- trunk/cherrypy/test/__init__.py (modified) (1 diff)
- trunk/cherrypy/test/benchmark.py (modified) (1 diff)
- trunk/cherrypy/test/modpy.py (modified) (1 diff)
- trunk/cherrypy/test/test.py (modified) (1 diff)
- trunk/cherrypy/test/test_caching.py (modified) (1 diff)
- trunk/cherrypy/test/test_config.py (modified) (2 diffs)
- trunk/cherrypy/test/test_conn.py (modified) (3 diffs)
- trunk/cherrypy/test/test_core.py (modified) (3 diffs)
- trunk/cherrypy/test/test_decodingencoding.py (modified) (1 diff)
- trunk/cherrypy/test/test_etags.py (modified) (1 diff)
- trunk/cherrypy/test/test_gzip.py (modified) (1 diff)
- trunk/cherrypy/test/test_http.py (modified) (1 diff)
- trunk/cherrypy/test/test_objectmapping.py (modified) (1 diff)
- trunk/cherrypy/test/test_proxy.py (modified) (1 diff)
- trunk/cherrypy/test/test_response_headers.py (modified) (1 diff)
- trunk/cherrypy/test/test_session.py (modified) (1 diff)
- trunk/cherrypy/test/test_sessionauthenticate.py (modified) (1 diff)
- trunk/cherrypy/test/test_states.py (modified) (3 diffs)
- trunk/cherrypy/test/test_states_demo.py (modified) (1 diff)
- trunk/cherrypy/test/test_static.py (modified) (1 diff)
- trunk/cherrypy/test/test_tools.py (modified) (2 diffs)
- trunk/cherrypy/test/test_tutorials.py (modified) (2 diffs)
- trunk/cherrypy/test/test_virtualhost.py (modified) (1 diff)
- trunk/cherrypy/test/test_wsgiapps.py (modified) (1 diff)
- trunk/cherrypy/test/test_xmlrpc.py (modified) (1 diff)
- trunk/cherrypy/tutorial/tut10_http_errors.py (modified) (2 diffs)
- trunk/cherrypy/tutorial/tutorial.conf (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/__init__.py
r1274 r1275 150 150 from cherrypy import _cperror 151 151 msg += _cperror.format_exc() 152 logfunc = config.get('log _function', _log_message)152 logfunc = config.get('log.error.function', _log_message) 153 153 logfunc(msg, context, severity) 154 154 trunk/cherrypy/_cpengine.py
r1263 r1275 69 69 conf = cherrypy.config.get 70 70 71 # Output config options to log72 if conf("log_config", True):73 cherrypy.config.log_config()74 75 71 for func in self.on_start_engine_list: 76 72 func() … … 78 74 self.state = STARTED 79 75 80 freq = float(c herrypy.config.get('deadlock_poll_freq', 60))76 freq = float(conf('deadlock.poll_freq', 60)) 81 77 if freq > 0: 82 78 self.monitor_thread = threading.Timer(freq, self.monitor) … … 223 219 for req, resp in self.servings: 224 220 resp.check_timeout() 225 freq = float(cherrypy.config.get('deadlock _poll_freq', 60))221 freq = float(cherrypy.config.get('deadlock.poll_freq', 60)) 226 222 self.monitor_thread = threading.Timer(freq, self.monitor) 227 223 self.monitor_thread.start() trunk/cherrypy/_cperror.py
r1243 r1275 178 178 response.status = self.status 179 179 tb = None 180 if cherrypy. config.get('show_tracebacks', False):180 if cherrypy.request.show_tracebacks: 181 181 tb = format_exc() 182 182 content = get_error_page(self.status, traceback=tb, trunk/cherrypy/_cpmodpy.py
r1260 r1275 19 19 func() 20 20 21 cherrypy.config.update({' global' : {'log_to_screen' : False}})21 cherrypy.config.update({'log.screen': False}) 22 22 23 23 if cherrypy.engine.state == cherrypy._cpengine.STOPPED: trunk/cherrypy/_cprequest.py
r1271 r1275 78 78 79 79 80 class PageHandler(object): 81 """Callable which sets response.body.""" 82 83 def __init__(self, callable, *args, **kwargs): 84 self.callable = callable 85 self.args = args 86 self.kwargs = kwargs 87 88 def __call__(self): 89 cherrypy.response.body = self.callable(*self.args, **self.kwargs) 90 91 92 class LateParamPageHandler(PageHandler): 93 """When passing cherrypy.request.params to the page handler, we don't 94 want to capture that dict too early; we want to give tools like the 95 decoding tool a chance to modify the params dict in-between the lookup 96 of the handler and the actual calling of the handler. This subclass 97 takes that into account, and allows request.params to be 'bound late' 98 (it's more complicated than that, but that's the effect). 99 """ 100 101 def _get_kwargs(self): 102 kwargs = cherrypy.request.params.copy() 103 if self._kwargs: 104 kwargs.update(self._kwargs) 105 return kwargs 106 107 def _set_kwargs(self, kwargs): 108 self._kwargs = kwargs 109 110 kwargs = property(_get_kwargs, _set_kwargs, 111 doc='page handler kwargs (with ' 112 'cherrypy.request.params copied in)') 113 114 115 class Dispatcher(object): 116 117 def __call__(self, path_info): 118 """Set handler and config for the current request.""" 119 request = cherrypy.request 120 func, vpath = self.find_handler(path_info) 121 122 if func: 123 # Decode any leftover %2F in the virtual_path atoms. 124 vpath = [x.replace("%2F", "/") for x in vpath] 125 request.handler = LateParamPageHandler(func, *vpath) 126 else: 127 request.handler = cherrypy.NotFound() 128 129 def find_handler(self, path): 130 """Find the appropriate page handler for the given path.""" 131 request = cherrypy.request 132 app = request.app 133 root = app.root 134 135 # Get config for the root object/path. 136 curpath = "" 137 nodeconf = {} 138 if hasattr(root, "_cp_config"): 139 nodeconf.update(root._cp_config) 140 if "/" in app.conf: 141 nodeconf.update(app.conf["/"]) 142 object_trail = [('root', root, nodeconf, curpath)] 143 144 node = root 145 names = [x for x in path.strip('/').split('/') if x] + ['index'] 146 for name in names: 147 # map to legal Python identifiers (replace '.' with '_') 148 objname = name.replace('.', '_') 149 150 nodeconf = {} 151 node = getattr(node, objname, None) 152 if node is not None: 153 # Get _cp_config attached to this node. 154 if hasattr(node, "_cp_config"): 155 nodeconf.update(node._cp_config) 156 157 # Mix in values from app.conf for this path. 158 curpath = "/".join((curpath, name)) 159 if curpath in app.conf: 160 nodeconf.update(app.conf[curpath]) 161 162 object_trail.append((objname, node, nodeconf, curpath)) 163 164 def set_conf(): 165 """Set cherrypy.request.config.""" 166 base = cherrypy.config.globalconf.copy() 167 # Note that we merge the config from each node 168 # even if that node was None. 169 for name, obj, conf, curpath in object_trail: 170 base.update(conf) 171 if 'tools.staticdir.dir' in conf: 172 base['tools.staticdir.section'] = curpath 173 return base 174 175 # Try successive objects (reverse order) 176 for i in xrange(len(object_trail) - 1, -1, -1): 177 178 name, candidate, nodeconf, curpath = object_trail[i] 179 if candidate is None: 180 continue 181 182 # Try a "default" method on the current leaf. 183 if hasattr(candidate, "default"): 184 defhandler = candidate.default 185 if getattr(defhandler, 'exposed', False): 186 # Insert any extra _cp_config from the default handler. 187 conf = getattr(defhandler, "_cp_config", {}) 188 object_trail.insert(i+1, ("default", defhandler, conf, curpath)) 189 request.config = set_conf() 190 return defhandler, names[i:-1] 191 192 # Uncomment the next line to restrict positional params to "default". 193 # if i < len(object_trail) - 2: continue 194 195 # Try the current leaf. 196 if getattr(candidate, 'exposed', False): 197 request.config = set_conf() 198 if i == len(object_trail) - 1: 199 # We found the extra ".index". Check if the original path 200 # had a trailing slash (otherwise, do a redirect). 201 if path[-1:] != '/': 202 atoms = request.browser_url.split("?", 1) 203 new_url = atoms.pop(0) + '/' 204 if atoms: 205 new_url += "?" + atoms[0] 206 raise cherrypy.HTTPRedirect(new_url) 207 return candidate, names[i:-1] 208 209 # We didn't find anything 210 request.config = set_conf() 211 return None, [] 212 213 214 class MethodDispatcher(Dispatcher): 215 """Additional dispatch based on cherrypy.request.method.upper(). 216 217 Methods named GET, POST, etc will be called on an exposed class. 218 The method names must be all caps; the appropriate Allow header 219 will be output showing all capitalized method names as allowable 220 HTTP verbs. 221 222 Note that the containing class must be exposed, not the methods. 223 """ 224 225 def __call__(self, path_info): 226 """Set handler and config for the current request.""" 227 request = cherrypy.request 228 resource, vpath = self.find_handler(path_info) 229 230 # Decode any leftover %2F in the virtual_path atoms. 231 vpath = [x.replace("%2F", "/") for x in vpath] 232 233 if resource: 234 # Set Allow header 235 avail = [m for m in dir(resource) if m.isupper()] 236 if "GET" in avail and "HEAD" not in avail: 237 avail.append("HEAD") 238 avail.sort() 239 cherrypy.response.headers['Allow'] = ", ".join(avail) 240 241 # Find the subhandler 242 meth = cherrypy.request.method.upper() 243 func = getattr(resource, meth, None) 244 if func is None and meth == "HEAD": 245 func = getattr(resource, "GET", None) 246 if func: 247 request.handler = LateParamPageHandler(func, *vpath) 248 else: 249 request.handler = cherrypy.HTTPError(405) 250 else: 251 request.handler = cherrypy.NotFound() 252 253 80 254 class Request(object): 81 255 """An HTTP request.""" … … 105 279 body = None 106 280 body_read = False 281 max_body_size = 100 * 1024 * 1024 107 282 108 283 # Dispatch attributes 284 dispatch = Dispatcher() 109 285 script_name = "" 110 286 path_info = "/" … … 113 289 toolmap = {} 114 290 config = None 115 error_response = cherrypy.HTTPError(500).set_response 291 recursive_redirect = False 292 116 293 hookpoints = ['on_start_resource', 'before_request_body', 117 294 'before_main', 'before_finalize', … … 119 296 'before_error_response', 'after_error_response'] 120 297 hooks = HookMap(hookpoints) 298 299 error_response = cherrypy.HTTPError(500).set_response 300 show_tracebacks = True 301 throw_errors = False 302 121 303 122 304 def __init__(self, local_host, remote_host, scheme="http", … … 219 401 except cherrypy.InternalRedirect, ir: 220 402 pi = ir.path 221 if (pi in self.redirections and 222 not cherrypy.config.get("recursive_redirect")): 403 if pi in self.redirections and not self.recursive_redirect: 223 404 raise RuntimeError("InternalRedirect visited the " 224 405 "same URL twice: %s" % repr(pi)) … … 229 410 raise 230 411 except: 231 if cherrypy.config.get("throw_errors", False):412 if self.throw_errors: 232 413 raise 233 414 self.handle_error(sys.exc_info()) … … 237 418 cherrypy.response.body = [] 238 419 239 log_access = cherrypy.config.get("log _access", cherrypy.log_access)420 log_access = cherrypy.config.get("log.access.function", cherrypy.log_access) 240 421 if log_access: 241 422 log_access() … … 265 446 if self.process_request_body: 266 447 # Prepare the SizeCheckWrapper for the request body 267 mbs = int(self.config.get('server.max_request_body_size', 268 100 * 1024 * 1024)) 448 mbs = self.max_body_size 269 449 if mbs > 0: 270 450 self.rfile = http.SizeCheckWrapper(self.rfile, mbs) … … 324 504 def get_resource(self, path): 325 505 """Find and call a dispatcher (which sets self.handler and .config).""" 326 dispatch = default_dispatch506 dispatch = self.dispatch 327 507 # First, see if there is a custom dispatch at this URI. Custom 328 508 # dispatchers can only be specified in app.conf, not in _cp_config … … 331 511 while trail: 332 512 nodeconf = self.app.conf.get(trail, {}) 333 d = nodeconf.get(" dispatch")513 d = nodeconf.get("request.dispatch") 334 514 if d: 335 515 dispatch = d … … 348 528 349 529 def tool_up(self): 350 """P opulate self.toolmap and set up each tool."""530 """Process self.config, populate self.toolmap and set up each tool.""" 351 531 # Get all 'tools.*' config entries as a {toolname: {k: v}} dict. 352 532 self.toolmap = tm = {} … … 366 546 v = cherrypy.lib.attributes(v) 367 547 self.hooks.attach(hookpoint, v) 548 elif namespace == "request": 549 # Override properties of this request object. 550 setattr(self, atoms[1], reqconf[k]) 551 elif namespace == "response": 552 # Override properties of the current response object. 553 setattr(cherrypy.response, atoms[1], reqconf[k]) 368 554 369 555 # Run tool._setup(conf) for each tool in the new toolmap. … … 432 618 433 619 # Failure in error handler or finalize. Bypass them. 434 if cherrypy.config.get('show_tracebacks', False):620 if self.show_tracebacks: 435 621 dbltrace = ("\n===First Error===\n\n%s" 436 622 "\n\n===Second Error===\n\n%s\n\n") … … 440 626 r = bare_error(body) 441 627 response.status, response.header_list, response.body = r 442 443 444 class PageHandler(object):445 """Callable which sets response.body."""446 447 def __init__(self, callable, *args, **kwargs):448 self.callable = callable449 self.args = args450 self.kwargs = kwargs451 452 def __call__(self):453 cherrypy.response.body = self.callable(*self.args, **self.kwargs)454 455 456 class LateParamPageHandler(PageHandler):457 """When passing cherrypy.request.params to the page handler, we don't458 want to capture that dict too early; we want to give tools like the459 decoding tool a chance to modify the params dict in-between the lookup460 of the handler and the actual calling of the handler. This subclass461 takes that into account, and allows request.params to be 'bound late'462 (it's more complicated than that, but that's the effect).463 """464 465 def _get_kwargs(self):466 kwargs = cherrypy.request.params.copy()467 if self._kwargs:468 kwargs.update(self._kwargs)469 return kwargs470 471 def _set_kwargs(self, kwargs):472 self._kwargs = kwargs473 474 kwargs = property(_get_kwargs, _set_kwargs,475 doc='page handler kwargs (with '476 'cherrypy.request.params copied in)')477 478 479 class Dispatcher(object):480 481 def __call__(self, path_info):482 """Set handler and config for the current request."""483 request = cherrypy.request484 func, vpath = self.find_handler(path_info)485 486 if func:487 # Decode any leftover %2F in the virtual_path atoms.488 vpath = [x.replace("%2F", "/") for x in vpath]489 request.handler = LateParamPageHandler(func, *vpath)490 else:491 request.handler = cherrypy.NotFound()492 493 def find_handler(self, path):494 """Find the appropriate page handler for the given path."""495 request = cherrypy.request496 app = request.app497 root = app.root498 499 # Get config for the root object/path.500 environments = cherrypy.config.environments501 curpath = ""502 nodeconf = {}503 if hasattr(root, "_cp_config"):504 nodeconf.update(root._cp_config)505 if 'environment' in nodeconf:506 env = environments[nodeconf['environment']]507 for k in env:508 if k not in nodeconf:509 nodeconf[k] = env[k]510 if "/" in app.conf:511 nodeconf.update(app.conf["/"])512 object_trail = [('root', root, nodeconf, curpath)]513 514 node = root515 names = [x for x in path.strip('/').split('/') if x] + ['index']516 for name in names:517 # map to legal Python identifiers (replace '.' with '_')518 objname = name.replace('.', '_')519 520 nodeconf = {}521 node = getattr(node, objname, None)522 if node is not None:523 # Get _cp_config attached to this node.524 if hasattr(node, "_cp_config"):525 nodeconf.update(node._cp_config)526 527 # Resolve "environment" entries. This must be done node-by-node528 # so that a child's "environment" can override concrete settings529 # of a parent. However, concrete settings in this node will530 # override "environment" settings in the same node.531 if 'environment' in nodeconf:532 env = environments[nodeconf['environment']]533 for k in env:534 if k not in nodeconf:535 nodeconf[k] = env[k]536 537 # Mix in values from app.conf for this path.538 curpath = "/".join((curpath, name))539 if curpath in app.conf:540 nodeconf.update(app.conf[curpath])541 542 object_trail.append((objname, node, nodeconf, curpath))543 544 def set_conf():545 """Set cherrypy.request.config."""546 base = cherrypy.config.globalconf.copy()547 # Note that we merge the config from each node548 # even if that node was None.549 for name, obj, conf, curpath in object_trail:550 base.update(conf)551 if 'tools.staticdir.dir' in conf:552 base['tools.staticdir.section'] = curpath553 return base554 555 # Try successive objects (reverse order)556 for i in xrange(len(object_trail) - 1, -1, -1):557 558 name, candidate, nodeconf, curpath = object_trail[i]559 if candidate is None:560 continue561 562 # Try a "default" method on the current leaf.563 if hasattr(candidate, "default"):564 defhandler = candidate.default565 if getattr(defhandler, 'exposed', False):566 # Insert any extra _cp_config from the default handler.567 conf = getattr(defhandler, "_cp_config", {})568 object_trail.insert(i+1, ("default", defhandler, conf, curpath))569 request.config = set_conf()570 return defhandler, names[i:-1]571 572 # Uncomment the next line to restrict positional params to "default".573 # if i < len(object_trail) - 2: continue574 575 # Try the current leaf.576 if getattr(candidate, 'exposed', False):577 request.config = set_conf()578 if i == len(object_trail) - 1:579 # We found the extra ".index". Check if the original path580 # had a trailing slash (otherwise, do a redirect).581 if path[-1:] != '/':582 atoms = request.browser_url.split("?", 1)583 new_url = atoms.pop(0) + '/'584 if atoms:585 new_url += "?" + atoms[0]586 raise cherrypy.HTTPRedirect(new_url)587 return candidate, names[i:-1]588 589 # We didn't find anything590 request.config = set_conf()591 return None, []592 593 default_dispatch = Dispatcher()594 595 596 class MethodDispatcher(Dispatcher):597 """Additional dispatch based on cherrypy.request.method.upper().598 599 Methods named GET, POST, etc will be called on an exposed class.600 The method names must be all caps; the appropriate Allow header601 will be output showing all capitalized method names as allowable602 HTTP verbs.603 604 Note that the containing class must be exposed, not the methods.605 """606 607 def __call__(self, path_info):608 """Set handler and config for the current request."""609 request = cherrypy.request610 resource, vpath = self.find_handler(path_info)611 612 # Decode any leftover %2F in the virtual_path atoms.613 vpath = [x.replace("%2F", "/") for x in vpath]614 615 if resource:616 # Set Allow header617 avail = [m for m in dir(resource) if m.isupper()]618 if "GET" in avail and "HEAD" not in avail:619 avail.append("HEAD")620 avail.sort()621 cherrypy.response.headers['Allow'] = ", ".join(avail)622 623 # Find the subhandler624 meth = cherrypy.request.method.upper()625 func = getattr(resource, meth, None)626 if func is None and meth == "HEAD":627 func = getattr(resource, "GET", None)628 if func:629 request.handler = LateParamPageHandler(func, *vpath)630 else:631 request.handler = cherrypy.HTTPError(405)632 else:633 request.handler = cherrypy.NotFound()634 628 635 629 … … 692 686 time = None 693 687 timed_out = False 688 stream = False 694 689 695 690 def __init__(self): … … 726 721 self.status = "%s %s" % (code, reason) 727 722 728 stream = cherrypy.config.get("stream_response", False)729 # OPTIONS requests MUST include a Content-Length of 0 if no body.730 # Just punt and figure Content-Length for all OPTIONS requests.731 if cherrypy.request.method == "OPTIONS":732 stream = False733 734 723 headers = self.headers 735 if s tream:724 if self.stream: 736 725 headers.pop('Content-Length', None) 737 726 else: … … 758 747 so that a monitor thread can interrupt the Response thread. 759 748 """ 760 timeout = float(cherrypy.config.get('deadlock _timeout', 300))749 timeout = float(cherrypy.config.get('deadlock.timeout', 300)) 761 750 if time.time() > self.time + timeout: 762 751 self.timed_out = True trunk/cherrypy/_cptools.py
r1261 r1275 235 235 wsgi_app - any wsgi application callable 236 236 env_update - a dictionary with arbitrary keys and values to be 237 merged with the WSGI environ mentdictionary.237 merged with the WSGI environ dictionary. 238 238 239 239 Example: trunk/cherrypy/_cptree.py
r1260 r1275 50 50 # Create log handlers as specified in config. 51 51 rootconf = self.conf.get("/", {}) 52 config._configure_builtin_logging(rootconf, self.access_log, "log _access_file")52 config._configure_builtin_logging(rootconf, self.access_log, "log.access.file") 53 53 config._configure_builtin_logging(rootconf, self.error_log) 54 54 trunk/cherrypy/_cpwsgi.py
r1269 r1275 68 68 raise ex 69 69 except: 70 if cherrypy.config.get("throw_errors", False):70 if request and request.throw_errors: 71 71 raise 72 72 tb = format_exc() 73 73 cherrypy.log(tb) 74 if not cherrypy.config.get("show_tracebacks", False):74 if request and not request.show_tracebacks: 75 75 tb = "" 76 76 s, h, b = bare_error(tb) … … 136 136 if isinstance(self.rfile, http.SizeCheckWrapper): 137 137 self.rfile = self.rfile.rfile 138 mbs = int(cherrypy.config.get('server.max_request_body_size', 139 100 * 1024 * 1024)) 138 mbs = int(cherrypy.config.get('request.max_body_size', 100 * 1024 * 1024)) 140 139 if mbs > 0: 141 140 self.rfile = http.SizeCheckWrapper(self.rfile, mbs) trunk/cherrypy/config.py
r1253 r1275 1 """Configuration system for CherryPy.""" 1 """Configuration system for CherryPy. 2 3 Configuration in CherryPy is implemented via dictionaries. Keys are strings 4 which name the mapped value, which may be of any type. 5 6 7 Architecture 8 ------------ 9 10 CherryPy Requests are part of an Application, which runs in a global context, 11 and configuration data may apply to any of those three scopes: 12 13 Global: configuration entries which apply everywhere are stored in 14 cherrypy.config.globalconf. Use the top-level function 'config.update' 15 to modify it. 16 17 Application: entries which apply to each mounted application are stored 18 on the Application object itself, as 'app.conf'. This is a two-level 19 dict where each key is a path, or "relative URL" (for example, "/" or 20 "/path/to/my/page"), and each value is a config dict. Usually, this 21 data is provided in the call to cherrypy.tree.mount(root(), conf=conf), 22 although you may also use app.merge(conf). 23 24 Request: each Request object possesses a single 'Request.config' dict. 25 Early in the request process, this dict is populated by merging global 26 config entries, Application entries (whose path equals or is a parent 27 of Request.path_info), and any config acquired while looking up the 28 page handler (see next). 29 30 31 Usage 32 ----- 33 34 Configuration data may be supplied as a Python dictionary, as a filename, 35 or as an open file object. When you supply a filename or file, CherryPy 36 uses Python's builtin ConfigParser; you declare Application config by 37 writing each path as a section header: 38 39 [/path/to/my/page] 40 request.stream = True 41 42 To declare global configuration entries, place them in a [global] section. 43 44 You may also declare config entries directly on the classes and methods 45 (page handlers) that make up your CherryPy application via the '_cp_config' 46 attribute. For example: 47 48 class Demo: 49 _cp_config = {'tools.gzip.on': True} 50 51 def index(self): 52 raise cherrypy.InternalRedirect("/cuba") 53 index.exposed = True 54 index._cp_config = {'request.recursive_redirect': True} 55 56 57 Namespaces 58 ---------- 59 60 Configuration keys are separated into namespaces by the first "." in the key. 61 Current namespaces: 62 63 autoreload: Controls the autoreload mechanism in cherrypy.engine. 64 These can only be declared in the global config. 65 deadlock: Controls the deadlock monitoring system in cherrypy.engine. 66 These can only be declared in the global config. 67 hooks: Declares additional request-processing functions. 68 log: Configures the logging for each application. 69 request: Adds attributes to each Request during the tool_up phase. 70 response: Adds attributes to each Response during the tool_up phase. 71 server: Controls the default HTTP server via cherrypy.server. 72 These can only be declared in the global config. 73 tools: Runs and configures additional request-processing packages. 74 75 The only key that does not exist in a namespace is the "environment" entry. 76 This special entry 'imports' other config entries from a template stored in 77 cherrypy.config.environments[environment]. It only applies to globalconf, 78 and only when you use "update" to modify globalconf. 79 """ 2 80 3 81 import ConfigParser … … 5 83 _logfmt = _logging.Formatter("%(message)s") 6 84 import os as _os 85 _localdir = _os.path.dirname(__file__) 7 86 8 87 import cherrypy … … 10 89 11 90 environments = { 12 "development": {13 'autoreload.on': True,14 'log_file_not_found': True,15 'show_tracebacks': True,16 'log_request_headers': True,17 },18 91 "staging": { 19 92 'autoreload.on': False, 20 'log_file_not_found': False, 21 'show_tracebacks': False, 22 'log_request_headers': False, 93 'tools.log_headers.on': False, 94 'request.show_tracebacks': False, 23 95 }, 24 96 "production": { 25 97 'autoreload.on': False, 26 ' log_file_not_found': False,27 ' show_tracebacks': False,28 'log _request_headers': False,98 'tools.log_headers.on': False, 99 'request.show_tracebacks': False, 100 'log.screen': False, 29 101 }, 30 " embedded": {102 "test_suite": { 31 103 'autoreload.on': False, 32 'log_to_screen': False, 33 'server.class': None, 104 'tools.log_headers.on': False, 105 'request.show_tracebacks': True, 106 'log.screen': False, 34 107 }, 35 108 } … … 40 113 if other not in cherrypy.engine.reload_files: 41 114 cherrypy.engine.reload_files.append(other) 42 other = Parser().dict_from_file(other)115 other = _Parser().dict_from_file(other) 43 116 elif hasattr(other, 'read'): 44 other = Parser().dict_from_file(other)117 other = _Parser().dict_from_file(other) 45 118 46 119 # Load other into base 47 120 for section, value_map in other.iteritems(): 48 # Resolve "environment" entries49 if 'environment' in value_map:50 env = environments[value_map['environment']]51 for k in env:52 if k not in value_map:53 value_map[k] = env[k]54 del value_map['environment']55 56 121 base.setdefault(section, {}).update(value_map) 57 122 123 58 124 default_conf = { 125 # Server config 59 126 'server.socket_port': 8080, 60 127 'server.socket_host': '', … … 65 132 'server.reverse_dns': False, 66 133 'server.thread_pool': 10, 67 'log_to_screen': True, 68 'log_file': _os.path.join(_os.getcwd(), _os.path.dirname(__file__), 69 "error.log"), 134 'server.max_request_header_size': 500 * 1024, 135 'server.instance': None, 136 137 # Log config 138 'log.to_screen': True, 139 ## 'log.error.function': cherrypy._log_message, 140 'log.error.file': _os.path.join(_os.getcwd(), _localdir, "error.log"), 141 # Using an access file makes CP about 10% slower. 142 ## 'log.access.function': cherrypy.log_access, 143 ## 'log.access.file': _os.path.join(_os.getcwd(), _localdir, "access.log"), 144 145 # Process management 146 'autoreload.on': True, 147 'autoreload.frequency': 1, 148 'deadlock.timeout': 300, 149 'deadlock.poll_freq': 60, 150 151 'error_page.404': '', 152 70 153 'tools.log_tracebacks.on': True, 71 ' environment': "development",154 'tools.log_headers.on': True, 72 155 } 156 73 157 74 158 globalconf = default_conf.copy() … … 83 167 if conf not in cherrypy.engine.reload_files: 84 168 cherrypy.engine.reload_files.append(conf) 85 conf = Parser().dict_from_file(conf)169 conf = _Parser().dict_from_file(conf) 86 170 elif hasattr(conf, 'read'): 87 conf = Parser().dict_from_file(conf)171 conf = _Parser().dict_from_file(conf) 88 172 89 173 if isinstance(conf.get("global", None), dict): … … 102 186 103 187 _configure_builtin_logging(globalconf, cherrypy._error_log) 104 _configure_builtin_logging(globalconf, cherrypy._access_log, "log _access_file")188 _configure_builtin_logging(globalconf, cherrypy._access_log, "log.access.file") 105 189 106 190 def _add_builtin_screen_handler(log): … … 119 203 log.addHandler(h) 120 204 121 def _configure_builtin_logging(conf, log, filekey="log _file"):205 def _configure_builtin_logging(conf, log, filekey="log.error.file"): 122 206 """Create/destroy builtin log handlers as needed from conf.""" 123 207 … … 125 209 for x in log.handlers]) 126 210 h = existing.get("screen") 127 screen = conf.get('log _to_screen')211 screen = conf.get('log.screen') 128 212 if screen: 129 213 if not h: … … 170 254 171 255 172 class Parser(ConfigParser.ConfigParser):256 class _Parser(ConfigParser.ConfigParser): 173 257 """Sub-class of ConfigParser that keeps the case of options and that raises 174 258 an exception if the file cannot be read. … … 227 311 server_vars = [ 228 312 'environment', 229 'log _to_screen',230 'log _file',313 'log.screen', 314 'log.error.file', 231 315 'server.protocol_version', 232 316 'server.socket_host', trunk/cherrypy/lib/encoding.py
r1243
