17 Jul 2022

  • #%s1974: Dangerous characters received in a host header encoded using RFC 2047 are now elided by default. Currently, dangerous characters are defined as CR and LF. The original value is still available as cherrypy.request.headers['Host'].raw if needed.


10 Jul 2022


03 Jul 2021


17 Apr 2020


27 Nov 2019


03 Nov 2019

  • PR #%s1715: Fixed issue in cpstats where the data/ endpoint would fail with encoding errors on Python 3.
  • PR #%s1821: Simplify the passthrough of parameters to CPWebCase.getPage to cheroot. CherryPy now requires cheroot 8.2.1 or later.


02 Oct 2019

  • PR #%s1806: Support handling multiple exceptions when processing hooks as reported in #%s1770.


03 Sep 2019

  • File-based sessions no longer attempt to remove the lock files when releasing locks, instead deferring to the default behavior of zc.lockfile. Fixes #%s1391 and #%s1779.
  • PR #%s1794: Add native support for 308 Permanent Redirect usable via raise cherrypy.HTTPRedirect('/new_uri', 308).


23 Jun 2019

  • Fixed #%s1377 via PR #%s1785: Restore a native WSGI-less HTTP server support.
  • PR #%s1769: Reduce log level for non-error events in win32.py


27 Mar 2019


09 Dec 2018

  • #%s1758 via PR #%s1759: In the bus, when awaiting a state change, only publish after the state has changed.


09 Sep 2018

  • #%s1738 via PR #%s1736: Restore support for ‘bytes’ in response headers.
  • Substantial removal of Python 2 compatibility code.


01 Sep 2018

  • #%s1730: Drop support for Python 2.7. CherryPy 17 will remain an LTS release for bug and security fixes.
  • Drop support for Python 3.4.


23 Jun 2019


23 Nov 2018

  • #%s1738 via PR #%s1755: Restore support for ‘bytes’ in response headers (backport from v18.0.1).


19 Aug 2018

  • %sa95e619f: When setting Response Body, reject Unicode values, making behavior on Python 2 same as on Python 3.
  • Other inconsequential refactorings.


16 Aug 2018


14 Aug 2018


14 Aug 2018

  • #%s1694 via PR #%s1695: Add support for accepting uploaded files with non-ascii filenames per RFC 5987.


10 Jul 2018

  • #%s1673: CherryPy now allows namespace packages for its dependencies. Environments that cannot handle namespace packgaes like py2exe will need to add such support or pin to older CherryPy versions.


10 Jul 2018

  • #%s1722: Pinned the tempora dependency against version 1.13 to avoid pulling in namespace packages.


18 Jun 2018

  • #%s1716 via PR #%s1717: Fixed handling of url-encoded parameters in digest authentication handling, correcting regression in v14.2.0.
  • #%s1719 via %s1d41828: Digest-auth tool will now return a status code of 401 for when a scheme other than ‘digest’ is indicated.


16 Jun 2018

  • #%s1688 via %s38ad1da: Removed basic_auth and digest_auth tools and the httpauth module, which have been officially deprecated earlier in v14.0.0.
  • Removed deprecated properties:
    • cherrypy._cpreqbody.Entity.type deprecated in favor of cherrypy._cpreqbody.Entity.content_type
    • cherrypy._cprequest.Request.body_params deprecated in favor of cherrypy._cprequest.RequestBody.params
  • #%s1377: In _cp_native server, set req.status using bytes (fixed in PR #%s1712).
  • #%s1697 via %s841f795: Fixed error on Python 3.7 with AutoReloader when __file__ is None.
  • #%s1713 via %s15aa80d: Fix warning emitted during test run.
  • #%s1370 via %s38f199c: Fail with HTTP 400 for invalid headers.


11 May 2018

  • #%s1708: Removed components from webtest that were removed in the refactoring of cheroot.test.webtest for cheroot 6.1.0.


22 Apr 2018

  • #%s1680 via PR #%s1683: Basic Auth and Digest Auth tools now support RFC 7617 UTF-8 charset decoding where possible, using latin-1 as a fallback.


19 Apr 2018

  • Cheroot PR #%s37: Add support for peercreds lookup over UNIX domain socket. This enables app to automatically identify “who’s on the other end of the wire”.

    This is how you enable it:

    server.peercreds: True
    server.peercreds_resolve: True

    The first option will put remote numeric data to WSGI env vars: app’s PID, user’s id and group.

    Second option will resolve that into user and group names.

    To prevent expensive syscalls, data is cached on per connection basis.


22 Mar 2018

  • #%s1700: Improve windows pywin32 dependency declaration via conditional extras.


