Wiki

Clone wiki

CherryPy / WhatsNewIn22

What's new in CherryPy-2.2

The 2.2 release is backward-compatible. If you find that the upgrade breaks your site please let us know so that this can be fixed.

A more detailed "How To Upgrade" document is at [wiki:UpgradeTo2.2 UpgradeTo2.2].

1. Support for multiple applications within one CherryPy process 2. The sessionfilter is now more stable, especially the file backend (the use of ''session.acquire_lock'' is now better documented in the book. If your site is used in an environment where you have multiple concurrent requests from the same browser then ''acquire_lock'' should be called by methods that '''write''' to the session). 3. New [wiki:PositionalParameters positional parameters]

Changes to Filters

New Location for Standard Filters

The standard CherryPy filters have moved from cherrypy.lib.filter to cherrypy.filters. Importing from cherrypy.lib.filter is still supported in 2.2, but it is deprecated. If you are using a custom filter written for 2.1 that inherits from cherrypy.lib.filter.basefilter.BaseFilter, a warning will be raised when you start CP notifying you of the deprecated cherrypy.lib.filter location.

Loading User Defined Filters

CherryPy offers a couple different ways of integrating user defined filters into an application. There have been some slight changes in how this works from 2.1 to 2.2.

Using the _cp_filters Attribute

You can still use _cpFilterList, but it is considered deprecated in 2.2. The new special attribute is _cp_filters.

from cherrypy.filters.basefilter import BaseFilter

class MyFilter(BaseFilter):
    def before_main(self):
        print "I was called before the page handler!"

class Test(object):
    _cp_filters = [MyFilter(),]
    @cherrypy.expose
    def index(self):
        return "Hello, world!"

Using the Configuration System

The config options server.filtersRoot, server.inputFiltersDict and server.outputFiltersDict are gone. We now have two new config options:

server.input_filters = ['package.module.FilterClass',]
server.output_filters = ['package.module.FilterClass',]

The example above assumes the following directory layout:

myapp/
      package/
              __init__.py
              module.py  # contains FilterClass
...

You can also do something like the following:

from package.module import FilterClass

cherrypy.config.update({'global':{'server.input_filters':[FilterClass,]}})

Custom Servers

CherryPy 2.2 offers support for custom server instances to be passed to cherrypy.server.start(). This opens up some interesting possibilities, including the ability to wrap the CherryPy wsgiApp in WSGI middleware.

Here is an example using the !EvalExeption middleware from Paste:

"""
This is an example of a way to use WSGI middleware with
CherryPy 2.2.

This example requires EvalException from Paste.
"""

import sys

import cherrypy
from cherrypy._cpwsgi import wsgiApp, CPHTTPRequest
from cherrypy._cpwsgiserver import CherryPyWSGIServer

from paste.evalexception.middleware import EvalException

# we need a WSGI server class that accepts a WSGI application
# as a parameter to its constructor - here is an example

class SimpleWSGIServer(CherryPyWSGIServer):
    """A WSGI server that accepts a WSGI application as a parameter."""
    RequestHandlerClass = CPHTTPRequest
    
    def __init__(self, wsgi_app):
        conf = cherrypy.config.get
        bind_addr = (conf("server.socket_host"), conf("server.socket_port"))
        CherryPyWSGIServer.__init__(self, bind_addr, wsgi_app,
                                    conf("server.thread_pool"),
                                    conf("server.socket_host"),
                                    request_queue_size = conf("server.socket_queue_size"),
                                    )


# here is a sample CherryPy root class
# we are using exception catching middleware in this example,
# so the "problem" page handler purposely generates an error
# to demonstrate the middleware

class Root(object):
    @cherrypy.expose
    def index(self):
        yield "Get in <a href='/problem'>trouble</a><br>"
        yield cherrypy.request.browser_url + '<br>'
        yield cherrypy.request.path + '<br>'
        yield cherrypy.request.object_path + '<br>'

    @cherrypy.expose
    def problem(self):
        "error on purpose to show off EvalException"
        assert 0, "Houston, we have a problem."

# we need this so that errors trickle down to the middleware
cherrypy.config.update({'server.throw_errors':True})

# mount our CherryPy
cherrypy.root = Root()

# wrap the CP wsgiApp in the middleware
app = EvalException(wsgiApp, global_conf={})

# init the custom server with the middleware
mw_server = SimpleWSGIServer(app)

# start CherryPy with the custom server
cherrypy.server.start(server=mw_server)

Updated