fietsboek.config module

Configuration parsing for Fietsboek.

Fietsboek mostly relies on pyramid’s INI parsing to get its configuration, however, there are quite a a few custom values that we add/need. Instead of manually sprinkling settings.get(...) all over the code, we’d rather just do it once at application startup, make sure that the values are well-formed, provide the user with good feedback if they aren’t, and set the default values in a single place.

Most of the logic is handled by pydantic.

class fietsboek.config.Config(**data)

Bases: BaseModel

Object representing the Fietsboek configuration.

available_locales: Annotated[list]

Available locales.

data_dir: Annotated[Path]

Fietsboek data directory.

default_tile_layers: Annotated[list]

The subset of the default tile layers that should be enabled.

By default, that’s all of them.

derive_secret(what_for)

Derive a secret for other parts of the application.

All secrets are derived from secret_key in a deterministic way. See https://docs.pylonsproject.org/projects/pyramid/en/latest/narr/security.html#admonishment-against-secret-sharing on why secret_key should not be used directly.

Parameters:

what_for (str) – What the secret is used for. Passing the same “use case” will generate the same secret.

Returns:

The generated secret.

Return type:

str

disable_tile_proxy: bool

Disable the tile proxy.

email_from: str

Email sender address.

email_password: SecretStr

SMTP password (optional).

email_smtp_url: str

Email SMTP server.

email_username: str

SMTP username (optional).

enable_account_registration: bool

Enable registration of new accounts.

enable_image_uploads: bool

Allow track uploaders to also upload images for tracks.

hittekaart_autogenerate: Annotated[list]

Overlay maps to automatically generate.

hittekaart_bin: str

Path to the hittekaart binary.

hittekaart_threads: int

Number of threads that hittekaart should use.

Defaults to 0, which makes it use as many threads as there are CPU cores.

language_packs: Annotated[list]

Additional language packs to load.

model_computed_fields: ClassVar[dict[str, ComputedFieldInfo]] = {}

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[dict[str, FieldInfo]] = {'available_locales': FieldInfo(annotation=list, required=False, default=['en', 'de'], metadata=[BeforeValidator(func=<function _validate_pyramid_list>)]), 'data_dir': FieldInfo(annotation=Path, required=True, alias='fietsboek.data_dir', alias_priority=2, metadata=[PathType(path_type='dir')]), 'default_tile_layers': FieldInfo(annotation=list, required=False, default=['osm', 'osmde', 'satellite', 'opentopo', 'topplusopen', 'opensea', 'cycling', 'hiking'], alias='fietsboek.default_tile_layers', alias_priority=2, metadata=[BeforeValidator(func=<function _validate_pyramid_list>)]), 'disable_tile_proxy': FieldInfo(annotation=bool, required=False, default=False, alias='fietsboek.tile_proxy.disable', alias_priority=2), 'email_from': FieldInfo(annotation=str, required=True, alias='email.from', alias_priority=2), 'email_password': FieldInfo(annotation=SecretStr, required=False, default=SecretStr(''), alias='email.password', alias_priority=2), 'email_smtp_url': FieldInfo(annotation=str, required=True, alias='email.smtp_url', alias_priority=2), 'email_username': FieldInfo(annotation=str, required=False, default='', alias='email.username', alias_priority=2), 'enable_account_registration': FieldInfo(annotation=bool, required=False, default=False), 'enable_image_uploads': FieldInfo(annotation=bool, required=False, default=True, alias='fietsboek.enable_image_uploads', alias_priority=2), 'hittekaart_autogenerate': FieldInfo(annotation=list, required=False, default=[], alias='hittekaart.autogenerate', alias_priority=2, metadata=[BeforeValidator(func=<function _validate_pyramid_list>)]), 'hittekaart_bin': FieldInfo(annotation=str, required=False, default='', alias='hittekaart.bin', alias_priority=2), 'hittekaart_threads': FieldInfo(annotation=int, required=False, default=0, alias='hittekaart.threads', alias_priority=2), 'language_packs': FieldInfo(annotation=list, required=False, default=[], alias='fietsboek.language_packs', alias_priority=2, metadata=[BeforeValidator(func=<function _validate_pyramid_list>)]), 'pages': FieldInfo(annotation=list, required=False, default=[], alias='fietsboek.pages', alias_priority=2, metadata=[BeforeValidator(func=<function _validate_pyramid_list>)]), 'redis_url': FieldInfo(annotation=str, required=True, alias='redis.url', alias_priority=2), 'session_key': FieldInfo(annotation=str, required=True), 'sqlalchemy_url': FieldInfo(annotation=str, required=True, alias='sqlalchemy.url', alias_priority=2), 'stamen_maps': FieldInfo(annotation=list, required=False, default=[], alias='stamen.maps', alias_priority=2, metadata=[BeforeValidator(func=<function _validate_pyramid_list>)]), 'thunderforest_access': FieldInfo(annotation=LayerAccess, required=False, default=<LayerAccess.RESTRICTED: 'restricted'>, alias='thunderforest.access', alias_priority=2), 'thunderforest_key': FieldInfo(annotation=SecretStr, required=False, default=SecretStr(''), alias='thunderforest.api_key', alias_priority=2), 'thunderforest_maps': FieldInfo(annotation=list, required=False, default=[], alias='thunderforest.maps', alias_priority=2, metadata=[BeforeValidator(func=<function _validate_pyramid_list>)]), 'tile_layers': FieldInfo(annotation=List[TileLayerConfig], required=False, default=[])}

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].

