Changeset 1280
- Timestamp:
- 08/26/06 01:26:58
- Files:
-
- trunk/cherrypy/__init__.py (modified) (6 diffs)
- trunk/cherrypy/_cpengine.py (modified) (1 diff)
- trunk/cherrypy/_cprequest.py (modified) (6 diffs)
- trunk/cherrypy/_cptools.py (modified) (2 diffs)
- trunk/cherrypy/lib/encoding.py (modified) (1 diff)
- trunk/cherrypy/lib/sessions.py (modified) (1 diff)
- trunk/cherrypy/test/test_tools.py (modified) (7 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/__init__.py
r1278 r1280 9 9 from cherrypy._cperror import HTTPError, HTTPRedirect, InternalRedirect, NotFound 10 10 from cherrypy._cperror import WrongConfigValue, TimeoutError 11 error_page = {}12 11 13 12 from cherrypy import _cptools 14 13 tools = _cptools.default_toolbox 14 Tool = _cptools.Tool 15 15 16 16 from cherrypy import _cptree … … 37 37 # a new HTTP conversation, yet still refer to them as module-level globals 38 38 # in a thread-safe way. 39 serving = _local()39 _serving = _local() 40 40 41 41 … … 50 50 def _get_child(self): 51 51 try: 52 return getattr( serving, self.__attrname__)52 return getattr(_serving, self.__attrname__) 53 53 except AttributeError: 54 54 # Bind dummy instances of default objects to help introspection. … … 83 83 # Create request and response object (the same objects will be used 84 84 # throughout the entire life of the webserver, but will redirect 85 # to the " serving" object)85 # to the "_serving" object) 86 86 from cherrypy.lib import http as _http 87 87 request = _ThreadLocalProxy('request', … … 113 113 114 114 115 class LogManager(object):115 class _LogManager(object): 116 116 117 117 screen = True … … 158 158 159 159 160 log = LogManager()160 log = _LogManager() 161 161 162 162 trunk/cherrypy/_cpengine.py
r1278 r1280 210 210 req = self.request_class(local_host, remote_host, scheme, 211 211 server_protocol) 212 cherrypy. serving.request = req213 cherrypy. serving.response = resp = self.response_class()212 cherrypy._serving.request = req 213 cherrypy._serving.response = resp = self.response_class() 214 214 self.servings.append((req, resp)) 215 215 return req trunk/cherrypy/_cprequest.py
r1278 r1280 13 13 14 14 15 class HookMap(object): 16 """A map of call points to callback lists. 17 18 callbacks: a dict of the form {call point: [callbacks]}. 19 Each 'call point' is a name and each callback is a callable 20 that takes no arguments. 21 failsafes: a dict of the form {callback: failsafe}. If 'failsafe' is 22 True, the callback is guaranteed to run even if other callbacks 23 from the same call point raise exceptions. False values are 24 permissible, but ignored. 15 class Hook(object): 16 """A callback and its metadata: failsafe, priority, and kwargs. 17 18 failsafe: If True, the callback is guaranteed to run even if other 19 callbacks from the same call point raise exceptions. 20 priority: Defines the order of execution for a list of Hooks. 21 Defaults to 50. Priority numbers should be limited to the 22 closed interval [0, 100], but values outside this range are 23 acceptable, as are fractional values. 25 24 """ 26 25 27 def __init__(self, points=None): 28 points = points or [] 29 self.callbacks = dict([(point, []) for point in points]) 30 self.failsafes = {} 31 32 def attach(self, point, callback, failsafe=None, **kwargs): 33 """Append callback at the given call point. 34 35 If failsafe is True, the supplied callback is guaranteed to 36 run, even is other callbacks at the same call point fail. 37 If failsafe is None or not given, callback.failsafe will 38 be used if present; otherwise, False is assumed. 39 If additional keyword args are provided, they will be passed 40 to the given callback for each call. 41 """ 42 func = callback 43 if kwargs: 44 def wrapper(): 45 callback(**kwargs) 46 func = wrapper 47 name = getattr(callback, "__name__", None) 48 if name: 49 func.__name__ = name 50 self.callbacks[point].append(func) 26 def __init__(self, callback, failsafe=None, priority=None, **kwargs): 27 self.callback = callback 28 51 29 if failsafe is None: 52 failsafe = getattr(callback, 'failsafe', False) 53 self.failsafes[func] = failsafe 30 failsafe = getattr(callback, "failsafe", False) 31 self.failsafe = failsafe 32 33 if priority is None: 34 priority = getattr(callback, "priority", 50) 35 self.priority = priority 36 37 self.kwargs = kwargs 38 39 def __cmp__(self, other): 40 return cmp(self.priority, other.priority) 41 42 def __call__(self): 43 return self.callback(**self.kwargs) 44 45 46 class HookMap(dict): 47 """A map of call points to lists of callbacks (Hook objects).""" 48 49 def __new__(cls, points=None): 50 d = dict.__new__(cls) 51 for p in points or []: 52 d[p] = [] 53 return d 54 55 def __init__(self, *a, **kw): 56 pass 57 58 def attach(self, point, callback, failsafe=None, priority=None, **kwargs): 59 """Append a new Hook made from the supplied arguments.""" 60 self[point].append(Hook(callback, failsafe, priority, **kwargs)) 54 61 55 62 def run(self, point): 56 """Execute all registered callbacksfor the given point."""63 """Execute all registered Hooks (callbacks) for the given point.""" 57 64 if cherrypy.response.timed_out: 58 65 raise cherrypy.TimeoutError() 59 66 60 67 exc = None 61 for callback in self.callbacks[point]: 62 # Some hookpoints guarantee all callbacks are run even if 63 # others at the same hookpoint fail. We will still log the 64 # failure, but proceed on to the next callback. The only way 65 # to stop all processing from one of these callbacks is 66 # to raise SystemExit and stop the whole server. So, trap 67 # your own errors in these callbacks! 68 if exc is None or self.failsafes.get(callback, False): 68 hooks = self[point] 69 hooks.sort() 70 for hook in hooks: 71 # Some hooks are guaranteed to run even if others at 72 # the same hookpoint fail. We will still log the failure, 73 # but proceed on to the next hook. The only way 74 # to stop all processing from one of these hooks is 75 # to raise SystemExit and stop the whole server. 76 if exc is None or hook.failsafe: 69 77 try: 70 callback()78 hook() 71 79 except (KeyboardInterrupt, SystemExit): 72 80 raise … … 320 328 self.closed = False 321 329 self.redirections = [] 330 331 # Put a *copy* of the class error_page into self. 332 self.error_page = self.error_page.copy() 322 333 323 334 def close(self): … … 326 337 self.hooks.run('on_end_request') 327 338 328 s = (self, cherrypy. serving.response)339 s = (self, cherrypy._serving.response) 329 340 try: 330 341 cherrypy.engine.servings.remove(s) … … 332 343 pass 333 344 334 cherrypy. serving.__dict__.clear()345 cherrypy._serving.__dict__.clear() 335 346 336 347 def run(self, method, path, query_string, req_protocol, headers, rfile): … … 532 543 def tool_up(self): 533 544 """Process self.config, populate self.toolmap and set up each tool.""" 534 self.error_page = cherrypy.error_page.copy()535 536 545 # Get all 'tools.*' config entries as a {toolname: {k: v}} dict. 537 546 self.toolmap = tm = {} … … 546 555 elif namespace == "hooks": 547 556 # Attach bare hooks declared in config. 548 hookpoint = atoms[1] 557 # Use split again to allow multiple hooks for a single 558 # hookpoint per path (e.g. "hooks.before_main.1"). 559 # Little-known fact you only get from reading source ;) 560 hookpoint = atoms[1].split(".", 1)[0] 549 561 v = reqconf[k] 550 562 if isinstance(v, basestring): 551 563 v = cherrypy.lib.attributes(v) 552 self.hooks.attach(hookpoint, v) 564 if not isinstance(v, Hook): 565 v = Hook(v) 566 self.hooks[hookpoint].append(v) 553 567 elif namespace == "request": 554 568 # Override properties of this request object. trunk/cherrypy/_cptools.py
r1275 r1280 122 122 return wrapper 123 123 124 def _wrapper(self ):125 if self.callable(** self._merged_args()):124 def _wrapper(self, **kwargs): 125 if self.callable(**kwargs): 126 126 cherrypy.request.handler = None 127 127 … … 132 132 method when the tool is "turned on" in config. 133 133 """ 134 # Don't pass conf (or our wrapper will get wrapped!)135 134 f = getattr(self.callable, "failsafe", False) 136 cherrypy.request.hooks.attach(self._point, self._wrapper, failsafe=f) 135 p = getattr(self.callable, "priority", 50) 136 cherrypy.request.hooks.attach(self._point, self._wrapper, failsafe=f, 137 priority=p, **self._merged_args()) 137 138 138 139 trunk/cherrypy/lib/encoding.py
r1275 r1280 217 217 return 218 218 cherrypy.HTTPError(406, "identity, gzip").set_response() 219 219 gzip.priority = 90 trunk/cherrypy/lib/sessions.py
r1278 r1280 381 381 kwargs['timeout'] = timeout 382 382 kwargs['clean_freq'] = clean_freq 383 cherrypy. serving.session = sess = globals()[storage_class](id, **kwargs)383 cherrypy._serving.session = sess = globals()[storage_class](id, **kwargs) 384 384 385 385 if locking == 'implicit': trunk/cherrypy/test/test_tools.py
r1278 r1280 7 7 8 8 import cherrypy 9 from cherrypy import _cptools,tools9 from cherrypy import tools 10 10 11 11 … … 17 17 if not getattr(cherrypy.request, "login", None): 18 18 raise cherrypy.HTTPError(401) 19 tools.check_access = _cptools.Tool('before_request_body', check_access)19 tools.check_access = cherrypy.Tool('before_request_body', check_access) 20 20 21 21 def numerify(): … … 27 27 cherrypy.response.body = number_it(cherrypy.response.body) 28 28 29 class NumTool( _cptools.Tool):29 class NumTool(cherrypy.Tool): 30 30 def _setup(self): 31 31 def makemap(): … … 37 37 cherrypy.request.error_response = cherrypy.HTTPError(502).set_response 38 38 critical.failsafe = True 39 39 40 cherrypy.request.hooks.attach('on_start_resource', critical) 40 41 41 cherrypy.request.hooks.attach(self._point, self.callable) 42 42 43 43 tools.numerify = NumTool('before_finalize', numerify) 44 44 45 # It's not mandatory to inherit from _cptools.Tool.45 # It's not mandatory to inherit from cherrypy.Tool. 46 46 class NadsatTool: 47 47 … … 58 58 yield chunk 59 59 cherrypy.response.body = nadsat_it_up(cherrypy.response.body) 60 nadsat.priority = 0 60 61 61 62 def cleanup(self): … … 68 69 cherrypy.request.counter = self.counter = self.counter + 1 69 70 self.ended[cherrypy.request.counter] = False 70 cherrypy.request.hooks. callbacks['before_finalize'].insert(0, self.nadsat)71 cherrypy.request.hooks.attach('before_finalize', self.nadsat) 71 72 cherrypy.request.hooks.attach('on_end_request', self.cleanup) 72 73 tools.nadsat = NadsatTool() … … 97 98 # XXX Note that encode must run before gzip. 98 99 def decorated_euro(self): 99 print cherrypy.request.hooks.callbacks100 100 yield u"Hello," 101 101 yield u"world"