04 Feb 2018

  • #%s1688: Officially deprecated basic_auth and digest_auth tools and the httpauth module, triggering DeprecationWarnings if they’re used. Applications should instead adapt to use the more recent auth_basic and auth_digest tools. This deprecated functionality will be removed in a subsequent release soon.
  • Removed DeprecatedTool and the long-deprecated and disabled tidy and nsgmls tools. See the rationale for this change.


17 Dec 2017

  • #%s1231 via PR #%s1654: CaseInsensitiveDict now re-uses the generalized functionality from jaraco.collections to provide a more complete interface for a CaseInsensitiveDict and HeaderMap.

    Users are encouraged to use the implementation from jaraco.collections except when dealing with headers in CherryPy.


17 Dec 2017

  • PR #%s1671: Restore support for installing CherryPy into environments hostile to namespace packages, broken since the 11.1.0 release.


04 Dec 2017

  • #%s1666: Drop support for Python 3.3.


03 Dec 2017

  • #%s1665: In request processing, when an invalid cookie is received, render the actual error message reported rather than guessing (sometimes incorrectly) what error occurred.


20 Nov 2017


17 Nov 2017

  • Drop support for Python 3.1 and 3.2.

  • #%s1625: Removed response timeout and timeout monitor and related exceptions, as it not possible to interrupt a request. Servers that wish to exit a request prematurely are recommended to monitor response.time and raise an exception or otherwise act accordingly.

    Servers that previously disabled timeouts by invoking cherrypy.engine.timeout_monitor.unsubscribe() will now crash. For forward-compatibility with this release on older versions of CherryPy, disable timeouts using the config option:

    'engine.timeout_monitor.on': False,

    Or test for the presence of the timeout_monitor attribute:

    with contextlib2.suppress(AttributeError):

    Additionally, the TimeoutError exception has been removed, as it’s no longer called anywhere. If your application benefits from this Exception, please comment in the linked ticket describing the use case, and we’ll help devise a solution or bring the exception back.


  • Bump to cheroot 5.9.0.
  • cherrypy.test.webtest module is now merged with the cheroot.test.webtest module. The CherryPy name is retained for now for compatibility and will be removed eventually.


13 Nov 2017

  • cherrypy.engine.subscribe now may be called without a callback, in which case it returns a decorator expecting the callback.
  • PR #%s1656: Images are now compressed using lossless compression and consume less space.


28 Oct 2017

  • PR #%s1611: Expose default status logic for a redirect as HTTPRedirect.default_status.
  • PR #%s1615: HTTPRedirect.status is now an instance property and derived from the value in args. Although it was previously possible to set the property on an instance, and this change prevents that possibilty, CherryPy never relied on that behavior and we presume no applications depend on that interface.
  • #%s1627: Fixed issue in proxy tool where more than one port would appear in the request.base and thus in cherrypy.url.
  • PR #%s1645: Added new log format markers:
    • i holds a per-request UUID4
    • z outputs UTC time in format of RFC 3339
    • cherrypy._cprequest.Request.unique_id.uuid4 now has lazily invocable UUID4
  • #%s1646: Improve http status conversion helper.
  • PR #%s1638: Always use backslash for path separator when processing paths in staticdir.
  • #%s1190: Fix gzip, caching, and staticdir tools integration. Makes cache of gzipped content valid.
  • Requires cheroot 5.8.3 or later.
  • Also, many improvements around continuous integration and code quality checks.

This release contained an unintentional regression in environments that are hostile to namespace packages, such as Pex, Celery, and py2exe. See PR #%s1671 for details.


08 Jul 2017

  • #%s1607: Dropped support for Python 2.6.


17 May 2017

  • #%s1595: Fixed over-eager normalization of paths in cherrypy.url.


13 Mar 2017

  • Remove unintended dependency on graphviz in Python 2.6.


12 Mar 2017

  • PR #%s1580: CPWSGIServer.version now reported as CherryPy/x.y.z Cheroot/x.y.z. Bump to cheroot 5.2.0.
  • The codebase is now PEP 8 complaint, flake8 linter is enabled in TravisCI by default.
  • Max line restriction is now set to 120 for flake8 linter.
  • PEP 257 linter runs as separate allowed failure job in Travis CI.
  • A few bugs related to undeclared variables have been fixed.
  • pre-commit testing goes faster due to enabled caching.


18 Feb 2017

  • #%s1342: Fix AssertionError on shutdown.


07 Feb 2017

  • Bump to cheroot 5.1.0.
  • #%s794: Prefer setting max-age for session cookie expiration, moving MSIE hack into a function documenting its purpose.


