## File: docs/plugins/dev.rst

.. currentmodule:: bottle

.. _plugindev:

===============
Writing Plugins
===============

This guide explains the plugin API and how to write custom plugins. I suggest reading :ref:`plugin-basics` first if you have not done so already. You might also want to have a look at the :doc:`/plugins/index` for some practical examples.

Plugin API
==========

Any callable that accepts a function and returns a function is a valid plugin. This simple approach has its limits, though. Plugins that need more context and control can implement the extended :class:`Plugin` interface and hook into advanced features. Note that this is not a real class you can import from :mod:`bottle`, just a contract that plugins must implement to be recognized as extended plugins.

.. class:: Plugin

    Plugins must be callable or implement :meth:`apply`. If :meth:`apply` is defined, it is always preferred over calling the plugin directly. All other methods and attributes are optional.

    .. attribute:: name

        Both :meth:`Bottle.uninstall` and the `skip` parameter of :meth:`Bottle.route()` accept a name string to refer to a plugin or plugin type. This works only for plugins that have a name attribute.

    .. attribute:: api

        The Plugin API is still evolving. This integer attribute tells bottle which version to use. If it is missing, bottle defaults to the first version. The current version is ``2``. See :ref:`plugin-changelog` for details.

    .. method:: setup(self, app: Bottle)

        Called as soon as the plugin is installed to an application via :meth:`Bottle.install`. The only parameter is the application object the plugin is installed to. This method is *not* called for plugins that were applied to routes via `apply`, but only for plugins installed to an application.

    .. method:: __call__(self, callback)

        As long as :meth:`apply` is not defined, the plugin itself is used as a decorator and applied directly to each route callback. The only parameter is the callback to be decorated. Whatever is returned by this method replaces the original callback. If there is no need to wrap or replace a given callback, just return the unmodified callback parameter.

    .. method:: apply(self, callback, route: Route)

        If defined, this method is used in favor of :meth:`__call__` to decorate route callbacks. The additional `route` parameter is an instance of :class:`Route` and provides a lot of context and meta-information and about the route to be decorated. See :ref:`route-context` for details.

    .. method:: close(self)

        Called as soon as the plugin is uninstalled or the application is closed (see :meth:`Bottle.uninstall` or :meth:`Bottle.close`). This method is *not* called for plugins that were applied to routes via `apply`, but only for plugins installed to an application.


.. _plugin-changelog:

Plugin API Versions
-------------------

The Plugin API is still evolving and changed with Bottle 0.10 to address certain issues with the route context dictionary. To ensure backwards compatibility with 0.9 Plugins, we added an optional :attr:`Plugin.api` attribute to tell bottle which API to use. The API differences are summarized here.

* **Bottle 0.9 API 1** (:attr:`Plugin.api` not present)

  * Original Plugin API as described in the 0.9 docs.

* **Bottle 0.10 API 2** (:attr:`Plugin.api` equals 2)

  * The `context` parameter of the :meth:`Plugin.apply` method is now an instance of :class:`Route` instead of a context dictionary.


.. _route-context:

The Route Context
=================

The :class:`Route` instance passed to :meth:`Plugin.apply` provides detailed information about the to-be-decorated route, the original route callback and route specific configuration.

Keep in mind that :attr:`Route.config` is local to the route, but shared between all plugins. It is always a good idea to add a unique prefix or, if your plugin needs a lot of configuration, store it in a separate namespace within the `config` dictionary. This helps to avoid naming collisions between plugins.

While some :class:`Route` attributes are mutable, changes may have unwanted effects on other plugins and also only affect plugins that were not applied yet. If you need to make changes to the route that are recognized by all plugins, call :meth:`Route.reset` afterwards. This will clear the route cache and apply all plugins again next time the route is called, giving all plugins a chance to adapt to the new config. The router is not updated, however. Changes to `rule` or `method` values have no effect on the router, only on plugins. This may change in the future.


Runtime optimizations
=====================

Once all plugins are applied to a route, the wrapped route callback is cached to speed up subsequent requests. If the behavior of your plugin depends on configuration, and you want to be able to change that configuration at runtime, you need to read the configuration on each request. Easy enough.

For performance reasons however, it might be worthwhile to return a different wrapper based on current needs, work with closures, or enable or disable a plugin at runtime. Let's take the built-in ``HooksPlugin`` as an example: If no hooks are installed, the plugin removes itself from all routes and has virtually no overhead. As soon as you install the first hook, the plugin activates itself and takes effect again.

To achieve this, you need control over the callback cache: :meth:`Route.reset` clears the cache for a single route and :meth:`Bottle.reset` clears all caches for all routes of an application at once. On the next request, all plugins are re-applied to the route as if it were requested for the first time.


Common patterns
===============

.. rubric:: Dependency or resource injection

Plugins may checks if the callback accepts a specific keyboard parameter and only apply themselves if that parameter is present. For example, route callbacks that expect a ``db`` keyword argument need a database connection. Routes that do not expect such a parameter can be skipped and not decorated. The paramneter name should be configurable to avoid conflicts with other plugins or route parameters.

