snowflake-cli-labs 2.8.0rc0__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/errors.py +16 -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.0rc0.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 -819
- 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.0rc0.dist-info/RECORD +0 -240
- snowflake_cli_labs-2.8.0rc0.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.0rc0.dist-info → snowflake_cli_labs-3.0.0rc0.dist-info}/WHEEL +0 -0
- {snowflake_cli_labs-2.8.0rc0.dist-info → snowflake_cli_labs-3.0.0rc0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,252 @@
|
|
|
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
|
+
import re
|
|
19
|
+
from enum import Enum
|
|
20
|
+
from typing import Dict, List, Set
|
|
21
|
+
|
|
22
|
+
from click import UsageError
|
|
23
|
+
from snowflake.cli._plugins.snowpark.models import Requirement
|
|
24
|
+
from snowflake.cli._plugins.snowpark.snowpark_project_paths import Artefact
|
|
25
|
+
from snowflake.cli.api.console import cli_console
|
|
26
|
+
from snowflake.cli.api.constants import ObjectType
|
|
27
|
+
from snowflake.cli.api.project.schemas.entities.snowpark_entity import (
|
|
28
|
+
ProcedureEntityModel,
|
|
29
|
+
SnowparkEntityModel,
|
|
30
|
+
)
|
|
31
|
+
from snowflake.cli.api.sql_execution import SqlExecutionMixin
|
|
32
|
+
from snowflake.connector.cursor import SnowflakeCursor
|
|
33
|
+
|
|
34
|
+
log = logging.getLogger(__name__)
|
|
35
|
+
|
|
36
|
+
SnowparkEntities = Dict[str, SnowparkEntityModel]
|
|
37
|
+
StageToArtefactMapping = Dict[str, set[Artefact]]
|
|
38
|
+
EntityToImportPathsMapping = Dict[str, set[str]]
|
|
39
|
+
|
|
40
|
+
DEFAULT_RUNTIME = "3.10"
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class SnowparkObject(Enum):
|
|
44
|
+
"""This clas is used only for Snowpark execute where choice is limited."""
|
|
45
|
+
|
|
46
|
+
PROCEDURE = str(ObjectType.PROCEDURE)
|
|
47
|
+
FUNCTION = str(ObjectType.FUNCTION)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
class SnowparkObjectManager(SqlExecutionMixin):
|
|
51
|
+
def execute(
|
|
52
|
+
self, execution_identifier: str, object_type: SnowparkObject
|
|
53
|
+
) -> SnowflakeCursor:
|
|
54
|
+
if object_type == SnowparkObject.FUNCTION:
|
|
55
|
+
return self._execute_query(f"select {execution_identifier}")
|
|
56
|
+
if object_type == SnowparkObject.PROCEDURE:
|
|
57
|
+
return self._execute_query(f"call {execution_identifier}")
|
|
58
|
+
raise UsageError(f"Unknown object type: {object_type}.")
|
|
59
|
+
|
|
60
|
+
def create_or_replace(
|
|
61
|
+
self,
|
|
62
|
+
entity: SnowparkEntityModel,
|
|
63
|
+
artifact_files: set[str],
|
|
64
|
+
snowflake_dependencies: list[str],
|
|
65
|
+
) -> str:
|
|
66
|
+
entity.imports.extend(artifact_files)
|
|
67
|
+
imports = [f"'{x}'" for x in entity.imports]
|
|
68
|
+
packages_list = ",".join(f"'{p}'" for p in snowflake_dependencies)
|
|
69
|
+
|
|
70
|
+
object_type = entity.get_type()
|
|
71
|
+
|
|
72
|
+
query = [
|
|
73
|
+
f"create or replace {object_type} {entity.udf_sproc_identifier.identifier_for_sql}",
|
|
74
|
+
f"copy grants",
|
|
75
|
+
f"returns {entity.returns}",
|
|
76
|
+
"language python",
|
|
77
|
+
f"runtime_version={entity.runtime or DEFAULT_RUNTIME}",
|
|
78
|
+
f"imports=({', '.join(imports)})",
|
|
79
|
+
f"handler='{entity.handler}'",
|
|
80
|
+
f"packages=({packages_list})",
|
|
81
|
+
]
|
|
82
|
+
|
|
83
|
+
if entity.external_access_integrations:
|
|
84
|
+
query.append(entity.get_external_access_integrations_sql())
|
|
85
|
+
|
|
86
|
+
if entity.secrets:
|
|
87
|
+
query.append(entity.get_secrets_sql())
|
|
88
|
+
|
|
89
|
+
if isinstance(entity, ProcedureEntityModel) and entity.execute_as_caller:
|
|
90
|
+
query.append("execute as caller")
|
|
91
|
+
|
|
92
|
+
return self._execute_query("\n".join(query))
|
|
93
|
+
|
|
94
|
+
def deploy_entity(
|
|
95
|
+
self,
|
|
96
|
+
entity: SnowparkEntityModel,
|
|
97
|
+
existing_objects: Dict[str, SnowflakeCursor],
|
|
98
|
+
snowflake_dependencies: List[str],
|
|
99
|
+
entities_to_artifact_map: EntityToImportPathsMapping,
|
|
100
|
+
):
|
|
101
|
+
cli_console.step(f"Creating {entity.type} {entity.fqn}")
|
|
102
|
+
object_exists = entity.entity_id in existing_objects
|
|
103
|
+
replace_object = False
|
|
104
|
+
if object_exists:
|
|
105
|
+
replace_object = _check_if_replace_is_required(
|
|
106
|
+
entity=entity,
|
|
107
|
+
current_state=existing_objects[entity.entity_id],
|
|
108
|
+
snowflake_dependencies=snowflake_dependencies,
|
|
109
|
+
stage_artifact_files=entities_to_artifact_map[entity.entity_id],
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
state = {
|
|
113
|
+
"object": entity.udf_sproc_identifier.identifier_with_arg_names_types_defaults,
|
|
114
|
+
"type": entity.get_type(),
|
|
115
|
+
}
|
|
116
|
+
if object_exists and not replace_object:
|
|
117
|
+
return {**state, "status": "packages updated"}
|
|
118
|
+
|
|
119
|
+
self.create_or_replace(
|
|
120
|
+
entity=entity,
|
|
121
|
+
artifact_files=entities_to_artifact_map[entity.entity_id],
|
|
122
|
+
snowflake_dependencies=snowflake_dependencies,
|
|
123
|
+
)
|
|
124
|
+
return {
|
|
125
|
+
**state,
|
|
126
|
+
"status": "created" if not object_exists else "definition updated",
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def _check_if_replace_is_required(
|
|
131
|
+
entity: SnowparkEntityModel,
|
|
132
|
+
current_state,
|
|
133
|
+
snowflake_dependencies: List[str],
|
|
134
|
+
stage_artifact_files: set[str],
|
|
135
|
+
) -> bool:
|
|
136
|
+
object_type = entity.get_type()
|
|
137
|
+
resource_json = _convert_resource_details_to_dict(current_state)
|
|
138
|
+
old_dependencies = resource_json["packages"]
|
|
139
|
+
|
|
140
|
+
if _snowflake_dependencies_differ(old_dependencies, snowflake_dependencies):
|
|
141
|
+
log.info(
|
|
142
|
+
"Found difference of package requirements. Replacing the %s.", object_type
|
|
143
|
+
)
|
|
144
|
+
return True
|
|
145
|
+
|
|
146
|
+
if set(entity.external_access_integrations) != set(
|
|
147
|
+
resource_json.get("external_access_integrations", [])
|
|
148
|
+
):
|
|
149
|
+
log.info(
|
|
150
|
+
"Found difference of external access integrations. Replacing the %s.",
|
|
151
|
+
object_type,
|
|
152
|
+
)
|
|
153
|
+
return True
|
|
154
|
+
|
|
155
|
+
if (
|
|
156
|
+
resource_json["handler"].lower() != entity.handler.lower()
|
|
157
|
+
or _sql_to_python_return_type_mapper(resource_json["returns"]).lower()
|
|
158
|
+
!= entity.returns.lower()
|
|
159
|
+
):
|
|
160
|
+
log.info(
|
|
161
|
+
"Return type or handler types do not match. Replacing the %s.", object_type
|
|
162
|
+
)
|
|
163
|
+
return True
|
|
164
|
+
|
|
165
|
+
if _compare_imports(resource_json, entity.imports, stage_artifact_files):
|
|
166
|
+
log.info("Imports do not match. Replacing the %s", object_type)
|
|
167
|
+
return True
|
|
168
|
+
|
|
169
|
+
if entity.runtime is not None and entity.runtime != resource_json.get(
|
|
170
|
+
"runtime_version", "RUNTIME_NOT_SET"
|
|
171
|
+
):
|
|
172
|
+
log.info("Runtime versions do not match. Replacing the %s", object_type)
|
|
173
|
+
return True
|
|
174
|
+
|
|
175
|
+
if isinstance(entity, ProcedureEntityModel):
|
|
176
|
+
if resource_json.get("execute as", "OWNER") != (
|
|
177
|
+
"CALLER" if entity.execute_as_caller else "OWNER"
|
|
178
|
+
):
|
|
179
|
+
log.info(
|
|
180
|
+
"Execute as caller settings do not match. Replacing the %s", object_type
|
|
181
|
+
)
|
|
182
|
+
return True
|
|
183
|
+
|
|
184
|
+
return False
|
|
185
|
+
|
|
186
|
+
|
|
187
|
+
def _convert_resource_details_to_dict(function_details: SnowflakeCursor) -> dict:
|
|
188
|
+
import json
|
|
189
|
+
|
|
190
|
+
function_dict = {}
|
|
191
|
+
json_properties = ["packages", "installed_packages"]
|
|
192
|
+
for function in function_details:
|
|
193
|
+
if function[0] in json_properties:
|
|
194
|
+
function_dict[function[0]] = json.loads(
|
|
195
|
+
function[1].replace("'", '"'),
|
|
196
|
+
)
|
|
197
|
+
else:
|
|
198
|
+
function_dict[function[0]] = function[1]
|
|
199
|
+
return function_dict
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
def _snowflake_dependencies_differ(
|
|
203
|
+
old_dependencies: List[str], new_dependencies: List[str]
|
|
204
|
+
) -> bool:
|
|
205
|
+
def _standardize(packages: List[str]) -> Set[str]:
|
|
206
|
+
return set(
|
|
207
|
+
Requirement.parse_line(package).name_and_version for package in packages
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
return _standardize(old_dependencies) != _standardize(new_dependencies)
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
def _sql_to_python_return_type_mapper(resource_return_type: str) -> str:
|
|
214
|
+
"""
|
|
215
|
+
Some of the Python data types get converted to SQL types, when function/procedure is created.
|
|
216
|
+
So, to properly compare types, we use mapping based on:
|
|
217
|
+
https://docs.snowflake.com/en/developer-guide/udf-stored-procedure-data-type-mapping#sql-python-data-type-mappings
|
|
218
|
+
|
|
219
|
+
Mind you, this only applies to cases, in which Snowflake accepts Python type as return.
|
|
220
|
+
Ie. if function returns list, it has to be declared as 'array' during creation,
|
|
221
|
+
therefore any conversion is not necessary
|
|
222
|
+
"""
|
|
223
|
+
mapping = {
|
|
224
|
+
"number(38,0)": "int",
|
|
225
|
+
"timestamp_ntz(9)": "datetime",
|
|
226
|
+
"timestamp_tz(9)": "datetime",
|
|
227
|
+
"varchar(16777216)": "string",
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return mapping.get(resource_return_type.lower(), resource_return_type.lower())
|
|
231
|
+
|
|
232
|
+
|
|
233
|
+
def _compare_imports(
|
|
234
|
+
resource_json: dict, imports: List[str], artifact_files: set[str]
|
|
235
|
+
) -> bool:
|
|
236
|
+
pattern = re.compile(r"(?:\[@?\w+_\w+\.)?(\w+(?:/\w+)+\.\w+)(?:\])?")
|
|
237
|
+
|
|
238
|
+
project_imports = {
|
|
239
|
+
imp
|
|
240
|
+
for import_string in [*imports, *artifact_files]
|
|
241
|
+
for imp in pattern.findall(import_string.lower())
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
if "imports" not in resource_json.keys():
|
|
245
|
+
object_imports = set()
|
|
246
|
+
else:
|
|
247
|
+
object_imports = {
|
|
248
|
+
imp.lower()
|
|
249
|
+
for imp in pattern.findall(resource_json.get("imports", "").lower())
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return project_imports != object_imports
|
|
@@ -17,19 +17,12 @@ from __future__ import annotations
|
|
|
17
17
|
import re
|
|
18
18
|
import zipfile
|
|
19
19
|
from dataclasses import dataclass
|
|
20
|
-
from enum import Enum
|
|
21
20
|
from pathlib import Path
|
|
22
21
|
from typing import List
|
|
23
22
|
|
|
24
23
|
from requirements import requirement
|
|
25
24
|
|
|
26
25
|
|
|
27
|
-
class YesNoAsk(Enum):
|
|
28
|
-
YES = "yes"
|
|
29
|
-
NO = "no"
|
|
30
|
-
ASK = "ask"
|
|
31
|
-
|
|
32
|
-
|
|
33
26
|
class Requirement(requirement.Requirement):
|
|
34
27
|
extra_pattern = re.compile("'([^']*)'")
|
|
35
28
|
|
|
@@ -24,10 +24,10 @@ from packaging.requirements import InvalidRequirement
|
|
|
24
24
|
from packaging.requirements import Requirement as PkgRequirement
|
|
25
25
|
from packaging.version import InvalidVersion, parse
|
|
26
26
|
from requests import HTTPError
|
|
27
|
+
from snowflake.cli._plugins.snowpark.models import Requirement
|
|
27
28
|
from snowflake.cli.api.exceptions import SnowflakeSQLExecutionError
|
|
28
29
|
from snowflake.cli.api.secure_path import SecurePath
|
|
29
30
|
from snowflake.cli.api.sql_execution import SqlExecutionMixin
|
|
30
|
-
from snowflake.cli.plugins.snowpark.models import Requirement
|
|
31
31
|
from snowflake.connector import DictCursor
|
|
32
32
|
|
|
33
33
|
log = logging.getLogger(__name__)
|
|
@@ -21,35 +21,29 @@ from typing import Optional
|
|
|
21
21
|
|
|
22
22
|
import typer
|
|
23
23
|
from click import ClickException
|
|
24
|
-
from snowflake.cli.
|
|
25
|
-
deprecated_flag_callback,
|
|
26
|
-
)
|
|
27
|
-
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
28
|
-
from snowflake.cli.api.output.types import CommandResult, MessageResult
|
|
29
|
-
from snowflake.cli.api.secure_path import SecurePath
|
|
30
|
-
from snowflake.cli.plugins.snowpark.models import (
|
|
24
|
+
from snowflake.cli._plugins.snowpark.models import (
|
|
31
25
|
Requirement,
|
|
32
|
-
YesNoAsk,
|
|
33
26
|
)
|
|
34
|
-
from snowflake.cli.
|
|
27
|
+
from snowflake.cli._plugins.snowpark.package.anaconda_packages import (
|
|
35
28
|
AnacondaPackages,
|
|
36
29
|
AnacondaPackagesManager,
|
|
37
30
|
)
|
|
38
|
-
from snowflake.cli.
|
|
39
|
-
from snowflake.cli.
|
|
31
|
+
from snowflake.cli._plugins.snowpark.package.manager import upload
|
|
32
|
+
from snowflake.cli._plugins.snowpark.package_utils import (
|
|
40
33
|
detect_and_log_shared_libraries,
|
|
41
34
|
download_unavailable_packages,
|
|
42
35
|
get_package_name_from_pip_wheel,
|
|
43
36
|
)
|
|
44
|
-
from snowflake.cli.
|
|
37
|
+
from snowflake.cli._plugins.snowpark.snowpark_shared import (
|
|
45
38
|
AllowSharedLibrariesOption,
|
|
46
39
|
IgnoreAnacondaOption,
|
|
47
40
|
IndexUrlOption,
|
|
48
41
|
SkipVersionCheckOption,
|
|
49
|
-
deprecated_allow_native_libraries_option,
|
|
50
|
-
resolve_allow_shared_libraries_yes_no_ask,
|
|
51
42
|
)
|
|
52
|
-
from snowflake.cli.
|
|
43
|
+
from snowflake.cli._plugins.snowpark.zipper import zip_dir
|
|
44
|
+
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
45
|
+
from snowflake.cli.api.output.types import CommandResult, MessageResult
|
|
46
|
+
from snowflake.cli.api.secure_path import SecurePath
|
|
53
47
|
|
|
54
48
|
app = SnowTyperFactory(
|
|
55
49
|
name="package",
|
|
@@ -58,36 +52,11 @@ app = SnowTyperFactory(
|
|
|
58
52
|
log = logging.getLogger(__name__)
|
|
59
53
|
|
|
60
54
|
|
|
61
|
-
lookup_install_option = typer.Option(
|
|
62
|
-
False,
|
|
63
|
-
"--pypi-download",
|
|
64
|
-
hidden=True,
|
|
65
|
-
callback=deprecated_flag_callback(
|
|
66
|
-
"Using --pypi-download is deprecated. Lookup command no longer checks for package in PyPi."
|
|
67
|
-
),
|
|
68
|
-
help="Installs packages that are not available on the Snowflake Anaconda channel.",
|
|
69
|
-
)
|
|
70
|
-
|
|
71
|
-
lookup_deprecated_install_option = typer.Option(
|
|
72
|
-
False,
|
|
73
|
-
"--yes",
|
|
74
|
-
"-y",
|
|
75
|
-
hidden=True,
|
|
76
|
-
callback=deprecated_flag_callback(
|
|
77
|
-
"Using --yes is deprecated. Lookup command no longer checks for package in PyPi."
|
|
78
|
-
),
|
|
79
|
-
help="Installs packages that are not available on the Snowflake Anaconda channel.",
|
|
80
|
-
)
|
|
81
|
-
|
|
82
|
-
|
|
83
55
|
@app.command("lookup", requires_connection=True)
|
|
84
56
|
def package_lookup(
|
|
85
57
|
package_name: str = typer.Argument(
|
|
86
58
|
..., help="Name of the package.", show_default=False
|
|
87
59
|
),
|
|
88
|
-
# todo: remove with 3.0
|
|
89
|
-
_: bool = lookup_install_option,
|
|
90
|
-
__: bool = lookup_deprecated_install_option,
|
|
91
60
|
**options,
|
|
92
61
|
) -> CommandResult:
|
|
93
62
|
"""
|
|
@@ -125,12 +94,14 @@ def package_upload(
|
|
|
125
94
|
"-f",
|
|
126
95
|
help="Path to the file to upload.",
|
|
127
96
|
exists=False,
|
|
97
|
+
show_default=False,
|
|
128
98
|
),
|
|
129
99
|
stage: str = typer.Option(
|
|
130
100
|
...,
|
|
131
101
|
"--stage",
|
|
132
102
|
"-s",
|
|
133
103
|
help="Name of the stage in which to upload the file, not including the @ symbol.",
|
|
104
|
+
show_default=False,
|
|
134
105
|
),
|
|
135
106
|
overwrite: bool = typer.Option(
|
|
136
107
|
False,
|
|
@@ -146,43 +117,17 @@ def package_upload(
|
|
|
146
117
|
return MessageResult(upload(file=file, stage=stage, overwrite=overwrite))
|
|
147
118
|
|
|
148
119
|
|
|
149
|
-
deprecated_pypi_download_option = typer.Option(
|
|
150
|
-
False,
|
|
151
|
-
"--pypi-download",
|
|
152
|
-
hidden=True,
|
|
153
|
-
callback=deprecated_flag_callback(
|
|
154
|
-
"Using --pypi-download is deprecated. Create command always checks for package in PyPi."
|
|
155
|
-
),
|
|
156
|
-
help="Installs packages that are not available on the Snowflake Anaconda channel.",
|
|
157
|
-
)
|
|
158
|
-
|
|
159
|
-
deprecated_install_option = typer.Option(
|
|
160
|
-
False,
|
|
161
|
-
"--yes",
|
|
162
|
-
"-y",
|
|
163
|
-
hidden=True,
|
|
164
|
-
help="Installs packages that are not available on the Snowflake Anaconda channel.",
|
|
165
|
-
callback=deprecated_flag_callback(
|
|
166
|
-
"Using --yes is deprecated. Create command always checks for package in PyPi."
|
|
167
|
-
),
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
|
|
171
120
|
@app.command("create", requires_connection=True)
|
|
172
121
|
def package_create(
|
|
173
122
|
name: str = typer.Argument(
|
|
174
123
|
...,
|
|
175
124
|
help="Name of the package to create.",
|
|
125
|
+
show_default=False,
|
|
176
126
|
),
|
|
177
127
|
ignore_anaconda: bool = IgnoreAnacondaOption,
|
|
178
128
|
index_url: Optional[str] = IndexUrlOption,
|
|
179
129
|
skip_version_check: bool = SkipVersionCheckOption,
|
|
180
130
|
allow_shared_libraries: bool = AllowSharedLibrariesOption,
|
|
181
|
-
deprecated_allow_native_libraries: YesNoAsk = deprecated_allow_native_libraries_option(
|
|
182
|
-
"--allow-native-libraries"
|
|
183
|
-
),
|
|
184
|
-
_deprecated_install_option: bool = deprecated_install_option,
|
|
185
|
-
_deprecated_install_packages: bool = deprecated_pypi_download_option,
|
|
186
131
|
**options,
|
|
187
132
|
) -> CommandResult:
|
|
188
133
|
"""
|
|
@@ -217,13 +162,7 @@ def package_create(
|
|
|
217
162
|
# The package is not in anaconda, so we have to pack it
|
|
218
163
|
log.info("Checking to see if packages have shared (.so/.dll) libraries...")
|
|
219
164
|
if detect_and_log_shared_libraries(download_result.downloaded_packages_details):
|
|
220
|
-
|
|
221
|
-
if not (
|
|
222
|
-
allow_shared_libraries
|
|
223
|
-
or resolve_allow_shared_libraries_yes_no_ask(
|
|
224
|
-
deprecated_allow_native_libraries
|
|
225
|
-
)
|
|
226
|
-
):
|
|
165
|
+
if not allow_shared_libraries:
|
|
227
166
|
raise ClickException(
|
|
228
167
|
"Some packages contain shared (.so/.dll) libraries. "
|
|
229
168
|
"Try again with --allow-shared-libraries."
|
|
@@ -17,9 +17,10 @@ from __future__ import annotations
|
|
|
17
17
|
import logging
|
|
18
18
|
from pathlib import Path
|
|
19
19
|
|
|
20
|
+
from snowflake.cli._plugins.snowpark.package.utils import prepare_app_zip
|
|
21
|
+
from snowflake.cli._plugins.stage.manager import StageManager
|
|
22
|
+
from snowflake.cli.api.identifiers import FQN
|
|
20
23
|
from snowflake.cli.api.secure_path import SecurePath
|
|
21
|
-
from snowflake.cli.plugins.snowpark.package.utils import prepare_app_zip
|
|
22
|
-
from snowflake.cli.plugins.stage.manager import StageManager
|
|
23
24
|
|
|
24
25
|
log = logging.getLogger(__name__)
|
|
25
26
|
|
|
@@ -30,7 +31,7 @@ def upload(file: Path, stage: str, overwrite: bool):
|
|
|
30
31
|
temp_app_zip_path = prepare_app_zip(SecurePath(file), temp_dir)
|
|
31
32
|
sm = StageManager()
|
|
32
33
|
|
|
33
|
-
sm.create(sm.get_stage_from_path(stage))
|
|
34
|
+
sm.create(FQN.from_string(sm.get_stage_from_path(stage)))
|
|
34
35
|
put_response = sm.put(
|
|
35
36
|
temp_app_zip_path.path, stage, overwrite=overwrite
|
|
36
37
|
).fetchone()
|
|
@@ -25,17 +25,17 @@ from textwrap import dedent
|
|
|
25
25
|
from typing import Dict, List, Optional
|
|
26
26
|
|
|
27
27
|
from click import ClickException
|
|
28
|
-
from snowflake.cli.
|
|
29
|
-
from snowflake.cli.api.secure_path import SecurePath
|
|
30
|
-
from snowflake.cli.plugins.snowpark.models import (
|
|
28
|
+
from snowflake.cli._plugins.snowpark.models import (
|
|
31
29
|
Requirement,
|
|
32
30
|
RequirementWithFiles,
|
|
33
31
|
RequirementWithWheel,
|
|
34
32
|
WheelMetadata,
|
|
35
33
|
)
|
|
36
|
-
from snowflake.cli.
|
|
34
|
+
from snowflake.cli._plugins.snowpark.package.anaconda_packages import (
|
|
37
35
|
AnacondaPackages,
|
|
38
36
|
)
|
|
37
|
+
from snowflake.cli.api.constants import DEFAULT_SIZE_LIMIT_MB
|
|
38
|
+
from snowflake.cli.api.secure_path import SecurePath
|
|
39
39
|
|
|
40
40
|
log = logging.getLogger(__name__)
|
|
41
41
|
|
|
@@ -61,7 +61,7 @@ def parse_requirements(
|
|
|
61
61
|
).splitlines():
|
|
62
62
|
line = re.sub(r"\s*#.*", "", line).strip()
|
|
63
63
|
if line:
|
|
64
|
-
reqs.append(Requirement.
|
|
64
|
+
reqs.append(Requirement.parse_line(line))
|
|
65
65
|
return reqs
|
|
66
66
|
|
|
67
67
|
|
|
@@ -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.snowpark 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.nativeapp import commands
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@plugin_hook_impl
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Copyright (c) 2024 Snowflake Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
from dataclasses import dataclass
|
|
17
|
+
from pathlib import Path, PurePosixPath
|
|
18
|
+
|
|
19
|
+
from snowflake.cli._plugins.snowpark.zipper import zip_dir
|
|
20
|
+
from snowflake.cli.api.console import cli_console
|
|
21
|
+
from snowflake.cli.api.constants import DEPLOYMENT_STAGE
|
|
22
|
+
from snowflake.cli.api.identifiers import FQN
|
|
23
|
+
from snowflake.cli.api.project.schemas.entities.snowpark_entity import PathMapping
|
|
24
|
+
from snowflake.cli.api.secure_path import SecurePath
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class SnowparkProjectPaths:
|
|
29
|
+
"""
|
|
30
|
+
This class represents allows you to manage files paths related to given project.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
project_root: Path
|
|
34
|
+
|
|
35
|
+
def path_relative_to_root(self, artifact_path: Path) -> Path:
|
|
36
|
+
if artifact_path.is_absolute():
|
|
37
|
+
return artifact_path
|
|
38
|
+
return (self.project_root / artifact_path).resolve()
|
|
39
|
+
|
|
40
|
+
def get_artefact_dto(self, artifact_path: PathMapping) -> Artefact:
|
|
41
|
+
return Artefact(
|
|
42
|
+
dest=artifact_path.dest,
|
|
43
|
+
path=self.path_relative_to_root(artifact_path.src),
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def get_dependencies_artefact(self) -> Artefact:
|
|
47
|
+
return Artefact(dest=None, path=self.dependencies)
|
|
48
|
+
|
|
49
|
+
@property
|
|
50
|
+
def snowflake_requirements(self) -> SecurePath:
|
|
51
|
+
return SecurePath(
|
|
52
|
+
self.path_relative_to_root(Path("requirements.snowflake.txt"))
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
@property
|
|
56
|
+
def requirements(self) -> SecurePath:
|
|
57
|
+
return SecurePath(self.path_relative_to_root(Path("requirements.txt")))
|
|
58
|
+
|
|
59
|
+
@property
|
|
60
|
+
def dependencies(self) -> Path:
|
|
61
|
+
return self.path_relative_to_root(Path("dependencies.zip"))
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass(unsafe_hash=True)
|
|
65
|
+
class Artefact:
|
|
66
|
+
"""Helper for getting paths related to given artefact."""
|
|
67
|
+
|
|
68
|
+
path: Path
|
|
69
|
+
dest: str | None = None
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def _artefact_name(self) -> str:
|
|
73
|
+
if self.path.is_dir():
|
|
74
|
+
return self.path.stem + ".zip"
|
|
75
|
+
return self.path.name
|
|
76
|
+
|
|
77
|
+
@property
|
|
78
|
+
def post_build_path(self) -> Path:
|
|
79
|
+
"""
|
|
80
|
+
Returns post-build artefact path. Directories are mapped to corresponding .zip files.
|
|
81
|
+
"""
|
|
82
|
+
return self.path.parent / self._artefact_name
|
|
83
|
+
|
|
84
|
+
def upload_path(self, stage: FQN | str | None) -> str:
|
|
85
|
+
"""
|
|
86
|
+
Path on stage to which the artefact should be uploaded.
|
|
87
|
+
"""
|
|
88
|
+
stage = stage or DEPLOYMENT_STAGE
|
|
89
|
+
if isinstance(stage, str):
|
|
90
|
+
stage = FQN.from_stage(stage).using_context()
|
|
91
|
+
|
|
92
|
+
stage_path = PurePosixPath(f"@{stage}")
|
|
93
|
+
if self.dest:
|
|
94
|
+
stage_path = stage_path / self.dest
|
|
95
|
+
return str(stage_path) + "/"
|
|
96
|
+
|
|
97
|
+
def import_path(self, stage: FQN | str | None) -> str:
|
|
98
|
+
"""Path for UDF/sproc imports clause."""
|
|
99
|
+
return self.upload_path(stage) + self._artefact_name
|
|
100
|
+
|
|
101
|
+
def build(self) -> None:
|
|
102
|
+
"""Build the artefact. Applies only to directories. Files are untouched."""
|
|
103
|
+
if not self.path.is_dir():
|
|
104
|
+
return
|
|
105
|
+
cli_console.step(f"Creating: {self.post_build_path.name}")
|
|
106
|
+
zip_dir(
|
|
107
|
+
source=self.path,
|
|
108
|
+
dest_zip=self.post_build_path,
|
|
109
|
+
)
|
|
@@ -14,33 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
import click
|
|
18
17
|
import typer
|
|
19
|
-
from snowflake.cli.api.commands.flags import (
|
|
20
|
-
deprecated_flag_callback,
|
|
21
|
-
deprecated_flag_callback_enum,
|
|
22
|
-
)
|
|
23
|
-
from snowflake.cli.plugins.snowpark.models import YesNoAsk
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def deprecated_allow_native_libraries_option(old_flag_name: str):
|
|
27
|
-
return typer.Option(
|
|
28
|
-
YesNoAsk.NO.value,
|
|
29
|
-
old_flag_name,
|
|
30
|
-
help="Allows native libraries, when using packages installed through PIP",
|
|
31
|
-
hidden=True,
|
|
32
|
-
callback=deprecated_flag_callback_enum(
|
|
33
|
-
f"{old_flag_name} flag is deprecated. Use --allow-shared-libraries flag instead."
|
|
34
|
-
),
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def resolve_allow_shared_libraries_yes_no_ask(allow_shared_libraries: YesNoAsk) -> bool:
|
|
39
|
-
if allow_shared_libraries == YesNoAsk.ASK:
|
|
40
|
-
return click.confirm("Continue with package installation?", default=False)
|
|
41
|
-
else:
|
|
42
|
-
return allow_shared_libraries == YesNoAsk.YES
|
|
43
|
-
|
|
44
18
|
|
|
45
19
|
AllowSharedLibrariesOption: bool = typer.Option(
|
|
46
20
|
False,
|
|
@@ -48,16 +22,6 @@ AllowSharedLibrariesOption: bool = typer.Option(
|
|
|
48
22
|
help="Allows shared (.so) libraries, when using packages installed through PIP.",
|
|
49
23
|
)
|
|
50
24
|
|
|
51
|
-
DeprecatedCheckAnacondaForPyPiDependencies: bool = typer.Option(
|
|
52
|
-
True,
|
|
53
|
-
"--check-anaconda-for-pypi-deps/--no-check-anaconda-for-pypi-deps",
|
|
54
|
-
"-a",
|
|
55
|
-
help="""Checks if any of missing Anaconda packages dependencies can be imported directly from Anaconda. Valid values include: `true`, `false`, Default: `true`.""",
|
|
56
|
-
hidden=True,
|
|
57
|
-
callback=deprecated_flag_callback(
|
|
58
|
-
"--check-anaconda-for-pypi-deps flag is deprecated. Use --ignore-anaconda flag instead."
|
|
59
|
-
),
|
|
60
|
-
)
|
|
61
25
|
|
|
62
26
|
IgnoreAnacondaOption: bool = typer.Option(
|
|
63
27
|
False,
|