Changeset 1145
- Timestamp:
- 06/13/06 01:04:32
- Files:
-
- trunk/cherrypy/_cprequest.py (modified) (1 diff)
- trunk/cherrypy/_cptools.py (modified) (17 diffs)
- trunk/cherrypy/lib/caching.py (modified) (1 diff)
- trunk/cherrypy/lib/static.py (modified) (2 diffs)
- trunk/cherrypy/test/test_core.py (modified) (1 diff)
- trunk/cherrypy/test/test_response_headers.py (modified) (1 diff)
- trunk/cherrypy/test/test_tools.py (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/_cprequest.py
r1143 r1145 305 305 bucket[".".join(atoms)] = v 306 306 307 # Run tool. setup(conf) for each tool in the new toolmap.307 # Run tool._setup(conf) for each tool in the new toolmap. 308 308 for toolname, conf in self.toolmap.iteritems(): 309 309 if conf.get("on", False): 310 310 tool = getattr(cherrypy.tools, toolname) 311 tool. setup()311 tool._setup() 312 312 313 313 def _get_browser_url(self): trunk/cherrypy/_cptools.py
r1143 r1145 9 9 10 10 Function decorators: 11 If the tool exposes an "enable" callable, that is assumed to be a12 compile-time decorator for use in configuring individual CherryPy13 page handlers (methods on the CherryPy tree). It should "turn on"14 the tool in thedecorated function's _cp_config attribute.11 All tools, when called, may be used as decorators which configure 12 individual CherryPy page handlers (methods on the CherryPy tree). 13 That is, "@tools.anytool()" should "turn on" the tool via the 14 decorated function's _cp_config attribute. 15 15 16 16 CherryPy hooks: "hooks" are points in the CherryPy request-handling 17 17 process which may hand off control to registered callbacks. The 18 Request object possesses a "hooks" attribute (a HookMap) 19 for manipulating this. If a tool exposes a "setup" callable,20 it will be called once per Request (if the feature is enabled18 Request object possesses a "hooks" attribute (a HookMap) for 19 manipulating this. If a tool exposes a "_setup" callable, it 20 will be called once per Request (if the feature is "turned on" 21 21 via config). 22 22 … … 28 28 29 29 30 def setargs(obj, func): 31 """Copy func parameter names to obj attributes.""" 32 try: 33 import inspect 34 for arg in inspect.getargspec(func)[0]: 35 setattr(obj, arg, None) 36 except (ImportError, AttributeError): 37 pass 38 39 30 40 class Tool(object): 31 41 """A registered function for use with CherryPy request-processing hooks. … … 35 45 36 46 def __init__(self, point, callable, name=None): 37 self. point = point47 self._point = point 38 48 self.callable = callable 39 self.name = name 40 # TODO: add an attribute to self for each arg 41 # in inspect.getargspec(callable) 42 43 def __call__(self, *args, **kwargs): 44 return self.callable(*args, **kwargs) 45 46 def merged_args(self, d=None): 47 conf = cherrypy.request.toolmap.get(self.name, {}).copy() 49 self._name = name 50 self.__doc__ = self.callable.__doc__ 51 setargs(self, callable) 52 53 def _merged_args(self, d=None): 54 conf = cherrypy.request.toolmap.get(self._name, {}).copy() 48 55 conf.update(d or {}) 49 56 if "on" in conf: … … 51 58 return conf 52 59 53 def enable(self, **kwargs):60 def __call__(self, **kwargs): 54 61 """Compile-time decorator (turn on the tool in config). 55 62 56 63 For example: 57 64 58 @tools.base_url .enable()65 @tools.base_url() 59 66 def whats_my_base(self): 60 67 return cherrypy.request.base … … 64 71 if not hasattr(f, "_cp_config"): 65 72 f._cp_config = {} 66 f._cp_config["tools." + self. name + ".on"] = True73 f._cp_config["tools." + self._name + ".on"] = True 67 74 for k, v in kwargs.iteritems(): 68 f._cp_config["tools." + self. name + "." + k] = v75 f._cp_config["tools." + self._name + "." + k] = v 69 76 return f 70 77 return wrapper 71 78 72 def setup(self):79 def _setup(self): 73 80 """Hook this tool into cherrypy.request. 74 81 … … 76 83 method when the tool is "turned on" in config. 77 84 """ 78 conf = self. merged_args()79 cherrypy.request.hooks.attach(self. point, self.callable, conf)85 conf = self._merged_args() 86 cherrypy.request.hooks.attach(self._point, self.callable, conf) 80 87 81 88 … … 99 106 """ 100 107 def wrapper(*a, **kw): 101 handled = self.callable(*args, **self. merged_args(kwargs))108 handled = self.callable(*args, **self._merged_args(kwargs)) 102 109 if not handled: 103 110 raise cherrypy.NotFound() … … 106 113 return wrapper 107 114 108 def setup(self):115 def _setup(self): 109 116 """Hook this tool into cherrypy.request. 110 117 … … 113 120 """ 114 121 def wrapper(): 115 if self.callable(**self. merged_args()):122 if self.callable(**self._merged_args()): 116 123 cherrypy.request.handler = None 117 124 # Don't pass conf (or our wrapper will get wrapped!) 118 cherrypy.request.hooks.attach(self. point, wrapper)125 cherrypy.request.hooks.attach(self._point, wrapper) 119 126 120 127 … … 125 132 Tool.__init__(self, None, callable, name) 126 133 127 def setup(self):134 def _setup(self): 128 135 """Hook this tool into cherrypy.request. 129 136 … … 132 139 """ 133 140 def wrapper(): 134 self.callable(**self. merged_args())141 self.callable(**self._merged_args()) 135 142 cherrypy.request.error_response = wrapper 136 143 … … 144 151 145 152 class StaticDirTool(MainTool): 146 def setup(self):153 def _setup(self): 147 154 """Hook this tool into cherrypy.request using the given conf.""" 148 conf = self. merged_args()155 conf = self._merged_args() 149 156 def wrapper(): 150 157 if self.callable(**conf): 151 158 cherrypy.request.handler = None 152 159 # Don't pass conf (or our wrapper will get wrapped!) 153 cherrypy.request.hooks.attach(self. point, wrapper)160 cherrypy.request.hooks.attach(self._point, wrapper) 154 161 155 162 156 163 class SessionTool(Tool): 164 """Session Tool for CherryPy.""" 165 157 166 def __init__(self): 158 self. point = "before_finalize"167 self._point = "before_finalize" 159 168 self.callable = _sessions.save 160 self. name = None161 162 def setup(self):169 self._name = None 170 171 def _setup(self): 163 172 """Hook this tool into cherrypy.request using the given conf. 164 173 … … 167 176 """ 168 177 def init(): 169 conf = cherrypy.request.toolmap.get(self. name, {})178 conf = cherrypy.request.toolmap.get(self._name, {}) 170 179 171 180 s = cherrypy.request._session = _sessions.Session() … … 215 224 """ 216 225 217 def setup(self):226 def _setup(self): 218 227 """Hook this tool into cherrypy.request using the given conf.""" 219 228 request = cherrypy.request … … 246 255 """ 247 256 248 def setup(self):257 def _setup(self): 249 258 # Keep request body intact so the wsgi app can have its way with it. 250 259 cherrypy.request.process_request_body = False 251 MainTool.setup(self) 260 MainTool._setup(self) 261 262 263 class CachingTool: 264 """Caching Tool for CherryPy.""" 265 266 def __init__(self): 267 self._setup = _caching._setup 268 self.__call__ = _caching.enable 252 269 253 270 … … 256 273 257 274 def __setattr__(self, name, value): 258 # If the Tool. name is None, supply it from the attribute name.275 # If the Tool._name is None, supply it from the attribute name. 259 276 if isinstance(value, Tool): 260 if value. name is None:261 value. name = name277 if value._name is None: 278 value._name = name 262 279 object.__setattr__(self, name, value) 263 280 … … 282 299 default_toolbox.xmlrpc = XMLRPCTool() 283 300 default_toolbox.wsgiapp = WSGIAppTool(_wsgiapp.run) 284 default_toolbox.caching = _caching301 default_toolbox.caching = CachingTool() 285 302 286 303 trunk/cherrypy/lib/caching.py
r1144 r1145 160 160 return wrapper 161 161 162 def setup():162 def _setup(): 163 163 """Hook caching into cherrypy.request using the given conf.""" 164 164 conf = cherrypy.request.toolmap.get("caching", {}) trunk/cherrypy/lib/static.py
r1141 r1145 143 143 144 144 def staticdir(section, dir, root="", match="", content_types=None, index=""): 145 """Serve a static resource from the given (root +) dir.""" 145 146 if match and not re.search(match, cherrypy.request.path_info): 146 147 return False … … 178 179 179 180 def staticfile(filename, root=None, match="", content_types=None): 181 """Serve a static resource from the given (root +) filename.""" 180 182 if match and not re.search(match, cherrypy.request.path_info): 181 183 return False trunk/cherrypy/test/test_core.py
r1143 r1145 162 162 163 163 # We support Python 2.3, but the @-deco syntax would look like this: 164 # @tools.login_redir .enable()164 # @tools.login_redir() 165 165 def secure(self): 166 166 return "Welcome!" 167 secure = tools.login_redir .enable()(secure)168 # Since enablereturns the same function you pass in,167 secure = tools.login_redir()(secure) 168 # Since calling the tool returns the same function you pass in, 169 169 # you could skip binding the return value, and just write: 170 # tools.login_redir .enable()(secure)170 # tools.login_redir()(secure) 171 171 172 172 def login(self): trunk/cherrypy/test/test_response_headers.py
r1143 r1145 12 12 index.exposed = True 13 13 h = [("Content-Language", "en-GB"), ('Content-Type', 'text/plain')] 14 tools.response_headers .enable(headers=h)(index)14 tools.response_headers(headers=h)(index) 15 15 16 16 def other(self): trunk/cherrypy/test/test_tools.py
r1143 r1145 28 28 29 29 class NumTool(_cptools.Tool): 30 def setup(self):30 def _setup(self): 31 31 def makemap(): 32 m = self. merged_args().get("map", {})32 m = self._merged_args().get("map", {}) 33 33 cherrypy.request.numerify_map = m.items() 34 34 cherrypy.request.hooks.attach('on_start_resource', makemap) 35 cherrypy.request.hooks.attach(self. point, self.callable)35 cherrypy.request.hooks.attach(self._point, self.callable) 36 36 tools.numerify = NumTool('before_finalize', numerify) 37 37 … … 42 42 self.counter = 0 43 43 self.ended = {} 44 self. name = "nadsat"44 self._name = "nadsat" 45 45 46 46 def nadsat(self): … … 57 57 self.ended[cherrypy.request.counter] = True 58 58 59 def setup(self):59 def _setup(self): 60 60 cherrypy.request.counter = self.counter = self.counter + 1 61 61 self.ended[cherrypy.request.counter] = False … … 111 111 yield "confidential" 112 112 113 # METHOD TWO: decorator using Tool .enable113 # METHOD TWO: decorator using Tool() 114 114 # We support Python 2.3, but the @-deco syntax would look like this: 115 # @tools.check_access .enable()115 # @tools.check_access() 116 116 def restricted(self): 117 117 return "Welcome!" 118 restricted = tools.check_access .enable()(restricted)118 restricted = tools.check_access()(restricted) 119 119 120 120 def err_in_onstart(self): … … 186 186 self.assertBody("True") 187 187 188 # Test the " enable" technique (compile-time decorator).188 # Test the "__call__" technique (compile-time decorator). 189 189 self.getPage("/demo/restricted") 190 190 self.assertErrorPage(401)