.. rubric:: Request context properties

Plugins may add new request-local properties to the current :data:`request`, for example ``request.session`` for a durable session or ``request.user`` for logged in users. See :class:`Request.__setattr__ `.

.. rubric:: Response type mapping

Plugins may check the return value of the wrapped callback and transform or serialize the output to a new type. The bundled :class:`JsonPlugin` does exactly that.

.. rubric:: Zero overhead plugins

Plugins that are not needed on a specific route should return the callback unchanged. If they want to remove themselves from a route at runtime, they can call :meth:`Route.reset` and skip the route the next time it is triggered.

.. rubric:: Before / after each request

Plugins can be a convenient alternative to ``before_request`` or ``after_request`` hooks (see :meth:`Bottle.add_hook`), especially if both are needed. 


Plugin Example: SQLitePlugin
============================

This plugin provides an sqlite3 database connection handle as an additional keyword argument to wrapped callbacks, but only if the callback expects it. If not, the route is ignored and no overhead is added. The wrapper does not affect the return value, but handles plugin-related exceptions properly. :meth:`Plugin.setup` is used to inspect the application and search for conflicting plugins.

::

    import sqlite3
    import inspect

    class SQLitePlugin:

        name = 'sqlite'
        api = 2

        def __init__(self,
                     dbfile=':memory:',
                     autocommit=True,
                     dictrows=True,
                     keyword='db'):
             self.dbfile = dbfile
             self.autocommit = autocommit
             self.dictrows = dictrows
             self.keyword = keyword

        def setup(self, app):
            ''' Make sure that other installed plugins don't affect the same
                keyword argument.'''
            for other in app.plugins:
                if not isinstance(other, SQLitePlugin): continue
                if other.keyword == self.keyword:
                    raise PluginError("Found another sqlite plugin with "\
                    "conflicting settings (non-unique keyword).")

        def apply(self, callback, route):
            # Override global configuration with route-specific values.
            conf = route.config.get('sqlite') or {}
            dbfile = conf.get('dbfile', self.dbfile)
            autocommit = conf.get('autocommit', self.autocommit)
            dictrows = conf.get('dictrows', self.dictrows)
            keyword = conf.get('keyword', self.keyword)

            # Test if the original callback accepts a 'db' keyword.
            # Ignore it if it does not need a database handle.
            args = inspect.getargspec(route.callback)[0]
            if keyword not in args:
                return callback

            def wrapper(*args, **kwargs):
                # Connect to the database
                db = sqlite3.connect(dbfile)
                # This enables column access by name: row['column_name']
                if dictrows: db.row_factory = sqlite3.Row
                # Add the connection handle as a keyword argument.
                kwargs[keyword] = db

                try:
                    rv = callback(*args, **kwargs)
                    if autocommit: db.commit()
                except sqlite3.IntegrityError, e:
                    db.rollback()
                    raise HTTPError(500, "Database Error", e)
                finally:
                    db.close()
                return rv

            # Replace the route callback with the wrapped one.
            return wrapper

This plugin is just an example, but actually usable::

    sqlite = SQLitePlugin(dbfile='/tmp/test.db')
    bottle.install(sqlite)

    @route('/show/')
    def show(page, db):
        row = db.execute('SELECT * from pages where name=?', page).fetchone()
        if row:
            return template('showpage', page=row)
        return HTTPError(404, "Page not found")

    @route('/static/<fname:path>')
    def static(fname):
        return static_file(fname, root='/some/path')

    @route('/admin/set/<db:re:[a-zA-Z]+>', skip=[sqlite])
    def change_dbfile(db):
        sqlite.dbfile = '/tmp/%s.db' % db
        return "Switched DB to %s.db" % db

The first route needs a database connection and tells the plugin to create a handle by accepting a ``db`` keyword argument. The second route does not need a database and is therefore ignored by the plugin. The third route does expect a 'db' keyword argument, but explicitly skips the sqlite plugin. This way the argument is not overruled by the plugin and still contains the value of the same-named url argument.

---

## File: docs/plugins/index.rst

.. currentmodule:: bottle

.. _plugins:

=============
Using Plugins
=============

.. versionadded:: 0.9

Bottle's core features cover most common use-cases, but as a micro-framework it has its limits. This is where "Plugins" come into play. Plugins add missing functionality to the framework, integrate third party libraries, or just automate some repetitive work.

We have a growing list of :doc:`/plugins/list` and most plugins are designed to be portable and re-usable across applications. Maybe your problem has already been solved and a ready-to-use plugin exists. If not, write your own. See :doc:`/plugins/dev` for details.

.. _plugin-basics:

Plugin Basics
=============

Bottles Plugin system builds on the concept of `decorators <https://docs.python.org/glossary.html#term-decorator>`_. To put it briefly, a plugin is a decorator applied to all route callback in an application. Plugins can do more than just decorating route callbacks, but it is still a good starting point to understand the concept. Lets have a look at a practical example::

    from bottle import response

    def stopwatch(callback):
        def wrapper(*args, **kwargs):
            start = time.time()
            result = callback(*args, **kwargs)
            end = time.time()
            response.headers['X-Exec-Time'] = str(end - start)
            return result
        return wrapper

