Changeset 1143
- Timestamp:
- 06/12/06 15:25:03
- Files:
-
- trunk/cherrypy/_cprequest.py (modified) (3 diffs)
- trunk/cherrypy/_cptools.py (modified) (6 diffs)
- trunk/cherrypy/lib/caching.py (modified) (1 diff)
- trunk/cherrypy/test/test_core.py (modified) (2 diffs)
- trunk/cherrypy/test/test_response_headers.py (modified) (2 diffs)
- trunk/cherrypy/test/test_tools.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/_cprequest.py
r1141 r1143 68 68 69 69 self.closed = False 70 71 pts = ['on_start_resource', 'before_request_body',72 'before_main', 'before_finalize',73 'on_end_resource', 'on_end_request',74 'before_error_response', 'after_error_response']75 self.hooks = HookMap(pts)76 self.hooks.failsafe = ['on_start_resource', 'on_end_resource',77 'on_end_request']78 70 self.redirections = [] 79 71 … … 151 143 except cherrypy.InternalRedirect, ir: 152 144 pi = ir.path 145 if (pi in self.redirections and 146 not cherrypy.config.get("recursive_redirect")): 147 raise RuntimeError("InternalRedirect visited the " 148 "same URL twice: %s" % repr(pi)) 153 149 self.redirections.append(pi) 154 150 except (KeyboardInterrupt, SystemExit): … … 163 159 try: 164 160 try: 161 pts = ['on_start_resource', 'before_request_body', 162 'before_main', 'before_finalize', 163 'on_end_resource', 'on_end_request', 164 'before_error_response', 'after_error_response'] 165 self.hooks = HookMap(pts) 166 self.hooks.failsafe = ['on_start_resource', 'on_end_resource', 167 'on_end_request'] 168 165 169 self.get_resource(path_info) 166 170 self.tool_up() trunk/cherrypy/_cptools.py
r1134 r1143 8 8 docstring. 9 9 10 Function decorators: if the tool exposes a "wrap" callable, that is11 assumed to be a decorator for use in wrapping individual CherryPy12 page handlers (methods on the CherryPy tree). The tool may choose13 not to call the page handler at all, if the response has already14 been populated.10 Function decorators: 11 If the tool exposes an "enable" callable, that is assumed to be a 12 compile-time decorator for use in configuring individual CherryPy 13 page handlers (methods on the CherryPy tree). It should "turn on" 14 the tool in the decorated function's _cp_config attribute. 15 15 16 16 CherryPy hooks: "hooks" are points in the CherryPy request-handling … … 29 29 30 30 class Tool(object): 31 """A registered function for use with CherryPy request-processing hooks.""" 31 """A registered function for use with CherryPy request-processing hooks. 32 33 help(tool.callable) should give you more information about this Tool. 34 """ 32 35 33 36 def __init__(self, point, callable, name=None): … … 48 51 return conf 49 52 50 def wrap(self, *args, **kwargs):51 """Call-time decorator (wrap the handler with pre and post logic).52 53 For example:54 55 @tools.decode.wrap(encoding='chinese')56 def mandarin(self, name):57 return "%s, ni hao shi jie" % name58 mandarin.exposed = True59 """60 def deco(f):61 def wrapper(*a, **kw):62 self.callable(*args, **self.merged_args(kwargs))63 return f(*a, **kw)64 return wrapper65 return deco66 67 53 def enable(self, **kwargs): 68 54 """Compile-time decorator (turn on the tool in config). … … 79 65 f._cp_config = {} 80 66 f._cp_config["tools." + self.name + ".on"] = True 81 for k, v in kwargs :67 for k, v in kwargs.iteritems(): 82 68 f._cp_config["tools." + self.name + "." + k] = v 83 69 return f … … 120 106 return wrapper 121 107 122 def wrap(self, *args, **kwargs):123 """Make a decorator for this tool.124 125 For example:126 127 @tools.staticdir.wrap(section="/slides", dir="styles", root=absDir)128 def slides(self, slide=None, style=None):129 return "No such file"130 slides.exposed = True131 """132 def deco(f):133 def wrapper(*a, **kw):134 handled = self.callable(*args, **self.merged_args(kwargs))135 if handled:136 return cherrypy.response.body137 else:138 return f(*a, **kw)139 return wrapper140 return deco141 142 108 def setup(self): 143 109 """Hook this tool into cherrypy.request. … … 192 158 self.point = "before_finalize" 193 159 self.callable = _sessions.save 194 self.name = "sessions" 195 196 def wrap(self, **kwargs): 197 """Make a decorator for this tool.""" 198 def deco(f): 199 def wrapper(*a, **kw): 200 conf = cherrypy.request.toolmap.get(self.name, {}).copy() 201 conf.update(kwargs) 202 203 s = cherrypy.request._session = _sessions.Session() 204 for k, v in conf.iteritems(): 205 setattr(s, str(k), v) 206 s.init() 207 if not hasattr(cherrypy, "session"): 208 cherrypy.session = _sessions.SessionWrapper() 209 210 result = f(*a, **kw) 211 _sessions.save() 212 cherrypy.request.hooks.attach('on_end_request', _sessions.cleanup) 213 return result 214 return wrapper 215 return deco 160 self.name = None 216 161 217 162 def setup(self): trunk/cherrypy/lib/caching.py
r1127 r1143 149 149 # CherryPy interfaces. Pick one. 150 150 151 def wrap(f): 152 """Caching decorator.""" 153 def wrapper(*a, **kw): 154 # There's are no parameters to get(), so there's no need 155 # to merge values from config. 156 if not get(): 157 f(*a, **kw) 158 tee_output() 151 def enable(**kwargs): 152 """Compile-time decorator (turn on the tool in config).""" 153 def wrapper(f): 154 if not hasattr(f, "_cp_config"): 155 f._cp_config = {} 156 f._cp_config["tools.caching.on"] = True 157 for k, v in kwargs: 158 f._cp_config["tools.caching." + k] = v 159 return f 159 160 return wrapper 160 161 trunk/cherrypy/test/test_core.py
r1141 r1143 162 162 163 163 # We support Python 2.3, but the @-deco syntax would look like this: 164 # @tools.login_redir. wrap()164 # @tools.login_redir.enable() 165 165 def secure(self): 166 166 return "Welcome!" 167 secure = tools.login_redir.wrap()(secure) 167 secure = tools.login_redir.enable()(secure) 168 # Since enable returns the same function you pass in, 169 # you could skip binding the return value, and just write: 170 # tools.login_redir.enable()(secure) 168 171 169 172 def login(self): … … 325 328 yield "<h1>Choose your document</h1>\n" 326 329 yield "<ul>\n" 327 for id, contents in self.documents :330 for id, contents in self.documents.iteritems(): 328 331 yield (" <li><a href='/divorce/get?ID=%s'>%s</a>: %s</li>\n" 329 332 % (id, id, contents)) trunk/cherrypy/test/test_response_headers.py
r1134 r1143 4 4 import cherrypy 5 5 from cherrypy import tools 6 headers = tools.response_headers.wrap7 6 8 7 … … 11 10 def index(self): 12 11 yield "Hello, world" 13 index = headers([("Content-Language", "en-GB"),14 ('Content-Type', 'text/plain')])(index)15 12 index.exposed = True 13 h = [("Content-Language", "en-GB"), ('Content-Type', 'text/plain')] 14 tools.response_headers.enable(headers=h)(index) 16 15 17 16 def other(self): trunk/cherrypy/test/test_tools.py
r1138 r1143 74 74 yield europoundUnicode 75 75 euro.exposed = True 76 77 # METHOD FOUR: decorator using Tool.enable78 # We support Python 2.3, but the @-deco syntax would look like this:79 # @tools.base_url.enable()80 def base(self):81 return cherrypy.request.base82 base = tools.base_url.enable()(base)83 base.exposed = True84 76 85 77 root = Root() … … 119 111 yield "confidential" 120 112 121 # METHOD TWO: decorator using Tool. wrap113 # METHOD TWO: decorator using Tool.enable 122 114 # We support Python 2.3, but the @-deco syntax would look like this: 123 # @tools.check_access. wrap()115 # @tools.check_access.enable() 124 116 def restricted(self): 125 117 return "Welcome!" 126 restricted = tools.check_access. wrap()(restricted)118 restricted = tools.check_access.enable()(restricted) 127 119 128 120 def err_in_onstart(self): … … 194 186 self.assertBody("True") 195 187 196 # Test the " wrap" technique (call-time decorator).188 # Test the "enable" technique (compile-time decorator). 197 189 self.getPage("/demo/restricted") 198 190 self.assertErrorPage(401) 199 200 # Test the "enable" technique (compile-time decorator).201 self.getPage("/base", headers=[('X-Forwarded-Host',202 'www.myforward.com')])203 self.assertBody("http://www.myforward.com")204 191 205 192 def testGuaranteedHooks(self):

