backend config: Add application configuration

Configuration is managed as a Pydantic model and can be loaded from a
YAML document.
master
Dustin 2022-01-25 21:41:52 -06:00
parent 46bc1869af
commit e33502eee1
6 changed files with 105 additions and 2 deletions

3
backend/.gitignore vendored
View File

@ -1,4 +1,5 @@
/.venv/
/dist/
/build/
__pycache__/
__pycache__/
/config.yml

52
backend/poetry.lock generated
View File

@ -276,6 +276,29 @@ python-versions = "*"
[package.extras]
dev = ["build", "pytest", "pytest-timeout"]
[[package]]
name = "ruamel.yaml"
version = "0.17.20"
description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order"
category = "main"
optional = false
python-versions = ">=3"
[package.dependencies]
"ruamel.yaml.clib" = {version = ">=0.2.6", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""}
[package.extras]
docs = ["ryd"]
jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"]
[[package]]
name = "ruamel.yaml.clib"
version = "0.2.6"
description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml"
category = "main"
optional = false
python-versions = ">=3.5"
[[package]]
name = "sniffio"
version = "1.2.0"
@ -381,7 +404,7 @@ python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
[metadata]
lock-version = "1.1"
python-versions = "^3.8"
content-hash = "4557b3cd4cddb758cdbb713b02a2f3c6974b8d1e0077ae67c30f44d5a6a68666"
content-hash = "b1acad0ac357a1cf7a02aaeb3106a761b3d74fb5535f707aca1bdeae1bf4d0cf"
[metadata.files]
anyio = [
@ -615,6 +638,33 @@ rope = [
{file = "rope-0.22.0-py3-none-any.whl", hash = "sha256:2847220bf72ead09b5abe72b1edc9cacff90ab93663ece06913fc97324167870"},
{file = "rope-0.22.0.tar.gz", hash = "sha256:b00fbc064a26fc62d7220578a27fd639b2fad57213663cc396c137e92d73f10f"},
]
"ruamel.yaml" = [
{file = "ruamel.yaml-0.17.20-py3-none-any.whl", hash = "sha256:810eef9c46523a3f77479c66267a4708255ebe806a2d540078408c2227f011af"},
{file = "ruamel.yaml-0.17.20.tar.gz", hash = "sha256:4b8a33c1efb2b443a93fcaafcfa4d2e445f8e8c29c528d9f5cdafb7cc9e4004c"},
]
"ruamel.yaml.clib" = [
{file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:cfdb9389d888c5b74af297e51ce357b800dd844898af9d4a547ffc143fa56751"},
{file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7b2927e92feb51d830f531de4ccb11b320255ee95e791022555971c466af4527"},
{file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win32.whl", hash = "sha256:ada3f400d9923a190ea8b59c8f60680c4ef8a4b0dfae134d2f2ff68429adfab5"},
{file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win_amd64.whl", hash = "sha256:de9c6b8a1ba52919ae919f3ae96abb72b994dd0350226e28f3686cb4f142165c"},
{file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d67f273097c368265a7b81e152e07fb90ed395df6e552b9fa858c6d2c9f42502"},
{file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:72a2b8b2ff0a627496aad76f37a652bcef400fd861721744201ef1b45199ab78"},
{file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win32.whl", hash = "sha256:9efef4aab5353387b07f6b22ace0867032b900d8e91674b5d8ea9150db5cae94"},
{file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win_amd64.whl", hash = "sha256:846fc8336443106fe23f9b6d6b8c14a53d38cef9a375149d61f99d78782ea468"},
{file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0847201b767447fc33b9c235780d3aa90357d20dd6108b92be544427bea197dd"},
{file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:78988ed190206672da0f5d50c61afef8f67daa718d614377dcd5e3ed85ab4a99"},
{file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win32.whl", hash = "sha256:a49e0161897901d1ac9c4a79984b8410f450565bbad64dbfcbf76152743a0cdb"},
{file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win_amd64.whl", hash = "sha256:bf75d28fa071645c529b5474a550a44686821decebdd00e21127ef1fd566eabe"},
{file = "ruamel.yaml.clib-0.2.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a32f8d81ea0c6173ab1b3da956869114cae53ba1e9f72374032e33ba3118c233"},
{file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7f7ecb53ae6848f959db6ae93bdff1740e651809780822270eab111500842a84"},
{file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win32.whl", hash = "sha256:89221ec6d6026f8ae859c09b9718799fea22c0e8da8b766b0b2c9a9ba2db326b"},
{file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win_amd64.whl", hash = "sha256:31ea73e564a7b5fbbe8188ab8b334393e06d997914a4e184975348f204790277"},
{file = "ruamel.yaml.clib-0.2.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dc6a613d6c74eef5a14a214d433d06291526145431c3b964f5e16529b1842bed"},
{file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1866cf2c284a03b9524a5cc00daca56d80057c5ce3cdc86a52020f4c720856f0"},
{file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win32.whl", hash = "sha256:3fb9575a5acd13031c57a62cc7823e5d2ff8bc3835ba4d94b921b4e6ee664104"},
{file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:825d5fccef6da42f3c8eccd4281af399f21c02b32d98e113dbc631ea6a6ecbc7"},
{file = "ruamel.yaml.clib-0.2.6.tar.gz", hash = "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd"},
]
sniffio = [
{file = "sniffio-1.2.0-py3-none-any.whl", hash = "sha256:471b71698eac1c2112a40ce2752bb2f4a4814c22a54a3eed3676bc0f5ca9f663"},
{file = "sniffio-1.2.0.tar.gz", hash = "sha256:c4666eecec1d3f50960c6bdf61ab7bc350648da6c126e3cf6898d8cd4ddcd3de"},

View File

@ -9,6 +9,7 @@ license = "MIT"
python = "^3.8"
fastapi = "^0.72.0"
SQLAlchemy = "^1.4.31"
"ruamel.yaml" = "^0.17.20"
[tool.poetry.dev-dependencies]
black = "^21.12b0"

View File

@ -13,10 +13,15 @@ context is available to request handlers using the
'''
import fastapi
from ..config import Configuration
class Context:
'''Application context'''
config: Configuration
'''Application configuration'''
def get_context(request: fastapi.Request) -> Context:
'''Dependency function to access the application context'''

View File

@ -4,6 +4,7 @@ from typing import Awaitable, Callable
import fastapi
from .. import __version__
from ..config import Configuration
from .context import Context
@ -18,6 +19,7 @@ app = fastapi.FastAPI(
# Application context
context = Context()
context.config = Configuration()
@app.middleware('http')

View File

@ -0,0 +1,44 @@
import os
from pathlib import Path
from typing import IO, Optional, Union
import pydantic
from ruamel import yaml
class DatabaseConfiguration(pydantic.BaseModel):
'''Database configuration'''
url: str = 'sqlite:///lycodon.db'
'''Database connection URL'''
class Configuration(pydantic.BaseModel):
'''Application configuration'''
database: DatabaseConfiguration = DatabaseConfiguration()
'''Database configuration'''
@classmethod
def load(cls, path: Optional[Union[Path, str]] = None) -> 'Configuration':
'''Load configuration from the specified file
:param path: Path to the configuration file
'''
if path is None:
path = Path(os.environ.get('LYCODON_CONFIG', 'config.yml'))
elif not isinstance(path, Path):
path = Path(path)
with path.open('r', encoding='utf-8') as f:
return cls.from_file(f)
@classmethod
def from_file(cls, f: IO[str]) -> 'Configuration':
'''Load configuration from an open file buffer
:param f: Open readable file object
'''
values = yaml.safe_load(f) or {}
return cls.parse_obj(values)