This "stopwatch" decorator measures the execution time of the wrapped function and then writes the result in the non-standard ``X-Exec-Time`` response header. You could just manually apply this decorator to all your route callbacks and call it a day::
    
    from bottle import route

    @route("/timed")
    @stopwatch  # <-- This works, but do not do this
    def timed():
        time.sleep(1)
        return "DONE"

But we wouldn't be talking about a plugin system if there wasn't a better way to do this!

Managing Plugins
================

Explicitly applying decorators to every single route in a growing application quickly becomes tedious and error-prone. If you really want to apply something to *all* routes, there is a simpler way::

    from bottle import route, install

    install(stopwatch)

    @route("/timed")
    def timed():
        ...

The :func:`install` method registries a plugin to be automatically applied to all routes in an application. It does not matter if you call :func:`install` before or after binding routes, all plugins are always applied to all routes. The order of :func:`install` calls is important though. If there are multiple plugins, they are applied in the same order the were installed.

Any callable object that works as a route callback decorator is a valid plugin. This includes normal decorators, classes, callables instances, but also plugins that implement the extended :class:`Plugin` API. See :ref:`plugindev` for details. 

You can also :func:`uninstall` a previously installed plugin by name, class or instance::

    sqlite_plugin = SQLitePlugin(dbfile='/tmp/test.db')
    install(sqlite_plugin)

    uninstall(sqlite_plugin) # uninstall a specific plugin
    uninstall(SQLitePlugin)  # uninstall all plugins of that type
    uninstall('sqlite')      # uninstall all plugins with that name
    uninstall(True)          # uninstall all plugins at once

Plugins can be installed and also removed at any time, even at runtime while serving requests. They are applied on-demand, that is, as soon as the route is requested for the first time. This enables some neat tricks (e.g. installing slow debugging or profiling plugins only when needed) but should not be overused. Each time the list of plugins changes, the route cache is flushed and all plugins need to be re-applied.

.. note::
    The module-level :func:`install` and :func:`uninstall` functions affect the :ref:`default application <default-app>`. To manage plugins for a specific application, use the corresponding methods on a :class:`Bottle` instance.

Selectively apply or skip Plugins
---------------------------------

Most plugins are smart enough to ignore routes that do not need their functionality and do not add any overhead to those routes, but you can also apply or skip specific plugins per route if you need to.

To apply a decorator or plugin to just a single route, do not :func:`install` it, but use the ``apply`` keyword of the :func:`route` decorator instead::

    @route('/timed', apply=[stopwatch])
    def timed():
        ...

Route-level plugins are applied first (before application-wide plugins) but handled exactly like normal plugins otherwise.

You can also explicitly disable an installed plugin for a number of routes. The :func:`route` decorator has a ``skip`` parameter for this purpose::

    install(stopwatch)

    @route('/notime', skip=[stopwatch])
    def no_time():
        pass

The ``skip`` parameter accepts a single value or a list of values. You can use a plugin name, class or instance to identify the plugin that should be skipped. Set ``skip=True`` to skip all plugins at once.


Plugins and :meth:`Bottle.mount`
--------------------------------

Most plugins are specific to the application they were installed to and should not affect sub-applications mounted with :meth:`Bottle.mount`. Here is an example::

    root = Bottle()
    root.install(plugins.WTForms())
    root.mount('/blog', apps.blog)

    @root.route('/contact')
    def contact():
        return template('contact', email='contact@example.com')

When mounting an application, Bottle creates a proxy-route on the mounting application that forwards all requests to the mounted application. Plugins are disabled for this kind of proxy-route by default. Our (fictional) ``WTForms`` plugin affects the ``/contact`` route, but does not affect the routes of the ``/blog`` sub-application.

This behavior is intended as a sane default, but can be overridden. The following example re-activates all plugins for a specific proxy-route::

    root.mount('/blog', apps.blog, skip=None)

Note that a plugin sees the whole sub-application as a single route, namely the proxy-route mentioned above. To wrap each individual route of the sub-application, you have to install the plugin to the mounted application directly.

Configuring Plugins
===================

Most plugins accept configuration as parameters passed to their constructor. This is the easiest and most obvious way to configure a plugin, e.g. to tell a database plugin which database to connect to::

    install(SQLitePlugin(dbfile='/tmp/test.db', ...))

Newer plugins may also read values from :attr:`Bottle.config` (see :doc:`../configuration`). This is useful for configuration that should be easy to change or override for a specific deployment. This pattern even supports runtime changes using :ref:`config hooks <conf-hook>`::

    app.config["sqlite.db"] = '/tmp/test.db'
    app.install(SQLitePlugin())

Plugins can also inspect the routes they are applied to and change their behavior for individual routes. Plugin authors have full access to the undecorated route callback as well as parameters passed to the :meth:`route` decorator, including custom parameters that are otherwise ignored by bottle. This allows for a great level of flexibility. Common patterns include:

