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,268 @@
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 logging
18
+ import re
19
+ from enum import Enum
20
+ from typing import Dict, List, Set
21
+
22
+ from click import UsageError
23
+ from snowflake.cli._plugins.snowpark.models import Requirement
24
+ from snowflake.cli._plugins.snowpark.snowpark_entity_model import (
25
+ ProcedureEntityModel,
26
+ SnowparkEntityModel,
27
+ )
28
+ from snowflake.cli._plugins.snowpark.snowpark_project_paths import Artefact
29
+ from snowflake.cli.api.console import cli_console
30
+ from snowflake.cli.api.constants import (
31
+ INIT_TEMPLATE_VARIABLE_CLOSING,
32
+ INIT_TEMPLATE_VARIABLE_OPENING,
33
+ PROJECT_TEMPLATE_VARIABLE_CLOSING,
34
+ PROJECT_TEMPLATE_VARIABLE_OPENING,
35
+ ObjectType,
36
+ )
37
+ from snowflake.cli.api.sql_execution import SqlExecutionMixin
38
+ from snowflake.connector.cursor import SnowflakeCursor
39
+
40
+ log = logging.getLogger(__name__)
41
+
42
+ SnowparkEntities = Dict[str, SnowparkEntityModel]
43
+ StageToArtefactMapping = Dict[str, set[Artefact]]
44
+ EntityToImportPathsMapping = Dict[str, set[str]]
45
+
46
+ DEFAULT_RUNTIME = "3.10"
47
+
48
+
49
+ class SnowparkObject(Enum):
50
+ """This clas is used only for Snowpark execute where choice is limited."""
51
+
52
+ PROCEDURE = str(ObjectType.PROCEDURE)
53
+ FUNCTION = str(ObjectType.FUNCTION)
54
+
55
+
56
+ class SnowparkObjectManager(SqlExecutionMixin):
57
+ def execute(
58
+ self, execution_identifier: str, object_type: SnowparkObject
59
+ ) -> SnowflakeCursor:
60
+ if object_type == SnowparkObject.FUNCTION:
61
+ return self._execute_query(f"select {execution_identifier}")
62
+ if object_type == SnowparkObject.PROCEDURE:
63
+ return self._execute_query(f"call {execution_identifier}")
64
+ raise UsageError(f"Unknown object type: {object_type}.")
65
+
66
+ def create_or_replace(
67
+ self,
68
+ entity: SnowparkEntityModel,
69
+ artifact_files: set[str],
70
+ snowflake_dependencies: list[str],
71
+ ) -> str:
72
+ entity.imports.extend(artifact_files)
73
+ imports = [f"'{x}'" for x in entity.imports]
74
+ packages_list = ",".join(f"'{p}'" for p in snowflake_dependencies)
75
+
76
+ object_type = entity.get_type()
77
+
78
+ query = [
79
+ f"create or replace {object_type} {entity.udf_sproc_identifier.identifier_for_sql}",
80
+ f"copy grants",
81
+ f"returns {entity.returns}",
82
+ "language python",
83
+ f"runtime_version={entity.runtime or DEFAULT_RUNTIME}",
84
+ f"imports=({', '.join(imports)})",
85
+ f"handler='{entity.handler}'",
86
+ f"packages=({packages_list})",
87
+ ]
88
+
89
+ if entity.external_access_integrations:
90
+ query.append(entity.get_external_access_integrations_sql())
91
+
92
+ if entity.secrets:
93
+ query.append(entity.get_secrets_sql())
94
+
95
+ if isinstance(entity, ProcedureEntityModel) and entity.execute_as_caller:
96
+ query.append("execute as caller")
97
+
98
+ return self._execute_query("\n".join(query))
99
+
100
+ def deploy_entity(
101
+ self,
102
+ entity: SnowparkEntityModel,
103
+ existing_objects: Dict[str, SnowflakeCursor],
104
+ snowflake_dependencies: List[str],
105
+ entities_to_artifact_map: EntityToImportPathsMapping,
106
+ ):
107
+ cli_console.step(f"Creating {entity.type} {entity.fqn}")
108
+ object_exists = entity.entity_id in existing_objects
109
+ replace_object = False
110
+ if object_exists:
111
+ replace_object = _check_if_replace_is_required(
112
+ entity=entity,
113
+ current_state=existing_objects[entity.entity_id],
114
+ snowflake_dependencies=snowflake_dependencies,
115
+ stage_artifact_files=entities_to_artifact_map[entity.entity_id],
116
+ )
117
+
118
+ state = {
119
+ "object": entity.udf_sproc_identifier.identifier_with_arg_names_types_defaults,
120
+ "type": entity.get_type(),
121
+ }
122
+ if object_exists and not replace_object:
123
+ return {**state, "status": "packages updated"}
124
+
125
+ self.create_or_replace(
126
+ entity=entity,
127
+ artifact_files=entities_to_artifact_map[entity.entity_id],
128
+ snowflake_dependencies=snowflake_dependencies,
129
+ )
130
+ return {
131
+ **state,
132
+ "status": "created" if not object_exists else "definition updated",
133
+ }
134
+
135
+
136
+ def _check_if_replace_is_required(
137
+ entity: SnowparkEntityModel,
138
+ current_state,
139
+ snowflake_dependencies: List[str],
140
+ stage_artifact_files: set[str],
141
+ ) -> bool:
142
+ object_type = entity.get_type()
143
+ resource_json = _convert_resource_details_to_dict(current_state)
144
+ old_dependencies = resource_json["packages"]
145
+
146
+ if _snowflake_dependencies_differ(old_dependencies, snowflake_dependencies):
147
+ log.info(
148
+ "Found difference of package requirements. Replacing the %s.", object_type
149
+ )
150
+ return True
151
+
152
+ if set(entity.external_access_integrations) != set(
153
+ resource_json.get("external_access_integrations", [])
154
+ ):
155
+ log.info(
156
+ "Found difference of external access integrations. Replacing the %s.",
157
+ object_type,
158
+ )
159
+ return True
160
+
161
+ if (
162
+ resource_json["handler"].lower() != entity.handler.lower()
163
+ or _sql_to_python_return_type_mapper(resource_json["returns"]).lower()
164
+ != entity.returns.lower()
165
+ ):
166
+ log.info(
167
+ "Return type or handler types do not match. Replacing the %s.", object_type
168
+ )
169
+ return True
170
+
171
+ if _compare_imports(resource_json, entity.imports, stage_artifact_files):
172
+ log.info("Imports do not match. Replacing the %s", object_type)
173
+ return True
174
+
175
+ if entity.runtime is not None and entity.runtime != resource_json.get(
176
+ "runtime_version", "RUNTIME_NOT_SET"
177
+ ):
178
+ log.info("Runtime versions do not match. Replacing the %s", object_type)
179
+ return True
180
+
181
+ if isinstance(entity, ProcedureEntityModel):
182
+ if resource_json.get("execute as", "OWNER") != (
183
+ "CALLER" if entity.execute_as_caller else "OWNER"
184
+ ):
185
+ log.info(
186
+ "Execute as caller settings do not match. Replacing the %s", object_type
187
+ )
188
+ return True
189
+
190
+ return False
191
+
192
+
193
+ def _convert_resource_details_to_dict(function_details: SnowflakeCursor) -> dict:
194
+ import json
195
+
196
+ function_dict = {}
197
+ json_properties = ["packages", "installed_packages"]
198
+ for function in function_details:
199
+ if function[0] in json_properties:
200
+ function_dict[function[0]] = json.loads(
201
+ function[1].replace("'", '"'),
202
+ )
203
+ else:
204
+ function_dict[function[0]] = function[1]
205
+ return function_dict
206
+
207
+
208
+ def _snowflake_dependencies_differ(
209
+ old_dependencies: List[str], new_dependencies: List[str]
210
+ ) -> bool:
211
+ def _standardize(packages: List[str]) -> Set[str]:
212
+ return set(
213
+ Requirement.parse_line(package).name_and_version for package in packages
214
+ )
215
+
216
+ return _standardize(old_dependencies) != _standardize(new_dependencies)
217
+
218
+
219
+ def _sql_to_python_return_type_mapper(resource_return_type: str) -> str:
220
+ """
221
+ Some of the Python data types get converted to SQL types, when function/procedure is created.
222
+ So, to properly compare types, we use mapping based on:
223
+ https://docs.snowflake.com/en/developer-guide/udf-stored-procedure-data-type-mapping#sql-python-data-type-mappings
224
+
225
+ Mind you, this only applies to cases, in which Snowflake accepts Python type as return.
226
+ Ie. if function returns list, it has to be declared as 'array' during creation,
227
+ therefore any conversion is not necessary
228
+ """
229
+ mapping = {
230
+ "number(38,0)": "int",
231
+ "timestamp_ntz(9)": "datetime",
232
+ "timestamp_tz(9)": "datetime",
233
+ "varchar(16777216)": "string",
234
+ }
235
+
236
+ return mapping.get(resource_return_type.lower(), resource_return_type.lower())
237
+
238
+
239
+ def _compare_imports(
240
+ resource_json: dict, imports: List[str], artifact_files: set[str]
241
+ ) -> bool:
242
+ pattern = re.compile(r"(?:\[@?\w+_\w+\.)?(\w+(?:/\w+)+\.\w+)(?:\])?")
243
+
244
+ project_imports = {
245
+ imp
246
+ for import_string in [*imports, *artifact_files]
247
+ for imp in pattern.findall(import_string.lower())
248
+ }
249
+
250
+ if "imports" not in resource_json.keys():
251
+ object_imports = set()
252
+ else:
253
+ object_imports = {
254
+ imp.lower()
255
+ for imp in pattern.findall(resource_json.get("imports", "").lower())
256
+ }
257
+
258
+ return project_imports != object_imports
259
+
260
+
261
+ def is_name_a_templated_one(name: str) -> bool:
262
+ return (
263
+ PROJECT_TEMPLATE_VARIABLE_OPENING in name
264
+ and PROJECT_TEMPLATE_VARIABLE_CLOSING in name
265
+ ) or (
266
+ INIT_TEMPLATE_VARIABLE_OPENING in name
267
+ and INIT_TEMPLATE_VARIABLE_CLOSING in name
268
+ )
@@ -17,19 +17,12 @@ from __future__ import annotations
17
17
  import re
