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,31 +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 dataclasses import dataclass
16
- from pathlib import Path
17
- from typing import (
18
- List,
19
- )
20
-
21
- from snowflake.cli.api.project.schemas.v1.native_app.path_mapping import PathMapping
22
-
23
-
24
- @dataclass
25
- class BundleContext:
26
- package_name: str
27
- artifacts: List[PathMapping]
28
- project_root: Path
29
- bundle_root: Path
30
- deploy_root: Path
31
- generated_root: Path
@@ -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.
@@ -1,91 +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 abc import ABC, abstractmethod
18
- from pathlib import Path
19
- from typing import Optional
20
-
21
- from click import ClickException
22
- from snowflake.cli._plugins.nativeapp.bundle_context import BundleContext
23
- from snowflake.cli.api.project.schemas.v1.native_app.path_mapping import (
24
- PathMapping,
25
- ProcessorMapping,
26
- )
27
-
28
-
29
- class UnsupportedArtifactProcessorError(ClickException):
30
- """Exception thrown when a user has passed in an unsupported artifact processor."""
31
-
32
- def __init__(self, processor_name: str):
33
- super().__init__(
34
- f"Unsupported value {processor_name} detected for an artifact processor. Please refer to documentation for a list of supported types."
35
- )
36
-
37
-
38
- def is_python_file_artifact(src: Path, _: Path):
39
- """Determines whether the provided source path is an existing python file."""
40
- return src.is_file() and src.suffix == ".py"
41
-
42
-
43
- class ProjectFileContextManager:
44
- """
45
- A context manager that encapsulates the logic required to update a project file
46
- in processor logic. The processor can use this manager to gain access to the contents
47
- of a file, and optionally provide replacement contents. If it does, the file is
48
- correctly modified in the deploy root directory to reflect the new contents.
49
- """
50
-
51
- def __init__(self, path: Path):
52
- self.path = path
53
- self._contents = None
54
- self.edited_contents = None
55
-
56
- @property
57
- def contents(self):
58
- return self._contents
59
-
60
- def __enter__(self):
61
- self._contents = self.path.read_text(encoding="utf-8")
62
-
63
- return self
64
-
65
- def __exit__(self, exc_type, exc_val, exc_tb):
66
- if self.edited_contents is not None:
67
- if self.path.is_symlink():
68
- # if the file is a symlink, make sure we don't overwrite the original
69
- self.path.unlink()
70
-
71
- self.path.write_text(self.edited_contents, encoding="utf-8")
72
-
73
-
74
- class ArtifactProcessor(ABC):
75
- def __init__(
76
- self,
77
- bundle_ctx: BundleContext,
78
- ) -> None:
79
- self._bundle_ctx = bundle_ctx
80
-
81
- @abstractmethod
82
- def process(
83
- self,
84
- artifact_to_process: PathMapping,
85
- processor_mapping: Optional[ProcessorMapping],
86
- **kwargs,
87
- ) -> None:
88
- pass
89
-
90
- def edit_file(self, path: Path):
91
- return ProjectFileContextManager(path)
@@ -1,149 +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
- import re
19
- from typing import Dict, Optional
20
-
21
- from click import ClickException
22
- from snowflake.cli._plugins.nativeapp.bundle_context import BundleContext
23
- from snowflake.cli._plugins.nativeapp.codegen.artifact_processor import (
24
- ArtifactProcessor,
25
- UnsupportedArtifactProcessorError,
26
- )
27
- from snowflake.cli._plugins.nativeapp.codegen.setup.native_app_setup_processor import (
28
- NativeAppSetupProcessor,
29
- )
30
- from snowflake.cli._plugins.nativeapp.codegen.snowpark.python_processor import (
31
- SnowparkAnnotationProcessor,
32
- )
33
- from snowflake.cli._plugins.nativeapp.codegen.templates.templates_processor import (
34
- TemplatesProcessor,
35
- )
36
- from snowflake.cli._plugins.nativeapp.feature_flags import FeatureFlag
37
- from snowflake.cli.api.cli_global_context import get_cli_context
38
- from snowflake.cli.api.console import cli_console as cc
39
- from snowflake.cli.api.metrics import CLICounterField
40
- from snowflake.cli.api.project.schemas.v1.native_app.path_mapping import (
41
- ProcessorMapping,
42
- )
43
-
44
- SNOWPARK_PROCESSOR = "snowpark"
45
- NA_SETUP_PROCESSOR = "native app setup"
46
- TEMPLATES_PROCESSOR = "templates"
47
-
48
- _REGISTERED_PROCESSORS_BY_NAME = {
49
- SNOWPARK_PROCESSOR: SnowparkAnnotationProcessor,
50
- NA_SETUP_PROCESSOR: NativeAppSetupProcessor,
51
- TEMPLATES_PROCESSOR: TemplatesProcessor,
52
- }
53
-
54
-
55
- class NativeAppCompiler:
56
- """
57
- Compiler class to perform custom processing on all relevant Native Apps artifacts (specified in the project definition file)
58
- before an application package can be created from those artifacts.
59
- An artifact can have more than one processor specified for itself, and this class will execute those processors in that order.
60
- The class also maintains a dictionary of processors it creates in order to reuse them across artifacts, since processor initialization
61
- is independent of the artifact to process.
62
- """
63
-
64
- def __init__(
65
- self,
66
- bundle_ctx: BundleContext,
67
- ):
68
- self._bundle_ctx = bundle_ctx
69
- # dictionary of all processors created and shared between different artifact objects.
70
- self.cached_processors: Dict[str, ArtifactProcessor] = {}
71
-
72
- def compile_artifacts(self):
73
- """
74
- Go through every artifact object in the project definition of a native app, and execute processors in order of specification for each of the artifact object.
75
- May have side-effects on the filesystem by either directly editing source files or the deploy root.
76
- """
77
- metrics = get_cli_context().metrics
78
- metrics.set_counter_default(CLICounterField.TEMPLATES_PROCESSOR, 0)
79
- metrics.set_counter_default(CLICounterField.SNOWPARK_PROCESSOR, 0)
80
-
81
- if not self._should_invoke_processors():
82
- return
83
-
84
- with cc.phase("Invoking artifact processors"):
85
- if self._bundle_ctx.generated_root.exists():
86
- raise ClickException(
87
- f"Path {self._bundle_ctx.generated_root} already exists. Please choose a different name for your generated directory in the project definition file."
88
- )
89
-
90
- for artifact in self._bundle_ctx.artifacts:
91
- for processor in artifact.processors:
92
- if self._is_enabled(processor):
93
- artifact_processor = self._try_create_processor(
94
- processor_mapping=processor,
95
- )
96
- if artifact_processor is None:
97
- raise UnsupportedArtifactProcessorError(
98
- processor_name=processor.name
99
- )
100
- else:
101
- artifact_processor.process(
102
- artifact_to_process=artifact,
103
- processor_mapping=processor,
104
- )
105
-
106
- def _try_create_processor(
107
- self,
108
- processor_mapping: ProcessorMapping,
109
- **kwargs,
110
- ) -> Optional[ArtifactProcessor]:
111
- """
112
- Fetch processor object if one already exists in the cached_processors dictionary.
113
- Else, initialize a new object to return, and add it to the cached_processors dictionary.
114
- """
115
- processor_name = processor_mapping.name.lower()
116
- current_processor = self.cached_processors.get(processor_name)
117
-
118
- if current_processor is not None:
119
- return current_processor
120
-
121
- processor_factory = _REGISTERED_PROCESSORS_BY_NAME.get(processor_name)
122
- if processor_factory is None:
123
- # No registered processor with the specified name
124
- return None
125
-
126
- processor_ctx = copy.copy(self._bundle_ctx)
127
- processor_subdirectory = re.sub(r"[^a-zA-Z0-9_$]", "_", processor_name)
128
- processor_ctx.bundle_root = (
129
- self._bundle_ctx.bundle_root / processor_subdirectory
130
- )
131
- processor_ctx.generated_root = (
132
- self._bundle_ctx.generated_root / processor_subdirectory
133
- )
134
- current_processor = processor_factory(processor_ctx)
135
- self.cached_processors[processor_name] = current_processor
136
-
137
- return current_processor
138
-
139
- def _should_invoke_processors(self):
140
- for artifact in self._bundle_ctx.artifacts:
141
- for processor in artifact.processors:
142
- if self._is_enabled(processor):
143
- return True
144
- return False
145
-
146
- def _is_enabled(self, processor: ProcessorMapping) -> bool:
147
- if processor.name.lower() == NA_SETUP_PROCESSOR:
148
- return FeatureFlag.ENABLE_NATIVE_APP_PYTHON_SETUP.is_enabled()
149
- return True
@@ -1,306 +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
- import shutil
19
- import subprocess
20
- import sys
21
- from enum import Enum
22
- from pathlib import Path
23
- from typing import Any, Mapping, Optional, Sequence, Union
24
- from venv import EnvBuilder
25
-
26
- from click.exceptions import ClickException
27
-
28
- EnvVars = Mapping[str, str] # Only support str -> str for cross-platform compatibility
29
-
30
-
31
- class SandboxExecutionError(ClickException):
32
- """An error occurred while executing a python script."""
33
-
34
- def __init__(self, error: str):
35
- super().__init__(f"Failed to execute python script. {error}")
36
-
37
-
38
- def _get_active_venv_dir() -> Optional[str]:
39
- return os.environ.get("VIRTUAL_ENV")
40
-
41
-
42
- def _get_active_conda_env() -> Optional[str]:
43
- return os.environ.get("CONDA_DEFAULT_ENV")
44
-
45
-
46
- def _is_venv_active() -> bool:
47
- return _get_active_venv_dir() is not None
48
-
49
-
50
- def _is_conda_active() -> bool:
51
- return _get_active_conda_env() is not None
52
-
53
-
54
- def _is_ms_windows() -> bool:
55
- return sys.platform == "win32"
56
-
57
-
58
- def _execute_python_interpreter(
59
- python_executable: Optional[Union[str, Path, Sequence[str]]],
60
- script_source: str,
61
- cwd: Optional[Union[str, Path]],
62
- timeout: Optional[int],
63
- env_vars: Optional[EnvVars],
64
- ) -> subprocess.CompletedProcess:
65
- if not python_executable:
66
- raise SandboxExecutionError("No python executable found")
67
-
68
- if isinstance(python_executable, str) or isinstance(python_executable, Path):
69
- args = [python_executable]
70
- else:
71
- args = [arg for arg in python_executable]
72
- args.append("-")
73
- return subprocess.run(
74
- args,
75
- capture_output=True,
76
- text=True,
77
- input=script_source,
78
- timeout=timeout,
79
- cwd=cwd,
80
- env=env_vars,
81
- )
82
-
83
-
84
- def _execute_in_venv(
85
- script_source: str,
86
- venv_path: Optional[Union[str, Path]] = None,
87
- cwd: Optional[Union[str, Path]] = None,
88
- timeout: Optional[int] = None,
89
- env_vars: Optional[EnvVars] = None,
90
- ) -> subprocess.CompletedProcess:
91
- resolved_venv_path = None
92
- if venv_path is None:
93
- active_venv_dir = _get_active_venv_dir()
94
- if active_venv_dir is not None:
95
- resolved_venv_path = Path(active_venv_dir).resolve()
96
- elif isinstance(venv_path, str):
97
- resolved_venv_path = Path(venv_path).resolve()
98
- else:
99
- resolved_venv_path = venv_path.resolve()
100
-
101
- if resolved_venv_path is None:
102
- raise SandboxExecutionError("No venv root found")
103
-
104
- if not resolved_venv_path.is_dir():
105
- raise SandboxExecutionError(
106
- f"venv path must be an existing directory: {resolved_venv_path}"
107
- )
108
-
109
- # find the python interpreter for this environment. There is no need to activate environment prior to invoking the
110
- # interpreter, as venv maintains the invariant that invoking any of the scripts will set up the virtual environment
111
- # correctly. activation scripts are only used for convenience in interactive shells.
112
- if _is_ms_windows():
113
- python_executable = resolved_venv_path / "Scripts" / "python.exe"
114
- else:
115
- python_executable = resolved_venv_path / "bin" / "python3"
116
-
117
- if not python_executable.is_file():
118
- raise SandboxExecutionError(
119
- f"No venv python executable found: {resolved_venv_path}"
120
- )
121
-
122
- return _execute_python_interpreter(
123
- python_executable, script_source, timeout=timeout, cwd=cwd, env_vars=env_vars
124
- )
125
-
126
-
127
- def _execute_in_conda_env(
128
- script_source: str,
129
- env_name: Optional[str] = None,
130
- cwd: Optional[Union[str, Path]] = None,
131
- timeout: Optional[int] = None,
132
- env_vars: Optional[EnvVars] = None,
133
- ) -> subprocess.CompletedProcess:
134
- conda_env = env_name
135
- if conda_env is None:
136
- conda_env = _get_active_conda_env()
137
- if conda_env is None:
138
- raise SandboxExecutionError("No conda environment found")
139
-
140
- conda_exec = shutil.which("conda")
141
- if conda_exec is None:
142
- raise SandboxExecutionError(
143
- "conda command not found, make sure it is installed on your system and in your PATH"
144
- )
145
-
146
- # conda run removes the need to activate the environment, as would typically be done in an interactive shell
147
- return _execute_python_interpreter(
148
- [conda_exec, "run", "-n", conda_env, "--no-capture-output", "python"],
149
- script_source,
150
- timeout=timeout,
151
- cwd=cwd,
152
- env_vars=env_vars,
153
- )
154
-
155
-
156
- def _execute_with_system_path_python(
157
- script_source: str,
158
- cwd: Optional[Union[str, Path]] = None,
159
- timeout: Optional[int] = None,
160
- env_vars: Optional[EnvVars] = None,
161
- ) -> subprocess.CompletedProcess:
162
- python_executable = (
163
- shutil.which("python3") or shutil.which("python") or sys.executable
164
- )
165
-
166
- return _execute_python_interpreter(
167
- python_executable,
168
- script_source,
169
- timeout=timeout,
170
- cwd=cwd,
171
- env_vars=env_vars,
172
- )
173
-
174
-
175
- class ExecutionEnvironmentType(Enum):
176
- AUTO_DETECT = 0 # auto-detect the current python interpreter by looking for an active virtual environment
177
- VENV = 1 # use the python interpreter specified by a venv environment
178
- CONDA = 2 # use the python interpreter specified by a conda environment
179
- SYSTEM_PATH = 3 # search for a python interpreter in the system path
180
- CURRENT = 4 # Use the python interpreter that is currently executing (i.e. `sys.executable`)
181
-
182
-
183
- def execute_script_in_sandbox(
184
- script_source: str,
185
- env_type: ExecutionEnvironmentType = ExecutionEnvironmentType.AUTO_DETECT,
186
- cwd: Optional[Union[str, Path]] = None,
187
- timeout: Optional[int] = None,
188
- env_vars: Optional[EnvVars] = None,
189
- **kwargs,
190
- ) -> subprocess.CompletedProcess:
191
- """
192
- Executes a python script in a sandboxed environment, and returns its output. The script is executed in a different
193
- process. The execution environment is determined by the `env_type` argument. By default, the logic will attempt
194
- to auto-detect the correct environment by looking for an active venv or conda environment. If none can be found, it
195
- will use the system's default python executable, as determined by the user's path. As a last resort, the current
196
- python execution environment will be used (still in a subprocess).
197
-
198
- Parameters:
199
- script_source (str): The python script to be executed, as a string.
200
- env_type: The type of execution environment to use (default: ExecutionEnvironmentType.AUTO_DETECT).
201
- cwd (Optional[Union[str, Path]]): An optional path to use as the current directory when executing the script.
202
- timeout (Optional[int]): An optional timeout in seconds when executing the script. Defaults to no timeout.
203
- **kwargs: Additional keyword arguments used by specific execution environments, as follows:
204
- - venv environments accept a 'path' argument to specify the venv root directory.
205
- - conda environments accept a 'name' argument to specify the name of the conda environment to use.
206
- Returns:
207
- A subprocess.CompletedProcess object containing the output of the script, if any.
208
- """
209
- if env_type == ExecutionEnvironmentType.AUTO_DETECT:
210
- if _is_venv_active():
211
- return _execute_in_venv(
212
- script_source, cwd=cwd, timeout=timeout, env_vars=env_vars
213
- )
214
- elif _is_conda_active():
215
- return _execute_in_conda_env(
216
- script_source, cwd=cwd, timeout=timeout, env_vars=env_vars
217
- )
218
- else:
219
- return _execute_with_system_path_python(
220
- script_source, cwd=cwd, timeout=timeout, env_vars=env_vars
221
- )
222
- elif env_type == ExecutionEnvironmentType.VENV:
223
- return _execute_in_venv(
224
- script_source,
225
- kwargs.get("path"),
226
- cwd=cwd,
227
- timeout=timeout,
228
- env_vars=env_vars,
229
- )
230
- elif env_type == ExecutionEnvironmentType.CONDA:
231
- return _execute_in_conda_env(
232
- script_source,
233
- kwargs.get("name"),
234
- cwd=cwd,
235
- timeout=timeout,
236
- env_vars=env_vars,
237
- )
238
- elif env_type == ExecutionEnvironmentType.SYSTEM_PATH:
239
- return _execute_with_system_path_python(
240
- script_source, cwd=cwd, timeout=timeout, env_vars=env_vars
241
- )
242
- else: # ExecutionEnvironmentType.CURRENT
243
- return _execute_python_interpreter(
244
- sys.executable, script_source, cwd=cwd, timeout=timeout, env_vars=env_vars
245
- )
246
-
247
-
248
- class SandboxEnvBuilder(EnvBuilder):
249
- """
250
- A virtual environment builder that can be used to build an environment suitable for
251
- executing user-provided python scripts in an isolated sandbox.
252
- """
253
-
254
- def __init__(self, path: Path, **kwargs) -> None:
255
- """
256
- Creates a new builder with the specified destination path. The path need not
257
- exist, it will be created when needed (recursively if necessary).
258
-
259
- Parameters:
260
- path (Path): The directory in which the sandbox environment will be created.
261
- """
262
- super().__init__(**kwargs)
263
- self.path = path
264
- self._context: Any = None # cached context
265
-
266
- def post_setup(self, context) -> None:
267
- self._context = context
268
-
269
- def ensure_created(self) -> None:
270
- """
271
- Ensures that the sandbox environment has been created and correctly initialized.
272
- """
273
- if self.path.exists():
274
- self._context = self.ensure_directories(self.path)
275
- else:
276
- self.path.mkdir(parents=True, exist_ok=True)
277
- self.create(
278
- self.path
279
- ) # will set self._context through the post_setup callback
280
-
281
- def run_python(self, *args) -> str:
282
- """
283
- Executes the python interpreter in the sandboxed environment with the provided arguments.
284
- This raises a CalledProcessError if the python interpreter was not executed successfully.
285
-
286
- Returns:
287
- The output of running the command.
288
- """
289
- positional_args = [
290
- self._context.env_exe,
291
- "-E", # passing -E ignores all PYTHON* env vars
292
- *args,
293
- ]
294
- kwargs = {
295
- "cwd": self._context.env_dir,
296
- "stderr": subprocess.STDOUT,
297
- }
298
- env = dict(os.environ)
299
- env["VIRTUAL_ENV"] = self._context.env_dir
300
- return subprocess.check_output(positional_args, **kwargs)
301
-
302
- def pip_install(self, *args: Any) -> None:
303
- """
304
- Invokes pip install with the provided arguments.
305
- """
306
- self.run_python("-m", "pip", "install", *[str(arg) for arg in args])