20 Jan 2017

  • #%s1332: CherryPy now uses portend for checking and waiting on ports for startup and teardown checks. The following names are no longer present:

    • cherrypy._cpserver.client_host
    • cherrypy._cpserver.check_port
    • cherrypy._cpserver.wait_for_free_port
    • cherrypy._cpserver.wait_for_occupied_port
    • cherrypy.process.servers.check_port
    • cherrypy.process.servers.wait_for_free_port
    • cherrypy.process.servers.wait_for_occupied_port

    Use this functionality from the portend package directly.


19 Jan 2017


16 Jan 2017

  • #%s1537: Restore dependency on pywin32 for Python 3.6.


13 Jan 2017

  • PR #%s1547: Replaced cherryd distutils script with a setuptools console entry point.

    When running CherryPy in daemon mode, the forked process no longer changes directory to /. If that behavior is something on which your application relied and should rely, please file a ticket with the project.


09 Jan 2017


31 Dec 2016

  • #%s645: Setting a bind port of 0 will bind to an ephemeral port.


27 Dec 2016

  • #%s1538 and #%s1090: Removed cruft from the setup script and instead rely on include_package_data to ensure the relevant files are included in the package. Note, this change does cause LICENSE.md no longer to be included in the installed package.


26 Dec 2016

  • The pyOpenSSL support is now included on Python 3 builds, removing the last disparity between Python 2 and Python 3 in the CherryPy package. This change is one small step in consideration of #%s1399. This change also fixes RPM builds, as reported in #%s1149.


26 Dec 2016

  • #%s1532: Also release wheels for Python 2, enabling offline installation.


25 Dec 2016

  • #%s1537: Disable dependency on pypiwin32 on Python 3.6 until a viable build of pypiwin32 can be made on that Python version.


24 Dec 2016

  • Consolidated some documentation and include the more concise readme in the package long description, as found on PyPI.


23 Dec 2016

  • #%s1463: CherryPy tests are now run under pytest and invoked using tox.


16 Dec 2016

  • #%s1530: Fix the issue with TypeError being swallowed by decorated handlers.


28 Sep 2016


27 Sep 2016

  • #%s1497: Handle errors thrown by ssl_module: 'builtin' when client opens connection to HTTPS port using HTTP.
  • #%s1350: Fix regression introduced in v6.1.0 where environment construction for WSGIGateway_u0 was passing one parameter and not two.
  • Other miscellaneous fixes.


04 Sep 2016

  • #%s1473: HTTPError now also works as a context manager.
  • #%s1487: The sessions tool now accepts a storage_class parameter, which supersedes the new deprecated storage_type parameter. The storage_class should be the actual Session subclass to be used.
  • Releases now use setuptools_scm to track the release versions. Therefore, releases can be cut by simply tagging a commit in the repo. Versions numbers are now stored in exactly one place.


03 Sep 2016


02 Sep 2016

  • #%s1483: Remove Deprecated constructs:
    • cherrypy.lib.http module.
    • unrepr, modules, and attributes in cherrypy.lib.
  • PR #%s1476: Drop support for python-memcached<1.58
  • #%s1401: Handle NoSSLErrors.
  • #%s1489: In wsgiserver.WSGIGateway.respond, the application must now yield bytes and not text, as the spec requires. If text is received, it will now raise a ValueError instead of silently encoding using ISO-8859-1.
  • Removed unicode filename from the package, working around pypa/pip#3894 and pypa/setuptools#704.


25 Jul 2016

  • PR #%s1458: Implement systemd’s socket activation mechanism for CherryPy servers, based on work sponsored by Endless Computers.

    Socket Activation allows one to setup a system so that systemd will sit on a port and start services ‘on demand’ (a little bit like inetd and xinetd used to do).


24 Jul 2016

Removed the long-deprecated backward compatibility for legacy config keys in the engine. Use the config for the namespaced-plugins instead:

  • autoreload_on -> autoreload.on
  • autoreload_frequency -> autoreload.frequency
  • autoreload_match -> autoreload.match
  • reload_files -> autoreload.files
  • deadlock_poll_frequency -> timeout_monitor.frequency


24 Jul 2016

  • #%s1460: Fix KeyError in Bus.publish when signal handlers set in config.


18 Jul 2016

  • #%s1441: Added tool to automatically convert request params based on type annotations (primarily in Python 3). For example:

    def resource(self, limit: int):
        assert isinstance(limit, int)


16 Jul 2016

  • Issue #%s1411: Fix issue where autoreload fails when the host interpreter for CherryPy was launched using python -m.


14 Jul 2016

  • Combined wsgiserver2 and wsgiserver3 modules into a single module, cherrypy.wsgiserver.


23 Jun 2016


06 Jun 2016

  • Issue #%s1444: Correct typos in @cherrypy.expose decorators.


