_cptools.py (10969B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\cherrypy\_cptools.py 2 import sys 3 import warnings 4 import cherrypy 5 6 def _getargs(func): 7 import types 8 if sys.version_info >= (3, 0): 9 if isinstance(func, types.MethodType): 10 func = func.__func__ 11 co = func.__code__ 12 else: 13 if isinstance(func, types.MethodType): 14 func = func.im_func 15 co = func.func_code 16 return co.co_varnames[:co.co_argcount] 17 18 19 _attr_error = 'CherryPy Tools cannot be turned on directly. Instead, turn them on via config, or use them as decorators on your page handlers.' 20 21 class Tool(object): 22 namespace = 'tools' 23 24 def __init__(self, point, callable, name = None, priority = 50): 25 self._point = point 26 self.callable = callable 27 self._name = name 28 self._priority = priority 29 self.__doc__ = self.callable.__doc__ 30 self._setargs() 31 32 def _get_on(self): 33 raise AttributeError(_attr_error) 34 35 def _set_on(self, value): 36 raise AttributeError(_attr_error) 37 38 on = property(_get_on, _set_on) 39 40 def _setargs(self): 41 try: 42 for arg in _getargs(self.callable): 43 setattr(self, arg, None) 44 45 except (TypeError, AttributeError): 46 if hasattr(self.callable, '__call__'): 47 for arg in _getargs(self.callable.__call__): 48 setattr(self, arg, None) 49 50 except NotImplementedError: 51 pass 52 except IndexError: 53 pass 54 55 def _merged_args(self, d = None): 56 if d: 57 conf = d.copy() 58 else: 59 conf = {} 60 tm = cherrypy.serving.request.toolmaps[self.namespace] 61 if self._name in tm: 62 conf.update(tm[self._name]) 63 if 'on' in conf: 64 del conf['on'] 65 return conf 66 67 def __call__(self, *args, **kwargs): 68 if args: 69 raise TypeError('The %r Tool does not accept positional arguments; you must use keyword arguments.' % self._name) 70 71 def tool_decorator(f): 72 if not hasattr(f, '_cp_config'): 73 f._cp_config = {} 74 subspace = self.namespace + '.' + self._name + '.' 75 f._cp_config[subspace + 'on'] = True 76 for k, v in kwargs.items(): 77 f._cp_config[subspace + k] = v 78 79 return f 80 81 return tool_decorator 82 83 def _setup(self): 84 conf = self._merged_args() 85 p = conf.pop('priority', None) 86 if p is None: 87 p = getattr(self.callable, 'priority', self._priority) 88 cherrypy.serving.request.hooks.attach(self._point, self.callable, priority=p, **conf) 89 90 91 class HandlerTool(Tool): 92 93 def __init__(self, callable, name = None): 94 Tool.__init__(self, 'before_handler', callable, name) 95 96 def handler(self, *args, **kwargs): 97 98 def handle_func(*a, **kw): 99 handled = self.callable(*args, **self._merged_args(kwargs)) 100 if not handled: 101 raise cherrypy.NotFound() 102 return cherrypy.serving.response.body 103 104 handle_func.exposed = True 105 return handle_func 106 107 def _wrapper(self, **kwargs): 108 if self.callable(**kwargs): 109 cherrypy.serving.request.handler = None 110 111 def _setup(self): 112 conf = self._merged_args() 113 p = conf.pop('priority', None) 114 if p is None: 115 p = getattr(self.callable, 'priority', self._priority) 116 cherrypy.serving.request.hooks.attach(self._point, self._wrapper, priority=p, **conf) 117 118 119 class HandlerWrapperTool(Tool): 120 121 def __init__(self, newhandler, point = 'before_handler', name = None, priority = 50): 122 self.newhandler = newhandler 123 self._point = point 124 self._name = name 125 self._priority = priority 126 127 def callable(self, debug = False): 128 innerfunc = cherrypy.serving.request.handler 129 130 def wrap(*args, **kwargs): 131 return self.newhandler(innerfunc, *args, **kwargs) 132 133 cherrypy.serving.request.handler = wrap 134 135 136 class ErrorTool(Tool): 137 138 def __init__(self, callable, name = None): 139 Tool.__init__(self, None, callable, name) 140 141 def _wrapper(self): 142 self.callable(**self._merged_args()) 143 144 def _setup(self): 145 cherrypy.serving.request.error_response = self._wrapper 146 147 148 from cherrypy.lib import cptools, encoding, auth, static, jsontools 149 from cherrypy.lib import sessions as _sessions, xmlrpc as _xmlrpc 150 from cherrypy.lib import caching as _caching 151 from cherrypy.lib import auth_basic, auth_digest 152 153 class SessionTool(Tool): 154 155 def __init__(self): 156 Tool.__init__(self, 'before_request_body', _sessions.init) 157 158 def _lock_session(self): 159 cherrypy.serving.session.acquire_lock() 160 161 def _setup(self): 162 hooks = cherrypy.serving.request.hooks 163 conf = self._merged_args() 164 p = conf.pop('priority', None) 165 if p is None: 166 p = getattr(self.callable, 'priority', self._priority) 167 hooks.attach(self._point, self.callable, priority=p, **conf) 168 locking = conf.pop('locking', 'implicit') 169 if locking == 'implicit': 170 hooks.attach('before_handler', self._lock_session) 171 elif locking == 'early': 172 hooks.attach('before_request_body', self._lock_session, priority=60) 173 hooks.attach('before_finalize', _sessions.save) 174 hooks.attach('on_end_request', _sessions.close) 175 176 def regenerate(self): 177 sess = cherrypy.serving.session 178 sess.regenerate() 179 conf = dict([ (k, v) for k, v in self._merged_args().items() if k in ('path', 'path_header', 'name', 'timeout', 'domain', 'secure') ]) 180 _sessions.set_response_cookie(**conf) 181 182 183 class XMLRPCController(object): 184 _cp_config = {'tools.xmlrpc.on': True} 185 186 def default(self, *vpath, **params): 187 rpcparams, rpcmethod = _xmlrpc.process_body() 188 subhandler = self 189 for attr in str(rpcmethod).split('.'): 190 subhandler = getattr(subhandler, attr, None) 191 192 if subhandler and getattr(subhandler, 'exposed', False): 193 body = subhandler(*(vpath + rpcparams), **params) 194 else: 195 raise Exception('method "%s" is not supported' % attr) 196 conf = cherrypy.serving.request.toolmaps['tools'].get('xmlrpc', {}) 197 _xmlrpc.respond(body, conf.get('encoding', 'utf-8'), conf.get('allow_none', 0)) 198 return cherrypy.serving.response.body 199 200 default.exposed = True 201 202 203 class SessionAuthTool(HandlerTool): 204 205 def _setargs(self): 206 for name in dir(cptools.SessionAuth): 207 if not name.startswith('__'): 208 setattr(self, name, None) 209 210 211 class CachingTool(Tool): 212 213 def _wrapper(self, **kwargs): 214 request = cherrypy.serving.request 215 if _caching.get(**kwargs): 216 request.handler = None 217 elif request.cacheable: 218 request.hooks.attach('before_finalize', _caching.tee_output, priority=90) 219 220 _wrapper.priority = 20 221 222 def _setup(self): 223 conf = self._merged_args() 224 p = conf.pop('priority', None) 225 cherrypy.serving.request.hooks.attach('before_handler', self._wrapper, priority=p, **conf) 226 227 228 class Toolbox(object): 229 230 def __init__(self, namespace): 231 self.namespace = namespace 232 233 def __setattr__(self, name, value): 234 if isinstance(value, Tool): 235 if value._name is None: 236 value._name = name 237 value.namespace = self.namespace 238 object.__setattr__(self, name, value) 239 240 def __enter__(self): 241 cherrypy.serving.request.toolmaps[self.namespace] = map = {} 242 243 def populate(k, v): 244 toolname, arg = k.split('.', 1) 245 bucket = map.setdefault(toolname, {}) 246 bucket[arg] = v 247 248 return populate 249 250 def __exit__(self, exc_type, exc_val, exc_tb): 251 map = cherrypy.serving.request.toolmaps.get(self.namespace) 252 if map: 253 for name, settings in map.items(): 254 if settings.get('on', False): 255 tool = getattr(self, name) 256 tool._setup() 257 258 259 class DeprecatedTool(Tool): 260 _name = None 261 warnmsg = 'This Tool is deprecated.' 262 263 def __init__(self, point, warnmsg = None): 264 self.point = point 265 if warnmsg is not None: 266 self.warnmsg = warnmsg 267 268 def __call__(self, *args, **kwargs): 269 warnings.warn(self.warnmsg) 270 271 def tool_decorator(f): 272 return f 273 274 return tool_decorator 275 276 def _setup(self): 277 warnings.warn(self.warnmsg) 278 279 280 default_toolbox = _d = Toolbox('tools') 281 _d.session_auth = SessionAuthTool(cptools.session_auth) 282 _d.allow = Tool('on_start_resource', cptools.allow) 283 _d.proxy = Tool('before_request_body', cptools.proxy, priority=30) 284 _d.response_headers = Tool('on_start_resource', cptools.response_headers) 285 _d.log_tracebacks = Tool('before_error_response', cptools.log_traceback) 286 _d.log_headers = Tool('before_error_response', cptools.log_request_headers) 287 _d.log_hooks = Tool('on_end_request', cptools.log_hooks, priority=100) 288 _d.err_redirect = ErrorTool(cptools.redirect) 289 _d.etags = Tool('before_finalize', cptools.validate_etags, priority=75) 290 _d.decode = Tool('before_request_body', encoding.decode) 291 _d.encode = Tool('before_handler', encoding.ResponseEncoder, priority=70) 292 _d.gzip = Tool('before_finalize', encoding.gzip, priority=80) 293 _d.staticdir = HandlerTool(static.staticdir) 294 _d.staticfile = HandlerTool(static.staticfile) 295 _d.sessions = SessionTool() 296 _d.xmlrpc = ErrorTool(_xmlrpc.on_error) 297 _d.caching = CachingTool('before_handler', _caching.get, 'caching') 298 _d.expires = Tool('before_finalize', _caching.expires) 299 _d.tidy = DeprecatedTool('before_finalize', 'The tidy tool has been removed from the standard distribution of CherryPy. The most recent version can be found at http://tools.cherrypy.org/browser.') 300 _d.nsgmls = DeprecatedTool('before_finalize', 'The nsgmls tool has been removed from the standard distribution of CherryPy. The most recent version can be found at http://tools.cherrypy.org/browser.') 301 _d.ignore_headers = Tool('before_request_body', cptools.ignore_headers) 302 _d.referer = Tool('before_request_body', cptools.referer) 303 _d.basic_auth = Tool('on_start_resource', auth.basic_auth) 304 _d.digest_auth = Tool('on_start_resource', auth.digest_auth) 305 _d.trailing_slash = Tool('before_handler', cptools.trailing_slash, priority=60) 306 _d.flatten = Tool('before_finalize', cptools.flatten) 307 _d.accept = Tool('on_start_resource', cptools.accept) 308 _d.redirect = Tool('on_start_resource', cptools.redirect) 309 _d.autovary = Tool('on_start_resource', cptools.autovary, priority=0) 310 _d.json_in = Tool('before_request_body', jsontools.json_in, priority=30) 311 _d.json_out = Tool('before_handler', jsontools.json_out, priority=30) 312 _d.auth_basic = Tool('before_handler', auth_basic.basic_auth, priority=1) 313 _d.auth_digest = Tool('before_handler', auth_digest.digest_auth, priority=1) 314 del _d 315 del cptools 316 del encoding 317 del auth 318 del static