snowflake-cli-labs 2.8.0rc1__py3-none-any.whl → 3.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- snowflake/cli/__about__.py +1 -1
- snowflake/cli/{app → _app}/__main__.py +1 -1
- snowflake/cli/{app → _app}/cli_app.py +22 -13
- snowflake/cli/{app → _app}/commands_registration/builtin_plugins.py +15 -19
- snowflake/cli/{app → _app}/commands_registration/command_plugins_loader.py +9 -9
- snowflake/cli/{app → _app}/commands_registration/commands_registration_with_callbacks.py +4 -4
- snowflake/cli/{app → _app}/commands_registration/exception_logging.py +2 -2
- snowflake/cli/{app → _app}/commands_registration/typer_registration.py +2 -2
- snowflake/cli/{app → _app}/dev/docs/commands_docs_generator.py +30 -12
- snowflake/cli/{app → _app}/dev/docs/generator.py +3 -3
- snowflake/cli/{app → _app}/dev/docs/project_definition_docs_generator.py +4 -4
- snowflake/cli/{app → _app}/dev/docs/templates/usage.rst.jinja2 +14 -4
- snowflake/cli/{app → _app}/main_typer.py +2 -2
- snowflake/cli/{app → _app}/printing.py +2 -2
- snowflake/cli/_app/secret.py +9 -0
- snowflake/cli/{app → _app}/snow_connector.py +127 -61
- snowflake/cli/{app → _app}/telemetry.py +38 -7
- snowflake/cli/_app/version_check.py +74 -0
- snowflake/cli/{plugins → _plugins}/connection/commands.py +34 -11
- snowflake/cli/_plugins/connection/plugin_spec.py +30 -0
- snowflake/cli/{plugins → _plugins}/connection/util.py +16 -0
- snowflake/cli/{plugins → _plugins}/cortex/commands.py +54 -49
- snowflake/cli/{plugins → _plugins}/cortex/constants.py +1 -1
- snowflake/cli/{plugins → _plugins}/cortex/manager.py +5 -5
- snowflake/cli/{plugins → _plugins}/cortex/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/git/commands.py +79 -26
- snowflake/cli/{plugins → _plugins}/git/manager.py +72 -17
- snowflake/cli/{plugins → _plugins}/git/plugin_spec.py +1 -1
- snowflake/cli/_plugins/helpers/commands.py +90 -0
- snowflake/cli/{plugins/notebook → _plugins/helpers}/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/init/commands.py +10 -6
- snowflake/cli/{plugins → _plugins}/init/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/nativeapp/artifacts.py +24 -9
- snowflake/cli/_plugins/nativeapp/bundle_context.py +31 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/artifact_processor.py +4 -4
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/compiler.py +37 -18
- snowflake/cli/_plugins/nativeapp/codegen/setup/native_app_setup_processor.py +249 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/setup/setup_driver.py.source +5 -2
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/extension_function_utils.py +5 -5
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/models.py +1 -1
- snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/python_processor.py +29 -34
- snowflake/cli/_plugins/nativeapp/codegen/templates/templates_processor.py +114 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/commands.py +252 -132
- snowflake/cli/{plugins → _plugins}/nativeapp/common_flags.py +1 -1
- snowflake/cli/_plugins/nativeapp/entities/application.py +878 -0
- snowflake/cli/_plugins/nativeapp/entities/application_package.py +1392 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/exceptions.py +3 -12
- snowflake/cli/_plugins/nativeapp/manager.py +415 -0
- snowflake/cli/{plugins/connection → _plugins/nativeapp}/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/nativeapp/policy.py +3 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/project_model.py +36 -20
- snowflake/cli/_plugins/nativeapp/run_processor.py +184 -0
- snowflake/cli/_plugins/nativeapp/same_account_install_method.py +70 -0
- snowflake/cli/_plugins/nativeapp/teardown_processor.py +70 -0
- snowflake/cli/_plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +262 -0
- snowflake/cli/{plugins → _plugins}/nativeapp/version/commands.py +20 -49
- snowflake/cli/_plugins/nativeapp/version/version_processor.py +98 -0
- snowflake/cli/{plugins → _plugins}/notebook/commands.py +8 -6
- snowflake/cli/{plugins → _plugins}/notebook/manager.py +14 -14
- snowflake/cli/{plugins/nativeapp → _plugins/notebook}/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/notebook/types.py +0 -1
- snowflake/cli/{plugins → _plugins}/object/command_aliases.py +6 -5
- snowflake/cli/{plugins → _plugins}/object/commands.py +16 -10
- snowflake/cli/{plugins → _plugins}/object/manager.py +43 -21
- snowflake/cli/{plugins → _plugins}/object/plugin_spec.py +1 -1
- snowflake/cli/_plugins/snowpark/commands.py +450 -0
- snowflake/cli/_plugins/snowpark/common.py +268 -0
- snowflake/cli/{plugins → _plugins}/snowpark/models.py +2 -8
- snowflake/cli/{plugins → _plugins}/snowpark/package/anaconda_packages.py +2 -36
- snowflake/cli/{plugins → _plugins}/snowpark/package/commands.py +13 -74
- snowflake/cli/{plugins → _plugins}/snowpark/package/manager.py +4 -3
- snowflake/cli/{plugins → _plugins}/snowpark/package_utils.py +5 -5
- snowflake/cli/_plugins/snowpark/plugin_spec.py +30 -0
- snowflake/cli/_plugins/snowpark/snowpark_entity.py +29 -0
- snowflake/cli/_plugins/snowpark/snowpark_entity_model.py +173 -0
- snowflake/cli/_plugins/snowpark/snowpark_project_paths.py +109 -0
- snowflake/cli/{plugins → _plugins}/snowpark/snowpark_shared.py +0 -36
- snowflake/cli/{plugins → _plugins}/snowpark/zipper.py +16 -8
- snowflake/cli/{plugins → _plugins}/spcs/__init__.py +5 -7
- snowflake/cli/{plugins → _plugins}/spcs/compute_pool/commands.py +29 -28
- snowflake/cli/{plugins → _plugins}/spcs/compute_pool/manager.py +3 -3
- snowflake/cli/{plugins → _plugins}/spcs/image_registry/commands.py +3 -3
- snowflake/cli/{plugins → _plugins}/spcs/image_repository/commands.py +25 -19
- snowflake/cli/{plugins → _plugins}/spcs/image_repository/manager.py +1 -1
- snowflake/cli/{plugins → _plugins}/spcs/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/spcs/services/commands.py +66 -32
- snowflake/cli/{plugins → _plugins}/spcs/services/manager.py +43 -5
- snowflake/cli/{plugins → _plugins}/sql/commands.py +20 -17
- snowflake/cli/{plugins → _plugins}/sql/manager.py +1 -1
- snowflake/cli/{plugins → _plugins}/sql/plugin_spec.py +1 -1
- snowflake/cli/{plugins → _plugins}/stage/commands.py +20 -17
- snowflake/cli/{plugins → _plugins}/stage/diff.py +1 -47
- snowflake/cli/{plugins → _plugins}/stage/manager.py +62 -24
- snowflake/cli/{plugins → _plugins}/stage/plugin_spec.py +1 -1
- snowflake/cli/_plugins/stage/utils.py +54 -0
- snowflake/cli/{plugins → _plugins}/streamlit/commands.py +71 -62
- snowflake/cli/{plugins → _plugins}/streamlit/manager.py +68 -70
- snowflake/cli/_plugins/streamlit/plugin_spec.py +30 -0
- snowflake/cli/_plugins/streamlit/streamlit_entity.py +12 -0
- snowflake/cli/_plugins/streamlit/streamlit_entity_model.py +66 -0
- snowflake/cli/_plugins/workspace/action_context.py +18 -0
- snowflake/cli/_plugins/workspace/commands.py +306 -0
- snowflake/cli/_plugins/workspace/manager.py +74 -0
- snowflake/cli/_plugins/workspace/plugin_spec.py +30 -0
- snowflake/cli/api/cli_global_context.py +152 -295
- snowflake/cli/api/commands/common.py +25 -0
- snowflake/cli/api/commands/decorators.py +19 -4
- snowflake/cli/api/commands/experimental_behaviour.py +2 -3
- snowflake/cli/api/commands/flags.py +143 -222
- snowflake/cli/api/commands/overrideable_parameter.py +143 -0
- snowflake/cli/api/commands/snow_typer.py +21 -11
- snowflake/cli/api/commands/utils.py +18 -0
- snowflake/cli/api/config.py +44 -12
- snowflake/cli/api/connections.py +216 -0
- snowflake/cli/api/console/abc.py +8 -3
- snowflake/cli/api/constants.py +11 -0
- snowflake/cli/api/entities/common.py +56 -0
- snowflake/cli/api/entities/utils.py +370 -0
- snowflake/cli/api/errno.py +1 -0
- snowflake/cli/api/exceptions.py +31 -5
- snowflake/cli/api/feature_flags.py +0 -1
- snowflake/cli/api/identifiers.py +45 -9
- snowflake/cli/api/metrics.py +92 -0
- snowflake/cli/api/project/definition.py +48 -6
- snowflake/cli/api/project/definition_conversion.py +400 -0
- snowflake/cli/api/project/definition_manager.py +16 -5
- snowflake/cli/api/project/project_verification.py +3 -3
- snowflake/cli/api/project/schemas/entities/common.py +91 -16
- snowflake/cli/api/project/schemas/entities/entities.py +37 -6
- snowflake/cli/api/project/schemas/project_definition.py +180 -49
- snowflake/cli/api/project/schemas/updatable_model.py +11 -3
- snowflake/cli/api/project/schemas/v1/__init__.py +0 -0
- snowflake/cli/api/project/schemas/{identifier_model.py → v1/identifier_model.py} +3 -1
- snowflake/cli/api/project/schemas/v1/native_app/__init__.py +0 -0
- snowflake/cli/api/project/schemas/{native_app → v1/native_app}/application.py +8 -9
- snowflake/cli/api/project/schemas/{native_app → v1/native_app}/native_app.py +4 -4
- snowflake/cli/api/project/schemas/{native_app → v1/native_app}/package.py +7 -1
- snowflake/cli/api/project/schemas/v1/snowpark/__init__.py +0 -0
- snowflake/cli/api/project/schemas/{snowpark → v1/snowpark}/callable.py +2 -2
- snowflake/cli/api/project/schemas/{snowpark → v1/snowpark}/snowpark.py +2 -2
- snowflake/cli/api/project/schemas/v1/streamlit/__init__.py +0 -0
- snowflake/cli/api/project/schemas/{streamlit → v1/streamlit}/streamlit.py +2 -1
- snowflake/cli/api/project/util.py +23 -6
- snowflake/cli/api/rendering/jinja.py +14 -8
- snowflake/cli/api/rendering/project_definition_templates.py +5 -1
- snowflake/cli/api/rendering/sql_templates.py +56 -11
- snowflake/cli/api/rest_api.py +11 -5
- snowflake/cli/api/secure_path.py +16 -18
- snowflake/cli/api/secure_utils.py +90 -1
- snowflake/cli/api/sql_execution.py +47 -27
- snowflake/cli/api/utils/definition_rendering.py +45 -13
- {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-3.0.0.dist-info}/METADATA +20 -18
- snowflake_cli_labs-3.0.0.dist-info/RECORD +242 -0
- snowflake_cli_labs-3.0.0.dist-info/entry_points.txt +2 -0
- snowflake/cli/api/commands/project_initialisation.py +0 -65
- snowflake/cli/api/commands/typer_pre_execute.py +0 -26
- snowflake/cli/api/project/schemas/entities/application_entity.py +0 -44
- snowflake/cli/api/project/schemas/entities/application_package_entity.py +0 -66
- snowflake/cli/app/build_and_push.sh +0 -8
- snowflake/cli/plugins/nativeapp/codegen/setup/native_app_setup_processor.py +0 -172
- snowflake/cli/plugins/nativeapp/init.py +0 -345
- snowflake/cli/plugins/nativeapp/manager.py +0 -823
- snowflake/cli/plugins/nativeapp/run_processor.py +0 -389
- snowflake/cli/plugins/nativeapp/teardown_processor.py +0 -301
- snowflake/cli/plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +0 -135
- snowflake/cli/plugins/nativeapp/version/version_processor.py +0 -362
- snowflake/cli/plugins/object_stage_deprecated/__init__.py +0 -15
- snowflake/cli/plugins/object_stage_deprecated/commands.py +0 -122
- snowflake/cli/plugins/object_stage_deprecated/plugin_spec.py +0 -32
- snowflake/cli/plugins/snowpark/commands.py +0 -548
- snowflake/cli/plugins/snowpark/common.py +0 -307
- snowflake/cli/plugins/snowpark/manager.py +0 -109
- snowflake/cli/plugins/snowpark/plugin_spec.py +0 -30
- snowflake/cli/plugins/snowpark/snowpark_package_paths.py +0 -65
- snowflake/cli/plugins/spcs/jobs/commands.py +0 -78
- snowflake/cli/plugins/spcs/jobs/manager.py +0 -53
- snowflake/cli/plugins/streamlit/__init__.py +0 -13
- snowflake/cli/plugins/streamlit/plugin_spec.py +0 -30
- snowflake/cli/plugins/workspace/__init__.py +0 -13
- snowflake/cli/plugins/workspace/commands.py +0 -35
- snowflake/cli/plugins/workspace/plugin_spec.py +0 -30
- snowflake/cli/templates/default_snowpark/.gitignore +0 -4
- snowflake/cli/templates/default_snowpark/app/common.py +0 -2
- snowflake/cli/templates/default_snowpark/app/functions.py +0 -15
- snowflake/cli/templates/default_snowpark/app/procedures.py +0 -22
- snowflake/cli/templates/default_snowpark/requirements.txt +0 -1
- snowflake/cli/templates/default_snowpark/snowflake.yml +0 -23
- snowflake/cli/templates/default_streamlit/.gitignore +0 -4
- snowflake/cli/templates/default_streamlit/common/hello.py +0 -2
- snowflake/cli/templates/default_streamlit/environment.yml +0 -6
- snowflake/cli/templates/default_streamlit/pages/my_page.py +0 -3
- snowflake/cli/templates/default_streamlit/snowflake.yml +0 -10
- snowflake/cli/templates/default_streamlit/streamlit_app.py +0 -4
- snowflake_cli_labs-2.8.0rc1.dist-info/RECORD +0 -240
- snowflake_cli_labs-2.8.0rc1.dist-info/entry_points.txt +0 -2
- /snowflake/cli/{app → _app}/__init__.py +0 -0
- /snowflake/cli/{api/project/schemas/native_app → _app/api_impl}/__init__.py +0 -0
- /snowflake/cli/{api/project/schemas/snowpark → _app/api_impl/plugin}/__init__.py +0 -0
- /snowflake/cli/{app → _app}/api_impl/plugin/plugin_config_provider_impl.py +0 -0
- /snowflake/cli/{app → _app}/commands_registration/__init__.py +0 -0
- /snowflake/cli/{app → _app}/commands_registration/threadsafe.py +0 -0
- /snowflake/cli/{app → _app}/constants.py +0 -0
- /snowflake/cli/{api/project/schemas/streamlit → _app/dev}/__init__.py +0 -0
- /snowflake/cli/{app → _app}/dev/commands_structure.py +0 -0
- /snowflake/cli/{app/api_impl → _app/dev/docs}/__init__.py +0 -0
- /snowflake/cli/{app → _app}/dev/docs/project_definition_generate_json_schema.py +0 -0
- /snowflake/cli/{app → _app}/dev/docs/template_utils.py +0 -0
- /snowflake/cli/{app → _app}/dev/docs/templates/definition_description.rst.jinja2 +0 -0
- /snowflake/cli/{app → _app}/dev/docs/templates/overview.rst.jinja2 +0 -0
- /snowflake/cli/{app → _app}/dev/pycharm_remote_debug.py +0 -0
- /snowflake/cli/{app → _app}/loggers.py +0 -0
- /snowflake/cli/{app/api_impl/plugin → _plugins}/__init__.py +0 -0
- /snowflake/cli/{app/dev → _plugins/connection}/__init__.py +0 -0
- /snowflake/cli/{app/dev/docs → _plugins/cortex}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/cortex/types.py +0 -0
- /snowflake/cli/{plugins → _plugins/git}/__init__.py +0 -0
- /snowflake/cli/{plugins/connection → _plugins/helpers}/__init__.py +0 -0
- /snowflake/cli/{plugins/cortex → _plugins/init}/__init__.py +0 -0
- /snowflake/cli/{plugins/git → _plugins/nativeapp}/__init__.py +0 -0
- /snowflake/cli/{plugins/init → _plugins/nativeapp/codegen}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/sandbox.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/codegen/snowpark/callback_source.py.jinja +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/constants.py +0 -0
- /snowflake/cli/{templates/default_snowpark/app → _plugins/nativeapp/entities}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/feature_flags.py +0 -0
- /snowflake/cli/{plugins → _plugins}/nativeapp/utils.py +0 -0
- /snowflake/cli/{plugins/nativeapp → _plugins/nativeapp/version}/__init__.py +0 -0
- /snowflake/cli/{plugins/nativeapp/codegen → _plugins/notebook}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/notebook/exceptions.py +0 -0
- /snowflake/cli/{plugins/nativeapp/version → _plugins/object}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/object/common.py +0 -0
- /snowflake/cli/{plugins/notebook → _plugins/snowpark}/__init__.py +0 -0
- /snowflake/cli/{plugins/object → _plugins/snowpark/package}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/snowpark/package/utils.py +0 -0
- /snowflake/cli/{plugins → _plugins}/spcs/common.py +0 -0
- /snowflake/cli/{plugins/snowpark → _plugins/spcs/compute_pool}/__init__.py +0 -0
- /snowflake/cli/{plugins/snowpark/package → _plugins/spcs/image_registry}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/spcs/image_registry/manager.py +0 -0
- /snowflake/cli/{plugins/spcs/compute_pool → _plugins/spcs/image_repository}/__init__.py +0 -0
- /snowflake/cli/{plugins/spcs/image_registry → _plugins/spcs/services}/__init__.py +0 -0
- /snowflake/cli/{plugins/spcs/image_repository → _plugins/sql}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/sql/snowsql_templating.py +0 -0
- /snowflake/cli/{plugins/spcs/jobs → _plugins/stage}/__init__.py +0 -0
- /snowflake/cli/{plugins → _plugins}/stage/md5.py +0 -0
- /snowflake/cli/{plugins/spcs/services → _plugins/streamlit}/__init__.py +0 -0
- /snowflake/cli/{plugins/sql → _plugins/workspace}/__init__.py +0 -0
- /snowflake/cli/{plugins/stage → api/project/schemas/entities}/__init__.py +0 -0
- /snowflake/cli/api/project/schemas/{native_app → v1/native_app}/path_mapping.py +0 -0
- /snowflake/cli/api/project/schemas/{snowpark → v1/snowpark}/argument.py +0 -0
- {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-3.0.0.dist-info}/WHEEL +0 -0
- {snowflake_cli_labs-2.8.0rc1.dist-info → snowflake_cli_labs-3.0.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -19,17 +19,17 @@ import logging
|
|
|
19
19
|
from typing import Callable, Optional
|
|
20
20
|
|
|
21
21
|
from click import ClickException
|
|
22
|
-
from snowflake.cli.
|
|
23
|
-
from snowflake.cli.api.exceptions import SnowflakeSQLExecutionError
|
|
24
|
-
from snowflake.cli.api.secure_path import SecurePath
|
|
25
|
-
from snowflake.cli.api.sql_execution import SqlExecutionMixin
|
|
26
|
-
from snowflake.cli.plugins.cortex.types import (
|
|
22
|
+
from snowflake.cli._plugins.cortex.types import (
|
|
27
23
|
Language,
|
|
28
24
|
Model,
|
|
29
25
|
Question,
|
|
30
26
|
SourceDocument,
|
|
31
27
|
Text,
|
|
32
28
|
)
|
|
29
|
+
from snowflake.cli.api.constants import DEFAULT_SIZE_LIMIT_MB
|
|
30
|
+
from snowflake.cli.api.exceptions import SnowflakeSQLExecutionError
|
|
31
|
+
from snowflake.cli.api.secure_path import SecurePath
|
|
32
|
+
from snowflake.cli.api.sql_execution import SqlExecutionMixin
|
|
33
33
|
from snowflake.connector import ProgrammingError
|
|
34
34
|
from snowflake.connector.cursor import DictCursor
|
|
35
35
|
|
|
@@ -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.cortex 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.cortex import commands
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@plugin_hook_impl
|
|
@@ -18,10 +18,17 @@ import itertools
|
|
|
18
18
|
import logging
|
|
19
19
|
from os import path
|
|
20
20
|
from pathlib import Path
|
|
21
|
-
from typing import List, Optional
|
|
21
|
+
from typing import Dict, List, Optional
|
|
22
22
|
|
|
23
23
|
import typer
|
|
24
24
|
from click import ClickException
|
|
25
|
+
from snowflake.cli._plugins.git.manager import GitManager
|
|
26
|
+
from snowflake.cli._plugins.object.command_aliases import (
|
|
27
|
+
add_object_command_aliases,
|
|
28
|
+
scope_option,
|
|
29
|
+
)
|
|
30
|
+
from snowflake.cli._plugins.object.manager import ObjectManager
|
|
31
|
+
from snowflake.cli.api.commands.common import OnErrorType
|
|
25
32
|
from snowflake.cli.api.commands.flags import (
|
|
26
33
|
ExecuteVariablesOption,
|
|
27
34
|
OnErrorOption,
|
|
@@ -34,13 +41,7 @@ from snowflake.cli.api.console.console import cli_console
|
|
|
34
41
|
from snowflake.cli.api.constants import ObjectType
|
|
35
42
|
from snowflake.cli.api.output.types import CollectionResult, CommandResult, QueryResult
|
|
36
43
|
from snowflake.cli.api.utils.path_utils import is_stage_path
|
|
37
|
-
from snowflake.
|
|
38
|
-
from snowflake.cli.plugins.object.command_aliases import (
|
|
39
|
-
add_object_command_aliases,
|
|
40
|
-
scope_option,
|
|
41
|
-
)
|
|
42
|
-
from snowflake.cli.plugins.object.manager import ObjectManager
|
|
43
|
-
from snowflake.cli.plugins.stage.manager import OnErrorType
|
|
44
|
+
from snowflake.connector import DictCursor
|
|
44
45
|
|
|
45
46
|
app = SnowTyperFactory(
|
|
46
47
|
name="git",
|
|
@@ -71,6 +72,7 @@ RepoPathArgument = typer.Argument(
|
|
|
71
72
|
" For example: @my_repo/branches/main/"
|
|
72
73
|
),
|
|
73
74
|
callback=_repo_path_argument_callback,
|
|
75
|
+
show_default=False,
|
|
74
76
|
)
|
|
75
77
|
add_object_command_aliases(
|
|
76
78
|
app=app,
|
|
@@ -82,10 +84,12 @@ add_object_command_aliases(
|
|
|
82
84
|
scope_option=scope_option(help_example="`list --in database my_db`"),
|
|
83
85
|
)
|
|
84
86
|
|
|
87
|
+
from snowflake.cli.api.identifiers import FQN
|
|
88
|
+
|
|
85
89
|
|
|
86
|
-
def _assure_repository_does_not_exist(om: ObjectManager, repository_name:
|
|
90
|
+
def _assure_repository_does_not_exist(om: ObjectManager, repository_name: FQN) -> None:
|
|
87
91
|
if om.object_exists(
|
|
88
|
-
object_type=ObjectType.GIT_REPOSITORY.value.cli_name,
|
|
92
|
+
object_type=ObjectType.GIT_REPOSITORY.value.cli_name, fqn=repository_name
|
|
89
93
|
):
|
|
90
94
|
raise ClickException(f"Repository '{repository_name}' already exists")
|
|
91
95
|
|
|
@@ -95,14 +99,34 @@ def _validate_origin_url(url: str) -> None:
|
|
|
95
99
|
raise ClickException("Url address should start with 'https'")
|
|
96
100
|
|
|
97
101
|
|
|
102
|
+
def _unique_new_object_name(
|
|
103
|
+
om: ObjectManager, object_type: ObjectType, proposed_fqn: FQN
|
|
104
|
+
) -> str:
|
|
105
|
+
existing_objects: List[Dict] = om.show(
|
|
106
|
+
object_type=object_type.value.cli_name,
|
|
107
|
+
like=f"{proposed_fqn.name}%",
|
|
108
|
+
cursor_class=DictCursor,
|
|
109
|
+
).fetchall()
|
|
110
|
+
existing_names = set(o["name"].upper() for o in existing_objects)
|
|
111
|
+
|
|
112
|
+
result = proposed_fqn.name
|
|
113
|
+
i = 1
|
|
114
|
+
while result.upper() in existing_names:
|
|
115
|
+
result = proposed_fqn.name + str(i)
|
|
116
|
+
i += 1
|
|
117
|
+
return result
|
|
118
|
+
|
|
119
|
+
|
|
98
120
|
@app.command("setup", requires_connection=True)
|
|
99
121
|
def setup(
|
|
100
|
-
repository_name:
|
|
122
|
+
repository_name: FQN = RepoNameArgument,
|
|
101
123
|
**options,
|
|
102
124
|
) -> CommandResult:
|
|
103
125
|
"""
|
|
104
126
|
Sets up a git repository object.
|
|
105
127
|
|
|
128
|
+
## Usage notes
|
|
129
|
+
|
|
106
130
|
You will be prompted for:
|
|
107
131
|
|
|
108
132
|
* url - address of repository to be used for git clone operation
|
|
@@ -123,12 +147,29 @@ def setup(
|
|
|
123
147
|
should_create_secret = False
|
|
124
148
|
secret_name = None
|
|
125
149
|
if secret_needed:
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
150
|
+
default_secret_name = (
|
|
151
|
+
FQN.from_string(f"{repository_name.name}_secret")
|
|
152
|
+
.set_schema(repository_name.schema)
|
|
153
|
+
.set_database(repository_name.database)
|
|
154
|
+
)
|
|
155
|
+
default_secret_name.set_name(
|
|
156
|
+
_unique_new_object_name(
|
|
157
|
+
om, object_type=ObjectType.SECRET, proposed_fqn=default_secret_name
|
|
158
|
+
),
|
|
129
159
|
)
|
|
160
|
+
secret_name = FQN.from_string(
|
|
161
|
+
typer.prompt(
|
|
162
|
+
"Secret identifier (will be created if not exists)",
|
|
163
|
+
default=default_secret_name.name,
|
|
164
|
+
)
|
|
165
|
+
)
|
|
166
|
+
if not secret_name.database:
|
|
167
|
+
secret_name.set_database(repository_name.database)
|
|
168
|
+
if not secret_name.schema:
|
|
169
|
+
secret_name.set_schema(repository_name.schema)
|
|
170
|
+
|
|
130
171
|
if om.object_exists(
|
|
131
|
-
object_type=ObjectType.SECRET.value.cli_name,
|
|
172
|
+
object_type=ObjectType.SECRET.value.cli_name, fqn=secret_name
|
|
132
173
|
):
|
|
133
174
|
cli_console.step(f"Using existing secret '{secret_name}'")
|
|
134
175
|
else:
|
|
@@ -137,10 +178,17 @@ def setup(
|
|
|
137
178
|
secret_username = typer.prompt("username")
|
|
138
179
|
secret_password = typer.prompt("password/token", hide_input=True)
|
|
139
180
|
|
|
140
|
-
|
|
141
|
-
api_integration =
|
|
142
|
-
|
|
143
|
-
|
|
181
|
+
# API integration is an account-level object
|
|
182
|
+
api_integration = FQN.from_string(f"{repository_name.name}_api_integration")
|
|
183
|
+
api_integration.set_name(
|
|
184
|
+
typer.prompt(
|
|
185
|
+
"API integration identifier (will be created if not exists)",
|
|
186
|
+
default=_unique_new_object_name(
|
|
187
|
+
om,
|
|
188
|
+
object_type=ObjectType.INTEGRATION,
|
|
189
|
+
proposed_fqn=api_integration,
|
|
190
|
+
),
|
|
191
|
+
)
|
|
144
192
|
)
|
|
145
193
|
|
|
146
194
|
if should_create_secret:
|
|
@@ -150,7 +198,7 @@ def setup(
|
|
|
150
198
|
cli_console.step(f"Secret '{secret_name}' successfully created.")
|
|
151
199
|
|
|
152
200
|
if not om.object_exists(
|
|
153
|
-
object_type=ObjectType.INTEGRATION.value.cli_name,
|
|
201
|
+
object_type=ObjectType.INTEGRATION.value.cli_name, fqn=api_integration
|
|
154
202
|
):
|
|
155
203
|
manager.create_api_integration(
|
|
156
204
|
name=api_integration,
|
|
@@ -177,7 +225,7 @@ def setup(
|
|
|
177
225
|
requires_connection=True,
|
|
178
226
|
)
|
|
179
227
|
def list_branches(
|
|
180
|
-
repository_name:
|
|
228
|
+
repository_name: FQN = RepoNameArgument,
|
|
181
229
|
like=like_option(
|
|
182
230
|
help_example='`list-branches --like "%_test"` lists all branches that end with "_test"'
|
|
183
231
|
),
|
|
@@ -186,7 +234,9 @@ def list_branches(
|
|
|
186
234
|
"""
|
|
187
235
|
List all branches in the repository.
|
|
188
236
|
"""
|
|
189
|
-
return QueryResult(
|
|
237
|
+
return QueryResult(
|
|
238
|
+
GitManager().show_branches(repo_name=repository_name.identifier, like=like)
|
|
239
|
+
)
|
|
190
240
|
|
|
191
241
|
|
|
192
242
|
@app.command(
|
|
@@ -194,7 +244,7 @@ def list_branches(
|
|
|
194
244
|
requires_connection=True,
|
|
195
245
|
)
|
|
196
246
|
def list_tags(
|
|
197
|
-
repository_name:
|
|
247
|
+
repository_name: FQN = RepoNameArgument,
|
|
198
248
|
like=like_option(
|
|
199
249
|
help_example='`list-tags --like "v2.0%"` lists all tags that start with "v2.0"'
|
|
200
250
|
),
|
|
@@ -203,7 +253,9 @@ def list_tags(
|
|
|
203
253
|
"""
|
|
204
254
|
List all tags in the repository.
|
|
205
255
|
"""
|
|
206
|
-
return QueryResult(
|
|
256
|
+
return QueryResult(
|
|
257
|
+
GitManager().show_tags(repo_name=repository_name.identifier, like=like)
|
|
258
|
+
)
|
|
207
259
|
|
|
208
260
|
|
|
209
261
|
@app.command(
|
|
@@ -228,13 +280,13 @@ def list_files(
|
|
|
228
280
|
requires_connection=True,
|
|
229
281
|
)
|
|
230
282
|
def fetch(
|
|
231
|
-
repository_name:
|
|
283
|
+
repository_name: FQN = RepoNameArgument,
|
|
232
284
|
**options,
|
|
233
285
|
) -> CommandResult:
|
|
234
286
|
"""
|
|
235
287
|
Fetch changes from origin to Snowflake repository.
|
|
236
288
|
"""
|
|
237
|
-
return QueryResult(GitManager().fetch(
|
|
289
|
+
return QueryResult(GitManager().fetch(fqn=repository_name))
|
|
238
290
|
|
|
239
291
|
|
|
240
292
|
@app.command(
|
|
@@ -245,6 +297,7 @@ def copy(
|
|
|
245
297
|
repository_path: str = RepoPathArgument,
|
|
246
298
|
destination_path: str = typer.Argument(
|
|
247
299
|
help="Target path for copy operation. Should be a path to a directory on remote stage or local file system.",
|
|
300
|
+
show_default=False,
|
|
248
301
|
),
|
|
249
302
|
parallel: int = typer.Option(
|
|
250
303
|
4,
|
|
@@ -14,43 +14,64 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
from pathlib import Path
|
|
17
|
+
from pathlib import Path, PurePosixPath
|
|
18
18
|
from textwrap import dedent
|
|
19
19
|
from typing import List
|
|
20
20
|
|
|
21
|
-
from
|
|
21
|
+
from click import UsageError
|
|
22
|
+
from snowflake.cli._plugins.stage.manager import (
|
|
22
23
|
USER_STAGE_PREFIX,
|
|
23
24
|
StageManager,
|
|
24
25
|
StagePathParts,
|
|
25
26
|
UserStagePathParts,
|
|
26
27
|
)
|
|
28
|
+
from snowflake.cli.api.identifiers import FQN
|
|
27
29
|
from snowflake.connector.cursor import SnowflakeCursor
|
|
28
30
|
|
|
31
|
+
# Replace magic numbers with constants
|
|
32
|
+
OMIT_FIRST = slice(1, None)
|
|
33
|
+
OMIT_STAGE = slice(3, None)
|
|
34
|
+
OMIT_STAGE_IN_NEW_LIST_FILES = slice(2, None)
|
|
35
|
+
ONLY_STAGE = slice(3)
|
|
36
|
+
|
|
29
37
|
|
|
30
38
|
class GitStagePathParts(StagePathParts):
|
|
31
39
|
def __init__(self, stage_path: str):
|
|
32
40
|
self.stage = GitManager.get_stage_from_path(stage_path)
|
|
33
|
-
stage_path_parts =
|
|
41
|
+
stage_path_parts = GitManager.split_git_path(stage_path)
|
|
34
42
|
git_repo_name = stage_path_parts[0].split(".")[-1]
|
|
35
43
|
if git_repo_name.startswith("@"):
|
|
36
|
-
git_repo_name = git_repo_name[
|
|
44
|
+
git_repo_name = git_repo_name[OMIT_FIRST]
|
|
37
45
|
self.stage_name = "/".join([git_repo_name, *stage_path_parts[1:3], ""])
|
|
38
|
-
self.directory = "/".join(stage_path_parts[
|
|
46
|
+
self.directory = "/".join(stage_path_parts[OMIT_STAGE])
|
|
39
47
|
self.is_directory = True if stage_path.endswith("/") else False
|
|
40
48
|
|
|
41
49
|
@property
|
|
42
50
|
def path(self) -> str:
|
|
43
|
-
return (
|
|
44
|
-
f"{self.stage_name}{self.directory}"
|
|
45
|
-
if self.stage_name.endswith("/")
|
|
46
|
-
else f"{self.stage_name}/{self.directory}"
|
|
47
|
-
)
|
|
51
|
+
return f"{self.stage_name.rstrip('/')}/{self.directory}"
|
|
48
52
|
|
|
49
|
-
|
|
53
|
+
@classmethod
|
|
54
|
+
def get_directory(cls, stage_path: str) -> str:
|
|
55
|
+
git_path_parts = GitManager.split_git_path(stage_path)
|
|
56
|
+
# New file list does not have a stage name at the beginning
|
|
57
|
+
if stage_path.startswith("/"):
|
|
58
|
+
return "/".join(git_path_parts[OMIT_STAGE_IN_NEW_LIST_FILES])
|
|
59
|
+
else:
|
|
60
|
+
return "/".join(git_path_parts[OMIT_STAGE])
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def full_path(self) -> str:
|
|
64
|
+
return f"{self.stage.rstrip('/')}/{self.directory}"
|
|
65
|
+
|
|
66
|
+
def replace_stage_prefix(self, file_path: str) -> str:
|
|
50
67
|
stage = Path(self.stage).parts[0]
|
|
51
|
-
file_path_without_prefix = Path(file_path).parts[
|
|
68
|
+
file_path_without_prefix = Path(file_path).parts[OMIT_FIRST]
|
|
52
69
|
return f"{stage}/{'/'.join(file_path_without_prefix)}"
|
|
53
70
|
|
|
71
|
+
def add_stage_prefix(self, file_path: str) -> str:
|
|
72
|
+
stage = self.stage.rstrip("/")
|
|
73
|
+
return f"{stage}/{file_path.lstrip('/')}"
|
|
74
|
+
|
|
54
75
|
def get_directory_from_file_path(self, file_path: str) -> List[str]:
|
|
55
76
|
stage_path_length = len(Path(self.directory).parts)
|
|
56
77
|
return list(Path(file_path).parts[3 + stage_path_length : -1])
|
|
@@ -63,15 +84,15 @@ class GitManager(StageManager):
|
|
|
63
84
|
def show_tags(self, repo_name: str, like: str) -> SnowflakeCursor:
|
|
64
85
|
return self._execute_query(f"show git tags like '{like}' in {repo_name}")
|
|
65
86
|
|
|
66
|
-
def fetch(self,
|
|
67
|
-
return self._execute_query(f"alter git repository {
|
|
87
|
+
def fetch(self, fqn: FQN) -> SnowflakeCursor:
|
|
88
|
+
return self._execute_query(f"alter git repository {fqn} fetch")
|
|
68
89
|
|
|
69
90
|
def create(
|
|
70
|
-
self, repo_name:
|
|
91
|
+
self, repo_name: FQN, api_integration: str, url: str, secret: str
|
|
71
92
|
) -> SnowflakeCursor:
|
|
72
93
|
query = dedent(
|
|
73
94
|
f"""
|
|
74
|
-
create git repository {repo_name}
|
|
95
|
+
create git repository {repo_name.sql_identifier}
|
|
75
96
|
api_integration = {api_integration}
|
|
76
97
|
origin = '{url}'
|
|
77
98
|
"""
|
|
@@ -86,7 +107,8 @@ class GitManager(StageManager):
|
|
|
86
107
|
Returns stage name from potential path on stage. For example
|
|
87
108
|
repo/branches/main/foo/bar -> repo/branches/main/
|
|
88
109
|
"""
|
|
89
|
-
|
|
110
|
+
path_parts = GitManager.split_git_path(path)
|
|
111
|
+
return f"{'/'.join(path_parts[ONLY_STAGE])}/"
|
|
90
112
|
|
|
91
113
|
@staticmethod
|
|
92
114
|
def _stage_path_part_factory(stage_path: str) -> StagePathParts:
|
|
@@ -94,3 +116,36 @@ class GitManager(StageManager):
|
|
|
94
116
|
if stage_path.startswith(USER_STAGE_PREFIX):
|
|
95
117
|
return UserStagePathParts(stage_path)
|
|
96
118
|
return GitStagePathParts(stage_path)
|
|
119
|
+
|
|
120
|
+
@staticmethod
|
|
121
|
+
def split_git_path(path: str):
|
|
122
|
+
# Check if path contains quotes and split it accordingly
|
|
123
|
+
if '/"' in path and '"/' in path:
|
|
124
|
+
if path.count('"') > 2:
|
|
125
|
+
raise UsageError(
|
|
126
|
+
f'Invalid string {path}, too much " in path, expected 2.'
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
path_parts = path.split('"')
|
|
130
|
+
before_quoted_part = GitManager._split_path_without_empty_parts(
|
|
131
|
+
path_parts[0]
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
if path_parts[2] == "/":
|
|
135
|
+
after_quoted_part = []
|
|
136
|
+
else:
|
|
137
|
+
after_quoted_part = GitManager._split_path_without_empty_parts(
|
|
138
|
+
path_parts[2]
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
return [
|
|
142
|
+
*before_quoted_part,
|
|
143
|
+
f'"{path_parts[1]}"',
|
|
144
|
+
*after_quoted_part,
|
|
145
|
+
]
|
|
146
|
+
else:
|
|
147
|
+
return GitManager._split_path_without_empty_parts(path)
|
|
148
|
+
|
|
149
|
+
@staticmethod
|
|
150
|
+
def _split_path_without_empty_parts(path: str):
|
|
151
|
+
return [e for e in PurePosixPath(path).parts if e != "/"]
|
|
@@ -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.git 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.git import commands
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@plugin_hook_impl
|
|
@@ -0,0 +1,90 @@
|
|
|
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 typer
|
|
18
|
+
import yaml
|
|
19
|
+
from click import ClickException
|
|
20
|
+
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
21
|
+
from snowflake.cli.api.output.types import MessageResult
|
|
22
|
+
from snowflake.cli.api.project.definition_conversion import (
|
|
23
|
+
convert_project_definition_to_v2,
|
|
24
|
+
)
|
|
25
|
+
from snowflake.cli.api.project.definition_manager import DefinitionManager
|
|
26
|
+
from snowflake.cli.api.secure_path import SecurePath
|
|
27
|
+
|
|
28
|
+
app = SnowTyperFactory(
|
|
29
|
+
name="helpers",
|
|
30
|
+
help="Helper commands.",
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@app.command()
|
|
35
|
+
def v1_to_v2(
|
|
36
|
+
accept_templates: bool = typer.Option(
|
|
37
|
+
False, "-t", "--accept-templates", help="Allows the migration of templates."
|
|
38
|
+
),
|
|
39
|
+
migrate_local_yml: (bool | None) = typer.Option(
|
|
40
|
+
None,
|
|
41
|
+
"-l",
|
|
42
|
+
"--migrate-local-overrides/--no-migrate-local-overrides",
|
|
43
|
+
help=(
|
|
44
|
+
"Merge values in snowflake.local.yml into the main project definition. "
|
|
45
|
+
"The snowflake.local.yml file will not be migrated, "
|
|
46
|
+
"instead its values will be reflected in the output snowflake.yml file. "
|
|
47
|
+
"If unset and snowflake.local.yml is present, an error will be raised."
|
|
48
|
+
),
|
|
49
|
+
show_default=False,
|
|
50
|
+
),
|
|
51
|
+
**options,
|
|
52
|
+
):
|
|
53
|
+
"""Migrates the Snowpark, Streamlit, and Native App project definition files from V1 to V2."""
|
|
54
|
+
manager = DefinitionManager()
|
|
55
|
+
local_yml_path = manager.project_root / "snowflake.local.yml"
|
|
56
|
+
has_local_yml = local_yml_path in manager.project_config_paths
|
|
57
|
+
if has_local_yml:
|
|
58
|
+
if migrate_local_yml is None:
|
|
59
|
+
raise ClickException(
|
|
60
|
+
"snowflake.local.yml file detected, "
|
|
61
|
+
"please specify --migrate-local-overrides to include "
|
|
62
|
+
"or --no-migrate-local-overrides to exclude its values."
|
|
63
|
+
)
|
|
64
|
+
if not migrate_local_yml:
|
|
65
|
+
# If we don't want the local file,
|
|
66
|
+
# remove it from the list of paths to load
|
|
67
|
+
manager.project_config_paths.remove(local_yml_path)
|
|
68
|
+
|
|
69
|
+
pd = manager.unrendered_project_definition
|
|
70
|
+
|
|
71
|
+
if pd.meets_version_requirement("2"):
|
|
72
|
+
return MessageResult("Project definition is already at version 2.")
|
|
73
|
+
|
|
74
|
+
pd_v2 = convert_project_definition_to_v2(
|
|
75
|
+
manager.project_root, pd, accept_templates, manager.template_context
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
SecurePath("snowflake.yml").rename("snowflake_V1.yml")
|
|
79
|
+
if has_local_yml:
|
|
80
|
+
SecurePath("snowflake.local.yml").rename("snowflake_V1.local.yml")
|
|
81
|
+
with open("snowflake.yml", "w") as file:
|
|
82
|
+
yaml.dump(
|
|
83
|
+
pd_v2.model_dump(
|
|
84
|
+
exclude_unset=True, exclude_none=True, mode="json", by_alias=True
|
|
85
|
+
),
|
|
86
|
+
file,
|
|
87
|
+
sort_keys=False,
|
|
88
|
+
width=float("inf"), # Don't break lines
|
|
89
|
+
)
|
|
90
|
+
return MessageResult("Project definition migrated to version 2.")
|
|
@@ -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.helpers 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.notebook import commands
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@plugin_hook_impl
|
|
@@ -23,10 +23,10 @@ from click import ClickException
|
|
|
23
23
|
from snowflake.cli.__about__ import VERSION
|
|
24
24
|
from snowflake.cli.api.commands.flags import (
|
|
25
25
|
NoInteractiveOption,
|
|
26
|
-
parse_key_value_variables,
|
|
27
26
|
variables_option,
|
|
28
27
|
)
|
|
29
28
|
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
29
|
+
from snowflake.cli.api.commands.utils import parse_key_value_variables
|
|
30
30
|
from snowflake.cli.api.constants import DEFAULT_SIZE_LIMIT_MB
|
|
31
31
|
from snowflake.cli.api.exceptions import InvalidTemplate
|
|
32
32
|
from snowflake.cli.api.output.types import (
|
|
@@ -68,7 +68,8 @@ TemplateOption = typer.Option(
|
|
|
68
68
|
show_default=False,
|
|
69
69
|
)
|
|
70
70
|
SourceOption = typer.Option(
|
|
71
|
-
|
|
71
|
+
DEFAULT_SOURCE,
|
|
72
|
+
"--template-source",
|
|
72
73
|
help=f"local path to template directory or URL to git repository with templates.",
|
|
73
74
|
)
|
|
74
75
|
VariablesOption = variables_option(
|
|
@@ -106,7 +107,7 @@ def _fetch_remote_template(
|
|
|
106
107
|
from git import rmtree as git_rmtree
|
|
107
108
|
|
|
108
109
|
# TODO: during nativeapp refactor get rid of this dependency
|
|
109
|
-
from snowflake.cli.
|
|
110
|
+
from snowflake.cli._plugins.nativeapp.utils import shallow_git_clone
|
|
110
111
|
|
|
111
112
|
log.info("Downloading remote template from %s", url)
|
|
112
113
|
try:
|
|
@@ -132,13 +133,13 @@ def _fetch_remote_template(
|
|
|
132
133
|
return template_root
|
|
133
134
|
|
|
134
135
|
|
|
135
|
-
def _read_template_metadata(template_root: SecurePath) -> Template:
|
|
136
|
+
def _read_template_metadata(template_root: SecurePath, args_error_msg: str) -> Template:
|
|
136
137
|
"""Parse template.yml file."""
|
|
137
138
|
template_metadata_path = template_root / TEMPLATE_METADATA_FILE_NAME
|
|
138
139
|
log.debug("Reading template metadata from %s", template_metadata_path.path)
|
|
139
140
|
if not template_metadata_path.exists():
|
|
140
141
|
raise InvalidTemplate(
|
|
141
|
-
f"
|
|
142
|
+
f"File {TEMPLATE_METADATA_FILE_NAME} not found. {args_error_msg}"
|
|
142
143
|
)
|
|
143
144
|
with template_metadata_path.open(read_file_limit_mb=DEFAULT_SIZE_LIMIT_MB) as fd:
|
|
144
145
|
yaml_contents = yaml.safe_load(fd) or {}
|
|
@@ -203,6 +204,7 @@ def init(
|
|
|
203
204
|
is_remote = any(
|
|
204
205
|
template_source.startswith(prefix) for prefix in ["git@", "http://", "https://"] # type: ignore
|
|
205
206
|
)
|
|
207
|
+
args_error_msg = f"Check whether {TemplateOption.param_decls[0]} and {SourceOption.param_decls[0]} arguments are correct."
|
|
206
208
|
|
|
207
209
|
# copy/download template into tmpdir, so it is going to be removed in case command ends with an error
|
|
208
210
|
with SecurePath.temporary_directory() as tmpdir:
|
|
@@ -217,7 +219,9 @@ def init(
|
|
|
217
219
|
destination=tmpdir,
|
|
218
220
|
)
|
|
219
221
|
|
|
220
|
-
template_metadata = _read_template_metadata(
|
|
222
|
+
template_metadata = _read_template_metadata(
|
|
223
|
+
template_root, args_error_msg=args_error_msg
|
|
224
|
+
)
|
|
221
225
|
if template_metadata.minimum_cli_version:
|
|
222
226
|
_validate_cli_version(template_metadata.minimum_cli_version)
|
|
223
227
|
|
|
@@ -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.init 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.init import commands
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
@plugin_hook_impl
|
|
@@ -22,7 +22,8 @@ from typing import Any, Callable, Dict, Iterable, Iterator, List, Optional, Tupl
|
|
|
22
22
|
|
|
23
23
|
from click.exceptions import ClickException
|
|
24
24
|
from snowflake.cli.api.constants import DEFAULT_SIZE_LIMIT_MB
|
|
25
|
-
from snowflake.cli.api.project.schemas.native_app.path_mapping import PathMapping
|
|
25
|
+
from snowflake.cli.api.project.schemas.v1.native_app.path_mapping import PathMapping
|
|
26
|
+
from snowflake.cli.api.project.util import to_identifier
|
|
26
27
|
from snowflake.cli.api.secure_path import SecurePath
|
|
27
28
|
from yaml import safe_load
|
|
28
29
|
|
|
@@ -199,6 +200,12 @@ class _ArtifactPathMap:
|
|
|
199
200
|
"""
|
|
200
201
|
return self.__src_to_dest.keys()
|
|
201
202
|
|
|
203
|
+
def is_empty(self) -> bool:
|
|
204
|
+
"""
|
|
205
|
+
Returns True if this map has no source-destination mappings.
|
|
206
|
+
"""
|
|
207
|
+
return len(self.__src_dest_pairs) == 0
|
|
208
|
+
|
|
202
209
|
def __iter__(self) -> Iterator[Tuple[Path, Path]]:
|
|
203
210
|
"""
|
|
204
211
|
Returns all (source, destination) pairs known to this map, in insertion order.
|
|
@@ -240,6 +247,9 @@ class BundleMap:
|
|
|
240
247
|
self._deploy_root: Path = resolve_without_follow(deploy_root)
|
|
241
248
|
self._artifact_map = _ArtifactPathMap(project_root=self._project_root)
|
|
242
249
|
|
|
250
|
+
def is_empty(self) -> bool:
|
|
251
|
+
return self._artifact_map.is_empty()
|
|
252
|
+
|
|
243
253
|
def deploy_root(self) -> Path:
|
|
244
254
|
return self._deploy_root
|
|
245
255
|
|
|
@@ -658,6 +668,11 @@ def build_bundle(
|
|
|
658
668
|
for artifact in artifacts:
|
|
659
669
|
bundle_map.add(artifact)
|
|
660
670
|
|
|
671
|
+
if bundle_map.is_empty():
|
|
672
|
+
raise ArtifactError(
|
|
673
|
+
"No artifacts mapping found in project definition, nothing to do."
|
|
674
|
+
)
|
|
675
|
+
|
|
661
676
|
for (absolute_src, absolute_dest) in bundle_map.all_mappings(
|
|
662
677
|
absolute=True, expand_directories=False
|
|
663
678
|
):
|
|
@@ -720,23 +735,23 @@ def find_setup_script_file(deploy_root: Path) -> Path:
|
|
|
720
735
|
|
|
721
736
|
def find_version_info_in_manifest_file(
|
|
722
737
|
deploy_root: Path,
|
|
723
|
-
) -> Tuple[Optional[str], Optional[
|
|
738
|
+
) -> Tuple[Optional[str], Optional[int]]:
|
|
724
739
|
"""
|
|
725
740
|
Find version and patch, if available, in the manifest.yml file.
|
|
726
741
|
"""
|
|
727
|
-
version_field = "version"
|
|
728
742
|
name_field = "name"
|
|
729
743
|
patch_field = "patch"
|
|
730
744
|
|
|
731
745
|
manifest_content = find_and_read_manifest_file(deploy_root=deploy_root)
|
|
732
746
|
|
|
733
747
|
version_name: Optional[str] = None
|
|
734
|
-
|
|
748
|
+
patch_number: Optional[int] = None
|
|
735
749
|
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
750
|
+
version_info = manifest_content.get("version", None)
|
|
751
|
+
if version_info:
|
|
752
|
+
if name_field in version_info:
|
|
753
|
+
version_name = to_identifier(str(version_info[name_field]))
|
|
739
754
|
if patch_field in version_info:
|
|
740
|
-
|
|
755
|
+
patch_number = int(version_info[patch_field])
|
|
741
756
|
|
|
742
|
-
return version_name,
|
|
757
|
+
return version_name, patch_number
|