Coverage for src/prisma/_config.py: 100%

49 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2024-04-28 15:17 +0000

1# (we don't need to care about this check in this file) 

2# pyright: reportIncompatibleVariableOverride=false 

3from __future__ import annotations 

4 

5from typing import TYPE_CHECKING, List, Union, ClassVar, Optional 

6from pathlib import Path 

7from typing_extensions import override 

8 

9import tomlkit 

10import pydantic 

11 

12from ._proxy import LazyProxy 

13from ._compat import ( 

14 PYDANTIC_V2, 

15 Field, 

16 ConfigDict, 

17 BaseSettings, 

18 BaseSettingsConfig, 

19 model_dict, 

20 model_parse, 

21) 

22 

23 

24class DefaultConfig(BaseSettings): 

25 # CLI version 

26 # TODO: if this version changes but the engine version 

27 # doesn't change then the CLI is incorrectly cached 

28 prisma_version: str = Field( 

29 env='PRISMA_VERSION', 

30 default='5.13.0', 

31 ) 

32 

33 # Engine binary versions can be found under https://github.com/prisma/prisma-engine/commits/main 

34 expected_engine_version: str = Field( 

35 env='PRISMA_EXPECTED_ENGINE_VERSION', 

36 default='b9a39a7ee606c28e3455d0fd60e78c3ba82b1a2b', 

37 ) 

38 

39 # Home directory, used to build the `binary_cache_dir` option by default, useful in multi-user 

40 # or testing environments so that the binaries can be easily cached without having to worry 

41 # about versioning them. 

42 home_dir: Path = Field( 

43 env='PRISMA_HOME_DIR', 

44 default=Path.home(), 

45 ) 

46 

47 # Where to store the downloaded binaries 

48 binary_cache_dir: Union[Path, None] = Field( 

49 env='PRISMA_BINARY_CACHE_DIR', 

50 default=None, 

51 ) 

52 

53 # Workaround to support setting the binary platform until it can be properly implemented 

54 binary_platform: Optional[str] = Field(env='PRISMA_BINARY_PLATFORM', default=None) 

55 

56 # Whether or not to use the global node installation (if available) 

57 use_global_node: bool = Field(env='PRISMA_USE_GLOBAL_NODE', default=True) 

58 

59 # Whether or not to use the `nodejs-bin` package (if installed) 

60 use_nodejs_bin: bool = Field(env='PRISMA_USE_NODEJS_BIN', default=True) 

61 

62 # Extra arguments to pass to nodeenv, arguments are passed after the path, e.g. python -m nodeenv <path> <extra args> 

63 nodeenv_extra_args: List[str] = Field( 

64 env='PRISMA_NODEENV_EXTRA_ARGS', 

65 default_factory=list, 

66 ) 

67 

68 # Where to download nodeenv to, defaults to ~/.cache/prisma-python/nodeenv 

69 nodeenv_cache_dir: Path = Field( 

70 env='PRISMA_NODEENV_CACHE_DIR', 

71 default_factory=lambda: Path.home() / '.cache' / 'prisma-python' / 'nodeenv', 

72 ) 

73 

74 if PYDANTIC_V2: 

75 model_config: ClassVar[ConfigDict] = ConfigDict(extra='ignore') 

76 else: 

77 if not TYPE_CHECKING: 

78 

79 class Config(BaseSettingsConfig): 

80 extra: Extra = pydantic.Extra.ignore 

81 

82 @classmethod 

83 def customise_sources(cls, init_settings, env_settings, file_secret_settings): 

84 # prioritise env settings over init settings 

85 return env_settings, init_settings, file_secret_settings 

86 

87 

88class Config(DefaultConfig): 

89 binary_cache_dir: Path = Field(env='PRISMA_BINARY_CACHE_DIR') 

90 

91 @classmethod 

92 def from_base(cls, config: DefaultConfig) -> Config: 

93 if config.binary_cache_dir is None: 

94 config.binary_cache_dir = ( 

95 config.home_dir 

96 / '.cache' 

97 / 'prisma-python' 

98 / 'binaries' 

99 / config.prisma_version 

100 / config.expected_engine_version 

101 ) 

102 

103 return model_parse(cls, model_dict(config)) 

104 

105 @classmethod 

106 def load(cls, path: Path | None = None) -> Config: 

107 if path is None: 

108 path = Path('pyproject.toml') 

109 

110 if path.exists(): 

111 config = tomlkit.loads(path.read_text()).get('tool', {}).get('prisma', {}) 

112 else: 

113 config = {} 

114 

115 return cls.parse(**config) 

116 

117 @classmethod 

118 def parse(cls, **kwargs: object) -> Config: 

119 return cls.from_base(model_parse(DefaultConfig, kwargs)) 

120 

121 

122class LazyConfigProxy(LazyProxy[Config]): 

123 @override 

124 def __load__(self) -> Config: 

125 return Config.load() 

126 

127 

128config: Config = LazyConfigProxy().__as_proxied__()