snowflake-cli-labs 3.0.0rc5__py3-none-any.whl → 3.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (244) hide show
  1. README.md +21 -0
  2. {snowflake_cli_labs-3.0.0rc5.dist-info → snowflake_cli_labs-3.0.2.dist-info}/METADATA +6 -96
  3. snowflake_cli_labs-3.0.2.dist-info/RECORD +5 -0
  4. snowflake/cli/__about__.py +0 -17
  5. snowflake/cli/__init__.py +0 -13
  6. snowflake/cli/_app/__init__.py +0 -22
  7. snowflake/cli/_app/__main__.py +0 -31
  8. snowflake/cli/_app/api_impl/__init__.py +0 -13
  9. snowflake/cli/_app/api_impl/plugin/__init__.py +0 -13
  10. snowflake/cli/_app/api_impl/plugin/plugin_config_provider_impl.py +0 -66
  11. snowflake/cli/_app/cli_app.py +0 -252
  12. snowflake/cli/_app/commands_registration/__init__.py +0 -33
  13. snowflake/cli/_app/commands_registration/builtin_plugins.py +0 -50
  14. snowflake/cli/_app/commands_registration/command_plugins_loader.py +0 -169
  15. snowflake/cli/_app/commands_registration/commands_registration_with_callbacks.py +0 -105
  16. snowflake/cli/_app/commands_registration/exception_logging.py +0 -26
  17. snowflake/cli/_app/commands_registration/threadsafe.py +0 -48
  18. snowflake/cli/_app/commands_registration/typer_registration.py +0 -153
  19. snowflake/cli/_app/constants.py +0 -19
  20. snowflake/cli/_app/dev/__init__.py +0 -13
  21. snowflake/cli/_app/dev/commands_structure.py +0 -48
  22. snowflake/cli/_app/dev/docs/__init__.py +0 -13
  23. snowflake/cli/_app/dev/docs/commands_docs_generator.py +0 -118
  24. snowflake/cli/_app/dev/docs/generator.py +0 -35
  25. snowflake/cli/_app/dev/docs/project_definition_docs_generator.py +0 -58
  26. snowflake/cli/_app/dev/docs/project_definition_generate_json_schema.py +0 -227
  27. snowflake/cli/_app/dev/docs/template_utils.py +0 -23
  28. snowflake/cli/_app/dev/docs/templates/definition_description.rst.jinja2 +0 -38
  29. snowflake/cli/_app/dev/docs/templates/overview.rst.jinja2 +0 -9
  30. snowflake/cli/_app/dev/docs/templates/usage.rst.jinja2 +0 -67
  31. snowflake/cli/_app/dev/pycharm_remote_debug.py +0 -46
  32. snowflake/cli/_app/loggers.py +0 -199
  33. snowflake/cli/_app/main_typer.py +0 -62
  34. snowflake/cli/_app/printing.py +0 -181
  35. snowflake/cli/_app/secret.py +0 -9
  36. snowflake/cli/_app/snow_connector.py +0 -309
  37. snowflake/cli/_app/telemetry.py +0 -220
  38. snowflake/cli/_app/version_check.py +0 -74
  39. snowflake/cli/_plugins/__init__.py +0 -13
  40. snowflake/cli/_plugins/connection/__init__.py +0 -13
  41. snowflake/cli/_plugins/connection/commands.py +0 -353
  42. snowflake/cli/_plugins/connection/plugin_spec.py +0 -30
  43. snowflake/cli/_plugins/connection/util.py +0 -195
  44. snowflake/cli/_plugins/cortex/__init__.py +0 -13
  45. snowflake/cli/_plugins/cortex/commands.py +0 -332
  46. snowflake/cli/_plugins/cortex/constants.py +0 -17
  47. snowflake/cli/_plugins/cortex/manager.py +0 -189
  48. snowflake/cli/_plugins/cortex/plugin_spec.py +0 -30
  49. snowflake/cli/_plugins/cortex/types.py +0 -22
  50. snowflake/cli/_plugins/git/__init__.py +0 -13
  51. snowflake/cli/_plugins/git/commands.py +0 -358
  52. snowflake/cli/_plugins/git/manager.py +0 -151
  53. snowflake/cli/_plugins/git/plugin_spec.py +0 -30
  54. snowflake/cli/_plugins/helpers/__init__.py +0 -13
  55. snowflake/cli/_plugins/helpers/commands.py +0 -90
  56. snowflake/cli/_plugins/helpers/plugin_spec.py +0 -30
  57. snowflake/cli/_plugins/init/__init__.py +0 -13
  58. snowflake/cli/_plugins/init/commands.py +0 -248
  59. snowflake/cli/_plugins/init/plugin_spec.py +0 -30
  60. snowflake/cli/_plugins/nativeapp/__init__.py +0 -13
  61. snowflake/cli/_plugins/nativeapp/artifacts.py +0 -757
  62. snowflake/cli/_plugins/nativeapp/bundle_context.py +0 -31
  63. snowflake/cli/_plugins/nativeapp/codegen/__init__.py +0 -13
  64. snowflake/cli/_plugins/nativeapp/codegen/artifact_processor.py +0 -91
  65. snowflake/cli/_plugins/nativeapp/codegen/compiler.py +0 -149
  66. snowflake/cli/_plugins/nativeapp/codegen/sandbox.py +0 -306
  67. snowflake/cli/_plugins/nativeapp/codegen/setup/native_app_setup_processor.py +0 -249
  68. snowflake/cli/_plugins/nativeapp/codegen/setup/setup_driver.py.source +0 -59
  69. snowflake/cli/_plugins/nativeapp/codegen/snowpark/callback_source.py.jinja +0 -181
  70. snowflake/cli/_plugins/nativeapp/codegen/snowpark/extension_function_utils.py +0 -217
  71. snowflake/cli/_plugins/nativeapp/codegen/snowpark/models.py +0 -61
  72. snowflake/cli/_plugins/nativeapp/codegen/snowpark/python_processor.py +0 -523
  73. snowflake/cli/_plugins/nativeapp/codegen/templates/templates_processor.py +0 -114
  74. snowflake/cli/_plugins/nativeapp/commands.py +0 -559
  75. snowflake/cli/_plugins/nativeapp/common_flags.py +0 -44
  76. snowflake/cli/_plugins/nativeapp/constants.py +0 -27
  77. snowflake/cli/_plugins/nativeapp/entities/__init__.py +0 -0
  78. snowflake/cli/_plugins/nativeapp/entities/application.py +0 -878
  79. snowflake/cli/_plugins/nativeapp/entities/application_package.py +0 -1392
  80. snowflake/cli/_plugins/nativeapp/exceptions.py +0 -113
  81. snowflake/cli/_plugins/nativeapp/feature_flags.py +0 -24
  82. snowflake/cli/_plugins/nativeapp/manager.py +0 -415
  83. snowflake/cli/_plugins/nativeapp/plugin_spec.py +0 -30
  84. snowflake/cli/_plugins/nativeapp/policy.py +0 -53
  85. snowflake/cli/_plugins/nativeapp/project_model.py +0 -211
  86. snowflake/cli/_plugins/nativeapp/run_processor.py +0 -184
  87. snowflake/cli/_plugins/nativeapp/same_account_install_method.py +0 -70
  88. snowflake/cli/_plugins/nativeapp/teardown_processor.py +0 -70
  89. snowflake/cli/_plugins/nativeapp/utils.py +0 -98
  90. snowflake/cli/_plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +0 -262
  91. snowflake/cli/_plugins/nativeapp/version/__init__.py +0 -13
  92. snowflake/cli/_plugins/nativeapp/version/commands.py +0 -141
  93. snowflake/cli/_plugins/nativeapp/version/version_processor.py +0 -98
  94. snowflake/cli/_plugins/notebook/__init__.py +0 -13
  95. snowflake/cli/_plugins/notebook/commands.py +0 -86
  96. snowflake/cli/_plugins/notebook/exceptions.py +0 -20
  97. snowflake/cli/_plugins/notebook/manager.py +0 -71
  98. snowflake/cli/_plugins/notebook/plugin_spec.py +0 -30
  99. snowflake/cli/_plugins/notebook/types.py +0 -15
  100. snowflake/cli/_plugins/object/__init__.py +0 -13
  101. snowflake/cli/_plugins/object/command_aliases.py +0 -95
  102. snowflake/cli/_plugins/object/commands.py +0 -180
  103. snowflake/cli/_plugins/object/common.py +0 -85
  104. snowflake/cli/_plugins/object/manager.py +0 -118
  105. snowflake/cli/_plugins/object/plugin_spec.py +0 -30
  106. snowflake/cli/_plugins/snowpark/__init__.py +0 -13
  107. snowflake/cli/_plugins/snowpark/commands.py +0 -450
  108. snowflake/cli/_plugins/snowpark/common.py +0 -268
  109. snowflake/cli/_plugins/snowpark/models.py +0 -150
  110. snowflake/cli/_plugins/snowpark/package/__init__.py +0 -13
  111. snowflake/cli/_plugins/snowpark/package/anaconda_packages.py +0 -199
  112. snowflake/cli/_plugins/snowpark/package/commands.py +0 -195
  113. snowflake/cli/_plugins/snowpark/package/manager.py +0 -44
  114. snowflake/cli/_plugins/snowpark/package/utils.py +0 -26
  115. snowflake/cli/_plugins/snowpark/package_utils.py +0 -354
  116. snowflake/cli/_plugins/snowpark/plugin_spec.py +0 -30
  117. snowflake/cli/_plugins/snowpark/snowpark_entity.py +0 -29
  118. snowflake/cli/_plugins/snowpark/snowpark_entity_model.py +0 -173
  119. snowflake/cli/_plugins/snowpark/snowpark_project_paths.py +0 -109
  120. snowflake/cli/_plugins/snowpark/snowpark_shared.py +0 -59
  121. snowflake/cli/_plugins/snowpark/zipper.py +0 -89
  122. snowflake/cli/_plugins/spcs/__init__.py +0 -33
  123. snowflake/cli/_plugins/spcs/common.py +0 -99
  124. snowflake/cli/_plugins/spcs/compute_pool/__init__.py +0 -13
  125. snowflake/cli/_plugins/spcs/compute_pool/commands.py +0 -241
  126. snowflake/cli/_plugins/spcs/compute_pool/manager.py +0 -121
  127. snowflake/cli/_plugins/spcs/image_registry/__init__.py +0 -13
  128. snowflake/cli/_plugins/spcs/image_registry/commands.py +0 -65
  129. snowflake/cli/_plugins/spcs/image_registry/manager.py +0 -105
  130. snowflake/cli/_plugins/spcs/image_repository/__init__.py +0 -13
  131. snowflake/cli/_plugins/spcs/image_repository/commands.py +0 -202
  132. snowflake/cli/_plugins/spcs/image_repository/manager.py +0 -84
  133. snowflake/cli/_plugins/spcs/plugin_spec.py +0 -30
  134. snowflake/cli/_plugins/spcs/services/__init__.py +0 -13
  135. snowflake/cli/_plugins/spcs/services/commands.py +0 -345
  136. snowflake/cli/_plugins/spcs/services/manager.py +0 -208
  137. snowflake/cli/_plugins/sql/__init__.py +0 -13
  138. snowflake/cli/_plugins/sql/commands.py +0 -86
  139. snowflake/cli/_plugins/sql/manager.py +0 -92
  140. snowflake/cli/_plugins/sql/plugin_spec.py +0 -30
  141. snowflake/cli/_plugins/sql/snowsql_templating.py +0 -28
  142. snowflake/cli/_plugins/stage/__init__.py +0 -13
  143. snowflake/cli/_plugins/stage/commands.py +0 -264
  144. snowflake/cli/_plugins/stage/diff.py +0 -280
  145. snowflake/cli/_plugins/stage/manager.py +0 -582
  146. snowflake/cli/_plugins/stage/md5.py +0 -160
  147. snowflake/cli/_plugins/stage/plugin_spec.py +0 -30
  148. snowflake/cli/_plugins/stage/utils.py +0 -54
  149. snowflake/cli/_plugins/streamlit/__init__.py +0 -13
  150. snowflake/cli/_plugins/streamlit/commands.py +0 -195
  151. snowflake/cli/_plugins/streamlit/manager.py +0 -220
  152. snowflake/cli/_plugins/streamlit/plugin_spec.py +0 -30
  153. snowflake/cli/_plugins/streamlit/streamlit_entity.py +0 -12
  154. snowflake/cli/_plugins/streamlit/streamlit_entity_model.py +0 -66
  155. snowflake/cli/_plugins/workspace/__init__.py +0 -13
  156. snowflake/cli/_plugins/workspace/action_context.py +0 -18
  157. snowflake/cli/_plugins/workspace/commands.py +0 -306
  158. snowflake/cli/_plugins/workspace/manager.py +0 -74
  159. snowflake/cli/_plugins/workspace/plugin_spec.py +0 -30
  160. snowflake/cli/api/__init__.py +0 -48
  161. snowflake/cli/api/cli_global_context.py +0 -247
  162. snowflake/cli/api/commands/__init__.py +0 -13
  163. snowflake/cli/api/commands/alias.py +0 -23
  164. snowflake/cli/api/commands/common.py +0 -25
  165. snowflake/cli/api/commands/decorators.py +0 -369
  166. snowflake/cli/api/commands/execution_metadata.py +0 -40
  167. snowflake/cli/api/commands/experimental_behaviour.py +0 -18
  168. snowflake/cli/api/commands/flags.py +0 -561
  169. snowflake/cli/api/commands/overrideable_parameter.py +0 -143
  170. snowflake/cli/api/commands/snow_typer.py +0 -247
  171. snowflake/cli/api/commands/utils.py +0 -18
  172. snowflake/cli/api/config.py +0 -380
  173. snowflake/cli/api/connections.py +0 -216
  174. snowflake/cli/api/console/__init__.py +0 -17
  175. snowflake/cli/api/console/abc.py +0 -94
  176. snowflake/cli/api/console/console.py +0 -134
  177. snowflake/cli/api/console/enum.py +0 -17
  178. snowflake/cli/api/constants.py +0 -90
  179. snowflake/cli/api/entities/common.py +0 -56
  180. snowflake/cli/api/entities/utils.py +0 -370
  181. snowflake/cli/api/errno.py +0 -28
  182. snowflake/cli/api/exceptions.py +0 -190
  183. snowflake/cli/api/feature_flags.py +0 -54
  184. snowflake/cli/api/identifiers.py +0 -190
  185. snowflake/cli/api/metrics.py +0 -92
  186. snowflake/cli/api/output/__init__.py +0 -13
  187. snowflake/cli/api/output/formats.py +0 -20
  188. snowflake/cli/api/output/types.py +0 -118
  189. snowflake/cli/api/plugins/__init__.py +0 -13
  190. snowflake/cli/api/plugins/command/__init__.py +0 -72
  191. snowflake/cli/api/plugins/command/plugin_hook_specs.py +0 -21
  192. snowflake/cli/api/plugins/plugin_config.py +0 -32
  193. snowflake/cli/api/project/__init__.py +0 -13
  194. snowflake/cli/api/project/definition.py +0 -126
  195. snowflake/cli/api/project/definition_conversion.py +0 -400
  196. snowflake/cli/api/project/definition_manager.py +0 -145
  197. snowflake/cli/api/project/errors.py +0 -56
  198. snowflake/cli/api/project/project_verification.py +0 -23
  199. snowflake/cli/api/project/schemas/__init__.py +0 -13
  200. snowflake/cli/api/project/schemas/entities/__init__.py +0 -13
  201. snowflake/cli/api/project/schemas/entities/common.py +0 -153
  202. snowflake/cli/api/project/schemas/entities/entities.py +0 -61
  203. snowflake/cli/api/project/schemas/project_definition.py +0 -330
  204. snowflake/cli/api/project/schemas/template.py +0 -77
  205. snowflake/cli/api/project/schemas/updatable_model.py +0 -202
  206. snowflake/cli/api/project/schemas/v1/__init__.py +0 -0
  207. snowflake/cli/api/project/schemas/v1/identifier_model.py +0 -51
  208. snowflake/cli/api/project/schemas/v1/native_app/__init__.py +0 -0
  209. snowflake/cli/api/project/schemas/v1/native_app/application.py +0 -61
  210. snowflake/cli/api/project/schemas/v1/native_app/native_app.py +0 -93
  211. snowflake/cli/api/project/schemas/v1/native_app/package.py +0 -84
  212. snowflake/cli/api/project/schemas/v1/native_app/path_mapping.py +0 -65
  213. snowflake/cli/api/project/schemas/v1/snowpark/__init__.py +0 -0
  214. snowflake/cli/api/project/schemas/v1/snowpark/argument.py +0 -28
  215. snowflake/cli/api/project/schemas/v1/snowpark/callable.py +0 -69
  216. snowflake/cli/api/project/schemas/v1/snowpark/snowpark.py +0 -36
  217. snowflake/cli/api/project/schemas/v1/streamlit/__init__.py +0 -0
  218. snowflake/cli/api/project/schemas/v1/streamlit/streamlit.py +0 -47
  219. snowflake/cli/api/project/util.py +0 -278
  220. snowflake/cli/api/rendering/__init__.py +0 -13
  221. snowflake/cli/api/rendering/jinja.py +0 -118
  222. snowflake/cli/api/rendering/project_definition_templates.py +0 -43
  223. snowflake/cli/api/rendering/project_templates.py +0 -98
  224. snowflake/cli/api/rendering/sql_templates.py +0 -105
  225. snowflake/cli/api/rest_api.py +0 -178
  226. snowflake/cli/api/sanitizers.py +0 -43
  227. snowflake/cli/api/secure_path.py +0 -360
  228. snowflake/cli/api/secure_utils.py +0 -118
  229. snowflake/cli/api/sql_execution.py +0 -280
  230. snowflake/cli/api/utils/__init__.py +0 -13
  231. snowflake/cli/api/utils/cursor.py +0 -34
  232. snowflake/cli/api/utils/definition_rendering.py +0 -415
  233. snowflake/cli/api/utils/dict_utils.py +0 -73
  234. snowflake/cli/api/utils/error_handling.py +0 -23
  235. snowflake/cli/api/utils/graph.py +0 -97
  236. snowflake/cli/api/utils/models.py +0 -63
  237. snowflake/cli/api/utils/naming_utils.py +0 -13
  238. snowflake/cli/api/utils/path_utils.py +0 -36
  239. snowflake/cli/api/utils/templating_functions.py +0 -144
  240. snowflake/cli/api/utils/types.py +0 -35
  241. snowflake_cli_labs-3.0.0rc5.dist-info/RECORD +0 -242
  242. snowflake_cli_labs-3.0.0rc5.dist-info/entry_points.txt +0 -2
  243. {snowflake_cli_labs-3.0.0rc5.dist-info → snowflake_cli_labs-3.0.2.dist-info}/WHEEL +0 -0
  244. {snowflake_cli_labs-3.0.0rc5.dist-info → snowflake_cli_labs-3.0.2.dist-info}/licenses/LICENSE +0 -0
