NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

_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