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
@@ -15,22 +15,27 @@
15
15
  from __future__ import annotations
16
16
 
17
17
  import logging
18
- import os
19
18
  from pathlib import Path
20
19
  from typing import List, Optional
21
20
 
21
+ from click import ClickException
22
+ from snowflake.cli._plugins.connection.util import (
23
+ MissingConnectionAccountError,
24
+ MissingConnectionRegionError,
25
+ make_snowsight_url,
26
+ )
27
+ from snowflake.cli._plugins.object.manager import ObjectManager
28
+ from snowflake.cli._plugins.stage.manager import StageManager
29
+ from snowflake.cli._plugins.streamlit.streamlit_entity_model import (
30
+ StreamlitEntityModel,
31
+ )
22
32
  from snowflake.cli.api.commands.experimental_behaviour import (
23
33
  experimental_behaviour_enabled,
24
34
  )
35
+ from snowflake.cli.api.console import cli_console
25
36
  from snowflake.cli.api.feature_flags import FeatureFlag
26
37
  from snowflake.cli.api.identifiers import FQN
27
38
  from snowflake.cli.api.sql_execution import SqlExecutionMixin
28
- from snowflake.cli.plugins.connection.util import (
29
- MissingConnectionAccountError,
30
- MissingConnectionRegionError,
31
- make_snowsight_url,
32
- )
33
- from snowflake.cli.plugins.stage.manager import StageManager
34
39
  from snowflake.connector.cursor import SnowflakeCursor
35
40
  from snowflake.connector.errors import ProgrammingError
36
41
 
@@ -38,6 +43,10 @@ log = logging.getLogger(__name__)
38
43
 
39
44
 
40
45
  class StreamlitManager(SqlExecutionMixin):
46
+ def execute(self, app_name: FQN):
47
+ query = f"EXECUTE STREAMLIT {app_name.sql_identifier}()"
48
+ return self._execute_query(query=query)
49
+
41
50
  def share(self, streamlit_name: FQN, to_role: str) -> SnowflakeCursor:
