Configuration

Bottle applications can store their configuration inBottle.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

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

importbottleapp=bottle.default_app()# or bottle.Bottle() if you preferapp.config['autojson']=False# Turns off the "autojson" featureapp.config['sqlite.db']=':memory:'# Tells the sqlite plugin which db to useapp.config['myapp.param']='value'# Example for a custom config value.# Change many values at onceapp.config.update({'autojson':False,'sqlite.db':':memory:','myapp.param':'value'})# Add default valuesapp.config.setdefault('myapp.param2','some default')# Receive valuesparam=app.config['myapp.param']param2=app.config.get('myapp.param2','fallback value')# An example route using configuration values@app.route('/about',view='about.rst')defabout():email=app.config.get('my.email','nomail@example.com')return{'email':email}

Helper functions can rely onRequest.app to get the applicationand configuration associated with thecurrent request:

frombottleimportrequestdefis_admin(user):returnuser==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 ornamespace.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 orwerkzeug.use_debugger).

  • Your own application should use a separate namespace (e.g.myapp.*).

Load configuration from a File

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:

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

WithConfigDict.load_config() you can load these*.ini style configurationfiles from disk and import their values into your existing configuration:

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

Load configuration from a python module

Loading configuration from a Python module is a common pattern for Pythonprograms and frameworks.ConfigDict.load_module() imports a pythonmodule by name and adds all upper-case variables to configuration.

DEBUG=TrueSQLITE={"db":":memory:"}
>>>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 ofConfigDict.load_dict(). You can prevent that by passingsquash=False as a parameter.

Loading configuration from adict

Another useful method isConfigDict.load_dict(). This method takesan entire structure of nested dictionaries and turns it into a flat listof keys and values with namespaced keys:

# Load an entire dict structureapp.config.load_dict({'autojson':False,'sqlite':{'db':':memory:'},'myapp':{'param':'value','param2':'value2'}})assertapp.config['myapp.param']=='value'# Load configuration from a json filewithopen('/etc/myapp.json')asfp:app.config.load_dict(json.load(fp))

Listening to configuration changes

Bottle triggers theconfig application hook each time a value inBottle.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')defon_config_change(key,value):ifkey=='debug':switch_own_debug_mode_to(value)

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

Filters and other Meta Data

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 oradmin 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 viahelp fields:

classSomePlugin(object):defsetup(app):app.config.meta_set('some.int','filter',int)app.config.meta_set('some.list','filter',lambdaval:str(val).split(';'))app.config.meta_set('some.list','help','A semicolon separated list.')defapply(self,callback,route):...importbottleapp=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

classConfigDict[source]

A dict-like configuration storage with additional support fornamespaces, validators, meta-data and overlays.

This dict-like class is heavily optimized for read access.Read-only methods and item access should be as fast as a native dict.

__init__()[source]
load_module(name,squash=True)[source]

Load values from a Python module.

Import a python module by name and add all upper-case module-levelvariables to this config dict.

Parameters:
  • name – Module name to import and load.

  • squash – If true (default), nested dicts are assumed torepresent namespaces and flattened (seeload_dict()).

load_config(filename,**options)[source]

Load values from*.ini style config files using configparser.

INI style sections (e.g.[section]) are used as namespace forall keys within that section. Both section and key names may containdots as namespace separators and are converted to lower-case.

The special sections[bottle] and[ROOT] refer to the rootnamespace and the[DEFAULT] section defines default values for allother sections.

Parameters:
  • filename – The path of a config file, or a list of paths.

  • options – All keyword parameters are passed to the underlyingconfigparser.ConfigParser constructor call.

load_dict(source,namespace='')[source]

Load values from a dictionary structure. Nesting can be used torepresent namespaces.

>>>c=ConfigDict()>>>c.load_dict({'some':{'namespace':{'key':'value'}}}){'some.namespace.key': 'value'}
update(*a,**ka)[source]

If the first parameter is a string, all keys are prefixed with thisnamespace. Apart from that it works just as the usual dict.update().

>>>c=ConfigDict()>>>c.update('some.namespace',key='value')
setdefault(key,value=None)[source]

Insert key with a value of default if key is not in the dictionary.

Return the value for key if key is in the dictionary, else default.

meta_get(key,metafield,default=None)[source]

Return the value of a meta field for a key.

meta_set(key,metafield,value)[source]

Set the meta field for a key to a new value.

Meta-fields are shared between all members of an overlay tree.

meta_list(key)[source]

Return an iterable of meta field names defined for a key.