snowflake-cli-labs 2.8.1__py3-none-any.whl → 3.0.0__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 (251) hide show
  1. snowflake/cli/__about__.py +1 -1
  2. snowflake/cli/{app → _app}/__main__.py +1 -1
  3. snowflake/cli/{app → _app}/cli_app.py +22 -13
  4. snowflake/cli/{app → _app}/commands_registration/builtin_plugins.py +15 -19
  5. snowflake/cli/{app → _app}/commands_registration/command_plugins_loader.py +9 -9
  6. snowflake/cli/{app → _app}/commands_registration/commands_registration_with_callbacks.py +4 -4
  7. snowflake/cli/{app → _app}/commands_registration/exception_logging.py +2 -2
  8. snowflake/cli/{app → _app}/commands_registration/typer_registration.py +2 -2
  9. snowflake/cli/{app → _app}/dev/docs/commands_docs_generator.py +30 -12
  10. snowflake/cli/{app → _app}/dev/docs/generator.py +3 -3
  11. snowflake/cli/{app → _app}/dev/docs/project_definition_docs_generator.py +4 -4
  12. snowflake/cli/{app → _app}/dev/docs/templates/usage.rst.jinja2 +14 -4
  13. snowflake/cli/{app → _app}/main_typer.py +2 -2
  14. snowflake/cli/{app → _app}/printing.py +2 -2
  15. snowflake/cli/_app/secret.py +9 -0
  16. snowflake/cli/{app → _app}/snow_connector.py +127 -61
  17. snowflake/cli/{app → _app}/telemetry.py +38 -7
  18. snowflake/cli/_app/version_check.py +74 -0
  19. snowflake/cli/{plugins → _plugins}/connection/commands.py +34 -11
  20. snowflake/cli/_plugins/connection/plugin_spec.py +30 -0
  21. snowflake/cli/{plugins → _plugins}/connection/util.py +16 -0
  22. snowflake/cli/{plugins → _plugins}/cortex/commands.py +54 -49
  23. snowflake/cli/{plugins → _plugins}/cortex/constants.py +1 -1
  24. snowflake/cli/{plugins → _plugins}/cortex/manager.py +5 -5
  25. snowflake/cli/{plugins → _plugins}/cortex/plugin_spec.py +1 -1
  26. snowflake/cli/{plugins → _plugins}/git/commands.py +11 -7
  27. snowflake/cli/{plugins → _plugins}/git/manager.py +55 -9
  28. snowflake/cli/{plugins → _plugins}/git/plugin_spec.py +1 -1
  29. snowflake/cli/_plugins/helpers/commands.py +90 -0
  30. snowflake/cli/{plugins/notebook → _plugins/helpers}/plugin_spec.py +1 -1
  31. snowflake/cli/{plugins → _plugins}/init/commands.py +2 -2
  32. snowflake/cli/{plugins → _plugins}/init/plugin_spec.py +1 -1
  33. snowflake/cli/{plugins → _plugins}/nativeapp/artifacts.py +24 -9
  34. snowflake/cli/_plugins/nativeapp/bundle_context.py +31 -0
  35. snowflake/cli/{plugins → _plugins}/nativeapp/codegen/artifact_processor.py +4 -4
  36. snowflake/cli/{plugins → _plugins}/nativeapp/codegen/compiler.py +37 -18
  37. snowflake/cli/_plugins/nativeapp/codegen/setup/native_app_setup_processor.py +249 -0
  38. snowflake/cli/{plugins → _plugins}/nativeapp/codegen/setup/setup_driver.py.source +5 -2
  39. snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/extension_function_utils.py +5 -5
  40. snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/models.py +1 -1
  41. snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/python_processor.py +29 -34
  42. snowflake/cli/_plugins/nativeapp/codegen/templates/templates_processor.py +114 -0
  43. snowflake/cli/{plugins → _plugins}/nativeapp/commands.py +252 -132
  44. snowflake/cli/{plugins → _plugins}/nativeapp/common_flags.py +1 -1
  45. snowflake/cli/_plugins/nativeapp/entities/application.py +878 -0
  46. snowflake/cli/_plugins/nativeapp/entities/application_package.py +1392 -0
  47. snowflake/cli/{plugins → _plugins}/nativeapp/exceptions.py +3 -12
  48. snowflake/cli/_plugins/nativeapp/manager.py +415 -0
  49. snowflake/cli/{plugins/connection → _plugins/nativeapp}/plugin_spec.py +1 -1
  50. snowflake/cli/{plugins → _plugins}/nativeapp/policy.py +3 -0
  51. snowflake/cli/{plugins → _plugins}/nativeapp/project_model.py +36 -20
  52. snowflake/cli/_plugins/nativeapp/run_processor.py +184 -0
  53. snowflake/cli/_plugins/nativeapp/same_account_install_method.py +70 -0
  54. snowflake/cli/_plugins/nativeapp/teardown_processor.py +70 -0
  55. snowflake/cli/_plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +262 -0
  56. snowflake/cli/{plugins → _plugins}/nativeapp/version/commands.py +20 -49
  57. snowflake/cli/_plugins/nativeapp/version/version_processor.py +98 -0
  58. snowflake/cli/{plugins → _plugins}/notebook/commands.py +3 -2
  59. snowflake/cli/{plugins → _plugins}/notebook/manager.py +5 -5
  60. snowflake/cli/{plugins/nativeapp → _plugins/notebook}/plugin_spec.py +1 -1
  61. snowflake/cli/{plugins → _plugins}/object/command_aliases.py +4 -4
  62. snowflake/cli/{plugins → _plugins}/object/commands.py +4 -5
  63. snowflake/cli/{plugins → _plugins}/object/manager.py +36 -15
  64. snowflake/cli/{plugins → _plugins}/object/plugin_spec.py +1 -1
  65. snowflake/cli/_plugins/snowpark/commands.py +450 -0
  66. snowflake/cli/_plugins/snowpark/common.py +268 -0
  67. snowflake/cli/{plugins → _plugins}/snowpark/models.py +0 -7
  68. snowflake/cli/{plugins → _plugins}/snowpark/package/anaconda_packages.py +2 -36
  69. snowflake/cli/{plugins → _plugins}/snowpark/package/commands.py +13 -74
  70. snowflake/cli/{plugins → _plugins}/snowpark/package/manager.py +2 -2
  71. snowflake/cli/{plugins → _plugins}/snowpark/package_utils.py +5 -5
  72. snowflake/cli/_plugins/snowpark/plugin_spec.py +30 -0
  73. snowflake/cli/_plugins/snowpark/snowpark_entity.py +29 -0
  74. snowflake/cli/_plugins/snowpark/snowpark_entity_model.py +173 -0
  75. snowflake/cli/_plugins/snowpark/snowpark_project_paths.py +109 -0
  76. snowflake/cli/{plugins → _plugins}/snowpark/snowpark_shared.py +0 -36
  77. snowflake/cli/{plugins → _plugins}/snowpark/zipper.py +16 -8
  78. snowflake/cli/{plugins → _plugins}/spcs/__init__.py +5 -7
  79. snowflake/cli/{plugins → _plugins}/spcs/compute_pool/commands.py +8 -8
  80. snowflake/cli/{plugins → _plugins}/spcs/compute_pool/manager.py +3 -3
  81. snowflake/cli/{plugins → _plugins}/spcs/image_registry/commands.py +3 -3
  82. snowflake/cli/{plugins → _plugins}/spcs/image_repository/commands.py +6 -6
  83. snowflake/cli/{plugins → _plugins}/spcs/image_repository/manager.py +1 -1
  84. snowflake/cli/{plugins → _plugins}/spcs/plugin_spec.py +1 -1
  85. snowflake/cli/{plugins → _plugins}/spcs/services/commands.py +44 -11
  86. snowflake/cli/{plugins → _plugins}/spcs/services/manager.py +43 -5
  87. snowflake/cli/{plugins → _plugins}/sql/commands.py +20 -17
  88. snowflake/cli/{plugins → _plugins}/sql/manager.py +1 -1
  89. snowflake/cli/{plugins → _plugins}/sql/plugin_spec.py +1 -1
  90. snowflake/cli/{plugins → _plugins}/stage/commands.py +15 -14
  91. snowflake/cli/{plugins → _plugins}/stage/diff.py +1 -47
  92. snowflake/cli/{plugins → _plugins}/stage/manager.py +12 -7
  93. snowflake/cli/{plugins → _plugins}/stage/plugin_spec.py +1 -1
  94. snowflake/cli/_plugins/stage/utils.py +54 -0
  95. snowflake/cli/{plugins → _plugins}/streamlit/commands.py +64 -48
  96. snowflake/cli/{plugins → _plugins}/streamlit/manager.py +67 -69
  97. snowflake/cli/_plugins/streamlit/plugin_spec.py +30 -0
  98. snowflake/cli/_plugins/streamlit/streamlit_entity.py +12 -0
  99. snowflake/cli/_plugins/streamlit/streamlit_entity_model.py +66 -0
  100. snowflake/cli/_plugins/workspace/action_context.py +18 -0
  101. snowflake/cli/_plugins/workspace/commands.py +306 -0
  102. snowflake/cli/_plugins/workspace/manager.py +74 -0
  103. snowflake/cli/_plugins/workspace/plugin_spec.py +30 -0
  104. snowflake/cli/api/cli_global_context.py +152 -295
  105. snowflake/cli/api/commands/common.py +25 -0
  106. snowflake/cli/api/commands/decorators.py +19 -4
  107. snowflake/cli/api/commands/experimental_behaviour.py +2 -3
  108. snowflake/cli/api/commands/flags.py +127 -228
  109. snowflake/cli/api/commands/overrideable_parameter.py +143 -0
  110. snowflake/cli/api/commands/snow_typer.py +21 -11
  111. snowflake/cli/api/commands/utils.py +18 -0
  112. snowflake/cli/api/config.py +44 -12
  113. snowflake/cli/api/connections.py +216 -0
  114. snowflake/cli/api/console/abc.py +8 -3
  115. snowflake/cli/api/constants.py +11 -0
  116. snowflake/cli/api/entities/common.py +56 -0
  117. snowflake/cli/api/entities/utils.py +370 -0
  118. snowflake/cli/api/errno.py +1 -0
  119. snowflake/cli/api/exceptions.py +31 -5
  120. snowflake/cli/api/feature_flags.py +0 -1
  121. snowflake/cli/api/identifiers.py +28 -5
  122. snowflake/cli/api/metrics.py +92 -0
  123. snowflake/cli/api/project/definition.py +48 -6
  124. snowflake/cli/api/project/definition_conversion.py +400 -0
  125. snowflake/cli/api/project/definition_manager.py +16 -5
  126. snowflake/cli/api/project/project_verification.py +3 -3
  127. snowflake/cli/api/project/schemas/entities/common.py +91 -16
  128. snowflake/cli/api/project/schemas/entities/entities.py +37 -6
  129. snowflake/cli/api/project/schemas/project_definition.py +180 -49
  130. snowflake/cli/api/project/schemas/updatable_model.py +11 -3
  131. snowflake/cli/api/project/schemas/v1/__init__.py +0 -0
  132. snowflake/cli/api/project/schemas/{identifier_model.py → v1/identifier_model.py} +3 -1
  133. snowflake/cli/api/project/schemas/v1/native_app/__init__.py +0 -0
  134. snowflake/cli/api/project/schemas/{native_app → v1/native_app}/application.py +8 -9
  135. snowflake/cli/api/project/schemas/{native_app → v1/native_app}/native_app.py +4 -4
  136. snowflake/cli/api/project/schemas/{native_app → v1/native_app}/package.py +7 -1
  137. snowflake/cli/api/project/schemas/v1/snowpark/__init__.py +0 -0
  138. snowflake/cli/api/project/schemas/{snowpark → v1/snowpark}/callable.py +2 -2
  139. snowflake/cli/api/project/schemas/{snowpark → v1/snowpark}/snowpark.py +2 -2
  140. snowflake/cli/api/project/schemas/v1/streamlit/__init__.py +0 -0
  141. snowflake/cli/api/project/schemas/{streamlit → v1/streamlit}/streamlit.py +2 -1
  142. snowflake/cli/api/project/util.py +23 -6
  143. snowflake/cli/api/rendering/jinja.py +14 -8
  144. snowflake/cli/api/rendering/project_definition_templates.py +5 -1
  145. snowflake/cli/api/rendering/sql_templates.py +56 -11
  146. snowflake/cli/api/rest_api.py +11 -5
  147. snowflake/cli/api/secure_path.py +16 -18
  148. snowflake/cli/api/secure_utils.py +90 -1
  149. snowflake/cli/api/sql_execution.py +43 -23
  150. snowflake/cli/api/utils/definition_rendering.py +45 -13
  151. {snowflake_cli_labs-2.8.1.dist-info → snowflake_cli_labs-3.0.0.dist-info}/METADATA +20 -18
  152. snowflake_cli_labs-3.0.0.dist-info/RECORD +242 -0
  153. snowflake_cli_labs-3.0.0.dist-info/entry_points.txt +2 -0
  154. snowflake/cli/api/commands/project_initialisation.py +0 -65
  155. snowflake/cli/api/commands/typer_pre_execute.py +0 -26
  156. snowflake/cli/api/project/schemas/entities/application_entity.py +0 -44
  157. snowflake/cli/api/project/schemas/entities/application_package_entity.py +0 -66
  158. snowflake/cli/app/build_and_push.sh +0 -8
  159. snowflake/cli/plugins/nativeapp/codegen/setup/native_app_setup_processor.py +0 -172
  160. snowflake/cli/plugins/nativeapp/init.py +0 -345
  161. snowflake/cli/plugins/nativeapp/manager.py +0 -823
  162. snowflake/cli/plugins/nativeapp/run_processor.py +0 -389
  163. snowflake/cli/plugins/nativeapp/teardown_processor.py +0 -301
  164. snowflake/cli/plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +0 -135
  165. snowflake/cli/plugins/nativeapp/version/version_processor.py +0 -362
  166. snowflake/cli/plugins/object_stage_deprecated/__init__.py +0 -15
  167. snowflake/cli/plugins/object_stage_deprecated/commands.py +0 -122
  168. snowflake/cli/plugins/object_stage_deprecated/plugin_spec.py +0 -32
  169. snowflake/cli/plugins/snowpark/commands.py +0 -546
  170. snowflake/cli/plugins/snowpark/common.py +0 -307
  171. snowflake/cli/plugins/snowpark/manager.py +0 -109
  172. snowflake/cli/plugins/snowpark/plugin_spec.py +0 -30
  173. snowflake/cli/plugins/snowpark/snowpark_package_paths.py +0 -65
  174. snowflake/cli/plugins/spcs/jobs/commands.py +0 -78
  175. snowflake/cli/plugins/spcs/jobs/manager.py +0 -53
  176. snowflake/cli/plugins/streamlit/__init__.py +0 -13
  177. snowflake/cli/plugins/streamlit/plugin_spec.py +0 -30
  178. snowflake/cli/plugins/workspace/__init__.py +0 -13
  179. snowflake/cli/plugins/workspace/commands.py +0 -35
  180. snowflake/cli/plugins/workspace/plugin_spec.py +0 -30
  181. snowflake/cli/templates/default_snowpark/.gitignore +0 -4
  182. snowflake/cli/templates/default_snowpark/app/common.py +0 -2
  183. snowflake/cli/templates/default_snowpark/app/functions.py +0 -15
  184. snowflake/cli/templates/default_snowpark/app/procedures.py +0 -22
  185. snowflake/cli/templates/default_snowpark/requirements.txt +0 -1
  186. snowflake/cli/templates/default_snowpark/snowflake.yml +0 -23
  187. snowflake/cli/templates/default_streamlit/.gitignore +0 -4
  188. snowflake/cli/templates/default_streamlit/common/hello.py +0 -2
  189. snowflake/cli/templates/default_streamlit/environment.yml +0 -6
  190. snowflake/cli/templates/default_streamlit/pages/my_page.py +0 -3
  191. snowflake/cli/templates/default_streamlit/snowflake.yml +0 -10
  192. snowflake/cli/templates/default_streamlit/streamlit_app.py +0 -4
  193. snowflake_cli_labs-2.8.1.dist-info/RECORD +0 -240
  194. snowflake_cli_labs-2.8.1.dist-info/entry_points.txt +0 -2
  195. /snowflake/cli/{app → _app}/__init__.py +0 -0
  196. /snowflake/cli/{api/project/schemas/native_app → _app/api_impl}/__init__.py +0 -0
  197. /snowflake/cli/{api/project/schemas/snowpark → _app/api_impl/plugin}/__init__.py +0 -0
  198. /snowflake/cli/{app → _app}/api_impl/plugin/plugin_config_provider_impl.py +0 -0
  199. /snowflake/cli/{app → _app}/commands_registration/__init__.py +0 -0
  200. /snowflake/cli/{app → _app}/commands_registration/threadsafe.py +0 -0
  201. /snowflake/cli/{app → _app}/constants.py +0 -0
  202. /snowflake/cli/{api/project/schemas/streamlit → _app/dev}/__init__.py +0 -0
  203. /snowflake/cli/{app → _app}/dev/commands_structure.py +0 -0
  204. /snowflake/cli/{app/api_impl → _app/dev/docs}/__init__.py +0 -0
  205. /snowflake/cli/{app → _app}/dev/docs/project_definition_generate_json_schema.py +0 -0
  206. /snowflake/cli/{app → _app}/dev/docs/template_utils.py +0 -0
  207. /snowflake/cli/{app → _app}/dev/docs/templates/definition_description.rst.jinja2 +0 -0
  208. /snowflake/cli/{app → _app}/dev/docs/templates/overview.rst.jinja2 +0 -0
  209. /snowflake/cli/{app → _app}/dev/pycharm_remote_debug.py +0 -0
  210. /snowflake/cli/{app → _app}/loggers.py +0 -0
  211. /snowflake/cli/{app/api_impl/plugin → _plugins}/__init__.py +0 -0
  212. /snowflake/cli/{app/dev → _plugins/connection}/__init__.py +0 -0
  213. /snowflake/cli/{app/dev/docs → _plugins/cortex}/__init__.py +0 -0
  214. /snowflake/cli/{plugins → _plugins}/cortex/types.py +0 -0
  215. /snowflake/cli/{plugins → _plugins/git}/__init__.py +0 -0
  216. /snowflake/cli/{plugins/connection → _plugins/helpers}/__init__.py +0 -0
  217. /snowflake/cli/{plugins/cortex → _plugins/init}/__init__.py +0 -0
  218. /snowflake/cli/{plugins/git → _plugins/nativeapp}/__init__.py +0 -0
  219. /snowflake/cli/{plugins/init → _plugins/nativeapp/codegen}/__init__.py +0 -0
  220. /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/sandbox.py +0 -0
  221. /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/callback_source.py.jinja +0 -0
  222. /snowflake/cli/{plugins → _plugins}/nativeapp/constants.py +0 -0
  223. /snowflake/cli/{templates/default_snowpark/app → _plugins/nativeapp/entities}/__init__.py +0 -0
  224. /snowflake/cli/{plugins → _plugins}/nativeapp/feature_flags.py +0 -0
  225. /snowflake/cli/{plugins → _plugins}/nativeapp/utils.py +0 -0
  226. /snowflake/cli/{plugins/nativeapp → _plugins/nativeapp/version}/__init__.py +0 -0
  227. /snowflake/cli/{plugins/nativeapp/codegen → _plugins/notebook}/__init__.py +0 -0
  228. /snowflake/cli/{plugins → _plugins}/notebook/exceptions.py +0 -0
  229. /snowflake/cli/{plugins → _plugins}/notebook/types.py +0 -0
  230. /snowflake/cli/{plugins/nativeapp/version → _plugins/object}/__init__.py +0 -0
  231. /snowflake/cli/{plugins → _plugins}/object/common.py +0 -0
  232. /snowflake/cli/{plugins/notebook → _plugins/snowpark}/__init__.py +0 -0
  233. /snowflake/cli/{plugins/object → _plugins/snowpark/package}/__init__.py +0 -0
  234. /snowflake/cli/{plugins → _plugins}/snowpark/package/utils.py +0 -0
  235. /snowflake/cli/{plugins → _plugins}/spcs/common.py +0 -0
  236. /snowflake/cli/{plugins/snowpark → _plugins/spcs/compute_pool}/__init__.py +0 -0
  237. /snowflake/cli/{plugins/snowpark/package → _plugins/spcs/image_registry}/__init__.py +0 -0
  238. /snowflake/cli/{plugins → _plugins}/spcs/image_registry/manager.py +0 -0
  239. /snowflake/cli/{plugins/spcs/compute_pool → _plugins/spcs/image_repository}/__init__.py +0 -0
  240. /snowflake/cli/{plugins/spcs/image_registry → _plugins/spcs/services}/__init__.py +0 -0
  241. /snowflake/cli/{plugins/spcs/image_repository → _plugins/sql}/__init__.py +0 -0
  242. /snowflake/cli/{plugins → _plugins}/sql/snowsql_templating.py +0 -0
  243. /snowflake/cli/{plugins/spcs/jobs → _plugins/stage}/__init__.py +0 -0
  244. /snowflake/cli/{plugins → _plugins}/stage/md5.py +0 -0
  245. /snowflake/cli/{plugins/spcs/services → _plugins/streamlit}/__init__.py +0 -0
  246. /snowflake/cli/{plugins/sql → _plugins/workspace}/__init__.py +0 -0
  247. /snowflake/cli/{plugins/stage → api/project/schemas/entities}/__init__.py +0 -0
  248. /snowflake/cli/api/project/schemas/{native_app → v1/native_app}/path_mapping.py +0 -0
  249. /snowflake/cli/api/project/schemas/{snowpark → v1/snowpark}/argument.py +0 -0
  250. {snowflake_cli_labs-2.8.1.dist-info → snowflake_cli_labs-3.0.0.dist-info}/WHEEL +0 -0
  251. {snowflake_cli_labs-2.8.1.dist-info → snowflake_cli_labs-3.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,184 @@
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 pathlib import Path
18
+ from typing import Optional
19
+
20
+ import typer
21
+ from snowflake.cli._plugins.nativeapp.artifacts import BundleMap
22
+ from snowflake.cli._plugins.nativeapp.entities.application import ApplicationEntity
23
+ from snowflake.cli._plugins.nativeapp.entities.application_package import (
24
+ ApplicationPackageEntity,
25
+ )
26
+ from snowflake.cli._plugins.nativeapp.manager import (
27
+ NativeAppCommandProcessor,
28
+ NativeAppManager,
29
+ )
30
+ from snowflake.cli._plugins.nativeapp.policy import PolicyBase
31
+ from snowflake.cli._plugins.nativeapp.same_account_install_method import (
32
+ SameAccountInstallMethod,
33
+ )
34
+ from snowflake.cli.api.console import cli_console as cc
35
+ from snowflake.cli.api.entities.common import get_sql_executor
36
+ from snowflake.cli.api.entities.utils import (
37
+ generic_sql_error_handler,
38
+ )
39
+ from snowflake.cli.api.errno import (
40
+ APPLICATION_NO_LONGER_AVAILABLE,
41
+ APPLICATION_OWNS_EXTERNAL_OBJECTS,
42
+ )
43
+ from snowflake.cli.api.project.schemas.v1.native_app.native_app import NativeApp
44
+ from snowflake.connector import ProgrammingError
45
+ from snowflake.connector.cursor import SnowflakeCursor
46
+
47
+
48
+ class NativeAppRunProcessor(NativeAppManager, NativeAppCommandProcessor):
49
+ def __init__(self, project_definition: NativeApp, project_root: Path):
50
+ super().__init__(project_definition, project_root)
51
+
52
+ def get_all_existing_versions(self) -> SnowflakeCursor:
53
+ return ApplicationPackageEntity.version_list(
54
+ self.package_name, self.package_role
55
+ )
56
+
57
+ def get_existing_version_info(self, version: str) -> Optional[dict]:
58
+ return ApplicationPackageEntity.get_existing_version_info(
59
+ version=version,
60
+ package_name=self.package_name,
61
+ package_role=self.package_role,
62
+ )
63
+
64
+ def drop_application_before_upgrade(
65
+ self, policy: PolicyBase, is_interactive: bool, cascade: bool = False
66
+ ):
67
+ """
68
+ This method will attempt to drop an application object if a previous upgrade fails.
69
+ """
70
+ if cascade:
71
+ try:
72
+ if application_objects := self.get_objects_owned_by_application():
73
+ application_objects_str = self._application_objects_to_str(
74
+ application_objects
75
+ )
76
+ cc.message(
77
+ f"The following objects are owned by application {self.app_name} and need to be dropped:\n{application_objects_str}"
78
+ )
79
+ except ProgrammingError as err:
80
+ if err.errno != APPLICATION_NO_LONGER_AVAILABLE:
81
+ generic_sql_error_handler(err)
82
+ cc.warning(
83
+ "The application owns other objects but they could not be determined."
84
+ )
85
+ user_prompt = "Do you want the Snowflake CLI to drop these objects, then drop the existing application object and recreate it?"
86
+ else:
87
+ user_prompt = "Do you want the Snowflake CLI to drop the existing application object and recreate it?"
88
+
89
+ if not policy.should_proceed(user_prompt):
90
+ if is_interactive:
91
+ cc.message("Not upgrading the application object.")
92
+ raise typer.Exit(0)
93
+ else:
94
+ cc.message(
95
+ "Cannot upgrade the application object non-interactively without --force."
96
+ )
97
+ raise typer.Exit(1)
98
+ try:
99
+ cascade_msg = " (cascade)" if cascade else ""
100
+ cc.step(f"Dropping application object {self.app_name}{cascade_msg}.")
101
+ cascade_sql = " cascade" if cascade else ""
102
+ sql_executor = get_sql_executor()
103
+ sql_executor.execute_query(f"drop application {self.app_name}{cascade_sql}")
104
+ except ProgrammingError as err:
105
+ if err.errno == APPLICATION_OWNS_EXTERNAL_OBJECTS and not cascade:
106
+ # We need to cascade the deletion, let's try again (only if we didn't try with cascade already)
107
+ return self.drop_application_before_upgrade(
108
+ policy, is_interactive, cascade=True
109
+ )
110
+ else:
111
+ generic_sql_error_handler(err)
112
+
113
+ def create_or_upgrade_app(
114
+ self,
115
+ policy: PolicyBase,
116
+ install_method: SameAccountInstallMethod,
117
+ is_interactive: bool = False,
118
+ ):
119
+ def drop_app():
120
+ self.drop_application_before_upgrade(policy, is_interactive)
121
+
122
+ return ApplicationEntity.create_or_upgrade_app(
123
+ console=cc,
124
+ project_root=self.project_root,
125
+ package_name=self.package_name,
126
+ package_role=self.package_role,
127
+ app_name=self.app_name,
128
+ app_role=self.app_role,
129
+ app_warehouse=self.application_warehouse,
130
+ stage_schema=self.stage_schema,
131
+ stage_fqn=self.stage_fqn,
132
+ debug_mode=self.debug_mode,
133
+ policy=policy,
134
+ install_method=install_method,
135
+ is_interactive=is_interactive,
136
+ post_deploy_hooks=self.app_post_deploy_hooks,
137
+ drop_application_before_upgrade=drop_app,
138
+ )
139
+
140
+ def process(
141
+ self,
142
+ bundle_map: BundleMap,
143
+ policy: PolicyBase,
144
+ version: Optional[str] = None,
145
+ patch: Optional[int] = None,
146
+ from_release_directive: bool = False,
147
+ is_interactive: bool = False,
148
+ validate: bool = True,
149
+ *args,
150
+ **kwargs,
151
+ ):
152
+ def deploy_package():
153
+ self.deploy(
154
+ bundle_map=bundle_map,
155
+ prune=True,
156
+ recursive=True,
157
+ validate=validate,
158
+ policy=policy,
159
+ )
160
+
161
+ def drop_app():
162
+ self.drop_application_before_upgrade(policy, is_interactive)
163
+
164
+ ApplicationEntity.deploy(
165
+ console=cc,
166
+ project_root=self.project_root,
167
+ app_name=self.app_name,
168
+ app_role=self.app_role,
169
+ app_warehouse=self.application_warehouse,
170
+ package_name=self.package_name,
171
+ package_role=self.package_role,
172
+ stage_schema=self.stage_schema,
173
+ stage_fqn=self.stage_fqn,
174
+ debug_mode=self.debug_mode,
175
+ validate=validate,
176
+ from_release_directive=from_release_directive,
177
+ is_interactive=is_interactive,
178
+ policy=policy,
179
+ version=version,
180
+ patch=patch,
181
+ post_deploy_hooks=self.app_post_deploy_hooks,
182
+ deploy_package=deploy_package,
183
+ drop_application_before_upgrade=drop_app,
184
+ )
@@ -0,0 +1,70 @@
1
+ from typing import Optional
2
+
3
+ from snowflake.cli._plugins.nativeapp.constants import (
4
+ ALLOWED_SPECIAL_COMMENTS,
5
+ COMMENT_COL,
6
+ )
7
+ from snowflake.cli._plugins.nativeapp.exceptions import (
8
+ ApplicationCreatedExternallyError,
9
+ )
10
+
11
+ # from snowflake.cli._plugins.nativeapp.project_model import NativeAppProjectModel
12
+ from snowflake.cli._plugins.stage.manager import StageManager
13
+
14
+
15
+ class SameAccountInstallMethod:
16
+ _requires_created_by_cli: bool
17
+ _from_release_directive: bool
18
+ version: Optional[str]
19
+ patch: Optional[int]
20
+
21
+ def __init__(
22
+ self,
23
+ requires_created_by_cli: bool,
24
+ version: Optional[str] = None,
25
+ patch: Optional[int] = None,
26
+ from_release_directive: bool = False,
27
+ ):
28
+ self._requires_created_by_cli = requires_created_by_cli
29
+ self.version = version
30
+ self.patch = patch
31
+ self._from_release_directive = from_release_directive
32
+
33
+ @classmethod
34
+ def unversioned_dev(cls):
35
+ """aka. stage dev aka loose files"""
36
+ return cls(True)
37
+
38
+ @classmethod
39
+ def versioned_dev(cls, version: str, patch: Optional[int] = None):
40
+ return cls(False, version, patch)
41
+
42
+ @classmethod
43
+ def release_directive(cls):
44
+ return cls(False, from_release_directive=True)
45
+
46
+ @property
47
+ def is_dev_mode(self) -> bool:
48
+ return not self._from_release_directive
49
+
50
+ def using_clause(
51
+ self,
52
+ stage_fqn: str,
53
+ ) -> str:
54
+ if self._from_release_directive:
55
+ return ""
56
+
57
+ if self.version:
58
+ patch_clause = f"patch {self.patch}" if self.patch else ""
59
+ return f"using version {self.version} {patch_clause}"
60
+
61
+ stage_name = StageManager.quote_stage_name(stage_fqn)
62
+ return f"using {stage_name}"
63
+
64
+ def ensure_app_usable(self, app_name: str, app_role: str, show_app_row: dict):
65
+ """Raise an exception if we cannot proceed with install given the pre-existing application object"""
66
+
67
+ if self._requires_created_by_cli:
68
+ if show_app_row[COMMENT_COL] not in ALLOWED_SPECIAL_COMMENTS:
69
+ # this application object was not created by this tooling
70
+ raise ApplicationCreatedExternallyError(app_name)
@@ -0,0 +1,70 @@
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 pathlib import Path
18
+ from typing import Dict, Optional
19
+
20
+ from snowflake.cli._plugins.nativeapp.entities.application import ApplicationEntity
21
+ from snowflake.cli._plugins.nativeapp.entities.application_package import (
22
+ ApplicationPackageEntity,
23
+ )
24
+ from snowflake.cli._plugins.nativeapp.manager import (
25
+ NativeAppCommandProcessor,
26
+ NativeAppManager,
27
+ )
28
+ from snowflake.cli.api.console import cli_console as cc
29
+
30
+
31
+ class NativeAppTeardownProcessor(NativeAppManager, NativeAppCommandProcessor):
32
+ def __init__(self, project_definition: Dict, project_root: Path):
33
+ super().__init__(project_definition, project_root)
34
+
35
+ def drop_application(
36
+ self, auto_yes: bool, interactive: bool = False, cascade: Optional[bool] = None
37
+ ):
38
+ return ApplicationEntity.drop(
39
+ console=cc,
40
+ app_name=self.app_name,
41
+ app_role=self.app_role,
42
+ auto_yes=auto_yes,
43
+ interactive=interactive,
44
+ cascade=cascade,
45
+ )
46
+
47
+ def drop_package(self, auto_yes: bool):
48
+ return ApplicationPackageEntity.drop(
49
+ console=cc,
50
+ package_name=self.package_name,
51
+ package_role=self.package_role,
52
+ force_drop=auto_yes,
53
+ )
54
+
55
+ def process(
56
+ self,
57
+ interactive: bool,
58
+ force_drop: bool = False,
59
+ cascade: Optional[bool] = None,
60
+ *args,
61
+ **kwargs,
62
+ ):
63
+
64
+ # Drop the application object
65
+ self.drop_application(
66
+ auto_yes=force_drop, interactive=interactive, cascade=cascade
67
+ )
68
+
69
+ # Drop the application package
70
+ self.drop_package(auto_yes=force_drop)
@@ -0,0 +1,262 @@
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 inspect
18
+ from functools import wraps
19
+ from typing import Any, Dict, Optional, Type, TypeVar, Union
20
+
21
+ import typer
22
+ from click import ClickException
23
+ from snowflake.cli._plugins.nativeapp.entities.application import ApplicationEntityModel
24
+ from snowflake.cli._plugins.nativeapp.entities.application_package import (
25
+ ApplicationPackageEntityModel,
26
+ )
27
+ from snowflake.cli.api.cli_global_context import (
28
+ get_cli_context,
29
+ get_cli_context_manager,
30
+ )
31
+ from snowflake.cli.api.commands.decorators import _options_decorator_factory
32
+ from snowflake.cli.api.project.schemas.entities.common import EntityModelBase
33
+ from snowflake.cli.api.project.schemas.project_definition import (
34
+ DefinitionV11,
35
+ DefinitionV20,
36
+ )
37
+ from snowflake.cli.api.project.schemas.v1.native_app.path_mapping import PathMapping
38
+ from snowflake.cli.api.utils.definition_rendering import render_definition_template
39
+
40
+
41
+ def _convert_v2_artifact_to_v1_dict(
42
+ v2_artifact: Union[PathMapping, str]
43
+ ) -> Union[Dict, str]:
44
+ if isinstance(v2_artifact, PathMapping):
45
+ return {
46
+ "src": v2_artifact.src,
47
+ "dest": v2_artifact.dest,
48
+ "processors": v2_artifact.processors,
49
+ }
50
+ return v2_artifact
51
+
52
+
53
+ def _pdf_v2_to_v1(
54
+ v2_definition: DefinitionV20,
55
+ package_entity_id: str = "",
56
+ app_entity_id: str = "",
57
+ app_required: bool = False,
58
+ ) -> DefinitionV11:
59
+ pdfv1: Dict[str, Any] = {"definition_version": "1.1", "native_app": {}}
60
+
61
+ # Determine the application entity to convert, there can be zero or one
62
+ app_definition = find_entity(
63
+ v2_definition,
64
+ ApplicationEntityModel,
65
+ app_entity_id,
66
+ disambiguation_option="--app-entity-id",
67
+ required=app_required,
68
+ )
69
+
70
+ # Infer or verify the package if we have an app entity to convert
71
+ if app_definition:
72
+ target_package = app_definition.from_.target
73
+ if package_entity_id:
74
+ # If the user specified a package entity ID,
75
+ # check that the app entity targets the user-specified package entity
76
+ # if the app entity is used by the command being run
77
+ if target_package != package_entity_id and app_required:
78
+ raise ClickException(
79
+ f"The application entity {app_definition.entity_id} does not "
80
+ f"target the application package entity {package_entity_id}. Either"
81
+ f"use --package-entity-id {target_package} to target the correct package entity, "
82
+ f"or omit the --package-entity-id flag to automatically use the package entity "
83
+ f"that the application entity targets."
84
+ )
85
+ elif target_package in v2_definition.get_entities_by_type(
86
+ ApplicationPackageEntityModel.get_type()
87
+ ):
88
+ # If the user didn't target a specific package entity, use the one the app entity targets
89
+ package_entity_id = target_package
90
+
91
+ # Determine the package entity to convert, there must be one
92
+ app_package_definition = find_entity(
93
+ v2_definition,
94
+ ApplicationPackageEntityModel,
95
+ package_entity_id,
96
+ disambiguation_option="--package-entity-id",
97
+ required=True,
98
+ )
99
+ assert app_package_definition is not None # satisfy mypy
100
+
101
+ # NativeApp
102
+ if app_definition and app_definition.fqn.identifier:
103
+ pdfv1["native_app"]["name"] = app_definition.fqn.identifier
104
+ else:
105
+ pdfv1["native_app"]["name"] = app_package_definition.fqn.identifier.split(
106
+ "_pkg_"
107
+ )[0]
108
+ pdfv1["native_app"]["artifacts"] = [
109
+ _convert_v2_artifact_to_v1_dict(a) for a in app_package_definition.artifacts
110
+ ]
111
+ pdfv1["native_app"]["source_stage"] = app_package_definition.stage
112
+ pdfv1["native_app"]["bundle_root"] = app_package_definition.bundle_root
113
+ pdfv1["native_app"]["generated_root"] = app_package_definition.generated_root
114
+ pdfv1["native_app"]["deploy_root"] = app_package_definition.deploy_root
115
+ pdfv1["native_app"]["scratch_stage"] = app_package_definition.scratch_stage
116
+
117
+ # Package
118
+ pdfv1["native_app"]["package"] = {}
119
+ pdfv1["native_app"]["package"]["name"] = app_package_definition.fqn.identifier
120
+ if app_package_definition.distribution:
121
+ pdfv1["native_app"]["package"][
122
+ "distribution"
123
+ ] = app_package_definition.distribution
124
+ if app_package_definition.meta and app_package_definition.meta.post_deploy:
125
+ pdfv1["native_app"]["package"][
126
+ "post_deploy"
127
+ ] = app_package_definition.meta.post_deploy
128
+ if app_package_definition.meta:
129
+ if app_package_definition.meta.role:
130
+ pdfv1["native_app"]["package"]["role"] = app_package_definition.meta.role
131
+ if app_package_definition.meta.warehouse:
132
+ pdfv1["native_app"]["package"][
133
+ "warehouse"
134
+ ] = app_package_definition.meta.warehouse
135
+
136
+ # Application
137
+ if app_definition:
138
+ pdfv1["native_app"]["application"] = {}
139
+ pdfv1["native_app"]["application"]["name"] = app_definition.fqn.identifier
140
+ if app_definition.debug:
141
+ pdfv1["native_app"]["application"]["debug"] = app_definition.debug
142
+ if app_definition.meta:
143
+ if app_definition.meta.role:
144
+ pdfv1["native_app"]["application"]["role"] = app_definition.meta.role
145
+ if app_definition.meta.warehouse:
146
+ pdfv1["native_app"]["application"][
147
+ "warehouse"
148
+ ] = app_definition.meta.warehouse
149
+ if app_definition.meta.post_deploy:
150
+ pdfv1["native_app"]["application"][
151
+ "post_deploy"
152
+ ] = app_definition.meta.post_deploy
153
+
154
+ result = render_definition_template(pdfv1, {})
155
+ # Override the definition object in global context
156
+ return result.project_definition
157
+
158
+
159
+ T = TypeVar("T", bound=EntityModelBase)
160
+
161
+
162
+ def find_entity(
163
+ project_definition: DefinitionV20,
164
+ entity_class: Type[T],
165
+ entity_id: str,
166
+ disambiguation_option: str,
167
+ required: bool,
168
+ ) -> T | None:
169
+ """
170
+ Find an entity of the specified type in the project definition file.
171
+
172
+ If an ID is passed, only that entity will be considered,
173
+ otherwise look for a single entity of the specified type.
174
+
175
+ If there are multiple entities of the specified type,
176
+ the user must specify which one to use using the CLI option
177
+ named in the disambiguation_option parameter.
178
+
179
+ If no entity is found, an error is raised if required is True,
180
+ otherwise None is returned.
181
+ """
182
+
183
+ entity_type = entity_class.get_type()
184
+ entities = project_definition.get_entities_by_type(entity_type)
185
+
186
+ entity: Optional[T] = None
187
+
188
+ if entity_id:
189
+ # If we're looking for a specific entity, use that one directly
190
+ entity = entities.get(entity_id)
191
+ elif len(entities) == 1:
192
+ # Otherwise, if there is only one entity, fall back to that one
193
+ entity = next(iter(entities.values()))
194
+ elif len(entities) > 1 and required:
195
+ # If there are multiple entities and it's required,
196
+ # the user must specify which one to use
197
+ raise ClickException(
198
+ f"More than one {entity_type} entity exists in the project definition file, "
199
+ f"specify {disambiguation_option} to choose which one to operate on."
200
+ )
201
+
202
+ # If we don't have a package entity to convert, error out if it's required
203
+ if not entity and required:
204
+ with_id = f'with ID "{entity_id}" ' if entity_id else ""
205
+ raise ClickException(
206
+ f"Could not find an {entity_type} entity {with_id}in the project definition file."
207
+ )
208
+
209
+ return entity
210
+
211
+
212
+ def nativeapp_definition_v2_to_v1(*, app_required: bool = False):
213
+ """
214
+ A command decorator that attempts to automatically convert a native app project from
215
+ definition v2 to v1.1. Assumes with_project_definition() has already been called.
216
+ The definition object in CliGlobalContext will be replaced with the converted object.
217
+ Exactly one application package entity type is expected, and up to one application
218
+ entity type is expected.
219
+ """
220
+
221
+ def decorator(func):
222
+ @wraps(func)
223
+ def wrapper(*args, **kwargs):
224
+ original_pdf: Optional[DefinitionV20] = get_cli_context().project_definition
225
+ if not original_pdf:
226
+ raise ValueError(
227
+ "Project definition could not be found. The nativeapp_definition_v2_to_v1 command decorator assumes with_project_definition() was called before it."
228
+ )
229
+ if original_pdf.definition_version == "2":
230
+ package_entity_id = kwargs.get("package_entity_id", "")
231
+ app_entity_id = kwargs.get("app_entity_id", "")
232
+ pdfv1 = _pdf_v2_to_v1(
233
+ original_pdf, package_entity_id, app_entity_id, app_required
234
+ )
235
+ get_cli_context_manager().override_project_definition = pdfv1
236
+ return func(*args, **kwargs)
237
+
238
+ return _options_decorator_factory(
239
+ wrapper,
240
+ additional_options=[
241
+ inspect.Parameter(
242
+ "package_entity_id",
243
+ inspect.Parameter.KEYWORD_ONLY,
244
+ annotation=Optional[str],
245
+ default=typer.Option(
246
+ default="",
247
+ help="The ID of the package entity on which to operate when definition_version is 2 or higher.",
248
+ ),
249
+ ),
250
+ inspect.Parameter(
251
+ "app_entity_id",
252
+ inspect.Parameter.KEYWORD_ONLY,
253
+ annotation=Optional[str],
254
+ default=typer.Option(
255
+ default="",
256
+ help="The ID of the application entity on which to operate when definition_version is 2 or higher.",
257
+ ),
258
+ ),
259
+ ],
260
+ )
261
+
262
+ return decorator