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,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,91 +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
|
-
from abc import ABC, abstractmethod
|
|
18
|
-
from pathlib import Path
|
|
19
|
-
from typing import Optional
|
|
20
|
-
|
|
21
|
-
from click import ClickException
|
|
22
|
-
from snowflake.cli.api.project.schemas.native_app.path_mapping import (
|
|
23
|
-
PathMapping,
|
|
24
|
-
ProcessorMapping,
|
|
25
|
-
)
|
|
26
|
-
from snowflake.cli.plugins.nativeapp.project_model import NativeAppProjectModel
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class UnsupportedArtifactProcessorError(ClickException):
|
|
30
|
-
"""Exception thrown when a user has passed in an unsupported artifact processor."""
|
|
31
|
-
|
|
32
|
-
def __init__(self, processor_name: str):
|
|
33
|
-
super().__init__(
|
|
34
|
-
f"Unsupported value {processor_name} detected for an artifact processor. Please refer to documentation for a list of supported types."
|
|
35
|
-
)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def is_python_file_artifact(src: Path, _: Path):
|
|
39
|
-
"""Determines whether the provided source path is an existing python file."""
|
|
40
|
-
return src.is_file() and src.suffix == ".py"
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
class ProjectFileContextManager:
|
|
44
|
-
"""
|
|
45
|
-
A context manager that encapsulates the logic required to update a project file
|
|
46
|
-
in processor logic. The processor can use this manager to gain access to the contents
|
|
47
|
-
of a file, and optionally provide replacement contents. If it does, the file is
|
|
48
|
-
correctly modified in the deploy root directory to reflect the new contents.
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
def __init__(self, path: Path):
|
|
52
|
-
self.path = path
|
|
53
|
-
self._contents = None
|
|
54
|
-
self.edited_contents = None
|
|
55
|
-
|
|
56
|
-
@property
|
|
57
|
-
def contents(self):
|
|
58
|
-
return self._contents
|
|
59
|
-
|
|
60
|
-
def __enter__(self):
|
|
61
|
-
self._contents = self.path.read_text(encoding="utf-8")
|
|
62
|
-
|
|
63
|
-
return self
|
|
64
|
-
|
|
65
|
-
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
66
|
-
if self.edited_contents is not None:
|
|
67
|
-
if self.path.is_symlink():
|
|
68
|
-
# if the file is a symlink, make sure we don't overwrite the original
|
|
69
|
-
self.path.unlink()
|
|
70
|
-
|
|
71
|
-
self.path.write_text(self.edited_contents, encoding="utf-8")
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
class ArtifactProcessor(ABC):
|
|
75
|
-
def __init__(
|
|
76
|
-
self,
|
|
77
|
-
na_project: NativeAppProjectModel,
|
|
78
|
-
) -> None:
|
|
79
|
-
self._na_project = na_project
|
|
80
|
-
|
|
81
|
-
@abstractmethod
|
|
82
|
-
def process(
|
|
83
|
-
self,
|
|
84
|
-
artifact_to_process: PathMapping,
|
|
85
|
-
processor_mapping: Optional[ProcessorMapping],
|
|
86
|
-
**kwargs,
|
|
87
|
-
) -> None:
|
|
88
|
-
pass
|
|
89
|
-
|
|
90
|
-
def edit_file(self, path: Path):
|
|
91
|
-
return ProjectFileContextManager(path)
|
|
@@ -1,130 +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
|
-
from typing import Dict, Optional
|
|
18
|
-
|
|
19
|
-
from snowflake.cli.api.console import cli_console as cc
|
|
20
|
-
from snowflake.cli.api.project.schemas.native_app.path_mapping import (
|
|
21
|
-
ProcessorMapping,
|
|
22
|
-
)
|
|
23
|
-
from snowflake.cli.plugins.nativeapp.codegen.artifact_processor import (
|
|
24
|
-
ArtifactProcessor,
|
|
25
|
-
UnsupportedArtifactProcessorError,
|
|
26
|
-
)
|
|
27
|
-
from snowflake.cli.plugins.nativeapp.codegen.setup.native_app_setup_processor import (
|
|
28
|
-
NativeAppSetupProcessor,
|
|
29
|
-
)
|
|
30
|
-
from snowflake.cli.plugins.nativeapp.codegen.snowpark.python_processor import (
|
|
31
|
-
SnowparkAnnotationProcessor,
|
|
32
|
-
)
|
|
33
|
-
from snowflake.cli.plugins.nativeapp.feature_flags import FeatureFlag
|
|
34
|
-
from snowflake.cli.plugins.nativeapp.project_model import NativeAppProjectModel
|
|
35
|
-
|
|
36
|
-
SNOWPARK_PROCESSOR = "snowpark"
|
|
37
|
-
NA_SETUP_PROCESSOR = "native-app-setup"
|
|
38
|
-
|
|
39
|
-
_REGISTERED_PROCESSORS_BY_NAME = {
|
|
40
|
-
SNOWPARK_PROCESSOR: SnowparkAnnotationProcessor,
|
|
41
|
-
NA_SETUP_PROCESSOR: NativeAppSetupProcessor,
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class NativeAppCompiler:
|
|
46
|
-
"""
|
|
47
|
-
Compiler class to perform custom processing on all relevant Native Apps artifacts (specified in the project definition file)
|
|
48
|
-
before an application package can be created from those artifacts.
|
|
49
|
-
An artifact can have more than one processor specified for itself, and this class will execute those processors in that order.
|
|
50
|
-
The class also maintains a dictionary of processors it creates in order to reuse them across artifacts, since processor initialization
|
|
51
|
-
is independent of the artifact to process.
|
|
52
|
-
"""
|
|
53
|
-
|
|
54
|
-
def __init__(
|
|
55
|
-
self,
|
|
56
|
-
na_project: NativeAppProjectModel,
|
|
57
|
-
):
|
|
58
|
-
self._na_project = na_project
|
|
59
|
-
# dictionary of all processors created and shared between different artifact objects.
|
|
60
|
-
self.cached_processors: Dict[str, ArtifactProcessor] = {}
|
|
61
|
-
|
|
62
|
-
def compile_artifacts(self):
|
|
63
|
-
"""
|
|
64
|
-
Go through every artifact object in the project definition of a native app, and execute processors in order of specification for each of the artifact object.
|
|
65
|
-
May have side-effects on the filesystem by either directly editing source files or the deploy root.
|
|
66
|
-
"""
|
|
67
|
-
|
|
68
|
-
if not self._should_invoke_processors():
|
|
69
|
-
return
|
|
70
|
-
|
|
71
|
-
with cc.phase("Invoking artifact processors"):
|
|
72
|
-
if self._na_project.generated_root.exists():
|
|
73
|
-
raise ClickException(
|
|
74
|
-
f"Path {self._na_project.generated_root} already exists. Please choose a different name for your generated directory in the project definition file."
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
for artifact in self._na_project.artifacts:
|
|
78
|
-
for processor in artifact.processors:
|
|
79
|
-
if self._is_enabled(processor):
|
|
80
|
-
artifact_processor = self._try_create_processor(
|
|
81
|
-
processor_mapping=processor,
|
|
82
|
-
)
|
|
83
|
-
if artifact_processor is None:
|
|
84
|
-
raise UnsupportedArtifactProcessorError(
|
|
85
|
-
processor_name=processor.name
|
|
86
|
-
)
|
|
87
|
-
else:
|
|
88
|
-
artifact_processor.process(
|
|
89
|
-
artifact_to_process=artifact,
|
|
90
|
-
processor_mapping=processor,
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
def _try_create_processor(
|
|
94
|
-
self,
|
|
95
|
-
processor_mapping: ProcessorMapping,
|
|
96
|
-
**kwargs,
|
|
97
|
-
) -> Optional[ArtifactProcessor]:
|
|
98
|
-
"""
|
|
99
|
-
Fetch processor object if one already exists in the cached_processors dictionary.
|
|
100
|
-
Else, initialize a new object to return, and add it to the cached_processors dictionary.
|
|
101
|
-
"""
|
|
102
|
-
processor_name = processor_mapping.name.lower()
|
|
103
|
-
current_processor = self.cached_processors.get(processor_name)
|
|
104
|
-
|
|
105
|
-
if current_processor is not None:
|
|
106
|
-
return current_processor
|
|
107
|
-
|
|
108
|
-
processor_factory = _REGISTERED_PROCESSORS_BY_NAME.get(processor_name)
|
|
109
|
-
if processor_factory is None:
|
|
110
|
-
# No registered processor with the specified name
|
|
111
|
-
return None
|
|
112
|
-
|
|
113
|
-
current_processor = processor_factory(
|
|
114
|
-
na_project=self._na_project,
|
|
115
|
-
)
|
|
116
|
-
self.cached_processors[processor_name] = current_processor
|
|
117
|
-
|
|
118
|
-
return current_processor
|
|
119
|
-
|
|
120
|
-
def _should_invoke_processors(self):
|
|
121
|
-
for artifact in self._na_project.artifacts:
|
|
122
|
-
for processor in artifact.processors:
|
|
123
|
-
if self._is_enabled(processor):
|
|
124
|
-
return True
|
|
125
|
-
return False
|
|
126
|
-
|
|
127
|
-
def _is_enabled(self, processor: ProcessorMapping) -> bool:
|
|
128
|
-
if processor.name.lower() == NA_SETUP_PROCESSOR:
|
|
129
|
-
return FeatureFlag.ENABLE_NATIVE_APP_PYTHON_SETUP.is_enabled()
|
|
130
|
-
return True
|
|
@@ -1,306 +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 os
|
|
18
|
-
import shutil
|
|
19
|
-
import subprocess
|
|
20
|
-
import sys
|
|
21
|
-
from enum import Enum
|
|
22
|
-
from pathlib import Path
|
|
23
|
-
from typing import Any, Mapping, Optional, Sequence, Union
|
|
24
|
-
from venv import EnvBuilder
|
|
25
|
-
|
|
26
|
-
from click.exceptions import ClickException
|
|
27
|
-
|
|
28
|
-
EnvVars = Mapping[str, str] # Only support str -> str for cross-platform compatibility
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
class SandboxExecutionError(ClickException):
|
|
32
|
-
"""An error occurred while executing a python script."""
|
|
33
|
-
|
|
34
|
-
def __init__(self, error: str):
|
|
35
|
-
super().__init__(f"Failed to execute python script. {error}")
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def _get_active_venv_dir() -> Optional[str]:
|
|
39
|
-
return os.environ.get("VIRTUAL_ENV")
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def _get_active_conda_env() -> Optional[str]:
|
|
43
|
-
return os.environ.get("CONDA_DEFAULT_ENV")
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def _is_venv_active() -> bool:
|
|
47
|
-
return _get_active_venv_dir() is not None
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def _is_conda_active() -> bool:
|
|
51
|
-
return _get_active_conda_env() is not None
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def _is_ms_windows() -> bool:
|
|
55
|
-
return sys.platform == "win32"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def _execute_python_interpreter(
|
|
59
|
-
python_executable: Optional[Union[str, Path, Sequence[str]]],
|
|
60
|
-
script_source: str,
|
|
61
|
-
cwd: Optional[Union[str, Path]],
|
|
62
|
-
timeout: Optional[int],
|
|
63
|
-
env_vars: Optional[EnvVars],
|
|
64
|
-
) -> subprocess.CompletedProcess:
|
|
65
|
-
if not python_executable:
|
|
66
|
-
raise SandboxExecutionError("No python executable found")
|
|
67
|
-
|
|
68
|
-
if isinstance(python_executable, str) or isinstance(python_executable, Path):
|
|
69
|
-
args = [python_executable]
|
|
70
|
-
else:
|
|
71
|
-
args = [arg for arg in python_executable]
|
|
72
|
-
args.append("-")
|
|
73
|
-
return subprocess.run(
|
|
74
|
-
args,
|
|
75
|
-
capture_output=True,
|
|
76
|
-
text=True,
|
|
77
|
-
input=script_source,
|
|
78
|
-
timeout=timeout,
|
|
79
|
-
cwd=cwd,
|
|
80
|
-
env=env_vars,
|
|
81
|
-
)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
def _execute_in_venv(
|
|
85
|
-
script_source: str,
|
|
86
|
-
venv_path: Optional[Union[str, Path]] = None,
|
|
87
|
-
cwd: Optional[Union[str, Path]] = None,
|
|
88
|
-
timeout: Optional[int] = None,
|
|
89
|
-
env_vars: Optional[EnvVars] = None,
|
|
90
|
-
) -> subprocess.CompletedProcess:
|
|
91
|
-
resolved_venv_path = None
|
|
92
|
-
if venv_path is None:
|
|
93
|
-
active_venv_dir = _get_active_venv_dir()
|
|
94
|
-
if active_venv_dir is not None:
|
|
95
|
-
resolved_venv_path = Path(active_venv_dir).resolve()
|
|
96
|
-
elif isinstance(venv_path, str):
|
|
97
|
-
resolved_venv_path = Path(venv_path).resolve()
|
|
98
|
-
else:
|
|
99
|
-
resolved_venv_path = venv_path.resolve()
|
|
100
|
-
|
|
101
|
-
if resolved_venv_path is None:
|
|
102
|
-
raise SandboxExecutionError("No venv root found")
|
|
103
|
-
|
|
104
|
-
if not resolved_venv_path.is_dir():
|
|
105
|
-
raise SandboxExecutionError(
|
|
106
|
-
f"venv path must be an existing directory: {resolved_venv_path}"
|
|
107
|
-
)
|
|
108
|
-
|
|
109
|
-
# find the python interpreter for this environment. There is no need to activate environment prior to invoking the
|
|
110
|
-
# interpreter, as venv maintains the invariant that invoking any of the scripts will set up the virtual environment
|
|
111
|
-
# correctly. activation scripts are only used for convenience in interactive shells.
|
|
112
|
-
if _is_ms_windows():
|
|
113
|
-
python_executable = resolved_venv_path / "Scripts" / "python.exe"
|
|
114
|
-
else:
|
|
115
|
-
python_executable = resolved_venv_path / "bin" / "python3"
|
|
116
|
-
|
|
117
|
-
if not python_executable.is_file():
|
|
118
|
-
raise SandboxExecutionError(
|
|
119
|
-
f"No venv python executable found: {resolved_venv_path}"
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
return _execute_python_interpreter(
|
|
123
|
-
python_executable, script_source, timeout=timeout, cwd=cwd, env_vars=env_vars
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
def _execute_in_conda_env(
|
|
128
|
-
script_source: str,
|
|
129
|
-
env_name: Optional[str] = None,
|
|
130
|
-
cwd: Optional[Union[str, Path]] = None,
|
|
131
|
-
timeout: Optional[int] = None,
|
|
132
|
-
env_vars: Optional[EnvVars] = None,
|
|
133
|
-
) -> subprocess.CompletedProcess:
|
|
134
|
-
conda_env = env_name
|
|
135
|
-
if conda_env is None:
|
|
136
|
-
conda_env = _get_active_conda_env()
|
|
137
|
-
if conda_env is None:
|
|
138
|
-
raise SandboxExecutionError("No conda environment found")
|
|
139
|
-
|
|
140
|
-
conda_exec = shutil.which("conda")
|
|
141
|
-
if conda_exec is None:
|
|
142
|
-
raise SandboxExecutionError(
|
|
143
|
-
"conda command not found, make sure it is installed on your system and in your PATH"
|
|
144
|
-
)
|
|
145
|
-
|
|
146
|
-
# conda run removes the need to activate the environment, as would typically be done in an interactive shell
|
|
147
|
-
return _execute_python_interpreter(
|
|
148
|
-
[conda_exec, "run", "-n", conda_env, "--no-capture-output", "python"],
|
|
149
|
-
script_source,
|
|
150
|
-
timeout=timeout,
|
|
151
|
-
cwd=cwd,
|
|
152
|
-
env_vars=env_vars,
|
|
153
|
-
)
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
def _execute_with_system_path_python(
|
|
157
|
-
script_source: str,
|
|
158
|
-
cwd: Optional[Union[str, Path]] = None,
|
|
159
|
-
timeout: Optional[int] = None,
|
|
160
|
-
env_vars: Optional[EnvVars] = None,
|
|
161
|
-
) -> subprocess.CompletedProcess:
|
|
162
|
-
python_executable = (
|
|
163
|
-
shutil.which("python3") or shutil.which("python") or sys.executable
|
|
164
|
-
)
|
|
165
|
-
|
|
166
|
-
return _execute_python_interpreter(
|
|
167
|
-
python_executable,
|
|
168
|
-
script_source,
|
|
169
|
-
timeout=timeout,
|
|
170
|
-
cwd=cwd,
|
|
171
|
-
env_vars=env_vars,
|
|
172
|
-
)
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
class ExecutionEnvironmentType(Enum):
|
|
176
|
-
AUTO_DETECT = 0 # auto-detect the current python interpreter by looking for an active virtual environment
|
|
177
|
-
VENV = 1 # use the python interpreter specified by a venv environment
|
|
178
|
-
CONDA = 2 # use the python interpreter specified by a conda environment
|
|
179
|
-
SYSTEM_PATH = 3 # search for a python interpreter in the system path
|
|
180
|
-
CURRENT = 4 # Use the python interpreter that is currently executing (i.e. `sys.executable`)
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
def execute_script_in_sandbox(
|
|
184
|
-
script_source: str,
|
|
185
|
-
env_type: ExecutionEnvironmentType = ExecutionEnvironmentType.AUTO_DETECT,
|
|
186
|
-
cwd: Optional[Union[str, Path]] = None,
|
|
187
|
-
timeout: Optional[int] = None,
|
|
188
|
-
env_vars: Optional[EnvVars] = None,
|
|
189
|
-
**kwargs,
|
|
190
|
-
) -> subprocess.CompletedProcess:
|
|
191
|
-
"""
|
|
192
|
-
Executes a python script in a sandboxed environment, and returns its output. The script is executed in a different
|
|
193
|
-
process. The execution environment is determined by the `env_type` argument. By default, the logic will attempt
|
|
194
|
-
to auto-detect the correct environment by looking for an active venv or conda environment. If none can be found, it
|
|
195
|
-
will use the system's default python executable, as determined by the user's path. As a last resort, the current
|
|
196
|
-
python execution environment will be used (still in a subprocess).
|
|
197
|
-
|
|
198
|
-
Parameters:
|
|
199
|
-
script_source (str): The python script to be executed, as a string.
|
|
200
|
-
env_type: The type of execution environment to use (default: ExecutionEnvironmentType.AUTO_DETECT).
|
|
201
|
-
cwd (Optional[Union[str, Path]]): An optional path to use as the current directory when executing the script.
|
|
202
|
-
timeout (Optional[int]): An optional timeout in seconds when executing the script. Defaults to no timeout.
|
|
203
|
-
**kwargs: Additional keyword arguments used by specific execution environments, as follows:
|
|
204
|
-
- venv environments accept a 'path' argument to specify the venv root directory.
|
|
205
|
-
- conda environments accept a 'name' argument to specify the name of the conda environment to use.
|
|
206
|
-
Returns:
|
|
207
|
-
A subprocess.CompletedProcess object containing the output of the script, if any.
|
|
208
|
-
"""
|
|
209
|
-
if env_type == ExecutionEnvironmentType.AUTO_DETECT:
|
|
210
|
-
if _is_venv_active():
|
|
211
|
-
return _execute_in_venv(
|
|
212
|
-
script_source, cwd=cwd, timeout=timeout, env_vars=env_vars
|
|
213
|
-
)
|
|
214
|
-
elif _is_conda_active():
|
|
215
|
-
return _execute_in_conda_env(
|
|
216
|
-
script_source, cwd=cwd, timeout=timeout, env_vars=env_vars
|
|
217
|
-
)
|
|
218
|
-
else:
|
|
219
|
-
return _execute_with_system_path_python(
|
|
220
|
-
script_source, cwd=cwd, timeout=timeout, env_vars=env_vars
|
|
221
|
-
)
|
|
222
|
-
elif env_type == ExecutionEnvironmentType.VENV:
|
|
223
|
-
return _execute_in_venv(
|
|
224
|
-
script_source,
|
|
225
|
-
kwargs.get("path"),
|
|
226
|
-
cwd=cwd,
|
|
227
|
-
timeout=timeout,
|
|
228
|
-
env_vars=env_vars,
|
|
229
|
-
)
|
|
230
|
-
elif env_type == ExecutionEnvironmentType.CONDA:
|
|
231
|
-
return _execute_in_conda_env(
|
|
232
|
-
script_source,
|
|
233
|
-
kwargs.get("name"),
|
|
234
|
-
cwd=cwd,
|
|
235
|
-
timeout=timeout,
|
|
236
|
-
env_vars=env_vars,
|
|
237
|
-
)
|
|
238
|
-
elif env_type == ExecutionEnvironmentType.SYSTEM_PATH:
|
|
239
|
-
return _execute_with_system_path_python(
|
|
240
|
-
script_source, cwd=cwd, timeout=timeout, env_vars=env_vars
|
|
241
|
-
)
|
|
242
|
-
else: # ExecutionEnvironmentType.CURRENT
|
|
243
|
-
return _execute_python_interpreter(
|
|
244
|
-
sys.executable, script_source, cwd=cwd, timeout=timeout, env_vars=env_vars
|
|
245
|
-
)
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
class SandboxEnvBuilder(EnvBuilder):
|
|
249
|
-
"""
|
|
250
|
-
A virtual environment builder that can be used to build an environment suitable for
|
|
251
|
-
executing user-provided python scripts in an isolated sandbox.
|
|
252
|
-
"""
|
|
253
|
-
|
|
254
|
-
def __init__(self, path: Path, **kwargs) -> None:
|
|
255
|
-
"""
|
|
256
|
-
Creates a new builder with the specified destination path. The path need not
|
|
257
|
-
exist, it will be created when needed (recursively if necessary).
|
|
258
|
-
|
|
259
|
-
Parameters:
|
|
260
|
-
path (Path): The directory in which the sandbox environment will be created.
|
|
261
|
-
"""
|
|
262
|
-
super().__init__(**kwargs)
|
|
263
|
-
self.path = path
|
|
264
|
-
self._context: Any = None # cached context
|
|
265
|
-
|
|
266
|
-
def post_setup(self, context) -> None:
|
|
267
|
-
self._context = context
|
|
268
|
-
|
|
269
|
-
def ensure_created(self) -> None:
|
|
270
|
-
"""
|
|
271
|
-
Ensures that the sandbox environment has been created and correctly initialized.
|
|
272
|
-
"""
|
|
273
|
-
if self.path.exists():
|
|
274
|
-
self._context = self.ensure_directories(self.path)
|
|
275
|
-
else:
|
|
276
|
-
self.path.mkdir(parents=True, exist_ok=True)
|
|
277
|
-
self.create(
|
|
278
|
-
self.path
|
|
279
|
-
) # will set self._context through the post_setup callback
|
|
280
|
-
|
|
281
|
-
def run_python(self, *args) -> str:
|
|
282
|
-
"""
|
|
283
|
-
Executes the python interpreter in the sandboxed environment with the provided arguments.
|
|
284
|
-
This raises a CalledProcessError if the python interpreter was not executed successfully.
|
|
285
|
-
|
|
286
|
-
Returns:
|
|
287
|
-
The output of running the command.
|
|
288
|
-
"""
|
|
289
|
-
positional_args = [
|
|
290
|
-
self._context.env_exe,
|
|
291
|
-
"-E", # passing -E ignores all PYTHON* env vars
|
|
292
|
-
*args,
|
|
293
|
-
]
|
|
294
|
-
kwargs = {
|
|
295
|
-
"cwd": self._context.env_dir,
|
|
296
|
-
"stderr": subprocess.STDOUT,
|
|
297
|
-
}
|
|
298
|
-
env = dict(os.environ)
|
|
299
|
-
env["VIRTUAL_ENV"] = self._context.env_dir
|
|
300
|
-
return subprocess.check_output(positional_args, **kwargs)
|
|
301
|
-
|
|
302
|
-
def pip_install(self, *args: Any) -> None:
|
|
303
|
-
"""
|
|
304
|
-
Invokes pip install with the provided arguments.
|
|
305
|
-
"""
|
|
306
|
-
self.run_python("-m", "pip", "install", *[str(arg) for arg in args])
|