snowflake-cli 2.8.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 (240) hide show
  1. snowflake/cli/__about__.py +17 -0
  2. snowflake/cli/__init__.py +13 -0
  3. snowflake/cli/api/__init__.py +48 -0
  4. snowflake/cli/api/cli_global_context.py +390 -0
  5. snowflake/cli/api/commands/__init__.py +13 -0
  6. snowflake/cli/api/commands/alias.py +23 -0
  7. snowflake/cli/api/commands/decorators.py +354 -0
  8. snowflake/cli/api/commands/execution_metadata.py +40 -0
  9. snowflake/cli/api/commands/experimental_behaviour.py +19 -0
  10. snowflake/cli/api/commands/flags.py +662 -0
  11. snowflake/cli/api/commands/project_initialisation.py +65 -0
  12. snowflake/cli/api/commands/snow_typer.py +237 -0
  13. snowflake/cli/api/commands/typer_pre_execute.py +26 -0
  14. snowflake/cli/api/config.py +348 -0
  15. snowflake/cli/api/console/__init__.py +17 -0
  16. snowflake/cli/api/console/abc.py +89 -0
  17. snowflake/cli/api/console/console.py +134 -0
  18. snowflake/cli/api/console/enum.py +17 -0
  19. snowflake/cli/api/constants.py +79 -0
  20. snowflake/cli/api/errno.py +27 -0
  21. snowflake/cli/api/exceptions.py +164 -0
  22. snowflake/cli/api/feature_flags.py +55 -0
  23. snowflake/cli/api/identifiers.py +167 -0
  24. snowflake/cli/api/output/__init__.py +13 -0
  25. snowflake/cli/api/output/formats.py +20 -0
  26. snowflake/cli/api/output/types.py +118 -0
  27. snowflake/cli/api/plugins/__init__.py +13 -0
  28. snowflake/cli/api/plugins/command/__init__.py +72 -0
  29. snowflake/cli/api/plugins/command/plugin_hook_specs.py +21 -0
  30. snowflake/cli/api/plugins/plugin_config.py +32 -0
  31. snowflake/cli/api/project/__init__.py +13 -0
  32. snowflake/cli/api/project/definition.py +84 -0
  33. snowflake/cli/api/project/definition_manager.py +134 -0
  34. snowflake/cli/api/project/errors.py +56 -0
  35. snowflake/cli/api/project/project_verification.py +23 -0
  36. snowflake/cli/api/project/schemas/__init__.py +13 -0
  37. snowflake/cli/api/project/schemas/entities/application_entity.py +44 -0
  38. snowflake/cli/api/project/schemas/entities/application_package_entity.py +66 -0
  39. snowflake/cli/api/project/schemas/entities/common.py +78 -0
  40. snowflake/cli/api/project/schemas/entities/entities.py +30 -0
  41. snowflake/cli/api/project/schemas/identifier_model.py +49 -0
  42. snowflake/cli/api/project/schemas/native_app/__init__.py +13 -0
  43. snowflake/cli/api/project/schemas/native_app/application.py +62 -0
  44. snowflake/cli/api/project/schemas/native_app/native_app.py +93 -0
  45. snowflake/cli/api/project/schemas/native_app/package.py +78 -0
  46. snowflake/cli/api/project/schemas/native_app/path_mapping.py +65 -0
  47. snowflake/cli/api/project/schemas/project_definition.py +199 -0
  48. snowflake/cli/api/project/schemas/snowpark/__init__.py +13 -0
  49. snowflake/cli/api/project/schemas/snowpark/argument.py +28 -0
  50. snowflake/cli/api/project/schemas/snowpark/callable.py +69 -0
  51. snowflake/cli/api/project/schemas/snowpark/snowpark.py +36 -0
  52. snowflake/cli/api/project/schemas/streamlit/__init__.py +13 -0
  53. snowflake/cli/api/project/schemas/streamlit/streamlit.py +46 -0
  54. snowflake/cli/api/project/schemas/template.py +77 -0
  55. snowflake/cli/api/project/schemas/updatable_model.py +194 -0
  56. snowflake/cli/api/project/util.py +261 -0
  57. snowflake/cli/api/rendering/__init__.py +13 -0
  58. snowflake/cli/api/rendering/jinja.py +112 -0
  59. snowflake/cli/api/rendering/project_definition_templates.py +39 -0
  60. snowflake/cli/api/rendering/project_templates.py +98 -0
  61. snowflake/cli/api/rendering/sql_templates.py +60 -0
  62. snowflake/cli/api/rest_api.py +172 -0
  63. snowflake/cli/api/sanitizers.py +43 -0
  64. snowflake/cli/api/secure_path.py +362 -0
  65. snowflake/cli/api/secure_utils.py +29 -0
  66. snowflake/cli/api/sql_execution.py +260 -0
  67. snowflake/cli/api/utils/__init__.py +13 -0
  68. snowflake/cli/api/utils/cursor.py +34 -0
  69. snowflake/cli/api/utils/definition_rendering.py +383 -0
  70. snowflake/cli/api/utils/dict_utils.py +73 -0
  71. snowflake/cli/api/utils/error_handling.py +23 -0
  72. snowflake/cli/api/utils/graph.py +97 -0
  73. snowflake/cli/api/utils/models.py +63 -0
  74. snowflake/cli/api/utils/naming_utils.py +13 -0
  75. snowflake/cli/api/utils/path_utils.py +36 -0
  76. snowflake/cli/api/utils/templating_functions.py +144 -0
  77. snowflake/cli/api/utils/types.py +35 -0
  78. snowflake/cli/app/__init__.py +22 -0
  79. snowflake/cli/app/__main__.py +31 -0
  80. snowflake/cli/app/api_impl/__init__.py +13 -0
  81. snowflake/cli/app/api_impl/plugin/__init__.py +13 -0
  82. snowflake/cli/app/api_impl/plugin/plugin_config_provider_impl.py +66 -0
  83. snowflake/cli/app/build_and_push.sh +8 -0
  84. snowflake/cli/app/cli_app.py +243 -0
  85. snowflake/cli/app/commands_registration/__init__.py +33 -0
  86. snowflake/cli/app/commands_registration/builtin_plugins.py +54 -0
  87. snowflake/cli/app/commands_registration/command_plugins_loader.py +169 -0
  88. snowflake/cli/app/commands_registration/commands_registration_with_callbacks.py +105 -0
  89. snowflake/cli/app/commands_registration/exception_logging.py +26 -0
  90. snowflake/cli/app/commands_registration/threadsafe.py +48 -0
  91. snowflake/cli/app/commands_registration/typer_registration.py +153 -0
  92. snowflake/cli/app/constants.py +19 -0
  93. snowflake/cli/app/dev/__init__.py +13 -0
  94. snowflake/cli/app/dev/commands_structure.py +48 -0
  95. snowflake/cli/app/dev/docs/__init__.py +13 -0
  96. snowflake/cli/app/dev/docs/commands_docs_generator.py +100 -0
  97. snowflake/cli/app/dev/docs/generator.py +35 -0
  98. snowflake/cli/app/dev/docs/project_definition_docs_generator.py +58 -0
  99. snowflake/cli/app/dev/docs/project_definition_generate_json_schema.py +227 -0
  100. snowflake/cli/app/dev/docs/template_utils.py +23 -0
  101. snowflake/cli/app/dev/docs/templates/definition_description.rst.jinja2 +38 -0
  102. snowflake/cli/app/dev/docs/templates/overview.rst.jinja2 +9 -0
  103. snowflake/cli/app/dev/docs/templates/usage.rst.jinja2 +57 -0
  104. snowflake/cli/app/dev/pycharm_remote_debug.py +46 -0
  105. snowflake/cli/app/loggers.py +199 -0
  106. snowflake/cli/app/main_typer.py +62 -0
  107. snowflake/cli/app/printing.py +181 -0
  108. snowflake/cli/app/snow_connector.py +243 -0
  109. snowflake/cli/app/telemetry.py +189 -0
  110. snowflake/cli/plugins/__init__.py +13 -0
  111. snowflake/cli/plugins/connection/__init__.py +13 -0
  112. snowflake/cli/plugins/connection/commands.py +330 -0
  113. snowflake/cli/plugins/connection/plugin_spec.py +30 -0
  114. snowflake/cli/plugins/connection/util.py +179 -0
  115. snowflake/cli/plugins/cortex/__init__.py +13 -0
  116. snowflake/cli/plugins/cortex/commands.py +327 -0
  117. snowflake/cli/plugins/cortex/constants.py +17 -0
  118. snowflake/cli/plugins/cortex/manager.py +189 -0
  119. snowflake/cli/plugins/cortex/plugin_spec.py +30 -0
  120. snowflake/cli/plugins/cortex/types.py +22 -0
  121. snowflake/cli/plugins/git/__init__.py +13 -0
  122. snowflake/cli/plugins/git/commands.py +354 -0
  123. snowflake/cli/plugins/git/manager.py +105 -0
  124. snowflake/cli/plugins/git/plugin_spec.py +30 -0
  125. snowflake/cli/plugins/init/__init__.py +13 -0
  126. snowflake/cli/plugins/init/commands.py +248 -0
  127. snowflake/cli/plugins/init/plugin_spec.py +30 -0
  128. snowflake/cli/plugins/nativeapp/__init__.py +13 -0
  129. snowflake/cli/plugins/nativeapp/artifacts.py +742 -0
  130. snowflake/cli/plugins/nativeapp/codegen/__init__.py +13 -0
  131. snowflake/cli/plugins/nativeapp/codegen/artifact_processor.py +91 -0
  132. snowflake/cli/plugins/nativeapp/codegen/compiler.py +130 -0
  133. snowflake/cli/plugins/nativeapp/codegen/sandbox.py +306 -0
  134. snowflake/cli/plugins/nativeapp/codegen/setup/native_app_setup_processor.py +172 -0
  135. snowflake/cli/plugins/nativeapp/codegen/setup/setup_driver.py.source +56 -0
  136. snowflake/cli/plugins/nativeapp/codegen/snowpark/callback_source.py.jinja +181 -0
  137. snowflake/cli/plugins/nativeapp/codegen/snowpark/extension_function_utils.py +217 -0
  138. snowflake/cli/plugins/nativeapp/codegen/snowpark/models.py +61 -0
  139. snowflake/cli/plugins/nativeapp/codegen/snowpark/python_processor.py +528 -0
  140. snowflake/cli/plugins/nativeapp/commands.py +439 -0
  141. snowflake/cli/plugins/nativeapp/common_flags.py +44 -0
  142. snowflake/cli/plugins/nativeapp/constants.py +27 -0
  143. snowflake/cli/plugins/nativeapp/exceptions.py +122 -0
  144. snowflake/cli/plugins/nativeapp/feature_flags.py +24 -0
  145. snowflake/cli/plugins/nativeapp/init.py +345 -0
  146. snowflake/cli/plugins/nativeapp/manager.py +823 -0
  147. snowflake/cli/plugins/nativeapp/plugin_spec.py +30 -0
  148. snowflake/cli/plugins/nativeapp/policy.py +50 -0
  149. snowflake/cli/plugins/nativeapp/project_model.py +195 -0
  150. snowflake/cli/plugins/nativeapp/run_processor.py +389 -0
  151. snowflake/cli/plugins/nativeapp/teardown_processor.py +301 -0
  152. snowflake/cli/plugins/nativeapp/utils.py +98 -0
  153. snowflake/cli/plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +135 -0
  154. snowflake/cli/plugins/nativeapp/version/__init__.py +13 -0
  155. snowflake/cli/plugins/nativeapp/version/commands.py +170 -0
  156. snowflake/cli/plugins/nativeapp/version/version_processor.py +362 -0
  157. snowflake/cli/plugins/notebook/__init__.py +13 -0
  158. snowflake/cli/plugins/notebook/commands.py +85 -0
  159. snowflake/cli/plugins/notebook/exceptions.py +20 -0
  160. snowflake/cli/plugins/notebook/manager.py +71 -0
  161. snowflake/cli/plugins/notebook/plugin_spec.py +30 -0
  162. snowflake/cli/plugins/notebook/types.py +15 -0
  163. snowflake/cli/plugins/object/__init__.py +13 -0
  164. snowflake/cli/plugins/object/command_aliases.py +95 -0
  165. snowflake/cli/plugins/object/commands.py +181 -0
  166. snowflake/cli/plugins/object/common.py +85 -0
  167. snowflake/cli/plugins/object/manager.py +97 -0
  168. snowflake/cli/plugins/object/plugin_spec.py +30 -0
  169. snowflake/cli/plugins/object_stage_deprecated/__init__.py +15 -0
  170. snowflake/cli/plugins/object_stage_deprecated/commands.py +122 -0
  171. snowflake/cli/plugins/object_stage_deprecated/plugin_spec.py +32 -0
  172. snowflake/cli/plugins/snowpark/__init__.py +13 -0
  173. snowflake/cli/plugins/snowpark/commands.py +546 -0
  174. snowflake/cli/plugins/snowpark/common.py +307 -0
  175. snowflake/cli/plugins/snowpark/manager.py +109 -0
  176. snowflake/cli/plugins/snowpark/models.py +157 -0
  177. snowflake/cli/plugins/snowpark/package/__init__.py +13 -0
  178. snowflake/cli/plugins/snowpark/package/anaconda_packages.py +233 -0
  179. snowflake/cli/plugins/snowpark/package/commands.py +256 -0
  180. snowflake/cli/plugins/snowpark/package/manager.py +44 -0
  181. snowflake/cli/plugins/snowpark/package/utils.py +26 -0
  182. snowflake/cli/plugins/snowpark/package_utils.py +354 -0
  183. snowflake/cli/plugins/snowpark/plugin_spec.py +30 -0
  184. snowflake/cli/plugins/snowpark/snowpark_package_paths.py +65 -0
  185. snowflake/cli/plugins/snowpark/snowpark_shared.py +95 -0
  186. snowflake/cli/plugins/snowpark/zipper.py +81 -0
  187. snowflake/cli/plugins/spcs/__init__.py +35 -0
  188. snowflake/cli/plugins/spcs/common.py +99 -0
  189. snowflake/cli/plugins/spcs/compute_pool/__init__.py +13 -0
  190. snowflake/cli/plugins/spcs/compute_pool/commands.py +241 -0
  191. snowflake/cli/plugins/spcs/compute_pool/manager.py +121 -0
  192. snowflake/cli/plugins/spcs/image_registry/__init__.py +13 -0
  193. snowflake/cli/plugins/spcs/image_registry/commands.py +65 -0
  194. snowflake/cli/plugins/spcs/image_registry/manager.py +105 -0
  195. snowflake/cli/plugins/spcs/image_repository/__init__.py +13 -0
  196. snowflake/cli/plugins/spcs/image_repository/commands.py +202 -0
  197. snowflake/cli/plugins/spcs/image_repository/manager.py +84 -0
  198. snowflake/cli/plugins/spcs/jobs/__init__.py +13 -0
  199. snowflake/cli/plugins/spcs/jobs/commands.py +78 -0
  200. snowflake/cli/plugins/spcs/jobs/manager.py +53 -0
  201. snowflake/cli/plugins/spcs/plugin_spec.py +30 -0
  202. snowflake/cli/plugins/spcs/services/__init__.py +13 -0
  203. snowflake/cli/plugins/spcs/services/commands.py +312 -0
  204. snowflake/cli/plugins/spcs/services/manager.py +170 -0
  205. snowflake/cli/plugins/sql/__init__.py +13 -0
  206. snowflake/cli/plugins/sql/commands.py +83 -0
  207. snowflake/cli/plugins/sql/manager.py +92 -0
  208. snowflake/cli/plugins/sql/plugin_spec.py +30 -0
  209. snowflake/cli/plugins/sql/snowsql_templating.py +28 -0
  210. snowflake/cli/plugins/stage/__init__.py +13 -0
  211. snowflake/cli/plugins/stage/commands.py +263 -0
  212. snowflake/cli/plugins/stage/diff.py +326 -0
  213. snowflake/cli/plugins/stage/manager.py +577 -0
  214. snowflake/cli/plugins/stage/md5.py +160 -0
  215. snowflake/cli/plugins/stage/plugin_spec.py +30 -0
  216. snowflake/cli/plugins/streamlit/__init__.py +13 -0
  217. snowflake/cli/plugins/streamlit/commands.py +179 -0
  218. snowflake/cli/plugins/streamlit/manager.py +222 -0
  219. snowflake/cli/plugins/streamlit/plugin_spec.py +30 -0
  220. snowflake/cli/plugins/workspace/__init__.py +13 -0
  221. snowflake/cli/plugins/workspace/commands.py +35 -0
  222. snowflake/cli/plugins/workspace/plugin_spec.py +30 -0
  223. snowflake/cli/templates/default_snowpark/.gitignore +4 -0
  224. snowflake/cli/templates/default_snowpark/app/__init__.py +0 -0
  225. snowflake/cli/templates/default_snowpark/app/common.py +2 -0
  226. snowflake/cli/templates/default_snowpark/app/functions.py +15 -0
  227. snowflake/cli/templates/default_snowpark/app/procedures.py +22 -0
  228. snowflake/cli/templates/default_snowpark/requirements.txt +1 -0
  229. snowflake/cli/templates/default_snowpark/snowflake.yml +23 -0
  230. snowflake/cli/templates/default_streamlit/.gitignore +4 -0
  231. snowflake/cli/templates/default_streamlit/common/hello.py +2 -0
  232. snowflake/cli/templates/default_streamlit/environment.yml +6 -0
  233. snowflake/cli/templates/default_streamlit/pages/my_page.py +3 -0
  234. snowflake/cli/templates/default_streamlit/snowflake.yml +10 -0
  235. snowflake/cli/templates/default_streamlit/streamlit_app.py +4 -0
  236. snowflake_cli-2.8.2.dist-info/METADATA +325 -0
  237. snowflake_cli-2.8.2.dist-info/RECORD +240 -0
  238. snowflake_cli-2.8.2.dist-info/WHEEL +4 -0
  239. snowflake_cli-2.8.2.dist-info/entry_points.txt +2 -0
  240. snowflake_cli-2.8.2.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,73 @@
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)
@@ -0,0 +1,23 @@
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
@@ -0,0 +1,97 @@
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
@@ -0,0 +1,63 @@
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
@@ -0,0 +1,13 @@
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.
@@ -0,0 +1,36 @@
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 sys
18
+
19
+ BUFFER_SIZE = 4096
20
+
21
+
22
+ def path_resolver(path_to_file: str) -> str:
23
+ if sys.platform == "win32" and "~1" in path_to_file:
24
+ from ctypes import create_unicode_buffer, windll # type: ignore
25
+
26
+ buffer = create_unicode_buffer(BUFFER_SIZE)
27
+ get_long_path_name = windll.kernel32.GetLongPathNameW
28
+ return_value = get_long_path_name(path_to_file, buffer, BUFFER_SIZE)
29
+
30
+ if 0 < return_value <= BUFFER_SIZE:
31
+ return buffer.value
32
+ return path_to_file
33
+
34
+
35
+ def is_stage_path(path: str) -> bool:
36
+ return path.startswith("@") or path.startswith("snow://")
@@ -0,0 +1,144 @@
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, Optional
18
+
19
+ from snowflake.cli.api.exceptions import InvalidTemplate
20
+ from snowflake.cli.api.project.util import (
21
+ concat_identifiers,
22
+ get_env_username,
23
+ identifier_to_str,
24
+ sanitize_identifier,
25
+ to_identifier,
26
+ )
27
+
28
+
29
+ class TemplatingFunctions:
30
+ """
31
+ This class contains all the functions available for templating.
32
+ Any callable not starting with '_' will automatically be available for users to use.
33
+ """
34
+
35
+ @staticmethod
36
+ def _verify_str_arguments(
37
+ func_name: str,
38
+ args: List[Any],
39
+ *,
40
+ min_count: Optional[int] = None,
41
+ max_count: Optional[int] = None,
42
+ ):
43
+ if min_count is not None and len(args) < min_count:
44
+ raise InvalidTemplate(
45
+ f"{func_name} requires at least {min_count} argument(s)"
46
+ )
47
+
48
+ if max_count is not None and len(args) > max_count:
49
+ raise InvalidTemplate(
50
+ f"{func_name} supports at most {max_count} argument(s)"
51
+ )
52
+
53
+ for arg in args:
54
+ if not isinstance(arg, str):
55
+ raise InvalidTemplate(f"{func_name} only accepts String values")
56
+
57
+ @staticmethod
58
+ def concat_ids(*args):
59
+ """
60
+ input: one or more string arguments (SQL ID or plain String).
61
+ output: a valid SQL ID (quoted or unquoted)
62
+
63
+ Takes on multiple String arguments and concatenate them into one String.
64
+ If any of the Strings is a valid quoted ID, it will be unescaped for the concatenation process.
65
+ The resulting String is then escaped and quoted if:
66
+ - It contains non SQL safe characters
67
+ - Any of the input was a valid quoted identifier.
68
+ """
69
+ TemplatingFunctions._verify_str_arguments("concat_ids", args, min_count=1)
70
+ return concat_identifiers(args)
71
+
72
+ @staticmethod
73
+ def str_to_id(*args):
74
+ """
75
+ input: one string argument. (SQL ID or plain String)
76
+ output: a valid SQL ID (quoted or unquoted)
77
+
78
+ If the input is a valid quoted or valid unquoted identifier, return it as is.
79
+ Otherwise, if the input contains unsafe characters and is not properly quoted,
80
+ then escape it and quote it.
81
+ """
82
+ TemplatingFunctions._verify_str_arguments(
83
+ "str_to_id", args, min_count=1, max_count=1
84
+ )
85
+ return to_identifier(args[0])
86
+
87
+ @staticmethod
88
+ def id_to_str(*args):
89
+ """
90
+ input: one string argument (SQL ID or plain String).
91
+ output: a plain string
92
+
93
+ If the input is a valid SQL ID, then unescape it and return the plain String version.
94
+ Otherwise, return the input as is.
95
+ """
96
+ TemplatingFunctions._verify_str_arguments(
97
+ "id_to_str", args, min_count=1, max_count=1
98
+ )
99
+ return identifier_to_str(args[0])
100
+
101
+ @staticmethod
102
+ def get_username(*args):
103
+ """
104
+ input: one optional string containing the fallback value
105
+ output: current username detected from the Operating System
106
+
107
+ If the current username is not found or is blank, return blank
108
+ or use the fallback value if provided.
109
+ """
110
+ TemplatingFunctions._verify_str_arguments(
111
+ "get_username", args, min_count=0, max_count=1
112
+ )
113
+ fallback_username = args[0] if len(args) > 0 else ""
114
+ return get_env_username() or fallback_username
115
+
116
+ @staticmethod
117
+ def sanitize_id(*args):
118
+ """
119
+ input: one string argument
120
+ output: a valid non-quoted SQL ID
121
+
122
+ Removes any unsafe SQL characters from the input,
123
+ prepend it with an underscore if it does not start with a valid character,
124
+ and limit the result to 255 characters.
125
+ The result is a valid unquoted SQL ID.
126
+ """
127
+ TemplatingFunctions._verify_str_arguments(
128
+ "sanitize_id", args, min_count=1, max_count=1
129
+ )
130
+
131
+ return sanitize_identifier(args[0])
132
+
133
+
134
+ def get_templating_functions():
135
+ """
136
+ Returns a dictionary with all the functions available for templating
137
+ """
138
+ templating_functions = {
139
+ func: getattr(TemplatingFunctions, func)
140
+ for func in dir(TemplatingFunctions)
141
+ if callable(getattr(TemplatingFunctions, func)) and not func.startswith("_")
142
+ }
143
+
144
+ return templating_functions
@@ -0,0 +1,35 @@
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, Dict
18
+
19
+ Context = Dict[str, Any]
20
+ Definition = Dict[str, Any]
21
+
22
+
23
+ def try_cast_to_bool(value: Any) -> bool:
24
+ if isinstance(value, bool):
25
+ return value
26
+
27
+ # Now if value is not string then cast it to str. Simplifies logic for 1 and 0
28
+ if not isinstance(value, str):
29
+ value = str(value)
30
+
31
+ know_booleans_mapping = {"true": True, "false": False, "1": True, "0": False}
32
+
33
+ if value.lower() not in know_booleans_mapping:
34
+ raise ValueError(f"Could not case {value} to bool value")
35
+ return know_booleans_mapping[value.lower()]
@@ -0,0 +1,22 @@
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
+ import logging
16
+ import os
17
+
18
+ # Suppress logging from Snowflake connector
19
+ logging.getLogger("snowflake").setLevel(logging.ERROR)
20
+
21
+ # Restrict permissions of all created files
22
+ os.umask(0o077)
@@ -0,0 +1,31 @@
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 sys
18
+
19
+ from snowflake.cli.app.cli_app import app_factory
20
+
21
+
22
+ def main(*args):
23
+ app = app_factory()
24
+ app(*args)
25
+
26
+
27
+ if __name__ == "__main__":
28
+ main()
29
+
30
+ if getattr(sys, "frozen", False):
31
+ main(sys.argv[1:])
@@ -0,0 +1,13 @@
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.
@@ -0,0 +1,13 @@
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.
@@ -0,0 +1,66 @@
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 List
18
+
19
+ from snowflake.cli.api import PluginConfigProvider
20
+ from snowflake.cli.api.config import (
21
+ PLUGINS_SECTION_PATH,
22
+ config_section_exists,
23
+ get_config_section,
24
+ get_config_value,
25
+ get_plugins_config,
26
+ )
27
+ from snowflake.cli.api.exceptions import InvalidPluginConfiguration
28
+ from snowflake.cli.api.plugins.plugin_config import PluginConfig
29
+
30
+
31
+ def _assert_value_is_bool(value, *, value_name: str, plugin_name: str) -> None:
32
+ if type(value) is not bool:
33
+ raise InvalidPluginConfiguration(
34
+ f'[{plugin_name}]: "{value_name}" must be a boolean'
35
+ )
36
+
37
+
38
+ _ENABLED_KEY = "enabled"
39
+
40
+
41
+ class PluginConfigProviderImpl(PluginConfigProvider):
42
+ def get_enabled_plugin_names(self) -> List[str]:
43
+ enabled_plugins = []
44
+ for plugin_name, plugin_config_section in get_plugins_config().items():
45
+ enabled = plugin_config_section.get(_ENABLED_KEY, False)
46
+ _assert_value_is_bool(
47
+ enabled, value_name=_ENABLED_KEY, plugin_name=plugin_name
48
+ )
49
+ if enabled:
50
+ enabled_plugins.append(plugin_name)
51
+ return enabled_plugins
52
+
53
+ def get_config(self, plugin_name: str) -> PluginConfig:
54
+ config_path = PLUGINS_SECTION_PATH + [plugin_name]
55
+ plugin_config = PluginConfig(is_plugin_enabled=False, internal_config={})
56
+ plugin_config.is_plugin_enabled = get_config_value(
57
+ *config_path, key=_ENABLED_KEY, default=False
58
+ )
59
+ _assert_value_is_bool(
60
+ plugin_config.is_plugin_enabled,
61
+ value_name=_ENABLED_KEY,
62
+ plugin_name=plugin_name,
63
+ )
64
+ if config_section_exists(*config_path, "config"):
65
+ plugin_config.internal_config = get_config_section(*config_path, "config")
66
+ return plugin_config
@@ -0,0 +1,8 @@
1
+ set -e
2
+ export SF_REGISTRY="$(snow spcs image-registry url -c integration)"
3
+ DATABASE=$(echo "${SNOWFLAKE_CONNECTIONS_INTEGRATION_DATABASE}" | tr '[:upper:]' '[:lower:]')
4
+
5
+ echo "Using registry: ${SF_REGISTRY}"
6
+ docker build --platform linux/amd64 -t "${SF_REGISTRY}/${DATABASE}/public/snowcli_repository/test_counter" .
7
+ snow spcs image-registry token --format=json -c integration | docker login "${SF_REGISTRY}/${DATABASE}/public/snowcli_repository" -u 0sessiontoken --password-stdin
8
+ docker push "${SF_REGISTRY}/${DATABASE}/public/snowcli_repository/test_counter"