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

_cptree.py (6589B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\lib\cherrypy\_cptree.py
      2 import os
      3 import cherrypy
      4 from cherrypy._cpcompat import ntou
      5 from cherrypy import _cpconfig, _cplogging, _cprequest, _cpwsgi, tools
      6 from cherrypy.lib import httputil
      7 
      8 class Application(object):
      9     root = None
     10     config = {}
     11     namespaces = _cpconfig.NamespaceSet()
     12     toolboxes = {'tools': cherrypy.tools}
     13     log = None
     14     wsgiapp = None
     15     request_class = _cprequest.Request
     16     response_class = _cprequest.Response
     17     relative_urls = False
     18 
     19     def __init__(self, root, script_name = '', config = None):
     20         self.log = _cplogging.LogManager(id(self), cherrypy.log.logger_root)
     21         self.root = root
     22         self.script_name = script_name
     23         self.wsgiapp = _cpwsgi.CPWSGIApp(self)
     24         self.namespaces = self.namespaces.copy()
     25         self.namespaces['log'] = lambda k, v: setattr(self.log, k, v)
     26         self.namespaces['wsgi'] = self.wsgiapp.namespace_handler
     27         self.config = self.__class__.config.copy()
     28         if config:
     29             self.merge(config)
     30 
     31     def __repr__(self):
     32         return '%s.%s(%r, %r)' % (self.__module__,
     33          self.__class__.__name__,
     34          self.root,
     35          self.script_name)
     36 
     37     script_name_doc = 'The URI "mount point" for this app. A mount point is that portion of\n    the URI which is constant for all URIs that are serviced by this\n    application; it does not include scheme, host, or proxy ("virtual host")\n    portions of the URI.\n    \n    For example, if script_name is "/my/cool/app", then the URL\n    "http://www.example.com/my/cool/app/page1" might be handled by a\n    "page1" method on the root object.\n    \n    The value of script_name MUST NOT end in a slash. If the script_name\n    refers to the root of the URI, it MUST be an empty string (not "/").\n    \n    If script_name is explicitly set to None, then the script_name will be\n    provided for each call from request.wsgi_environ[\'SCRIPT_NAME\'].\n    '
     38 
     39     def _get_script_name(self):
     40         if self._script_name is None:
     41             return cherrypy.serving.request.wsgi_environ['SCRIPT_NAME'].rstrip('/')
     42         return self._script_name
     43 
     44     def _set_script_name(self, value):
     45         if value:
     46             value = value.rstrip('/')
     47         self._script_name = value
     48 
     49     script_name = property(fget=_get_script_name, fset=_set_script_name, doc=script_name_doc)
     50 
     51     def merge(self, config):
     52         _cpconfig.merge(self.config, config)
     53         self.namespaces(self.config.get('/', {}))
     54 
     55     def find_config(self, path, key, default = None):
     56         trail = path or '/'
     57         while trail:
     58             nodeconf = self.config.get(trail, {})
     59             if key in nodeconf:
     60                 return nodeconf[key]
     61             lastslash = trail.rfind('/')
     62             if lastslash == -1:
     63                 break
     64             elif lastslash == 0 and trail != '/':
     65                 trail = '/'
     66             else:
     67                 trail = trail[:lastslash]
     68 
     69         return default
     70 
     71     def get_serving(self, local, remote, scheme, sproto):
     72         req = self.request_class(local, remote, scheme, sproto)
     73         req.app = self
     74         for name, toolbox in self.toolboxes.items():
     75             req.namespaces[name] = toolbox
     76 
     77         resp = self.response_class()
     78         cherrypy.serving.load(req, resp)
     79         cherrypy.engine.timeout_monitor.acquire()
     80         cherrypy.engine.publish('acquire_thread')
     81         return (req, resp)
     82 
     83     def release_serving(self):
     84         req = cherrypy.serving.request
     85         cherrypy.engine.timeout_monitor.release()
     86         try:
     87             req.close()
     88         except:
     89             cherrypy.log(traceback=True, severity=40)
     90 
     91         cherrypy.serving.clear()
     92 
     93     def __call__(self, environ, start_response):
     94         return self.wsgiapp(environ, start_response)
     95 
     96 
     97 class Tree(object):
     98     apps = {}
     99 
    100     def __init__(self):
    101         self.apps = {}
    102 
    103     def mount(self, root, script_name = '', config = None):
    104         if script_name is None:
    105             raise TypeError("The 'script_name' argument may not be None. Application objects may, however, possess a script_name of None (in order to inpect the WSGI environ for SCRIPT_NAME upon each request). You cannot mount such Applications on this Tree; you must pass them to a WSGI server interface directly.")
    106         script_name = script_name.rstrip('/')
    107         if isinstance(root, Application):
    108             app = root
    109             if script_name != '' and script_name != app.script_name:
    110                 raise ValueError('Cannot specify a different script name and pass an Application instance to cherrypy.mount')
    111             script_name = app.script_name
    112         else:
    113             app = Application(root, script_name)
    114             if script_name == '' and root is not None and not hasattr(root, 'favicon_ico'):
    115                 favicon = os.path.join(os.getcwd(), os.path.dirname(__file__), 'favicon.ico')
    116                 root.favicon_ico = tools.staticfile.handler(favicon)
    117         if config:
    118             app.merge(config)
    119         self.apps[script_name] = app
    120         return app
    121 
    122     def graft(self, wsgi_callable, script_name = ''):
    123         script_name = script_name.rstrip('/')
    124         self.apps[script_name] = wsgi_callable
    125 
    126     def script_name(self, path = None):
    127         if path is None:
    128             try:
    129                 request = cherrypy.serving.request
    130                 path = httputil.urljoin(request.script_name, request.path_info)
    131             except AttributeError:
    132                 return
    133 
    134         while True:
    135             if path in self.apps:
    136                 return path
    137             if path == '':
    138                 return
    139             path = path[:path.rfind('/')]
    140 
    141     def __call__(self, environ, start_response):
    142         env1x = environ
    143         if environ.get(ntou('wsgi.version')) == (ntou('u'), 0):
    144             env1x = _cpwsgi.downgrade_wsgi_ux_to_1x(environ)
    145         path = httputil.urljoin(env1x.get('SCRIPT_NAME', ''), env1x.get('PATH_INFO', ''))
    146         sn = self.script_name(path or '/')
    147         if sn is None:
    148             start_response('404 Not Found', [])
    149             return []
    150         app = self.apps[sn]
    151         environ = environ.copy()
    152         if environ.get(u'wsgi.version') == (u'u', 0):
    153             enc = environ[u'wsgi.url_encoding']
    154             environ[u'SCRIPT_NAME'] = sn.decode(enc)
    155             environ[u'PATH_INFO'] = path[len(sn.rstrip('/')):].decode(enc)
    156         else:
    157             environ['SCRIPT_NAME'] = sn
    158             environ['PATH_INFO'] = path[len(sn.rstrip('/')):]
    159         return app(environ, start_response)