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

27 statements  

« prev     ^ index     » next       coverage.py v7.6.10, created at 2025-01-09 20:07 +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 

29 

30class AbstractTypedConfig: 

31 """ 

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

33 """ 

34 

35 @classmethod 

36 def load( 

37 cls: typing.Type[C], 

38 data: T_data = None, 

39 key: str = None, 

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

41 strict: bool = True, 

42 lower_keys: bool = False, 

43 convert_types: bool = False, 

44 ) -> C: 

45 """ 

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

47 

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

49 """ 

50 from .core import load_into 

51 

52 return load_into( 

53 cls, data, key=key, init=init, strict=strict, lower_keys=lower_keys, convert_types=convert_types 

54 ) 

55 

56 @classmethod 

57 def from_env( 

58 cls: typing.Type[C], 

59 load_dotenv: str | bool = False, 

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

61 strict: bool = True, 

62 convert_types: bool = True, 

63 ) -> C: 

64 """ 

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

66 object attributes based on those values. 

67 

68 Args: 

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

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

71 in the object creation. Defaults to None. 

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

73 is missing. Defaults to True. 

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

75 to the appropriate Python types. Defaults to False. 

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

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

78 

79 Returns: 

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

81 """ 

82 from .core import load_into 

83 

84 if load_dotenv: 

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

86 dotenv.load_dotenv(dotenv_path) 

87 

88 data = {**os.environ} 

89 

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