42
51
  return self._execute_query(
43
52
  f"grant usage on streamlit {streamlit_name.sql_identifier} to role {to_role}"
@@ -46,39 +55,35 @@ class StreamlitManager(SqlExecutionMixin):
46
55
  def _put_streamlit_files(
47
56
  self,
48
57
  root_location: str,
49
- main_file: Path,
50
- environment_file: Optional[Path],
51
- pages_dir: Optional[Path],
52
- additional_source_files: Optional[List[Path]],
58
+ artifacts: Optional[List[Path]] = None,
53
59
  ):
60
+ cli_console.step(f"Deploying files to {root_location}")
61
+ if not artifacts:
62
+ return
54
63
  stage_manager = StageManager()
55
-
56
- stage_manager.put(main_file, root_location, 4, True)
57
-
58
- if environment_file and environment_file.exists():
59
- stage_manager.put(environment_file, root_location, 4, True)
60
-
61
- if pages_dir and pages_dir.exists():
62
- stage_manager.put(pages_dir / "*.py", f"{root_location}/pages", 4, True)
63
-
64
- if additional_source_files:
65
- for file in additional_source_files:
66
- if os.sep in str(file):
67
- destination = f"{root_location}/{str(file.parent)}"
68
- else:
69
- destination = root_location
70
- stage_manager.put(file, destination, 4, True)
64
+ for file in artifacts:
65
+ if file.is_dir():
66
+ if not any(file.iterdir()):
67
+ cli_console.warning(f"Skipping empty directory: {file}")
68
+ continue
69
+
70
+ stage_manager.put(
71
+ f"{file.joinpath('*')}", f"{root_location}/{file}", 4, True
72
+ )
73
+ elif len(file.parts) > 1:
74
+ stage_manager.put(file, f"{root_location}/{file.parent}", 4, True)
75
+ else:
76
+ stage_manager.put(file, root_location, 4, True)
71
77
 
72
78
  def _create_streamlit(
73
79
  self,
74
- streamlit_id: FQN,
75
- main_file: Path,
80
+ streamlit: StreamlitEntityModel,
76
81
  replace: Optional[bool] = None,
77
82
  experimental: Optional[bool] = None,
78
- query_warehouse: Optional[str] = None,
79
83
  from_stage_name: Optional[str] = None,
80
- title: Optional[str] = None,
81
84
  ):
85
+ streamlit_id = streamlit.fqn.using_connection(self._conn)
86
+ cli_console.step(f"Creating {streamlit_id} Streamlit")
82
87
  query = []
83
88
  if replace:
84
89
  query.append(f"CREATE OR REPLACE STREAMLIT {streamlit_id.sql_identifier}")
@@ -96,28 +101,35 @@ class StreamlitManager(SqlExecutionMixin):
96
101
  if from_stage_name:
97
102
  query.append(f"ROOT_LOCATION = '{from_stage_name}'")
98
103
 
99
- query.append(f"MAIN_FILE = '{main_file.name}'")
104
+ query.append(f"MAIN_FILE = '{streamlit.main_file}'")
105
+ if streamlit.imports:
106
+ query.append(streamlit.get_imports_sql())
107
+ if streamlit.query_warehouse:
108
+ query.append(f"QUERY_WAREHOUSE = {streamlit.query_warehouse}")
109
+ if streamlit.title:
110
+ query.append(f"TITLE = '{streamlit.title}'")
111
+
112
+ if streamlit.comment:
113
+ query.append(f"COMMENT = '{streamlit.comment}'")
114
+
115
+ if streamlit.external_access_integrations:
116
+ query.append(streamlit.get_external_access_integrations_sql())
100
117
 
101
- if query_warehouse:
102
- query.append(f"QUERY_WAREHOUSE = {query_warehouse}")
103
- if title:
104
- query.append(f"TITLE = '{title}'")
118
+ if streamlit.secrets:
119
+ query.append(streamlit.get_secrets_sql())
105
120
 
106
121
  self._execute_query("\n".join(query))
107
122
 
108
- def deploy(
109
- self,
110
- streamlit_id: FQN,
111
- main_file: Path,
112
- environment_file: Optional[Path] = None,
113
- pages_dir: Optional[Path] = None,
114
- stage_name: Optional[str] = None,
115
- query_warehouse: Optional[str] = None,
116
- replace: Optional[bool] = False,
117
- additional_source_files: Optional[List[Path]] = None,
118
- title: Optional[str] = None,
119
- **options,
120
- ):
123
+ def deploy(self, streamlit: StreamlitEntityModel, replace: bool = False):
124
+ streamlit_id = streamlit.fqn.using_connection(self._conn)
125
+ if (
126
+ ObjectManager().object_exists(object_type="streamlit", fqn=streamlit_id)
127
+ and not replace
128
+ ):
129
+ raise ClickException(
130
+ f"Streamlit {streamlit.fqn} already exist. If you want to replace it use --replace flag."
131
+ )
132
+
121
133
  # for backwards compatibility - quoted stage path might be case-sensitive
122
134
  # https://docs.snowflake.com/en/sql-reference/identifiers-syntax#double-quoted-identifiers
123
135
  streamlit_name_for_root_location = streamlit_id.name
@@ -134,12 +146,9 @@ class StreamlitManager(SqlExecutionMixin):
134
146
  # TODO: Support from_stage
135
147
  # from_stage_stmt = f"FROM_STAGE = '{stage_name}'" if stage_name else ""
136
148
  self._create_streamlit(
137
- streamlit_id,
138
- main_file,
149
+ streamlit=streamlit,
139
150
  replace=replace,
140
- query_warehouse=query_warehouse,
141
151
  experimental=True,
142
- title=title,
143
152
  )
144
153
  try:
145
154
  if use_versioned_stage:
@@ -169,10 +178,7 @@ class StreamlitManager(SqlExecutionMixin):
169
178
 
170
179
  self._put_streamlit_files(
171
180
  root_location,
172
- main_file,
173
- environment_file,
174
- pages_dir,
175
- additional_source_files,
181
+ streamlit.artifacts,
176
182
  )
177
183
  else:
178
184
  """
@@ -182,31 +188,23 @@ class StreamlitManager(SqlExecutionMixin):
182
188
  """
183
189
  stage_manager = StageManager()
184
190
 
185
- stage_name = stage_name or "streamlit"
191
+ stage_name = streamlit.stage or "streamlit"
186
192
  stage_name = FQN.from_string(stage_name).using_connection(self._conn)
187
193
 
188
- stage_manager.create(stage_name=stage_name)
194
+ cli_console.step(f"Creating {stage_name} stage")
195
+ stage_manager.create(fqn=stage_name)
189
196
 
190
197
  root_location = stage_manager.get_standard_stage_prefix(
191
198
  f"{stage_name}/{streamlit_name_for_root_location}"
192
199
  )
193
200
 
194
- self._put_streamlit_files(
195
- root_location,
196
- main_file,
197
- environment_file,
198
- pages_dir,
199
- additional_source_files,
200
- )
201
+ self._put_streamlit_files(root_location, streamlit.artifacts)
201
202
 
202
203
  self._create_streamlit(
203
- streamlit_id,
204
- main_file,
204
+ streamlit=streamlit,
205
205
  replace=replace,
206
- query_warehouse=query_warehouse,
207
206
  from_stage_name=root_location,
208
207
  experimental=False,
209
- title=title,
210
208
  )
211
209
 
212
210
  return self.get_url(streamlit_name=streamlit_id)
@@ -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.streamlit 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,12 @@
1
+ from snowflake.cli._plugins.streamlit.streamlit_entity_model import (
2
+ StreamlitEntityModel,
3
+ )
4
+ from snowflake.cli.api.entities.common import EntityBase
5
+
6
+
7
+ class StreamlitEntity(EntityBase[StreamlitEntityModel]):
8
+ """
9
+ A Streamlit app.
10
+ """
11
+
12
+ pass
@@ -0,0 +1,66 @@
1
+ # Copyright (c) 2024 Snowflake Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ from __future__ import annotations
15
+
16
+ from pathlib import Path
17
+ from typing import List, Literal, Optional
18
+
19
+ from pydantic import Field, model_validator
20
+ from snowflake.cli.api.project.schemas.entities.common import (
21
+ EntityModelBase,
22
+ ExternalAccessBaseModel,
23
+ ImportsBaseModel,
24
+ )
25
+ from snowflake.cli.api.project.schemas.updatable_model import (
26
+ DiscriminatorField,
27
+ )
28
+
29
+
30
+ class StreamlitEntityModel(EntityModelBase, ExternalAccessBaseModel, ImportsBaseModel):
31
+ type: Literal["streamlit"] = DiscriminatorField() # noqa: A003
32
+ title: Optional[str] = Field(
33
+ title="Human-readable title for the Streamlit dashboard", default=None
34
+ )
35
+ comment: Optional[str] = Field(title="Comment for the Streamlit app", default=None)
36
+ query_warehouse: str = Field(
37
+ title="Snowflake warehouse to host the app", default=None
38
+ )
39
+ main_file: Optional[str] = Field(
40
+ title="Entrypoint file of the Streamlit app", default="streamlit_app.py"
41
+ )
42
+ pages_dir: Optional[str] = Field(title="Streamlit pages", default=None)
43
+ stage: Optional[str] = Field(
44
+ title="Stage in which the app’s artifacts will be stored", default="streamlit"
45
+ )
46
+ # Possibly can be PathMapping
47
+ artifacts: Optional[List[Path]] = Field(
48
+ title="List of files which should be deployed. Each file needs to exist locally. "
49
+ "Main file needs to be included in the artifacts.",
50
+ default=None,
51
+ )
52
+
53
+ @model_validator(mode="after")
54
+ def artifacts_must_exists(self):
55
+ if not self.artifacts:
56
+ return self
57
+
58
+ for artifact in self.artifacts:
59
+ if "*" in artifact.name:
60
+ continue
61
+ if not artifact.exists():
62
+ raise ValueError(
63
+ f"Specified artifact {artifact} does not exist locally."
64
+ )
65
+
66
+ return self
@@ -0,0 +1,18 @@
1
+ from dataclasses import dataclass
2
+ from pathlib import Path
3
+ from typing import Callable, Optional
4
+
5
+ from snowflake.cli.api.console.abc import AbstractConsole
6
+
7
+
8
+ @dataclass
9
+ class ActionContext:
10
+ """
11
+ An object that is passed to each action when called by WorkspaceManager
12
+ """
13
+
14
+ console: AbstractConsole
15
+ project_root: Path
16
+ default_role: str
17
+ default_warehouse: Optional[str]
18
+ get_entity: Callable
@@ -0,0 +1,306 @@
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
+ from pathlib import Path
19
+ from textwrap import dedent
20
+ from typing import List, Optional
21
+
22
+ import typer
23
+ from click import MissingParameter
24
+ from snowflake.cli._plugins.nativeapp.artifacts import BundleMap
25
+ from snowflake.cli._plugins.nativeapp.common_flags import (
26
+ ForceOption,
27
+ InteractiveOption,
28
+ ValidateOption,
29
+ )
30
+ from snowflake.cli._plugins.workspace.manager import WorkspaceManager
31
+ from snowflake.cli.api.cli_global_context import get_cli_context
32
+ from snowflake.cli.api.commands.decorators import with_project_definition
33
+ from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
34
+ from snowflake.cli.api.entities.common import EntityActions
35
+ from snowflake.cli.api.exceptions import IncompatibleParametersError
36
+ from snowflake.cli.api.output.types import MessageResult, QueryResult
37
+
38
+ ws = SnowTyperFactory(
39
+ name="ws",
40
+ help="Deploy and interact with snowflake.yml-based entities.",
41
+ is_hidden=lambda: True,
42
+ )
43
+ log = logging.getLogger(__name__)
44
+
45
+
46
+ @ws.command(requires_connection=True, hidden=True)
47
+ @with_project_definition()
48
+ def bundle(
49
+ entity_id: str = typer.Option(
50
+ help=f"""The ID of the entity you want to bundle.""",
51
+ ),
52
+ **options,
53
+ ):
54
+ """
55
+ Prepares a local folder with the configured artifacts of the specified entity.
56
+ """
57
+
58
+ cli_context = get_cli_context()
59
+ ws = WorkspaceManager(
60
+ project_definition=cli_context.project_definition,
61
+ project_root=cli_context.project_root,
62
+ )
63
+
64
+ bundle_map: BundleMap = ws.perform_action(entity_id, EntityActions.BUNDLE)
65
+ return MessageResult(f"Bundle generated at {bundle_map.deploy_root()}")
66
+
67
+
68
+ @ws.command(requires_connection=True, hidden=True)
69
+ @with_project_definition()
70
+ def deploy(
71
+ entity_id: str = typer.Option(
72
+ help=f"""The ID of the entity you want to deploy.""",
73
+ ),
74
+ # TODO The following options should be generated automatically, depending on the specified entity type
75
+ prune: Optional[bool] = typer.Option(
76
+ default=None,
77
+ help=f"""Whether to delete specified files from the stage if they don't exist locally. If set, the command deletes files that exist in the stage, but not in the local filesystem. This option cannot be used when paths are specified.""",
78
+ ),
79
+ recursive: Optional[bool] = typer.Option(
80
+ None,
81
+ "--recursive/--no-recursive",
82
+ "-r",
83
+ help=f"""Whether to traverse and deploy files from subdirectories. If set, the command deploys all files and subdirectories; otherwise, only files in the current directory are deployed.""",
84
+ ),
85
+ paths: Optional[List[Path]] = typer.Argument(
86
+ default=None,
87
+ show_default=False,
88
+ help=dedent(
89
+ f"""
90
+ Paths, relative to the the project root, of files or directories you want to upload to a stage. If a file is
91
+ specified, it must match one of the artifacts src pattern entries in snowflake.yml. If a directory is
92
+ specified, it will be searched for subfolders or files to deploy based on artifacts src pattern entries. If
93
+ unspecified, the command syncs all local changes to the stage."""
94
+ ).strip(),
95
+ ),
96
+ from_release_directive: Optional[bool] = typer.Option(
97
+ False,
98
+ "--from-release-directive",
99
+ help=f"""Creates or upgrades an application object to the version and patch specified by the release directive applicable to your Snowflake account.
100
+ The command fails if no release directive exists for your Snowflake account for a given application package, which is determined from the project definition file. Default: unset.""",
101
+ is_flag=True,
102
+ ),
103
+ interactive: bool = InteractiveOption,
104
+ force: Optional[bool] = ForceOption,
105
+ validate: bool = ValidateOption,
106
+ **options,
107
+ ):
108
+ """
109
+ Deploys the specified entity.
110
+ """
111
+ if prune is None and recursive is None and not paths:
112
+ prune = True
113
+ recursive = True
114
+ else:
115
+ if prune is None:
116
+ prune = False
117
+ if recursive is None:
118
+ recursive = False
119
+
120
+ if paths and prune:
121
+ raise IncompatibleParametersError(["paths", "--prune"])
122
+
123
+ cli_context = get_cli_context()
124
+ ws = WorkspaceManager(
125
+ project_definition=cli_context.project_definition,
126
+ project_root=cli_context.project_root,
127
+ )
128
+
129
+ ws.perform_action(
130
+ entity_id,
131
+ EntityActions.DEPLOY,
132
+ prune=prune,
133
+ recursive=recursive,
134
+ paths=paths,
135
+ validate=validate,
136
+ from_release_directive=from_release_directive,
137
+ interactive=interactive,
138
+ force=force,
139
+ )
140
+ return MessageResult("Deployed successfully.")
141
+
142
+
143
+ @ws.command(requires_connection=True, hidden=True)
144
+ @with_project_definition()
145
+ def drop(
146
+ entity_id: str = typer.Option(
147
+ help=f"""The ID of the entity you want to drop.""",
148
+ ),
149
+ # TODO The following options should be generated automatically, depending on the specified entity type
150
+ interactive: bool = InteractiveOption,
151
+ force: Optional[bool] = ForceOption,
152
+ cascade: Optional[bool] = typer.Option(
153
+ None,
154
+ help=f"""Whether to drop all application objects owned by the application within the account. Default: false.""",
155
+ show_default=False,
156
+ ),
157
+ **options,
158
+ ):
159
+ """
160
+ Drops the specified entity.
161
+ """
162
+ cli_context = get_cli_context()
163
+ ws = WorkspaceManager(
164
+ project_definition=cli_context.project_definition,
165
+ project_root=cli_context.project_root,
166
+ )
167
+
168
+ ws.perform_action(
169
+ entity_id,
170
+ EntityActions.DROP,
171
+ force_drop=force,
172
+ interactive=interactive,
173
+ cascade=cascade,
174
+ )
175
+
176
+
177
+ @ws.command(requires_connection=True, hidden=True)
178
+ @with_project_definition()
179
+ def validate(
180
+ entity_id: str = typer.Option(
181
+ help=f"""The ID of the entity you want to validate.""",
182
+ ),
183
+ interactive: bool = InteractiveOption,
184
+ force: Optional[bool] = ForceOption,
185
+ **options,
186
+ ):
187
+ """Validates the specified entity."""
188
+ cli_context = get_cli_context()
189
+ ws = WorkspaceManager(
190
+ project_definition=cli_context.project_definition,
191
+ project_root=cli_context.project_root,
192
+ )
193
+
194
+ ws.perform_action(
195
+ entity_id,
196
+ EntityActions.VALIDATE,
197
+ interactive=interactive,
198
+ force=force,
199
+ )
200
+
201
+
202
+ version = SnowTyperFactory(
203
+ name="version",
204
+ help="Manages versions for project entities.",
205
+ )
206
+ ws.add_typer(version)
207
+
208
+
209
+ @version.command(name="list", requires_connection=True, hidden=True)
210
+ @with_project_definition()
211
+ def version_list(
212
+ entity_id: str = typer.Option(
213
+ help="The ID of the entity you want to list versions for.",
214
+ ),
215
+ **options,
216
+ ):
217
+ """Lists the versions of the specified entity."""
218
+ cli_context = get_cli_context()
219
+ ws = WorkspaceManager(
220
+ project_definition=cli_context.project_definition,
221
+ project_root=cli_context.project_root,
222
+ )
223
+ cursor = ws.perform_action(
224
+ entity_id,
225
+ EntityActions.VERSION_LIST,
226
+ )
227
+ return QueryResult(cursor)
228
+
229
+
230
+ @version.command(name="create", requires_connection=True, hidden=True)
231
+ @with_project_definition()
232
+ def version_create(
233
+ entity_id: str = typer.Option(
234
+ help="The ID of the entity you want to create a version for.",
235
+ ),
236
+ version: Optional[str] = typer.Argument(
237
+ None,
238
+ help=f"""Version to define in your application package. If the version already exists, an auto-incremented patch is added to the version instead. Defaults to the version specified in the `manifest.yml` file.""",
239
+ ),
240
+ patch: Optional[int] = typer.Option(
241
+ None,
242
+ "--patch",
243
+ help=f"""The patch number you want to create for an existing version.
244
+ Defaults to undefined if it is not set, which means the Snowflake CLI either uses the patch specified in the `manifest.yml` file or automatically generates a new patch number.""",
245
+ ),
246
+ skip_git_check: Optional[bool] = typer.Option(
247
+ False,
248
+ "--skip-git-check",
249
+ help="When enabled, the Snowflake CLI skips checking if your project has any untracked or stages files in git. Default: unset.",
250
+ is_flag=True,
251
+ ),
252
+ interactive: bool = InteractiveOption,
253
+ force: Optional[bool] = ForceOption,
254
+ **options,
255
+ ):
256
+ """Creates a new version for the specified entity."""
257
+ if version is None and patch is not None:
258
+ raise MissingParameter("Cannot provide a patch without version!")
259
+
260
+ cli_context = get_cli_context()
261
+ ws = WorkspaceManager(
262
+ project_definition=cli_context.project_definition,
263
+ project_root=cli_context.project_root,
264
+ )
265
+ ws.perform_action(
266
+ entity_id,
267
+ EntityActions.VERSION_CREATE,
268
+ version=version,
269
+ patch=patch,
270
+ skip_git_check=skip_git_check,
271
+ interactive=interactive,
272
+ force=force,
273
+ )
274
+
275
+
276
+ @version.command(name="drop", requires_connection=True, hidden=True)
277
+ @with_project_definition()
278
+ def version_drop(
279
+ entity_id: str = typer.Option(
280
+ help="The ID of the entity you want to create a version for.",
281
+ ),
282
+ version: Optional[str] = typer.Argument(
283
+ None,
284
+ help=f"""Version to define in your application package. If the version already exists, an auto-incremented patch is added to the version instead. Defaults to the version specified in the `manifest.yml` file.""",
285
+ ),
286
+ interactive: bool = InteractiveOption,
287
+ force: Optional[bool] = ForceOption,
288
+ **options,
289
+ ):
290
+ """
291
+ Drops a version defined for your entity. Versions can either be passed in as an argument to the command or read from the `manifest.yml` file.
292
+ Dropping patches is not allowed.
293
+ """
294
+
295
+ cli_context = get_cli_context()
296
+ ws = WorkspaceManager(
297
+ project_definition=cli_context.project_definition,
298
+ project_root=cli_context.project_root,
299
+ )
300
+ ws.perform_action(
301
+ entity_id,
302
+ EntityActions.VERSION_CREATE,
303
+ version=version,
304
+ interactive=interactive,
305
+ force=force,
306
+ )