18
18
  import zipfile
19
19
  from dataclasses import dataclass
20
- from enum import Enum
21
20
  from pathlib import Path
22
21
  from typing import List
23
22
 
24
23
  from requirements import requirement
25
24
 
26
25
 
27
- class YesNoAsk(Enum):
28
- YES = "yes"
29
- NO = "no"
30
- ASK = "ask"
31
-
32
-
33
26
  class Requirement(requirement.Requirement):
34
27
  extra_pattern = re.compile("'([^']*)'")
35
28
 
@@ -18,16 +18,13 @@ import logging
18
18
  from dataclasses import dataclass
19
19
  from typing import Dict, List, Set
20
20
 
21
- import requests
22
- from click import ClickException
23
21
  from packaging.requirements import InvalidRequirement
24
22
  from packaging.requirements import Requirement as PkgRequirement
25
23
  from packaging.version import InvalidVersion, parse
26
- from requests import HTTPError
24
+ from snowflake.cli._plugins.snowpark.models import Requirement
27
25
  from snowflake.cli.api.exceptions import SnowflakeSQLExecutionError
28
26
  from snowflake.cli.api.secure_path import SecurePath
29
27
  from snowflake.cli.api.sql_execution import SqlExecutionMixin
30
- from snowflake.cli.plugins.snowpark.models import Requirement
31
28
  from snowflake.connector import DictCursor
