snowflake-cli 3.4.1__py3-none-any.whl → 3.6.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 (73) hide show
  1. snowflake/cli/__about__.py +13 -1
  2. snowflake/cli/_app/cli_app.py +1 -10
  3. snowflake/cli/_app/commands_registration/builtin_plugins.py +7 -1
  4. snowflake/cli/_app/commands_registration/command_plugins_loader.py +3 -1
  5. snowflake/cli/_app/commands_registration/commands_registration_with_callbacks.py +3 -3
  6. snowflake/cli/_app/printing.py +2 -2
  7. snowflake/cli/_app/snow_connector.py +5 -4
  8. snowflake/cli/_app/telemetry.py +3 -15
  9. snowflake/cli/_app/version_check.py +4 -4
  10. snowflake/cli/_plugins/auth/__init__.py +11 -0
  11. snowflake/cli/_plugins/auth/keypair/__init__.py +0 -0
  12. snowflake/cli/_plugins/auth/keypair/commands.py +151 -0
  13. snowflake/cli/_plugins/auth/keypair/manager.py +331 -0
  14. snowflake/cli/_plugins/auth/keypair/plugin_spec.py +30 -0
  15. snowflake/cli/_plugins/connection/commands.py +79 -5
  16. snowflake/cli/_plugins/helpers/commands.py +3 -4
  17. snowflake/cli/_plugins/nativeapp/entities/application.py +4 -1
  18. snowflake/cli/_plugins/nativeapp/sf_sql_facade.py +33 -6
  19. snowflake/cli/_plugins/notebook/commands.py +3 -4
  20. snowflake/cli/_plugins/object/command_aliases.py +3 -1
  21. snowflake/cli/_plugins/object/manager.py +4 -2
  22. snowflake/cli/_plugins/plugin/commands.py +79 -0
  23. snowflake/cli/_plugins/plugin/manager.py +74 -0
  24. snowflake/cli/_plugins/plugin/plugin_spec.py +30 -0
  25. snowflake/cli/_plugins/project/__init__.py +0 -0
  26. snowflake/cli/_plugins/project/commands.py +173 -0
  27. snowflake/cli/{_app/api_impl/plugin/__init__.py → _plugins/project/feature_flags.py} +9 -0
  28. snowflake/cli/_plugins/project/manager.py +76 -0
  29. snowflake/cli/_plugins/project/plugin_spec.py +30 -0
  30. snowflake/cli/_plugins/project/project_entity_model.py +40 -0
  31. snowflake/cli/_plugins/snowpark/commands.py +2 -1
  32. snowflake/cli/_plugins/spcs/compute_pool/commands.py +70 -10
  33. snowflake/cli/_plugins/spcs/compute_pool/compute_pool_entity.py +8 -0
  34. snowflake/cli/_plugins/spcs/compute_pool/compute_pool_entity_model.py +37 -0
  35. snowflake/cli/_plugins/spcs/compute_pool/manager.py +45 -0
  36. snowflake/cli/_plugins/spcs/image_repository/commands.py +29 -0
  37. snowflake/cli/_plugins/spcs/image_repository/image_repository_entity.py +8 -0
  38. snowflake/cli/_plugins/spcs/image_repository/image_repository_entity_model.py +8 -0
  39. snowflake/cli/_plugins/spcs/image_repository/manager.py +1 -1
  40. snowflake/cli/_plugins/spcs/services/commands.py +53 -0
  41. snowflake/cli/_plugins/spcs/services/manager.py +114 -0
  42. snowflake/cli/_plugins/spcs/services/service_entity.py +6 -0
  43. snowflake/cli/_plugins/spcs/services/service_entity_model.py +45 -0
  44. snowflake/cli/_plugins/spcs/services/service_project_paths.py +15 -0
  45. snowflake/cli/_plugins/sql/manager.py +42 -51
  46. snowflake/cli/_plugins/sql/source_reader.py +230 -0
  47. snowflake/cli/_plugins/stage/manager.py +10 -4
  48. snowflake/cli/_plugins/streamlit/commands.py +9 -24
  49. snowflake/cli/_plugins/streamlit/manager.py +5 -36
  50. snowflake/cli/api/artifacts/upload.py +51 -0
  51. snowflake/cli/api/commands/flags.py +35 -10
  52. snowflake/cli/api/commands/snow_typer.py +12 -0
  53. snowflake/cli/api/commands/utils.py +2 -0
  54. snowflake/cli/api/config.py +15 -10
  55. snowflake/cli/api/constants.py +2 -0
  56. snowflake/cli/api/errno.py +1 -0
  57. snowflake/cli/api/exceptions.py +15 -1
  58. snowflake/cli/api/feature_flags.py +2 -0
  59. snowflake/cli/api/plugins/plugin_config.py +43 -4
  60. snowflake/cli/api/project/definition_helper.py +31 -0
  61. snowflake/cli/api/project/schemas/entities/entities.py +26 -0
  62. snowflake/cli/api/rest_api.py +2 -3
  63. snowflake/cli/{_app → api}/secret.py +4 -1
  64. snowflake/cli/api/secure_path.py +16 -4
  65. snowflake/cli/api/sql_execution.py +7 -3
  66. {snowflake_cli-3.4.1.dist-info → snowflake_cli-3.6.0.dist-info}/METADATA +12 -12
  67. {snowflake_cli-3.4.1.dist-info → snowflake_cli-3.6.0.dist-info}/RECORD +71 -50
  68. snowflake/cli/_app/api_impl/plugin/plugin_config_provider_impl.py +0 -66
  69. snowflake/cli/api/__init__.py +0 -48
  70. /snowflake/cli/{_app/api_impl → _plugins/plugin}/__init__.py +0 -0
  71. {snowflake_cli-3.4.1.dist-info → snowflake_cli-3.6.0.dist-info}/WHEEL +0 -0
  72. {snowflake_cli-3.4.1.dist-info → snowflake_cli-3.6.0.dist-info}/entry_points.txt +0 -0
  73. {snowflake_cli-3.4.1.dist-info → snowflake_cli-3.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,79 @@
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 typing import Dict, List
19
+
20
+ import typer
21
+ from snowflake.cli._plugins.plugin.manager import PluginManager
22
+ from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
23
+ from snowflake.cli.api.output.types import (
24
+ CollectionResult,
25
+ CommandResult,
26
+ MessageResult,
27
+ )
28
+
29
+ log = logging.getLogger(__name__)
30
+
31
+ app = SnowTyperFactory(
32
+ name="plugin",
33
+ help="Plugin management commands.",
34
+ is_hidden=lambda: True,
35
+ )
36
+
37
+
38
+ @app.command(name="enable", requires_connection=False)
39
+ def enable(
40
+ plugin_name: str = typer.Argument(None, help="Plugin name"),
41
+ **options,
42
+ ) -> CommandResult:
43
+ """Enables a plugin with a given name."""
44
+ plugin_manager = PluginManager()
45
+ plugin_manager.assert_plugin_is_installed(plugin_name)
46
+ plugin_manager.enable_plugin(plugin_name)
47
+
48
+ return MessageResult(f"Plugin {plugin_name} successfully enabled.")
49
+
50
+
51
+ @app.command(name="disable", requires_connection=False)
52
+ def disable(
53
+ plugin_name: str = typer.Argument(None, help="Plugin name"),
54
+ **options,
55
+ ) -> CommandResult:
56
+ """Disables a plugin with a given name."""
57
+ plugin_manager = PluginManager()
58
+ plugin_manager.assert_plugin_is_installed(plugin_name)
59
+ plugin_manager.disable_plugin(plugin_name)
60
+
61
+ return MessageResult(f"Plugin {plugin_name} successfully disabled.")
62
+
63
+
64
+ @app.command(name="list", requires_connection=False)
65
+ def list_(
66
+ **options,
67
+ ) -> CommandResult:
68
+ """Lists all installed plugins."""
69
+ plugin_manager = PluginManager()
70
+ result: List[Dict[str, str]] = []
71
+ for plugin_name in sorted(plugin_manager.get_installed_plugin_names()):
72
+ result.append(
73
+ {
74
+ "plugin name": plugin_name,
75
+ "enabled": plugin_manager.is_plugin_enabled(plugin_name),
76
+ }
77
+ )
78
+
79
+ return CollectionResult(result)
@@ -0,0 +1,74 @@
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
+ import importlib
15
+ from typing import List
16
+
17
+ from snowflake.cli.api.config import (
18
+ PLUGIN_ENABLED_KEY,
19
+ PLUGINS_SECTION_PATH,
20
+ config_section_exists,
21
+ get_config_section,
22
+ set_config_value,
23
+ )
24
+ from snowflake.cli.api.exceptions import PluginNotInstalledError
25
+ from snowflake.cli.api.plugins.command import SNOWCLI_COMMAND_PLUGIN_NAMESPACE
26
+ from snowflake.cli.api.plugins.plugin_config import PluginConfigProvider
27
+
28
+
29
+ class PluginManager:
30
+ """
31
+ Manage installation of plugins.
32
+ """
33
+
34
+ def enable_plugin(self, plugin_name: str):
35
+ self._change_plugin_enabled(plugin_name, enable=True)
36
+
37
+ def disable_plugin(self, plugin_name: str):
38
+ self._change_plugin_enabled(plugin_name, enable=False)
39
+
40
+ @staticmethod
41
+ def _change_plugin_enabled(plugin_name: str, enable: bool):
42
+ plugin_config_path = PLUGINS_SECTION_PATH + [plugin_name]
43
+
44
+ if config_section_exists(*plugin_config_path):
45
+ plugin_config = get_config_section(*plugin_config_path)
46
+ elif enable:
47
+ plugin_config = {}
48
+ else:
49
+ # do not add a new plugin config if user wants to disable a plugin which is not configured
50
+ # (plugins are disabled by default)
51
+ return
52
+
53
+ plugin_config[PLUGIN_ENABLED_KEY] = enable
54
+ set_config_value(path=plugin_config_path, value=plugin_config)
55
+
56
+ @staticmethod
57
+ def is_plugin_enabled(plugin_name: str) -> bool:
58
+ return PluginConfigProvider.get_config(plugin_name).is_plugin_enabled
59
+
60
+ def assert_plugin_is_installed(self, plugin_name: str):
61
+ installed_plugins = self.get_installed_plugin_names()
62
+ if plugin_name not in installed_plugins:
63
+ raise PluginNotInstalledError(
64
+ plugin_name, installed_plugins=sorted(installed_plugins)
65
+ )
66
+
67
+ @staticmethod
68
+ def get_installed_plugin_names() -> List[str]:
69
+ return [
70
+ entry_point.name
71
+ for entry_point in importlib.metadata.entry_points(
72
+ group=SNOWCLI_COMMAND_PLUGIN_NAMESPACE
73
+ )
74
+ ]
@@ -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.plugin 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
+ )
File without changes
@@ -0,0 +1,173 @@
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 typing import List, Optional
16
+
17
+ import typer
18
+ from snowflake.cli._plugins.object.command_aliases import add_object_command_aliases
19
+ from snowflake.cli._plugins.object.commands import scope_option
20
+ from snowflake.cli._plugins.project.feature_flags import FeatureFlag
21
+ from snowflake.cli._plugins.project.manager import ProjectManager
22
+ from snowflake.cli._plugins.project.project_entity_model import (
23
+ ProjectEntityModel,
24
+ )
25
+ from snowflake.cli._plugins.stage.manager import StageManager
26
+ from snowflake.cli.api.artifacts.upload import put_files
27
+ from snowflake.cli.api.cli_global_context import get_cli_context
28
+ from snowflake.cli.api.commands.decorators import with_project_definition
29
+ from snowflake.cli.api.commands.flags import (
30
+ entity_argument,
31
+ identifier_argument,
32
+ like_option,
33
+ variables_option,
34
+ )
35
+ from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
36
+ from snowflake.cli.api.commands.utils import get_entity_for_operation
37
+ from snowflake.cli.api.console.console import cli_console
38
+ from snowflake.cli.api.constants import ObjectType
39
+ from snowflake.cli.api.identifiers import FQN
40
+ from snowflake.cli.api.output.types import MessageResult, SingleQueryResult
41
+ from snowflake.cli.api.project.project_paths import ProjectPaths
42
+
43
+ app = SnowTyperFactory(
44
+ name="project",
45
+ help="Manages projects in Snowflake.",
46
+ is_hidden=FeatureFlag.ENABLE_SNOWFLAKE_PROJECTS.is_disabled,
47
+ )
48
+
49
+ project_identifier = identifier_argument(sf_object="project", example="MY_PROJECT")
50
+ version_flag = typer.Option(
51
+ ..., "--version", help="Version of the project to use.", show_default=False
52
+ )
53
+ variables_flag = variables_option(
54
+ 'Variables for the execution context; for example: `-D "<key>=<value>"`.'
55
+ )
56
+
57
+
58
+ add_object_command_aliases(
59
+ app=app,
60
+ object_type=ObjectType.PROJECT,
61
+ name_argument=project_identifier,
62
+ like_option=like_option(
63
+ help_example='`list --like "my%"` lists all projects that begin with “my”'
64
+ ),
65
+ scope_option=scope_option(help_example="`list --in database my_db`"),
66
+ ommit_commands=["drop", "create", "describe"],
67
+ )
68
+
69
+
70
+ @app.command(requires_connection=True)
71
+ def execute(
72
+ identifier: FQN = project_identifier,
73
+ version: str = version_flag,
74
+ variables: Optional[List[str]] = variables_flag,
75
+ **options,
76
+ ):
77
+ """
78
+ Executes a project.
79
+ """
80
+ result = ProjectManager().execute(
81
+ project_name=identifier, version=version, variables=variables
82
+ )
83
+ return SingleQueryResult(result)
84
+
85
+
86
+ @app.command(requires_connection=True)
87
+ def dry_run(
88
+ identifier: FQN = project_identifier,
89
+ version: str = version_flag,
90
+ variables: Optional[List[str]] = variables_flag,
91
+ **options,
92
+ ):
93
+ """
94
+ Validates a project.
95
+ """
96
+ result = ProjectManager().execute(
97
+ project_name=identifier, version=version, dry_run=True, variables=variables
98
+ )
99
+ return SingleQueryResult(result)
100
+
101
+
102
+ @app.command(requires_connection=True)
103
+ @with_project_definition()
104
+ def create_version(
105
+ entity_id: str = entity_argument("project"),
106
+ **options,
107
+ ):
108
+ """
109
+ Upload local files and create a new version of a project using those files. If the stage does not exist, it will be created.
110
+ """
111
+ cli_context = get_cli_context()
112
+ project: ProjectEntityModel = get_entity_for_operation(
113
+ cli_context=cli_context,
114
+ entity_id=entity_id,
115
+ project_definition=cli_context.project_definition,
116
+ entity_type="project",
117
+ )
118
+
119
+ # Sync state
120
+ with cli_console.phase("Syncing project state"):
121
+ stage_name = FQN.from_stage(project.stage)
122
+ sm = StageManager()
123
+
124
+ cli_console.step(f"Creating stage {stage_name}")
125
+ sm.create(fqn=stage_name)
126
+
127
+ put_files(
128
+ project_paths=ProjectPaths(project_root=cli_context.project_root),
129
+ stage_root=project.stage,
130
+ artifacts=project.artifacts,
131
+ )
132
+
133
+ # Create project and version
134
+ with cli_console.phase("Creating project and version"):
135
+ pm = ProjectManager()
136
+ cli_console.step(f"Creating project {project.fqn}")
137
+ pm.create(project_name=project.fqn)
138
+
139
+ cli_console.step(f"Creating version from stage {stage_name}")
140
+ pm.create_version(project_name=project.fqn, stage_name=stage_name)
141
+ return MessageResult(f"Project {project.fqn} deployed.")
142
+
143
+
144
+ @app.command(requires_connection=True)
145
+ @with_project_definition()
146
+ def add_version(
147
+ entity_id: str = entity_argument("project"),
148
+ _from: str = typer.Option(
149
+ ...,
150
+ "--from",
151
+ help="Source stage to create the version from.",
152
+ show_default=False,
153
+ ),
154
+ alias: str
155
+ | None = typer.Option(
156
+ None, "--alias", help="Alias for the version.", show_default=False
157
+ ),
158
+ comment: str
159
+ | None = typer.Option(
160
+ None, "--comment", help="Version comment.", show_default=False
161
+ ),
162
+ **options,
163
+ ):
164
+ """Adds a new version to a project using existing sources from provided stage path."""
165
+
166
+ pm = ProjectManager()
167
+ pm.add_version(
168
+ project_name=entity_id,
169
+ from_stage=_from,
170
+ alias=alias,
171
+ comment=comment,
172
+ )
173
+ return MessageResult("Version added.")
@@ -11,3 +11,12 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
+
15
+ from enum import unique
16
+
17
+ from snowflake.cli.api.feature_flags import BooleanFlag, FeatureFlagMixin
18
+
19
+
20
+ @unique
21
+ class FeatureFlag(FeatureFlagMixin):
22
+ ENABLE_SNOWFLAKE_PROJECTS = BooleanFlag("ENABLE_SNOWFLAKE_PROJECTS", False)
@@ -0,0 +1,76 @@
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 textwrap import dedent
15
+ from typing import List
16
+
17
+ from snowflake.cli._plugins.stage.manager import StageManager
18
+ from snowflake.cli.api.commands.utils import parse_key_value_variables
19
+ from snowflake.cli.api.identifiers import FQN
20
+ from snowflake.cli.api.sql_execution import SqlExecutionMixin
21
+ from snowflake.cli.api.stage_path import StagePath
22
+
23
+
24
+ class ProjectManager(SqlExecutionMixin):
25
+ def execute(
26
+ self,
27
+ project_name: FQN,
28
+ version: str | None = None,
29
+ variables: List[str] | None = None,
30
+ dry_run: bool = False,
31
+ ):
32
+ query = f"EXECUTE PROJECT {project_name.sql_identifier}"
33
+ if variables:
34
+ query += StageManager.parse_execute_variables(
35
+ parse_key_value_variables(variables)
36
+ )
37
+ if version:
38
+ query += f" WITH VERSION {version}"
39
+ if dry_run:
40
+ query += " DRY_RUN=TRUE"
41
+ return self.execute_query(query=query)
42
+
43
+ def create(
44
+ self,
45
+ project_name: FQN,
46
+ ) -> str:
47
+ queries = dedent(f"CREATE PROJECT IF NOT EXISTS {project_name.sql_identifier}")
48
+ return self.execute_query(query=queries)
49
+
50
+ def create_version(self, project_name: FQN, stage_name: FQN):
51
+ return self.add_version(
52
+ project_name=project_name,
53
+ from_stage=StagePath.from_stage_str(stage_name).absolute_path(
54
+ at_prefix=True
55
+ ),
56
+ )
57
+
58
+ def add_version(
59
+ self,
60
+ project_name: str | FQN,
61
+ from_stage: str,
62
+ alias: str | None = None,
63
+ comment: str | None = None,
64
+ ):
65
+ project_name = (
66
+ project_name
67
+ if isinstance(project_name, FQN)
68
+ else FQN.from_string(project_name)
69
+ )
70
+ query = f"ALTER PROJECT {project_name.identifier} ADD VERSION"
71
+ if alias:
72
+ query += f" IF NOT EXIST {alias}"
73
+ query += f" FROM {from_stage}"
74
+ if comment:
75
+ query += f" COMMENT = '{comment}'"
76
+ return self.execute_query(query=query)
@@ -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.project 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,40 @@
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 typing import Literal, Optional, TypeVar
17
+
18
+ from pydantic import Field
19
+ from snowflake.cli.api.entities.common import EntityBase, attach_spans_to_entity_actions
20
+ from snowflake.cli.api.project.schemas.entities.common import (
21
+ EntityModelBaseWithArtifacts,
22
+ )
23
+ from snowflake.cli.api.project.schemas.updatable_model import (
24
+ DiscriminatorField,
25
+ )
26
+
27
+ T = TypeVar("T")
28
+
29
+
30
+ class ProjectEntityModel(EntityModelBaseWithArtifacts):
31
+ type: Literal["project"] = DiscriminatorField() # noqa: A003
32
+ stage: Optional[str] = Field(
33
+ title="Stage in which the project artifacts will be stored", default=None
34
+ )
35
+ main_file: Optional[str] = Field(title="Path to the main file of the project")
36
+
37
+
38
+ @attach_spans_to_entity_actions(entity_name="project")
39
+ class ProjectEntity(EntityBase[ProjectEntityModel]):
40
+ """Placeholder for project entity"""
@@ -129,7 +129,8 @@ LikeOption = like_option(
129
129
  @with_project_definition()
130
130
  def deploy(
131
131
  replace: bool = ReplaceOption(
132
- help="Replaces procedure or function if there were changes in the definition."
132
+ help="Replaces procedure or function if there were changes in the definition. It only uploads new and "
133
+ "overwrites existing files, but does not remove any files already on the stage."
133
134
  ),
134
135
  force_replace: bool = ForceReplaceOption(),
135
136
  **options,