snowflake-cli-labs 2.4.1__py3-none-any.whl → 2.5.0rc0__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 (204) hide show
  1. snowflake/cli/__about__.py +15 -1
  2. snowflake/cli/__init__.py +13 -0
  3. snowflake/cli/api/__init__.py +14 -0
  4. snowflake/cli/api/cli_global_context.py +26 -0
  5. snowflake/cli/api/commands/__init__.py +13 -0
  6. snowflake/cli/api/commands/alias.py +14 -0
  7. snowflake/cli/api/commands/decorators.py +14 -0
  8. snowflake/cli/api/commands/experimental_behaviour.py +14 -0
  9. snowflake/cli/api/commands/flags.py +21 -1
  10. snowflake/cli/api/commands/project_initialisation.py +19 -2
  11. snowflake/cli/api/commands/snow_typer.py +90 -1
  12. snowflake/cli/api/config.py +14 -0
  13. snowflake/cli/api/console/__init__.py +14 -0
  14. snowflake/cli/api/console/abc.py +14 -0
  15. snowflake/cli/api/console/console.py +14 -0
  16. snowflake/cli/api/console/enum.py +14 -0
  17. snowflake/cli/api/constants.py +14 -0
  18. snowflake/cli/api/exceptions.py +22 -0
  19. snowflake/cli/api/feature_flags.py +14 -1
  20. snowflake/cli/api/identifiers.py +16 -2
  21. snowflake/cli/api/output/__init__.py +13 -0
  22. snowflake/cli/api/output/formats.py +14 -0
  23. snowflake/cli/api/output/types.py +14 -0
  24. snowflake/cli/api/plugins/__init__.py +13 -0
  25. snowflake/cli/api/plugins/command/__init__.py +14 -0
  26. snowflake/cli/api/plugins/command/plugin_hook_specs.py +14 -0
  27. snowflake/cli/api/plugins/plugin_config.py +14 -0
  28. snowflake/cli/api/project/__init__.py +13 -0
  29. snowflake/cli/api/project/definition.py +54 -8
  30. snowflake/cli/api/project/definition_manager.py +28 -2
  31. snowflake/cli/api/project/errors.py +14 -0
  32. snowflake/cli/api/project/schemas/__init__.py +13 -0
  33. snowflake/cli/api/project/schemas/identifier_model.py +14 -0
  34. snowflake/cli/api/project/schemas/native_app/__init__.py +13 -0
  35. snowflake/cli/api/project/schemas/native_app/application.py +14 -0
  36. snowflake/cli/api/project/schemas/native_app/native_app.py +35 -0
  37. snowflake/cli/api/project/schemas/native_app/package.py +14 -0
  38. snowflake/cli/api/project/schemas/native_app/path_mapping.py +15 -1
  39. snowflake/cli/api/project/schemas/project_definition.py +14 -0
  40. snowflake/cli/api/project/schemas/snowpark/__init__.py +13 -0
  41. snowflake/cli/api/project/schemas/snowpark/argument.py +14 -0
  42. snowflake/cli/api/project/schemas/snowpark/callable.py +14 -0
  43. snowflake/cli/api/project/schemas/snowpark/snowpark.py +14 -0
  44. snowflake/cli/api/project/schemas/streamlit/__init__.py +13 -0
  45. snowflake/cli/api/project/schemas/streamlit/streamlit.py +14 -0
  46. snowflake/cli/api/project/schemas/updatable_model.py +14 -0
  47. snowflake/cli/api/project/util.py +32 -3
  48. snowflake/cli/api/secure_path.py +59 -7
  49. snowflake/cli/api/secure_utils.py +14 -0
  50. snowflake/cli/api/sql_execution.py +14 -0
  51. snowflake/cli/api/utils/__init__.py +13 -0
  52. snowflake/cli/api/utils/cursor.py +14 -0
  53. snowflake/cli/api/utils/definition_rendering.py +268 -0
  54. snowflake/cli/api/utils/dict_utils.py +73 -0
  55. snowflake/cli/api/utils/error_handling.py +14 -0
  56. snowflake/cli/api/utils/graph.py +97 -0
  57. snowflake/cli/api/utils/models.py +14 -0
  58. snowflake/cli/api/utils/naming_utils.py +13 -0
  59. snowflake/cli/api/utils/path_utils.py +14 -0
  60. snowflake/cli/api/utils/rendering.py +21 -152
  61. snowflake/cli/api/utils/types.py +18 -1
  62. snowflake/cli/app/__init__.py +14 -0
  63. snowflake/cli/app/__main__.py +14 -0
  64. snowflake/cli/app/api_impl/__init__.py +13 -0
  65. snowflake/cli/app/api_impl/plugin/__init__.py +13 -0
  66. snowflake/cli/app/api_impl/plugin/plugin_config_provider_impl.py +14 -0
  67. snowflake/cli/app/cli_app.py +14 -0
  68. snowflake/cli/app/commands_registration/__init__.py +14 -0
  69. snowflake/cli/app/commands_registration/builtin_plugins.py +14 -0
  70. snowflake/cli/app/commands_registration/command_plugins_loader.py +14 -0
  71. snowflake/cli/app/commands_registration/commands_registration_with_callbacks.py +14 -0
  72. snowflake/cli/app/commands_registration/exception_logging.py +14 -0
  73. snowflake/cli/app/commands_registration/threadsafe.py +14 -0
  74. snowflake/cli/app/commands_registration/typer_registration.py +14 -0
  75. snowflake/cli/app/constants.py +14 -0
  76. snowflake/cli/app/dev/__init__.py +13 -0
  77. snowflake/cli/app/dev/commands_structure.py +14 -0
  78. snowflake/cli/app/dev/docs/__init__.py +13 -0
  79. snowflake/cli/app/dev/docs/generator.py +14 -0
  80. snowflake/cli/app/dev/pycharm_remote_debug.py +14 -0
  81. snowflake/cli/app/loggers.py +14 -0
  82. snowflake/cli/app/main_typer.py +14 -0
  83. snowflake/cli/app/printing.py +14 -0
  84. snowflake/cli/app/snow_connector.py +14 -0
  85. snowflake/cli/app/telemetry.py +14 -0
  86. snowflake/cli/plugins/__init__.py +13 -0
  87. snowflake/cli/plugins/connection/__init__.py +13 -0
  88. snowflake/cli/plugins/connection/commands.py +27 -2
  89. snowflake/cli/plugins/connection/plugin_spec.py +15 -1
  90. snowflake/cli/plugins/connection/util.py +21 -1
  91. snowflake/cli/plugins/cortex/__init__.py +13 -0
  92. snowflake/cli/plugins/cortex/commands.py +16 -2
  93. snowflake/cli/plugins/cortex/constants.py +14 -0
  94. snowflake/cli/plugins/cortex/manager.py +14 -0
  95. snowflake/cli/plugins/cortex/plugin_spec.py +15 -1
  96. snowflake/cli/plugins/cortex/types.py +14 -0
  97. snowflake/cli/plugins/git/__init__.py +13 -0
  98. snowflake/cli/plugins/git/commands.py +16 -2
  99. snowflake/cli/plugins/git/manager.py +14 -0
  100. snowflake/cli/plugins/git/plugin_spec.py +15 -1
  101. snowflake/cli/plugins/nativeapp/__init__.py +13 -0
  102. snowflake/cli/plugins/nativeapp/artifacts.py +202 -98
  103. snowflake/cli/plugins/nativeapp/codegen/__init__.py +13 -0
  104. snowflake/cli/plugins/nativeapp/codegen/artifact_processor.py +14 -0
  105. snowflake/cli/plugins/nativeapp/codegen/compiler.py +14 -0
  106. snowflake/cli/plugins/nativeapp/codegen/sandbox.py +14 -0
  107. snowflake/cli/plugins/nativeapp/codegen/snowpark/callback_source.py.jinja +4 -4
  108. snowflake/cli/plugins/nativeapp/codegen/snowpark/extension_function_utils.py +34 -13
  109. snowflake/cli/plugins/nativeapp/codegen/snowpark/models.py +14 -0
  110. snowflake/cli/plugins/nativeapp/codegen/snowpark/python_processor.py +52 -13
  111. snowflake/cli/plugins/nativeapp/commands.py +63 -10
  112. snowflake/cli/plugins/nativeapp/common_flags.py +20 -0
  113. snowflake/cli/plugins/nativeapp/constants.py +15 -0
  114. snowflake/cli/plugins/nativeapp/exceptions.py +23 -2
  115. snowflake/cli/plugins/nativeapp/init.py +14 -0
  116. snowflake/cli/plugins/nativeapp/manager.py +118 -25
  117. snowflake/cli/plugins/nativeapp/plugin_spec.py +15 -1
  118. snowflake/cli/plugins/nativeapp/policy.py +14 -0
  119. snowflake/cli/plugins/nativeapp/run_processor.py +22 -3
  120. snowflake/cli/plugins/nativeapp/teardown_processor.py +14 -0
  121. snowflake/cli/plugins/nativeapp/utils.py +14 -0
  122. snowflake/cli/plugins/nativeapp/version/__init__.py +13 -0
  123. snowflake/cli/plugins/nativeapp/version/commands.py +19 -4
  124. snowflake/cli/plugins/nativeapp/version/version_processor.py +26 -4
  125. snowflake/cli/plugins/notebook/__init__.py +13 -0
  126. snowflake/cli/plugins/notebook/commands.py +16 -4
  127. snowflake/cli/plugins/notebook/exceptions.py +14 -0
  128. snowflake/cli/plugins/notebook/manager.py +14 -0
  129. snowflake/cli/plugins/notebook/plugin_spec.py +15 -1
  130. snowflake/cli/plugins/notebook/types.py +14 -0
  131. snowflake/cli/plugins/object/__init__.py +13 -11
  132. snowflake/cli/plugins/object/command_aliases.py +20 -6
  133. snowflake/cli/plugins/object/commands.py +16 -2
  134. snowflake/cli/plugins/object/common.py +14 -0
  135. snowflake/cli/plugins/object/manager.py +14 -0
  136. snowflake/cli/plugins/object/plugin_spec.py +16 -2
  137. snowflake/cli/plugins/object_stage_deprecated/__init__.py +14 -0
  138. snowflake/cli/plugins/object_stage_deprecated/commands.py +16 -2
  139. snowflake/cli/plugins/object_stage_deprecated/plugin_spec.py +16 -4
  140. snowflake/cli/plugins/snowpark/__init__.py +13 -4
  141. snowflake/cli/plugins/snowpark/commands.py +18 -2
  142. snowflake/cli/plugins/snowpark/common.py +15 -0
  143. snowflake/cli/plugins/snowpark/manager.py +14 -0
  144. snowflake/cli/plugins/snowpark/models.py +15 -1
  145. snowflake/cli/plugins/snowpark/package/__init__.py +13 -0
  146. snowflake/cli/plugins/snowpark/package/anaconda_packages.py +14 -0
  147. snowflake/cli/plugins/snowpark/package/commands.py +16 -2
  148. snowflake/cli/plugins/snowpark/package/manager.py +14 -0
  149. snowflake/cli/plugins/snowpark/package/utils.py +14 -0
  150. snowflake/cli/plugins/snowpark/package_utils.py +15 -1
  151. snowflake/cli/plugins/snowpark/plugin_spec.py +16 -2
  152. snowflake/cli/plugins/snowpark/snowpark_package_paths.py +14 -0
  153. snowflake/cli/plugins/snowpark/snowpark_shared.py +14 -0
  154. snowflake/cli/plugins/snowpark/zipper.py +20 -3
  155. snowflake/cli/plugins/spcs/__init__.py +16 -2
  156. snowflake/cli/plugins/spcs/common.py +14 -0
  157. snowflake/cli/plugins/spcs/compute_pool/__init__.py +13 -0
  158. snowflake/cli/plugins/spcs/compute_pool/commands.py +16 -2
  159. snowflake/cli/plugins/spcs/compute_pool/manager.py +14 -0
  160. snowflake/cli/plugins/spcs/image_registry/__init__.py +13 -0
  161. snowflake/cli/plugins/spcs/image_registry/commands.py +16 -2
  162. snowflake/cli/plugins/spcs/image_registry/manager.py +16 -0
  163. snowflake/cli/plugins/spcs/image_repository/__init__.py +13 -0
  164. snowflake/cli/plugins/spcs/image_repository/commands.py +16 -2
  165. snowflake/cli/plugins/spcs/image_repository/manager.py +14 -0
  166. snowflake/cli/plugins/spcs/jobs/__init__.py +13 -0
  167. snowflake/cli/plugins/spcs/jobs/commands.py +17 -3
  168. snowflake/cli/plugins/spcs/jobs/manager.py +14 -0
  169. snowflake/cli/plugins/spcs/plugin_spec.py +15 -1
  170. snowflake/cli/plugins/spcs/services/__init__.py +13 -0
  171. snowflake/cli/plugins/spcs/services/commands.py +16 -2
  172. snowflake/cli/plugins/spcs/services/manager.py +14 -0
  173. snowflake/cli/plugins/sql/__init__.py +13 -0
  174. snowflake/cli/plugins/sql/commands.py +16 -2
  175. snowflake/cli/plugins/sql/manager.py +14 -0
  176. snowflake/cli/plugins/sql/plugin_spec.py +15 -1
  177. snowflake/cli/plugins/sql/snowsql_templating.py +14 -0
  178. snowflake/cli/plugins/stage/__init__.py +13 -0
  179. snowflake/cli/plugins/stage/commands.py +17 -3
  180. snowflake/cli/plugins/stage/diff.py +14 -0
  181. snowflake/cli/plugins/stage/manager.py +16 -5
  182. snowflake/cli/plugins/stage/plugin_spec.py +16 -2
  183. snowflake/cli/plugins/streamlit/__init__.py +13 -0
  184. snowflake/cli/plugins/streamlit/commands.py +16 -2
  185. snowflake/cli/plugins/streamlit/manager.py +14 -0
  186. snowflake/cli/plugins/streamlit/plugin_spec.py +15 -1
  187. snowflake/cli/templates/default_snowpark/app/__init__.py +13 -0
  188. snowflake/cli/templates/default_snowpark/app/common.py +15 -0
  189. snowflake/cli/templates/default_snowpark/app/functions.py +14 -0
  190. snowflake/cli/templates/default_snowpark/app/procedures.py +14 -0
  191. snowflake/cli/templates/default_snowpark/snowflake.yml +1 -1
  192. snowflake/cli/templates/default_streamlit/common/hello.py +15 -0
  193. snowflake/cli/templates/default_streamlit/pages/my_page.py +14 -0
  194. snowflake/cli/templates/default_streamlit/snowflake.yml +1 -1
  195. snowflake/cli/templates/default_streamlit/streamlit_app.py +14 -0
  196. {snowflake_cli_labs-2.4.1.dist-info → snowflake_cli_labs-2.5.0rc0.dist-info}/METADATA +23 -7
  197. snowflake_cli_labs-2.5.0rc0.dist-info/RECORD +206 -0
  198. snowflake/cli/plugins/nativeapp/feature_flags.py +0 -10
  199. snowflake/cli/templates/environment.yml.jinja +0 -5
  200. snowflake/cli/templates/streamlit_app_launcher.py.jinja +0 -19
  201. snowflake_cli_labs-2.4.1.dist-info/RECORD +0 -206
  202. {snowflake_cli_labs-2.4.1.dist-info → snowflake_cli_labs-2.5.0rc0.dist-info}/WHEEL +0 -0
  203. {snowflake_cli_labs-2.4.1.dist-info → snowflake_cli_labs-2.5.0rc0.dist-info}/entry_points.txt +0 -0
  204. {snowflake_cli_labs-2.4.1.dist-info → snowflake_cli_labs-2.5.0rc0.dist-info}/licenses/LICENSE +0 -0
