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