snowflake-cli-labs 2.8.0rc1__py3-none-any.whl → 3.0.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.
- snowflake/cli/__about__.py +1 -1
- snowflake/cli/{app → _app}/__main__.py +1 -1
- snowflake/cli/{app → _app}/cli_app.py +12 -12
- snowflake/cli/{app → _app}/commands_registration/builtin_plugins.py +13 -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 → _app}/snow_connector.py +6 -6
- snowflake/cli/{app → _app}/telemetry.py +4 -5
- snowflake/cli/{plugins → _plugins}/connection/commands.py +22 -5
- 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 +32 -20
- snowflake/cli/{plugins → _plugins}/git/manager.py +6 -5
- snowflake/cli/{plugins → _plugins}/git/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 +14 -0
- snowflake/cli/_plugins/nativeapp/bundle_context.py +31 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/artifact_processor.py +3 -3
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/compiler.py +16 -18
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/setup/native_app_setup_processor.py +24 -28
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/extension_function_utils.py +4 -4
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/python_processor.py +20 -24
- snowflake/cli/{plugins → _plugins}/nativeapp/commands.py +171 -42
- snowflake/cli/{plugins → _plugins}/nativeapp/common_flags.py +1 -1
- snowflake/cli/{plugins → _plugins}/nativeapp/init.py +1 -1
- snowflake/cli/_plugins/nativeapp/manager.py +601 -0
- snowflake/cli/{plugins/connection → _plugins/nativeapp}/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/nativeapp/project_model.py +34 -11
- snowflake/cli/{plugins → _plugins}/nativeapp/run_processor.py +25 -23
- snowflake/cli/{plugins → _plugins}/nativeapp/teardown_processor.py +8 -8
- snowflake/cli/{plugins → _plugins}/nativeapp/v2_conversions/v2_to_v1_decorator.py +47 -28
- snowflake/cli/{plugins → _plugins}/nativeapp/version/commands.py +15 -12
- snowflake/cli/{plugins → _plugins}/nativeapp/version/version_processor.py +22 -20
- snowflake/cli/{plugins → _plugins}/notebook/commands.py +8 -6
- snowflake/cli/{plugins → _plugins}/notebook/manager.py +14 -14
- snowflake/cli/{plugins → _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 +7 -6
- snowflake/cli/{plugins → _plugins}/object/plugin_spec.py +1 -1
- snowflake/cli/_plugins/snowpark/commands.py +510 -0
- snowflake/cli/_plugins/snowpark/common.py +252 -0
- snowflake/cli/{plugins → _plugins}/snowpark/models.py +0 -7
- snowflake/cli/{plugins → _plugins}/snowpark/package/anaconda_packages.py +1 -1
- 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/nativeapp → _plugins/snowpark}/plugin_spec.py +1 -1
- 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 +19 -15
- 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 +8 -6
- snowflake/cli/{plugins → _plugins}/stage/plugin_spec.py +1 -1
- snowflake/cli/_plugins/stage/utils.py +54 -0
- snowflake/cli/_plugins/streamlit/commands.py +242 -0
- snowflake/cli/{plugins → _plugins}/streamlit/manager.py +47 -70
- snowflake/cli/_plugins/streamlit/plugin_spec.py +30 -0
- snowflake/cli/_plugins/workspace/action_context.py +11 -0
- snowflake/cli/_plugins/workspace/commands.py +113 -0
- snowflake/cli/_plugins/workspace/manager.py +57 -0
- snowflake/cli/{plugins → _plugins}/workspace/plugin_spec.py +1 -1
- snowflake/cli/api/cli_global_context.py +34 -7
- snowflake/cli/api/commands/common.py +25 -0
- snowflake/cli/api/commands/decorators.py +4 -3
- snowflake/cli/api/commands/experimental_behaviour.py +2 -3
- snowflake/cli/api/commands/flags.py +73 -174
- snowflake/cli/api/commands/overrideable_parameter.py +143 -0
- snowflake/cli/api/commands/snow_typer.py +5 -4
- snowflake/cli/api/commands/typer_pre_execute.py +3 -3
- snowflake/cli/api/commands/utils.py +18 -0
- snowflake/cli/api/config.py +1 -1
- snowflake/cli/api/console/abc.py +5 -2
- snowflake/cli/api/entities/application_entity.py +12 -0
- snowflake/cli/api/entities/application_package_entity.py +260 -0
- snowflake/cli/api/entities/common.py +47 -0
- snowflake/cli/api/entities/snowpark_entity.py +29 -0
- snowflake/cli/api/entities/streamlit_entity.py +12 -0
- snowflake/cli/api/entities/utils.py +321 -0
- snowflake/cli/api/exceptions.py +19 -3
- snowflake/cli/api/feature_flags.py +2 -1
- snowflake/cli/api/identifiers.py +41 -9
- snowflake/cli/api/project/definition.py +13 -5
- snowflake/cli/api/project/definition_manager.py +12 -1
- snowflake/cli/api/project/project_verification.py +3 -3
- snowflake/cli/api/project/schemas/entities/{application_entity.py → application_entity_model.py} +21 -9
- snowflake/cli/api/project/schemas/entities/{application_package_entity.py → application_package_entity_model.py} +26 -15
- snowflake/cli/api/project/schemas/entities/common.py +80 -6
- snowflake/cli/api/project/schemas/entities/entities.py +38 -8
- snowflake/cli/api/project/schemas/entities/snowpark_entity.py +176 -0
- snowflake/cli/api/project/schemas/entities/streamlit_entity_model.py +73 -0
- snowflake/cli/api/project/schemas/identifier_model.py +10 -1
- snowflake/cli/api/project/schemas/native_app/application.py +8 -9
- snowflake/cli/api/project/schemas/native_app/package.py +7 -1
- snowflake/cli/api/project/schemas/project_definition.py +97 -23
- snowflake/cli/api/project/schemas/updatable_model.py +11 -3
- snowflake/cli/api/project/util.py +23 -6
- snowflake/cli/api/rendering/jinja.py +28 -8
- snowflake/cli/api/rendering/sql_templates.py +41 -12
- snowflake/cli/api/secure_path.py +3 -0
- snowflake/cli/api/sql_execution.py +35 -19
- snowflake/cli/api/utils/definition_rendering.py +14 -2
- {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-3.0.0rc0.dist-info}/METADATA +12 -12
- snowflake_cli_labs-3.0.0rc0.dist-info/RECORD +234 -0
- snowflake_cli_labs-3.0.0rc0.dist-info/entry_points.txt +2 -0
- snowflake/cli/api/commands/project_initialisation.py +0 -65
- snowflake/cli/app/build_and_push.sh +0 -8
- snowflake/cli/plugins/nativeapp/manager.py +0 -823
- 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/commands.py +0 -186
- snowflake/cli/plugins/streamlit/plugin_spec.py +0 -30
- snowflake/cli/plugins/workspace/commands.py +0 -35
- snowflake/cli/templates/default_snowpark/.gitignore +0 -4
- snowflake/cli/templates/default_snowpark/app/__init__.py +0 -0
- 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/{app → _app}/api_impl/__init__.py +0 -0
- /snowflake/cli/{app → _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/{app → _app}/dev/__init__.py +0 -0
- /snowflake/cli/{app → _app}/dev/commands_structure.py +0 -0
- /snowflake/cli/{app → _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/{plugins → _plugins}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/connection/__init__.py +0 -0
- /snowflake/cli/{plugins → _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 → _plugins}/init/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/sandbox.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/setup/setup_driver.py.source +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/callback_source.py.jinja +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/models.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/constants.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/exceptions.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/feature_flags.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/policy.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/utils.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/version/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/notebook/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/notebook/exceptions.py +0 -0
- /snowflake/cli/{plugins → _plugins}/object/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/object/common.py +0 -0
- /snowflake/cli/{plugins → _plugins}/snowpark/__init__.py +0 -0
- /snowflake/cli/{plugins → _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 → _plugins}/spcs/compute_pool/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/spcs/image_registry/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/spcs/image_registry/manager.py +0 -0
- /snowflake/cli/{plugins → _plugins}/spcs/image_repository/__init__.py +0 -0
- /snowflake/cli/{plugins/spcs/jobs → _plugins/spcs/services}/__init__.py +0 -0
- /snowflake/cli/{plugins/spcs/services → _plugins/sql}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/sql/snowsql_templating.py +0 -0
- /snowflake/cli/{plugins/sql → _plugins/stage}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/stage/md5.py +0 -0
- /snowflake/cli/{plugins/stage → _plugins/streamlit}/__init__.py +0 -0
- /snowflake/cli/{plugins/streamlit → _plugins/workspace}/__init__.py +0 -0
- /snowflake/cli/{plugins/workspace → api/project/schemas/entities}/__init__.py +0 -0
- {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-3.0.0rc0.dist-info}/WHEEL +0 -0
- {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-3.0.0rc0.dist-info}/licenses/LICENSE +0 -0
|
@@ -19,15 +19,15 @@ from pathlib import Path
|
|
|
19
19
|
from typing import List, Optional
|
|
20
20
|
|
|
21
21
|
import yaml
|
|
22
|
-
from snowflake.cli.
|
|
23
|
-
from snowflake.cli.
|
|
24
|
-
from snowflake.cli.api.sql_execution import SqlExecutionMixin
|
|
25
|
-
from snowflake.cli.plugins.object.common import Tag
|
|
26
|
-
from snowflake.cli.plugins.spcs.common import (
|
|
22
|
+
from snowflake.cli._plugins.object.common import Tag
|
|
23
|
+
from snowflake.cli._plugins.spcs.common import (
|
|
27
24
|
NoPropertiesProvidedError,
|
|
28
25
|
handle_object_already_exists,
|
|
29
26
|
strip_empty_lines,
|
|
30
27
|
)
|
|
28
|
+
from snowflake.cli.api.constants import DEFAULT_SIZE_LIMIT_MB, ObjectType
|
|
29
|
+
from snowflake.cli.api.secure_path import SecurePath
|
|
30
|
+
from snowflake.cli.api.sql_execution import SqlExecutionMixin
|
|
31
31
|
from snowflake.connector.cursor import SnowflakeCursor
|
|
32
32
|
from snowflake.connector.errors import ProgrammingError
|
|
33
33
|
|
|
@@ -85,6 +85,44 @@ class ServiceManager(SqlExecutionMixin):
|
|
|
85
85
|
except ProgrammingError as e:
|
|
86
86
|
handle_object_already_exists(e, ObjectType.SERVICE, service_name)
|
|
87
87
|
|
|
88
|
+
def execute_job(
|
|
89
|
+
self,
|
|
90
|
+
job_service_name: str,
|
|
91
|
+
compute_pool: str,
|
|
92
|
+
spec_path: Path,
|
|
93
|
+
external_access_integrations: Optional[List[str]],
|
|
94
|
+
query_warehouse: Optional[str],
|
|
95
|
+
comment: Optional[str],
|
|
96
|
+
) -> SnowflakeCursor:
|
|
97
|
+
spec = self._read_yaml(spec_path)
|
|
98
|
+
query = f"""\
|
|
99
|
+
EXECUTE JOB SERVICE
|
|
100
|
+
IN COMPUTE POOL {compute_pool}
|
|
101
|
+
FROM SPECIFICATION $$
|
|
102
|
+
{spec}
|
|
103
|
+
$$
|
|
104
|
+
NAME = {job_service_name}
|
|
105
|
+
""".splitlines()
|
|
106
|
+
|
|
107
|
+
if external_access_integrations:
|
|
108
|
+
external_access_integration_list = ",".join(
|
|
109
|
+
f"{e}" for e in external_access_integrations
|
|
110
|
+
)
|
|
111
|
+
query.append(
|
|
112
|
+
f"EXTERNAL_ACCESS_INTEGRATIONS = ({external_access_integration_list})"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
if query_warehouse:
|
|
116
|
+
query.append(f"QUERY_WAREHOUSE = {query_warehouse}")
|
|
117
|
+
|
|
118
|
+
if comment:
|
|
119
|
+
query.append(f"COMMENT = {comment}")
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
return self._execute_query(strip_empty_lines(query))
|
|
123
|
+
except ProgrammingError as e:
|
|
124
|
+
handle_object_already_exists(e, ObjectType.SERVICE, job_service_name)
|
|
125
|
+
|
|
88
126
|
def _read_yaml(self, path: Path) -> str:
|
|
89
127
|
# TODO(aivanou): Add validation towards schema
|
|
90
128
|
with SecurePath(path).open("r", read_file_limit_mb=DEFAULT_SIZE_LIMIT_MB) as fh:
|
|
@@ -17,43 +17,46 @@ from __future__ import annotations
|
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
from typing import List, Optional
|
|
19
19
|
|
|
20
|
-
import
|
|
20
|
+
from snowflake.cli._plugins.sql.manager import SqlManager
|
|
21
21
|
from snowflake.cli.api.commands.decorators import with_project_definition
|
|
22
22
|
from snowflake.cli.api.commands.flags import (
|
|
23
|
-
parse_key_value_variables,
|
|
24
23
|
variables_option,
|
|
25
24
|
)
|
|
25
|
+
from snowflake.cli.api.commands.overrideable_parameter import OverrideableOption
|
|
26
26
|
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
27
|
+
from snowflake.cli.api.commands.utils import parse_key_value_variables
|
|
27
28
|
from snowflake.cli.api.output.types import CommandResult, MultipleResults, QueryResult
|
|
28
|
-
from snowflake.cli.plugins.sql.manager import SqlManager
|
|
29
29
|
|
|
30
30
|
# simple Typer with defaults because it won't become a command group as it contains only one command
|
|
31
31
|
app = SnowTyperFactory()
|
|
32
32
|
|
|
33
|
+
SOURCE_EXCLUSIVE_OPTIONS_NAMES = ["query", "files", "std_in"]
|
|
34
|
+
|
|
35
|
+
SourceOption = OverrideableOption(
|
|
36
|
+
mutually_exclusive=SOURCE_EXCLUSIVE_OPTIONS_NAMES, show_default=False
|
|
37
|
+
)
|
|
38
|
+
|
|
33
39
|
|
|
34
40
|
@app.command(name="sql", requires_connection=True, no_args_is_help=True)
|
|
35
41
|
@with_project_definition(is_optional=True)
|
|
36
42
|
def execute_sql(
|
|
37
|
-
query: Optional[str] =
|
|
38
|
-
None,
|
|
39
|
-
"--query",
|
|
40
|
-
"-q",
|
|
43
|
+
query: Optional[str] = SourceOption(
|
|
44
|
+
default=None,
|
|
45
|
+
param_decls=["--query", "-q"],
|
|
41
46
|
help="Query to execute.",
|
|
42
47
|
),
|
|
43
|
-
files: Optional[List[Path]] =
|
|
44
|
-
|
|
45
|
-
"--filename",
|
|
46
|
-
"-f",
|
|
48
|
+
files: Optional[List[Path]] = SourceOption(
|
|
49
|
+
default=[],
|
|
50
|
+
param_decls=["--filename", "-f"],
|
|
47
51
|
exists=True,
|
|
48
52
|
file_okay=True,
|
|
49
53
|
dir_okay=False,
|
|
50
54
|
readable=True,
|
|
51
55
|
help="File to execute.",
|
|
52
56
|
),
|
|
53
|
-
std_in: Optional[bool] =
|
|
54
|
-
False,
|
|
55
|
-
"--stdin",
|
|
56
|
-
"-i",
|
|
57
|
+
std_in: Optional[bool] = SourceOption(
|
|
58
|
+
default=False,
|
|
59
|
+
param_decls=["--stdin", "-i"],
|
|
57
60
|
help="Read the query from standard input. Use it when piping input to this command.",
|
|
58
61
|
),
|
|
59
62
|
data_override: List[str] = variables_option(
|
|
@@ -73,6 +76,7 @@ def execute_sql(
|
|
|
73
76
|
The command supports variable substitution that happens on client-side. Both &VARIABLE or &{ VARIABLE }
|
|
74
77
|
syntax are supported.
|
|
75
78
|
"""
|
|
79
|
+
|
|
76
80
|
data = {}
|
|
77
81
|
if data_override:
|
|
78
82
|
data = {v.key: v.value for v in parse_key_value_variables(data_override)}
|
|
@@ -22,10 +22,10 @@ from typing import Dict, Iterable, List, Tuple
|
|
|
22
22
|
|
|
23
23
|
from click import ClickException, UsageError
|
|
24
24
|
from jinja2 import UndefinedError
|
|
25
|
+
from snowflake.cli._plugins.sql.snowsql_templating import transpile_snowsql_templates
|
|
25
26
|
from snowflake.cli.api.rendering.sql_templates import snowflake_sql_jinja_render
|
|
26
27
|
from snowflake.cli.api.secure_path import UNLIMITED, SecurePath
|
|
27
28
|
from snowflake.cli.api.sql_execution import SqlExecutionMixin, VerboseCursor
|
|
28
|
-
from snowflake.cli.plugins.sql.snowsql_templating import transpile_snowsql_templates
|
|
29
29
|
from snowflake.connector.cursor import SnowflakeCursor
|
|
30
30
|
from snowflake.connector.util_text import split_statements
|
|
31
31
|
|
|
@@ -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.sql 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.sql import commands
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@plugin_hook_impl
|
|
@@ -21,16 +21,29 @@ from typing import List, Optional
|
|
|
21
21
|
|
|
22
22
|
import click
|
|
23
23
|
import typer
|
|
24
|
-
from snowflake.cli.
|
|
24
|
+
from snowflake.cli._plugins.object.command_aliases import (
|
|
25
|
+
add_object_command_aliases,
|
|
26
|
+
scope_option,
|
|
27
|
+
)
|
|
28
|
+
from snowflake.cli._plugins.stage.diff import (
|
|
29
|
+
DiffResult,
|
|
30
|
+
compute_stage_diff,
|
|
31
|
+
)
|
|
32
|
+
from snowflake.cli._plugins.stage.manager import StageManager
|
|
33
|
+
from snowflake.cli._plugins.stage.utils import print_diff_to_console
|
|
34
|
+
from snowflake.cli.api.cli_global_context import get_cli_context
|
|
35
|
+
from snowflake.cli.api.commands.common import OnErrorType
|
|
25
36
|
from snowflake.cli.api.commands.flags import (
|
|
26
37
|
ExecuteVariablesOption,
|
|
27
38
|
OnErrorOption,
|
|
28
39
|
PatternOption,
|
|
40
|
+
identifier_argument,
|
|
29
41
|
like_option,
|
|
30
42
|
)
|
|
31
43
|
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
32
44
|
from snowflake.cli.api.console import cli_console
|
|
33
45
|
from snowflake.cli.api.constants import ObjectType
|
|
46
|
+
from snowflake.cli.api.identifiers import FQN
|
|
34
47
|
from snowflake.cli.api.output.formats import OutputFormat
|
|
35
48
|
from snowflake.cli.api.output.types import (
|
|
36
49
|
CollectionResult,
|
|
@@ -40,23 +53,13 @@ from snowflake.cli.api.output.types import (
|
|
|
40
53
|
SingleQueryResult,
|
|
41
54
|
)
|
|
42
55
|
from snowflake.cli.api.utils.path_utils import is_stage_path
|
|
43
|
-
from snowflake.cli.plugins.object.command_aliases import (
|
|
44
|
-
add_object_command_aliases,
|
|
45
|
-
scope_option,
|
|
46
|
-
)
|
|
47
|
-
from snowflake.cli.plugins.stage.diff import (
|
|
48
|
-
DiffResult,
|
|
49
|
-
compute_stage_diff,
|
|
50
|
-
print_diff_to_console,
|
|
51
|
-
)
|
|
52
|
-
from snowflake.cli.plugins.stage.manager import OnErrorType, StageManager
|
|
53
56
|
|
|
54
57
|
app = SnowTyperFactory(
|
|
55
58
|
name="stage",
|
|
56
59
|
help="Manages stages.",
|
|
57
60
|
)
|
|
58
61
|
|
|
59
|
-
StageNameArgument =
|
|
62
|
+
StageNameArgument = identifier_argument(sf_object="stage", example="@my_stage")
|
|
60
63
|
|
|
61
64
|
add_object_command_aliases(
|
|
62
65
|
app=app,
|
|
@@ -142,17 +145,17 @@ def copy(
|
|
|
142
145
|
|
|
143
146
|
|
|
144
147
|
@app.command("create", requires_connection=True)
|
|
145
|
-
def stage_create(stage_name:
|
|
148
|
+
def stage_create(stage_name: FQN = StageNameArgument, **options) -> CommandResult:
|
|
146
149
|
"""
|
|
147
150
|
Creates a named stage if it does not already exist.
|
|
148
151
|
"""
|
|
149
|
-
cursor = StageManager().create(
|
|
152
|
+
cursor = StageManager().create(fqn=stage_name)
|
|
150
153
|
return SingleQueryResult(cursor)
|
|
151
154
|
|
|
152
155
|
|
|
153
156
|
@app.command("remove", requires_connection=True)
|
|
154
157
|
def stage_remove(
|
|
155
|
-
stage_name:
|
|
158
|
+
stage_name: FQN = StageNameArgument,
|
|
156
159
|
file_name: str = typer.Argument(
|
|
157
160
|
...,
|
|
158
161
|
help="Name of the file to remove.",
|
|
@@ -164,7 +167,7 @@ def stage_remove(
|
|
|
164
167
|
Removes a file from a stage.
|
|
165
168
|
"""
|
|
166
169
|
|
|
167
|
-
cursor = StageManager().remove(stage_name=stage_name, path=file_name)
|
|
170
|
+
cursor = StageManager().remove(stage_name=stage_name.identifier, path=file_name)
|
|
168
171
|
return SingleQueryResult(cursor)
|
|
169
172
|
|
|
170
173
|
|
|
@@ -186,7 +189,7 @@ def stage_diff(
|
|
|
186
189
|
diff: DiffResult = compute_stage_diff(
|
|
187
190
|
local_root=Path(folder_name), stage_fqn=stage_name
|
|
188
191
|
)
|
|
189
|
-
if
|
|
192
|
+
if get_cli_context().output_format == OutputFormat.JSON:
|
|
190
193
|
return ObjectResult(diff.to_dict())
|
|
191
194
|
else:
|
|
192
195
|
print_diff_to_console(diff)
|
|
@@ -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
|
|
|
@@ -168,7 +168,9 @@ class StageManager(SqlExecutionMixin):
|
|
|
168
168
|
self._python_exe_procedure = None
|
|
169
169
|
|
|
170
170
|
@staticmethod
|
|
171
|
-
def get_standard_stage_prefix(name: str) -> str:
|
|
171
|
+
def get_standard_stage_prefix(name: str | FQN) -> str:
|
|
172
|
+
if isinstance(name, FQN):
|
|
173
|
+
name = name.identifier
|
|
172
174
|
# Handle embedded stages
|
|
173
175
|
if name.startswith("snow://") or name.startswith("@"):
|
|
174
176
|
return name
|
|
@@ -300,8 +302,8 @@ class StageManager(SqlExecutionMixin):
|
|
|
300
302
|
quoted_stage_name = self.quote_stage_name(f"{stage_name}{path}")
|
|
301
303
|
return self._execute_query(f"remove {quoted_stage_name}")
|
|
302
304
|
|
|
303
|
-
def create(self,
|
|
304
|
-
query = f"create stage if not exists {
|
|
305
|
+
def create(self, fqn: FQN, comment: Optional[str] = None) -> SnowflakeCursor:
|
|
306
|
+
query = f"create stage if not exists {fqn.sql_identifier}"
|
|
305
307
|
if comment:
|
|
306
308
|
query += f" comment='{comment}'"
|
|
307
309
|
return 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)
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
# Copyright (c) 2024 Snowflake Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import logging
|
|
18
|
+
from pathlib import Path
|
|
19
|
+
from typing import Dict
|
|
20
|
+
|
|
21
|
+
import click
|
|
22
|
+
import typer
|
|
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.api.cli_global_context import get_cli_context
|
|
30
|
+
from snowflake.cli.api.commands.decorators import (
|
|
31
|
+
with_experimental_behaviour,
|
|
32
|
+
with_project_definition,
|
|
33
|
+
)
|
|
34
|
+
from snowflake.cli.api.commands.flags import (
|
|
35
|
+
ReplaceOption,
|
|
36
|
+
entity_argument,
|
|
37
|
+
identifier_argument,
|
|
38
|
+
like_option,
|
|
39
|
+
)
|
|
40
|
+
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
41
|
+
from snowflake.cli.api.constants import ObjectType
|
|
42
|
+
from snowflake.cli.api.exceptions import NoProjectDefinitionError
|
|
43
|
+
from snowflake.cli.api.identifiers import FQN
|
|
44
|
+
from snowflake.cli.api.output.types import (
|
|
45
|
+
CommandResult,
|
|
46
|
+
MessageResult,
|
|
47
|
+
SingleQueryResult,
|
|
48
|
+
)
|
|
49
|
+
from snowflake.cli.api.project.schemas.entities.streamlit_entity_model import (
|
|
50
|
+
StreamlitEntityModel,
|
|
51
|
+
)
|
|
52
|
+
from snowflake.cli.api.project.schemas.project_definition import (
|
|
53
|
+
ProjectDefinition,
|
|
54
|
+
ProjectDefinitionV2,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
app = SnowTyperFactory(
|
|
58
|
+
name="streamlit",
|
|
59
|
+
help="Manages a Streamlit app in Snowflake.",
|
|
60
|
+
)
|
|
61
|
+
log = logging.getLogger(__name__)
|
|
62
|
+
|
|
63
|
+
StreamlitNameArgument = identifier_argument(
|
|
64
|
+
sf_object="Streamlit app", example="my_streamlit"
|
|
65
|
+
)
|
|
66
|
+
OpenOption = typer.Option(
|
|
67
|
+
False,
|
|
68
|
+
"--open",
|
|
69
|
+
help="Whether to open the Streamlit app in a browser.",
|
|
70
|
+
is_flag=True,
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
add_object_command_aliases(
|
|
75
|
+
app=app,
|
|
76
|
+
object_type=ObjectType.STREAMLIT,
|
|
77
|
+
name_argument=StreamlitNameArgument,
|
|
78
|
+
like_option=like_option(
|
|
79
|
+
help_example='`list --like "my%"` lists all streamlit apps that begin with “my”'
|
|
80
|
+
),
|
|
81
|
+
scope_option=scope_option(help_example="`list --in database my_db`"),
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
@app.command("share", requires_connection=True)
|
|
86
|
+
def streamlit_share(
|
|
87
|
+
name: FQN = StreamlitNameArgument,
|
|
88
|
+
to_role: str = typer.Argument(
|
|
89
|
+
...,
|
|
90
|
+
help="Role with which to share the Streamlit app.",
|
|
91
|
+
show_default=False,
|
|
92
|
+
),
|
|
93
|
+
**options,
|
|
94
|
+
) -> CommandResult:
|
|
95
|
+
"""
|
|
96
|
+
Shares a Streamlit app with another role.
|
|
97
|
+
"""
|
|
98
|
+
cursor = StreamlitManager().share(streamlit_name=name, to_role=to_role)
|
|
99
|
+
return SingleQueryResult(cursor)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def _default_file_callback(param_name: str):
|
|
103
|
+
from click.core import ParameterSource # type: ignore
|
|
104
|
+
|
|
105
|
+
def _check_file_exists_if_not_default(ctx: click.Context, value):
|
|
106
|
+
if (
|
|
107
|
+
ctx.get_parameter_source(param_name) != ParameterSource.DEFAULT # type: ignore
|
|
108
|
+
and value
|
|
109
|
+
and not Path(value).exists()
|
|
110
|
+
):
|
|
111
|
+
raise ClickException(f"Provided file {value} does not exist")
|
|
112
|
+
return Path(value)
|
|
113
|
+
|
|
114
|
+
return _check_file_exists_if_not_default
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
@app.command("deploy", requires_connection=True)
|
|
118
|
+
@with_project_definition()
|
|
119
|
+
@with_experimental_behaviour()
|
|
120
|
+
def streamlit_deploy(
|
|
121
|
+
replace: bool = ReplaceOption(
|
|
122
|
+
help="Replace the Streamlit app if it already exists."
|
|
123
|
+
),
|
|
124
|
+
entity_id: str = entity_argument("streamlit"),
|
|
125
|
+
open_: bool = OpenOption,
|
|
126
|
+
**options,
|
|
127
|
+
) -> CommandResult:
|
|
128
|
+
"""
|
|
129
|
+
Deploys a Streamlit app defined in the project definition file (snowflake.yml). By default, the command uploads
|
|
130
|
+
environment.yml and any other pages or folders, if present. If you don’t specify a stage name, the `streamlit`
|
|
131
|
+
stage is used. If the specified stage does not exist, the command creates it. If multiple Streamlits are defined
|
|
132
|
+
in snowflake.yml and no entity_id is provided then command will raise an error.
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
cli_context = get_cli_context()
|
|
136
|
+
pd = cli_context.project_definition
|
|
137
|
+
if not pd.meets_version_requirement("2"):
|
|
138
|
+
if not pd.streamlit:
|
|
139
|
+
raise NoProjectDefinitionError(
|
|
140
|
+
project_type="streamlit", project_root=cli_context.project_root
|
|
141
|
+
)
|
|
142
|
+
pd = migrate_v1_streamlit_to_v2(pd)
|
|
143
|
+
|
|
144
|
+
streamlits: Dict[str, StreamlitEntityModel] = pd.get_entities_by_type(
|
|
145
|
+
entity_type="streamlit"
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
if not streamlits:
|
|
149
|
+
raise NoProjectDefinitionError(
|
|
150
|
+
project_type="streamlit", project_root=cli_context.project_root
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
if entity_id and entity_id not in streamlits:
|
|
154
|
+
raise UsageError(f"No '{entity_id}' entity in project definition file.")
|
|
155
|
+
|
|
156
|
+
if len(streamlits.keys()) == 1:
|
|
157
|
+
entity_id = list(streamlits.keys())[0]
|
|
158
|
+
|
|
159
|
+
if entity_id is None:
|
|
160
|
+
raise UsageError(
|
|
161
|
+
"Multiple Streamlit apps found. Please provide entity id for the operation."
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
# Get first streamlit
|
|
165
|
+
streamlit: StreamlitEntityModel = streamlits[entity_id]
|
|
166
|
+
url = StreamlitManager().deploy(streamlit=streamlit, replace=replace)
|
|
167
|
+
|
|
168
|
+
if open_:
|
|
169
|
+
typer.launch(url)
|
|
170
|
+
|
|
171
|
+
return MessageResult(f"Streamlit successfully deployed and available under {url}")
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
def migrate_v1_streamlit_to_v2(pd: ProjectDefinition):
|
|
175
|
+
default_env_file = "environment.yml"
|
|
176
|
+
default_pages_dir = "pages"
|
|
177
|
+
|
|
178
|
+
# Process env file
|
|
179
|
+
environment_file = pd.streamlit.env_file
|
|
180
|
+
if environment_file and not Path(environment_file).exists():
|
|
181
|
+
raise ClickException(f"Provided file {environment_file} does not exist")
|
|
182
|
+
elif environment_file is None and Path(default_env_file).exists():
|
|
183
|
+
environment_file = default_env_file
|
|
184
|
+
# Process pages dir
|
|
185
|
+
pages_dir = pd.streamlit.pages_dir
|
|
186
|
+
if pages_dir and not Path(pages_dir).exists():
|
|
187
|
+
raise ClickException(f"Provided file {pages_dir} does not exist")
|
|
188
|
+
elif pages_dir is None and Path(default_pages_dir).exists():
|
|
189
|
+
pages_dir = default_pages_dir
|
|
190
|
+
|
|
191
|
+
# Build V2 definition
|
|
192
|
+
artifacts = [
|
|
193
|
+
pd.streamlit.main_file,
|
|
194
|
+
environment_file,
|
|
195
|
+
pages_dir,
|
|
196
|
+
]
|
|
197
|
+
artifacts = [a for a in artifacts if a is not None]
|
|
198
|
+
if pd.streamlit.additional_source_files:
|
|
199
|
+
artifacts.extend(pd.streamlit.additional_source_files)
|
|
200
|
+
|
|
201
|
+
identifier = {"name": pd.streamlit.name}
|
|
202
|
+
if pd.streamlit.schema_name:
|
|
203
|
+
identifier["schema"] = pd.streamlit.schema_name
|
|
204
|
+
if pd.streamlit.database:
|
|
205
|
+
identifier["database"] = pd.streamlit.database
|
|
206
|
+
|
|
207
|
+
if pd.streamlit.name.startswith("<%") and pd.streamlit.name.endswith("%>"):
|
|
208
|
+
streamlit_name = "streamlit_entity_1"
|
|
209
|
+
else:
|
|
210
|
+
streamlit_name = pd.streamlit.name
|
|
211
|
+
|
|
212
|
+
data = {
|
|
213
|
+
"definition_version": "2",
|
|
214
|
+
"entities": {
|
|
215
|
+
streamlit_name: {
|
|
216
|
+
"type": "streamlit",
|
|
217
|
+
"identifier": identifier,
|
|
218
|
+
"title": pd.streamlit.title,
|
|
219
|
+
"query_warehouse": pd.streamlit.query_warehouse,
|
|
220
|
+
"main_file": str(pd.streamlit.main_file),
|
|
221
|
+
"pages_dir": str(pd.streamlit.pages_dir),
|
|
222
|
+
"stage": pd.streamlit.stage,
|
|
223
|
+
"artifacts": artifacts,
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
}
|
|
227
|
+
if hasattr(pd, "env") and pd.env:
|
|
228
|
+
data["env"] = {k: v for k, v in pd.env.items()}
|
|
229
|
+
return ProjectDefinitionV2(**data)
|
|
230
|
+
|
|
231
|
+
|
|
232
|
+
@app.command("get-url", requires_connection=True)
|
|
233
|
+
def get_url(
|
|
234
|
+
name: FQN = StreamlitNameArgument,
|
|
235
|
+
open_: bool = OpenOption,
|
|
236
|
+
**options,
|
|
237
|
+
):
|
|
238
|
+
"""Returns a URL to the specified Streamlit app"""
|
|
239
|
+
url = StreamlitManager().get_url(streamlit_name=name)
|
|
240
|
+
if open_:
|
|
241
|
+
typer.launch(url)
|
|
242
|
+
return MessageResult(url)
|