snowflake-cli-labs 2.8.0rc1__py3-none-any.whl → 3.0.0rc1__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 +24 -17
- snowflake/cli/{app → _app}/telemetry.py +4 -5
- snowflake/cli/{plugins → _plugins}/connection/commands.py +25 -7
- 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 +20 -11
- 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 +32 -18
- snowflake/cli/_plugins/nativeapp/codegen/setup/native_app_setup_processor.py +249 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/setup/setup_driver.py.source +5 -2
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/extension_function_utils.py +4 -4
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/python_processor.py +23 -29
- snowflake/cli/_plugins/nativeapp/codegen/templates/templates_processor.py +93 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/commands.py +171 -42
- snowflake/cli/{plugins → _plugins}/nativeapp/common_flags.py +1 -1
- snowflake/cli/{plugins → _plugins}/nativeapp/exceptions.py +3 -3
- snowflake/cli/{plugins → _plugins}/nativeapp/init.py +1 -1
- snowflake/cli/_plugins/nativeapp/manager.py +572 -0
- snowflake/cli/{plugins/connection → _plugins/nativeapp}/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/nativeapp/project_model.py +35 -19
- snowflake/cli/{plugins → _plugins}/nativeapp/run_processor.py +25 -23
- snowflake/cli/{plugins → _plugins}/nativeapp/teardown_processor.py +24 -110
- 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 +450 -0
- snowflake/cli/_plugins/snowpark/common.py +268 -0
- snowflake/cli/{plugins → _plugins}/snowpark/models.py +0 -7
- snowflake/cli/{plugins → _plugins}/snowpark/package/anaconda_packages.py +2 -36
- snowflake/cli/{plugins → _plugins}/snowpark/package/commands.py +13 -74
- snowflake/cli/{plugins → _plugins}/snowpark/package/manager.py +4 -3
- snowflake/cli/{plugins → _plugins}/snowpark/package_utils.py +5 -5
- snowflake/cli/{plugins/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 +20 -17
- snowflake/cli/{plugins → _plugins}/sql/manager.py +1 -1
- snowflake/cli/{plugins → _plugins}/sql/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/stage/commands.py +20 -17
- snowflake/cli/{plugins → _plugins}/stage/diff.py +1 -47
- snowflake/cli/{plugins → _plugins}/stage/manager.py +54 -21
- snowflake/cli/{plugins → _plugins}/stage/plugin_spec.py +1 -1
- snowflake/cli/_plugins/stage/utils.py +54 -0
- snowflake/cli/{plugins → _plugins}/streamlit/commands.py +59 -62
- snowflake/cli/{plugins → _plugins}/streamlit/manager.py +51 -70
- snowflake/cli/_plugins/streamlit/plugin_spec.py +30 -0
- snowflake/cli/_plugins/workspace/action_context.py +17 -0
- snowflake/cli/_plugins/workspace/commands.py +194 -0
- snowflake/cli/_plugins/workspace/manager.py +73 -0
- snowflake/cli/{plugins → _plugins}/workspace/plugin_spec.py +1 -1
- snowflake/cli/api/cli_global_context.py +40 -13
- snowflake/cli/api/commands/common.py +25 -0
- snowflake/cli/api/commands/decorators.py +5 -4
- snowflake/cli/api/commands/experimental_behaviour.py +2 -3
- snowflake/cli/api/commands/flags.py +97 -179
- snowflake/cli/api/commands/overrideable_parameter.py +143 -0
- snowflake/cli/api/commands/snow_typer.py +14 -6
- snowflake/cli/api/commands/typer_pre_execute.py +3 -3
- snowflake/cli/api/commands/utils.py +18 -0
- snowflake/cli/api/config.py +18 -5
- snowflake/cli/api/console/abc.py +5 -2
- snowflake/cli/api/constants.py +11 -0
- snowflake/cli/api/entities/application_entity.py +12 -0
- snowflake/cli/api/entities/application_package_entity.py +553 -0
- snowflake/cli/api/entities/common.py +51 -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 +357 -0
- snowflake/cli/api/exceptions.py +31 -5
- snowflake/cli/api/feature_flags.py +0 -1
- snowflake/cli/api/identifiers.py +41 -9
- snowflake/cli/api/project/definition.py +37 -6
- snowflake/cli/api/project/definition_conversion.py +194 -0
- snowflake/cli/api/project/definition_manager.py +12 -1
- snowflake/cli/api/project/project_verification.py +3 -3
- snowflake/cli/api/project/schemas/entities/{application_entity.py → application_entity_model.py} +21 -9
- snowflake/cli/api/project/schemas/entities/{application_package_entity.py → application_package_entity_model.py} +43 -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 +98 -27
- snowflake/cli/api/project/schemas/updatable_model.py +11 -3
- snowflake/cli/api/project/util.py +23 -6
- snowflake/cli/api/rendering/jinja.py +14 -8
- snowflake/cli/api/rendering/project_definition_templates.py +1 -1
- snowflake/cli/api/rendering/sql_templates.py +43 -11
- snowflake/cli/api/secure_path.py +16 -18
- snowflake/cli/api/secure_utils.py +90 -1
- snowflake/cli/api/sql_execution.py +48 -19
- snowflake/cli/api/utils/definition_rendering.py +18 -8
- {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-3.0.0rc1.dist-info}/METADATA +13 -13
- snowflake_cli_labs-3.0.0rc1.dist-info/RECORD +236 -0
- snowflake_cli_labs-3.0.0rc1.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/codegen/setup/native_app_setup_processor.py +0 -172
- snowflake/cli/plugins/nativeapp/manager.py +0 -823
- snowflake/cli/plugins/object_stage_deprecated/__init__.py +0 -15
- snowflake/cli/plugins/object_stage_deprecated/commands.py +0 -122
- snowflake/cli/plugins/object_stage_deprecated/plugin_spec.py +0 -32
- snowflake/cli/plugins/snowpark/commands.py +0 -548
- snowflake/cli/plugins/snowpark/common.py +0 -307
- snowflake/cli/plugins/snowpark/manager.py +0 -109
- snowflake/cli/plugins/snowpark/plugin_spec.py +0 -30
- snowflake/cli/plugins/snowpark/snowpark_package_paths.py +0 -65
- snowflake/cli/plugins/spcs/jobs/commands.py +0 -78
- snowflake/cli/plugins/spcs/jobs/manager.py +0 -53
- snowflake/cli/plugins/streamlit/plugin_spec.py +0 -30
- snowflake/cli/plugins/workspace/commands.py +0 -35
- snowflake/cli/templates/default_snowpark/.gitignore +0 -4
- snowflake/cli/templates/default_snowpark/app/__init__.py +0 -0
- snowflake/cli/templates/default_snowpark/app/common.py +0 -2
- snowflake/cli/templates/default_snowpark/app/functions.py +0 -15
- snowflake/cli/templates/default_snowpark/app/procedures.py +0 -22
- snowflake/cli/templates/default_snowpark/requirements.txt +0 -1
- snowflake/cli/templates/default_snowpark/snowflake.yml +0 -23
- snowflake/cli/templates/default_streamlit/.gitignore +0 -4
- snowflake/cli/templates/default_streamlit/common/hello.py +0 -2
- snowflake/cli/templates/default_streamlit/environment.yml +0 -6
- snowflake/cli/templates/default_streamlit/pages/my_page.py +0 -3
- snowflake/cli/templates/default_streamlit/snowflake.yml +0 -10
- snowflake/cli/templates/default_streamlit/streamlit_app.py +0 -4
- snowflake_cli_labs-2.8.0rc1.dist-info/RECORD +0 -240
- snowflake_cli_labs-2.8.0rc1.dist-info/entry_points.txt +0 -2
- /snowflake/cli/{app → _app}/__init__.py +0 -0
- /snowflake/cli/{app → _app}/api_impl/__init__.py +0 -0
- /snowflake/cli/{app → _app}/api_impl/plugin/__init__.py +0 -0
- /snowflake/cli/{app → _app}/api_impl/plugin/plugin_config_provider_impl.py +0 -0
- /snowflake/cli/{app → _app}/commands_registration/__init__.py +0 -0
- /snowflake/cli/{app → _app}/commands_registration/threadsafe.py +0 -0
- /snowflake/cli/{app → _app}/constants.py +0 -0
- /snowflake/cli/{app → _app}/dev/__init__.py +0 -0
- /snowflake/cli/{app → _app}/dev/commands_structure.py +0 -0
- /snowflake/cli/{app → _app}/dev/docs/__init__.py +0 -0
- /snowflake/cli/{app → _app}/dev/docs/project_definition_generate_json_schema.py +0 -0
- /snowflake/cli/{app → _app}/dev/docs/template_utils.py +0 -0
- /snowflake/cli/{app → _app}/dev/docs/templates/definition_description.rst.jinja2 +0 -0
- /snowflake/cli/{app → _app}/dev/docs/templates/overview.rst.jinja2 +0 -0
- /snowflake/cli/{app → _app}/dev/pycharm_remote_debug.py +0 -0
- /snowflake/cli/{app → _app}/loggers.py +0 -0
- /snowflake/cli/{plugins → _plugins}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/connection/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/cortex/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/cortex/types.py +0 -0
- /snowflake/cli/{plugins → _plugins}/git/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/init/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/sandbox.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/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/feature_flags.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/policy.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/utils.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/version/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/notebook/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/notebook/exceptions.py +0 -0
- /snowflake/cli/{plugins → _plugins}/object/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/object/common.py +0 -0
- /snowflake/cli/{plugins → _plugins}/snowpark/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/snowpark/package/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/snowpark/package/utils.py +0 -0
- /snowflake/cli/{plugins → _plugins}/spcs/common.py +0 -0
- /snowflake/cli/{plugins → _plugins}/spcs/compute_pool/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/spcs/image_registry/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/spcs/image_registry/manager.py +0 -0
- /snowflake/cli/{plugins → _plugins}/spcs/image_repository/__init__.py +0 -0
- /snowflake/cli/{plugins/spcs/jobs → _plugins/spcs/services}/__init__.py +0 -0
- /snowflake/cli/{plugins/spcs/services → _plugins/sql}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/sql/snowsql_templating.py +0 -0
- /snowflake/cli/{plugins/sql → _plugins/stage}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/stage/md5.py +0 -0
- /snowflake/cli/{plugins/stage → _plugins/streamlit}/__init__.py +0 -0
- /snowflake/cli/{plugins/streamlit → _plugins/workspace}/__init__.py +0 -0
- /snowflake/cli/{plugins/workspace → api/project/schemas/entities}/__init__.py +0 -0
- {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-3.0.0rc1.dist-info}/WHEEL +0 -0
- {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-3.0.0rc1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Copyright (c) 2024 Snowflake Inc.
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
|
|
15
|
+
from dataclasses import dataclass
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
from typing import (
|
|
18
|
+
List,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
from snowflake.cli.api.project.schemas.native_app.path_mapping import PathMapping
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass
|
|
25
|
+
class BundleContext:
|
|
26
|
+
package_name: str
|
|
27
|
+
artifacts: List[PathMapping]
|
|
28
|
+
project_root: Path
|
|
29
|
+
bundle_root: Path
|
|
30
|
+
deploy_root: Path
|
|
31
|
+
generated_root: Path
|
|
@@ -19,11 +19,11 @@ from pathlib import Path
|
|
|
19
19
|
from typing import Optional
|
|
20
20
|
|
|
21
21
|
from click import ClickException
|
|
22
|
+
from snowflake.cli._plugins.nativeapp.bundle_context import BundleContext
|
|
22
23
|
from snowflake.cli.api.project.schemas.native_app.path_mapping import (
|
|
23
24
|
PathMapping,
|
|
24
25
|
ProcessorMapping,
|
|
25
26
|
)
|
|
26
|
-
from snowflake.cli.plugins.nativeapp.project_model import NativeAppProjectModel
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
class UnsupportedArtifactProcessorError(ClickException):
|
|
@@ -74,9 +74,9 @@ class ProjectFileContextManager:
|
|
|
74
74
|
class ArtifactProcessor(ABC):
|
|
75
75
|
def __init__(
|
|
76
76
|
self,
|
|
77
|
-
|
|
77
|
+
bundle_ctx: BundleContext,
|
|
78
78
|
) -> None:
|
|
79
|
-
self.
|
|
79
|
+
self._bundle_ctx = bundle_ctx
|
|
80
80
|
|
|
81
81
|
@abstractmethod
|
|
82
82
|
def process(
|
|
@@ -14,31 +14,39 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
+
import copy
|
|
18
|
+
import re
|
|
17
19
|
from typing import Dict, Optional
|
|
18
20
|
|
|
19
|
-
from
|
|
20
|
-
from snowflake.cli.
|
|
21
|
-
|
|
22
|
-
)
|
|
23
|
-
from snowflake.cli.plugins.nativeapp.codegen.artifact_processor import (
|
|
21
|
+
from click import ClickException
|
|
22
|
+
from snowflake.cli._plugins.nativeapp.bundle_context import BundleContext
|
|
23
|
+
from snowflake.cli._plugins.nativeapp.codegen.artifact_processor import (
|
|
24
24
|
ArtifactProcessor,
|
|
25
25
|
UnsupportedArtifactProcessorError,
|
|
26
26
|
)
|
|
27
|
-
from snowflake.cli.
|
|
27
|
+
from snowflake.cli._plugins.nativeapp.codegen.setup.native_app_setup_processor import (
|
|
28
28
|
NativeAppSetupProcessor,
|
|
29
29
|
)
|
|
30
|
-
from snowflake.cli.
|
|
30
|
+
from snowflake.cli._plugins.nativeapp.codegen.snowpark.python_processor import (
|
|
31
31
|
SnowparkAnnotationProcessor,
|
|
32
32
|
)
|
|
33
|
-
from snowflake.cli.
|
|
34
|
-
|
|
33
|
+
from snowflake.cli._plugins.nativeapp.codegen.templates.templates_processor import (
|
|
34
|
+
TemplatesProcessor,
|
|
35
|
+
)
|
|
36
|
+
from snowflake.cli._plugins.nativeapp.feature_flags import FeatureFlag
|
|
37
|
+
from snowflake.cli.api.console import cli_console as cc
|
|
38
|
+
from snowflake.cli.api.project.schemas.native_app.path_mapping import (
|
|
39
|
+
ProcessorMapping,
|
|
40
|
+
)
|
|
35
41
|
|
|
36
42
|
SNOWPARK_PROCESSOR = "snowpark"
|
|
37
|
-
NA_SETUP_PROCESSOR = "native
|
|
43
|
+
NA_SETUP_PROCESSOR = "native app setup"
|
|
44
|
+
TEMPLATES_PROCESSOR = "templates"
|
|
38
45
|
|
|
39
46
|
_REGISTERED_PROCESSORS_BY_NAME = {
|
|
40
47
|
SNOWPARK_PROCESSOR: SnowparkAnnotationProcessor,
|
|
41
48
|
NA_SETUP_PROCESSOR: NativeAppSetupProcessor,
|
|
49
|
+
TEMPLATES_PROCESSOR: TemplatesProcessor,
|
|
42
50
|
}
|
|
43
51
|
|
|
44
52
|
|
|
@@ -53,9 +61,9 @@ class NativeAppCompiler:
|
|
|
53
61
|
|
|
54
62
|
def __init__(
|
|
55
63
|
self,
|
|
56
|
-
|
|
64
|
+
bundle_ctx: BundleContext,
|
|
57
65
|
):
|
|
58
|
-
self.
|
|
66
|
+
self._bundle_ctx = bundle_ctx
|
|
59
67
|
# dictionary of all processors created and shared between different artifact objects.
|
|
60
68
|
self.cached_processors: Dict[str, ArtifactProcessor] = {}
|
|
61
69
|
|
|
@@ -69,12 +77,12 @@ class NativeAppCompiler:
|
|
|
69
77
|
return
|
|
70
78
|
|
|
71
79
|
with cc.phase("Invoking artifact processors"):
|
|
72
|
-
if self.
|
|
80
|
+
if self._bundle_ctx.generated_root.exists():
|
|
73
81
|
raise ClickException(
|
|
74
|
-
f"Path {self.
|
|
82
|
+
f"Path {self._bundle_ctx.generated_root} already exists. Please choose a different name for your generated directory in the project definition file."
|
|
75
83
|
)
|
|
76
84
|
|
|
77
|
-
for artifact in self.
|
|
85
|
+
for artifact in self._bundle_ctx.artifacts:
|
|
78
86
|
for processor in artifact.processors:
|
|
79
87
|
if self._is_enabled(processor):
|
|
80
88
|
artifact_processor = self._try_create_processor(
|
|
@@ -110,15 +118,21 @@ class NativeAppCompiler:
|
|
|
110
118
|
# No registered processor with the specified name
|
|
111
119
|
return None
|
|
112
120
|
|
|
113
|
-
|
|
114
|
-
|
|
121
|
+
processor_ctx = copy.copy(self._bundle_ctx)
|
|
122
|
+
processor_subdirectory = re.sub(r"[^a-zA-Z0-9_$]", "_", processor_name)
|
|
123
|
+
processor_ctx.bundle_root = (
|
|
124
|
+
self._bundle_ctx.bundle_root / processor_subdirectory
|
|
125
|
+
)
|
|
126
|
+
processor_ctx.generated_root = (
|
|
127
|
+
self._bundle_ctx.generated_root / processor_subdirectory
|
|
115
128
|
)
|
|
129
|
+
current_processor = processor_factory(processor_ctx)
|
|
116
130
|
self.cached_processors[processor_name] = current_processor
|
|
117
131
|
|
|
118
132
|
return current_processor
|
|
119
133
|
|
|
120
134
|
def _should_invoke_processors(self):
|
|
121
|
-
for artifact in self.
|
|
135
|
+
for artifact in self._bundle_ctx.artifacts:
|
|
122
136
|
for processor in artifact.processors:
|
|
123
137
|
if self._is_enabled(processor):
|
|
124
138
|
return True
|
|
@@ -0,0 +1,249 @@
|
|
|
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 json
|
|
18
|
+
import logging
|
|
19
|
+
import os.path
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import List, Optional
|
|
22
|
+
|
|
23
|
+
import yaml
|
|
24
|
+
from click import ClickException
|
|
25
|
+
from snowflake.cli._plugins.nativeapp.artifacts import (
|
|
26
|
+
BundleMap,
|
|
27
|
+
find_manifest_file,
|
|
28
|
+
find_setup_script_file,
|
|
29
|
+
)
|
|
30
|
+
from snowflake.cli._plugins.nativeapp.codegen.artifact_processor import (
|
|
31
|
+
ArtifactProcessor,
|
|
32
|
+
is_python_file_artifact,
|
|
33
|
+
)
|
|
34
|
+
from snowflake.cli._plugins.nativeapp.codegen.sandbox import (
|
|
35
|
+
ExecutionEnvironmentType,
|
|
36
|
+
SandboxEnvBuilder,
|
|
37
|
+
execute_script_in_sandbox,
|
|
38
|
+
)
|
|
39
|
+
from snowflake.cli._plugins.stage.diff import to_stage_path
|
|
40
|
+
from snowflake.cli.api.console import cli_console as cc
|
|
41
|
+
from snowflake.cli.api.project.schemas.native_app.path_mapping import (
|
|
42
|
+
PathMapping,
|
|
43
|
+
ProcessorMapping,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
DEFAULT_TIMEOUT = 30
|
|
47
|
+
DRIVER_PATH = Path(__file__).parent / "setup_driver.py.source"
|
|
48
|
+
|
|
49
|
+
log = logging.getLogger(__name__)
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def safe_set(d: dict, *keys: str, **kwargs) -> None:
|
|
53
|
+
"""
|
|
54
|
+
Sets a value in a nested dictionary structure, creating intermediate dictionaries as needed.
|
|
55
|
+
Sample usage:
|
|
56
|
+
|
|
57
|
+
d = {}
|
|
58
|
+
safe_set(d, "a", "b", "c", value=42)
|
|
59
|
+
|
|
60
|
+
d is now:
|
|
61
|
+
{
|
|
62
|
+
"a": {
|
|
63
|
+
"b": {
|
|
64
|
+
"c": 42
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
"""
|
|
69
|
+
curr = d
|
|
70
|
+
for k in keys[:-1]:
|
|
71
|
+
curr = curr.setdefault(k, {})
|
|
72
|
+
|
|
73
|
+
curr[keys[-1]] = kwargs.get("value")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class NativeAppSetupProcessor(ArtifactProcessor):
|
|
77
|
+
def __init__(self, *args, **kwargs):
|
|
78
|
+
super().__init__(*args, **kwargs)
|
|
79
|
+
|
|
80
|
+
def process(
|
|
81
|
+
self,
|
|
82
|
+
artifact_to_process: PathMapping,
|
|
83
|
+
processor_mapping: Optional[ProcessorMapping],
|
|
84
|
+
**kwargs,
|
|
85
|
+
) -> None:
|
|
86
|
+
"""
|
|
87
|
+
Processes a Python setup script and generates the corresponding SQL commands.
|
|
88
|
+
"""
|
|
89
|
+
bundle_map = BundleMap(
|
|
90
|
+
project_root=self._bundle_ctx.project_root,
|
|
91
|
+
deploy_root=self._bundle_ctx.deploy_root,
|
|
92
|
+
)
|
|
93
|
+
bundle_map.add(artifact_to_process)
|
|
94
|
+
|
|
95
|
+
self._create_or_update_sandbox()
|
|
96
|
+
|
|
97
|
+
cc.step("Processing Python setup files")
|
|
98
|
+
|
|
99
|
+
files_to_process = []
|
|
100
|
+
for src_file, dest_file in bundle_map.all_mappings(
|
|
101
|
+
absolute=True, expand_directories=True, predicate=is_python_file_artifact
|
|
102
|
+
):
|
|
103
|
+
cc.message(
|
|
104
|
+
f"Found Python setup file: {src_file.relative_to(self._bundle_ctx.project_root)}"
|
|
105
|
+
)
|
|
106
|
+
files_to_process.append(src_file)
|
|
107
|
+
|
|
108
|
+
result = self._execute_in_sandbox(files_to_process)
|
|
109
|
+
if not result:
|
|
110
|
+
return # nothing to do
|
|
111
|
+
|
|
112
|
+
logs = result.get("logs", [])
|
|
113
|
+
for msg in logs:
|
|
114
|
+
log.debug(msg)
|
|
115
|
+
|
|
116
|
+
warnings = result.get("warnings", [])
|
|
117
|
+
for msg in warnings:
|
|
118
|
+
cc.warning(msg)
|
|
119
|
+
|
|
120
|
+
schema_version = result.get("schema_version")
|
|
121
|
+
if schema_version != "1":
|
|
122
|
+
raise ClickException(
|
|
123
|
+
f"Unsupported schema version returned from snowflake-app-python library: {schema_version}"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
setup_script_mods = [
|
|
127
|
+
mod
|
|
128
|
+
for mod in result.get("modifications", [])
|
|
129
|
+
if mod.get("target") == "native_app:setup_script"
|
|
130
|
+
]
|
|
131
|
+
if setup_script_mods:
|
|
132
|
+
self._edit_setup_sql(setup_script_mods)
|
|
133
|
+
|
|
134
|
+
manifest_mods = [
|
|
135
|
+
mod
|
|
136
|
+
for mod in result.get("modifications", [])
|
|
137
|
+
if mod.get("target") == "native_app:manifest"
|
|
138
|
+
]
|
|
139
|
+
if manifest_mods:
|
|
140
|
+
self._edit_manifest(manifest_mods)
|
|
141
|
+
|
|
142
|
+
def _execute_in_sandbox(self, py_files: List[Path]) -> dict:
|
|
143
|
+
file_count = len(py_files)
|
|
144
|
+
cc.step(f"Processing {file_count} setup file{'s' if file_count > 1 else ''}")
|
|
145
|
+
|
|
146
|
+
manifest_path = find_manifest_file(deploy_root=self._bundle_ctx.deploy_root)
|
|
147
|
+
|
|
148
|
+
generated_root = self._bundle_ctx.generated_root
|
|
149
|
+
generated_root.mkdir(exist_ok=True, parents=True)
|
|
150
|
+
|
|
151
|
+
env_vars = {
|
|
152
|
+
"_SNOWFLAKE_CLI_PROJECT_PATH": str(self._bundle_ctx.project_root),
|
|
153
|
+
"_SNOWFLAKE_CLI_SETUP_FILES": os.pathsep.join(map(str, py_files)),
|
|
154
|
+
"_SNOWFLAKE_CLI_APP_NAME": str(self._bundle_ctx.package_name),
|
|
155
|
+
"_SNOWFLAKE_CLI_SQL_DEST_DIR": str(generated_root),
|
|
156
|
+
"_SNOWFLAKE_CLI_MANIFEST_PATH": str(manifest_path),
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
try:
|
|
160
|
+
result = execute_script_in_sandbox(
|
|
161
|
+
script_source=DRIVER_PATH.read_text(),
|
|
162
|
+
env_type=ExecutionEnvironmentType.VENV,
|
|
163
|
+
cwd=self._bundle_ctx.bundle_root,
|
|
164
|
+
timeout=DEFAULT_TIMEOUT,
|
|
165
|
+
path=self.sandbox_root,
|
|
166
|
+
env_vars=env_vars,
|
|
167
|
+
)
|
|
168
|
+
except Exception as e:
|
|
169
|
+
raise ClickException(
|
|
170
|
+
f"Exception while executing python setup script logic: {e}"
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
if result.returncode == 0:
|
|
174
|
+
return json.loads(result.stdout)
|
|
175
|
+
else:
|
|
176
|
+
raise ClickException(
|
|
177
|
+
f"Failed to execute python setup script logic: {result.stderr}"
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
def _edit_setup_sql(self, modifications: List[dict]) -> None:
|
|
181
|
+
cc.step("Patching setup script")
|
|
182
|
+
setup_file_path = find_setup_script_file(
|
|
183
|
+
deploy_root=self._bundle_ctx.deploy_root
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
with self.edit_file(setup_file_path) as f:
|
|
187
|
+
prepended = []
|
|
188
|
+
appended = []
|
|
189
|
+
|
|
190
|
+
for mod in modifications:
|
|
191
|
+
for inst in mod.get("instructions", []):
|
|
192
|
+
if inst.get("type") == "insert":
|
|
193
|
+
default_loc = inst.get("default_location")
|
|
194
|
+
if default_loc == "end":
|
|
195
|
+
appended.append(self._setup_mod_instruction_to_sql(inst))
|
|
196
|
+
elif default_loc == "start":
|
|
197
|
+
prepended.append(self._setup_mod_instruction_to_sql(inst))
|
|
198
|
+
|
|
199
|
+
if prepended or appended:
|
|
200
|
+
f.edited_contents = "\n".join(prepended + [f.contents] + appended)
|
|
201
|
+
|
|
202
|
+
def _edit_manifest(self, modifications: List[dict]) -> None:
|
|
203
|
+
cc.step("Patching manifest")
|
|
204
|
+
manifest_path = find_manifest_file(deploy_root=self._bundle_ctx.deploy_root)
|
|
205
|
+
|
|
206
|
+
with self.edit_file(manifest_path) as f:
|
|
207
|
+
manifest = yaml.safe_load(f.contents)
|
|
208
|
+
|
|
209
|
+
for mod in modifications:
|
|
210
|
+
for inst in mod.get("instructions", []):
|
|
211
|
+
if inst.get("type") == "set":
|
|
212
|
+
payload = inst.get("payload")
|
|
213
|
+
if payload:
|
|
214
|
+
key = payload.get("key")
|
|
215
|
+
value = payload.get("value")
|
|
216
|
+
safe_set(manifest, *key.split("."), value=value)
|
|
217
|
+
f.edited_contents = yaml.safe_dump(manifest, sort_keys=False)
|
|
218
|
+
|
|
219
|
+
def _setup_mod_instruction_to_sql(self, mod_inst: dict) -> str:
|
|
220
|
+
payload = mod_inst.get("payload")
|
|
221
|
+
if not payload:
|
|
222
|
+
raise ClickException("Unsupported instruction received: no payload found")
|
|
223
|
+
|
|
224
|
+
payload_type = payload.get("type")
|
|
225
|
+
if payload_type == "execute immediate":
|
|
226
|
+
file_path = payload.get("file_path")
|
|
227
|
+
if file_path:
|
|
228
|
+
sql_file_path = self._bundle_ctx.generated_root / file_path
|
|
229
|
+
return f"EXECUTE IMMEDIATE FROM '/{to_stage_path(sql_file_path.relative_to(self._bundle_ctx.deploy_root))}';"
|
|
230
|
+
|
|
231
|
+
raise ClickException(f"Unsupported instruction type received: {payload_type}")
|
|
232
|
+
|
|
233
|
+
@property
|
|
234
|
+
def sandbox_root(self):
|
|
235
|
+
return self._bundle_ctx.bundle_root / "venv"
|
|
236
|
+
|
|
237
|
+
def _create_or_update_sandbox(self):
|
|
238
|
+
sandbox_root = self.sandbox_root
|
|
239
|
+
env_builder = SandboxEnvBuilder(sandbox_root, with_pip=True)
|
|
240
|
+
if sandbox_root.exists():
|
|
241
|
+
cc.step("Virtual environment found")
|
|
242
|
+
else:
|
|
243
|
+
cc.step(
|
|
244
|
+
f"Creating virtual environment in {sandbox_root.relative_to(self._bundle_ctx.project_root)}"
|
|
245
|
+
)
|
|
246
|
+
env_builder.ensure_created()
|
|
247
|
+
|
|
248
|
+
# Temporarily fetch the library from a location specified via env vars
|
|
249
|
+
env_builder.pip_install(os.environ["SNOWFLAKE_APP_PYTHON_LOC"])
|
|
@@ -20,8 +20,11 @@ from pathlib import Path
|
|
|
20
20
|
import snowflake.app.context as ctx
|
|
21
21
|
from snowflake.app.sql import SQLGenerator
|
|
22
22
|
|
|
23
|
-
ctx.
|
|
24
|
-
ctx.
|
|
23
|
+
ctx.configure("project_path", os.environ.get("_SNOWFLAKE_CLI_PROJECT_PATH", None))
|
|
24
|
+
ctx.configure("manifest_path", os.environ.get("_SNOWFLAKE_CLI_MANIFEST_PATH", None))
|
|
25
|
+
ctx.configure("current_app_name", os.environ.get("_SNOWFLAKE_CLI_APP_NAME", None))
|
|
26
|
+
ctx.configure("enable_sql_generation", True)
|
|
27
|
+
|
|
25
28
|
__snowflake_internal_py_files = os.environ["_SNOWFLAKE_CLI_SETUP_FILES"].split(
|
|
26
29
|
os.pathsep
|
|
27
30
|
)
|
|
@@ -23,6 +23,10 @@ from typing import (
|
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
from click.exceptions import ClickException
|
|
26
|
+
from snowflake.cli._plugins.nativeapp.codegen.snowpark.models import (
|
|
27
|
+
ExtensionFunctionTypeEnum,
|
|
28
|
+
NativeAppExtensionFunction,
|
|
29
|
+
)
|
|
26
30
|
from snowflake.cli.api.project.schemas.snowpark.argument import Argument
|
|
27
31
|
from snowflake.cli.api.project.util import (
|
|
28
32
|
is_valid_identifier,
|
|
@@ -30,10 +34,6 @@ from snowflake.cli.api.project.util import (
|
|
|
30
34
|
to_identifier,
|
|
31
35
|
to_string_literal,
|
|
32
36
|
)
|
|
33
|
-
from snowflake.cli.plugins.nativeapp.codegen.snowpark.models import (
|
|
34
|
-
ExtensionFunctionTypeEnum,
|
|
35
|
-
NativeAppExtensionFunction,
|
|
36
|
-
)
|
|
37
37
|
|
|
38
38
|
ASTDefNode = Union[ast.FunctionDef, ast.ClassDef]
|
|
39
39
|
|
|
@@ -21,26 +21,20 @@ from textwrap import dedent
|
|
|
21
21
|
from typing import Any, Dict, List, Optional, Set
|
|
22
22
|
|
|
23
23
|
from pydantic import ValidationError
|
|
24
|
-
from snowflake.cli.
|
|
25
|
-
from snowflake.cli.api.project.schemas.native_app.path_mapping import (
|
|
26
|
-
PathMapping,
|
|
27
|
-
ProcessorMapping,
|
|
28
|
-
)
|
|
29
|
-
from snowflake.cli.api.rendering.jinja import jinja_render_from_file
|
|
30
|
-
from snowflake.cli.plugins.nativeapp.artifacts import (
|
|
24
|
+
from snowflake.cli._plugins.nativeapp.artifacts import (
|
|
31
25
|
BundleMap,
|
|
32
26
|
find_setup_script_file,
|
|
33
27
|
)
|
|
34
|
-
from snowflake.cli.
|
|
28
|
+
from snowflake.cli._plugins.nativeapp.codegen.artifact_processor import (
|
|
35
29
|
ArtifactProcessor,
|
|
36
30
|
is_python_file_artifact,
|
|
37
31
|
)
|
|
38
|
-
from snowflake.cli.
|
|
32
|
+
from snowflake.cli._plugins.nativeapp.codegen.sandbox import (
|
|
39
33
|
ExecutionEnvironmentType,
|
|
40
34
|
SandboxExecutionError,
|
|
41
35
|
execute_script_in_sandbox,
|
|
42
36
|
)
|
|
43
|
-
from snowflake.cli.
|
|
37
|
+
from snowflake.cli._plugins.nativeapp.codegen.snowpark.extension_function_utils import (
|
|
44
38
|
deannotate_module_source,
|
|
45
39
|
ensure_all_string_literals,
|
|
46
40
|
ensure_string_literal,
|
|
@@ -49,12 +43,17 @@ from snowflake.cli.plugins.nativeapp.codegen.snowpark.extension_function_utils i
|
|
|
49
43
|
get_sql_argument_signature,
|
|
50
44
|
get_sql_object_type,
|
|
51
45
|
)
|
|
52
|
-
from snowflake.cli.
|
|
46
|
+
from snowflake.cli._plugins.nativeapp.codegen.snowpark.models import (
|
|
53
47
|
ExtensionFunctionTypeEnum,
|
|
54
48
|
NativeAppExtensionFunction,
|
|
55
49
|
)
|
|
56
|
-
from snowflake.cli.
|
|
57
|
-
from snowflake.cli.
|
|
50
|
+
from snowflake.cli._plugins.stage.diff import to_stage_path
|
|
51
|
+
from snowflake.cli.api.console import cli_console as cc
|
|
52
|
+
from snowflake.cli.api.project.schemas.native_app.path_mapping import (
|
|
53
|
+
PathMapping,
|
|
54
|
+
ProcessorMapping,
|
|
55
|
+
)
|
|
56
|
+
from snowflake.cli.api.rendering.jinja import jinja_render_from_file
|
|
58
57
|
|
|
59
58
|
DEFAULT_TIMEOUT = 30
|
|
60
59
|
TEMPLATE_PATH = Path(__file__).parent / "callback_source.py.jinja"
|
|
@@ -163,11 +162,8 @@ class SnowparkAnnotationProcessor(ArtifactProcessor):
|
|
|
163
162
|
and generate SQL code for creation of extension functions based on those discovered objects.
|
|
164
163
|
"""
|
|
165
164
|
|
|
166
|
-
def __init__(
|
|
167
|
-
|
|
168
|
-
na_project: NativeAppProjectModel,
|
|
169
|
-
):
|
|
170
|
-
super().__init__(na_project=na_project)
|
|
165
|
+
def __init__(self, *args, **kwargs):
|
|
166
|
+
super().__init__(*args, **kwargs)
|
|
171
167
|
|
|
172
168
|
def process(
|
|
173
169
|
self,
|
|
@@ -181,8 +177,8 @@ class SnowparkAnnotationProcessor(ArtifactProcessor):
|
|
|
181
177
|
"""
|
|
182
178
|
|
|
183
179
|
bundle_map = BundleMap(
|
|
184
|
-
project_root=self.
|
|
185
|
-
deploy_root=self.
|
|
180
|
+
project_root=self._bundle_ctx.project_root,
|
|
181
|
+
deploy_root=self._bundle_ctx.deploy_root,
|
|
186
182
|
)
|
|
187
183
|
bundle_map.add(artifact_to_process)
|
|
188
184
|
|
|
@@ -230,13 +226,9 @@ class SnowparkAnnotationProcessor(ArtifactProcessor):
|
|
|
230
226
|
edit_setup_script_with_exec_imm_sql(
|
|
231
227
|
collected_sql_files=collected_sql_files,
|
|
232
228
|
deploy_root=bundle_map.deploy_root(),
|
|
233
|
-
generated_root=self.
|
|
229
|
+
generated_root=self._bundle_ctx.generated_root,
|
|
234
230
|
)
|
|
235
231
|
|
|
236
|
-
@property
|
|
237
|
-
def _generated_root(self):
|
|
238
|
-
return self._na_project.generated_root / "snowpark"
|
|
239
|
-
|
|
240
232
|
def _normalize_imports(
|
|
241
233
|
self,
|
|
242
234
|
extension_fn: NativeAppExtensionFunction,
|
|
@@ -315,7 +307,7 @@ class SnowparkAnnotationProcessor(ArtifactProcessor):
|
|
|
315
307
|
self, bundle_map: BundleMap, processor_mapping: Optional[ProcessorMapping]
|
|
316
308
|
) -> Dict[Path, List[NativeAppExtensionFunction]]:
|
|
317
309
|
kwargs = (
|
|
318
|
-
_determine_virtual_env(self.
|
|
310
|
+
_determine_virtual_env(self._bundle_ctx.project_root, processor_mapping)
|
|
319
311
|
if processor_mapping is not None
|
|
320
312
|
else {}
|
|
321
313
|
)
|
|
@@ -338,7 +330,7 @@ class SnowparkAnnotationProcessor(ArtifactProcessor):
|
|
|
338
330
|
)
|
|
339
331
|
collected_extension_function_json = _execute_in_sandbox(
|
|
340
332
|
py_file=str(dest_file.resolve()),
|
|
341
|
-
deploy_root=self.
|
|
333
|
+
deploy_root=self._bundle_ctx.deploy_root,
|
|
342
334
|
kwargs=kwargs,
|
|
343
335
|
)
|
|
344
336
|
|
|
@@ -369,8 +361,10 @@ class SnowparkAnnotationProcessor(ArtifactProcessor):
|
|
|
369
361
|
"""
|
|
370
362
|
Generates a SQL filename for the generated root from the python file, and creates its parent directories.
|
|
371
363
|
"""
|
|
372
|
-
relative_py_file = py_file.relative_to(self.
|
|
373
|
-
sql_file = Path(
|
|
364
|
+
relative_py_file = py_file.relative_to(self._bundle_ctx.deploy_root)
|
|
365
|
+
sql_file = Path(
|
|
366
|
+
self._bundle_ctx.generated_root, relative_py_file.with_suffix(".sql")
|
|
367
|
+
)
|
|
374
368
|
if sql_file.exists():
|
|
375
369
|
cc.warning(
|
|
376
370
|
f"""\
|
|
@@ -0,0 +1,93 @@
|
|
|
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 Optional
|
|
18
|
+
|
|
19
|
+
import jinja2
|
|
20
|
+
from snowflake.cli._plugins.nativeapp.artifacts import BundleMap
|
|
21
|
+
from snowflake.cli._plugins.nativeapp.codegen.artifact_processor import (
|
|
22
|
+
ArtifactProcessor,
|
|
23
|
+
)
|
|
24
|
+
from snowflake.cli._plugins.nativeapp.exceptions import InvalidTemplateInFileError
|
|
25
|
+
from snowflake.cli.api.cli_global_context import get_cli_context
|
|
26
|
+
from snowflake.cli.api.console import cli_console as cc
|
|
27
|
+
from snowflake.cli.api.project.schemas.native_app.path_mapping import (
|
|
28
|
+
PathMapping,
|
|
29
|
+
ProcessorMapping,
|
|
30
|
+
)
|
|
31
|
+
from snowflake.cli.api.rendering.project_definition_templates import (
|
|
32
|
+
get_client_side_jinja_env,
|
|
33
|
+
)
|
|
34
|
+
from snowflake.cli.api.rendering.sql_templates import (
|
|
35
|
+
choose_sql_jinja_env_based_on_template_syntax,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class TemplatesProcessor(ArtifactProcessor):
|
|
40
|
+
"""
|
|
41
|
+
Processor class to perform template expansion on all relevant artifacts (specified in the project definition file).
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def process(
|
|
45
|
+
self,
|
|
46
|
+
artifact_to_process: PathMapping,
|
|
47
|
+
processor_mapping: Optional[ProcessorMapping],
|
|
48
|
+
**kwargs,
|
|
49
|
+
):
|
|
50
|
+
"""
|
|
51
|
+
Process the artifact by executing the template expansion logic on it.
|
|
52
|
+
"""
|
|
53
|
+
cc.step(f"Processing artifact {artifact_to_process} with templates processor")
|
|
54
|
+
|
|
55
|
+
bundle_map = BundleMap(
|
|
56
|
+
project_root=self._bundle_ctx.project_root,
|
|
57
|
+
deploy_root=self._bundle_ctx.deploy_root,
|
|
58
|
+
)
|
|
59
|
+
bundle_map.add(artifact_to_process)
|
|
60
|
+
|
|
61
|
+
for src, dest in bundle_map.all_mappings(
|
|
62
|
+
absolute=True,
|
|
63
|
+
expand_directories=True,
|
|
64
|
+
):
|
|
65
|
+
if src.is_dir():
|
|
66
|
+
continue
|
|
67
|
+
with self.edit_file(dest) as f:
|
|
68
|
+
file_name = src.relative_to(self._bundle_ctx.project_root)
|
|
69
|
+
|
|
70
|
+
jinja_env = (
|
|
71
|
+
choose_sql_jinja_env_based_on_template_syntax(
|
|
72
|
+
f.contents, reference_name=file_name
|
|
73
|
+
)
|
|
74
|
+
if dest.name.lower().endswith(".sql")
|
|
75
|
+
else get_client_side_jinja_env()
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
try:
|
|
79
|
+
expanded_template = jinja_env.from_string(f.contents).render(
|
|
80
|
+
get_cli_context().template_context
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
# For now, we are printing the source file path in the error message
|
|
84
|
+
# instead of the destination file path to make it easier for the user
|
|
85
|
+
# to identify the file that has the error, and edit the correct file.
|
|
86
|
+
except jinja2.TemplateSyntaxError as e:
|
|
87
|
+
raise InvalidTemplateInFileError(file_name, e, e.lineno) from e
|
|
88
|
+
|
|
89
|
+
except jinja2.UndefinedError as e:
|
|
90
|
+
raise InvalidTemplateInFileError(file_name, e) from e
|
|
91
|
+
|
|
92
|
+
if expanded_template != f.contents:
|
|
93
|
+
f.edited_contents = expanded_template
|