32
29
 
33
30
  log = logging.getLogger(__name__)
@@ -170,23 +167,13 @@ class AnacondaPackagesManager(SqlExecutionMixin):
170
167
  "https://repo.anaconda.com/pkgs/snowflake/channeldata.json"
171
168
  )
172
169
 
173
- # TODO in v3.0: Keep only SQL query, remove fallback to JSON with channel's metadata
174
170
  def find_packages_available_in_snowflake_anaconda(self) -> AnacondaPackages:
175
171
  """
176
172
  Finds python packages available in Snowflake to use in functions and stored procedures.
177
173
  It tries to get the list of packages using SQL query
178
174
  but if the try fails then the fallback is to parse JSON containing info about Snowflake's Anaconda channel.
179
175
  """
180
- try:
181
- packages = self._query_snowflake_for_available_packages()
182
- except Exception as ex:
183
- log.warning(
184
- "Cannot fetch available packages information from Snowflake. "
185
- "Please check your connection configuration. "
186
- "Fallback to Anaconda channel metadata."
187
- )
188
- log.debug("Available packages query failure: %s", ex.__str__(), exc_info=ex)
189
- packages = self._get_available_packages_from_anaconda_channel_info()
176
+ packages = self._query_snowflake_for_available_packages()
190
177
  return AnacondaPackages(packages)