@@ -1,5 +1,20 @@
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
+
1
15
  from __future__ import annotations
2
16
 
17
+ import json
3
18
  import os
4
19
  from abc import ABC, abstractmethod
5
20
  from functools import cached_property
@@ -17,19 +32,19 @@ from snowflake.cli.api.project.definition import (
17
32
  default_role,
18
33
  )
19
34
  from snowflake.cli.api.project.schemas.native_app.native_app import NativeApp
35
+ from snowflake.cli.api.project.schemas.native_app.path_mapping import PathMapping
20
36
  from snowflake.cli.api.project.util import (
21
37
  extract_schema,
38
+ identifier_for_url,
22
39
  to_identifier,
23
40
  unquote_identifier,
24
41
  )
25
42
  from snowflake.cli.api.sql_execution import SqlExecutionMixin
26
43
  from snowflake.cli.plugins.connection.util import make_snowsight_url
27
44
  from snowflake.cli.plugins.nativeapp.artifacts import (
28
- ArtifactMapping,
29
45
  BundleMap,
30
46
  build_bundle,
31
47
  resolve_without_follow,
32
- translate_artifact,
33
48
  )
34
49
  from snowflake.cli.plugins.nativeapp.codegen.compiler import (
35
50
  NativeAppCompiler,
@@ -38,6 +53,7 @@ from snowflake.cli.plugins.nativeapp.constants import (
38
53
  ALLOWED_SPECIAL_COMMENTS,
39
54
  COMMENT_COL,
40
55
  ERROR_MESSAGE_606,
56
+ ERROR_MESSAGE_2003,
41
57
  ERROR_MESSAGE_2043,
42
58
  INTERNAL_DISTRIBUTION,
43
59
  NAME_COL,
@@ -46,11 +62,12 @@ from snowflake.cli.plugins.nativeapp.constants import (
46
62
  )
47
63
  from snowflake.cli.plugins.nativeapp.exceptions import (
48
64
  ApplicationPackageAlreadyExistsError,
65
+ ApplicationPackageDoesNotExistError,
49
66
  InvalidPackageScriptError,
50
67
  MissingPackageScriptError,
68
+ SetupScriptFailedValidation,
51
69
  UnexpectedOwnerError,
52
70
  )
53
- from snowflake.cli.plugins.nativeapp.feature_flags import FeatureFlag
54
71
  from snowflake.cli.plugins.nativeapp.utils import verify_exists, verify_no_directories
55
72
  from snowflake.cli.plugins.stage.diff import (
56
73
  DiffResult,
@@ -60,6 +77,7 @@ from snowflake.cli.plugins.stage.diff import (
60
77
  sync_local_diff_with_stage,
61
78
  to_stage_path,
62
79
  )
80
+ from snowflake.cli.plugins.stage.manager import StageManager
63
81
  from snowflake.connector import ProgrammingError
64
82
  from snowflake.connector.cursor import DictCursor
65
83
 
@@ -158,8 +176,8 @@ class NativeAppManager(SqlExecutionMixin):
158
176
  return self._project_definition
159
177
 
160
178
  @cached_property
161
- def artifacts(self) -> List[ArtifactMapping]:
162
- return [translate_artifact(item) for item in self.definition.artifacts]
179
+ def artifacts(self) -> List[PathMapping]:
180
+ return self.definition.artifacts
163
181
 
164
182
  @cached_property
165
183
  def deploy_root(self) -> Path:
@@ -183,6 +201,10 @@ class NativeAppManager(SqlExecutionMixin):
183
201
  def stage_fqn(self) -> str:
184
202
  return f"{self.package_name}.{self.definition.source_stage}"
185
203
 
204
+ @cached_property
205
+ def scratch_stage_fqn(self) -> str:
206
+ return f"{self.package_name}.{self.definition.scratch_stage}"
207
+
186
208
  @cached_property
187
209
  def stage_schema(self) -> Optional[str]:
188
210
  return extract_schema(self.stage_fqn)
@@ -320,36 +342,36 @@ class NativeAppManager(SqlExecutionMixin):
320
342
  Populates the local deploy root from artifact sources.
321
343
  """
322
344
  mapped_files = build_bundle(self.project_root, self.deploy_root, self.artifacts)
323
- if FeatureFlag.ENABLE_SETUP_SCRIPT_GENERATION.is_enabled():
324
- compiler = NativeAppCompiler(
325
- project_definition=self._project_definition,
326
- project_root=self.project_root,
327
- deploy_root=self.deploy_root,
328
- generated_root=self.generated_root,
329
- )
330
- compiler.compile_artifacts()
345
+ compiler = NativeAppCompiler(
346
+ project_definition=self._project_definition,
347
+ project_root=self.project_root,
348
+ deploy_root=self.deploy_root,
349
+ generated_root=self.generated_root,
350
+ )
351
+ compiler.compile_artifacts()
331
352
  return mapped_files
332
353
 
333
354
  def sync_deploy_root_with_stage(
334
355
  self,
356
+ bundle_map: BundleMap,
335
357
  role: str,
336
358
  prune: bool,
337
359
  recursive: bool,
360
+ stage_fqn: str,
338
361
  local_paths_to_sync: List[Path] | None = None,
339
- bundle_map: Optional[BundleMap] = None,
340
362
  ) -> DiffResult:
341
363
  """
342
364
  Ensures that the files on our remote stage match the artifacts we have in
343
365
  the local filesystem.
344
366
 
345
367
  Args:
368
+ bundle_map (BundleMap): The artifact mapping computed by the `build_bundle` function.
346
369
  role (str): The name of the role to use for queries and commands.
347
370
  prune (bool): Whether to prune artifacts from the stage that don't exist locally.
348
371
  recursive (bool): Whether to traverse directories recursively.
372
+ stage_fqn (str): The name of the stage to diff against and upload to.
349
373
  local_paths_to_sync (List[Path], optional): List of local paths to sync. Defaults to None to sync all
350
374
  local paths. Note that providing an empty list here is equivalent to None.
351
- bundle_map: the artifact mapping computed during the `bundle` step. Required when local_paths_to_sync is
352
- provided.
353
375
 
354
376
  Returns:
355
377
  A `DiffResult` instance describing the changes that were performed.
@@ -357,14 +379,16 @@ class NativeAppManager(SqlExecutionMixin):
357
379
 
358
380
  # Does a stage already exist within the application package, or we need to create one?
359
381
  # Using "if not exists" should take care of either case.
360
- cc.step("Checking if stage exists, or creating a new one if none exists.")
382
+ cc.step(
383
+ f"Checking if stage {stage_fqn} exists, or creating a new one if none exists."
384
+ )
361
385
  with self.use_role(role):
362
386
  self._execute_query(
363
387
  f"create schema if not exists {self.package_name}.{self.stage_schema}"
364
388
  )
365
389
  self._execute_query(
366
390
  f"""
367
- create stage if not exists {self.stage_fqn}
391
+ create stage if not exists {stage_fqn}
368
392
  encryption = (TYPE = 'SNOWFLAKE_SSE')
369
393
  DIRECTORY = (ENABLE = TRUE)"""
370
394
  )
@@ -374,12 +398,10 @@ class NativeAppManager(SqlExecutionMixin):
374
398
  "Performing a diff between the Snowflake stage and your local deploy_root ('%s') directory."
375
399
  % self.deploy_root
376
400
  )
377
- diff: DiffResult = compute_stage_diff(self.deploy_root, self.stage_fqn)
401
+ diff: DiffResult = compute_stage_diff(self.deploy_root, stage_fqn)
378
402
 
379
403
  files_not_removed = []
380
404
  if local_paths_to_sync:
381
- assert bundle_map is not None
382
-
383
405
  # Deploying specific files/directories
384
406
  resolved_paths_to_sync = [
385
407
  resolve_without_follow(p) for p in local_paths_to_sync
@@ -427,7 +449,7 @@ class NativeAppManager(SqlExecutionMixin):
427
449
  role=role,
428
450
  deploy_root_path=self.deploy_root,
429
451
  diff_result=diff,
430
- stage_fqn=self.stage_fqn,
452
+ stage_fqn=stage_fqn,
431
453
  )
432
454
  return diff
433
455
 
@@ -464,7 +486,7 @@ class NativeAppManager(SqlExecutionMixin):
464
486
 
465
487
  def get_snowsight_url(self) -> str:
466
488
  """Returns the URL that can be used to visit this app via Snowsight."""
467
- name = unquote_identifier(self.app_name)
489
+ name = identifier_for_url(self.app_name)
468
490
  return make_snowsight_url(self._conn, f"/#/apps/application/{name}")
469
491
 
470
492
  def create_app_package(self) -> None:
@@ -552,10 +574,12 @@ class NativeAppManager(SqlExecutionMixin):
552
574
 
553
575
  def deploy(
554
576
  self,
577
+ bundle_map: BundleMap,
555
578
  prune: bool,
556
579
  recursive: bool,
580
+ stage_fqn: Optional[str] = None,
557
581
  local_paths_to_sync: List[Path] | None = None,
558
- bundle_map: Optional[BundleMap] = None,
582
+ validate: bool = True,
559
583
  ) -> DiffResult:
560
584
  """app deploy process"""
561
585
 
@@ -567,8 +591,77 @@ class NativeAppManager(SqlExecutionMixin):
567
591
  self._apply_package_scripts()
568
592
 
569
593
  # 3. Upload files from deploy root local folder to the above stage
594
+ stage_fqn = stage_fqn or self.stage_fqn
570
595
  diff = self.sync_deploy_root_with_stage(
571
- self.package_role, prune, recursive, local_paths_to_sync, bundle_map
596
+ bundle_map=bundle_map,
597
+ role=self.package_role,
598
+ prune=prune,
599
+ recursive=recursive,
600
+ stage_fqn=stage_fqn,
601
+ local_paths_to_sync=local_paths_to_sync,
572
602
  )
573
603
 
604
+ if validate:
605
+ self.validate(use_scratch_stage=False)
606
+
574
607
  return diff
608
+
609
+ def validate(self, use_scratch_stage: bool = False):
610
+ """Validates Native App setup script SQL."""
611
+ with cc.phase(f"Validating Snowflake Native App setup script."):
612
+ validation_result = self.get_validation_result(use_scratch_stage)
613
+
614
+ # First print warnings, regardless of the outcome of validation
615
+ for warning in validation_result.get("warnings", []):
616
+ cc.warning(_validation_item_to_str(warning))
617
+
618
+ # Then print errors
619
+ for error in validation_result.get("errors", []):
620
+ # Print them as warnings for now since we're going to be
621
+ # revamping CLI output soon
622
+ cc.warning(_validation_item_to_str(error))
623
+
624
+ # Then raise an exception if validation failed
625
+ if validation_result["status"] == "FAIL":
626
+ raise SetupScriptFailedValidation()
627
+
628
+ def get_validation_result(self, use_scratch_stage: bool):
629
+ """Call system$validate_native_app_setup() to validate deployed Native App setup script."""
630
+ stage_fqn = self.stage_fqn
631
+ if use_scratch_stage:
632
+ stage_fqn = self.scratch_stage_fqn
633
+ bundle_map = self.build_bundle()
634
+ self.deploy(
635
+ bundle_map=bundle_map,
636
+ prune=True,
637
+ recursive=True,
638
+ stage_fqn=stage_fqn,
639
+ validate=False,
640
+ )
641
+ prefixed_stage_fqn = StageManager.get_standard_stage_prefix(stage_fqn)
642
+ try:
643
+ cursor = self._execute_query(
644
+ f"call system$validate_native_app_setup('{prefixed_stage_fqn}')"
645
+ )
646
+ except ProgrammingError as err:
647
+ if err.errno == 2003 and ERROR_MESSAGE_2003 in err.msg:
648
+ raise ApplicationPackageDoesNotExistError(self.package_name)
649
+ generic_sql_error_handler(err)
650
+ else:
651
+ if not cursor.rowcount:
652
+ raise SnowflakeSQLExecutionError()
653
+ return json.loads(cursor.fetchone()[0])
654
+ finally:
655
+ if use_scratch_stage:
656
+ cc.step(f"Dropping stage {self.scratch_stage_fqn}.")
657
+ with self.use_role(self.package_role):
658
+ self._execute_query(
659
+ f"drop stage if exists {self.scratch_stage_fqn}"
660
+ )
661
+
662
+
663
+ def _validation_item_to_str(item: dict[str, str | int]):
664
+ s = item["message"]
665
+ if item["errorCode"]:
666
+ s = f"{s} (error code {item['errorCode']})"
667
+ return s
@@ -1,3 +1,17 @@
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
+
1
15
  from snowflake.cli.api.plugins.command import (
2
16
  SNOWCLI_ROOT_COMMAND_PATH,
3
17
  CommandSpec,
@@ -12,5 +26,5 @@ def command_spec():
12
26
  return CommandSpec(
13
27
  parent_command_path=SNOWCLI_ROOT_COMMAND_PATH,
14
28
  command_type=CommandType.COMMAND_GROUP,
15
- typer_instance=commands.app,
29
+ typer_instance=commands.app.create_instance(),
16
30
  )
@@ -1,3 +1,17 @@
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
+
1
15
  from __future__ import annotations
2
16
 
3
17
  from abc import ABC, abstractmethod
@@ -1,3 +1,17 @@
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
+
1
15
  from __future__ import annotations
2
16
 
3
17
  from pathlib import Path
@@ -14,6 +28,7 @@ from snowflake.cli.api.project.util import (
14
28
  unquote_identifier,
15
29
  )
16
30
  from snowflake.cli.api.utils.cursor import find_all_rows
31
+ from snowflake.cli.plugins.nativeapp.artifacts import BundleMap
17
32
  from snowflake.cli.plugins.nativeapp.constants import (
18
33
  ALLOWED_SPECIAL_COMMENTS,
19
34
  COMMENT_COL,
@@ -195,7 +210,7 @@ class NativeAppRunProcessor(NativeAppManager, NativeAppCommandProcessor):
195
210
  policy: PolicyBase,
196
211
  is_interactive: bool,
197
212
  version: Optional[str] = None,
198
- patch: Optional[str] = None,
213
+ patch: Optional[int] = None,
199
214
  ):
200
215
 
201
216
  patch_clause = f"patch {patch}" if patch else ""
@@ -278,11 +293,13 @@ class NativeAppRunProcessor(NativeAppManager, NativeAppCommandProcessor):
278
293
 
279
294
  def process(
280
295
  self,
296
+ bundle_map: BundleMap,
281
297
  policy: PolicyBase,
282
298
  version: Optional[str] = None,
283
- patch: Optional[str] = None,
299
+ patch: Optional[int] = None,
284
300
  from_release_directive: bool = False,
285
301
  is_interactive: bool = False,
302
+ validate: bool = True,
286
303
  *args,
287
304
  **kwargs,
288
305
  ):
@@ -312,5 +329,7 @@ class NativeAppRunProcessor(NativeAppManager, NativeAppCommandProcessor):
312
329
  )
313
330
  return
314
331
 
315
- diff = self.deploy(prune=True, recursive=True)
332
+ diff = self.deploy(
333
+ bundle_map=bundle_map, prune=True, recursive=True, validate=validate
334
+ )
316
335
  self._create_dev_app(diff)
@@ -1,3 +1,17 @@
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
+
1
15
  from __future__ import annotations
2
16
 
3
17
  from pathlib import Path
@@ -1,3 +1,17 @@
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
+
1
15
  from __future__ import annotations
2
16
 
3
17
  import os
@@ -0,0 +1,13 @@
1
+ # Copyright (c) 2024 Snowflake Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
@@ -1,3 +1,17 @@
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
+
1
15
  from __future__ import annotations
2
16
 
3
17
  import logging
@@ -9,7 +23,7 @@ from snowflake.cli.api.cli_global_context import cli_context
9
23
  from snowflake.cli.api.commands.decorators import (
10
24
  with_project_definition,
11
25
  )
12
- from snowflake.cli.api.commands.snow_typer import SnowTyper
26
+ from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
13
27
  from snowflake.cli.api.output.types import CommandResult, MessageResult, QueryResult
14
28
  from snowflake.cli.plugins.nativeapp.common_flags import ForceOption, InteractiveOption
15
29
  from snowflake.cli.plugins.nativeapp.policy import (
@@ -23,7 +37,7 @@ from snowflake.cli.plugins.nativeapp.version.version_processor import (
23
37
  NativeAppVersionDropProcessor,
24
38
  )
25
39
 
26
- app = SnowTyper(
40
+ app = SnowTyperFactory(
27
41
  name="version",
28
42
  help="Manages versions defined in an application package",
29
43
  )
@@ -38,7 +52,7 @@ def create(
38
52
  None,
39
53
  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.""",
40
54
  ),
41
- patch: Optional[str] = typer.Option(
55
+ patch: Optional[int] = typer.Option(
42
56
  None,
43
57
  "--patch",
44
58
  help=f"""The patch number you want to create for an existing version.
@@ -80,8 +94,9 @@ def create(
80
94
  )
81
95
 
82
96
  # We need build_bundle() to (optionally) find version in manifest.yml and create an application package
83
- processor.build_bundle()
97
+ bundle_map = processor.build_bundle()
84
98
  processor.process(
99
+ bundle_map=bundle_map,
85
100
  version=version,
86
101
  patch=patch,
87
102
  policy=policy,
@@ -1,3 +1,17 @@
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
+
1
15
  from __future__ import annotations
2
16
 
3
17
  from pathlib import Path
@@ -14,7 +28,10 @@ from snowflake.cli.api.utils.cursor import (
14
28
  find_all_rows,
15
29
  find_first_row,
16
30
  )
17
- from snowflake.cli.plugins.nativeapp.artifacts import find_version_info_in_manifest_file
31
+ from snowflake.cli.plugins.nativeapp.artifacts import (
32
+ BundleMap,
33
+ find_version_info_in_manifest_file,
34
+ )
18
35
  from snowflake.cli.plugins.nativeapp.constants import VERSION_COL
19
36
  from snowflake.cli.plugins.nativeapp.exceptions import (
20
37
  ApplicationPackageDoesNotExistError,
@@ -117,7 +134,7 @@ class NativeAppVersionCreateProcessor(NativeAppRunProcessor):
117
134
  f"Version {version} created for application package {self.package_name}."
118
135
  )
119
136
 
120
- def add_new_patch_to_version(self, version: str, patch: Optional[str] = None):
137
+ def add_new_patch_to_version(self, version: str, patch: Optional[int] = None):
121
138
  """
122
139
  Add a new patch, optionally a custom one, to an existing version in an application package.
123
140
  """
@@ -148,8 +165,9 @@ class NativeAppVersionCreateProcessor(NativeAppRunProcessor):
148
165
 
149
166
  def process(
150
167
  self,
168
+ bundle_map: BundleMap,
151
169
  version: Optional[str],
152
- patch: Optional[str],
170
+ patch: Optional[int],
153
171
  policy: PolicyBase,
154
172
  git_policy: PolicyBase,
155
173
  is_interactive: bool,
@@ -202,7 +220,11 @@ class NativeAppVersionCreateProcessor(NativeAppRunProcessor):
202
220
 
203
221
  # Upload files from deploy root local folder to the above stage
204
222
  self.sync_deploy_root_with_stage(
205
- self.package_role, prune=True, recursive=True
223
+ bundle_map=bundle_map,
224
+ role=self.package_role,
225
+ prune=True,
226
+ recursive=True,
227
+ stage_fqn=self.stage_fqn,
206
228
  )
207
229
 
208
230
  # Warn if the version exists in a release directive(s)
@@ -0,0 +1,13 @@
1
+ # Copyright (c) 2024 Snowflake Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
@@ -1,18 +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
+
1
15
  import logging
2
16
 
3
17
  import typer
4
18
  from snowflake.cli.api.commands.flags import identifier_argument
5
- from snowflake.cli.api.commands.snow_typer import SnowTyper
6
- from snowflake.cli.api.feature_flags import FeatureFlag
19
+ from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
7
20
  from snowflake.cli.api.output.types import MessageResult
8
21
  from snowflake.cli.plugins.notebook.manager import NotebookManager
9
22
  from snowflake.cli.plugins.notebook.types import NotebookName, NotebookStagePath
10
23
  from typing_extensions import Annotated
11
24
 
12
- app = SnowTyper(
25
+ app = SnowTyperFactory(
13
26
  name="notebook",
14
27
  help="Manages notebooks in Snowflake.",
15
- hidden=FeatureFlag.ENABLE_NOTEBOOKS.is_disabled(),
16
28
  )
17
29
  log = logging.getLogger(__name__)
18
30
 
@@ -1,3 +1,17 @@
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
+
1
15
  from click.exceptions import ClickException
2
16
 
3
17
 
@@ -1,3 +1,17 @@
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
+
1
15
  from pathlib import Path
2
16
  from textwrap import dedent
3
17
 
@@ -1,3 +1,17 @@
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
+
1
15
  from snowflake.cli.api.plugins.command import (
2
16
  SNOWCLI_ROOT_COMMAND_PATH,
3
17
  CommandSpec,
@@ -12,5 +26,5 @@ def command_spec():
12
26
  return CommandSpec(
13
27
  parent_command_path=SNOWCLI_ROOT_COMMAND_PATH,
14
28
  command_type=CommandType.COMMAND_GROUP,
15
- typer_instance=commands.app,
29
+ typer_instance=commands.app.create_instance(),
16
30
  )