snowflake-cli-labs 2.8.0rc1__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 +79 -26
  27. snowflake/cli/{plugins → _plugins}/git/manager.py +72 -17
  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 +10 -6
  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 +8 -6
  59. snowflake/cli/{plugins → _plugins}/notebook/manager.py +14 -14
  60. snowflake/cli/{plugins/nativeapp → _plugins/notebook}/plugin_spec.py +1 -1
  61. snowflake/cli/{plugins → _plugins}/notebook/types.py +0 -1
  62. snowflake/cli/{plugins → _plugins}/object/command_aliases.py +6 -5
  63. snowflake/cli/{plugins → _plugins}/object/commands.py +16 -10
  64. snowflake/cli/{plugins → _plugins}/object/manager.py +43 -21
  65. snowflake/cli/{plugins → _plugins}/object/plugin_spec.py +1 -1
  66. snowflake/cli/_plugins/snowpark/commands.py +450 -0
  67. snowflake/cli/_plugins/snowpark/common.py +268 -0
  68. snowflake/cli/{plugins → _plugins}/snowpark/models.py +2 -8
  69. snowflake/cli/{plugins → _plugins}/snowpark/package/anaconda_packages.py +2 -36
  70. snowflake/cli/{plugins → _plugins}/snowpark/package/commands.py +13 -74
  71. snowflake/cli/{plugins → _plugins}/snowpark/package/manager.py +4 -3
  72. snowflake/cli/{plugins → _plugins}/snowpark/package_utils.py +5 -5
  73. snowflake/cli/_plugins/snowpark/plugin_spec.py +30 -0
  74. snowflake/cli/_plugins/snowpark/snowpark_entity.py +29 -0
  75. snowflake/cli/_plugins/snowpark/snowpark_entity_model.py +173 -0
  76. snowflake/cli/_plugins/snowpark/snowpark_project_paths.py +109 -0
  77. snowflake/cli/{plugins → _plugins}/snowpark/snowpark_shared.py +0 -36
  78. snowflake/cli/{plugins → _plugins}/snowpark/zipper.py +16 -8
  79. snowflake/cli/{plugins → _plugins}/spcs/__init__.py +5 -7
  80. snowflake/cli/{plugins → _plugins}/spcs/compute_pool/commands.py +29 -28
  81. snowflake/cli/{plugins → _plugins}/spcs/compute_pool/manager.py +3 -3
  82. snowflake/cli/{plugins → _plugins}/spcs/image_registry/commands.py +3 -3
  83. snowflake/cli/{plugins → _plugins}/spcs/image_repository/commands.py +25 -19
  84. snowflake/cli/{plugins → _plugins}/spcs/image_repository/manager.py +1 -1
  85. snowflake/cli/{plugins → _plugins}/spcs/plugin_spec.py +1 -1
  86. snowflake/cli/{plugins → _plugins}/spcs/services/commands.py +66 -32
  87. snowflake/cli/{plugins → _plugins}/spcs/services/manager.py +43 -5
  88. snowflake/cli/{plugins → _plugins}/sql/commands.py +20 -17
  89. snowflake/cli/{plugins → _plugins}/sql/manager.py +1 -1
  90. snowflake/cli/{plugins → _plugins}/sql/plugin_spec.py +1 -1
  91. snowflake/cli/{plugins → _plugins}/stage/commands.py +20 -17
  92. snowflake/cli/{plugins → _plugins}/stage/diff.py +1 -47
  93. snowflake/cli/{plugins → _plugins}/stage/manager.py +62 -24
  94. snowflake/cli/{plugins → _plugins}/stage/plugin_spec.py +1 -1
  95. snowflake/cli/_plugins/stage/utils.py +54 -0
  96. snowflake/cli/{plugins → _plugins}/streamlit/commands.py +71 -62
  97. snowflake/cli/{plugins → _plugins}/streamlit/manager.py +68 -70
  98. snowflake/cli/_plugins/streamlit/plugin_spec.py +30 -0
  99. snowflake/cli/_plugins/streamlit/streamlit_entity.py +12 -0
  100. snowflake/cli/_plugins/streamlit/streamlit_entity_model.py +66 -0
  101. snowflake/cli/_plugins/workspace/action_context.py +18 -0
  102. snowflake/cli/_plugins/workspace/commands.py +306 -0
  103. snowflake/cli/_plugins/workspace/manager.py +74 -0
  104. snowflake/cli/_plugins/workspace/plugin_spec.py +30 -0
  105. snowflake/cli/api/cli_global_context.py +152 -295
  106. snowflake/cli/api/commands/common.py +25 -0
  107. snowflake/cli/api/commands/decorators.py +19 -4
  108. snowflake/cli/api/commands/experimental_behaviour.py +2 -3
  109. snowflake/cli/api/commands/flags.py +143 -222
  110. snowflake/cli/api/commands/overrideable_parameter.py +143 -0
  111. snowflake/cli/api/commands/snow_typer.py +21 -11
  112. snowflake/cli/api/commands/utils.py +18 -0
  113. snowflake/cli/api/config.py +44 -12
  114. snowflake/cli/api/connections.py +216 -0
  115. snowflake/cli/api/console/abc.py +8 -3
  116. snowflake/cli/api/constants.py +11 -0
  117. snowflake/cli/api/entities/common.py +56 -0
  118. snowflake/cli/api/entities/utils.py +370 -0
  119. snowflake/cli/api/errno.py +1 -0
  120. snowflake/cli/api/exceptions.py +31 -5
  121. snowflake/cli/api/feature_flags.py +0 -1
  122. snowflake/cli/api/identifiers.py +45 -9
  123. snowflake/cli/api/metrics.py +92 -0
  124. snowflake/cli/api/project/definition.py +48 -6
  125. snowflake/cli/api/project/definition_conversion.py +400 -0
  126. snowflake/cli/api/project/definition_manager.py +16 -5
  127. snowflake/cli/api/project/project_verification.py +3 -3
  128. snowflake/cli/api/project/schemas/entities/common.py +91 -16
  129. snowflake/cli/api/project/schemas/entities/entities.py +37 -6
  130. snowflake/cli/api/project/schemas/project_definition.py +180 -49
  131. snowflake/cli/api/project/schemas/updatable_model.py +11 -3
  132. snowflake/cli/api/project/schemas/v1/__init__.py +0 -0
  133. snowflake/cli/api/project/schemas/{identifier_model.py → v1/identifier_model.py} +3 -1
  134. snowflake/cli/api/project/schemas/v1/native_app/__init__.py +0 -0
  135. snowflake/cli/api/project/schemas/{native_app → v1/native_app}/application.py +8 -9
  136. snowflake/cli/api/project/schemas/{native_app → v1/native_app}/native_app.py +4 -4
  137. snowflake/cli/api/project/schemas/{native_app → v1/native_app}/package.py +7 -1
  138. snowflake/cli/api/project/schemas/v1/snowpark/__init__.py +0 -0
  139. snowflake/cli/api/project/schemas/{snowpark → v1/snowpark}/callable.py +2 -2
  140. snowflake/cli/api/project/schemas/{snowpark → v1/snowpark}/snowpark.py +2 -2
  141. snowflake/cli/api/project/schemas/v1/streamlit/__init__.py +0 -0
  142. snowflake/cli/api/project/schemas/{streamlit → v1/streamlit}/streamlit.py +2 -1
  143. snowflake/cli/api/project/util.py +23 -6
  144. snowflake/cli/api/rendering/jinja.py +14 -8
  145. snowflake/cli/api/rendering/project_definition_templates.py +5 -1
  146. snowflake/cli/api/rendering/sql_templates.py +56 -11
  147. snowflake/cli/api/rest_api.py +11 -5
  148. snowflake/cli/api/secure_path.py +16 -18
  149. snowflake/cli/api/secure_utils.py +90 -1
  150. snowflake/cli/api/sql_execution.py +47 -27
  151. snowflake/cli/api/utils/definition_rendering.py +45 -13
  152. {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-3.0.0.dist-info}/METADATA +20 -18
  153. snowflake_cli_labs-3.0.0.dist-info/RECORD +242 -0
  154. snowflake_cli_labs-3.0.0.dist-info/entry_points.txt +2 -0
  155. snowflake/cli/api/commands/project_initialisation.py +0 -65
  156. snowflake/cli/api/commands/typer_pre_execute.py +0 -26
  157. snowflake/cli/api/project/schemas/entities/application_entity.py +0 -44
  158. snowflake/cli/api/project/schemas/entities/application_package_entity.py +0 -66
  159. snowflake/cli/app/build_and_push.sh +0 -8
  160. snowflake/cli/plugins/nativeapp/codegen/setup/native_app_setup_processor.py +0 -172
  161. snowflake/cli/plugins/nativeapp/init.py +0 -345
  162. snowflake/cli/plugins/nativeapp/manager.py +0 -823
  163. snowflake/cli/plugins/nativeapp/run_processor.py +0 -389
  164. snowflake/cli/plugins/nativeapp/teardown_processor.py +0 -301
  165. snowflake/cli/plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +0 -135
  166. snowflake/cli/plugins/nativeapp/version/version_processor.py +0 -362
  167. snowflake/cli/plugins/object_stage_deprecated/__init__.py +0 -15
  168. snowflake/cli/plugins/object_stage_deprecated/commands.py +0 -122
  169. snowflake/cli/plugins/object_stage_deprecated/plugin_spec.py +0 -32
  170. snowflake/cli/plugins/snowpark/commands.py +0 -548
  171. snowflake/cli/plugins/snowpark/common.py +0 -307
  172. snowflake/cli/plugins/snowpark/manager.py +0 -109
  173. snowflake/cli/plugins/snowpark/plugin_spec.py +0 -30
  174. snowflake/cli/plugins/snowpark/snowpark_package_paths.py +0 -65
  175. snowflake/cli/plugins/spcs/jobs/commands.py +0 -78
  176. snowflake/cli/plugins/spcs/jobs/manager.py +0 -53
  177. snowflake/cli/plugins/streamlit/__init__.py +0 -13
  178. snowflake/cli/plugins/streamlit/plugin_spec.py +0 -30
  179. snowflake/cli/plugins/workspace/__init__.py +0 -13
  180. snowflake/cli/plugins/workspace/commands.py +0 -35
  181. snowflake/cli/plugins/workspace/plugin_spec.py +0 -30
  182. snowflake/cli/templates/default_snowpark/.gitignore +0 -4
  183. snowflake/cli/templates/default_snowpark/app/common.py +0 -2
  184. snowflake/cli/templates/default_snowpark/app/functions.py +0 -15
  185. snowflake/cli/templates/default_snowpark/app/procedures.py +0 -22
  186. snowflake/cli/templates/default_snowpark/requirements.txt +0 -1
  187. snowflake/cli/templates/default_snowpark/snowflake.yml +0 -23
  188. snowflake/cli/templates/default_streamlit/.gitignore +0 -4
  189. snowflake/cli/templates/default_streamlit/common/hello.py +0 -2
  190. snowflake/cli/templates/default_streamlit/environment.yml +0 -6
  191. snowflake/cli/templates/default_streamlit/pages/my_page.py +0 -3
  192. snowflake/cli/templates/default_streamlit/snowflake.yml +0 -10
  193. snowflake/cli/templates/default_streamlit/streamlit_app.py +0 -4
  194. snowflake_cli_labs-2.8.0rc1.dist-info/RECORD +0 -240
  195. snowflake_cli_labs-2.8.0rc1.dist-info/entry_points.txt +0 -2
  196. /snowflake/cli/{app → _app}/__init__.py +0 -0
  197. /snowflake/cli/{api/project/schemas/native_app → _app/api_impl}/__init__.py +0 -0
  198. /snowflake/cli/{api/project/schemas/snowpark → _app/api_impl/plugin}/__init__.py +0 -0
  199. /snowflake/cli/{app → _app}/api_impl/plugin/plugin_config_provider_impl.py +0 -0
  200. /snowflake/cli/{app → _app}/commands_registration/__init__.py +0 -0
  201. /snowflake/cli/{app → _app}/commands_registration/threadsafe.py +0 -0
  202. /snowflake/cli/{app → _app}/constants.py +0 -0
  203. /snowflake/cli/{api/project/schemas/streamlit → _app/dev}/__init__.py +0 -0
  204. /snowflake/cli/{app → _app}/dev/commands_structure.py +0 -0
  205. /snowflake/cli/{app/api_impl → _app/dev/docs}/__init__.py +0 -0
  206. /snowflake/cli/{app → _app}/dev/docs/project_definition_generate_json_schema.py +0 -0
  207. /snowflake/cli/{app → _app}/dev/docs/template_utils.py +0 -0
  208. /snowflake/cli/{app → _app}/dev/docs/templates/definition_description.rst.jinja2 +0 -0
  209. /snowflake/cli/{app → _app}/dev/docs/templates/overview.rst.jinja2 +0 -0
  210. /snowflake/cli/{app → _app}/dev/pycharm_remote_debug.py +0 -0
  211. /snowflake/cli/{app → _app}/loggers.py +0 -0
  212. /snowflake/cli/{app/api_impl/plugin → _plugins}/__init__.py +0 -0
  213. /snowflake/cli/{app/dev → _plugins/connection}/__init__.py +0 -0
  214. /snowflake/cli/{app/dev/docs → _plugins/cortex}/__init__.py +0 -0
  215. /snowflake/cli/{plugins → _plugins}/cortex/types.py +0 -0
  216. /snowflake/cli/{plugins → _plugins/git}/__init__.py +0 -0
  217. /snowflake/cli/{plugins/connection → _plugins/helpers}/__init__.py +0 -0
  218. /snowflake/cli/{plugins/cortex → _plugins/init}/__init__.py +0 -0
  219. /snowflake/cli/{plugins/git → _plugins/nativeapp}/__init__.py +0 -0
  220. /snowflake/cli/{plugins/init → _plugins/nativeapp/codegen}/__init__.py +0 -0
  221. /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/sandbox.py +0 -0
  222. /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/callback_source.py.jinja +0 -0
  223. /snowflake/cli/{plugins → _plugins}/nativeapp/constants.py +0 -0
  224. /snowflake/cli/{templates/default_snowpark/app → _plugins/nativeapp/entities}/__init__.py +0 -0
  225. /snowflake/cli/{plugins → _plugins}/nativeapp/feature_flags.py +0 -0
  226. /snowflake/cli/{plugins → _plugins}/nativeapp/utils.py +0 -0
  227. /snowflake/cli/{plugins/nativeapp → _plugins/nativeapp/version}/__init__.py +0 -0
  228. /snowflake/cli/{plugins/nativeapp/codegen → _plugins/notebook}/__init__.py +0 -0
  229. /snowflake/cli/{plugins → _plugins}/notebook/exceptions.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.0rc1.dist-info → snowflake_cli_labs-3.0.0.dist-info}/WHEEL +0 -0
  251. {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-3.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -19,11 +19,10 @@ from dataclasses import dataclass, field
19
19
  from pathlib import Path, PurePosixPath
20
20
  from typing import Collection, Dict, List, Optional, Tuple
21
21
 
22
- from snowflake.cli.api.console import cli_console as cc
22
+ from snowflake.cli._plugins.nativeapp.artifacts import BundleMap
23
23
  from snowflake.cli.api.exceptions import (
24
24
  SnowflakeSQLExecutionError,
25
25
  )
26
- from snowflake.cli.plugins.nativeapp.artifacts import BundleMap
27
26
  from snowflake.connector.cursor import DictCursor
28
27
 
29
28
  from .manager import StageManager
@@ -279,48 +278,3 @@ def _to_diff_line(status: str, src: Optional[str], dest: str) -> str:
279
278
  status_prefix = f"[red]{status}[/red]: {padding}"
280
279
 
281
280
  return f"{status_prefix}{src_prefix}{dest}"
282
-
283
-
284
- def print_diff_to_console(
285
- diff: DiffResult,
286
- bundle_map: Optional[BundleMap] = None,
287
- ):
288
- if not diff.has_changes():
289
- cc.message("Your stage is up-to-date with your local deploy root.")
290
- return
291
-
292
- blank_line_needed = False
293
- if diff.only_local or diff.different:
294
- cc.message("Local changes to be deployed:")
295
- messages_to_output = []
296
- for p in diff.different:
297
- src_dest_pair = _to_src_dest_pair(p, bundle_map)
298
- messages_to_output.append(
299
- (
300
- src_dest_pair,
301
- _to_diff_line("modified", src_dest_pair[0], src_dest_pair[1]),
302
- )
303
- )
304
- for p in diff.only_local:
305
- src_dest_pair = _to_src_dest_pair(p, bundle_map)
306
- messages_to_output.append(
307
- (
308
- src_dest_pair,
309
- _to_diff_line("added", src_dest_pair[0], src_dest_pair[1]),
310
- )
311
- )
312
-
313
- with cc.indented():
314
- for key, message in sorted(messages_to_output, key=lambda pair: pair[0]):
315
- cc.message(message)
316
-
317
- blank_line_needed = True
318
-
319
- if diff.only_on_stage:
320
- if blank_line_needed:
321
- cc.message("")
322
- cc.message(f"Deleted paths to be removed from your stage:")
323
- with cc.indented():
324
- for p in sorted(diff.only_on_stage):
325
- diff_line = _to_diff_line("deleted", src=None, dest=str(p))
326
- cc.message(diff_line)
@@ -27,11 +27,12 @@ from textwrap import dedent
27
27
  from typing import Dict, List, Optional, Union
28
28
 
29
29
  from click import ClickException
30
- from snowflake.cli.api.commands.flags import (
30
+ from snowflake.cli._plugins.snowpark.package_utils import parse_requirements
31
+ from snowflake.cli.api.commands.common import (
31
32
  OnErrorType,
32
33
  Variable,
33
- parse_key_value_variables,
34
34
  )
35
+ from snowflake.cli.api.commands.utils import parse_key_value_variables
35
36
  from snowflake.cli.api.console import cli_console
36
37
  from snowflake.cli.api.constants import PYTHON_3_12
37
38
  from snowflake.cli.api.identifiers import FQN
@@ -39,7 +40,6 @@ from snowflake.cli.api.project.util import to_string_literal
39
40
  from snowflake.cli.api.secure_path import SecurePath
40
41
  from snowflake.cli.api.sql_execution import SqlExecutionMixin
41
42
  from snowflake.cli.api.utils.path_utils import path_resolver
42
- from snowflake.cli.plugins.snowpark.package_utils import parse_requirements
43
43
  from snowflake.connector import DictCursor, ProgrammingError
44
44
  from snowflake.connector.cursor import SnowflakeCursor
45
45
 
@@ -57,6 +57,9 @@ EXECUTE_SUPPORTED_FILES_FORMATS = (
57
57
  ".py",
58
58
  ) # tuple to preserve order but it's a set
59
59
 
60
+ # Replace magic numbers with constants
61
+ OMIT_FIRST = slice(1, None)
62
+
60
63
 
61
64
  @dataclass
62
65
  class StagePathParts:
@@ -65,14 +68,21 @@ class StagePathParts:
65
68
  stage_name: str
66
69
  is_directory: bool
67
70
 
68
- @staticmethod
69
- def get_directory(stage_path: str) -> str:
70
- return "/".join(Path(stage_path).parts[1:])
71
+ @classmethod
72
+ def get_directory(cls, stage_path: str) -> str:
73
+ return "/".join(Path(stage_path).parts[OMIT_FIRST])
71
74
 
72
75
  @property
73
76
  def path(self) -> str:
74
77
  raise NotImplementedError
75
78
 
79
+ @property
80
+ def full_path(self) -> str:
81
+ raise NotImplementedError
82
+
83
+ def replace_stage_prefix(self, file_path: str) -> str:
84
+ raise NotImplementedError
85
+
76
86
  def add_stage_prefix(self, file_path: str) -> str:
77
87
  raise NotImplementedError
78
88
 
@@ -112,24 +122,29 @@ class DefaultStagePathParts(StagePathParts):
112
122
  self.directory = self.get_directory(stage_path)
113
123
  self.stage = StageManager.get_stage_from_path(stage_path)
114
124
  stage_name = self.stage.split(".")[-1]
115
- if stage_name.startswith("@"):
116
- stage_name = stage_name[1:]
125
+ stage_name = (
126
+ stage_name[OMIT_FIRST] if stage_name.startswith("@") else stage_name
127
+ )
117
128
  self.stage_name = stage_name
118
129
  self.is_directory = True if stage_path.endswith("/") else False
119
130
 
120
131
  @property
121
132
  def path(self) -> str:
122
- return (
123
- f"{self.stage_name}{self.directory}"
124
- if self.stage_name.endswith("/")
125
- else f"{self.stage_name}/{self.directory}"
126
- )
133
+ return f"{self.stage_name.rstrip('/')}/{self.directory}"
127
134
 
128
- def add_stage_prefix(self, file_path: str) -> str:
135
+ @property
136
+ def full_path(self) -> str:
137
+ return f"{self.stage.rstrip('/')}/{self.directory}"
138
+
139
+ def replace_stage_prefix(self, file_path: str) -> str:
129
140
  stage = Path(self.stage).parts[0]
130
- file_path_without_prefix = Path(file_path).parts[1:]
141
+ file_path_without_prefix = Path(file_path).parts[OMIT_FIRST]
131
142
  return f"{stage}/{'/'.join(file_path_without_prefix)}"
132
143
 
144
+ def add_stage_prefix(self, file_path: str) -> str:
145
+ stage = self.stage.rstrip("/")
146
+ return f"{stage}/{file_path.lstrip('/')}"
147
+
133
148
  def get_directory_from_file_path(self, file_path: str) -> List[str]:
134
149
  stage_path_length = len(Path(self.directory).parts)
135
150
  return list(Path(file_path).parts[1 + stage_path_length : -1])
@@ -146,14 +161,29 @@ class UserStagePathParts(StagePathParts):
146
161
 
147
162
  def __init__(self, stage_path: str):
148
163
  self.directory = self.get_directory(stage_path)
149
- self.stage = "@~"
150
- self.stage_name = "@~"
164
+ self.stage = USER_STAGE_PREFIX
165
+ self.stage_name = USER_STAGE_PREFIX
151
166
  self.is_directory = True if stage_path.endswith("/") else False
152
167
 
168
+ @classmethod
169
+ def get_directory(cls, stage_path: str) -> str:
170
+ if Path(stage_path).parts[0] == USER_STAGE_PREFIX:
171
+ return super().get_directory(stage_path)
172
+ return stage_path
173
+
153
174
  @property
154
175
  def path(self) -> str:
155
176
  return f"{self.directory}"
156
177
 
178
+ @property
179
+ def full_path(self) -> str:
180
+ return f"{self.stage}/{self.directory}"
181
+
182
+ def replace_stage_prefix(self, file_path: str) -> str:
183
+ if Path(file_path).parts[0] == self.stage_name:
184
+ return file_path
185
+ return f"{self.stage}/{file_path}"
186
+
157
187
  def add_stage_prefix(self, file_path: str) -> str:
158
188
  return f"{self.stage}/{file_path}"
159
189
 
@@ -168,7 +198,9 @@ class StageManager(SqlExecutionMixin):
168
198
  self._python_exe_procedure = None
169
199
 
170
200
  @staticmethod
171
- def get_standard_stage_prefix(name: str) -> str:
201
+ def get_standard_stage_prefix(name: str | FQN) -> str:
202
+ if isinstance(name, FQN):
203
+ name = name.identifier
172
204
  # Handle embedded stages
173
205
  if name.startswith("snow://") or name.startswith("@"):
174
206
  return name
@@ -239,7 +271,7 @@ class StageManager(SqlExecutionMixin):
239
271
  self._assure_is_existing_directory(dest_directory)
240
272
 
241
273
  result = self._execute_query(
242
- f"get {self.quote_stage_name(stage_path_parts.add_stage_prefix(file_path))} {self._to_uri(f'{dest_directory}/')} parallel={parallel}"
274
+ f"get {self.quote_stage_name(stage_path_parts.replace_stage_prefix(file_path))} {self._to_uri(f'{dest_directory}/')} parallel={parallel}"
243
275
  )
244
276
  results.append(result)
245
277
 
@@ -300,8 +332,8 @@ class StageManager(SqlExecutionMixin):
300
332
  quoted_stage_name = self.quote_stage_name(f"{stage_name}{path}")
301
333
  return self._execute_query(f"remove {quoted_stage_name}")
302
334
 
303
- def create(self, stage_name: str, comment: Optional[str] = None) -> SnowflakeCursor:
304
- query = f"create stage if not exists {stage_name}"
335
+ def create(self, fqn: FQN, comment: Optional[str] = None) -> SnowflakeCursor:
336
+ query = f"create stage if not exists {fqn.sql_identifier}"
305
337
  if comment:
306
338
  query += f" comment='{comment}'"
307
339
  return self._execute_query(query)
@@ -319,8 +351,14 @@ class StageManager(SqlExecutionMixin):
319
351
  stage_path_parts = self._stage_path_part_factory(stage_path)
320
352
  all_files_list = self._get_files_list_from_stage(stage_path_parts)
321
353
 
354
+ all_files_with_stage_name_prefix = [
355
+ stage_path_parts.get_directory(file) for file in all_files_list
356
+ ]
357
+
322
358
  # filter files from stage if match stage_path pattern
323
- filtered_file_list = self._filter_files_list(stage_path_parts, all_files_list)
359
+ filtered_file_list = self._filter_files_list(
360
+ stage_path_parts, all_files_with_stage_name_prefix
361
+ )
324
362
 
325
363
  if not filtered_file_list:
326
364
  raise ClickException(f"No files matched pattern '{stage_path}'")
@@ -376,7 +414,7 @@ class StageManager(SqlExecutionMixin):
376
414
  if not stage_path_parts.directory:
377
415
  return self._filter_supported_files(files_on_stage)
378
416
 
379
- stage_path = stage_path_parts.path.lower()
417
+ stage_path = stage_path_parts.directory
380
418
 
381
419
  # Exact file path was provided if stage_path in file list
382
420
  if stage_path in files_on_stage:
@@ -428,7 +466,7 @@ class StageManager(SqlExecutionMixin):
428
466
  on_error: OnErrorType,
429
467
  ) -> Dict:
430
468
  try:
431
- query = f"execute immediate from {file_stage_path}"
469
+ query = f"execute immediate from {self.quote_stage_name(file_stage_path)}"
432
470
  if variables:
433
471
  query += variables
434
472
  self._execute_query(query)
@@ -12,13 +12,13 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
+ from snowflake.cli._plugins.stage import commands
15
16
  from snowflake.cli.api.plugins.command import (
16
17
  SNOWCLI_ROOT_COMMAND_PATH,
17
18
  CommandSpec,
18
19
  CommandType,
19
20
  plugin_hook_impl,
20
21
  )
21
- from snowflake.cli.plugins.stage import commands
22
22
 
23
23
 
24
24
  @plugin_hook_impl
@@ -0,0 +1,54 @@
1
+ from typing import Optional
2
+
3
+ from snowflake.cli._plugins.nativeapp.artifacts import BundleMap
4
+ from snowflake.cli._plugins.stage.diff import (
5
+ DiffResult,
6
+ _to_diff_line,
7
+ _to_src_dest_pair,
8
+ )
9
+ from snowflake.cli.api.console import cli_console as cc
10
+
11
+
12
+ def print_diff_to_console(
13
+ diff: DiffResult,
14
+ bundle_map: Optional[BundleMap] = None,
15
+ ):
16
+ if not diff.has_changes():
17
+ cc.message("Your stage is up-to-date with your local deploy root.")
18
+ return
19
+
20
+ blank_line_needed = False
21
+ if diff.only_local or diff.different:
22
+ cc.message("Local changes to be deployed:")
23
+ messages_to_output = []
24
+ for p in diff.different:
25
+ src_dest_pair = _to_src_dest_pair(p, bundle_map)
26
+ messages_to_output.append(
27
+ (
28
+ src_dest_pair,
29
+ _to_diff_line("modified", src_dest_pair[0], src_dest_pair[1]),
30
+ )
31
+ )
32
+ for p in diff.only_local:
33
+ src_dest_pair = _to_src_dest_pair(p, bundle_map)
34
+ messages_to_output.append(
35
+ (
36
+ src_dest_pair,
37
+ _to_diff_line("added", src_dest_pair[0], src_dest_pair[1]),
38
+ )
39
+ )
40
+
41
+ with cc.indented():
42
+ for key, message in sorted(messages_to_output, key=lambda pair: pair[0]):
43
+ cc.message(message)
44
+
45
+ blank_line_needed = True
46
+
47
+ if diff.only_on_stage:
48
+ if blank_line_needed:
49
+ cc.message("")
50
+ cc.message(f"Deleted paths to be removed from your stage:")
51
+ with cc.indented():
52
+ for p in sorted(diff.only_on_stage):
53
+ diff_line = _to_diff_line("deleted", src=None, dest=str(p))
54
+ cc.message(diff_line)
@@ -16,32 +16,42 @@ from __future__ import annotations
16
16
 
17
17
  import logging
18
18
  from pathlib import Path
19
+ from typing import Dict
19
20
 
20
21
  import click
21
22
  import typer
22
- from click import ClickException
23
- from snowflake.cli.api.cli_global_context import cli_context
23
+ from click import ClickException, UsageError
24
+ from snowflake.cli._plugins.object.command_aliases import (
25
+ add_object_command_aliases,
26
+ scope_option,
27
+ )
28
+ from snowflake.cli._plugins.streamlit.manager import StreamlitManager
29
+ from snowflake.cli._plugins.streamlit.streamlit_entity_model import (
30
+ StreamlitEntityModel,
31
+ )
32
+ from snowflake.cli.api.cli_global_context import get_cli_context
24
33
  from snowflake.cli.api.commands.decorators import (
25
34
  with_experimental_behaviour,
26
35
  with_project_definition,
27
36
  )
28
- from snowflake.cli.api.commands.flags import ReplaceOption, like_option
29
- from snowflake.cli.api.commands.project_initialisation import add_init_command
37
+ from snowflake.cli.api.commands.flags import (
38
+ ReplaceOption,
39
+ entity_argument,
40
+ identifier_argument,
41
+ like_option,
42
+ )
30
43
  from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
31
44
  from snowflake.cli.api.constants import ObjectType
45
+ from snowflake.cli.api.exceptions import NoProjectDefinitionError
32
46
  from snowflake.cli.api.identifiers import FQN
33
47
  from snowflake.cli.api.output.types import (
34
48
  CommandResult,
35
49
  MessageResult,
36
50
  SingleQueryResult,
37
51
  )
38
- from snowflake.cli.api.project.project_verification import assert_project_type
39
- from snowflake.cli.api.project.schemas.streamlit.streamlit import Streamlit
40
- from snowflake.cli.plugins.object.command_aliases import (
41
- add_object_command_aliases,
42
- scope_option,
52
+ from snowflake.cli.api.project.definition_conversion import (
53
+ convert_project_definition_to_v2,
43
54
  )
44
- from snowflake.cli.plugins.streamlit.manager import StreamlitManager
45
55
 
46
56
  app = SnowTyperFactory(
47
57
  name="streamlit",
@@ -49,19 +59,8 @@ app = SnowTyperFactory(
49
59
  )
50
60
  log = logging.getLogger(__name__)
51
61
 
52
-
53
- class IdentifierType(click.ParamType):
54
- name = "TEXT"
55
-
56
- def convert(self, value, param, ctx):
57
- return FQN.from_string(value)
58
-
59
-
60
- StreamlitNameArgument = typer.Argument(
61
- ...,
62
- help="Name of the Streamlit app.",
63
- show_default=False,
64
- click_type=IdentifierType(),
62
+ StreamlitNameArgument = identifier_argument(
63
+ sf_object="Streamlit app", example="my_streamlit"
65
64
  )
66
65
  OpenOption = typer.Option(
67
66
  False,
@@ -70,12 +69,6 @@ OpenOption = typer.Option(
70
69
  is_flag=True,
71
70
  )
72
71
 
73
- add_init_command(
74
- app,
75
- project_type="Streamlit",
76
- template="default_streamlit",
77
- help_message="Name of the Streamlit app project directory you want to create. Defaults to `example_streamlit`.",
78
- )
79
72
 
80
73
  add_object_command_aliases(
81
74
  app=app,
@@ -88,11 +81,25 @@ add_object_command_aliases(
88
81
  )
89
82
 
90
83
 
84
+ @app.command(requires_connection=True)
85
+ def execute(
86
+ name: FQN = StreamlitNameArgument,
87
+ **options,
88
+ ):
89
+ """
90
+ Executes a streamlit in a headless mode.
91
+ """
92
+ _ = StreamlitManager().execute(app_name=name)
93
+ return MessageResult(f"Streamlit {name} executed.")
94
+
95
+
91
96
  @app.command("share", requires_connection=True)
92
97
  def streamlit_share(
93
98
  name: FQN = StreamlitNameArgument,
94
99
  to_role: str = typer.Argument(
95
- ..., help="Role with which to share the Streamlit app."
100
+ ...,
101
+ help="Role with which to share the Streamlit app.",
102
+ show_default=False,
96
103
  ),
97
104
  **options,
98
105
  ) -> CommandResult:
@@ -125,48 +132,50 @@ def streamlit_deploy(
125
132
  replace: bool = ReplaceOption(
126
133
  help="Replace the Streamlit app if it already exists."
127
134
  ),
135
+ entity_id: str = entity_argument("streamlit"),
128
136
  open_: bool = OpenOption,
129
137
  **options,
130
138
  ) -> CommandResult:
131
139
  """
132
140
  Deploys a Streamlit app defined in the project definition file (snowflake.yml). By default, the command uploads
133
141
  environment.yml and any other pages or folders, if present. If you don’t specify a stage name, the `streamlit`
134
- stage is used. If the specified stage does not exist, the command creates it.
142
+ stage is used. If the specified stage does not exist, the command creates it. If multiple Streamlits are defined
143
+ in snowflake.yml and no entity_id is provided then command will raise an error.
135
144
  """
136
145
 
137
- assert_project_type("streamlit")
138
-
139
- streamlit: Streamlit = cli_context.project_definition.streamlit
140
- if not streamlit:
141
- return MessageResult("No streamlit were specified in project definition.")
142
-
143
- environment_file = streamlit.env_file
144
- if environment_file and not Path(environment_file).exists():
145
- raise ClickException(f"Provided file {environment_file} does not exist")
146
- elif environment_file is None:
147
- environment_file = "environment.yml"
148
-
149
- pages_dir = streamlit.pages_dir
150
- if pages_dir and not Path(pages_dir).exists():
151
- raise ClickException(f"Provided file {pages_dir} does not exist")
152
- elif pages_dir is None:
153
- pages_dir = "pages"
154
-
155
- streamlit_id = FQN.from_identifier_model(streamlit).using_context()
156
-
157
- url = StreamlitManager().deploy(
158
- streamlit_id=streamlit_id,
159
- environment_file=Path(environment_file),
160
- pages_dir=Path(pages_dir),
161
- stage_name=streamlit.stage,
162
- main_file=Path(streamlit.main_file),
163
- replace=replace,
164
- query_warehouse=streamlit.query_warehouse,
165
- additional_source_files=streamlit.additional_source_files,
166
- title=streamlit.title,
167
- **options,
146
+ cli_context = get_cli_context()
147
+ pd = cli_context.project_definition
148
+ if not pd.meets_version_requirement("2"):
149
+ if not pd.streamlit:
150
+ raise NoProjectDefinitionError(
151
+ project_type="streamlit", project_root=cli_context.project_root
152
+ )
153
+ pd = convert_project_definition_to_v2(cli_context.project_root, pd)
154
+
155
+ streamlits: Dict[str, StreamlitEntityModel] = pd.get_entities_by_type(
156
+ entity_type="streamlit"
168
157
  )
169
158
 
159
+ if not streamlits:
160
+ raise NoProjectDefinitionError(
161
+ project_type="streamlit", project_root=cli_context.project_root
162
+ )
163
+
164
+ if entity_id and entity_id not in streamlits:
165
+ raise UsageError(f"No '{entity_id}' entity in project definition file.")
166
+
167
+ if len(streamlits.keys()) == 1:
168
+ entity_id = list(streamlits.keys())[0]
169
+
170
+ if entity_id is None:
171
+ raise UsageError(
172
+ "Multiple Streamlit apps found. Please provide entity id for the operation."
173
+ )
174
+
175
+ # Get first streamlit
176
+ streamlit: StreamlitEntityModel = streamlits[entity_id]
177
+ url = StreamlitManager().deploy(streamlit=streamlit, replace=replace)
178
+
170
179
  if open_:
171
180
  typer.launch(url)
172
181