snowflake-cli-labs 2.8.0rc1__py3-none-any.whl → 2.8.2__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.
- README.md +21 -0
- {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-2.8.2.dist-info}/METADATA +7 -95
- snowflake_cli_labs-2.8.2.dist-info/RECORD +5 -0
- snowflake/cli/__about__.py +0 -17
- snowflake/cli/__init__.py +0 -13
- snowflake/cli/api/__init__.py +0 -48
- snowflake/cli/api/cli_global_context.py +0 -390
- snowflake/cli/api/commands/__init__.py +0 -13
- snowflake/cli/api/commands/alias.py +0 -23
- snowflake/cli/api/commands/decorators.py +0 -354
- snowflake/cli/api/commands/execution_metadata.py +0 -40
- snowflake/cli/api/commands/experimental_behaviour.py +0 -19
- snowflake/cli/api/commands/flags.py +0 -640
- snowflake/cli/api/commands/project_initialisation.py +0 -65
- snowflake/cli/api/commands/snow_typer.py +0 -237
- snowflake/cli/api/commands/typer_pre_execute.py +0 -26
- snowflake/cli/api/config.py +0 -348
- snowflake/cli/api/console/__init__.py +0 -17
- snowflake/cli/api/console/abc.py +0 -89
- snowflake/cli/api/console/console.py +0 -134
- snowflake/cli/api/console/enum.py +0 -17
- snowflake/cli/api/constants.py +0 -79
- snowflake/cli/api/errno.py +0 -27
- snowflake/cli/api/exceptions.py +0 -164
- snowflake/cli/api/feature_flags.py +0 -55
- snowflake/cli/api/identifiers.py +0 -154
- snowflake/cli/api/output/__init__.py +0 -13
- snowflake/cli/api/output/formats.py +0 -20
- snowflake/cli/api/output/types.py +0 -118
- snowflake/cli/api/plugins/__init__.py +0 -13
- snowflake/cli/api/plugins/command/__init__.py +0 -72
- snowflake/cli/api/plugins/command/plugin_hook_specs.py +0 -21
- snowflake/cli/api/plugins/plugin_config.py +0 -32
- snowflake/cli/api/project/__init__.py +0 -13
- snowflake/cli/api/project/definition.py +0 -84
- snowflake/cli/api/project/definition_manager.py +0 -134
- snowflake/cli/api/project/errors.py +0 -56
- snowflake/cli/api/project/project_verification.py +0 -23
- snowflake/cli/api/project/schemas/__init__.py +0 -13
- 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/api/project/schemas/entities/common.py +0 -78
- snowflake/cli/api/project/schemas/entities/entities.py +0 -30
- snowflake/cli/api/project/schemas/identifier_model.py +0 -49
- snowflake/cli/api/project/schemas/native_app/__init__.py +0 -13
- snowflake/cli/api/project/schemas/native_app/application.py +0 -62
- snowflake/cli/api/project/schemas/native_app/native_app.py +0 -93
- snowflake/cli/api/project/schemas/native_app/package.py +0 -78
- snowflake/cli/api/project/schemas/native_app/path_mapping.py +0 -65
- snowflake/cli/api/project/schemas/project_definition.py +0 -199
- snowflake/cli/api/project/schemas/snowpark/__init__.py +0 -13
- snowflake/cli/api/project/schemas/snowpark/argument.py +0 -28
- snowflake/cli/api/project/schemas/snowpark/callable.py +0 -69
- snowflake/cli/api/project/schemas/snowpark/snowpark.py +0 -36
- snowflake/cli/api/project/schemas/streamlit/__init__.py +0 -13
- snowflake/cli/api/project/schemas/streamlit/streamlit.py +0 -46
- snowflake/cli/api/project/schemas/template.py +0 -77
- snowflake/cli/api/project/schemas/updatable_model.py +0 -194
- snowflake/cli/api/project/util.py +0 -261
- snowflake/cli/api/rendering/__init__.py +0 -13
- snowflake/cli/api/rendering/jinja.py +0 -112
- snowflake/cli/api/rendering/project_definition_templates.py +0 -39
- snowflake/cli/api/rendering/project_templates.py +0 -98
- snowflake/cli/api/rendering/sql_templates.py +0 -60
- snowflake/cli/api/rest_api.py +0 -172
- snowflake/cli/api/sanitizers.py +0 -43
- snowflake/cli/api/secure_path.py +0 -362
- snowflake/cli/api/secure_utils.py +0 -29
- snowflake/cli/api/sql_execution.py +0 -260
- snowflake/cli/api/utils/__init__.py +0 -13
- snowflake/cli/api/utils/cursor.py +0 -34
- snowflake/cli/api/utils/definition_rendering.py +0 -383
- snowflake/cli/api/utils/dict_utils.py +0 -73
- snowflake/cli/api/utils/error_handling.py +0 -23
- snowflake/cli/api/utils/graph.py +0 -97
- snowflake/cli/api/utils/models.py +0 -63
- snowflake/cli/api/utils/naming_utils.py +0 -13
- snowflake/cli/api/utils/path_utils.py +0 -36
- snowflake/cli/api/utils/templating_functions.py +0 -144
- snowflake/cli/api/utils/types.py +0 -35
- snowflake/cli/app/__init__.py +0 -22
- snowflake/cli/app/__main__.py +0 -31
- snowflake/cli/app/api_impl/__init__.py +0 -13
- snowflake/cli/app/api_impl/plugin/__init__.py +0 -13
- snowflake/cli/app/api_impl/plugin/plugin_config_provider_impl.py +0 -66
- snowflake/cli/app/build_and_push.sh +0 -8
- snowflake/cli/app/cli_app.py +0 -243
- snowflake/cli/app/commands_registration/__init__.py +0 -33
- snowflake/cli/app/commands_registration/builtin_plugins.py +0 -54
- snowflake/cli/app/commands_registration/command_plugins_loader.py +0 -169
- snowflake/cli/app/commands_registration/commands_registration_with_callbacks.py +0 -105
- snowflake/cli/app/commands_registration/exception_logging.py +0 -26
- snowflake/cli/app/commands_registration/threadsafe.py +0 -48
- snowflake/cli/app/commands_registration/typer_registration.py +0 -153
- snowflake/cli/app/constants.py +0 -19
- snowflake/cli/app/dev/__init__.py +0 -13
- snowflake/cli/app/dev/commands_structure.py +0 -48
- snowflake/cli/app/dev/docs/__init__.py +0 -13
- snowflake/cli/app/dev/docs/commands_docs_generator.py +0 -100
- snowflake/cli/app/dev/docs/generator.py +0 -35
- snowflake/cli/app/dev/docs/project_definition_docs_generator.py +0 -58
- snowflake/cli/app/dev/docs/project_definition_generate_json_schema.py +0 -227
- snowflake/cli/app/dev/docs/template_utils.py +0 -23
- snowflake/cli/app/dev/docs/templates/definition_description.rst.jinja2 +0 -38
- snowflake/cli/app/dev/docs/templates/overview.rst.jinja2 +0 -9
- snowflake/cli/app/dev/docs/templates/usage.rst.jinja2 +0 -57
- snowflake/cli/app/dev/pycharm_remote_debug.py +0 -46
- snowflake/cli/app/loggers.py +0 -199
- snowflake/cli/app/main_typer.py +0 -62
- snowflake/cli/app/printing.py +0 -181
- snowflake/cli/app/snow_connector.py +0 -243
- snowflake/cli/app/telemetry.py +0 -189
- snowflake/cli/plugins/__init__.py +0 -13
- snowflake/cli/plugins/connection/__init__.py +0 -13
- snowflake/cli/plugins/connection/commands.py +0 -330
- snowflake/cli/plugins/connection/plugin_spec.py +0 -30
- snowflake/cli/plugins/connection/util.py +0 -179
- snowflake/cli/plugins/cortex/__init__.py +0 -13
- snowflake/cli/plugins/cortex/commands.py +0 -327
- snowflake/cli/plugins/cortex/constants.py +0 -17
- snowflake/cli/plugins/cortex/manager.py +0 -189
- snowflake/cli/plugins/cortex/plugin_spec.py +0 -30
- snowflake/cli/plugins/cortex/types.py +0 -22
- snowflake/cli/plugins/git/__init__.py +0 -13
- snowflake/cli/plugins/git/commands.py +0 -305
- snowflake/cli/plugins/git/manager.py +0 -96
- snowflake/cli/plugins/git/plugin_spec.py +0 -30
- snowflake/cli/plugins/init/__init__.py +0 -13
- snowflake/cli/plugins/init/commands.py +0 -244
- snowflake/cli/plugins/init/plugin_spec.py +0 -30
- snowflake/cli/plugins/nativeapp/__init__.py +0 -13
- snowflake/cli/plugins/nativeapp/artifacts.py +0 -742
- snowflake/cli/plugins/nativeapp/codegen/__init__.py +0 -13
- snowflake/cli/plugins/nativeapp/codegen/artifact_processor.py +0 -91
- snowflake/cli/plugins/nativeapp/codegen/compiler.py +0 -130
- snowflake/cli/plugins/nativeapp/codegen/sandbox.py +0 -306
- snowflake/cli/plugins/nativeapp/codegen/setup/native_app_setup_processor.py +0 -172
- snowflake/cli/plugins/nativeapp/codegen/setup/setup_driver.py.source +0 -56
- snowflake/cli/plugins/nativeapp/codegen/snowpark/callback_source.py.jinja +0 -181
- snowflake/cli/plugins/nativeapp/codegen/snowpark/extension_function_utils.py +0 -217
- snowflake/cli/plugins/nativeapp/codegen/snowpark/models.py +0 -61
- snowflake/cli/plugins/nativeapp/codegen/snowpark/python_processor.py +0 -528
- snowflake/cli/plugins/nativeapp/commands.py +0 -439
- snowflake/cli/plugins/nativeapp/common_flags.py +0 -44
- snowflake/cli/plugins/nativeapp/constants.py +0 -27
- snowflake/cli/plugins/nativeapp/exceptions.py +0 -122
- snowflake/cli/plugins/nativeapp/feature_flags.py +0 -24
- snowflake/cli/plugins/nativeapp/init.py +0 -345
- snowflake/cli/plugins/nativeapp/manager.py +0 -823
- snowflake/cli/plugins/nativeapp/plugin_spec.py +0 -30
- snowflake/cli/plugins/nativeapp/policy.py +0 -50
- snowflake/cli/plugins/nativeapp/project_model.py +0 -195
- snowflake/cli/plugins/nativeapp/run_processor.py +0 -389
- snowflake/cli/plugins/nativeapp/teardown_processor.py +0 -301
- snowflake/cli/plugins/nativeapp/utils.py +0 -98
- snowflake/cli/plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +0 -135
- snowflake/cli/plugins/nativeapp/version/__init__.py +0 -13
- snowflake/cli/plugins/nativeapp/version/commands.py +0 -170
- snowflake/cli/plugins/nativeapp/version/version_processor.py +0 -362
- snowflake/cli/plugins/notebook/__init__.py +0 -13
- snowflake/cli/plugins/notebook/commands.py +0 -84
- snowflake/cli/plugins/notebook/exceptions.py +0 -20
- snowflake/cli/plugins/notebook/manager.py +0 -71
- snowflake/cli/plugins/notebook/plugin_spec.py +0 -30
- snowflake/cli/plugins/notebook/types.py +0 -16
- snowflake/cli/plugins/object/__init__.py +0 -13
- snowflake/cli/plugins/object/command_aliases.py +0 -94
- snowflake/cli/plugins/object/commands.py +0 -174
- snowflake/cli/plugins/object/common.py +0 -85
- snowflake/cli/plugins/object/manager.py +0 -96
- snowflake/cli/plugins/object/plugin_spec.py +0 -30
- 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/__init__.py +0 -13
- 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/models.py +0 -156
- snowflake/cli/plugins/snowpark/package/__init__.py +0 -13
- snowflake/cli/plugins/snowpark/package/anaconda_packages.py +0 -233
- snowflake/cli/plugins/snowpark/package/commands.py +0 -256
- snowflake/cli/plugins/snowpark/package/manager.py +0 -43
- snowflake/cli/plugins/snowpark/package/utils.py +0 -26
- snowflake/cli/plugins/snowpark/package_utils.py +0 -354
- snowflake/cli/plugins/snowpark/plugin_spec.py +0 -30
- snowflake/cli/plugins/snowpark/snowpark_package_paths.py +0 -65
- snowflake/cli/plugins/snowpark/snowpark_shared.py +0 -95
- snowflake/cli/plugins/snowpark/zipper.py +0 -81
- snowflake/cli/plugins/spcs/__init__.py +0 -35
- snowflake/cli/plugins/spcs/common.py +0 -99
- snowflake/cli/plugins/spcs/compute_pool/__init__.py +0 -13
- snowflake/cli/plugins/spcs/compute_pool/commands.py +0 -240
- snowflake/cli/plugins/spcs/compute_pool/manager.py +0 -121
- snowflake/cli/plugins/spcs/image_registry/__init__.py +0 -13
- snowflake/cli/plugins/spcs/image_registry/commands.py +0 -65
- snowflake/cli/plugins/spcs/image_registry/manager.py +0 -105
- snowflake/cli/plugins/spcs/image_repository/__init__.py +0 -13
- snowflake/cli/plugins/spcs/image_repository/commands.py +0 -196
- snowflake/cli/plugins/spcs/image_repository/manager.py +0 -84
- snowflake/cli/plugins/spcs/jobs/__init__.py +0 -13
- snowflake/cli/plugins/spcs/jobs/commands.py +0 -78
- snowflake/cli/plugins/spcs/jobs/manager.py +0 -53
- snowflake/cli/plugins/spcs/plugin_spec.py +0 -30
- snowflake/cli/plugins/spcs/services/__init__.py +0 -13
- snowflake/cli/plugins/spcs/services/commands.py +0 -311
- snowflake/cli/plugins/spcs/services/manager.py +0 -170
- snowflake/cli/plugins/sql/__init__.py +0 -13
- snowflake/cli/plugins/sql/commands.py +0 -83
- snowflake/cli/plugins/sql/manager.py +0 -92
- snowflake/cli/plugins/sql/plugin_spec.py +0 -30
- snowflake/cli/plugins/sql/snowsql_templating.py +0 -28
- snowflake/cli/plugins/stage/__init__.py +0 -13
- snowflake/cli/plugins/stage/commands.py +0 -261
- snowflake/cli/plugins/stage/diff.py +0 -326
- snowflake/cli/plugins/stage/manager.py +0 -544
- snowflake/cli/plugins/stage/md5.py +0 -160
- snowflake/cli/plugins/stage/plugin_spec.py +0 -30
- snowflake/cli/plugins/streamlit/__init__.py +0 -13
- snowflake/cli/plugins/streamlit/commands.py +0 -186
- snowflake/cli/plugins/streamlit/manager.py +0 -222
- 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/__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_labs-2.8.0rc1.dist-info → snowflake_cli_labs-2.8.2.dist-info}/WHEEL +0 -0
- {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-2.8.2.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,156 +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
|
-
import zipfile
|
|
19
|
-
from dataclasses import dataclass
|
|
20
|
-
from enum import Enum
|
|
21
|
-
from pathlib import Path
|
|
22
|
-
from typing import List
|
|
23
|
-
|
|
24
|
-
from requirements import requirement
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
class YesNoAsk(Enum):
|
|
28
|
-
YES = "yes"
|
|
29
|
-
NO = "no"
|
|
30
|
-
ASK = "ask"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class Requirement(requirement.Requirement):
|
|
34
|
-
extra_pattern = re.compile("'([^']*)'")
|
|
35
|
-
|
|
36
|
-
def __init__(self, *args, **kwargs):
|
|
37
|
-
super().__init__(*args, **kwargs)
|
|
38
|
-
self.package_name = None
|
|
39
|
-
|
|
40
|
-
@classmethod
|
|
41
|
-
def parse_line(cls, line: str) -> Requirement:
|
|
42
|
-
if len(line_elements := line.split(";")) > 1:
|
|
43
|
-
line = line_elements[0]
|
|
44
|
-
result = super().parse_line(line)
|
|
45
|
-
|
|
46
|
-
if len(line_elements) > 1:
|
|
47
|
-
for element in line_elements[1:]:
|
|
48
|
-
if "extra" in element and (extras := cls.extra_pattern.search(element)):
|
|
49
|
-
result.extras.extend(extras.groups())
|
|
50
|
-
|
|
51
|
-
result.package_name = result.name
|
|
52
|
-
|
|
53
|
-
if result.uri and not result.name:
|
|
54
|
-
result.name = get_package_name(result.uri)
|
|
55
|
-
result.name = cls.standardize_name(result.name)
|
|
56
|
-
|
|
57
|
-
return result
|
|
58
|
-
|
|
59
|
-
@staticmethod
|
|
60
|
-
def standardize_name(name: str) -> str:
|
|
61
|
-
return WheelMetadata.to_wheel_name_format(name.lower())
|
|
62
|
-
|
|
63
|
-
@property
|
|
64
|
-
def formatted_specs(self):
|
|
65
|
-
return ",".join(sorted(spec[0] + spec[1] for spec in self.specs))
|
|
66
|
-
|
|
67
|
-
@property
|
|
68
|
-
def name_and_version(self):
|
|
69
|
-
return self.name + self.formatted_specs
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
@dataclass
|
|
73
|
-
class RequirementWithFiles:
|
|
74
|
-
"""A dataclass to hold a requirement and the path to the
|
|
75
|
-
downloaded files/folders that belong to it"""
|
|
76
|
-
|
|
77
|
-
requirement: Requirement
|
|
78
|
-
files: List[str]
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
@dataclass
|
|
82
|
-
class RequirementWithWheel:
|
|
83
|
-
"""A dataclass to hold a requirement and corresponding .whl file."""
|
|
84
|
-
|
|
85
|
-
requirement: Requirement
|
|
86
|
-
wheel_path: Path | None
|
|
87
|
-
|
|
88
|
-
def extract_files(self, destination: Path) -> None:
|
|
89
|
-
if self.wheel_path is not None:
|
|
90
|
-
zipfile.ZipFile(self.wheel_path).extractall(destination)
|
|
91
|
-
|
|
92
|
-
def namelist(self) -> List[str]:
|
|
93
|
-
if self.wheel_path is None:
|
|
94
|
-
return []
|
|
95
|
-
return zipfile.ZipFile(self.wheel_path).namelist()
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
@dataclass
|
|
99
|
-
class WheelMetadata:
|
|
100
|
-
"""A dataclass to hold metadata from .whl file.
|
|
101
|
-
[name] is the name of the package standardized according to
|
|
102
|
-
https://peps.python.org/pep-0491/#escaping-and-unicode
|
|
103
|
-
"""
|
|
104
|
-
|
|
105
|
-
name: str
|
|
106
|
-
wheel_path: Path
|
|
107
|
-
dependencies: List[str]
|
|
108
|
-
|
|
109
|
-
@classmethod
|
|
110
|
-
def from_wheel(cls, wheel_path: Path):
|
|
111
|
-
"""Parses wheel metadata according to
|
|
112
|
-
https://peps.python.org/pep-0491/#file-contents"""
|
|
113
|
-
with zipfile.ZipFile(wheel_path, "r") as whl:
|
|
114
|
-
metadata_path = [
|
|
115
|
-
path for path in whl.namelist() if path.endswith(".dist-info/METADATA")
|
|
116
|
-
]
|
|
117
|
-
if len(metadata_path) != 1:
|
|
118
|
-
# malformatted wheel package
|
|
119
|
-
return None
|
|
120
|
-
|
|
121
|
-
root = zipfile.Path(whl)
|
|
122
|
-
metadata = (root / metadata_path[0]).read_text(encoding="utf-8")
|
|
123
|
-
|
|
124
|
-
dep_keyword = "Requires-Dist:"
|
|
125
|
-
dependencies = [
|
|
126
|
-
line[len(dep_keyword) :].strip()
|
|
127
|
-
for line in metadata.splitlines()
|
|
128
|
-
if line.startswith(dep_keyword)
|
|
129
|
-
]
|
|
130
|
-
name = cls._get_name_from_wheel_filename(wheel_path.name)
|
|
131
|
-
return cls(name=name, wheel_path=wheel_path, dependencies=dependencies)
|
|
132
|
-
|
|
133
|
-
@staticmethod
|
|
134
|
-
def _get_name_from_wheel_filename(wheel_filename: str) -> str:
|
|
135
|
-
# wheel filename is in format {name}-{version}[-{extra info}]
|
|
136
|
-
# https://peps.python.org/pep-0491/#file-name-convention
|
|
137
|
-
return wheel_filename.split("-")[0]
|
|
138
|
-
|
|
139
|
-
@staticmethod
|
|
140
|
-
def to_wheel_name_format(package_name: str) -> str:
|
|
141
|
-
# https://peps.python.org/pep-0491/#escaping-and-unicode
|
|
142
|
-
return re.sub(r"[^\w\d.]+", "_", package_name, re.UNICODE)
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
def get_package_name(name: str) -> str:
|
|
146
|
-
if name.lower().startswith(("git+", "http")):
|
|
147
|
-
pattern = re.compile(r"github\.com\/[^\/]+\/([^\/][^.@$/]+)")
|
|
148
|
-
if match := pattern.search(name):
|
|
149
|
-
return match.group(1)
|
|
150
|
-
else:
|
|
151
|
-
return name
|
|
152
|
-
|
|
153
|
-
elif name.endswith(".zip"):
|
|
154
|
-
return name.replace(".zip", "")
|
|
155
|
-
else:
|
|
156
|
-
return name
|
|
@@ -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.
|