Download Install Tutorial Docs FAQ Tools WikiLicense Team IRC Planet Involvement Shop Book

Changeset 1249

Show
Ignore:
Timestamp:
08/17/06 18:29:23
Author:
fumanchu
Message:

WSGI improvements from Christian's cp3-wsgi-remix branch:

  1. cherrypy.Application is now a WSGI callable.
  2. cherrypy.tree may now be used as a WSGI dispatcher by simply calling it. This replaces the _cpwsgi.wsgiApp function.
  3. You may now mount arbitrary WSGI apps using tree.graft(wsgi callable, script name).
  4. If you set an Application object's script_name to None, it will try to pull script_name from cherrypy.request.wsgi_environ['SCRIPT_NAME'].

There's a new test_wsgiapps.py (copied from the branch) which helps demonstrate the changes.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cherrypy/__init__.py

    r1243 r1249  
    1414import _cptree 
    1515tree = _cptree.Tree() 
     16from _cptree import Application 
    1617import _cpengine 
    1718engine = _cpengine.Engine() 
  • trunk/cherrypy/_cptree.py

    r1156 r1249  
    22import sys 
    33 
    4 from cherrypy import config 
     4import cherrypy 
     5from cherrypy import config, _cpwsgi 
    56 
    67 
    78class Application: 
    8     """A CherryPy Application.""" 
     9    """A CherryPy Application. 
     10     
     11    An instance of this class may also be used as a WSGI callable 
     12    (WSGI application object) for itself. 
     13     
     14    root: the top-most container of page handlers for this app. 
     15    script_name: the URL "mount point" for this app; for example, 
     16        if script_name is "/my/cool/app", then the URL 
     17        "http://my.domain.tld/my/cool/app/page1" might be handled 
     18        by a "page1" method on the root object. If script_name is 
     19        explicitly set to None, then CherryPy will attempt to provide 
     20        it each time from request.wsgi_environ['SCRIPT_NAME']. 
     21    conf: a dict of {path: pathconf} pairs, where 'pathconf' is itself 
     22        a dict of {key: value} pairs. 
     23    """ 
    924     
    1025    def __init__(self, root, script_name="", conf=None): 
     
    2035        if conf: 
    2136            self.merge(conf) 
     37     
     38    def _get_script_name(self): 
     39        if self._script_name is None: 
     40            # None signals that the script name should be pulled from WSGI environ. 
     41            return cherrypy.request.wsgi_environ['SCRIPT_NAME'] 
     42        return self._script_name 
     43    def _set_script_name(self, value): 
     44        self._script_name = value 
     45    script_name = property(_get_script_name, _set_script_name) 
    2246     
    2347    def merge(self, conf): 
     
    4872            host += ":%s" % port 
    4973        return scheme + host + self.script_name 
     74     
     75    def __call__(self, environ, start_response): 
     76        return _cpwsgi._wsgi_callable(environ, start_response, app=self) 
    5077 
    5178 
    5279class Tree: 
    53     """A registry of CherryPy applications, mounted at diverse points.""" 
     80    """A registry of CherryPy applications, mounted at diverse points. 
     81     
     82    An instance of this class may also be used as a WSGI callable 
     83    (WSGI application object), in which case it dispatches to all 
     84    mounted apps. 
     85    """ 
    5486     
    5587    def __init__(self): 
     
    72104         
    73105        return app 
     106     
     107    def graft(self, wsgi_callable, script_name=""): 
     108        """Mount a wsgi callable at the given script_name.""" 
     109        # Next line both 1) strips trailing slash and 2) maps "/" -> "". 
     110        script_name = script_name.rstrip("/") 
     111        self.apps[script_name] = wsgi_callable 
    74112     
    75113    def script_name(self, path=None): 
     
    110148        from cherrypy.lib import http 
    111149        return http.urljoin(script_name, path) 
     150     
     151    def __call__(self, environ, start_response): 
     152        return _cpwsgi._wsgi_callable(environ, start_response) 
    112153 
  • trunk/cherrypy/_cpwsgi.py

    r1230 r1249  
    113113            yield chunk 
    114114 
    115 def wsgiApp(environ, start_response): 
    116     """The WSGI 'application object' for CherryPy. 
    117      
    118     Use this as the same WSGI callable for all your CP apps. 
    119     """ 
    120     return _wsgi_callable(environ, start_response) 
    121  
    122 def make_app(app): 
    123     """Factory for making separate WSGI 'application objects' for each CP app. 
    124      
    125     Example: 
    126         # 'app' will be a CherryPy application object 
    127         app = cherrypy.tree.mount(Root(), "/", localconf) 
    128          
    129         # 'wsgi_app' will be a WSGI application 
    130         wsgi_app = _cpwsgi.make_app(app) 
    131     """ 
    132     def single_app(environ, start_response): 
    133         return _wsgi_callable(environ, start_response, app) 
    134     return single_app 
    135  
    136  
    137115 
    138116#                            Server components                            # 
     
    197175                         conf('server.socket_port')) 
    198176         
    199         apps = [(base, wsgiApp) for base in cherrypy.tree.apps] 
    200          
    201177        s = _cpwsgiserver.CherryPyWSGIServer 
    202         s.__init__(self, bind_addr, apps
     178        s.__init__(self, bind_addr, cherrypy.tree
    203179                   conf('server.thread_pool'), 
    204180                   conf('server.socket_host'), 
  • trunk/cherrypy/test/benchmark.py

    r1225 r1249  
    296296    PythonFixupHandler cherrypy.test.benchmark::startup_modpython 
    297297    PythonHandler modpython_gateway::handler 
    298     PythonOption wsgi.application cherrypy._cpwsgi::wsgiApp 
     298    PythonOption wsgi.application cherrypy::tree 
    299299    PythonDebug On 
    300300%s%s 
  • trunk/cherrypy/test/helper.py

    r1219 r1249  
    102102                                        args=(moduleNames, conf)) 
    103103 
     104def sync_apps(profile=False): 
     105    apps = [] 
     106    for base, app in cherrypy.tree.apps.iteritems(): 
     107        if base == "/": 
     108            base = "" 
     109        if profile: 
     110            apps.append((base, profiler.make_app(app, aggregate=False))) 
     111        else: 
     112            apps.append((base, app)) 
     113    apps.sort() 
     114    apps.reverse() 
     115    for s in cherrypy.server.httpservers: 
     116        s.mount_points = apps 
     117 
    104118def _run_test_suite_thread(moduleNames, conf): 
    105     from cherrypy import _cpwsgi 
    106119    for testmod in moduleNames: 
    107120        # Must run each module in a separate suite, 
     
    118131        # The setup functions probably mounted new apps. 
    119132        # Tell our server about them. 
    120         apps = [] 
    121         for base, app in cherrypy.tree.apps.iteritems(): 
    122             if base == "/": 
    123                 base = "" 
    124             if conf.get("profiling.on", False): 
    125                 apps.append((base, profiler.make_app(_cpwsgi.wsgiApp))) 
    126 ##                apps.append((base, profiler.make_app(_cpwsgi.wsgiApp, aggregate=True))) 
    127             else: 
    128                 apps.append((base, _cpwsgi.wsgiApp)) 
    129 ##            # We could use the following line, but it breaks test_tutorials 
    130 ##            apps.append((base, _cpwsgi.make_app(app))) 
    131         apps.sort() 
    132         apps.reverse() 
    133         for s in cherrypy.server.httpservers: 
    134             s.mount_points = apps 
     133        sync_apps(profile=conf.get("profiling.on", False)) 
    135134         
    136135        suite = CPTestLoader.loadTestsFromName(testmod) 
  • trunk/cherrypy/test/modpy.py

    r1150 r1249  
    6262PythonOption testmod %s 
    6363PythonHandler modpython_gateway::handler 
    64 PythonOption wsgi.application cherrypy._cpwsgi::wsgiApp 
     64PythonOption wsgi.application cherrypy::tree 
    6565PythonDebug On 
    6666""" 
  • trunk/cherrypy/test/test_tutorials.py

    r1209 r1249  
    2828        app.root.sessions = sessions 
    2929        app.root.traceback_setting = traceback_setting 
     30         
     31        helper.sync_apps() 
    3032    load_tut_module.exposed = True 
    3133     

Hosted by WebFaction

Log in as guest/cpguest to create tickets