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

29 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2026-02-11 11:38 +0100

1""" 

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

3""" 

4 

5import os 

6import types 

7import typing 

8from pathlib import Path 

9 

10import dotenv 

11from dotenv import find_dotenv 

12 

13# T is a reusable typevar 

14T = typing.TypeVar("T") 

15# t_typelike is anything that can be type hinted 

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

17# t_data is anything that can be fed to _load_data 

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

19T_data = T_data_types | list[T_data_types] 

20 

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

22C = typing.TypeVar("C") 

23# type c is a config class 

24Type_C = typing.Type[C] 

25 

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

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

28 

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

30DEFAULT_ENV_SETTING: UseEnvSetting = "yes" 

31 

32 

33class 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)