snowflake-cli-labs 3.0.0rc4__py3-none-any.whl → 3.0.1__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.0rc4.dist-info → snowflake_cli_labs-3.0.1.dist-info}/METADATA +6 -96
  3. snowflake_cli_labs-3.0.1.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 -61
  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 -395
  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.0rc4.dist-info/RECORD +0 -242
  242. snowflake_cli_labs-3.0.0rc4.dist-info/entry_points.txt +0 -2
  243. {snowflake_cli_labs-3.0.0rc4.dist-info → snowflake_cli_labs-3.0.1.dist-info}/WHEEL +0 -0
  244. {snowflake_cli_labs-3.0.0rc4.dist-info → snowflake_cli_labs-3.0.1.dist-info}/licenses/LICENSE +0 -0
@@ -1,415 +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
- import copy
18
- from typing import Any, Optional
19
-
20
- from jinja2 import Environment, TemplateSyntaxError, nodes
21
- from packaging.version import Version
22
- from snowflake.cli.api.cli_global_context import get_cli_context
23
- from snowflake.cli.api.console import cli_console as cc
24
- from snowflake.cli.api.exceptions import CycleDetectedError, InvalidTemplate
25
- from snowflake.cli.api.metrics import CLICounterField
26
- from snowflake.cli.api.project.schemas.project_definition import (
27
- ProjectProperties,
28
- build_project_definition,
29
- )
30
- from snowflake.cli.api.project.schemas.updatable_model import context
31
- from snowflake.cli.api.rendering.jinja import CONTEXT_KEY, FUNCTION_KEY
32
- from snowflake.cli.api.rendering.project_definition_templates import (
33
- get_client_side_jinja_env,
34
- )
35
- from snowflake.cli.api.utils.dict_utils import deep_merge_dicts, traverse
36
- from snowflake.cli.api.utils.graph import Graph, Node
37
- from snowflake.cli.api.utils.models import ProjectEnvironment
38
- from snowflake.cli.api.utils.templating_functions import get_templating_functions
39
- from snowflake.cli.api.utils.types import Context, Definition
40
-
41
-
42
- class TemplatedEnvironment:
43
- """
44
- This class is a utility class
45
- that encapsulates some of the Jinja Templating functionality.
46
- """
47
-
48
- def __init__(self, env: Environment):
49
- self._jinja_env: Environment = env
50
-
51
- def render(self, template_value: Any, context: Context) -> Any:
52
- if not self.get_referenced_vars(template_value):
53
- return template_value
54
-
55
- jinja_template = self._jinja_env.from_string(str(template_value))
56
- return jinja_template.render(context)
57
-
58
- def get_referenced_vars(self, template_value: Any) -> set[TemplateVar]:
59
- template_str = str(template_value)
60
- try:
61
- ast = self._jinja_env.parse(template_str)
62
- except TemplateSyntaxError as e:
63
- raise InvalidTemplate(
64
- f"Error parsing template from project definition file. Value: '{template_str}'. Error: {e}"
65
- ) from e
66
-
67
- return self._get_referenced_vars(ast, template_str)
68
-
69
- def _get_referenced_vars(
70
- self,
71
- ast_node: nodes.Template,
72
- template_value: str,
73
- current_attr_chain: Optional[list[str]] = None,
74
- ) -> set[TemplateVar]:
75
- """
76
- Traverse Jinja AST to find the variable chain referenced by the template.
77
- A variable like ctx.env.test is internally represented in the AST tree as
78
- Getattr Node (attr='test') -> Getattr Node (attr='env') -> Name Node (name='ctx')
79
- """
80
- all_referenced_vars: set[TemplateVar] = set()
81
- if isinstance(ast_node, nodes.Getattr):
82
- current_attr_chain = [ast_node.attr] + (current_attr_chain or []) # type: ignore[attr-defined]
83
- elif isinstance(ast_node, nodes.Name):
84
- current_attr_chain = [ast_node.name] + (current_attr_chain or []) # type: ignore[attr-defined]
85
- all_referenced_vars.add(TemplateVar(current_attr_chain))
86
- current_attr_chain = None
87
- elif (
88
- not isinstance(
89
- ast_node,
90
- (
91
- nodes.Template,
92
- nodes.TemplateData,
93
- nodes.Output,
94
- nodes.Call,
95
- nodes.Const,
96
- nodes.Filter,
97
- ),
98
- )
99
- or current_attr_chain is not None
100
- ):
101
- raise InvalidTemplate(f"Unexpected template syntax in {template_value}")
102
-
103
- for child_node in ast_node.iter_child_nodes():
104
- all_referenced_vars.update(
105
- self._get_referenced_vars(
106
- child_node, template_value, current_attr_chain
107
- )
108
- )
109
-
110
- return all_referenced_vars
111
-
112
-
113
- class TemplateVar:
114
- """
115
- This class tracks template variable information.
116
- For a variable like ctx.env.var, this class will track
117
- the chain of keys referenced by this variable (ctx, env, var),
118
- as well as the value of this variable. (e.g. ctx.env.var = "hello_<% ctx.definition_version %>")
119
-
120
- The value of this variable is divided into 2 parts.
121
- The templated value (e.g. "hello_<% ctx.definition %>"),
122
- as well as the rendered_value (e.g. "hello_1.1")
123
- """
124
-
125
- def __init__(self, vars_chain):
126
- self._vars_chain: list[str] = list(vars_chain)
127
- self.templated_value: Optional[Any] = None
128
- self.rendered_value: Optional[Any] = None
129
-
130
- @property
131
- def key(self) -> str:
132
- return ".".join(self._vars_chain)
133
-
134
- @property
135
- def is_env_var(self) -> bool:
136
- return (
137
- len(self._vars_chain) == 3
138
- and self._vars_chain[0] == CONTEXT_KEY
139
- and self._vars_chain[1] == "env"
140
- )
141
-
142
- def get_env_var_name(self) -> str:
143
- if not self.is_env_var:
144
- raise KeyError(
145
- f"Referenced variable {self.key} is not an environment variable"
146
- )
147
- return self._vars_chain[2]
148
-
149
- def add_to_context(self, context: Context) -> None:
150
- """
151
- Takes a multi-level context dict as input. Modifies the context dict with the rendered value of this variable.
152
-
153
- If the variable has multi-levels (e.g. ctx.env), recursively traverse the dictionary
154
- to set the inner level's key to the rendered value of this variable.
155
-
156
- Example: vars chain contains ['ctx', 'env', 'x'], and context is {}, and rendered_value is 'val'.
157
- At the end of this call, context content will be: {'ctx': {'env': {'x': 'val'}}}
158
- """
159
- current_dict_level = context
160
- last_element_index = len(self._vars_chain) - 1
161
- for index, var in enumerate(self._vars_chain):
162
- if index == last_element_index:
163
- current_dict_level[var] = self.rendered_value
164
- else:
165
- current_dict_level.setdefault(var, {})
166
- current_dict_level = current_dict_level[var]
167
-
168
- def read_from_context(self, context: Context) -> Any:
169
- """
170
- Takes a multi-level context dict as input.
171
-
172
- If the variable has multi-levels (e.g. ctx.env), recursively traverse the dictionary
173
- to find the key that the variable points to.
174
-
175
- Returns the value in that location.
176
-
177
- Raise InvalidTemplate if the variable is None or not found.
178
- """
179
- current_dict_level = context
180
- for key in self._vars_chain:
181
- if (
182
- not isinstance(current_dict_level, dict)
183
- or key not in current_dict_level
184
- ):
185
- raise InvalidTemplate(f"Could not find template variable {self.key}")
186
- current_dict_level = current_dict_level[key]
187
-
188
- value = current_dict_level
189
-
190
- if value is None:
191
- raise InvalidTemplate(f"Template variable {self.key} does not have a value")
192
-
193
- if isinstance(value, (dict, list)):
194
- raise InvalidTemplate(
195
- f"Template variable {self.key} does not have a scalar value"
196
- )
197
-
198
- return value
199
-
200
- def __hash__(self):
201
- return hash(self.key)
202
-
203
- def __eq__(self, other):
204
- return self.key == other.key
205
-
206
-
207
- def _build_dependency_graph(
208
- env: TemplatedEnvironment,
209
- all_vars: set[TemplateVar],
210
- context: Context,
211
- environment_overrides: ProjectEnvironment,
212
- ) -> Graph[TemplateVar]:
213
- dependencies_graph = Graph[TemplateVar]()
214
- for variable in all_vars:
215
- dependencies_graph.add(Node[TemplateVar](key=variable.key, data=variable))
216
- for variable in all_vars:
217
- # If variable is found in os.environ or from cli override, then use the value as is
218
- # skip rendering by pre-setting the rendered_value attribute
219
- if variable.is_env_var and variable.get_env_var_name() in environment_overrides:
220
- env_value = environment_overrides.get(variable.get_env_var_name())
221
- variable.rendered_value = env_value
222
- variable.templated_value = env_value
223
- else:
224
- variable.templated_value = variable.read_from_context(context)
225
- dependencies_vars = env.get_referenced_vars(variable.templated_value)
226
-
227
- for referenced_var in dependencies_vars:
228
- dependencies_graph.add_directed_edge(variable.key, referenced_var.key)
229
-
230
- return dependencies_graph
231
-
232
-
233
- def _render_graph_node(env: TemplatedEnvironment, node: Node[TemplateVar]) -> None:
234
- if node.data.rendered_value is not None:
235
- # Do not re-evaluate resolved nodes like env variable nodes
236
- # which might contain template-like values, or non-string nodes
237
- return
238
-
239
- current_context: Context = {}
240
- for dep_node in node.neighbors:
241
- dep_node.data.add_to_context(current_context)
242
-
243
- node.data.rendered_value = env.render(node.data.templated_value, current_context)
244
-
245
-
246
- def _validate_env_section(env_section: dict):
247
- if not isinstance(env_section, dict):
248
- raise InvalidTemplate(
249
- "env section in project definition file should be a mapping"
250
- )
251
- for variable, value in env_section.items():
252
- if value is None or isinstance(value, (dict, list)):
253
- raise InvalidTemplate(
254
- f"Variable {variable} in env section of project definition file should be a scalar"
255
- )
256
-
257
-
258
- def _get_referenced_vars_in_definition(
259
- template_env: TemplatedEnvironment, definition: Definition
260
- ):
261
- referenced_vars = set()
262
-
263
- def find_any_template_vars(element):
264
- referenced_vars.update(template_env.get_referenced_vars(element))
265
-
266
- traverse(definition, visit_action=find_any_template_vars)
267
-
268
- return referenced_vars
269
-
270
-
271
- def _has_referenced_vars_in_definition(
272
- template_env: TemplatedEnvironment, definition: Definition
273
- ) -> bool:
274
- return len(_get_referenced_vars_in_definition(template_env, definition)) > 0
275
-
276
-
277
- def _template_version_warning():
278
- cc.warning(
279
- "Ignoring template pattern in project definition file. "
280
- "Update 'definition_version' to 1.1 or later in snowflake.yml to enable template expansion."
281
- )
282
-
283
-
284
- def _add_defaults_to_definition(original_definition: Definition) -> Definition:
285
- with context({"skip_validation_on_templates": True}):
286
- # pass a flag to Pydantic to skip validation for templated scalars
287
- # populate the defaults
288
- project_definition = build_project_definition(
289
- **copy.deepcopy(original_definition)
290
- )
291
-
292
- definition_with_defaults = project_definition.model_dump(
293
- exclude_none=True, warnings=False, by_alias=True
294
- )
295
- # The main purpose of the above operation was to populate defaults from Pydantic.
296
- # By merging the original definition back in, we ensure that any transformations
297
- # that Pydantic would have performed are undone.
298
- deep_merge_dicts(definition_with_defaults, original_definition)
299
- return definition_with_defaults
300
-
301
-
302
- def _update_metrics(template_env: TemplatedEnvironment, definition: Definition):
303
- metrics = get_cli_context().metrics
304
-
305
- # render_definition_template is invoked multiple times both by the user
306
- # and by us so we should make sure we don't overwrite a 1 with a 0 here
307
- metrics.set_counter_default(CLICounterField.PDF_TEMPLATES, 0)
308
-
309
- if _has_referenced_vars_in_definition(template_env, definition):
310
- metrics.set_counter(CLICounterField.PDF_TEMPLATES, 1)
311
-
312
-
313
- def render_definition_template(
314
- original_definition: Optional[Definition], context_overrides: Context
315
- ) -> ProjectProperties:
316
- """
317
- Takes a definition file as input. An arbitrary structure containing dict|list|scalars,
318
- with the top level being a dictionary.
319
- Requires item 'definition_version' to be set to a version of 1.1 and higher.
320
-
321
- Searches for any templating in all of the scalar fields, and attempts to resolve them
322
- from the definition structure itself or from the environment variable.
323
-
324
- Environment variables take precedence during the rendering process.
325
- """
326
-
327
- # copy input to protect it from update
328
- definition = copy.deepcopy(original_definition)
329
-
330
- # collect all the override --env variables passed through CLI input
331
- override_env = context_overrides.get(CONTEXT_KEY, {}).get("env", {})
332
-
333
- # set up Project Environment with empty default_env because
334
- # default env section from project definition file is still templated at this time
335
- environment_overrides = ProjectEnvironment(
336
- default_env={}, override_env=override_env
337
- )
338
-
339
- if definition is None:
340
- return ProjectProperties(None, {CONTEXT_KEY: {"env": environment_overrides}})
341
-
342
- template_env = TemplatedEnvironment(get_client_side_jinja_env())
343
-
344
- if "definition_version" not in definition or Version(
345
- definition["definition_version"]
346
- ) < Version("1.1"):
347
- try:
348
- if _has_referenced_vars_in_definition(template_env, definition):
349
- _template_version_warning()
350
- except Exception:
351
- # also warn on Exception, as it means the user is incorrectly attempting to use templating
352
- _template_version_warning()
353
-
354
- project_definition = build_project_definition(**definition)
355
- project_context = {CONTEXT_KEY: definition}
356
- project_context[CONTEXT_KEY]["env"] = environment_overrides
357
- return ProjectProperties(project_definition, project_context)
358
-
359
- # need to have the metrics added here since we add defaults to the
360
- # definition that the user might not have added themselves later
361
- _update_metrics(template_env, definition)
362
-
363
- definition = _add_defaults_to_definition(definition)
364
- project_context = {CONTEXT_KEY: definition}
365
-
366
- _validate_env_section(definition.get("env", {}))
367
-
368
- # add available templating functions
369
- project_context[FUNCTION_KEY] = get_templating_functions()
370
-
371
- referenced_vars = _get_referenced_vars_in_definition(template_env, definition)
372
-
373
- dependencies_graph = _build_dependency_graph(
374
- template_env, referenced_vars, project_context, environment_overrides
375
- )
376
-
377
- def on_cycle_action(node: Node[TemplateVar]):
378
- raise CycleDetectedError(f"Cycle detected in template variable {node.data.key}")
379
-
380
- dependencies_graph.dfs(
381
- visit_action=lambda node: _render_graph_node(template_env, node),
382
- on_cycle_action=on_cycle_action,
383
- )
384
-
385
- # now that we determined the values of all templated vars,
386
- # use these resolved values as a fresh context to resolve definition
387
- final_context: Context = {}
388
- for node in dependencies_graph.get_all_nodes():
389
- node.data.add_to_context(final_context)
390
-
391
- traverse(
392
- definition,
393
- update_action=lambda val: template_env.render(val, final_context),
394
- )
395
-
396
- project_definition = build_project_definition(**definition)
397
-
398
- # Use the values originally provided by the user as the template context
399
- # This intentionally doesn't reflect any field changes made by
400
- # validators, to minimize user surprise when templating values
401
- project_context[CONTEXT_KEY] = definition
402
-
403
- # Use `ProjectEnvironment` in project context in order to
404
- # handle env variables overrides from OS env and from CLI arguments.
405
- project_context[CONTEXT_KEY]["env"] = ProjectEnvironment(
406
- default_env=project_context[CONTEXT_KEY].get("env"), override_env=override_env
407
- )
408
- return ProjectProperties(project_definition, project_context)
409
-
410
-
411
- def raw_project_properties(definition: Definition) -> ProjectProperties:
412
- """
413
- Returns the raw project definition data without any templating.
414
- """
415
- return ProjectProperties(build_project_definition(**definition), {})
@@ -1,73 +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, Callable
18
-
19
-
20
- def deep_merge_dicts(
21
- original_values: dict[Any, Any], override_values: dict[Any, Any]
22
- ) -> None:
23
- """
24
- Takes 2 dictionaries as input: original and override. The original dictionary is modified.
25
-
26
- For every key in the override dictionary, override the same key
27
- in the original dictionary, or create a new one if the key is not present.
28
-
29
- If the override value and the original value are both dictionaries,
30
- instead of overriding, this function recursively calls itself to merge the keys of the sub-dictionaries.
31
- """
32
- if not isinstance(override_values, dict) or not isinstance(original_values, dict):
33
- raise ValueError("Arguments are not of type dict")
34
-
35
- for field, value in override_values.items():
36
- if (
37
- field in original_values
38
- and isinstance(original_values[field], dict)
39
- and isinstance(value, dict)
40
- ):
41
- deep_merge_dicts(original_values[field], value)
42
- else:
43
- original_values[field] = value
44
-
45
-
46
- def traverse(
47
- element: Any,
48
- visit_action: Callable[[Any], None] = lambda element: None,
49
- update_action: Callable[[Any], Any] = lambda element: element,
50
- ) -> Any:
51
- """
52
- Traverse a nested structure (lists, dicts, scalars).
53
-
54
- On traversal, it allows for actions or updates on each visit.
55
-
56
- visit_action: caller can provide a function to execute on each scalar element in the structure (leaves of the tree).
57
- visit_action accepts an element (scalar) as input. Return value is ignored.
58
-
59
- update_action: caller can provide a function to update each scalar element in the structure.
60
- update_action accepts an element (scalar) as input, and returns the modified value.
61
-
62
- """
63
- if isinstance(element, dict):
64
- for key, value in element.items():
65
- element[key] = traverse(value, visit_action, update_action)
66
- return element
67
- elif isinstance(element, list):
68
- for index, value in enumerate(element):
69
- element[index] = traverse(value, visit_action, update_action)
70
- return element
71
- else:
72
- visit_action(element)
73
- return update_action(element)
@@ -1,23 +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 contextlib import contextmanager
16
-
17
-
18
- @contextmanager
19
- def ignore_exceptions():
20
- try:
21
- yield
22
- except:
23
- pass
@@ -1,97 +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, field
18
- from enum import Enum
19
- from typing import Callable, Generic, TypeVar
20
-
21
- T = TypeVar("T")
22
-
23
-
24
- class VisitStatus(Enum):
25
- VISITING = 1
26
- VISITED = 2
27
-
28
-
29
- @dataclass
30
- class Node(Generic[T]):
31
- key: str
32
- data: T
33
- neighbors: set[Node[T]] = field(default_factory=set)
34
-
35
- def __hash__(self):
36
- return hash(self.key)
37
-
38
- def __eq__(self, other):
39
- return self.key == other.key
40
-
41
-
42
- class Graph(Generic[T]):
43
- def __init__(self):
44
- self._graph_nodes_map: dict[str, Node[T]] = {}
45
-
46
- def get(self, key: str) -> Node[T]:
47
- if key in self._graph_nodes_map:
48
- return self._graph_nodes_map[key]
49
- raise KeyError(f"Node with key {key} not found")
50
-
51
- def get_all_nodes(self) -> set[Node[T]]:
52
- return set(self._graph_nodes_map.values())
53
-
54
- def add(self, node: Node[T]) -> None:
55
- if node.key in self._graph_nodes_map:
56
- raise KeyError(f"Node key {node.key} already exists")
57
- self._graph_nodes_map[node.key] = node
58
-
59
- def add_directed_edge(self, from_node_key: str, to_node_key: str) -> None:
60
- from_node = self.get(from_node_key)
61
- to_node = self.get(to_node_key)
62
- from_node.neighbors.add(to_node)
63
-
64
- @staticmethod
65
- def _dfs_visit(
66
- nodes_status: dict[str, VisitStatus],
67
- node: Node[T],
68
- visit_action: Callable[[Node[T]], None],
69
- on_cycle_action: Callable[[Node[T]], None],
70
- ) -> None:
71
- if nodes_status.get(node.key) == VisitStatus.VISITED:
72
- return
73
-
74
- nodes_status[node.key] = VisitStatus.VISITING
75
- for neighbor_node in node.neighbors:
76
- if nodes_status.get(neighbor_node.key) == VisitStatus.VISITING:
77
- on_cycle_action(node)
78
- else:
79
- Graph._dfs_visit(
80
- nodes_status, neighbor_node, visit_action, on_cycle_action
81
- )
82
-
83
- visit_action(node)
84
-
85
- nodes_status[node.key] = VisitStatus.VISITED
86
-
87
- def dfs(
88
- self,
89
- visit_action: Callable[[Node[T]], None] = lambda node: None,
90
- on_cycle_action: Callable[[Node[T]], None] = lambda node: None,
91
- ) -> None:
92
- nodes_status: dict[str, VisitStatus] = {}
93
- for node in self._graph_nodes_map.values():
94
- Graph._dfs_visit(nodes_status, node, visit_action, on_cycle_action)
95
-
96
- def __contains__(self, key: str) -> bool:
97
- return key in self._graph_nodes_map
@@ -1,63 +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
- import os
18
- from dataclasses import dataclass
19
- from typing import Any, Dict, Optional
20
-
21
-
22
- @dataclass
23
- class ProjectEnvironment:
24
- """
25
- This class handles retrieval of project env variables.
26
- These env variables can be accessed through templating, as ctx.env.<var_name>
27
-
28
- This class checks for env values in the following order:
29
- - Check for overrides values from the command line. Use these values first.
30
- - Check if these variables are available as environment variables and return them if found.
31
- - Check for default values from the project definition file.
32
- """
33
-
34
- override_env: Dict[str, Any]
35
- default_env: Dict[str, Any]
36
-
37
- def __init__(
38
- self,
39
- default_env: Optional[Dict[str, Any]] = None,
40
- override_env: Optional[Dict[str, Any]] = None,
41
- ):
42
- self.override_env = override_env or {}
43
- self.default_env = default_env or {}
44
-
45
- def __getitem__(self, item):
46
- if item in self.override_env:
47
- return self.override_env.get(item)
48
- if item in os.environ:
49
- return os.environ[item]
50
- return self.default_env[item]
51
-
52
- def get(self, item, default=None):
53
- try:
54
- return self[item]
55
- except KeyError:
56
- return default
57
-
58
- def __contains__(self, item) -> bool:
59
- try:
60
- self[item]
61
- return True
62
- except KeyError:
63
- return False
@@ -1,13 +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.