Release Notes¶
This project loosly follows Semantic Versioning (major.minor.patch), withthe exception that changes are allowed in minor releases as long as the changeis necessary to match documentation, specification or expectation.In other words: Bugfixes do not count as backward incompatible changes, even ifthey technically change something fromincorrect tocorrect and may breakapplications that rely onincorrect,undefined orundocumented behavior.
As long as the major version is still0.x, breaking API changes are alsoallowed in minor releases, but we try our best to provide fallbacks and emitdeprecation warnings for at least one minor release circle.
How to upgrade
Upgrade to the most recent patch release available for your current minorrelease. (e.g.
0.12.3to0.12.25)Read the release notes for the next minor release, run your tests and fix alldeprecation warnings.
Upgrade to the next minor release (e.g.
0.12.25to0.13.2), run testagain, fix all warnings and continue.
Support for old releases
Bugs and security issues are usually fixed in the latest minor release of thetwo most recent major releases (named stable and old-stable). With each new majorrelease, stable becomes old-stable and the old old-stable will no longer receiveregular updates. LTS releases (e.g. 0.12) are an exception. Those will continueto receive updates on a best-effort basis.
Release 0.14 (in development)¶
Deprecated APIs or behavior
Route.get_undecorated_callback()was able to look into closure cells to guess the original function wrapped by a decorator, but this is too aggressive in some cases and may return the wrong function. To avoid this, we will depend on proper use of@functools.wraps(orig)orfunctools.update_wrapper(wrapper,orig)in decorators in the future.
Removed APIs
Dropped support for Python 2 (EOL: 2020-01-01) and removed workarounds or helpers that only make sense in a Python 2/3 dual codebase.
Dropped support for Python 3.8 (EOL: 2024-10-07).
Removed the
RouteResetexception and associated logic.Removed thebottle.py console script entrypoint in favour of the newbottle script. You can still executebottle.py directly or viapython -m bottle. The only change is that the command installed by pip or similar tools into the bin/Scripts folder of the (virtual) environment is now calledbottle to avoid circular import errors.
Changes
Form values, query parameters, path elements and cookies are now always decoded asutf8 witherrors=’surrogateescape’. This is the correct approach for almost all modern web applications, but still allows applications to recover the original byte sequence if needed. This also means that
bottle.FormsDictno longer re-encodes PEP-3333latin1 strings toutf8 on demand (via attribute access). TheFormsDict.getunicode()andFormsDict.decode()methods are deprecated and do nothing, as all values are already transcoded toutf8.
New features
bottle.HTTPErrorraised on invalid JSON now include the underlying exception in theexceptionfield.
Release 0.13¶
Warning
This release contains breaking changers, please read the notes below
Dropped support for Python versions that reached their end-of-life.
Bottle up to 0.12 supported an absurd range of Python versions (2.5 to 3.12) andkeeping support for Python versions as ancient as 2.5 required a ton of workaroundsand compromises, but served no real purpose. If you need support for older Pythonversions, you can stay on bottle 0.12. The updated list of tested and supported pythonreleases is as follows:
Python 2 >= 2.7.3
Python 3 >= 3.8
Support for Python 2.5 was marked as deprecated since 0.12. We decided to go a step furtherand also remove support for 2.6 and 3.1 to 3.7 even if it was never deprecated explicitlyin bottle. This means that this release isnot backwards compatible in Python <2.7.3 or<3.8 environments. Maintainers for distributions or systems that still use these old pythonversions should not update to Bottle 0.13 and stick with 0.12 instead.
Stabilized APIs
The documented API of the
ConfigDictclass is now considered stable and ready to use.
Deprecated APIs
Python 2 support is now deprecated and will be dropped with the next release. This includes helpers and workarounds that only make sense in a Python 2/3 dual codebase (e.g.
tonat()or thepy3kflag).The command line executable installed along with bottle will be renamed frombottle.py to justbottle. You can still execute bottle directly as a script (e.g../bottle.py orpython3 bottle.py) or as a module (viapython3 -m bottle). Just the executable installed by your packaging tool (e.g.pip) into thebin folder of your (virtual) environment will change.
The old route syntax (
/hello/:name) is deprecated in favor of the more readable and flexible/hello/<name>syntax.Bottle.mount()now recognizes Bottle instance and will warn about parameters that are not compatible with the new mounting behavior. The old behavior (mount applications as WSGI callable) still works and is used as a fallback automatically.The undocumented
local_property()helper is now deprecated.The server adapter for google app engine is not useful anymore and marked as deprecated.
Bottle uses pickle to store arbitrary objects into signed cookies. This is safe, as long as the signature key remains a secret. Unfortunately, people tend to push code with signature keys to github all the time, so we decided to remove pickle-support from bottle. Signed cookies will now issue a deprecation warning if the value is not a string, and support for non-string values will be removed in 0.14. The global
cookie_encode(),cookie_decode()andis_cookie_encoded()are now also deprecated. If you are using this feature, think about using json to serialize your objects before storing them into cookies, or switch to a session system that stores data server-side instead of client-side.
Removed APIs (deprecated since 0.12)
Plugins with the old API (
api=1or no api attribute) will no longer work.Parameter order of
Bottle.mount()changed in 0.10. The old order will now result in an error instead of a warning.The
ConfigDictclass was introduced in 0.11 and changed during 0.12. These changes are now final.Attribute access and assignment was removed due to high overhead and limited usability.
Namespaced sub-instance creation was removed.
config["a"]["b"]has a high overhead and little benefit overconfig["a.b"].ConfigDictinstances are no longer callable. This was a shortcut forConfigDict.update().ConfigDictconstructor no longer accepts any parameters. Use theload_* methods instead.
Bottle 0.12 changed some aspects of the Simple Template Engine. These changes are now final and the old syntax will now longer work.
The magic
{{rebase()}}call was replaced by abasevariable. Example:{{base}}In STPL Templates, the
rebaseandincludekeywords were replaced with functions in 0.12.PEP-263 encoding strings are no longer recognized. Templates are always utf-8.
The ‘geventSocketIO’ server adapter was removed without notice. It did not work anyway.
Changes
These changes might require special care when updating.
Signed cookies now use a stronger HMAC algorithm by default. This will result in old cookies to appear invalid after the update. Pass an explicit
digestmod=hashlib.md5toRequest.get_cookieandResponse.set_cookieto get the old behavior.Bottle now ships with its own multipart form data parser (borrowed frommultipart) and no longer relies on
cgi.FieldStorage, which was removed in Python 3.13. This may change the way broken (non-standard) form submissions are parsed. The new parser is more strict and correct than ohe old one.Installing bottle withpip or similar tools will now install an additional command line executable namedbottle into thebin folder of your (virtual) environment. This will replace the now deprecatedbottle.py executable in a later release. See above.
Other Improvements
Bottleinstances are now context managers. If used in a with-statement, the default application changes to the specific instance and the shortcuts for many instance methods can be used.Added support for
PATCHrequests and theBottle.patch()decorator.Added command-line arguments for config from json or ini files.
Bottle.mount()now recognizes instances ofBottleand mounts them with significantly less overhead than other WSGI applications.The
Request.jsonproperty now acceptsapplication/json-rpcrequests.static_file()gained support forETagheaders. It will generate ETags and recognizesIf-None-Matchheaders.static_file()will now guess the mime type of*.gzand other compressed files correctly (e.g.application/gzip) and NOT set theContent-Encodingheader.Jinja2 templates will produce better error messages than before.
Release 0.12¶
New SimpleTemplate parser implementation
Support for multi-line code blocks (<% … %>).
The keywordsinclude andrebase are functions now and can accept variable template names.
The new
Request.routeproperty returns theRoutethat originally matched the request.Removed the
Request.MAX_PARAMSlimit. The hash collision bug in CPythons dict() implementation was fixed over a year ago. If you are still using Python 2.5 in production, consider upgrading or at least make sure that you get security fixed from your distributor.New
ConfigDictAPI (seeConfiguration)
More information can be found in thisdevelopment blog post.
Release 0.11¶
Native support for Python 2.x and 3.x syntax. No need to run 2to3 anymore.
Support for partial downloads (
Rangeheader) instatic_file().The new
ResourceManagerinterface helps locating files bundled with an application.Added a server adapter forwaitress.
New
Bottle.merge()method to install all routes from one application into another.New
Request.appproperty to get the application object that handles a request.Added
FormsDict.decode()to get an all-unicode version (needed by WTForms).MultiDictand subclasses are now pickle-able.
API Changes
Response.statusis a read-write property that can be assigned either a numeric status code or a status string with a reason phrase (200OK). The return value is now a string to better match existing APIs (WebOb, werkzeug). To be absolutely clear, you can use the read-only propertiesResponse.status_codeandResponse.status_line.
API Deprecations
SimpleTALTemplateis now deprecating. There seems to be no demand.
Release 0.10¶
Plugin API v2
To use the new API, set
Plugin.apito2.Plugin.apply()receives aRouteobject instead of a context dictionary as second parameter. The new object offers some additional information and may be extended in the future.Plugin names are considered unique now. The topmost plugin with a given name on a given route is installed, all other plugins with the same name are silently ignored.
The Request/Response Objects
Added
Request.json,Request.remote_route,Request.remote_addr,Request.queryandRequest.script_name.Added
Response.status_lineandResponse.status_codeattributes. In future releases,Response.statuswill return a string (e.g.200OK) instead of an integer to match the API of other common frameworks. To make the transition as smooth as possible, you should use the verbose attributes from now on.Replaced
MultiDictwith a specializedFormsDictin many places. The new dict implementation allows attribute access and handles unicode form values transparently.
Templates
Added three new functions to the SimpleTemplate default namespace that handle undefined variables:
stpl.defined(),stpl.get()andstpl.setdefault().The default escape function for SimpleTemplate now additionally escapes single and double quotes.
Routing
A new route syntax (e.g.
/object/<id:int>) and support for route wildcard filters.Four new wildcard filters:int,float,path andre.
Other changes
Added command line interface to load applications and start servers.
Introduced a
ConfigDictthat makes accessing configuration a lot easier (attribute access and auto-expanding namespaces).Added support for raw WSGI applications to
Bottle.mount().Bottle.mount()parameter order changed.Bottle.route()now accepts an import string for thecallbackparameter.Dropped Gunicorn 0.8 support. Current supported version is 0.13.
Added custom options to Gunicorn server.
Finally dropped support for type filters. Replace with a custom plugin of needed.
Release 0.9¶
Whats new?
A brand new plugin-API. SeeUsing Plugins andWriting Plugins for details.
The
route()decorator got a lot of new features. SeeBottle.route()for details.Support for SimpleTAL templates.
Better runtime exception handling for mako templates in debug mode.
Lots of documentation, fixes and small improvements.
A new
Request.urlpartsproperty.
Performance improvements
The
Routernow special-caseswsgi.run_onceenvironments to speed up CGI.Reduced module load time by ~30% and optimized template parser. See8ccb2d,f72a7c andb14b9a for details.
Support for “App Caching” on Google App Engine. Seeaf93ec.
Some of the rarely used or deprecated features are now plugins that avoid overhead if the feature is not used.
API changes
This release is mostly backward compatible, but some APIs are marked deprecated now and will be removed for the next release. Most noteworthy:
The
staticroute parameter is deprecated. You can escape wild-cards with a backslash.Type-based output filters are deprecated. They can easily be replaced with plugins.
Release 0.8¶
API changes
These changes may break compatibility with previous versions.
The built-in Key/Value database is not available anymore. It is marked deprecated since 0.6.4
The Route syntax and behaviour changed.
Regular expressions must be encapsulated with
#. In 0.6 all non-alphanumeric characters not present in the regular expression were allowed.Regular expressions not part of a route wildcard are escaped automatically. You don’t have to escape dots or other regular control characters anymore. In 0.6 the whole URL was interpreted as a regular expression. You can use anonymous wildcards (
/index:#(\.html)?#) to achieve a similar behaviour.
The
BreakTheBottleexception is gone. UseHTTPResponseinstead.The
SimpleTemplateengine escapes HTML special characters in{{bad_html}}expressions automatically. Use the new{{!good_html}}syntax to get old behaviour (no escaping).The
SimpleTemplateengine returns unicode strings instead of lists of byte strings.bottle.optimize()and the automatic route optimization is obsolete.Some functions and attributes were renamed:
Request._environis nowRequest.environResponse.headeris nowResponse.headersdefault_app()is obsolete. Useapp()instead.
The default
redirect()code changed from 307 to 303.Removed support for
@default. Use@error(404)instead.
New features
This is an incomplete list of new features and improved functionality.
The
Requestobject got new properties:Request.body,Request.auth,Request.url,Request.header,Request.forms,Request.files.The
Response.set_cookieandRequest.get_cookiemethods are now able to encode and decode python objects. This is called asecure cookie because the encoded values are signed and protected from changes on client side. All pickle-able data structures are allowed.The new
Routerclass drastically improves performance for setups with lots of dynamic routes and supports named routes (named route + dict = URL string).It is now possible (and recommended) to return
HTTPErrorandHTTPResponseinstances or other exception objects instead of raising them.The new function
static_file()equalssend_file()but returns aHTTPResponseorHTTPErrorinstead of raising it.send_file()is deprecated.The
SimpleTemplateengine got full unicode support.Lots of non-critical bugfixes.
