Coverage for src/configuraptor/abs.py: 100%

1"""

2 Contains the Abstract config class shared by TypedConfig and BinaryConfig.

3"""

4

5 import os

6 import types

7 import typing

8 from pathlib import Path

9

10 import dotenv

11 from dotenv import find_dotenv

12

13# T is a reusable typevar

14 T = typing.TypeVar("T")

15# t_typelike is anything that can be type hinted

16 T_typelike: typing.TypeAlias = type | types.UnionType # | typing.Union

17# t_data is anything that can be fed to _load_data

18 T_data_types = str | Path | bytes | dict[str, typing.Any] | None

19 T_data = T_data_types | list[T_data_types]

20

21# c = a config class instance, can be any (user-defined) class

22 C = typing.TypeVar("C")

23# type c is a config class

24 Type_C = typing.Type[C]

25

26 AnyType: typing.TypeAlias = typing.Type[typing.Any]

27 T_Type = typing.TypeVar("T_Type", bound=AnyType)

28

29 UseEnvSetting = typing.Literal["yes", "inverse", "dotenv", "environ", "no"]

30 DEFAULT_ENV_SETTING: UseEnvSetting = "yes"

31

32

33 class AbstractTypedConfig:

34 """

35 These functions only exist on the class, not on instances.

36 """

37

38 @classmethod

39 def load(

40 cls: typing.Type[C],

41 data: T_data = None,

42 key: str = None,

43 init: dict[str, typing.Any] = None,

44 strict: bool = True,

45 lower_keys: bool = False,

46 convert_types: bool = False,

47 use_env: UseEnvSetting = DEFAULT_ENV_SETTING,

48 ) -> C:

49 """

50 Load a class' config values from the config file.

51

52 SomeClass.load(data, ...) = load_into(SomeClass, data, ...).

53 """

54 from .core import load_into

55

56 return load_into(

57 cls,

58 data,

59 key=key,

60 init=init,

61 strict=strict,

62 lower_keys=lower_keys,

63 convert_types=convert_types,

64 use_env=use_env,

65 )

66

67 @classmethod

68 def from_env(

69 cls: typing.Type[C],

70 load_dotenv: str | bool = False,

71 init: dict[str, typing.Any] = None,

72 strict: bool = True,

73 convert_types: bool = True,

74 ) -> C:

75 """

76 Create an instance of the typed config class by loading environment variables and initializing \

77 object attributes based on those values.

78

79 Args:

80 cls (typing.Type[C]): The class to create an instance of.

81 init (dict[str, typing.Any], optional): Additional initialization data to be used

82 in the object creation. Defaults to None.

83 strict (bool, optional): If True, raise an error if any required environment variable

84 is missing. Defaults to True.

85 convert_types (bool, optional): If True, attempt to convert environment variable values

86 to the appropriate Python types. Defaults to False.

87 load_dotenv (str | bool, optional): Path to a dotenv file or True to load the default

88 dotenv file. If False, no dotenv file will be loaded. Defaults to False.

89

90 Returns:

91 C: An instance of the class `C` with attributes initialized based on the environment variables.

92 """

93 from .core import load_into

94

95 if load_dotenv:

96 dotenv_path = load_dotenv if isinstance(load_dotenv, str) else find_dotenv(usecwd=True)

97 dotenv.load_dotenv(dotenv_path)

98

99 data = {**os.environ}

100

101 return load_into(cls, data, lower_keys=True, init=init, strict=strict, convert_types=convert_types)