* A database plugin may automatically start a transaction if the route callback accepts a ``db`` keyword.
* A forms plugin may ignore routes that do not listen to ``POST`` requests.
* An access control plugin may check for a custom ``roles_allowed`` parameter passed to the :meth:`route` decorator.

In any case, check the plugin documentation for details. If you want to write your own plugins, check out :doc:`dev`.

---

## File: docs/plugins/list.rst

.. currentmodule:: bottle

=========================
3rd Party Plugins
=========================

This is a list of third-party plugins that add extend Bottles core functionality or integrate other libraries with the Bottle framework.

Have a look at :ref:`plugins` for general questions about plugins (installation, usage). If you plan to develop a new plugin, the :ref:`plugindev` may help you.

`Bottle-Beaker <https://pypi.python.org/pypi/bottle-beaker/>`_
    Beaker to session and caching library with WSGI Middleware

`Bottle-Cork <https://pypi.org/project/bottle-cork/>`_
	Cork provides a simple set of methods to implement Authentication and Authorization in web applications based on Bottle.

`Bottle-Cors-plugin <https://pypi.org/project/bottle-cors-plugin/>`_
	Cors-plugin is the easiest way to implement cors on your bottle web application

`Bottle-Extras <https://pypi.python.org/pypi/bottle-extras/>`_
	Meta package to install the bottle plugin collection.

`Bottle-Flash <https://pypi.python.org/pypi/bottle-flash/>`_
	flash plugin for bottle

`Bottle-Hotqueue <https://pypi.python.org/pypi/bottle-hotqueue/>`_
	FIFO Queue for Bottle built upon redis

`Macaron <https://nobrin.github.com/macaron/webapp.html>`_
	Macaron is an object-relational mapper (ORM) for SQLite.

`Bottle-Memcache <https://pypi.python.org/pypi/bottle-memcache/>`_
	Memcache integration for Bottle.

`Bottle-Mongo <https://pypi.python.org/pypi/bottle-mongo/>`_
	MongoDB integration for Bottle

`Bottle-OAuthlib <https://pypi.python.org/pypi/bottle-oauthlib/>`_
	Adapter for oauthlib - create your own OAuth2.0 implementation

`Bottle-Redis <https://pypi.python.org/pypi/bottle-redis/>`_
	Redis integration for Bottle.

`Bottle-Renderer <https://pypi.python.org/pypi/bottle-renderer/>`_
	Renderer plugin for bottle

`Bottle-Servefiles <https://pypi.python.org/pypi/bottle-servefiles/>`_
	A reusable app that serves static files for bottle apps

`Bottle-Sqlalchemy <https://pypi.python.org/pypi/bottle-sqlalchemy/>`_
	SQLAlchemy integration for Bottle.

`Bottle-Sqlite <https://pypi.python.org/pypi/bottle-sqlite/>`_
	SQLite3 database integration for Bottle.

`Bottle-Web2pydal <https://pypi.python.org/pypi/bottle-web2pydal/>`_
	Web2py Dal integration for Bottle.

`Bottle-Werkzeug <https://pypi.python.org/pypi/bottle-werkzeug/>`_
	Integrates the `werkzeug` library (alternative request and response objects, advanced debugging middleware and more).

`bottle-smart-filters <https://github.com/agile4you/bottle-smart-filters/>`_
	Bottle Querystring smart guessing.

`bottle-jwt <https://github.com/agile4you/bottle-jwt/>`_
	JSON Web Token authentication plugin for bottle.py

`bottlejwt <https://github.com/agalera/bottlejwt>`_
	JWT integration for bottle

`canister <https://github.com/dagnelies/canister>`_
	a bottle wrapper to provide logging, sessions and authentication

`bottle-cerberus <https://github.com/agalera/bottle-cerberus>`_
	Cerberus integration for bottle

`Bottle-errorsrest <https://github.com/agalera/bottle-errorsrest>`_
	All errors generated from bottle are returned in json

`Bottle-tools <https://github.com/theSage21/bottle-tools>`_
	Decorators that auto-supply function arguments using POST/query string data.


Plugins listed here are not part of Bottle or the Bottle project, but developed and maintained by third parties.

---

## File: docs/api.rst

==============================
API Reference
==============================

.. module:: bottle
   :platform: Unix, Windows
   :synopsis: WSGI micro framework
.. moduleauthor:: Marcel Hellkamp <marc@gsites.de>

Bottle prides itself on having source code that is easy to read and follow, so most questions about APIs or inner workings can be answered quickly by inspecting sources. Your IDE should give you the same information you'll find on this page, as most of it is auto-generates from docstrings and method signatures anyway. If you are new to bottle, you may find the :doc:`tutorial` more helpful as a starting point.



Global functions
================

The module defines several functions, constants, and an exception.

.. function:: app()
              default_app()

    Return the current :ref:`default-app`. This is actually a callable instances of :class:`AppStack`.

.. autofunction:: debug

.. autofunction:: install

.. autofunction:: uninstall

.. autofunction:: run


Global decorators
=================

Bottle maintains a stack of :class:`Bottle` instances (see :func:`app` and :class:`AppStack`)
and uses the top of the stack as a :ref:`default-app` for some of the module-level functions
and decorators. All of those have a corresponding method on the :class:`Bottle` class.