191
178
 
192
179
  def _query_snowflake_for_available_packages(self) -> dict[str, AvailablePackage]:
@@ -210,24 +197,3 @@ class AnacondaPackagesManager(SqlExecutionMixin):
210
197
  snowflake_name=package_name, versions={version}
211
198
  )
212
199
  return packages
213
-
214
- def _get_available_packages_from_anaconda_channel_info(
215
- self,
216
- ) -> dict[str, AvailablePackage]:
217
- try:
218
- response = requests.get(self._snowflake_channel_url)
219
- response.raise_for_status()
220
- packages = {}
221
- for key, package in response.json()["packages"].items():
222
- if not (version := package.get("version")):
223
- continue
224
- package_name = package.get("name", key)
225
- standardized_name = Requirement.standardize_name(package_name)
226
- packages[standardized_name] = AvailablePackage(
227
- snowflake_name=package_name, versions={version}
228
- )
229
- return packages
230
- except HTTPError as err:
231
- raise ClickException(
232
- f"Accessing Snowflake Anaconda channel failed. Reason {err}"
233
- )
@@ -21,35 +21,29 @@ from typing import Optional
21
21
 
22
22
  import typer
23
23
  from click import ClickException
24
- from snowflake.cli.api.commands.flags import (
25
- deprecated_flag_callback,
26
- )
27
- from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
28
- from snowflake.cli.api.output.types import CommandResult, MessageResult
29
- from snowflake.cli.api.secure_path import SecurePath
30
- from snowflake.cli.plugins.snowpark.models import (
24
+ from snowflake.cli._plugins.snowpark.models import (
31
25
  Requirement,
32
- YesNoAsk,
33
26
  )
34
- from snowflake.cli.plugins.snowpark.package.anaconda_packages import (
27
+ from snowflake.cli._plugins.snowpark.package.anaconda_packages import (
35
28
  AnacondaPackages,
36
29
  AnacondaPackagesManager,
37
30
  )
38
- from snowflake.cli.plugins.snowpark.package.manager import upload
39
- from snowflake.cli.plugins.snowpark.package_utils import (
31
+ from snowflake.cli._plugins.snowpark.package.manager import upload
32
+ from snowflake.cli._plugins.snowpark.package_utils import (
40
33
  detect_and_log_shared_libraries,
41
34
  download_unavailable_packages,
42
35
  get_package_name_from_pip_wheel,
43
36
  )
44
- from snowflake.cli.plugins.snowpark.snowpark_shared import (
37
+ from snowflake.cli._plugins.snowpark.snowpark_shared import (
45
38
  AllowSharedLibrariesOption,
46
39
  IgnoreAnacondaOption,
47
40
  IndexUrlOption,
48
41
  SkipVersionCheckOption,
49
- deprecated_allow_native_libraries_option,
50
- resolve_allow_shared_libraries_yes_no_ask,
51
42
  )
52
- from snowflake.cli.plugins.snowpark.zipper import zip_dir
43
+ from snowflake.cli._plugins.snowpark.zipper import zip_dir
44
+ from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
45
+ from snowflake.cli.api.output.types import CommandResult, MessageResult
46
+ from snowflake.cli.api.secure_path import SecurePath
53
47
 
54
48
  app = SnowTyperFactory(
55
49
  name="package",
@@ -58,36 +52,11 @@ app = SnowTyperFactory(
58
52
  log = logging.getLogger(__name__)
59
53
 
60
54
 
61
- lookup_install_option = typer.Option(
62
- False,
63
- "--pypi-download",
64
- hidden=True,
65
- callback=deprecated_flag_callback(
66
- "Using --pypi-download is deprecated. Lookup command no longer checks for package in PyPi."
67
- ),
68
- help="Installs packages that are not available on the Snowflake Anaconda channel.",
69
- )
70
-
71
- lookup_deprecated_install_option = typer.Option(
72
- False,
73
- "--yes",
74
- "-y",
75
- hidden=True,
76
- callback=deprecated_flag_callback(
77
- "Using --yes is deprecated. Lookup command no longer checks for package in PyPi."
78
- ),
79
- help="Installs packages that are not available on the Snowflake Anaconda channel.",
80
- )
81
-
82
-
83
55
  @app.command("lookup", requires_connection=True)
84
56
  def package_lookup(
85
57
  package_name: str = typer.Argument(
86
58
  ..., help="Name of the package.", show_default=False
87
59
  ),
88
- # todo: remove with 3.0
89
- _: bool = lookup_install_option,
90
- __: bool = lookup_deprecated_install_option,
91
60
  **options,
92
61
  ) -> CommandResult:
93
62
  """
@@ -125,12 +94,14 @@ def package_upload(
125
94
  "-f",
126
95
  help="Path to the file to upload.",
127
96
  exists=False,
97
+ show_default=False,
128
98
  ),
129
99
  stage: str = typer.Option(
130
100
  ...,
131
101
  "--stage",
132
102
  "-s",
133
103
  help="Name of the stage in which to upload the file, not including the @ symbol.",
104
+ show_default=False,
134
105
  ),
135
106
  overwrite: bool = typer.Option(
136
107
  False,
@@ -146,43 +117,17 @@ def package_upload(
146
117
  return MessageResult(upload(file=file, stage=stage, overwrite=overwrite))
147
118
 
148
119
 
149
- deprecated_pypi_download_option = typer.Option(
150
- False,
151
- "--pypi-download",
152
- hidden=True,
153
- callback=deprecated_flag_callback(
154
- "Using --pypi-download is deprecated. Create command always checks for package in PyPi."
155
- ),
156
- help="Installs packages that are not available on the Snowflake Anaconda channel.",
157
- )
158
-
159
- deprecated_install_option = typer.Option(
160
- False,
161
- "--yes",
162
- "-y",
163
- hidden=True,
164
- help="Installs packages that are not available on the Snowflake Anaconda channel.",
165
- callback=deprecated_flag_callback(
166
- "Using --yes is deprecated. Create command always checks for package in PyPi."
167
- ),
168
- )
169
-
170
-
171
120
  @app.command("create", requires_connection=True)
172
121
  def package_create(
173
122
  name: str = typer.Argument(
174
123
  ...,
175
124
  help="Name of the package to create.",
125
+ show_default=False,
176
126
  ),
177
127
  ignore_anaconda: bool = IgnoreAnacondaOption,
178
128
  index_url: Optional[str] = IndexUrlOption,
179
129
  skip_version_check: bool = SkipVersionCheckOption,
180
130
  allow_shared_libraries: bool = AllowSharedLibrariesOption,
181
- deprecated_allow_native_libraries: YesNoAsk = deprecated_allow_native_libraries_option(
182
- "--allow-native-libraries"
183
- ),
184
- _deprecated_install_option: bool = deprecated_install_option,
185
- _deprecated_install_packages: bool = deprecated_pypi_download_option,
186
131
  **options,
187
132
  ) -> CommandResult:
188
133
  """
@@ -217,13 +162,7 @@ def package_create(
217
162
  # The package is not in anaconda, so we have to pack it
218
163
  log.info("Checking to see if packages have shared (.so/.dll) libraries...")
219
164
  if detect_and_log_shared_libraries(download_result.downloaded_packages_details):
220
- # TODO: yes/no/ask logic should be removed in 3.0
221
- if not (
222
- allow_shared_libraries
223
- or resolve_allow_shared_libraries_yes_no_ask(
224
- deprecated_allow_native_libraries
225
- )
226
- ):
165
+ if not allow_shared_libraries:
227
166
  raise ClickException(
228
167
  "Some packages contain shared (.so/.dll) libraries. "
229
168
  "Try again with --allow-shared-libraries."
@@ -17,10 +17,10 @@ from __future__ import annotations
17
17
  import logging
18
18
  from pathlib import Path
19
19
 
20
+ from snowflake.cli._plugins.snowpark.package.utils import prepare_app_zip
21
+ from snowflake.cli._plugins.stage.manager import StageManager
20
22
  from snowflake.cli.api.identifiers import FQN
21
23
  from snowflake.cli.api.secure_path import SecurePath
22
- from snowflake.cli.plugins.snowpark.package.utils import prepare_app_zip
23
- from snowflake.cli.plugins.stage.manager import StageManager
24
24
 
25
25
  log = logging.getLogger(__name__)
26
26
 
@@ -25,17 +25,17 @@ from textwrap import dedent
25
25
  from typing import Dict, List, Optional
26
26
 
27
27
  from click import ClickException
28
- from snowflake.cli.api.constants import DEFAULT_SIZE_LIMIT_MB
29
- from snowflake.cli.api.secure_path import SecurePath
30
- from snowflake.cli.plugins.snowpark.models import (
28
+ from snowflake.cli._plugins.snowpark.models import (
31
29
  Requirement,
32
30
  RequirementWithFiles,
33
31
  RequirementWithWheel,
34
32
  WheelMetadata,
35
33
  )
36
- from snowflake.cli.plugins.snowpark.package.anaconda_packages import (
34
+ from snowflake.cli._plugins.snowpark.package.anaconda_packages import (
37
35
  AnacondaPackages,
38
36
  )
37
+ from snowflake.cli.api.constants import DEFAULT_SIZE_LIMIT_MB
38
+ from snowflake.cli.api.secure_path import SecurePath
39
39
 
40
40
  log = logging.getLogger(__name__)
41
41
 
@@ -61,7 +61,7 @@ def parse_requirements(
61
61
  ).splitlines():
62
62
  line = re.sub(r"\s*#.*", "", line).strip()
63
63
  if line:
64
- reqs.append(Requirement.parse(line))
64
+ reqs.append(Requirement.parse_line(line))
65
65
  return reqs
66
66
 
67
67
 
@@ -0,0 +1,30 @@
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 snowflake.cli._plugins.snowpark import commands
16
+ from snowflake.cli.api.plugins.command import (
17
+ SNOWCLI_ROOT_COMMAND_PATH,
18
+ CommandSpec,
19
+ CommandType,
20
+ plugin_hook_impl,
21
+ )
22
+
23
+
24
+ @plugin_hook_impl
25
+ def command_spec():
26
+ return CommandSpec(
27
+ parent_command_path=SNOWCLI_ROOT_COMMAND_PATH,
28
+ command_type=CommandType.COMMAND_GROUP,
29
+ typer_instance=commands.app.create_instance(),
30
+ )
@@ -0,0 +1,29 @@
1
+ from typing import Generic, TypeVar
2
+
3
+ from snowflake.cli._plugins.snowpark.snowpark_entity_model import (
4
+ FunctionEntityModel,
5
+ ProcedureEntityModel,
6
+ )
7
+ from snowflake.cli.api.entities.common import EntityBase
8
+
9
+ T = TypeVar("T")
10
+
11
+
12
+ class SnowparkEntity(EntityBase[Generic[T]]):
13
+ pass
14
+
15
+
16
+ class FunctionEntity(SnowparkEntity[FunctionEntityModel]):
17
+ """
18
+ A single UDF
19
+ """
20
+
21
+ pass
22
+
23
+
24
+ class ProcedureEntity(SnowparkEntity[ProcedureEntityModel]):
25
+ """
26
+ A stored procedure
27
+ """
28
+
29
+ pass