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
|
@@ -1,307 +0,0 @@
|
|
|
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 re
|
|
18
|
-
from typing import Dict, List, Optional, Set, Union
|
|
19
|
-
|
|
20
|
-
from snowflake.cli.api.constants import ObjectType
|
|
21
|
-
from snowflake.cli.api.identifiers import FQN
|
|
22
|
-
from snowflake.cli.api.project.schemas.snowpark.callable import (
|
|
23
|
-
FunctionSchema,
|
|
24
|
-
ProcedureSchema,
|
|
25
|
-
)
|
|
26
|
-
from snowflake.cli.api.sql_execution import SqlExecutionMixin
|
|
27
|
-
from snowflake.cli.plugins.snowpark.models import Requirement
|
|
28
|
-
from snowflake.cli.plugins.snowpark.package_utils import (
|
|
29
|
-
generate_deploy_stage_name,
|
|
30
|
-
)
|
|
31
|
-
from snowflake.connector.cursor import SnowflakeCursor
|
|
32
|
-
|
|
33
|
-
DEFAULT_RUNTIME = "3.8"
|
|
34
|
-
FunctionOrProcedure = Union[FunctionSchema, ProcedureSchema]
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def check_if_replace_is_required(
|
|
38
|
-
object_type: ObjectType,
|
|
39
|
-
current_state,
|
|
40
|
-
handler: str,
|
|
41
|
-
return_type: str,
|
|
42
|
-
snowflake_dependencies: List[str],
|
|
43
|
-
external_access_integrations: List[str],
|
|
44
|
-
imports: List[str],
|
|
45
|
-
stage_artifact_file: str,
|
|
46
|
-
runtime_ver: Optional[str] = None,
|
|
47
|
-
execute_as_caller: Optional[bool] = None,
|
|
48
|
-
) -> bool:
|
|
49
|
-
import logging
|
|
50
|
-
|
|
51
|
-
log = logging.getLogger(__name__)
|
|
52
|
-
resource_json = _convert_resource_details_to_dict(current_state)
|
|
53
|
-
old_dependencies = resource_json["packages"]
|
|
54
|
-
log.info(
|
|
55
|
-
"Found %d defined Anaconda packages in deployed %s...",
|
|
56
|
-
len(old_dependencies),
|
|
57
|
-
object_type,
|
|
58
|
-
)
|
|
59
|
-
log.info("Checking if app configuration has changed...")
|
|
60
|
-
|
|
61
|
-
if _snowflake_dependencies_differ(old_dependencies, snowflake_dependencies):
|
|
62
|
-
log.info(
|
|
63
|
-
"Found difference of package requirements. Replacing the %s.", object_type
|
|
64
|
-
)
|
|
65
|
-
return True
|
|
66
|
-
|
|
67
|
-
if set(external_access_integrations) != set(
|
|
68
|
-
resource_json.get("external_access_integrations", [])
|
|
69
|
-
):
|
|
70
|
-
log.info(
|
|
71
|
-
"Found difference of external access integrations. Replacing the %s.",
|
|
72
|
-
object_type,
|
|
73
|
-
)
|
|
74
|
-
return True
|
|
75
|
-
|
|
76
|
-
if (
|
|
77
|
-
resource_json["handler"].lower() != handler.lower()
|
|
78
|
-
or _sql_to_python_return_type_mapper(resource_json["returns"]).lower()
|
|
79
|
-
!= return_type.lower()
|
|
80
|
-
):
|
|
81
|
-
log.info(
|
|
82
|
-
"Return type or handler types do not match. Replacing the %s.", object_type
|
|
83
|
-
)
|
|
84
|
-
return True
|
|
85
|
-
|
|
86
|
-
if _compare_imports(resource_json, imports, stage_artifact_file):
|
|
87
|
-
log.info("Imports do not match. Replacing the %s", object_type)
|
|
88
|
-
return True
|
|
89
|
-
|
|
90
|
-
if runtime_ver is not None and runtime_ver != resource_json.get(
|
|
91
|
-
"runtime_version", "RUNTIME_NOT_SET"
|
|
92
|
-
):
|
|
93
|
-
log.info("Runtime versions do not match. Replacing the %s", object_type)
|
|
94
|
-
return True
|
|
95
|
-
|
|
96
|
-
if execute_as_caller is not None and (
|
|
97
|
-
resource_json.get("execute as", "OWNER")
|
|
98
|
-
!= ("CALLER" if execute_as_caller else "OWNER")
|
|
99
|
-
):
|
|
100
|
-
log.info(
|
|
101
|
-
"Execute as caller settings do not match. Replacing the %s", object_type
|
|
102
|
-
)
|
|
103
|
-
return True
|
|
104
|
-
|
|
105
|
-
return False
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
def _convert_resource_details_to_dict(function_details: SnowflakeCursor) -> dict:
|
|
109
|
-
import json
|
|
110
|
-
|
|
111
|
-
function_dict = {}
|
|
112
|
-
json_properties = ["packages", "installed_packages"]
|
|
113
|
-
for function in function_details:
|
|
114
|
-
if function[0] in json_properties:
|
|
115
|
-
function_dict[function[0]] = json.loads(
|
|
116
|
-
function[1].replace("'", '"'),
|
|
117
|
-
)
|
|
118
|
-
else:
|
|
119
|
-
function_dict[function[0]] = function[1]
|
|
120
|
-
return function_dict
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def _snowflake_dependencies_differ(
|
|
124
|
-
old_dependencies: List[str], new_dependencies: List[str]
|
|
125
|
-
) -> bool:
|
|
126
|
-
def _standardize(packages: List[str]) -> Set[str]:
|
|
127
|
-
return set(
|
|
128
|
-
Requirement.parse_line(package).name_and_version for package in packages
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
return _standardize(old_dependencies) != _standardize(new_dependencies)
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
def _sql_to_python_return_type_mapper(resource_return_type: str) -> str:
|
|
135
|
-
"""
|
|
136
|
-
Some of the Python data types get converted to SQL types, when function/procedure is created.
|
|
137
|
-
So, to properly compare types, we use mapping based on:
|
|
138
|
-
https://docs.snowflake.com/en/developer-guide/udf-stored-procedure-data-type-mapping#sql-python-data-type-mappings
|
|
139
|
-
|
|
140
|
-
Mind you, this only applies to cases, in which Snowflake accepts Python type as return.
|
|
141
|
-
Ie. if function returns list, it has to be declared as 'array' during creation,
|
|
142
|
-
therefore any conversion is not necessary
|
|
143
|
-
"""
|
|
144
|
-
mapping = {
|
|
145
|
-
"number(38,0)": "int",
|
|
146
|
-
"timestamp_ntz(9)": "datetime",
|
|
147
|
-
"timestamp_tz(9)": "datetime",
|
|
148
|
-
"varchar(16777216)": "string",
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
return mapping.get(resource_return_type.lower(), resource_return_type.lower())
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
class SnowparkObjectManager(SqlExecutionMixin):
|
|
155
|
-
@property
|
|
156
|
-
def _object_type(self) -> ObjectType:
|
|
157
|
-
raise NotImplementedError()
|
|
158
|
-
|
|
159
|
-
@property
|
|
160
|
-
def _object_execute(self):
|
|
161
|
-
raise NotImplementedError()
|
|
162
|
-
|
|
163
|
-
def create(self, *args, **kwargs) -> SnowflakeCursor:
|
|
164
|
-
raise NotImplementedError()
|
|
165
|
-
|
|
166
|
-
def execute(self, execution_identifier: str) -> SnowflakeCursor:
|
|
167
|
-
return self._execute_query(f"{self._object_execute} {execution_identifier}")
|
|
168
|
-
|
|
169
|
-
@staticmethod
|
|
170
|
-
def artifact_stage_path(identifier: str):
|
|
171
|
-
return generate_deploy_stage_name(identifier).lower()
|
|
172
|
-
|
|
173
|
-
def create_query(
|
|
174
|
-
self,
|
|
175
|
-
identifier: UdfSprocIdentifier,
|
|
176
|
-
return_type: str,
|
|
177
|
-
handler: str,
|
|
178
|
-
artifact_file: str,
|
|
179
|
-
packages: List[str],
|
|
180
|
-
imports: List[str],
|
|
181
|
-
external_access_integrations: Optional[List[str]] = None,
|
|
182
|
-
secrets: Optional[Dict[str, str]] = None,
|
|
183
|
-
runtime: Optional[str] = None,
|
|
184
|
-
execute_as_caller: bool = False,
|
|
185
|
-
) -> str:
|
|
186
|
-
imports.append(artifact_file)
|
|
187
|
-
imports = [f"'{x}'" for x in imports]
|
|
188
|
-
packages_list = ",".join(f"'{p}'" for p in packages)
|
|
189
|
-
|
|
190
|
-
query = [
|
|
191
|
-
f"create or replace {self._object_type.value.sf_name} {identifier.identifier_for_sql}",
|
|
192
|
-
f"copy grants",
|
|
193
|
-
f"returns {return_type}",
|
|
194
|
-
"language python",
|
|
195
|
-
f"runtime_version={runtime or DEFAULT_RUNTIME}",
|
|
196
|
-
f"imports=({', '.join(imports)})",
|
|
197
|
-
f"handler='{handler}'",
|
|
198
|
-
f"packages=({packages_list})",
|
|
199
|
-
]
|
|
200
|
-
|
|
201
|
-
if external_access_integrations:
|
|
202
|
-
external_access_integration_name = ",".join(
|
|
203
|
-
f"{e}" for e in external_access_integrations
|
|
204
|
-
)
|
|
205
|
-
query.append(
|
|
206
|
-
f"external_access_integrations=({external_access_integration_name})"
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
if secrets:
|
|
210
|
-
secret_name = ",".join(f"'{k}'={v}" for k, v in secrets.items())
|
|
211
|
-
query.append(f"secrets=({secret_name})")
|
|
212
|
-
|
|
213
|
-
if execute_as_caller:
|
|
214
|
-
query.append("execute as caller")
|
|
215
|
-
|
|
216
|
-
return "\n".join(query)
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
def _is_signature_type_a_string(sig_type: str) -> bool:
|
|
220
|
-
return sig_type.lower() in ["string", "varchar"]
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
class UdfSprocIdentifier:
|
|
224
|
-
def __init__(self, identifier: FQN, arg_names, arg_types, arg_defaults):
|
|
225
|
-
self._identifier = identifier
|
|
226
|
-
self._arg_names = arg_names
|
|
227
|
-
self._arg_types = arg_types
|
|
228
|
-
self._arg_defaults = arg_defaults
|
|
229
|
-
|
|
230
|
-
def _identifier_from_signature(self, sig: List[str], for_sql: bool = False):
|
|
231
|
-
signature = self._comma_join(sig)
|
|
232
|
-
id_ = self._identifier.sql_identifier if for_sql else self._identifier
|
|
233
|
-
return f"{id_}({signature})"
|
|
234
|
-
|
|
235
|
-
@staticmethod
|
|
236
|
-
def _comma_join(*args):
|
|
237
|
-
return ", ".join(*args)
|
|
238
|
-
|
|
239
|
-
@property
|
|
240
|
-
def identifier_with_arg_names(self):
|
|
241
|
-
return self._identifier_from_signature(self._arg_names)
|
|
242
|
-
|
|
243
|
-
@property
|
|
244
|
-
def identifier_with_arg_types(self):
|
|
245
|
-
return self._identifier_from_signature(self._arg_types)
|
|
246
|
-
|
|
247
|
-
@property
|
|
248
|
-
def identifier_with_arg_names_types(self):
|
|
249
|
-
sig = [f"{n} {t}" for n, t in zip(self._arg_names, self._arg_types)]
|
|
250
|
-
return self._identifier_from_signature(sig)
|
|
251
|
-
|
|
252
|
-
@property
|
|
253
|
-
def identifier_with_arg_names_types_defaults(self):
|
|
254
|
-
return self._identifier_from_signature(self._full_signature())
|
|
255
|
-
|
|
256
|
-
def _full_signature(self):
|
|
257
|
-
sig = []
|
|
258
|
-
for name, _type, _default in zip(
|
|
259
|
-
self._arg_names, self._arg_types, self._arg_defaults
|
|
260
|
-
):
|
|
261
|
-
s = f"{name} {_type}"
|
|
262
|
-
if _default:
|
|
263
|
-
if _is_signature_type_a_string(_type):
|
|
264
|
-
_default = f"'{_default}'"
|
|
265
|
-
s += f" default {_default}"
|
|
266
|
-
sig.append(s)
|
|
267
|
-
return sig
|
|
268
|
-
|
|
269
|
-
@property
|
|
270
|
-
def identifier_for_sql(self):
|
|
271
|
-
return self._identifier_from_signature(self._full_signature(), for_sql=True)
|
|
272
|
-
|
|
273
|
-
@classmethod
|
|
274
|
-
def from_definition(cls, udf_sproc: FunctionOrProcedure):
|
|
275
|
-
names = []
|
|
276
|
-
types = []
|
|
277
|
-
defaults = []
|
|
278
|
-
if udf_sproc.signature and udf_sproc.signature != "null":
|
|
279
|
-
for arg in udf_sproc.signature:
|
|
280
|
-
names.append(arg.name)
|
|
281
|
-
types.append(arg.arg_type)
|
|
282
|
-
defaults.append(arg.default)
|
|
283
|
-
|
|
284
|
-
identifier = FQN.from_identifier_model(udf_sproc).using_context()
|
|
285
|
-
return cls(identifier, names, types, defaults)
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
def _compare_imports(
|
|
289
|
-
resource_json: dict, imports: List[str], artifact_file: str
|
|
290
|
-
) -> bool:
|
|
291
|
-
pattern = re.compile(r"(?:\[@?\w+_\w+\.)?(\w+(?:/\w+)+\.\w+)(?:\])?")
|
|
292
|
-
|
|
293
|
-
project_imports = {
|
|
294
|
-
imp
|
|
295
|
-
for import_string in [*imports, artifact_file]
|
|
296
|
-
for imp in pattern.findall(import_string.lower())
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if "imports" not in resource_json.keys():
|
|
300
|
-
object_imports = set()
|
|
301
|
-
else:
|
|
302
|
-
object_imports = {
|
|
303
|
-
imp.lower()
|
|
304
|
-
for imp in pattern.findall(resource_json.get("imports", "").lower())
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
return project_imports != object_imports
|
|
@@ -1,109 +0,0 @@
|
|
|
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, Optional
|
|
19
|
-
|
|
20
|
-
from snowflake.cli.api.constants import ObjectType
|
|
21
|
-
from snowflake.cli.plugins.snowpark.common import (
|
|
22
|
-
SnowparkObjectManager,
|
|
23
|
-
UdfSprocIdentifier,
|
|
24
|
-
)
|
|
25
|
-
from snowflake.connector.cursor import SnowflakeCursor
|
|
26
|
-
|
|
27
|
-
log = logging.getLogger(__name__)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
class FunctionManager(SnowparkObjectManager):
|
|
31
|
-
@property
|
|
32
|
-
def _object_type(self):
|
|
33
|
-
return ObjectType.FUNCTION
|
|
34
|
-
|
|
35
|
-
@property
|
|
36
|
-
def _object_execute(self):
|
|
37
|
-
return "select"
|
|
38
|
-
|
|
39
|
-
def create_or_replace(
|
|
40
|
-
self,
|
|
41
|
-
identifier: UdfSprocIdentifier,
|
|
42
|
-
return_type: str,
|
|
43
|
-
handler: str,
|
|
44
|
-
artifact_file: str,
|
|
45
|
-
packages: List[str],
|
|
46
|
-
imports: List[str],
|
|
47
|
-
external_access_integrations: Optional[List[str]] = None,
|
|
48
|
-
secrets: Optional[Dict[str, str]] = None,
|
|
49
|
-
runtime: Optional[str] = None,
|
|
50
|
-
) -> SnowflakeCursor:
|
|
51
|
-
log.debug(
|
|
52
|
-
"Creating function %s using @%s",
|
|
53
|
-
identifier.identifier_with_arg_names_types_defaults,
|
|
54
|
-
artifact_file,
|
|
55
|
-
)
|
|
56
|
-
query = self.create_query(
|
|
57
|
-
identifier,
|
|
58
|
-
return_type,
|
|
59
|
-
handler,
|
|
60
|
-
artifact_file,
|
|
61
|
-
packages,
|
|
62
|
-
imports,
|
|
63
|
-
external_access_integrations,
|
|
64
|
-
secrets,
|
|
65
|
-
runtime,
|
|
66
|
-
)
|
|
67
|
-
return self._execute_query(query)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
class ProcedureManager(SnowparkObjectManager):
|
|
71
|
-
@property
|
|
72
|
-
def _object_type(self):
|
|
73
|
-
return ObjectType.PROCEDURE
|
|
74
|
-
|
|
75
|
-
@property
|
|
76
|
-
def _object_execute(self):
|
|
77
|
-
return "call"
|
|
78
|
-
|
|
79
|
-
def create_or_replace(
|
|
80
|
-
self,
|
|
81
|
-
identifier: UdfSprocIdentifier,
|
|
82
|
-
return_type: str,
|
|
83
|
-
handler: str,
|
|
84
|
-
artifact_file: str,
|
|
85
|
-
packages: List[str],
|
|
86
|
-
imports: List[str],
|
|
87
|
-
external_access_integrations: Optional[List[str]] = None,
|
|
88
|
-
secrets: Optional[Dict[str, str]] = None,
|
|
89
|
-
runtime: Optional[str] = None,
|
|
90
|
-
execute_as_caller: bool = False,
|
|
91
|
-
) -> SnowflakeCursor:
|
|
92
|
-
log.debug(
|
|
93
|
-
"Creating procedure %s using @%s",
|
|
94
|
-
identifier.identifier_with_arg_names_types_defaults,
|
|
95
|
-
artifact_file,
|
|
96
|
-
)
|
|
97
|
-
query = self.create_query(
|
|
98
|
-
identifier,
|
|
99
|
-
return_type,
|
|
100
|
-
handler,
|
|
101
|
-
artifact_file,
|
|
102
|
-
packages,
|
|
103
|
-
imports,
|
|
104
|
-
external_access_integrations,
|
|
105
|
-
secrets,
|
|
106
|
-
runtime,
|
|
107
|
-
execute_as_caller,
|
|
108
|
-
)
|
|
109
|
-
return self._execute_query(query)
|
|
@@ -1,30 +0,0 @@
|
|
|
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.api.plugins.command import (
|
|
16
|
-
SNOWCLI_ROOT_COMMAND_PATH,
|
|
17
|
-
CommandSpec,
|
|
18
|
-
CommandType,
|
|
19
|
-
plugin_hook_impl,
|
|
20
|
-
)
|
|
21
|
-
from snowflake.cli.plugins.snowpark import commands
|
|
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
|
-
)
|
|
@@ -1,65 +0,0 @@
|
|
|
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 dataclasses import dataclass
|
|
16
|
-
|
|
17
|
-
from snowflake.cli.api.project.schemas.snowpark.snowpark import Snowpark
|
|
18
|
-
from snowflake.cli.api.secure_path import SecurePath
|
|
19
|
-
|
|
20
|
-
_DEFINED_REQUIREMENTS = "requirements.txt"
|
|
21
|
-
_REQUIREMENTS_SNOWFLAKE = "requirements.snowflake.txt"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
@dataclass
|
|
25
|
-
class SnowparkPackagePaths:
|
|
26
|
-
source: SecurePath
|
|
27
|
-
artifact_file: SecurePath
|
|
28
|
-
defined_requirements_file: SecurePath = SecurePath(_DEFINED_REQUIREMENTS)
|
|
29
|
-
snowflake_requirements_file: SecurePath = SecurePath(_REQUIREMENTS_SNOWFLAKE)
|
|
30
|
-
|
|
31
|
-
@classmethod
|
|
32
|
-
def for_snowpark_project(
|
|
33
|
-
cls, project_root: SecurePath, snowpark_project_definition: Snowpark
|
|
34
|
-
) -> "SnowparkPackagePaths":
|
|
35
|
-
defined_source_path = SecurePath(snowpark_project_definition.src)
|
|
36
|
-
return cls(
|
|
37
|
-
source=cls._get_snowpark_project_source_absolute_path(
|
|
38
|
-
project_root=project_root,
|
|
39
|
-
defined_source_path=defined_source_path,
|
|
40
|
-
),
|
|
41
|
-
artifact_file=cls._get_snowpark_project_artifact_absolute_path(
|
|
42
|
-
project_root=project_root,
|
|
43
|
-
defined_source_path=defined_source_path,
|
|
44
|
-
),
|
|
45
|
-
defined_requirements_file=project_root / _DEFINED_REQUIREMENTS,
|
|
46
|
-
snowflake_requirements_file=project_root / _REQUIREMENTS_SNOWFLAKE,
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
@classmethod
|
|
50
|
-
def _get_snowpark_project_source_absolute_path(
|
|
51
|
-
cls, project_root: SecurePath, defined_source_path: SecurePath
|
|
52
|
-
) -> SecurePath:
|
|
53
|
-
if defined_source_path.path.is_absolute():
|
|
54
|
-
return defined_source_path
|
|
55
|
-
return SecurePath((project_root / defined_source_path.path).path.resolve())
|
|
56
|
-
|
|
57
|
-
@classmethod
|
|
58
|
-
def _get_snowpark_project_artifact_absolute_path(
|
|
59
|
-
cls, project_root: SecurePath, defined_source_path: SecurePath
|
|
60
|
-
) -> SecurePath:
|
|
61
|
-
source_path = cls._get_snowpark_project_source_absolute_path(
|
|
62
|
-
project_root=project_root, defined_source_path=defined_source_path
|
|
63
|
-
)
|
|
64
|
-
artifact_file = project_root / (source_path.path.name + ".zip")
|
|
65
|
-
return artifact_file
|
|
@@ -1,78 +0,0 @@
|
|
|
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
|
-
import sys
|
|
16
|
-
from pathlib import Path
|
|
17
|
-
|
|
18
|
-
import typer
|
|
19
|
-
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
20
|
-
from snowflake.cli.api.output.types import CommandResult, SingleQueryResult
|
|
21
|
-
from snowflake.cli.plugins.spcs.common import print_log_lines
|
|
22
|
-
from snowflake.cli.plugins.spcs.jobs.manager import JobManager
|
|
23
|
-
|
|
24
|
-
app = SnowTyperFactory(
|
|
25
|
-
name="job",
|
|
26
|
-
help="Manages Snowpark jobs.",
|
|
27
|
-
is_hidden=lambda: True,
|
|
28
|
-
)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
@app.command(requires_connection=True)
|
|
32
|
-
def create(
|
|
33
|
-
compute_pool: str = typer.Option(
|
|
34
|
-
..., "--compute-pool", help="Name of the pool in which to run the job."
|
|
35
|
-
),
|
|
36
|
-
spec_path: Path = typer.Option(
|
|
37
|
-
...,
|
|
38
|
-
"--spec-path",
|
|
39
|
-
help="Path to the `spec.yaml` file containing the job details.",
|
|
40
|
-
file_okay=True,
|
|
41
|
-
dir_okay=False,
|
|
42
|
-
exists=True,
|
|
43
|
-
),
|
|
44
|
-
**options,
|
|
45
|
-
) -> CommandResult:
|
|
46
|
-
"""
|
|
47
|
-
Creates a job to run in a compute pool.
|
|
48
|
-
"""
|
|
49
|
-
cursor = JobManager().create(compute_pool=compute_pool, spec_path=spec_path)
|
|
50
|
-
return SingleQueryResult(cursor)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
@app.command(requires_connection=True)
|
|
54
|
-
def logs(
|
|
55
|
-
identifier: str = typer.Argument(..., help="Job id"),
|
|
56
|
-
container_name: str = typer.Option(
|
|
57
|
-
..., "--container-name", help="Name of the container."
|
|
58
|
-
),
|
|
59
|
-
**options,
|
|
60
|
-
):
|
|
61
|
-
"""
|
|
62
|
-
Retrieves local logs from a job container.
|
|
63
|
-
"""
|
|
64
|
-
results = JobManager().logs(job_name=identifier, container_name=container_name)
|
|
65
|
-
cursor = results.fetchone()
|
|
66
|
-
logs = next(iter(cursor)).split("\n")
|
|
67
|
-
print_log_lines(sys.stdout, identifier, "0", logs)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
@app.command(requires_connection=True)
|
|
71
|
-
def status(
|
|
72
|
-
identifier: str = typer.Argument(..., help="ID of the job."), **options
|
|
73
|
-
) -> CommandResult:
|
|
74
|
-
"""
|
|
75
|
-
Returns the status of a named Snowpark Container Services job.
|
|
76
|
-
"""
|
|
77
|
-
cursor = JobManager().status(job_name=identifier)
|
|
78
|
-
return SingleQueryResult(cursor)
|
|
@@ -1,53 +0,0 @@
|
|
|
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 pathlib import Path
|
|
16
|
-
|
|
17
|
-
from snowflake.cli.api.constants import DEFAULT_SIZE_LIMIT_MB
|
|
18
|
-
from snowflake.cli.api.secure_path import SecurePath
|
|
19
|
-
from snowflake.cli.api.sql_execution import SqlExecutionMixin
|
|
20
|
-
from snowflake.connector.cursor import SnowflakeCursor
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class JobManager(SqlExecutionMixin):
|
|
24
|
-
def create(self, compute_pool: str, spec_path: Path) -> SnowflakeCursor:
|
|
25
|
-
spec = self._read_yaml(spec_path)
|
|
26
|
-
return self._execute_schema_query(
|
|
27
|
-
f"""\
|
|
28
|
-
EXECUTE SERVICE
|
|
29
|
-
IN COMPUTE POOL {compute_pool}
|
|
30
|
-
FROM SPECIFICATION $$
|
|
31
|
-
{spec}
|
|
32
|
-
$$
|
|
33
|
-
"""
|
|
34
|
-
)
|
|
35
|
-
|
|
36
|
-
def _read_yaml(self, path: Path) -> str:
|
|
37
|
-
# TODO(aivanou): Add validation towards schema
|
|
38
|
-
# TODO(aivanou): Combine this with service manager
|
|
39
|
-
import json
|
|
40
|
-
|
|
41
|
-
import yaml
|
|
42
|
-
|
|
43
|
-
with SecurePath(path).open("r", read_file_limit_mb=DEFAULT_SIZE_LIMIT_MB) as fh:
|
|
44
|
-
data = yaml.safe_load(fh)
|
|
45
|
-
return json.dumps(data)
|
|
46
|
-
|
|
47
|
-
def status(self, job_name: str) -> SnowflakeCursor:
|
|
48
|
-
return self._execute_query(f"CALL SYSTEM$GET_JOB_STATUS('{job_name}')")
|
|
49
|
-
|
|
50
|
-
def logs(self, job_name: str, container_name: str):
|
|
51
|
-
return self._execute_query(
|
|
52
|
-
f"call SYSTEM$GET_JOB_LOGS('{job_name}', '{container_name}')"
|
|
53
|
-
)
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2024 Snowflake Inc.
|
|
2
|
-
#
|
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
-
# you may not use this file except in compliance with the License.
|
|
5
|
-
# You may obtain a copy of the License at
|
|
6
|
-
#
|
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
-
#
|
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
-
# See the License for the specific language governing permissions and
|
|
13
|
-
# limitations under the License.
|
|
@@ -1,30 +0,0 @@
|
|
|
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.api.plugins.command import (
|
|
16
|
-
SNOWCLI_ROOT_COMMAND_PATH,
|
|
17
|
-
CommandSpec,
|
|
18
|
-
CommandType,
|
|
19
|
-
plugin_hook_impl,
|
|
20
|
-
)
|
|
21
|
-
from snowflake.cli.plugins.streamlit import commands
|
|
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
|
-
)
|