This replaces Model.__fields__ from Pydantic V1.

pages: Annotated[list]

Custom pages.

redis_url: str

Redis URL.

session_key: str

Session key.

sqlalchemy_url: str

SQLAlchemy URL.

stamen_maps: Annotated[list]

Enabled stamen maps.

thunderforest_access: LayerAccess

Thunderforest access restriction.

thunderforest_key: SecretStr

API key for the Thunderforest integration.

thunderforest_maps: Annotated[list]

List of enabled Thunderforest maps.

tile_layers: List[TileLayerConfig]

Tile layers.

class fietsboek.config.LayerAccess(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

Enum discerning whether a layer is publicly accessible or restriced to logged-in users.

Note that in the future, a finer-grained distinction might be possible.

PUBLIC = 'public'
RESTRICTED = 'restricted'
class fietsboek.config.LayerType(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)

Bases: Enum

Enum to distinguish base layers and overlay layers.

BASE = 'base'
OVERLAY = 'overlay'
class fietsboek.config.TileLayerConfig(**data)

Bases: BaseModel

Object representing a single tile layer.

access: LayerAccess

Layer access restriction.

attribution: str

Attribution of the layer copyright.

layer_id: str

ID of the layer.

layer_type: LayerType

Type of the layer.

model_computed_fields: ClassVar[dict[str, ComputedFieldInfo]] = {}

A dictionary of computed field names and their corresponding ComputedFieldInfo objects.

model_config: ClassVar[ConfigDict] = {'populate_by_name': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

model_fields: ClassVar[dict[str, FieldInfo]] = {'access': FieldInfo(annotation=LayerAccess, required=False, default=<LayerAccess.PUBLIC: 'public'>), 'attribution': FieldInfo(annotation=str, required=False, default=''), 'layer_id': FieldInfo(annotation=str, required=True), 'layer_type': FieldInfo(annotation=LayerType, required=False, default=<LayerType.BASE: 'base'>, alias='type', alias_priority=2), 'name': FieldInfo(annotation=str, required=True), 'url': FieldInfo(annotation=Url, required=True), 'zoom': FieldInfo(annotation=Union[int, NoneType], required=False, default=22)}

Metadata about the fields defined on the model, mapping of field names to [FieldInfo][pydantic.fields.FieldInfo].

This replaces Model.__fields__ from Pydantic V1.

name: str

Human-readable name of the layer.

url: Url

URL of the layer tiles (with placeholders).

zoom: Optional[int]

Maximum zoom factor of the layer.

exception fietsboek.config.ValidationError(errors)

Bases: Exception

Exception for malformed configurations.

This provides a nice str() representation that can be printed out.

fietsboek.config.parse(config)

Parses the configuration into a Config.

Parameters:

config (dict) – The configuration dict to parse.

Return type:

Config

Returns:

The parsed (and validated) configuration.

Raises:

ValidationError – When the configuration is malformed.