.. function:: route(path, method='GET', callback=None, **options)
              get(...)
              post(...)
              put(...)
              delete(...)
              patch(...)

   Decorator to install a route to the current default application. See :meth:`Bottle.route` for details.

.. function:: error(...)

   Decorator to install an error handler to the current default application. See :meth:`Bottle.error` for details.

.. autofunction:: hook



Request Context
===============

The global :data:`request` and :data:`response` instances are only valid from within an request handler function and represent the *current* HTTP request or response.

.. autodata:: request

.. autodata:: response


Helper Functions
================

.. autofunction:: abort

.. autofunction:: redirect

.. autofunction:: static_file


Exceptions
==========

.. autoexception:: BottleException
   :members:

.. autoexception:: HTTPResponse
   :members:

.. autoexception:: HTTPError
   :members:


The :class:`Bottle` Class
=========================

.. autoclass:: Bottle
   :members:


The :class:`Request` Object
===================================================

The :class:`Request` class wraps a WSGI environment and provides helpful methods to parse and access form data, cookies, file uploads and other metadata. Most of the attributes are read-only.

.. autoclass:: Request
   :members:

.. autoclass:: BaseRequest
   :members:
   :special-members: __setattr__

.. autoclass:: LocalRequest
   :members:


The :class:`Response` Object
============================

The :class:`Response` class stores the HTTP status code as well as headers and cookies that are to be sent to the client. Similar to :data:`bottle.request` there is a thread-local :data:`bottle.response` instance that can be used to adjust the `current` response. Moreover, you can instantiate :class:`Response` and return it from your request handler. In this case, the custom instance overrules the headers and cookies defined in the global one.

.. autoclass:: Response
   :members:

.. autoclass:: BaseResponse
   :members:

.. autoclass:: LocalResponse
   :members:


Data Structures
===============

.. autoclass:: AppStack
   :members:

   .. method:: pop()

      Return the current default application and remove it from the stack.

.. autoclass:: ConfigDict
   :members:

.. autoclass:: MultiDict
   :members:

.. autoclass:: WSGIHeaderDict
   :members:

.. autoclass:: HeaderDict
   :members:

.. autoclass:: FormsDict
   :members:

.. autoclass:: FileUpload
   :members:


Request routing
===============

.. autoclass:: Router
    :members:

.. autoclass:: Route
    :members:


Templating
==========

All template engines supported by :mod:`bottle` implement the :class:`BaseTemplate` API. This way it is possible to switch and mix template engines without changing the application code at all.

.. autoclass:: BaseTemplate
   :members:

.. autofunction:: view

.. autofunction:: template

.. autodata:: TEMPLATE_PATH

   Global search path for templates.


You can write your own adapter for your favourite template engine or use one of the predefined adapters. Currently there are four fully supported template engines:

========================   ==================================   ====================   ========================
Class                      URL                                  Decorator              Render function
========================   ==================================   ====================   ========================
:class:`SimpleTemplate`    :doc:`stpl`                          :func:`view`           :func:`template`
:class:`MakoTemplate`      https://www.makotemplates.org         :func:`mako_view`      :func:`mako_template`
:class:`CheetahTemplate`   https://www.cheetahtemplate.org/      :func:`cheetah_view`   :func:`cheetah_template`
:class:`Jinja2Template`    https://jinja.palletsprojects.com/   :func:`jinja2_view`    :func:`jinja2_template`
========================   ==================================   ====================   ========================

To use :class:`MakoTemplate` as your default template engine, just import its specialised decorator and render function::

  from bottle import mako_view as view, mako_template as template

HTTP utilities
==============

.. autofunction:: parse_date

.. autofunction:: parse_auth

.. autofunction:: cookie_encode

.. autofunction:: cookie_decode

.. autofunction:: cookie_is_encoded

.. autofunction:: path_shift

.. autodata:: HTTP_CODES
  :no-value:

Misc utilities
==============

.. autoclass:: DictProperty

.. autoclass:: cached_property

.. autoclass:: lazy_attribute

.. autofunction:: yieldroutes

.. autofunction:: load

.. autofunction:: load_app

---

## File: docs/configuration.rst

=============
Configuration
=============

.. currentmodule:: bottle

Bottle applications can store their configuration in :attr:`Bottle.config`, a dict-like object and central place for application specific settings. This dictionary controls many aspects of the framework, tells (newer) plugins what to do, and can be used to store your own configuration as well.

Configuration Basics
====================

The :attr:`Bottle.config` object behaves a lot like an ordinary dictionary. All the common dict methods work as expected. Let us start with some examples::

    import bottle
    app = bottle.default_app()             # or bottle.Bottle() if you prefer

    app.config['autojson']    = False      # Turns off the "autojson" feature
    app.config['sqlite.db']   = ':memory:' # Tells the sqlite plugin which db to use
    app.config['myapp.param'] = 'value'    # Example for a custom config value.

    # Change many values at once
    app.config.update({
        'autojson': False,
        'sqlite.db': ':memory:',
        'myapp.param': 'value'
    })

    # Add default values
    app.config.setdefault('myapp.param2', 'some default')

    # Receive values
    param  = app.config['myapp.param']
    param2 = app.config.get('myapp.param2', 'fallback value')

    # An example route using configuration values
    @app.route('/about', view='about.rst')
    def about():
        email = app.config.get('my.email', 'nomail@example.com')
        return {'email': email}

