baseplate.lib.config

Configuration parsing and validation.

This module provides parse_config which turns a dictionary of stringy keys and values into a structured and typed configuration object.

For example, an INI file like the following:

[app:main]
simple = true
cards = clubs, spades, diamonds
nested.once = 1
nested.really.deep = 3 seconds
some_file = /var/lib/whatever.txt
sample_rate = 37.1%
interval = 30 seconds
default_from_env = blah

Might be parsed like the following. Note: when running under the baseplate server, The config_parser.items(...) step is taken care of for you and raw_config is passed as the only argument to your factory function.

>>> raw_config = dict(config_parser.items("app:main"))

>>> CARDS = config.OneOf(clubs=1, spades=2, diamonds=3, hearts=4)
>>> cfg = config.parse_config(raw_config, {
...     "simple": config.Boolean,
...     "cards": config.TupleOf(CARDS),
...     "nested": {
...         "once": config.Integer,
...
...         "really": {
...             "deep": config.Timespan,
...         },
...     },
...     "some_file": config.File(mode="r"),
...     "optional": config.Optional(config.Integer, default=9001),
...     "sample_rate": config.Percent,
...     "interval": config.Fallback(config.Timespan, config.Integer),
...     "default_from_env": config.DefaultFromEnv(config.String, env_var_name),
... })

>>> print(cfg.simple)
True

>>> print(cfg.cards)
[1, 2, 3]

>>> print(cfg.nested.really.deep)
0:00:03

>>> cfg.some_file.read()
'cool'

>>> cfg.some_file.close()

>>> cfg.sample_rate
0.371

>>> print(cfg.interval)
0:00:30

>>> print(cfg.default_from_env)
blah

Parser

baseplate.lib.config.parse_config(config, spec)[source]

Parse options against a spec and return a structured representation.

Parameters:
Raises:

ConfigurationError The configuration violated the spec.

Return type:

ConfigNamespace

Returns:

A structured configuration object.

Value Types

Each option can have a type specified. Some types compose with other types to make complicated expressions.

baseplate.lib.config.String(text)[source]

A raw string.

Return type:

str

baseplate.lib.config.Float(text)[source]

A floating-point number.

Return type:

float

baseplate.lib.config.Integer(text=None, base=10)[source]

An integer.

To prevent mistakes, this will raise an error if the user attempts to configure a non-whole number.

Parameters:

base (int) – (Optional) If specified, the base of the integer to parse.

Return type:

Union[int, Callable[[str], int]]

baseplate.lib.config.Boolean(text)[source]

True or False, case insensitive.

Return type:

bool

baseplate.lib.config.Endpoint(text)[source]

A remote endpoint to connect to.

Returns an EndpointConfiguration.

If the endpoint is a hostname:port pair, the family will be socket.AF_INET and address will be a two-tuple of host and port, as expected by socket.

If the endpoint contains a slash (/), it will be interpreted as a path to a UNIX domain socket. The family will be socket.AF_UNIX and address will be the path as a string.

Return type:

EndpointConfiguration

baseplate.lib.config.Timespan(text)[source]

A span of time.

This takes a string of the form “1 second” or “3 days” and returns a datetime.timedelta representing that span of time.

Units supported are: milliseconds, seconds, minutes, hours, days.

Return type:

timedelta

baseplate.lib.config.Base64(text)[source]

A base64 encoded block of data.

This is useful for arbitrary binary blobs.

Return type:

bytes

baseplate.lib.config.File(mode='r')[source]

A path to a file.

This takes a path to a file and returns an open file object, like returned by open().

Parameters:

mode (str) – an optional string that specifies the mode in which the file is opened.

Return type:

Callable[[str], IO]

baseplate.lib.config.Percent(text)[source]

A percentage.

This takes a string of the form “37.2%” or “44%” and returns a float in the range [0.0, 1.0].

Return type:

float

baseplate.lib.config.UnixUser(text)[source]

A Unix user name or decimal ID.

The parsed value will be the integer user ID.

Return type:

int

baseplate.lib.config.UnixGroup(text)[source]

A Unix group name or decimal ID.

The parsed value will be the integer group ID.

Return type:

int

baseplate.lib.config.OneOf(**options)[source]

One of several choices.

For each option, the name is what should be in the configuration file and the value is what it is mapped to.

For example:

OneOf(hearts="H", spades="S")

would parse:

"hearts"

into:

"H"
Return type:

Callable[[str], TypeVar(T)]

baseplate.lib.config.TupleOf(item_parser)[source]

A comma-delimited list of type T.

At least one value must be provided. If you want an empty list to be a valid choice, wrap with Optional().

Return type:

Callable[[str], Sequence[TypeVar(T)]]

If you need something custom or fancy for your application, just use a callable which takes a string and returns the parsed value or raises ValueError.

Combining Types

These options are used in combination with other types to form more complex configurations.

baseplate.lib.config.Optional(item_parser, default=None)[source]

An option of type T, or default if not configured.

Return type:

Callable[[str], Optional[TypeVar(T)]]

baseplate.lib.config.Fallback(primary_parser, fallback_parser)[source]

An option of type T1, or if that fails to parse, of type T2.

This is useful for backwards-compatible configuration changes.

Return type:

Callable[[str], TypeVar(T)]

baseplate.lib.config.DictOf(spec)[source]

A group of options of a given type.

This is useful for providing data to the application without the application having to know ahead of time all of the possible keys.

[app:main]
population.cn = 1383890000
population.in = 1317610000
population.us = 325165000
population.id = 263447000
population.br = 207645000
>>> cfg = config.parse_config(raw_config, {
...     "population": config.DictOf(config.Integer),
... })

>>> len(cfg.population)
5

>>> cfg.population["br"]
207645000

It can also be combined with other configuration specs or parsers to parse more complicated structures:

[app:main]
countries.cn.population = 1383890000
countries.cn.capital = Beijing
countries.in.population = 1317610000
countries.in.capital = New Delhi
countries.us.population = 325165000
countries.us.capital = Washington D.C.
countries.id.population = 263447000
countries.id.capital = Jakarta
countries.br.population = 207645000
countries.br.capital = Brasília
>>> cfg = config.parse_config(raw_config, {
...     "countries": config.DictOf({
...         "population": config.Integer,
...         "capital": config.String,
...     }),
... })

>>> len(cfg.countries)
5

>>> cfg.countries["cn"].capital
'Beijing'

>>> cfg.countries["id"].population
263447000

Data Types

class baseplate.lib.config.EndpointConfiguration(family: AddressFamily, address: InternetAddress | str)[source]

A description of a remote endpoint.

This is a 2-tuple of (family and address).

family

One of socket.AF_INET or socket.AF_UNIX.

address

An address appropriate for the family.

Add a new parser

class baseplate.lib.config.Parser[source]

Base class for configuration parsers.

Exceptions

exception baseplate.lib.config.ConfigurationError(key, error)[source]

Raised when the configuration violates the spec.