Clone wiki

CherryPy / WhatsNewIn32

What's new in CherryPy 3.2

This document only describes new features in CherryPy 3.2. A detailed "How To Upgrade" document is at UpgradeTo32.

Python 3 Support

CherryPy 3.2 runs on Python 3! You'll find separate downloadable packages, as well as a separate Subversion branch. Python 2.6 support has been improved, too, by the way.

The biggest change required for Python 3 is the switch from bytes to unicode. CherryPy 3.1 only ran on Python 2, which favored byte strings over unicode strings. But in Python 3, unicode strings are preferred. Most Request attributes are now unicode strings in Python 3.


CherryPy is now monitorable! There is a new `lib/` module that provides "tools.cpstats". Import the module and turn it on in config to start collecting statistical information about your CherryPy application. There's also a `StatsPage` class you can drop into your app to show the results. There's ''also'' new stats code in `wsgiserver`: turn it on by setting `cherrypy.server.httpserver.stats['Enabled']` to `True`. Then the statistics it gathers will automatically show up in the output of the `StatsPage` class!

In fact, you (or any other library or app) can participate in the gathering and reporting of statistics quite easily. See the [source:trunk/py2/cherrypy/lib/ cpstats docstring] for the complete spec.

Sphinx Documentation

There is a brand-new doc effort underway in the repo itself. You can read it online at, or check out the source code and help us improve it!



The FastCGI support in `cherryd` is much improved and tested, including socket file support; also, autoreload and the conflicting signal handlers are now off by default. SCGI support is also included via the `-s` option to `cherryd` (thanks georgem), and there's a new adapter for flup's CGI server (also available via the '-x' command-line arg to cherryd).

cherryd and sys.path

`cherryd` now adds the current directory to sys.path, so that modules in it can be more easily imported. There's also a new `-P` command-line option to prepend additional paths to sys.path.


We now support Python's builtin `ssl` module, in addition to the former `pyOpenSSL`, and there is an established `SSLAdapter` API for hooking up other SSL libraries.

In !CherryPy 3.1, you could tell the wsgiserver to use SSL by setting a couple of configuration entries like so:

server.ssl_certificate = <filename>
server.ssl_private_key = <filename>

If you wish to continue using pyOpenSSL in Python 2 using the syntax above, nothing has changed.

To use Python's builtin `ssl` module in Python 2 instead, add the line:

    server.ssl_module = 'builtin'

For Python 3, the builtin module is the default.

In addition, the `pyOpenSSL` adapter sports a new `context` configuration method, which you can set to an instance of `SSL.Context` for more advanced settings. See the `pyOpenSSL` documentation for all the options. It also accepts a `certificate_chain` argument, the filename of CA's intermediate certificate bundle. This is needed for cheaper "chained root" SSL certificates, and should be left as None if not required.

Open sockets are no longer inherited by child processes (thanks nicolas grilly). See #856 for more details.


`cherrypy.engine` is an instance of `cherrypy.process.wspbus.Bus`. Beginning in !CherryPy 3.2, the "state" argument to `Bus.wait(state, interval)` may be a list or tuple, instead of a single state, in order to wake up on any of several states.


Dynamic Dispatch by Controllers

To find a handler for the current request, !CherryPy's default dispatcher traverses a tree of objects and methods. Beginning in CherryPy 3.2, when a controller possesses a `_cp_dispatch(vpath)` method, !CherryPy's default dispatcher will now use its return value as the 'next hop' in the object traversal (Quixote refugees rejoice!). Returning `None` effectively stops traversal; !CherryPy will then work backward looking for a default handler as normal. In addition, the `_cp_dispatch` method is a list of remaining path segments, and the method is allowed to mutate it. For example, to handle the URI `/users/123/profile`, a `Users._cp_dispatch` method would receive a `vpath` argument of `['123', 'profile']`, at which point it could write:

def _cp_dispatch(vpath):
    if vpath:
        cherrypy.request.params['user_id'] = vpath.pop(0)
    if vpath:
        return getattr(self, vpath[0], None)


There's a new `cherrypy.popargs` function which can be used to pop path segments off into cherrypy.request.params during dispatch. This decorator may be used in one of two ways. First, as a class decorator:

    @cherrypy.popargs('year', 'month', 'day')
    class Blog:
        def index(self, year=None, month=None, day=None):
            #Process the parameters here; any url like
            #/, /2009, /2009/12, or /2009/12/31
            #will fill in the appropriate parameters.
        def create(self):
            #This link will still be available at /create.  Defined functions
            #take precedence over arguments.

...or as a member of a class:

    class Blog:
        _cp_dispatch = cherrypy.popargs('year', 'month', 'day')

Mismatched Request Params

In previous versions, unexpected URI path segments, or unexpected parameters in the query string or request body, would generally return somewhat unhelpful "500 Server Error" responses. Starting in CherryPy 3.2, when query parameters passed to a handler are incorrect, or when path segments are incorrectly passed to a handler, "404 Not Found" is returned instead. When body params are incorrectly passed to a handler, "400 Bad Request" is returned.

If `request.show_mismatched_params` is `True`, a message listing the mismatched params will be output in the 4xx response body. If `False`, the 4xx response will be empty.

In other parameter news, `multipart/*` requests that have no Content-Disposition are now passed to the handler as a 'parts' argument. See #890.


This dispatcher now includes any `_cp_config` attribute on the `GET`/`POST`/etc handler method itself.

