Add config handler
This commit is contained in:
parent
04b2ee57bd
commit
9affe75810
|
@ -3,7 +3,12 @@ name = "event_management"
|
|||
version = "0.1.0"
|
||||
description = "Backed part of the final project assignment for AP7PD"
|
||||
authors = [{ name = "Peter Vacho", email = "p_vacho@utb.cz" }]
|
||||
dependencies = ["fastapi>=0.115.5", "uvicorn>=0.32.1", "poethepoet>=0.31.1"]
|
||||
dependencies = [
|
||||
"fastapi>=0.115.5",
|
||||
"uvicorn>=0.32.1",
|
||||
"poethepoet>=0.31.1",
|
||||
"python-decouple>=3.8",
|
||||
]
|
||||
readme = "README.md"
|
||||
requires-python = ">= 3.12"
|
||||
license = { text = "GPL-3.0-or-later" }
|
||||
|
|
|
@ -46,6 +46,8 @@ pydantic==2.10.2
|
|||
# via fastapi
|
||||
pydantic-core==2.27.1
|
||||
# via pydantic
|
||||
python-decouple==3.8
|
||||
# via event-management
|
||||
pyyaml==6.0.2
|
||||
# via poethepoet
|
||||
# via pre-commit
|
||||
|
|
|
@ -30,6 +30,8 @@ pydantic==2.10.2
|
|||
# via fastapi
|
||||
pydantic-core==2.27.1
|
||||
# via pydantic
|
||||
python-decouple==3.8
|
||||
# via event-management
|
||||
pyyaml==6.0.2
|
||||
# via poethepoet
|
||||
sniffio==1.3.1
|
||||
|
|
0
src/settings.py
Normal file
0
src/settings.py
Normal file
0
src/utils/__init__.py
Normal file
0
src/utils/__init__.py
Normal file
91
src/utils/config.py
Normal file
91
src/utils/config.py
Normal file
|
@ -0,0 +1,91 @@
|
|||
"""File containing a typed wrapper function around ``decouple.config``."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from typing import Any, NewType, TypeVar, cast, overload
|
||||
|
||||
from decouple import UndefinedValueError, config
|
||||
|
||||
__all__ = ["get_config"]
|
||||
|
||||
T = TypeVar("T")
|
||||
U = TypeVar("U")
|
||||
Sentinel = NewType("Sentinel", object)
|
||||
_MISSING = cast(Sentinel, object())
|
||||
|
||||
|
||||
@overload
|
||||
def get_config(
|
||||
search_path: str,
|
||||
*,
|
||||
cast: None = None,
|
||||
default: U | Sentinel = _MISSING,
|
||||
) -> str | U: ...
|
||||
|
||||
|
||||
@overload
|
||||
def get_config(
|
||||
search_path: str,
|
||||
*,
|
||||
cast: Callable[[str], T],
|
||||
default: U | Sentinel = _MISSING,
|
||||
) -> T | U: ...
|
||||
|
||||
|
||||
def get_config(
|
||||
search_path: str,
|
||||
*,
|
||||
cast: Callable[[str], object] | None = None,
|
||||
default: object = _MISSING,
|
||||
) -> object:
|
||||
"""Typed wrapper around ``decouple.config`` for static type analysis."""
|
||||
try:
|
||||
val = config(search_path)
|
||||
except UndefinedValueError as exc:
|
||||
if default is not _MISSING:
|
||||
return default
|
||||
raise exc from exc
|
||||
|
||||
# Treat empty strings as unset values
|
||||
if val == "":
|
||||
if default is not _MISSING:
|
||||
return default
|
||||
|
||||
raise UndefinedValueError(
|
||||
f"{search_path} was found, but the content was an empty string. "
|
||||
"Set a non-empty value for the envvar or define a default value."
|
||||
)
|
||||
|
||||
# We run this again, this time with a cast function.
|
||||
# the reason we don't do this immediately is that the empty strings might not
|
||||
# work with the cast function, which could raise various exceptions.
|
||||
if cast is None:
|
||||
cast = lambda x: x
|
||||
return config(search_path, cast=cast)
|
||||
|
||||
|
||||
@overload
|
||||
def config_cast_list(cast: None = None) -> Callable[[str], list[str]]: ...
|
||||
|
||||
|
||||
@overload
|
||||
def config_cast_list(cast: Callable[[str], T]) -> Callable[[str], list[T]]: ...
|
||||
|
||||
|
||||
def config_cast_list(cast: Callable[[str], object] | None = None) -> Callable[[str], list[Any]]:
|
||||
"""Cast function to convert the content of an environmental variable to a list of values.
|
||||
|
||||
This works by splitting the contents of the environmental variable on `,` characters.
|
||||
Currently, there is not support for escaping here, so list variables that require `,`
|
||||
symbol to be present will not work.
|
||||
|
||||
You can use this function in :func:`get_config` for the ``cast`` argument.
|
||||
"""
|
||||
if cast is None or cast is str: # type: ignore[reportUnnecessaryComparison] # str is infact a subtype of (str) -> object
|
||||
cast = lambda x: x
|
||||
|
||||
def inner(raw_value: str) -> list[Any]:
|
||||
return [cast(x) for x in raw_value.split(",") if x]
|
||||
|
||||
return inner
|
Loading…
Reference in a new issue