Helper functions can rely on :attr:`Request.app ` to get the application
and configuration associated with the *current* request::

    from bottle import request
    def is_admin(user):
        return user == request.app.config['myapp.admin_user']

Naming Convention
=================

To make life easier, plugins and applications should follow some simple rules when it comes to config parameter names:

- All keys should be lowercase strings and follow the rules for python identifiers (no special characters but the underscore).
- Namespaces are separated by dots (e.g. ``namespace.field`` or ``namespace.subnamespace.field``).
- Bottle uses the root namespace for its own configuration. Plugins should store all their variables in their own namespace (e.g. ``sqlite.db`` or ``werkzeug.use_debugger``).
- Your own application should use a separate namespace (e.g. ``myapp.*``).


Load configuration from a File
=================================

.. versionadded 0.12

Configuration files are useful if you want to enable non-programmers to configure your application,
or just don't want to hack python module files just to change the database port. A very common syntax for configuration files is shown here:

.. code-block:: ini

    [sqlite]
    db = /tmp/test.db
    commit = auto
 
    [myapp]
    admin_user = defnull

With :meth:`ConfigDict.load_config` you can load these ``*.ini`` style configuration
files from disk and import their values into your existing configuration::

    app.config.load_config('/etc/myapp.conf')


Load configuration from a python module
==========================================

.. versionadded 0.13

Loading configuration from a Python module is a common pattern for Python
programs and frameworks. :meth:`ConfigDict.load_module` imports a python
module by name and adds all upper-case variables to configuration.

.. code-block:: python

     DEBUG = True
     SQLITE = {"db": ":memory:"}

.. code-block::

   >>> c = ConfigDict()
   >>> c.load_module('config')
   {'debug': True, 'sqlite.db': 'memory'}
   >>> c.load_module("config", squash=False)
   {'debug': True, 'sqlite': {'db': 'memory'}}

Configuration is flattened by default, similar to the behavior of :meth:`ConfigDict.load_dict`. You can prevent that by passing ``squash=False`` as a parameter.


Loading configuration from a :class:`dict`
==========================================

.. versionadded 0.12

Another useful method is :meth:`ConfigDict.load_dict`. This method takes
an entire structure of nested dictionaries and turns it into a flat list
of keys and values with namespaced keys::

    # Load an entire dict structure
    app.config.load_dict({
        'autojson': False,
        'sqlite': { 'db': ':memory:' },
        'myapp': {
            'param': 'value',
            'param2': 'value2'
        }
    })
    
    assert app.config['myapp.param'] == 'value'

    # Load configuration from a json file
    with open('/etc/myapp.json') as fp:
        app.config.load_dict(json.load(fp))

.. _conf-hook:

Listening to configuration changes
==================================

.. versionadded 0.12

Bottle triggers the ``config`` application hook each time a value in :attr:`Bottle.config` is about to be changed.
This hook can be used to dynamically re-configure plugins or parts of your application once configuration changes at runtime.
For example:

  * Enable or disable maintenance or debug mode.
  * Reconnect to a new database.
  * Change the settings on a plugin or background service.
  * Resize worker thread pools.
  
The hook callback receives two arguments (key, new_value) and is called before the value is actually changed in the dictionary.
Raising an exception from this callback will prevent the change and preserve the old value.

::

  @app.hook('config')
  def on_config_change(key, value):
    if key == 'debug':
        switch_own_debug_mode_to(value)

The hook callbacks cannot *change* the value that is to be stored to the dictionary. That is what filters are for.


.. _conf-meta:

Filters and other Meta Data
===========================

.. versionadded 0.12

:class:`ConfigDict` allows you to store meta data along with configuration keys. Two meta fields are currently defined:

``help``
    A help or description string. May be used by debugging, introspection or
    admin tools to help the site maintainer configuring their application.
``filter``
    A callable that accepts and returns a single value. If a filter is defined for a key, any new value stored to that key is first passed through the filter callback. The filter can be used to cast the value to a different type, check for invalid values (throw a ValueError) or trigger side effects.

This feature is most useful for plugins. They can validate their config parameters or trigger side effects using filters and document their configuration via ``help`` fields::

    class SomePlugin(object):
        def setup(app):
            app.config.meta_set('some.int', 'filter', int)
            app.config.meta_set('some.list', 'filter',
                lambda val: str(val).split(';'))
            app.config.meta_set('some.list', 'help',
                'A semicolon separated list.')

        def apply(self, callback, route):
            ...

    import bottle
    app = bottle.default_app()
    app.install(SomePlugin())

    app.config['some.list'] = 'a;b;c'     # Actually stores ['a', 'b', 'c']
    app.config['some.int'] = 'not an int' # raises ValueError