Punctuation in URL's

Since forever, you could map dots in URL's to underscores, so that you could serve the URL '/foo.html' from a page handler like `def foo_html(self):` for example. Starting in 3.2, all punctuation is now converted to underscores for you. If you don't like that for some reason, you can define your own mapping via the new `translate` argument to `cherrypy.dispatch.Dispatcher`. See [2676] for complete details.

Request Bodies

CherryPy 3.2 has a new `_cpreqbody` module which completely replaces its use of the standard library's `cgi` module (and our `safemime` and `cpcgifs` modules, to boot). There are default processors for common content-types (including improved support for `multipart/*` types), and you can write your own custom processors! See RequestBodies for more details.


New config decorator

`cherrypy.config` can now be used as a page handler decorator. It works just like the `_cp_config` attribute; in fact, that's all it really does. But it might look better. Instead of

    def index(self):
        return "Hello world"
    index._cp_config = {'response.headers.Content-Type': 'text/plain'}

you can now write:

    @cherrypy.config(**{'response.headers.Content-Type': 'text/plain'})
    def index(self):
        return "Hello world"

...and it interacts with tools-as-decorators more safely, to boot.


Much of the basic approach to config has been isolated in its own re-usable module at `cherrypy.lib.reprconf`. This includes the `unrepr` approach to configuration (where values use Python syntax), as well as key namespaces and the ability to use dicts, filenames, or file objects.


All engine attributes may now be changed in config via the "engine.*" config namespace.

Engine plugins, whether builtin or custom, may also now be configured if they are added to the engine object itself. The builtin plugins "autoreload", "thread_manager", "signal_handler", "timeout_monitor", and "console_control_handler" are already added. The "on" config entry subscribes or unsubscribes the plugin, and all other entries are set as attributes on the plugin instance.

cherrypy.engine.my_plugin = MyPlugin(a=3, b='foo')
cherrypy.config.update({'engine.my_plugin.on': True,
                        'engine.my_plugin.a': 16})


Additional servers may now be turned on and off, and configured, via config entries in the `server.<servername>.*` namespace. The "servername" portion is arbitrary; it only matters that you use the same name for all settings for the same server. Any new name will add a new server, so that, for example, `server.2.socket_port` will start a new WSGIServer (on that port); any new server is on by default. To start a different type of server, set `server.<servername>.instance` to the server (or its class) you wish to use.


`request.query_string_encoding` is now available to declare the expected encoding of querystring paramters.


`response.headers` are now settable in config; just set `response.headers.<field-name> = <field-value>`. For example: `response.headers.Content-Type = "text/plain"`.


`cherrypy.HTTPError` now takes full reason phrases in the `status` argument. See #898.


CherryPy 3.2 is fully compliant with the new WSGI 1.0.1. See [ PEP 3333] for complete spec details.

There's a new REQUEST_URI environ entry, which equals the [ Request-URI] in the HTTP spec. Also, the SERVER_NAME entry is no longer settable by the client.

The wsgiserver is no longer hard-coded to emit WSGI 1.0; instead, it has its own internal format (which is much closer to HTTP than CGI). Just before the server calls its WSGI application, it uses a Gateway to convert its internal formats to WSGI. This means that wsgiserver can now support ''any'' version of WSGI, blessed by a given standards body or not. There's even a new 'native' gateway which doesn't use WSGI at all! CherryPy 3.2 ships with gateways for WSGI 1.0 (the long-time standard), which now includes support for WSGI 1.0.1 (see PEP 3333), and an experimental version we're calling `('u', 0)`, which uses full unicode strings for most environ keys and values.

!InternalRedirect and exception trapping have been moved out of the WSGI application adapter and into WSGI components, so you can now turn them off to be even leaner and meaner. :)


Most tools now take a `debug` configuration option. When `True`, they emit log entries to help diagnose problems in configuration.


There's a new pairs of tools for JSON: `json_in` checks the Content-Type of the request and reads the body, decoding it and placing it into `request.json`; `json_out` sets the Content-Type response header and encodes the page handler output to JSON.


The session cleanup thread can be completely disabled now by setting `tools.sessions.clean_freq` to 0 or None. This is required for Google App Engine, which does not allow the creation of new threads.

Until now, all session cookies expired according to `tools.sessions.timeout`. Starting in 3.2, if `tools.sessions.persistent` is `False`, the cookies will expire when the user closes their browser. See #870.

There's a new `tools.sessions.pickle_procotol` attribute, and the default has been changed to `pickle.HIGHEST_PROTOCOL`.


The caching tool now stores separate responses based on varying request header values (as required by the HTTP spec).

It also does antistampeding by default; that is, when one thread begins to calculate a cached response, other competing requests will wait for it to finish and then return its result.

Finally, there's more (as in "some") support for Cache-Control (and Pragma) request header values `max-age` and `no-cache`, and response header values `no-cache` and `no-store`.


`tools.autovary` keeps track of which request headers your application accesses, and auto-populates the Vary response header.


Thanks to visteya, the existing `basic_auth` and `digest_auth` tools have been supplemented with `tools.auth_basic` and `tools.auth_digest`. See #913 and #914 for all the reasons why you should switch.


The `trailing_slash` tool has a new `status` argument, to allow XmlHttpRequest's to receive 307 redirects. Defaults to 301.


The gzip tool now allows for simple pattern matching such as `text/*` or `application/*+xml` in its `mime_types` parameter.