05 Jun 2016

  • Setuptools is now required to build CherryPy. Pure distutils installs are no longer supported. This change allows CherryPy to depend on other packages and re-use code from them. It’s still possible to install pre-built CherryPy packages (wheels) using pip without Setuptools.
  • six is now a requirement and subsequent requirements will be declared in the project metadata.
  • #%s1440: Back out changes from PR #%s1432 attempting to fix redirects with Unicode URLs, as it also had the unintended consequence of causing the ‘Location’ to be bytes on Python 3.
  • cherrypy.expose now works on classes.
  • cherrypy.config decorator is now used throughout the code internally.


05 Jun 2016

  • @cherrypy.expose now will also set the exposed attribute on a class.
  • Rewrote all tutorials and internal usage to prefer the decorator usage of expose rather than setting the attribute explicitly.
  • Removed test-specific code from tutorials.


05 Jun 2016

  • #%s1397: Fix for filenames with semicolons and quote characters in filenames found in headers.
  • #%s1311: Added decorator for registering tools.
  • #%s1194: Use simpler encoding rules for SCRIPT_NAME and PATH_INFO environment variables in CherryPy Tree allowing non-latin characters to pass even when wsgi.version is not u.0.
  • #%s1352: Ensure that multipart fields are decoded even when cached in a file.


10 May 2016

  • cherrypy.test.webtest.WebCase now honors a ‘WEBTEST_INTERACTIVE’ environment variable to disable interactive tests (still enabled by default). Set to ‘0’ or ‘false’ or ‘False’ to disable interactive tests.
  • #%s1408: Fix AttributeError when listiterator was accessed using the next attribute.
  • #%s748: Removed cherrypy.lib.sessions.PostgresqlSession.
  • PR #%s1432: Fix errors with redirects to Unicode URLs.


30 Apr 2016

  • #%s1202: Add support for specifying a certificate authority when serving SSL using the built-in SSL support.
  • Use ssl.create_default_context when available.
  • #%s1392: Catch platform-specific socket errors on OS X.
  • #%s1386: Fix parsing of URIs containing :// in the path part.


30 Apr 2016


  • Bugfix issue #%s1315 for test_HTTP11_pipelining test in Python 3.5
  • Bugfix issue #%s1382 regarding the keyword arguments support for Python 3 on the config file.
  • Bugfix issue #%s1406 for test_2_KeyboardInterrupt test in Python 3.5. by monkey patching the HTTPRequest given a bug on CPython that is affecting the testsuite (https://bugs.python.org/issue23377).
  • Add additional parameter raise_subcls to the tests helpers openURL and CPWebCase.getPage to have finer control on which exceptions can be raised.
  • Add support for direct keywords on the calls (e.g. foo=bar) on the config file under Python 3.
  • Add additional validation to determine if the process is running as a daemon on cherrypy.process.plugins.SignalHandler to allow the execution of the testsuite under CI tools.


  • Bugfix for NameError following #%s94.


  • Removed deprecated support for ssl_certificate and ssl_private_key attributes and implicit construction of SSL adapter on Python 2 WSGI servers.
  • Default SSL Adapter on Python 2 is the builtin SSL adapter, matching Python 3 behavior.
  • Pull request #%s94: In proxy tool, defer to Host header for resolving the base if no base is supplied.


  • Drop support for Python 2.5 and earlier.
  • No longer build Windows installers by default.


  • Pull Request #%s116: Correct InternalServerError when null bytes in static file path. Now responds with 404 instead.


  • Pull Request #%s96: Pass exc_info to logger as keyword rather than formatting the error and injecting into the message.


  • CherryPy daemon may now be invoked with python -m cherrypy in addition to the cherryd script.
  • Issue #%s1298: Fix SSL handling on CPython 2.7 with builtin SSL module and pyOpenSSL 0.14. This change will break PyPy for now.
  • Several documentation fixes.


  • Fixed HTTP range headers for negative length larger than content size.
  • Disabled universal wheel generation as wsgiserver has Python duality.
  • Pull Request #%s42: Correct TypeError in check_auth when encrypt is used.
  • Pull Request #%s59: Correct signature of HandlerWrapperTool.
  • Pull Request #%s60: Fix error in SessionAuth where login_screen was incorrectly used.
  • Issue #%s1077: Support keyword-only arguments in dispatchers (Python 3).
  • Issue #%s1019: Allow logging host name in the access log.
  • Pull Request #%s50: Fixed race condition in session cleanup.


  • Issue #%s1301: When the incoming queue is full, now reject additional connections. This functionality was added to CherryPy 3.0, but unintentionally lost in 3.1.


  • Miscellaneous quality improvements.


CherryPy adopts semver.