@@ -1,330 +0,0 @@
1
- # Copyright (c) 2024 Snowflake Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- from __future__ import annotations
16
-
17
- from dataclasses import dataclass
18
- from typing import Any, Dict, List, Optional, Union
19
-
20
- from packaging.version import Version
21
- from pydantic import Field, ValidationError, field_validator, model_validator
22
- from snowflake.cli._plugins.nativeapp.entities.application import ApplicationEntityModel
23
- from snowflake.cli.api.project.errors import SchemaValidationError
24
- from snowflake.cli.api.project.schemas.entities.common import (
25
- TargetField,
26
- )
27
- from snowflake.cli.api.project.schemas.entities.entities import (
28
- EntityModel,
29
- v2_entity_model_types_map,
30
- )
31
- from snowflake.cli.api.project.schemas.updatable_model import UpdatableModel
32
- from snowflake.cli.api.project.schemas.v1.native_app.native_app import (
33
- NativeApp,
34
- NativeAppV11,
35
- )
36
- from snowflake.cli.api.project.schemas.v1.snowpark.snowpark import Snowpark
37
- from snowflake.cli.api.project.schemas.v1.streamlit.streamlit import Streamlit
38
- from snowflake.cli.api.utils.types import Context
39
- from typing_extensions import Annotated
40
-
41
- AnnotatedEntity = Annotated[EntityModel, Field(discriminator="type")]
42
- scalar = str | int | float | bool
43
-
44
-
45
- @dataclass
46
- class ProjectProperties:
47
- """
48
- This class stores 2 objects representing the snowflake project:
49
-
50
- The project_context object:
51
- - Used as the context for templating when users reference variables in the project definition file.
52
-
53
- The project_definition object:
54
- - This is a transformed object type through Pydantic, which has been normalized.
55
- - This object could have slightly different structure than what the users see in their yaml project definition files.
56
- - This should be used for the business logic of snow CLI modules.
57
- """
58
-
59
- project_definition: ProjectDefinition
60
- project_context: Context
61
-
62
-
63
- @dataclass
64
- class YamlOverride:
65
- data: dict | list
66
-
67
-
68
- class _ProjectDefinitionBase(UpdatableModel):
69
- def __init__(self, *args, **kwargs):
70
- try:
71
- super().__init__(**kwargs)
72
- except ValidationError as e:
73
- raise SchemaValidationError(e) from e
74
-
75
- definition_version: Union[str, int] = Field(
76
- title="Version of the project definition schema, which is currently 1",
77
- )
78
-
79
- @field_validator("definition_version")
80
- @classmethod
81
- def _is_supported_version(cls, version: str) -> str:
82
- version = str(version)
83
- version_map = get_version_map()
84
- if version not in version_map:
85
- raise ValueError(
86
- f'Version {version} is not supported. Supported versions: {", ".join(version_map)}'
87
- )
88
- return version
89
-
90
- def meets_version_requirement(self, required_version: str) -> bool:
91
- return Version(self.definition_version) >= Version(required_version)
92
-
93
-
94
- class DefinitionV10(_ProjectDefinitionBase):
95
- native_app: Optional[NativeApp] = Field(
96
- title="Native app definitions for the project", default=None
97
- )
98
- snowpark: Optional[Snowpark] = Field(
99
- title="Snowpark functions and procedures definitions for the project",
100
- default=None,
101
- )
102
- streamlit: Optional[Streamlit] = Field(
103
- title="Streamlit definitions for the project", default=None
104
- )
105
-
106
-
107
- class DefinitionV11(DefinitionV10):
108
- native_app: Optional[NativeAppV11] = Field(
109
- title="Native app definitions for the project", default=None
110
- )
111
- env: Optional[Dict[str, Union[str, int, bool]]] = Field(
112
- title="Default environment specification for this project.",
113
- default=None,
114
- )
115
-
116
-
117
- class DefinitionV20(_ProjectDefinitionBase):
118
- entities: Dict[str, AnnotatedEntity] = Field(title="Entity definitions.")
119
-
120
- @model_validator(mode="after")
121
- def validate_entities_identifiers(self):
122
- for key, entity in self.entities.items():
123
- entity.set_entity_id(key)
124
- entity.validate_identifier()
125
- return self
126
-
127
- @field_validator("entities", mode="after")
128
- @classmethod
129
- def validate_entities(
130
- cls, entities: Dict[str, AnnotatedEntity]
131
- ) -> Dict[str, AnnotatedEntity]:
132
- for key, entity in entities.items():
133
- # TODO Automatically detect TargetFields to validate
134
- if isinstance(entity, list):
135
- for e in entity:
136
- cls._validate_single_entity(e, entities)
137
- else:
138
- cls._validate_single_entity(entity, entities)
139
- return entities
140
-
141
- @classmethod
142
- def _validate_single_entity(
143
- cls, entity: EntityModel, entities: Dict[str, AnnotatedEntity]
144
- ):
145
- if entity.type == ApplicationEntityModel.get_type():
146
- if isinstance(entity.from_, TargetField):
147
- target_key = entity.from_.target
148
- target_object = entity.from_
149
- target_type = target_object.get_type()
150
- cls._validate_target_field(target_key, target_type, entities)
151
-
152
- @classmethod
153
- def _validate_target_field(
154
- cls, target_key: str, target_type: EntityModel, entities: Dict[str, EntityModel]
155
- ):
156
- if target_key not in entities:
157
- raise ValueError(f"No such target: {target_key}")
158
-
159
- # Validate the target type
160
- actual_target_type = entities[target_key].__class__
161
- if target_type and target_type is not actual_target_type:
162
- raise ValueError(
163
- f"Target type mismatch. Expected {target_type.__name__}, got {actual_target_type.__name__}"
164
- )
165
-
166
- env: Optional[Dict[str, Union[str, int, bool]]] = Field(
167
- title="Default environment specification for this project.",
168
- default=None,
169
- )
170
-
171
- mixins: Optional[Dict[str, Dict]] = Field(
172
- title="Mixins to apply to entities",
173
- default=None,
174
- )
175
-
176
- @model_validator(mode="before")
177
- @classmethod
178
- def apply_mixins(cls, data: Dict) -> Dict:
179
- """
180
- Applies mixins to those entities, whose meta field contains the mixin name.
181
- """
182
- if "mixins" not in data or "entities" not in data:
183
- return data
184
-
185
- entities = data["entities"]
186
- for entity_name, entity in entities.items():
187
- entity_mixins = entity_mixins_to_list(
188
- entity.get("meta", {}).get("use_mixins")
189
- )
190
-
191
- merged_values = cls._merge_mixins_with_entity(
192
- entity_id=entity_name,
193
- entity=entity,
194
- entity_mixins_names=entity_mixins,
195
- mixin_defs=data["mixins"],
196
- )
197
- entities[entity_name] = merged_values
198
- return data
199
-
200
- @classmethod
201
- def _merge_mixins_with_entity(
202
- cls,
203
- entity_id: str,
204
- entity: dict,
205
- entity_mixins_names: list,
206
- mixin_defs: dict,
207
- ) -> dict:
208
- # Validate mixins
209
- for mixin_name in entity_mixins_names:
210
- if mixin_name not in mixin_defs:
211
- raise ValueError(f"Mixin {mixin_name} not defined")
212
-
213
- # Build object override data from mixins
214
- data: dict = {}
215
- for mx_name in entity_mixins_names:
216
- data = cls._merge_data(data, mixin_defs[mx_name])
217
-
218
- for key, override_value in data.items():
219
- if key not in get_allowed_fields_for_entity(entity):
220
- raise ValueError(
221
- f"Unsupported key '{key}' for entity {entity_id} of type {entity['type']} "
222
- )
223
-
224
- entity_value = entity.get(key)
225
- if (
226
- entity_value is not None
227
- and not isinstance(entity_value, YamlOverride)
228
- and not isinstance(entity_value, type(override_value))
229
- ):
230
- raise ValueError(
231
- f"Value from mixins for property {key} is of type '{type(override_value).__name__}' "
232
- f"while entity {entity_id} expects value of type '{type(entity_value).__name__}'"
233
- )
234
-
235
- # Apply entity data on top of mixins
236
- data = cls._merge_data(data, entity)
237
- return data
238
-
239
- @classmethod
240
- def _merge_data(
241
- cls,
242
- left: dict | list | scalar | None,
243
- right: dict | list | scalar | None | YamlOverride,
244
- ):
245
- """
246
- Merges right data into left. Right and left is expected to be of the same type, if not right is returned.
247
- If left is sequence then missing elements from right are appended.
248
- If left is dictionary then we update it with data from right. The update is done recursively key by key.
249
- """
250
- if isinstance(right, YamlOverride):
251
- return right.data
252
-
253
- if left is None:
254
- return right
255
-
256
- # At that point left and right are of the same type
257
- if isinstance(left, dict) and isinstance(right, dict):
258
- data = dict(left)
259
- for key in right:
260
- data[key] = cls._merge_data(left=data.get(key), right=right[key])
261
- return data
262
-
263
- if isinstance(left, list) and isinstance(right, list):
264
- return _unique_extend(left, right)
265
-
266
- if not isinstance(right, type(left)):
267
- raise ValueError(f"Could not merge {type(right)} and {type(left)}.")
268
-
269
- return right
270
-
271
- def get_entities_by_type(self, entity_type: str):
272
- return {i: e for i, e in self.entities.items() if e.get_type() == entity_type}
273
-
274
-
275
- def build_project_definition(**data) -> ProjectDefinition:
276
- """
277
- Returns a ProjectDefinition instance with a version matching the provided definition_version value
278
- """
279
- if not isinstance(data, dict):
280
- return
281
- version = data.get("definition_version")
282
- version_model = get_version_map().get(str(version))
283
- if not version or not version_model:
284
- # Raises a SchemaValidationError
285
- _ProjectDefinitionBase(**data)
286
- return version_model(**data)
287
-
288
-
289
- ProjectDefinitionV1 = Union[DefinitionV10, DefinitionV11]
290
- ProjectDefinitionV2 = DefinitionV20
291
- ProjectDefinition = Union[ProjectDefinitionV1, ProjectDefinitionV2]
292
-
293
-
294
- def get_version_map():
295
- version_map = {"1": DefinitionV10, "1.1": DefinitionV11, "2": DefinitionV20}
296
- return version_map
297
-
298
-
299
- def entity_mixins_to_list(entity_mixins: Optional[str | List[str]]) -> List[str]:
300
- """
301
- Convert an optional string or a list of strings to a list of strings.
302
- """
303
- if entity_mixins is None:
304
- return []
305
- if isinstance(entity_mixins, str):
306
- return [entity_mixins]
307
- return entity_mixins
308
-
309
-
310
- def get_allowed_fields_for_entity(entity: Dict[str, Any]) -> List[str]:
311
- """
312
- Get the allowed fields for the given entity.
313
- """
314
- entity_type = entity.get("type")
315
- if entity_type is None:
316
- raise ValueError("Entity is missing type declaration.")
317
-
318
- if entity_type not in v2_entity_model_types_map:
319
- return []
320
-
321
- entity_model = v2_entity_model_types_map[entity_type]
322
- return entity_model.model_fields
323
-
324
-
325
- def _unique_extend(list_a: List, list_b: List) -> List:
326
- new_list = list(list_a)
327
- for item in list_b:
328
- if item not in list_a:
329
- new_list.append(item)
330
- return new_list
@@ -1,77 +0,0 @@
1
- # Copyright (c) 2024 Snowflake Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- from __future__ import annotations
16
-
17
- from typing import Any, List, Literal, Optional, Union
18
-
19
- import typer
20
- from click import ClickException
21
- from pydantic import BaseModel, Field
22
- from snowflake.cli.api.exceptions import InvalidTemplate
23
- from snowflake.cli.api.secure_path import SecurePath
24
-
25
-
26
- class TemplateVariable(BaseModel):
27
- name: str = Field(..., title="Variable identifier")
28
- type: Optional[Literal["string", "float", "int"]] = Field( # noqa: A003
29
- title="Type of the variable", default=None
30
- )
31
- prompt: Optional[str] = Field(title="Prompt message for the variable", default=None)
32
- default: Optional[Any] = Field(title="Default value of the variable", default=None)
33
-
34
- @property
35
- def python_type(self):
36
- # override "unchecked type" (None) with 'str', as Typer deduces type from the value of 'default'
37
- return {
38
- "string": str,
39
- "float": float,
40
- "int": int,
41
- None: str,
42
- }[self.type]
43
-
44
- def prompt_user_for_value(self, no_interactive: bool) -> Union[str, float, int]:
45
- if no_interactive:
46
- if not self.default:
47
- raise ClickException(f"Cannot determine value of variable {self.name}")
48
- return self.default
49
-
50
- prompt = self.prompt if self.prompt else self.name
51
- return typer.prompt(prompt, default=self.default, type=self.python_type)
52
-
53
-
54
- class Template(BaseModel):
55
- minimum_cli_version: Optional[str] = Field(
56
- None, title="Minimum version of Snowflake CLI supporting this template"
57
- )
58
- files_to_render: List[str] = Field(title="List of files to be rendered", default=[])
59
- variables: List[TemplateVariable] = Field(
60
- title="List of variables to be rendered", default=[]
61
- )
62
-
63
- def __init__(self, template_root: SecurePath, **kwargs):
64
- super().__init__(**kwargs)
65
- self._validate_files_exist(template_root)
66
-
67
- def _validate_files_exist(self, template_root: SecurePath) -> None:
68
- for path_in_template in self.files_to_render:
69
- full_path = template_root / path_in_template
70
- if not full_path.exists():
71
- raise InvalidTemplate(
72
- f"[files_to_render] contains not-existing file: {path_in_template}"
73
- )
74
- if full_path.is_dir():
75
- raise InvalidTemplate(
76
- f"[files_to_render] contains a dictionary: {path_in_template}"
77
- )
@@ -1,202 +0,0 @@
1
- # Copyright (c) 2024 Snowflake Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- from __future__ import annotations
16
-
17
- from contextlib import contextmanager
18
- from contextvars import ContextVar
19
- from typing import Any, Dict, Iterator, Optional
20
-
21
- from pydantic import (
22
- BaseModel,
23
- ConfigDict,
24
- Field,
25
- ValidationInfo,
26
- field_validator,
27
- )
28
- from pydantic.fields import FieldInfo
29
- from snowflake.cli.api.project.util import IDENTIFIER_NO_LENGTH
30
-
31
- PROJECT_TEMPLATE_START = "<%"
32
-
33
-
34
- def _is_templated(info: ValidationInfo, value: Any) -> bool:
35
- return (
36
- info.context
37
- and info.context.get("skip_validation_on_templates", False)
38
- and isinstance(value, str)
39
- and PROJECT_TEMPLATE_START in value
40
- )
41
-
42
-
43
- _initial_context: ContextVar[Optional[Dict[str, Any]]] = ContextVar(
44
- "_init_context_var", default=None
45
- )
46
-
47
-
48
- @contextmanager
49
- def context(value: Dict[str, Any]) -> Iterator[None]:
50
- """
51
- Thread safe context for Pydantic.
52
- By using `with context()`, you ensure context changes apply
53
- to the with block only
54
- """
55
- token = _initial_context.set(value)
56
- try:
57
- yield
58
- finally:
59
- _initial_context.reset(token)
60
-
61
-
62
- class UpdatableModel(BaseModel):
63
- model_config = ConfigDict(validate_assignment=True, extra="forbid")
64
-
65
- def __init__(self, /, **data: Any) -> None:
66
- """
67
- Pydantic provides 2 options to pass in context:
68
- 1) Through `model_validate()` as a second argument.
69
- 2) Through a custom init method and the use of ContextVar
70
-
71
- We decided not to use 1) because it silently stops working
72
- if someone adds a pass through __init__ to any of the Pydantic models.
73
-
74
- We decided to go with 2) as the safer approach.
75
- Calling validate_python() in the __init__ is how we can pass context
76
- on initialization according to Pydantic's documentation:
77
- https://docs.pydantic.dev/latest/concepts/validators/#using-validation-context-with-basemodel-initialization
78
- """
79
- self.__pydantic_validator__.validate_python(
80
- data,
81
- self_instance=self,
82
- context=_initial_context.get(),
83
- )
84
-
85
- @classmethod
86
- def _is_entity_type_field(cls, field: Any) -> bool:
87
- """
88
- Checks if a field is of type `DiscriminatorField`
89
- """
90
- if not isinstance(field, FieldInfo) or not field.json_schema_extra:
91
- return False
92
-
93
- return (
94
- "is_discriminator_field" in field.json_schema_extra
95
- and field.json_schema_extra["is_discriminator_field"]
96
- )
97
-
98
- @classmethod
99
- def __init_subclass__(cls, **kwargs):
100
- """
101
- This method will collect all the Pydantic annotations for the class
102
- currently being initialized (any subclass of `UpdatableModel`).
103
-
104
- It will add a field validator wrapper for every Pydantic field
105
- in order to skip validation when templates are found.
106
-
107
- It will apply this to all Pydantic fields, except for fields
108
- marked as `DiscriminatorField`. These will be skipped because
109
- Pydantic does not support validators for discriminator field types.
110
- """
111
-
112
- super().__init_subclass__(**kwargs)
113
-
114
- field_annotations = {}
115
- field_values = {}
116
- # Go through the inheritance classes and collect all the annotations and
117
- # all the values of the class attributes. We go in reverse order so that
118
- # values in subclasses overrides values from parent classes in case of field overrides.
119
-
120
- private_attrs = set()
121
- for class_ in reversed(cls.__mro__):
122
- class_dict = class_.__dict__
123
- field_annotations.update(class_dict.get("__annotations__", {}))
124
-
125
- if "model_fields" in class_dict:
126
- # This means the class dict has already been processed by Pydantic
127
- # All fields should properly be populated in model_fields
128
- field_values.update(class_dict["model_fields"])
129
- else:
130
- # If Pydantic did not process this class yet, get the values from class_dict directly
131
- field_values.update(class_dict)
132
- for pa in class_dict.get("__private_attributes__", []):
133
- private_attrs.add(pa)
134
-
135
- # Add Pydantic validation wrapper around all fields except `DiscriminatorField`s
136
- for field_name in field_annotations:
137
- if field_name in private_attrs:
138
- continue
139
- field = field_values.get(field_name)
140
- if not cls._is_entity_type_field(field):
141
- cls._add_validator(field_name)
142
-
143
- @classmethod
144
- def _add_validator(cls, field_name: str):
145
- """
146
- Adds a Pydantic validator with mode=wrap for the provided `field_name`.
147
- During validation, this will check if the field is templated (not expanded yet)
148
- and in that case, it will skip all the remaining Pydantic validation on that field.
149
-
150
- Since this validator is added last, it will skip all the other field validators
151
- defined in the subclasses when templates are found.
152
-
153
- This logic on templates only applies when context contains `skip_validation_on_templates` flag.
154
- """
155
-
156
- def validator_skipping_templated_str(cls, value, handler, info: ValidationInfo):
157
- if _is_templated(info, value):
158
- return value
159
- return handler(value)
160
-
161
- setattr(
162
- cls,
163
- # Unique name so that subclasses get a unique instance of this validator
164
- f"_{cls.__module__}.{cls.__name__}_validate_{field_name}",
165
- field_validator(field_name, mode="wrap")(validator_skipping_templated_str),
166
- )
167
-
168
- def update_from_dict(self, update_values: Dict[str, Any]):
169
- """
170
- Takes a dictionary with values to override.
171
- If the field type is subclass of a UpdatableModel, its update_from_dict() method is called with
172
- the value to be set.
173
- If not, we use simple setattr to set new value.
174
- Values provided are validated against original restrictions, so it's impossible to overwrite string field with
175
- integer value etc.
176
- """
177
- for field, value in update_values.items():
178
- if field in self.model_fields.keys():
179
- if (
180
- hasattr(getattr(self, field), "update_from_dict")
181
- and field in self.model_fields_set
182
- ):
183
- getattr(self, field).update_from_dict(value)
184
- else:
185
- setattr(self, field, value)
186
- return self
187
-
188
-
189
- def DiscriminatorField(*args, **kwargs): # noqa N802
190
- """
191
- Use this type for discriminator fields used for differentiating
192
- between different entity types.
193
-
194
- When this `DiscriminatorField` is used on a pydantic attribute,
195
- we will not allow templating on it.
196
- """
197
- extra = dict(is_discriminator_field=True)
198
- return Field(json_schema_extra=extra, *args, **kwargs)
199
-
200
-
201
- def IdentifierField(*args, **kwargs): # noqa N802
202
- return Field(max_length=254, pattern=IDENTIFIER_NO_LENGTH, *args, **kwargs)
File without changes
@@ -1,51 +0,0 @@
1
- # Copyright (c) 2024 Snowflake Inc.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- from __future__ import annotations
16
-
17
- from typing import Optional, cast
18
-
19
- from pydantic import Field
20
- from snowflake.cli.api.project.schemas.updatable_model import (
21
- IdentifierField,
22
- )
23
-
24
-
25
- class ObjectIdentifierBaseModel:
26
- """
27
- Type representing a base class defining object that can be identified by fully qualified name (db.schema.name).
28
- This is not a Pydantic model and the purpose of this class is to provide typing support to Pydantic models
29
- generated using a factory class ObjectIdentifierModel.
30
- """
31
-
32
- name: str
33
- database: Optional[str]
34
- schema_name: Optional[str]
35
-
36
-
37
- def ObjectIdentifierModel(object_name: str) -> ObjectIdentifierBaseModel: # noqa: N802
38
- """Generates ObjectIdentifierBaseModel but with object specific descriptions."""
39
-
40
- class _ObjectIdentifierModel(ObjectIdentifierBaseModel):
41
- name: str = Field(title=f"{object_name.capitalize()} name")
42
- database: Optional[str] = IdentifierField(
43
- title=f"Name of the database for the {object_name}", default=None
44
- )
45
- schema_name: Optional[str] = IdentifierField(
46
- title=f"Name of the schema for the {object_name}",
47
- default=None,
48
- alias="schema",
49
- )
50
-
51
- return cast(ObjectIdentifierBaseModel, _ObjectIdentifierModel)