API Documentation
=================

.. versionadded 0.12

.. autoclass:: ConfigDict
   :members:
   :no-index:

---

## File: docs/deployment.rst

.. highlight:: python
.. currentmodule:: bottle

.. _flup: https://pypi.org/project/flup/
.. _gae: https://code.google.com/appengine/docs/python/overview.html
.. _wsgiref: https://docs.python.org/library/wsgiref.html
.. _cherrypy: https://cherrypy.dev/
.. _paste: https://pythonpaste.readthedocs.io/
.. _gunicorn: https://pypi.python.org/pypi/gunicorn
.. _tornado: https://www.tornadoweb.org/
.. _twisted: https://twistedmatrix.com/
.. _diesel: https://dieselweb.org/
.. _meinheld: https://pypi.python.org/pypi/meinheld
.. _bjoern: https://pypi.python.org/pypi/bjoern
.. _gevent: https://www.gevent.org/
.. _eventlet: https://eventlet.net/
.. _waitress: https://readthedocs.org/docs/waitress/en/latest/
.. _apache: https://httpd.apache.org/
.. _mod_wsgi: https://code.google.com/p/modwsgi/
.. _pound: https://www.apsis.ch/pound
.. _nginx: https://nginx.org/
.. _lighttpd: https://www.lighttpd.net/
.. _cherokee: https://cherokee-project.com/
.. _uWSGI: https://uwsgi-docs.readthedocs.io/en/latest/
.. _cheroot: https://cheroot.cherrypy.dev/

.. _tutorial-deployment:

================================================================================
Deployment
================================================================================

The bottle :func:`run` function, when called without any parameters, starts a local development server on port 8080. You can access and test your application via http://localhost:8080/ if you are on the same host.

To get your application available to the outside world, specify the IP the server should listen to (e.g. ``run(host='192.168.0.1')``) or let the server listen to all interfaces at once (e.g. ``run(host='0.0.0.0')``). The listening port can be changed in a similar way, but you need root or admin rights to choose a port below 1024. Port 80 is the standard for HTTP servers::

  # Listen to HTTP on all interfaces
  if __name__ == '__main__':
      run(host='0.0.0.0', port=80)

Scaling for Production
================================================================================

The built-in development server is base on `wsgiref WSGIServer <https://docs.python.org/library/wsgiref.html#module-wsgiref.simple_server>`_, which is a very simple non-threading HTTP server implementation. This is perfectly fine for development, but may become a performance bottleneck when server load increases.

The easiest way to increase performance is to install a multi-threaded server library like cheroot_ or gunicorn_ and tell Bottle to use that instead of the single-threaded wsgiref server::

    run(server='cheroot', ...)   # Pure Python, runs everywhere
    run(server='gunicorn', ...)  # High performance

Or using the ``bottle`` command line interface:

.. code-block:: sh

    python3 -m bottle --server gunicorn [...] mymodule:app

For production deployments gunicorn_ is a really good choice. It comes with its own command line utility that supports a lot more options than bottle. Since :class:`Bottle` instances are WSGI applications, you can tell gunicorn_ (or any other WSGI server) to load your app instead of calling :func:`run` yourself:

.. code-block:: sh

    gunicorn -w 4 mymodule:app

This will start your application with 4 gunicorn workers and sane default settings. For more details and more complete examples, check out `Gunicorn Documentation <https://docs.gunicorn.org/>`_.

Server adapters
------------------------------------------------------------------------------

Bottle ships with a bunch of ready-to-use adapters for the most common WSGI servers so you can try out different server backends easily. You can select a server backend via `run(server='NAME')` or `python3 -m bottle --server NAME`. Here is an incomplete list:

========  ============  ======================================================
Name      Homepage      Description
========  ============  ======================================================
cgi                     Run as CGI script
flup      flup_         Run as FastCGI process
gae       gae_          Helper for Google App Engine deployments
wsgiref   wsgiref_      Single-threaded default server
cherrypy  cherrypy_     Multi-threaded (deprectated))
cheroot   cheroot_      Successor of cheerypy
paste     paste_        Multi-threaded, stable, tried and tested
waitress  waitress_     Multi-threaded, poweres Pyramid
gunicorn  gunicorn_     Pre-forked, partly written in C
eventlet  eventlet_     Asynchronous framework with WSGI support.
gevent    gevent_       Asynchronous (greenlets)
diesel    diesel_       Asynchronous (greenlets)
tornado   tornado_      Asynchronous, powers some parts of Facebook
twisted   twisted_      Asynchronous, well tested but... twisted
meinheld  meinheld_     Asynchronous, partly written in C
bjoern    bjoern_       Asynchronous, very fast and written in C
auto                    Automatically selects the first available server adapter
========  ============  ======================================================

Those adapters are very basic and just for convenience, though. If you need more control over your deployment, refer to the server backend documentation and mount your Bottle application just like any other WSGI application.


WSGI Deployment
------------------------------------------------------------------------------

