snowflake-cli-labs 3.0.0rc2__py3-none-any.whl → 3.0.0rc4__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/commands_registration/builtin_plugins.py +2 -0
- snowflake/cli/_app/secret.py +9 -0
- snowflake/cli/_app/snow_connector.py +39 -27
- snowflake/cli/_app/telemetry.py +28 -0
- snowflake/cli/_plugins/connection/commands.py +9 -4
- snowflake/cli/_plugins/git/manager.py +53 -7
- snowflake/cli/_plugins/helpers/commands.py +61 -0
- snowflake/cli/{api/project/schemas/snowpark/__init__.py → _plugins/helpers/plugin_spec.py} +17 -0
- snowflake/cli/_plugins/nativeapp/artifacts.py +10 -9
- snowflake/cli/_plugins/nativeapp/bundle_context.py +1 -1
- snowflake/cli/_plugins/nativeapp/codegen/artifact_processor.py +1 -1
- snowflake/cli/_plugins/nativeapp/codegen/compiler.py +6 -1
- snowflake/cli/_plugins/nativeapp/codegen/setup/native_app_setup_processor.py +1 -1
- snowflake/cli/_plugins/nativeapp/codegen/snowpark/extension_function_utils.py +1 -1
- snowflake/cli/_plugins/nativeapp/codegen/snowpark/models.py +1 -1
- snowflake/cli/_plugins/nativeapp/codegen/snowpark/python_processor.py +5 -1
- snowflake/cli/_plugins/nativeapp/codegen/templates/templates_processor.py +4 -1
- snowflake/cli/_plugins/nativeapp/commands.py +87 -96
- snowflake/cli/_plugins/nativeapp/entities/__init__.py +0 -0
- snowflake/cli/{api/entities/application_entity.py → _plugins/nativeapp/entities/application.py} +264 -83
- snowflake/cli/_plugins/nativeapp/entities/application_package.py +1392 -0
- snowflake/cli/_plugins/nativeapp/exceptions.py +0 -9
- snowflake/cli/_plugins/nativeapp/manager.py +69 -185
- snowflake/cli/_plugins/nativeapp/policy.py +3 -0
- snowflake/cli/_plugins/nativeapp/project_model.py +2 -2
- snowflake/cli/_plugins/nativeapp/run_processor.py +17 -20
- snowflake/cli/_plugins/nativeapp/same_account_install_method.py +0 -4
- snowflake/cli/_plugins/nativeapp/teardown_processor.py +4 -6
- snowflake/cli/_plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +122 -88
- snowflake/cli/_plugins/nativeapp/version/commands.py +7 -39
- snowflake/cli/_plugins/nativeapp/version/version_processor.py +46 -312
- snowflake/cli/_plugins/object/manager.py +36 -15
- snowflake/cli/_plugins/snowpark/commands.py +4 -4
- snowflake/cli/_plugins/snowpark/common.py +4 -4
- snowflake/cli/{api/entities → _plugins/snowpark}/snowpark_entity.py +2 -2
- snowflake/cli/{api/project/schemas/entities/snowpark_entity.py → _plugins/snowpark/snowpark_entity_model.py} +3 -6
- snowflake/cli/_plugins/snowpark/snowpark_project_paths.py +1 -1
- snowflake/cli/_plugins/stage/manager.py +9 -4
- snowflake/cli/_plugins/streamlit/commands.py +15 -3
- snowflake/cli/_plugins/streamlit/manager.py +12 -4
- snowflake/cli/{api/entities → _plugins/streamlit}/streamlit_entity.py +2 -2
- snowflake/cli/{api/project/schemas/entities → _plugins/streamlit}/streamlit_entity_model.py +5 -12
- snowflake/cli/_plugins/workspace/commands.py +116 -36
- snowflake/cli/_plugins/workspace/plugin_spec.py +1 -1
- snowflake/cli/api/cli_global_context.py +7 -0
- snowflake/cli/api/commands/decorators.py +14 -0
- snowflake/cli/api/commands/flags.py +18 -0
- snowflake/cli/api/commands/snow_typer.py +1 -1
- snowflake/cli/api/config.py +25 -6
- snowflake/cli/api/connections.py +3 -1
- snowflake/cli/api/entities/common.py +4 -0
- snowflake/cli/api/entities/utils.py +3 -14
- snowflake/cli/api/errno.py +1 -0
- snowflake/cli/api/identifiers.py +4 -3
- snowflake/cli/api/metrics.py +92 -0
- snowflake/cli/api/project/definition_conversion.py +61 -18
- snowflake/cli/api/project/schemas/entities/common.py +17 -4
- snowflake/cli/api/project/schemas/entities/entities.py +11 -10
- snowflake/cli/api/project/schemas/project_definition.py +5 -7
- snowflake/cli/api/project/schemas/v1/__init__.py +0 -0
- snowflake/cli/api/project/schemas/{identifier_model.py → v1/identifier_model.py} +0 -7
- snowflake/cli/api/project/schemas/v1/native_app/__init__.py +0 -0
- snowflake/cli/api/project/schemas/{native_app → v1/native_app}/native_app.py +4 -4
- 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/rendering/sql_templates.py +6 -0
- snowflake/cli/api/rest_api.py +11 -5
- snowflake/cli/api/sql_execution.py +6 -15
- snowflake/cli/api/utils/definition_rendering.py +24 -4
- {snowflake_cli_labs-3.0.0rc2.dist-info → snowflake_cli_labs-3.0.0rc4.dist-info}/METADATA +9 -7
- {snowflake_cli_labs-3.0.0rc2.dist-info → snowflake_cli_labs-3.0.0rc4.dist-info}/RECORD +83 -79
- snowflake/cli/_plugins/nativeapp/init.py +0 -345
- snowflake/cli/api/entities/application_package_entity.py +0 -658
- snowflake/cli/api/project/schemas/entities/application_entity_model.py +0 -56
- snowflake/cli/api/project/schemas/entities/application_package_entity_model.py +0 -94
- snowflake/cli/api/project/schemas/streamlit/__init__.py +0 -13
- /snowflake/cli/{api/project/schemas/native_app → _plugins/helpers}/__init__.py +0 -0
- /snowflake/cli/api/project/schemas/{native_app → v1/native_app}/application.py +0 -0
- /snowflake/cli/api/project/schemas/{native_app → v1/native_app}/package.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-3.0.0rc2.dist-info → snowflake_cli_labs-3.0.0rc4.dist-info}/WHEEL +0 -0
- {snowflake_cli_labs-3.0.0rc2.dist-info → snowflake_cli_labs-3.0.0rc4.dist-info}/entry_points.txt +0 -0
- {snowflake_cli_labs-3.0.0rc2.dist-info → snowflake_cli_labs-3.0.0rc4.dist-info}/licenses/LICENSE +0 -0
|
@@ -20,36 +20,62 @@ from snowflake.cli.api.entities.utils import render_script_template
|
|
|
20
20
|
from snowflake.cli.api.project.schemas.entities.common import (
|
|
21
21
|
SqlScriptHookType,
|
|
22
22
|
)
|
|
23
|
-
from snowflake.cli.api.project.schemas.native_app.application import (
|
|
24
|
-
Application,
|
|
25
|
-
ApplicationV11,
|
|
26
|
-
)
|
|
27
|
-
from snowflake.cli.api.project.schemas.native_app.native_app import NativeApp
|
|
28
|
-
from snowflake.cli.api.project.schemas.native_app.package import Package, PackageV11
|
|
29
23
|
from snowflake.cli.api.project.schemas.project_definition import (
|
|
30
24
|
ProjectDefinition,
|
|
31
25
|
ProjectDefinitionV2,
|
|
32
26
|
)
|
|
33
|
-
from snowflake.cli.api.project.schemas.
|
|
27
|
+
from snowflake.cli.api.project.schemas.v1.native_app.application import (
|
|
28
|
+
Application,
|
|
29
|
+
ApplicationV11,
|
|
30
|
+
)
|
|
31
|
+
from snowflake.cli.api.project.schemas.v1.native_app.native_app import NativeApp
|
|
32
|
+
from snowflake.cli.api.project.schemas.v1.native_app.package import Package, PackageV11
|
|
33
|
+
from snowflake.cli.api.project.schemas.v1.snowpark.callable import (
|
|
34
34
|
FunctionSchema,
|
|
35
35
|
ProcedureSchema,
|
|
36
36
|
)
|
|
37
|
-
from snowflake.cli.api.project.schemas.snowpark.snowpark import Snowpark
|
|
38
|
-
from snowflake.cli.api.project.schemas.streamlit.streamlit import Streamlit
|
|
37
|
+
from snowflake.cli.api.project.schemas.v1.snowpark.snowpark import Snowpark
|
|
38
|
+
from snowflake.cli.api.project.schemas.v1.streamlit.streamlit import Streamlit
|
|
39
39
|
from snowflake.cli.api.rendering.jinja import get_basic_jinja_env
|
|
40
40
|
|
|
41
41
|
log = logging.getLogger(__name__)
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
def _is_field_defined(template_context: Optional[Dict[str, Any]], *path: str) -> bool:
|
|
45
|
+
"""
|
|
46
|
+
Determines if a field is defined in the provided template context. For example,
|
|
47
|
+
|
|
48
|
+
_is_field_defined({"ctx": {"native_app": {"bundle_root": "my_root"}}}, "ctx", "native_app", "bundle_root")
|
|
49
|
+
|
|
50
|
+
returns True. If the provided template context is None, this function returns True for all paths.
|
|
51
|
+
|
|
52
|
+
"""
|
|
53
|
+
if template_context is None:
|
|
54
|
+
return True # No context, so assume that all variables are defined
|
|
55
|
+
|
|
56
|
+
current_dict = template_context
|
|
57
|
+
for key in path:
|
|
58
|
+
if not isinstance(current_dict, dict):
|
|
59
|
+
return False
|
|
60
|
+
if key not in current_dict:
|
|
61
|
+
return False
|
|
62
|
+
current_dict = current_dict[key]
|
|
63
|
+
|
|
64
|
+
return True
|
|
65
|
+
|
|
66
|
+
|
|
44
67
|
def convert_project_definition_to_v2(
|
|
45
|
-
project_root: Path,
|
|
68
|
+
project_root: Path,
|
|
69
|
+
pd: ProjectDefinition,
|
|
70
|
+
accept_templates: bool = False,
|
|
71
|
+
template_context: Optional[Dict[str, Any]] = None,
|
|
46
72
|
) -> ProjectDefinitionV2:
|
|
47
73
|
_check_if_project_definition_meets_requirements(pd, accept_templates)
|
|
48
74
|
|
|
49
75
|
snowpark_data = convert_snowpark_to_v2_data(pd.snowpark) if pd.snowpark else {}
|
|
50
76
|
streamlit_data = convert_streamlit_to_v2_data(pd.streamlit) if pd.streamlit else {}
|
|
51
77
|
native_app_data = (
|
|
52
|
-
convert_native_app_to_v2_data(project_root, pd.native_app)
|
|
78
|
+
convert_native_app_to_v2_data(project_root, pd.native_app, template_context)
|
|
53
79
|
if pd.native_app
|
|
54
80
|
else {}
|
|
55
81
|
)
|
|
@@ -157,6 +183,7 @@ def convert_streamlit_to_v2_data(streamlit: Streamlit) -> Dict[str, Any]:
|
|
|
157
183
|
"type": "streamlit",
|
|
158
184
|
"identifier": identifier,
|
|
159
185
|
"title": streamlit.title,
|
|
186
|
+
"comment": streamlit.comment,
|
|
160
187
|
"query_warehouse": streamlit.query_warehouse,
|
|
161
188
|
"main_file": str(streamlit.main_file),
|
|
162
189
|
"pages_dir": str(streamlit.pages_dir),
|
|
@@ -169,7 +196,9 @@ def convert_streamlit_to_v2_data(streamlit: Streamlit) -> Dict[str, Any]:
|
|
|
169
196
|
|
|
170
197
|
|
|
171
198
|
def convert_native_app_to_v2_data(
|
|
172
|
-
project_root,
|
|
199
|
+
project_root,
|
|
200
|
+
native_app: NativeApp,
|
|
201
|
+
template_context: Optional[Dict[str, Any]] = None,
|
|
173
202
|
) -> Dict[str, Any]:
|
|
174
203
|
def _make_meta(obj: Application | Package):
|
|
175
204
|
meta = {}
|
|
@@ -249,14 +278,24 @@ def convert_native_app_to_v2_data(
|
|
|
249
278
|
"identifier": package_identifier,
|
|
250
279
|
"manifest": _find_manifest(),
|
|
251
280
|
"artifacts": native_app.artifacts,
|
|
252
|
-
"bundle_root": native_app.bundle_root,
|
|
253
|
-
"generated_root": native_app.generated_root,
|
|
254
|
-
"deploy_root": native_app.deploy_root,
|
|
255
|
-
"stage": native_app.source_stage,
|
|
256
|
-
"scratch_stage": native_app.scratch_stage,
|
|
257
281
|
}
|
|
282
|
+
|
|
283
|
+
if _is_field_defined(template_context, "ctx", "native_app", "bundle_root"):
|
|
284
|
+
package["bundle_root"] = native_app.bundle_root
|
|
285
|
+
if _is_field_defined(template_context, "ctx", "native_app", "generated_root"):
|
|
286
|
+
package["generated_root"] = native_app.generated_root
|
|
287
|
+
if _is_field_defined(template_context, "ctx", "native_app", "deploy_root"):
|
|
288
|
+
package["deploy_root"] = native_app.deploy_root
|
|
289
|
+
if _is_field_defined(template_context, "ctx", "native_app", "source_stage"):
|
|
290
|
+
package["stage"] = native_app.source_stage
|
|
291
|
+
if _is_field_defined(template_context, "ctx", "native_app", "scratch_stage"):
|
|
292
|
+
package["scratch_stage"] = native_app.scratch_stage
|
|
293
|
+
|
|
258
294
|
if native_app.package:
|
|
259
|
-
|
|
295
|
+
if _is_field_defined(
|
|
296
|
+
template_context, "ctx", "native_app", "package", "distribution"
|
|
297
|
+
):
|
|
298
|
+
package["distribution"] = native_app.package.distribution
|
|
260
299
|
package_meta = _make_meta(native_app.package)
|
|
261
300
|
if native_app.package.scripts:
|
|
262
301
|
converted_post_deploy_hooks = _convert_package_script_files(
|
|
@@ -288,6 +327,10 @@ def convert_native_app_to_v2_data(
|
|
|
288
327
|
if native_app.application:
|
|
289
328
|
if app_meta := _make_meta(native_app.application):
|
|
290
329
|
app["meta"] = app_meta
|
|
330
|
+
if _is_field_defined(
|
|
331
|
+
template_context, "ctx", "native_app", "application", "debug"
|
|
332
|
+
):
|
|
333
|
+
app["debug"] = native_app.application.debug
|
|
291
334
|
|
|
292
335
|
return {
|
|
293
336
|
"entities": {
|
|
@@ -15,11 +15,10 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
from abc import ABC
|
|
18
|
-
from typing import Generic, List, Optional, TypeVar, Union
|
|
18
|
+
from typing import Dict, Generic, List, Optional, TypeVar, Union
|
|
19
19
|
|
|
20
20
|
from pydantic import Field, PrivateAttr, field_validator
|
|
21
21
|
from snowflake.cli.api.identifiers import FQN
|
|
22
|
-
from snowflake.cli.api.project.schemas.identifier_model import Identifier
|
|
23
22
|
from snowflake.cli.api.project.schemas.updatable_model import (
|
|
24
23
|
IdentifierField,
|
|
25
24
|
UpdatableModel,
|
|
@@ -61,6 +60,12 @@ class MetaField(UpdatableModel):
|
|
|
61
60
|
return mixins
|
|
62
61
|
|
|
63
62
|
|
|
63
|
+
class Identifier(UpdatableModel):
|
|
64
|
+
name: str = Field(title="Entity name")
|
|
65
|
+
schema_: Optional[str] = Field(title="Entity schema", alias="schema", default=None)
|
|
66
|
+
database: Optional[str] = Field(title="Entity database", default=None)
|
|
67
|
+
|
|
68
|
+
|
|
64
69
|
class EntityModelBase(ABC, UpdatableModel):
|
|
65
70
|
@classmethod
|
|
66
71
|
def get_type(cls) -> str:
|
|
@@ -112,9 +117,17 @@ class TargetField(UpdatableModel, Generic[TargetType]):
|
|
|
112
117
|
return self.__pydantic_generic_metadata__["args"][0]
|
|
113
118
|
|
|
114
119
|
|
|
115
|
-
|
|
120
|
+
class ImportsBaseModel:
|
|
121
|
+
imports: Optional[List[str]] = Field(
|
|
122
|
+
title="Stage and path to previously uploaded files you want to import",
|
|
123
|
+
default=[],
|
|
124
|
+
)
|
|
116
125
|
|
|
117
|
-
|
|
126
|
+
def get_imports_sql(self) -> str | None:
|
|
127
|
+
if not self.imports:
|
|
128
|
+
return None
|
|
129
|
+
imports = ", ".join(f"'{i}'" for i in self.imports)
|
|
130
|
+
return f"IMPORTS = ({imports})"
|
|
118
131
|
|
|
119
132
|
|
|
120
133
|
class ExternalAccessBaseModel:
|
|
@@ -16,23 +16,24 @@ from __future__ import annotations
|
|
|
16
16
|
|
|
17
17
|
from typing import Dict, List, Union, get_args
|
|
18
18
|
|
|
19
|
-
from snowflake.cli.
|
|
20
|
-
|
|
21
|
-
ApplicationPackageEntity,
|
|
22
|
-
)
|
|
23
|
-
from snowflake.cli.api.entities.snowpark_entity import FunctionEntity, ProcedureEntity
|
|
24
|
-
from snowflake.cli.api.entities.streamlit_entity import StreamlitEntity
|
|
25
|
-
from snowflake.cli.api.project.schemas.entities.application_entity_model import (
|
|
19
|
+
from snowflake.cli._plugins.nativeapp.entities.application import (
|
|
20
|
+
ApplicationEntity,
|
|
26
21
|
ApplicationEntityModel,
|
|
27
22
|
)
|
|
28
|
-
from snowflake.cli.
|
|
23
|
+
from snowflake.cli._plugins.nativeapp.entities.application_package import (
|
|
24
|
+
ApplicationPackageEntity,
|
|
29
25
|
ApplicationPackageEntityModel,
|
|
30
26
|
)
|
|
31
|
-
from snowflake.cli.
|
|
27
|
+
from snowflake.cli._plugins.snowpark.snowpark_entity import (
|
|
28
|
+
FunctionEntity,
|
|
29
|
+
ProcedureEntity,
|
|
30
|
+
)
|
|
31
|
+
from snowflake.cli._plugins.snowpark.snowpark_entity_model import (
|
|
32
32
|
FunctionEntityModel,
|
|
33
33
|
ProcedureEntityModel,
|
|
34
34
|
)
|
|
35
|
-
from snowflake.cli.
|
|
35
|
+
from snowflake.cli._plugins.streamlit.streamlit_entity import StreamlitEntity
|
|
36
|
+
from snowflake.cli._plugins.streamlit.streamlit_entity_model import (
|
|
36
37
|
StreamlitEntityModel,
|
|
37
38
|
)
|
|
38
39
|
|
|
@@ -19,10 +19,8 @@ from typing import Any, Dict, List, Optional, Union
|
|
|
19
19
|
|
|
20
20
|
from packaging.version import Version
|
|
21
21
|
from pydantic import Field, ValidationError, field_validator, model_validator
|
|
22
|
+
from snowflake.cli._plugins.nativeapp.entities.application import ApplicationEntityModel
|
|
22
23
|
from snowflake.cli.api.project.errors import SchemaValidationError
|
|
23
|
-
from snowflake.cli.api.project.schemas.entities.application_entity_model import (
|
|
24
|
-
ApplicationEntityModel,
|
|
25
|
-
)
|
|
26
24
|
from snowflake.cli.api.project.schemas.entities.common import (
|
|
27
25
|
TargetField,
|
|
28
26
|
)
|
|
@@ -30,13 +28,13 @@ from snowflake.cli.api.project.schemas.entities.entities import (
|
|
|
30
28
|
EntityModel,
|
|
31
29
|
v2_entity_model_types_map,
|
|
32
30
|
)
|
|
33
|
-
from snowflake.cli.api.project.schemas.
|
|
31
|
+
from snowflake.cli.api.project.schemas.updatable_model import UpdatableModel
|
|
32
|
+
from snowflake.cli.api.project.schemas.v1.native_app.native_app import (
|
|
34
33
|
NativeApp,
|
|
35
34
|
NativeAppV11,
|
|
36
35
|
)
|
|
37
|
-
from snowflake.cli.api.project.schemas.snowpark.snowpark import Snowpark
|
|
38
|
-
from snowflake.cli.api.project.schemas.streamlit.streamlit import Streamlit
|
|
39
|
-
from snowflake.cli.api.project.schemas.updatable_model import UpdatableModel
|
|
36
|
+
from snowflake.cli.api.project.schemas.v1.snowpark.snowpark import Snowpark
|
|
37
|
+
from snowflake.cli.api.project.schemas.v1.streamlit.streamlit import Streamlit
|
|
40
38
|
from snowflake.cli.api.utils.types import Context
|
|
41
39
|
from typing_extensions import Annotated
|
|
42
40
|
|
|
File without changes
|
|
@@ -19,16 +19,9 @@ from typing import Optional, cast
|
|
|
19
19
|
from pydantic import Field
|
|
20
20
|
from snowflake.cli.api.project.schemas.updatable_model import (
|
|
21
21
|
IdentifierField,
|
|
22
|
-
UpdatableModel,
|
|
23
22
|
)
|
|
24
23
|
|
|
25
24
|
|
|
26
|
-
class Identifier(UpdatableModel):
|
|
27
|
-
name: str = Field(title="Entity name")
|
|
28
|
-
schema_: Optional[str] = Field(title="Entity schema", alias="schema", default=None)
|
|
29
|
-
database: Optional[str] = Field(title="Entity database", default=None)
|
|
30
|
-
|
|
31
|
-
|
|
32
25
|
class ObjectIdentifierBaseModel:
|
|
33
26
|
"""
|
|
34
27
|
Type representing a base class defining object that can be identified by fully qualified name (db.schema.name).
|
|
File without changes
|
|
@@ -18,13 +18,13 @@ import re
|
|
|
18
18
|
from typing import List, Optional, Union
|
|
19
19
|
|
|
20
20
|
from pydantic import Field, field_validator
|
|
21
|
-
from snowflake.cli.api.project.schemas.
|
|
21
|
+
from snowflake.cli.api.project.schemas.updatable_model import UpdatableModel
|
|
22
|
+
from snowflake.cli.api.project.schemas.v1.native_app.application import (
|
|
22
23
|
Application,
|
|
23
24
|
ApplicationV11,
|
|
24
25
|
)
|
|
25
|
-
from snowflake.cli.api.project.schemas.native_app.package import Package, PackageV11
|
|
26
|
-
from snowflake.cli.api.project.schemas.native_app.path_mapping import PathMapping
|
|
27
|
-
from snowflake.cli.api.project.schemas.updatable_model import UpdatableModel
|
|
26
|
+
from snowflake.cli.api.project.schemas.v1.native_app.package import Package, PackageV11
|
|
27
|
+
from snowflake.cli.api.project.schemas.v1.native_app.path_mapping import PathMapping
|
|
28
28
|
from snowflake.cli.api.project.util import (
|
|
29
29
|
SCHEMA_AND_NAME,
|
|
30
30
|
)
|
|
File without changes
|
|
@@ -17,9 +17,9 @@ from __future__ import annotations
|
|
|
17
17
|
from typing import Dict, List, Optional, Union
|
|
18
18
|
|
|
19
19
|
from pydantic import Field, field_validator
|
|
20
|
-
from snowflake.cli.api.project.schemas.identifier_model import ObjectIdentifierModel
|
|
21
|
-
from snowflake.cli.api.project.schemas.snowpark.argument import Argument
|
|
22
20
|
from snowflake.cli.api.project.schemas.updatable_model import UpdatableModel
|
|
21
|
+
from snowflake.cli.api.project.schemas.v1.identifier_model import ObjectIdentifierModel
|
|
22
|
+
from snowflake.cli.api.project.schemas.v1.snowpark.argument import Argument
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class _CallableBase(UpdatableModel):
|
|
@@ -17,11 +17,11 @@ from __future__ import annotations
|
|
|
17
17
|
from typing import List, Optional
|
|
18
18
|
|
|
19
19
|
from pydantic import Field
|
|
20
|
-
from snowflake.cli.api.project.schemas.
|
|
20
|
+
from snowflake.cli.api.project.schemas.updatable_model import UpdatableModel
|
|
21
|
+
from snowflake.cli.api.project.schemas.v1.snowpark.callable import (
|
|
21
22
|
FunctionSchema,
|
|
22
23
|
ProcedureSchema,
|
|
23
24
|
)
|
|
24
|
-
from snowflake.cli.api.project.schemas.updatable_model import UpdatableModel
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class Snowpark(UpdatableModel):
|
|
File without changes
|
|
@@ -18,8 +18,8 @@ from pathlib import Path
|
|
|
18
18
|
from typing import List, Optional
|
|
19
19
|
|
|
20
20
|
from pydantic import Field
|
|
21
|
-
from snowflake.cli.api.project.schemas.identifier_model import ObjectIdentifierModel
|
|
22
21
|
from snowflake.cli.api.project.schemas.updatable_model import UpdatableModel
|
|
22
|
+
from snowflake.cli.api.project.schemas.v1.identifier_model import ObjectIdentifierModel
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
class Streamlit(UpdatableModel, ObjectIdentifierModel(object_name="Streamlit")): # type: ignore
|
|
@@ -44,3 +44,4 @@ class Streamlit(UpdatableModel, ObjectIdentifierModel(object_name="Streamlit")):
|
|
|
44
44
|
title: Optional[str] = Field(
|
|
45
45
|
title="Human-readable title for the Streamlit dashboard", default=None
|
|
46
46
|
)
|
|
47
|
+
comment: Optional[str] = Field(title="Comment for the Streamlit app", default=None)
|
|
@@ -21,6 +21,7 @@ from jinja2 import Environment, StrictUndefined, loaders, meta
|
|
|
21
21
|
from snowflake.cli.api.cli_global_context import get_cli_context
|
|
22
22
|
from snowflake.cli.api.console.console import cli_console
|
|
23
23
|
from snowflake.cli.api.exceptions import InvalidTemplate
|
|
24
|
+
from snowflake.cli.api.metrics import CLICounterField
|
|
24
25
|
from snowflake.cli.api.rendering.jinja import (
|
|
25
26
|
CONTEXT_KEY,
|
|
26
27
|
FUNCTION_KEY,
|
|
@@ -96,4 +97,9 @@ def snowflake_sql_jinja_render(content: str, data: Dict | None = None) -> str:
|
|
|
96
97
|
context_data = get_cli_context().template_context
|
|
97
98
|
context_data.update(data)
|
|
98
99
|
env = choose_sql_jinja_env_based_on_template_syntax(content)
|
|
100
|
+
|
|
101
|
+
get_cli_context().metrics.set_counter(
|
|
102
|
+
CLICounterField.SQL_TEMPLATES, int(has_sql_templates(content))
|
|
103
|
+
)
|
|
104
|
+
|
|
99
105
|
return env.from_string(content).render(context_data)
|
snowflake/cli/api/rest_api.py
CHANGED
|
@@ -21,8 +21,9 @@ from typing import Any, Dict, Optional
|
|
|
21
21
|
from click import ClickException
|
|
22
22
|
from snowflake.cli.api.constants import SF_REST_API_URL_PREFIX
|
|
23
23
|
from snowflake.connector.connection import SnowflakeConnection
|
|
24
|
-
from snowflake.connector.errors import BadRequest
|
|
24
|
+
from snowflake.connector.errors import BadRequest
|
|
25
25
|
from snowflake.connector.network import SnowflakeRestful
|
|
26
|
+
from snowflake.connector.vendored.requests.exceptions import HTTPError
|
|
26
27
|
|
|
27
28
|
log = logging.getLogger(__name__)
|
|
28
29
|
|
|
@@ -47,10 +48,10 @@ class RestApi:
|
|
|
47
48
|
Check whether [get] endpoint exists under given URL.
|
|
48
49
|
"""
|
|
49
50
|
try:
|
|
50
|
-
|
|
51
|
-
return
|
|
52
|
-
except
|
|
53
|
-
if
|
|
51
|
+
self.send_rest_request(url, method="get")
|
|
52
|
+
return True
|
|
53
|
+
except HTTPError as err:
|
|
54
|
+
if err.response.status_code == 404:
|
|
54
55
|
return False
|
|
55
56
|
raise err
|
|
56
57
|
|
|
@@ -60,6 +61,10 @@ class RestApi:
|
|
|
60
61
|
return bool(result)
|
|
61
62
|
except BadRequest:
|
|
62
63
|
return False
|
|
64
|
+
except HTTPError as err:
|
|
65
|
+
if err.response.status_code == 404:
|
|
66
|
+
return False
|
|
67
|
+
raise err
|
|
63
68
|
|
|
64
69
|
def send_rest_request(
|
|
65
70
|
self, url: str, method: str, data: Optional[Dict[str, Any]] = None
|
|
@@ -91,6 +96,7 @@ class RestApi:
|
|
|
91
96
|
token=self.rest.token,
|
|
92
97
|
data=json.dumps(data if data else {}),
|
|
93
98
|
no_retry=True,
|
|
99
|
+
raise_raw_http_failure=True,
|
|
94
100
|
)
|
|
95
101
|
|
|
96
102
|
def _database_exists(self, db_name: str) -> bool:
|
|
@@ -98,11 +98,7 @@ class SqlExecutor:
|
|
|
98
98
|
)
|
|
99
99
|
|
|
100
100
|
def current_role(self) -> str:
|
|
101
|
-
|
|
102
|
-
"select current_role()", cursor_class=DictCursor
|
|
103
|
-
)
|
|
104
|
-
role_result = cursor.fetchone()
|
|
105
|
-
return role_result["CURRENT_ROLE()"]
|
|
101
|
+
return self._execute_query(f"select current_role()").fetchone()[0]
|
|
106
102
|
|
|
107
103
|
@contextmanager
|
|
108
104
|
def use_role(self, new_role: str):
|
|
@@ -110,10 +106,7 @@ class SqlExecutor:
|
|
|
110
106
|
Switches to a different role for a while, then switches back.
|
|
111
107
|
This is a no-op if the requested role is already active.
|
|
112
108
|
"""
|
|
113
|
-
|
|
114
|
-
f"select current_role()", cursor_class=DictCursor
|
|
115
|
-
).fetchone()
|
|
116
|
-
prev_role = role_result["CURRENT_ROLE()"]
|
|
109
|
+
prev_role = self.current_role()
|
|
117
110
|
is_different_role = new_role.lower() != prev_role.lower()
|
|
118
111
|
if is_different_role:
|
|
119
112
|
self._log.debug("Assuming different role: %s", new_role)
|
|
@@ -126,9 +119,9 @@ class SqlExecutor:
|
|
|
126
119
|
|
|
127
120
|
def session_has_warehouse(self) -> bool:
|
|
128
121
|
result = self._execute_query(
|
|
129
|
-
"select current_warehouse() is not null
|
|
122
|
+
"select current_warehouse() is not null"
|
|
130
123
|
).fetchone()
|
|
131
|
-
return bool(result
|
|
124
|
+
return bool(result[0])
|
|
132
125
|
|
|
133
126
|
@contextmanager
|
|
134
127
|
def use_warehouse(self, new_wh: str):
|
|
@@ -138,12 +131,10 @@ class SqlExecutor:
|
|
|
138
131
|
If there is no default warehouse in the account, it will throw an error.
|
|
139
132
|
"""
|
|
140
133
|
|
|
141
|
-
wh_result = self._execute_query(
|
|
142
|
-
f"select current_warehouse()", cursor_class=DictCursor
|
|
143
|
-
).fetchone()
|
|
134
|
+
wh_result = self._execute_query(f"select current_warehouse()").fetchone()
|
|
144
135
|
# If user has an assigned default warehouse, prev_wh will contain a value even if the warehouse is suspended.
|
|
145
136
|
try:
|
|
146
|
-
prev_wh = wh_result[
|
|
137
|
+
prev_wh = wh_result[0]
|
|
147
138
|
except:
|
|
148
139
|
prev_wh = None
|
|
149
140
|
|
|
@@ -19,8 +19,10 @@ from typing import Any, Optional
|
|
|
19
19
|
|
|
20
20
|
from jinja2 import Environment, TemplateSyntaxError, nodes
|
|
21
21
|
from packaging.version import Version
|
|
22
|
+
from snowflake.cli.api.cli_global_context import get_cli_context
|
|
22
23
|
from snowflake.cli.api.console import cli_console as cc
|
|
23
24
|
from snowflake.cli.api.exceptions import CycleDetectedError, InvalidTemplate
|
|
25
|
+
from snowflake.cli.api.metrics import CLICounterField
|
|
24
26
|
from snowflake.cli.api.project.schemas.project_definition import (
|
|
25
27
|
ProjectProperties,
|
|
26
28
|
build_project_definition,
|
|
@@ -266,6 +268,12 @@ def _get_referenced_vars_in_definition(
|
|
|
266
268
|
return referenced_vars
|
|
267
269
|
|
|
268
270
|
|
|
271
|
+
def _has_referenced_vars_in_definition(
|
|
272
|
+
template_env: TemplatedEnvironment, definition: Definition
|
|
273
|
+
) -> bool:
|
|
274
|
+
return len(_get_referenced_vars_in_definition(template_env, definition)) > 0
|
|
275
|
+
|
|
276
|
+
|
|
269
277
|
def _template_version_warning():
|
|
270
278
|
cc.warning(
|
|
271
279
|
"Ignoring template pattern in project definition file. "
|
|
@@ -291,6 +299,17 @@ def _add_defaults_to_definition(original_definition: Definition) -> Definition:
|
|
|
291
299
|
return definition_with_defaults
|
|
292
300
|
|
|
293
301
|
|
|
302
|
+
def _update_metrics(template_env: TemplatedEnvironment, definition: Definition):
|
|
303
|
+
metrics = get_cli_context().metrics
|
|
304
|
+
|
|
305
|
+
# render_definition_template is invoked multiple times both by the user
|
|
306
|
+
# and by us so we should make sure we don't overwrite a 1 with a 0 here
|
|
307
|
+
metrics.set_counter_default(CLICounterField.PDF_TEMPLATES, 0)
|
|
308
|
+
|
|
309
|
+
if _has_referenced_vars_in_definition(template_env, definition):
|
|
310
|
+
metrics.set_counter(CLICounterField.PDF_TEMPLATES, 1)
|
|
311
|
+
|
|
312
|
+
|
|
294
313
|
def render_definition_template(
|
|
295
314
|
original_definition: Optional[Definition], context_overrides: Context
|
|
296
315
|
) -> ProjectProperties:
|
|
@@ -326,10 +345,7 @@ def render_definition_template(
|
|
|
326
345
|
definition["definition_version"]
|
|
327
346
|
) < Version("1.1"):
|
|
328
347
|
try:
|
|
329
|
-
|
|
330
|
-
template_env, definition
|
|
331
|
-
)
|
|
332
|
-
if referenced_vars:
|
|
348
|
+
if _has_referenced_vars_in_definition(template_env, definition):
|
|
333
349
|
_template_version_warning()
|
|
334
350
|
except Exception:
|
|
335
351
|
# also warn on Exception, as it means the user is incorrectly attempting to use templating
|
|
@@ -340,6 +356,10 @@ def render_definition_template(
|
|
|
340
356
|
project_context[CONTEXT_KEY]["env"] = environment_overrides
|
|
341
357
|
return ProjectProperties(project_definition, project_context)
|
|
342
358
|
|
|
359
|
+
# need to have the metrics added here since we add defaults to the
|
|
360
|
+
# definition that the user might not have added themselves later
|
|
361
|
+
_update_metrics(template_env, definition)
|
|
362
|
+
|
|
343
363
|
definition = _add_defaults_to_definition(definition)
|
|
344
364
|
project_context = {CONTEXT_KEY: definition}
|
|
345
365
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: snowflake-cli-labs
|
|
3
|
-
Version: 3.0.
|
|
3
|
+
Version: 3.0.0rc4
|
|
4
4
|
Summary: Snowflake CLI
|
|
5
5
|
Project-URL: Source code, https://github.com/snowflakedb/snowflake-cli
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/snowflakedb/snowflake-cli/issues
|
|
@@ -222,14 +222,14 @@ Requires-Dist: jinja2==3.1.4
|
|
|
222
222
|
Requires-Dist: packaging
|
|
223
223
|
Requires-Dist: pip
|
|
224
224
|
Requires-Dist: pluggy==1.5.0
|
|
225
|
-
Requires-Dist: pydantic==2.9.
|
|
225
|
+
Requires-Dist: pydantic==2.9.2
|
|
226
226
|
Requires-Dist: pyyaml==6.0.2
|
|
227
227
|
Requires-Dist: requests==2.32.3
|
|
228
228
|
Requires-Dist: requirements-parser==0.11.0
|
|
229
|
-
Requires-Dist: rich==13.8.
|
|
230
|
-
Requires-Dist: setuptools==
|
|
231
|
-
Requires-Dist: snowflake-connector-python[secure-local-storage]==3.12.
|
|
232
|
-
Requires-Dist: snowflake-core==0.
|
|
229
|
+
Requires-Dist: rich==13.8.1
|
|
230
|
+
Requires-Dist: setuptools==75.1.0
|
|
231
|
+
Requires-Dist: snowflake-connector-python[secure-local-storage]==3.12.2
|
|
232
|
+
Requires-Dist: snowflake-core==0.12.1; python_version < '3.12'
|
|
233
233
|
Requires-Dist: snowflake-snowpark-python>=1.15.0; python_version < '3.12'
|
|
234
234
|
Requires-Dist: tomlkit==0.13.2
|
|
235
235
|
Requires-Dist: typer==0.12.5
|
|
@@ -238,8 +238,10 @@ Provides-Extra: development
|
|
|
238
238
|
Requires-Dist: coverage==7.6.1; extra == 'development'
|
|
239
239
|
Requires-Dist: pre-commit>=3.5.0; extra == 'development'
|
|
240
240
|
Requires-Dist: pytest-randomly==3.15.0; extra == 'development'
|
|
241
|
-
Requires-Dist: pytest==8.3.
|
|
241
|
+
Requires-Dist: pytest==8.3.3; extra == 'development'
|
|
242
242
|
Requires-Dist: syrupy==4.7.1; extra == 'development'
|
|
243
|
+
Provides-Extra: packaging
|
|
244
|
+
Requires-Dist: pyinstaller~=6.10; extra == 'packaging'
|
|
243
245
|
Description-Content-Type: text/markdown
|
|
244
246
|
|
|
245
247
|
<!--
|