If there is no adapter for your favorite server or if you need more control over the server setup, you may want to start the server manually. Refer to the server documentation on how to run WSGI applications. Here is an example for cheroot_::

    import cheroot.wsgi
    import mymodule.app

    wsgi_server = cheroot.wsgi.Server(
        bind_addr=('0.0.0.0', 80),
        wsgi_app=mymodule.app
    )

    try:
        wsgi_server.start()
    finally:
        wsgi_server.stop()

---

## File: docs/development.rst

Developer Notes
=================

This document is intended for developers and package maintainers interested in the bottle development and release workflow. If you want to contribute, you are just right!


Get involved
------------

There are several ways to join the community and stay up to date. Here are some of them:

* **Mailing list**: Join our mailing list by sending an email to `bottlepy+subscribe@googlegroups.com <mailto:bottlepy+subscribe@googlegroups.com>`_ (no google account required).
* **IRC**: Join `#bottlepy on irc.libera.chat `_ or use the `web chat interface <https://web.libera.chat/#bottlepy>`_.


Get the Sources
---------------

The bottle `development repository <https://github.com/bottlepy/bottle>`_ and the `issue tracker <https://github.com/bottlepy/bottle/issues>`_ are both hosted at `github <https://github.com/bottlepy/bottle>`_. If you plan to contribute, it is a good idea to create an account there and fork the main repository. This way your changes and ideas are visible to other developers and can be discussed openly. Even without an account, you can clone the repository or just download the latest development version as a source archive.

* **git:** ``git clone git://github.com/bottlepy/bottle.git``
* **git/https:** ``git clone https://github.com/bottlepy/bottle.git``
* **Download:** Development branch as `tar archive <https://github.com/bottlepy/bottle/tarball/master>`_ or `zip file <https://github.com/bottlepy/bottle/zipball/master>`_.


Releases and Updates
--------------------

Bottle is released at irregular intervals and distributed through `PyPI <https://pypi.python.org/pypi/bottle>`_. Release candidates are only available from the git repository mentioned above. Debian and many other Linux distributions offer packages.

The Bottle version number splits into three parts (**major.minor.patch**) but does not follow the rules of `SemVer <https://semver.org/>`_. Instead, you can usually rely on the following rules:

Major Release (x.0)
    The major release number is increased on important milestones that change the design of core parts of the framework and break backward compatibility in some fundamental way. You probably have to change parts of your application to use a new major release. These releases are very rare, through.

Minor Release (x.y)
    The minor release number is increased whenever APIs or behavior changes in some backwards incompatible way or major features or new APIs are added. You might get some depreciation warnings any may have to tweak some configuration settings to restore the old behavior, but in most cases these changes are designed to be backward compatible for at least one minor release. You should update to stay up do date, but don't have to.

Patches (x.y.z)
    The patch number is increased on bug-fixes and other patches that do not change APIs or behaviour. You can safely update without editing your application code. In fact, you really should as soon as possible, because important security fixes are released this way.

Pre-Release Versions
    Release candidates are marked by an ``rc`` in their revision number. These are API stable most of the time and open for testing, but not officially released yet. You should not use these for production.


Repository Structure
--------------------

The source repository is structured as follows:

``master`` branch
  This is the integration, testing and development branch. All changes that are planned to be part of the next release are merged and tested here.

``release-x.y`` branches
  As soon as the master branch is (almost) ready for a new release, it is branched into a new release branch. This "release candidate" is feature-frozen but may receive bug-fixes and last-minute changes until it is considered production ready and officially released. From that point on it is called a "maintenance branch" and still receives bug-fixes, but only important ones. The patch number is increased on each push to these branches, so you can keep up with important changes.

Feature branches
  All other branches are feature branches. These are based on the master branch and only live as long as they are still active and not merged back into ``master``.


.. rubric:: What does this mean for a developer?

If you want to add a feature, create a new feature branch from ``master``. If you want to fix a bug, branch off of ``release-x.y`` for each affected release. Please use a separate branch for each feature or bug to make integration as easy as possible.

.. rubric:: What does this mean for a maintainer ?

Watch the tags (and the mailing list) for bug-fixes and new releases. If you want to fetch a specific release from the git repository, trust the tags, not the branches. A branch may contain changes that are not released yet, but a tag marks the exact commit which changed the version number.


Submitting Patches
------------------

The best way to get your changes integrated into the main development branch is to fork the main repository at github, create a new feature-branch, apply your changes and send a pull-request. Further down this page is a small collection of git workflow examples that may guide you. Submitting git-compatible patches to the mailing list is fine too. In any case, please follow some basic rules:

* **Documentation:** Tell us what your patch does. Comment your code. If you introduced a new feature, add to the documentation so others can learn about it.
* **Test:** Write tests to prove that your code works as expected and does not break anything. If you fixed a bug, write at least one test-case that triggers the bug. Make sure that all tests pass before you submit a patch.
* **One patch at a time:** Only fix one bug or add one feature at a time. Design your patches so that they can be applied as a whole. Keep your patches clean, small and focused. 
* **Sync with upstream:** If the ``upstream/master`` branch changed while you were working on your patch, rebase or pull to make sure that your patch still applies without conflicts.