snowflake-cli-labs 2.6.1__py3-none-any.whl → 2.7.0rc0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- snowflake/cli/__about__.py +1 -1
- snowflake/cli/api/cli_global_context.py +9 -0
- snowflake/cli/api/commands/decorators.py +9 -4
- snowflake/cli/api/commands/execution_metadata.py +40 -0
- snowflake/cli/api/commands/flags.py +45 -36
- snowflake/cli/api/commands/project_initialisation.py +4 -1
- snowflake/cli/api/commands/snow_typer.py +20 -9
- snowflake/cli/api/errno.py +27 -0
- snowflake/cli/api/feature_flags.py +1 -0
- snowflake/cli/api/identifiers.py +20 -3
- snowflake/cli/api/output/types.py +9 -0
- snowflake/cli/api/project/definition_manager.py +2 -2
- snowflake/cli/api/project/project_verification.py +23 -0
- snowflake/cli/api/project/schemas/entities/application_entity.py +50 -0
- snowflake/cli/api/project/schemas/entities/application_package_entity.py +63 -0
- snowflake/cli/api/project/schemas/entities/common.py +85 -0
- snowflake/cli/api/project/schemas/entities/entities.py +30 -0
- snowflake/cli/api/project/schemas/project_definition.py +114 -22
- snowflake/cli/api/project/schemas/streamlit/streamlit.py +5 -4
- snowflake/cli/api/project/schemas/template.py +77 -0
- snowflake/cli/{plugins/nativeapp/errno.py → api/rendering/__init__.py} +0 -2
- snowflake/cli/api/{utils/rendering.py → rendering/jinja.py} +3 -48
- snowflake/cli/api/rendering/project_definition_templates.py +39 -0
- snowflake/cli/api/rendering/project_templates.py +97 -0
- snowflake/cli/api/rendering/sql_templates.py +56 -0
- snowflake/cli/api/sql_execution.py +40 -1
- snowflake/cli/api/utils/definition_rendering.py +8 -5
- snowflake/cli/app/commands_registration/builtin_plugins.py +4 -0
- snowflake/cli/app/dev/docs/project_definition_docs_generator.py +2 -2
- snowflake/cli/app/loggers.py +3 -1
- snowflake/cli/app/printing.py +17 -7
- snowflake/cli/app/snow_connector.py +9 -1
- snowflake/cli/app/telemetry.py +41 -2
- snowflake/cli/plugins/connection/commands.py +4 -3
- snowflake/cli/plugins/connection/util.py +73 -18
- snowflake/cli/plugins/cortex/commands.py +2 -1
- snowflake/cli/plugins/git/commands.py +20 -4
- snowflake/cli/plugins/git/manager.py +44 -20
- snowflake/cli/plugins/init/__init__.py +13 -0
- snowflake/cli/plugins/init/commands.py +242 -0
- snowflake/cli/plugins/init/plugin_spec.py +30 -0
- snowflake/cli/plugins/nativeapp/codegen/artifact_processor.py +40 -0
- snowflake/cli/plugins/nativeapp/codegen/compiler.py +57 -27
- snowflake/cli/plugins/nativeapp/codegen/sandbox.py +99 -10
- snowflake/cli/plugins/nativeapp/codegen/setup/native_app_setup_processor.py +172 -0
- snowflake/cli/plugins/nativeapp/codegen/setup/setup_driver.py.source +56 -0
- snowflake/cli/plugins/nativeapp/codegen/snowpark/python_processor.py +21 -21
- snowflake/cli/plugins/nativeapp/commands.py +69 -6
- snowflake/cli/plugins/nativeapp/constants.py +0 -6
- snowflake/cli/plugins/nativeapp/exceptions.py +37 -12
- snowflake/cli/plugins/nativeapp/init.py +1 -1
- snowflake/cli/plugins/nativeapp/manager.py +114 -39
- snowflake/cli/plugins/nativeapp/project_model.py +8 -4
- snowflake/cli/plugins/nativeapp/run_processor.py +117 -102
- snowflake/cli/plugins/nativeapp/teardown_processor.py +7 -2
- snowflake/cli/plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +146 -0
- snowflake/cli/plugins/nativeapp/version/commands.py +19 -3
- snowflake/cli/plugins/nativeapp/version/version_processor.py +11 -3
- snowflake/cli/plugins/snowpark/commands.py +34 -26
- snowflake/cli/plugins/snowpark/common.py +88 -27
- snowflake/cli/plugins/snowpark/manager.py +16 -5
- snowflake/cli/plugins/snowpark/models.py +6 -0
- snowflake/cli/plugins/sql/commands.py +3 -5
- snowflake/cli/plugins/sql/manager.py +1 -1
- snowflake/cli/plugins/stage/commands.py +2 -2
- snowflake/cli/plugins/stage/diff.py +4 -2
- snowflake/cli/plugins/stage/manager.py +290 -86
- snowflake/cli/plugins/streamlit/commands.py +20 -6
- snowflake/cli/plugins/streamlit/manager.py +29 -27
- snowflake/cli/plugins/workspace/__init__.py +13 -0
- snowflake/cli/plugins/workspace/commands.py +35 -0
- snowflake/cli/plugins/workspace/plugin_spec.py +30 -0
- snowflake/cli/templates/default_snowpark/app/__init__.py +0 -13
- snowflake/cli/templates/default_snowpark/app/common.py +0 -15
- snowflake/cli/templates/default_snowpark/app/functions.py +0 -14
- snowflake/cli/templates/default_snowpark/app/procedures.py +0 -14
- snowflake/cli/templates/default_streamlit/common/hello.py +0 -15
- snowflake/cli/templates/default_streamlit/pages/my_page.py +0 -14
- snowflake/cli/templates/default_streamlit/streamlit_app.py +0 -14
- {snowflake_cli_labs-2.6.1.dist-info → snowflake_cli_labs-2.7.0rc0.dist-info}/METADATA +7 -6
- {snowflake_cli_labs-2.6.1.dist-info → snowflake_cli_labs-2.7.0rc0.dist-info}/RECORD +84 -64
- {snowflake_cli_labs-2.6.1.dist-info → snowflake_cli_labs-2.7.0rc0.dist-info}/WHEEL +0 -0
- {snowflake_cli_labs-2.6.1.dist-info → snowflake_cli_labs-2.7.0rc0.dist-info}/entry_points.txt +0 -0
- {snowflake_cli_labs-2.6.1.dist-info → snowflake_cli_labs-2.7.0rc0.dist-info}/licenses/LICENSE +0 -0
|
@@ -38,9 +38,7 @@ from snowflake.cli.api.constants import (
|
|
|
38
38
|
DEPLOYMENT_STAGE,
|
|
39
39
|
ObjectType,
|
|
40
40
|
)
|
|
41
|
-
from snowflake.cli.api.exceptions import
|
|
42
|
-
SecretsWithoutExternalAccessIntegrationError,
|
|
43
|
-
)
|
|
41
|
+
from snowflake.cli.api.exceptions import SecretsWithoutExternalAccessIntegrationError
|
|
44
42
|
from snowflake.cli.api.identifiers import FQN
|
|
45
43
|
from snowflake.cli.api.output.types import (
|
|
46
44
|
CollectionResult,
|
|
@@ -48,6 +46,7 @@ from snowflake.cli.api.output.types import (
|
|
|
48
46
|
MessageResult,
|
|
49
47
|
SingleQueryResult,
|
|
50
48
|
)
|
|
49
|
+
from snowflake.cli.api.project.project_verification import assert_project_type
|
|
51
50
|
from snowflake.cli.api.project.schemas.snowpark.callable import (
|
|
52
51
|
FunctionSchema,
|
|
53
52
|
ProcedureSchema,
|
|
@@ -68,7 +67,8 @@ from snowflake.cli.plugins.object.commands import (
|
|
|
68
67
|
from snowflake.cli.plugins.object.manager import ObjectManager
|
|
69
68
|
from snowflake.cli.plugins.snowpark import package_utils
|
|
70
69
|
from snowflake.cli.plugins.snowpark.common import (
|
|
71
|
-
|
|
70
|
+
FunctionOrProcedure,
|
|
71
|
+
UdfSprocIdentifier,
|
|
72
72
|
check_if_replace_is_required,
|
|
73
73
|
)
|
|
74
74
|
from snowflake.cli.plugins.snowpark.manager import FunctionManager, ProcedureManager
|
|
@@ -116,7 +116,7 @@ add_init_command(app, project_type="Snowpark", template="default_snowpark")
|
|
|
116
116
|
|
|
117
117
|
|
|
118
118
|
@app.command("deploy", requires_connection=True)
|
|
119
|
-
@with_project_definition(
|
|
119
|
+
@with_project_definition()
|
|
120
120
|
def deploy(
|
|
121
121
|
replace: bool = ReplaceOption(
|
|
122
122
|
help="Replaces procedure or function, even if no detected changes to metadata"
|
|
@@ -128,6 +128,9 @@ def deploy(
|
|
|
128
128
|
By default, if any of the objects exist already the commands will fail unless `--replace` flag is provided.
|
|
129
129
|
All deployed objects use the same artifact which is deployed only once.
|
|
130
130
|
"""
|
|
131
|
+
|
|
132
|
+
assert_project_type("snowpark")
|
|
133
|
+
|
|
131
134
|
snowpark = cli_context.project_definition.snowpark
|
|
132
135
|
paths = SnowparkPackagePaths.for_snowpark_project(
|
|
133
136
|
project_root=SecurePath(cli_context.project_root),
|
|
@@ -218,7 +221,7 @@ def deploy(
|
|
|
218
221
|
|
|
219
222
|
|
|
220
223
|
def _assert_object_definitions_are_correct(
|
|
221
|
-
object_type, object_definitions: List[
|
|
224
|
+
object_type, object_definitions: List[FunctionOrProcedure]
|
|
222
225
|
):
|
|
223
226
|
for definition in object_definitions:
|
|
224
227
|
database = definition.database
|
|
@@ -237,14 +240,14 @@ def _assert_object_definitions_are_correct(
|
|
|
237
240
|
|
|
238
241
|
def _find_existing_objects(
|
|
239
242
|
object_type: ObjectType,
|
|
240
|
-
objects: List[
|
|
243
|
+
objects: List[FunctionOrProcedure],
|
|
241
244
|
om: ObjectManager,
|
|
242
245
|
):
|
|
243
246
|
existing_objects = {}
|
|
244
247
|
for object_definition in objects:
|
|
245
|
-
identifier =
|
|
246
|
-
object_definition
|
|
247
|
-
)
|
|
248
|
+
identifier = UdfSprocIdentifier.from_definition(
|
|
249
|
+
object_definition
|
|
250
|
+
).identifier_with_arg_types
|
|
248
251
|
try:
|
|
249
252
|
current_state = om.describe(
|
|
250
253
|
object_type=object_type.value.sf_name,
|
|
@@ -293,50 +296,52 @@ def get_app_stage_path(stage_name: Optional[str], project_name: str) -> str:
|
|
|
293
296
|
def _deploy_single_object(
|
|
294
297
|
manager: FunctionManager | ProcedureManager,
|
|
295
298
|
object_type: ObjectType,
|
|
296
|
-
object_definition:
|
|
299
|
+
object_definition: FunctionOrProcedure,
|
|
297
300
|
existing_objects: Dict[str, Dict],
|
|
298
301
|
snowflake_dependencies: List[str],
|
|
299
302
|
stage_artifact_path: str,
|
|
300
303
|
):
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
manager,
|
|
307
|
-
include_parameter_names=True,
|
|
308
|
-
include_default_values=True,
|
|
304
|
+
|
|
305
|
+
identifiers = UdfSprocIdentifier.from_definition(object_definition)
|
|
306
|
+
|
|
307
|
+
log.info(
|
|
308
|
+
"Deploying %s: %s", object_type, identifiers.identifier_with_arg_names_types
|
|
309
309
|
)
|
|
310
|
-
log.info("Deploying %s: %s", object_type, identifier_with_default_values)
|
|
311
310
|
|
|
312
311
|
handler = object_definition.handler
|
|
313
312
|
returns = object_definition.returns
|
|
314
313
|
imports = object_definition.imports
|
|
315
314
|
external_access_integrations = object_definition.external_access_integrations
|
|
315
|
+
runtime_ver = object_definition.runtime
|
|
316
|
+
execute_as_caller = None
|
|
317
|
+
if object_type == ObjectType.PROCEDURE:
|
|
318
|
+
execute_as_caller = object_definition.execute_as_caller
|
|
316
319
|
replace_object = False
|
|
317
320
|
|
|
318
|
-
object_exists =
|
|
321
|
+
object_exists = identifiers.identifier_with_arg_types in existing_objects
|
|
319
322
|
if object_exists:
|
|
320
323
|
replace_object = check_if_replace_is_required(
|
|
321
324
|
object_type=object_type,
|
|
322
|
-
current_state=existing_objects[
|
|
325
|
+
current_state=existing_objects[identifiers.identifier_with_arg_types],
|
|
323
326
|
handler=handler,
|
|
324
327
|
return_type=returns,
|
|
325
328
|
snowflake_dependencies=snowflake_dependencies,
|
|
326
329
|
external_access_integrations=external_access_integrations,
|
|
327
330
|
imports=imports,
|
|
328
331
|
stage_artifact_file=stage_artifact_path,
|
|
332
|
+
runtime_ver=runtime_ver,
|
|
333
|
+
execute_as_caller=execute_as_caller,
|
|
329
334
|
)
|
|
330
335
|
|
|
331
336
|
if object_exists and not replace_object:
|
|
332
337
|
return {
|
|
333
|
-
"object":
|
|
338
|
+
"object": identifiers.identifier_with_arg_names_types_defaults,
|
|
334
339
|
"type": str(object_type),
|
|
335
340
|
"status": "packages updated",
|
|
336
341
|
}
|
|
337
342
|
|
|
338
343
|
create_or_replace_kwargs = {
|
|
339
|
-
"identifier":
|
|
344
|
+
"identifier": identifiers,
|
|
340
345
|
"handler": handler,
|
|
341
346
|
"return_type": returns,
|
|
342
347
|
"artifact_file": stage_artifact_path,
|
|
@@ -354,7 +359,7 @@ def _deploy_single_object(
|
|
|
354
359
|
|
|
355
360
|
status = "created" if not object_exists else "definition updated"
|
|
356
361
|
return {
|
|
357
|
-
"object":
|
|
362
|
+
"object": identifiers.identifier_with_arg_names_types_defaults,
|
|
358
363
|
"type": str(object_type),
|
|
359
364
|
"status": status,
|
|
360
365
|
}
|
|
@@ -379,7 +384,7 @@ def _read_snowflake_requrements_file(file_path: SecurePath):
|
|
|
379
384
|
|
|
380
385
|
|
|
381
386
|
@app.command("build", requires_connection=True)
|
|
382
|
-
@with_project_definition(
|
|
387
|
+
@with_project_definition()
|
|
383
388
|
def build(
|
|
384
389
|
ignore_anaconda: bool = IgnoreAnacondaOption,
|
|
385
390
|
allow_shared_libraries: bool = AllowSharedLibrariesOption,
|
|
@@ -396,6 +401,9 @@ def build(
|
|
|
396
401
|
Builds the Snowpark project as a `.zip` archive that can be used by `deploy` command.
|
|
397
402
|
The archive is built using only the `src` directory specified in the project file.
|
|
398
403
|
"""
|
|
404
|
+
|
|
405
|
+
assert_project_type("snowpark")
|
|
406
|
+
|
|
399
407
|
if not deprecated_check_anaconda_for_pypi_deps:
|
|
400
408
|
ignore_anaconda = True
|
|
401
409
|
snowpark_paths = SnowparkPackagePaths.for_snowpark_project(
|
|
@@ -15,11 +15,14 @@
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
17
|
import re
|
|
18
|
-
from typing import Dict, List, Optional, Set
|
|
18
|
+
from typing import Dict, List, Optional, Set, Union
|
|
19
19
|
|
|
20
20
|
from snowflake.cli.api.constants import ObjectType
|
|
21
21
|
from snowflake.cli.api.identifiers import FQN
|
|
22
|
-
from snowflake.cli.api.project.schemas.snowpark.
|
|
22
|
+
from snowflake.cli.api.project.schemas.snowpark.callable import (
|
|
23
|
+
FunctionSchema,
|
|
24
|
+
ProcedureSchema,
|
|
25
|
+
)
|
|
23
26
|
from snowflake.cli.api.sql_execution import SqlExecutionMixin
|
|
24
27
|
from snowflake.cli.plugins.snowpark.models import Requirement
|
|
25
28
|
from snowflake.cli.plugins.snowpark.package_utils import (
|
|
@@ -28,6 +31,7 @@ from snowflake.cli.plugins.snowpark.package_utils import (
|
|
|
28
31
|
from snowflake.connector.cursor import SnowflakeCursor
|
|
29
32
|
|
|
30
33
|
DEFAULT_RUNTIME = "3.8"
|
|
34
|
+
FunctionOrProcedure = Union[FunctionSchema, ProcedureSchema]
|
|
31
35
|
|
|
32
36
|
|
|
33
37
|
def check_if_replace_is_required(
|
|
@@ -39,6 +43,8 @@ def check_if_replace_is_required(
|
|
|
39
43
|
external_access_integrations: List[str],
|
|
40
44
|
imports: List[str],
|
|
41
45
|
stage_artifact_file: str,
|
|
46
|
+
runtime_ver: Optional[str] = None,
|
|
47
|
+
execute_as_caller: Optional[bool] = None,
|
|
42
48
|
) -> bool:
|
|
43
49
|
import logging
|
|
44
50
|
|
|
@@ -78,6 +84,22 @@ def check_if_replace_is_required(
|
|
|
78
84
|
return True
|
|
79
85
|
|
|
80
86
|
if _compare_imports(resource_json, imports, stage_artifact_file):
|
|
87
|
+
log.info("Imports do not match. Replacing the %s", object_type)
|
|
88
|
+
return True
|
|
89
|
+
|
|
90
|
+
if runtime_ver is not None and runtime_ver != resource_json.get(
|
|
91
|
+
"runtime_version", "RUNTIME_NOT_SET"
|
|
92
|
+
):
|
|
93
|
+
log.info("Runtime versions do not match. Replacing the %s", object_type)
|
|
94
|
+
return True
|
|
95
|
+
|
|
96
|
+
if execute_as_caller is not None and (
|
|
97
|
+
resource_json.get("execute as", "OWNER")
|
|
98
|
+
!= ("CALLER" if execute_as_caller else "OWNER")
|
|
99
|
+
):
|
|
100
|
+
log.info(
|
|
101
|
+
"Execute as caller settings do not match. Replacing the %s", object_type
|
|
102
|
+
)
|
|
81
103
|
return True
|
|
82
104
|
|
|
83
105
|
return False
|
|
@@ -150,7 +172,7 @@ class SnowparkObjectManager(SqlExecutionMixin):
|
|
|
150
172
|
|
|
151
173
|
def create_query(
|
|
152
174
|
self,
|
|
153
|
-
identifier:
|
|
175
|
+
identifier: UdfSprocIdentifier,
|
|
154
176
|
return_type: str,
|
|
155
177
|
handler: str,
|
|
156
178
|
artifact_file: str,
|
|
@@ -166,7 +188,7 @@ class SnowparkObjectManager(SqlExecutionMixin):
|
|
|
166
188
|
packages_list = ",".join(f"'{p}'" for p in packages)
|
|
167
189
|
|
|
168
190
|
query = [
|
|
169
|
-
f"create or replace {self._object_type.value.sf_name} {identifier}",
|
|
191
|
+
f"create or replace {self._object_type.value.sf_name} {identifier.identifier_for_sql}",
|
|
170
192
|
f"copy grants",
|
|
171
193
|
f"returns {return_type}",
|
|
172
194
|
"language python",
|
|
@@ -198,30 +220,69 @@ def _is_signature_type_a_string(sig_type: str) -> bool:
|
|
|
198
220
|
return sig_type.lower() in ["string", "varchar"]
|
|
199
221
|
|
|
200
222
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
val = f"{arg.default}"
|
|
213
|
-
if _is_signature_type_a_string(arg.arg_type):
|
|
214
|
-
val = f"'{val}'"
|
|
215
|
-
result += f" default {val}"
|
|
216
|
-
return result
|
|
217
|
-
|
|
218
|
-
if udf_sproc.signature and udf_sproc.signature != "null":
|
|
219
|
-
arguments = ", ".join(format_arg(arg) for arg in udf_sproc.signature)
|
|
220
|
-
else:
|
|
221
|
-
arguments = ""
|
|
223
|
+
class UdfSprocIdentifier:
|
|
224
|
+
def __init__(self, identifier: FQN, arg_names, arg_types, arg_defaults):
|
|
225
|
+
self._identifier = identifier
|
|
226
|
+
self._arg_names = arg_names
|
|
227
|
+
self._arg_types = arg_types
|
|
228
|
+
self._arg_defaults = arg_defaults
|
|
229
|
+
|
|
230
|
+
def _identifier_from_signature(self, sig: List[str], for_sql: bool = False):
|
|
231
|
+
signature = self._comma_join(sig)
|
|
232
|
+
id_ = self._identifier.sql_identifier if for_sql else self._identifier
|
|
233
|
+
return f"{id_}({signature})"
|
|
222
234
|
|
|
223
|
-
|
|
224
|
-
|
|
235
|
+
@staticmethod
|
|
236
|
+
def _comma_join(*args):
|
|
237
|
+
return ", ".join(*args)
|
|
238
|
+
|
|
239
|
+
@property
|
|
240
|
+
def identifier_with_arg_names(self):
|
|
241
|
+
return self._identifier_from_signature(self._arg_names)
|
|
242
|
+
|
|
243
|
+
@property
|
|
244
|
+
def identifier_with_arg_types(self):
|
|
245
|
+
return self._identifier_from_signature(self._arg_types)
|
|
246
|
+
|
|
247
|
+
@property
|
|
248
|
+
def identifier_with_arg_names_types(self):
|
|
249
|
+
sig = [f"{n} {t}" for n, t in zip(self._arg_names, self._arg_types)]
|
|
250
|
+
return self._identifier_from_signature(sig)
|
|
251
|
+
|
|
252
|
+
@property
|
|
253
|
+
def identifier_with_arg_names_types_defaults(self):
|
|
254
|
+
return self._identifier_from_signature(self._full_signature())
|
|
255
|
+
|
|
256
|
+
def _full_signature(self):
|
|
257
|
+
sig = []
|
|
258
|
+
for name, _type, _default in zip(
|
|
259
|
+
self._arg_names, self._arg_types, self._arg_defaults
|
|
260
|
+
):
|
|
261
|
+
s = f"{name} {_type}"
|
|
262
|
+
if _default:
|
|
263
|
+
if _is_signature_type_a_string(_type):
|
|
264
|
+
_default = f"'{_default}'"
|
|
265
|
+
s += f" default {_default}"
|
|
266
|
+
sig.append(s)
|
|
267
|
+
return sig
|
|
268
|
+
|
|
269
|
+
@property
|
|
270
|
+
def identifier_for_sql(self):
|
|
271
|
+
return self._identifier_from_signature(self._full_signature(), for_sql=True)
|
|
272
|
+
|
|
273
|
+
@classmethod
|
|
274
|
+
def from_definition(cls, udf_sproc: FunctionOrProcedure):
|
|
275
|
+
names = []
|
|
276
|
+
types = []
|
|
277
|
+
defaults = []
|
|
278
|
+
if udf_sproc.signature and udf_sproc.signature != "null":
|
|
279
|
+
for arg in udf_sproc.signature:
|
|
280
|
+
names.append(arg.name)
|
|
281
|
+
types.append(arg.arg_type)
|
|
282
|
+
defaults.append(arg.default)
|
|
283
|
+
|
|
284
|
+
identifier = FQN.from_identifier_model(udf_sproc).using_context()
|
|
285
|
+
return cls(identifier, names, types, defaults)
|
|
225
286
|
|
|
226
287
|
|
|
227
288
|
def _compare_imports(
|
|
@@ -18,7 +18,10 @@ import logging
|
|
|
18
18
|
from typing import Dict, List, Optional
|
|
19
19
|
|
|
20
20
|
from snowflake.cli.api.constants import ObjectType
|
|
21
|
-
from snowflake.cli.plugins.snowpark.common import
|
|
21
|
+
from snowflake.cli.plugins.snowpark.common import (
|
|
22
|
+
SnowparkObjectManager,
|
|
23
|
+
UdfSprocIdentifier,
|
|
24
|
+
)
|
|
22
25
|
from snowflake.connector.cursor import SnowflakeCursor
|
|
23
26
|
|
|
24
27
|
log = logging.getLogger(__name__)
|
|
@@ -35,7 +38,7 @@ class FunctionManager(SnowparkObjectManager):
|
|
|
35
38
|
|
|
36
39
|
def create_or_replace(
|
|
37
40
|
self,
|
|
38
|
-
identifier:
|
|
41
|
+
identifier: UdfSprocIdentifier,
|
|
39
42
|
return_type: str,
|
|
40
43
|
handler: str,
|
|
41
44
|
artifact_file: str,
|
|
@@ -45,7 +48,11 @@ class FunctionManager(SnowparkObjectManager):
|
|
|
45
48
|
secrets: Optional[Dict[str, str]] = None,
|
|
46
49
|
runtime: Optional[str] = None,
|
|
47
50
|
) -> SnowflakeCursor:
|
|
48
|
-
log.debug(
|
|
51
|
+
log.debug(
|
|
52
|
+
"Creating function %s using @%s",
|
|
53
|
+
identifier.identifier_with_arg_names_types_defaults,
|
|
54
|
+
artifact_file,
|
|
55
|
+
)
|
|
49
56
|
query = self.create_query(
|
|
50
57
|
identifier,
|
|
51
58
|
return_type,
|
|
@@ -71,7 +78,7 @@ class ProcedureManager(SnowparkObjectManager):
|
|
|
71
78
|
|
|
72
79
|
def create_or_replace(
|
|
73
80
|
self,
|
|
74
|
-
identifier:
|
|
81
|
+
identifier: UdfSprocIdentifier,
|
|
75
82
|
return_type: str,
|
|
76
83
|
handler: str,
|
|
77
84
|
artifact_file: str,
|
|
@@ -82,7 +89,11 @@ class ProcedureManager(SnowparkObjectManager):
|
|
|
82
89
|
runtime: Optional[str] = None,
|
|
83
90
|
execute_as_caller: bool = False,
|
|
84
91
|
) -> SnowflakeCursor:
|
|
85
|
-
log.debug(
|
|
92
|
+
log.debug(
|
|
93
|
+
"Creating procedure %s using @%s",
|
|
94
|
+
identifier.identifier_with_arg_names_types_defaults,
|
|
95
|
+
artifact_file,
|
|
96
|
+
)
|
|
86
97
|
query = self.create_query(
|
|
87
98
|
identifier,
|
|
88
99
|
return_type,
|
|
@@ -33,6 +33,10 @@ class YesNoAsk(Enum):
|
|
|
33
33
|
class Requirement(requirement.Requirement):
|
|
34
34
|
extra_pattern = re.compile("'([^']*)'")
|
|
35
35
|
|
|
36
|
+
def __init__(self, *args, **kwargs):
|
|
37
|
+
super().__init__(*args, **kwargs)
|
|
38
|
+
self.package_name = None
|
|
39
|
+
|
|
36
40
|
@classmethod
|
|
37
41
|
def parse_line(cls, line: str) -> Requirement:
|
|
38
42
|
if len(line_elements := line.split(";")) > 1:
|
|
@@ -44,6 +48,8 @@ class Requirement(requirement.Requirement):
|
|
|
44
48
|
if "extra" in element and (extras := cls.extra_pattern.search(element)):
|
|
45
49
|
result.extras.extend(extras.groups())
|
|
46
50
|
|
|
51
|
+
result.package_name = result.name
|
|
52
|
+
|
|
47
53
|
if result.uri and not result.name:
|
|
48
54
|
result.name = get_package_name(result.uri)
|
|
49
55
|
result.name = cls.standardize_name(result.name)
|
|
@@ -21,6 +21,7 @@ import typer
|
|
|
21
21
|
from snowflake.cli.api.commands.decorators import with_project_definition
|
|
22
22
|
from snowflake.cli.api.commands.flags import (
|
|
23
23
|
parse_key_value_variables,
|
|
24
|
+
variables_option,
|
|
24
25
|
)
|
|
25
26
|
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
26
27
|
from snowflake.cli.api.output.types import CommandResult, MultipleResults, QueryResult
|
|
@@ -55,11 +56,8 @@ def execute_sql(
|
|
|
55
56
|
"-i",
|
|
56
57
|
help="Read the query from standard input. Use it when piping input to this command.",
|
|
57
58
|
),
|
|
58
|
-
data_override: List[str] =
|
|
59
|
-
|
|
60
|
-
"--variable",
|
|
61
|
-
"-D",
|
|
62
|
-
help="String in format of key=value. If provided the SQL content will "
|
|
59
|
+
data_override: List[str] = variables_option(
|
|
60
|
+
"String in format of key=value. If provided the SQL content will "
|
|
63
61
|
"be treated as template and rendered using provided data.",
|
|
64
62
|
),
|
|
65
63
|
**options,
|
|
@@ -22,9 +22,9 @@ from typing import Dict, Iterable, List, Tuple
|
|
|
22
22
|
|
|
23
23
|
from click import ClickException, UsageError
|
|
24
24
|
from jinja2 import UndefinedError
|
|
25
|
+
from snowflake.cli.api.rendering.sql_templates import snowflake_sql_jinja_render
|
|
25
26
|
from snowflake.cli.api.secure_path import UNLIMITED, SecurePath
|
|
26
27
|
from snowflake.cli.api.sql_execution import SqlExecutionMixin, VerboseCursor
|
|
27
|
-
from snowflake.cli.api.utils.rendering import snowflake_sql_jinja_render
|
|
28
28
|
from snowflake.cli.plugins.sql.snowsql_templating import transpile_snowsql_templates
|
|
29
29
|
from snowflake.connector.cursor import SnowflakeCursor
|
|
30
30
|
from snowflake.connector.util_text import split_statements
|
|
@@ -23,9 +23,9 @@ import click
|
|
|
23
23
|
import typer
|
|
24
24
|
from snowflake.cli.api.cli_global_context import cli_context
|
|
25
25
|
from snowflake.cli.api.commands.flags import (
|
|
26
|
+
ExecuteVariablesOption,
|
|
26
27
|
OnErrorOption,
|
|
27
28
|
PatternOption,
|
|
28
|
-
VariablesOption,
|
|
29
29
|
like_option,
|
|
30
30
|
)
|
|
31
31
|
from snowflake.cli.api.commands.snow_typer import SnowTyperFactory
|
|
@@ -201,7 +201,7 @@ def execute(
|
|
|
201
201
|
show_default=False,
|
|
202
202
|
),
|
|
203
203
|
on_error: OnErrorType = OnErrorOption,
|
|
204
|
-
variables: Optional[List[str]] =
|
|
204
|
+
variables: Optional[List[str]] = ExecuteVariablesOption,
|
|
205
205
|
**options,
|
|
206
206
|
):
|
|
207
207
|
"""
|
|
@@ -72,10 +72,12 @@ class DiffResult:
|
|
|
72
72
|
}
|
|
73
73
|
|
|
74
74
|
|
|
75
|
-
def is_valid_md5sum(checksum: str) -> bool:
|
|
75
|
+
def is_valid_md5sum(checksum: Optional[str]) -> bool:
|
|
76
76
|
"""
|
|
77
77
|
Could the provided hexadecimal checksum represent a valid md5sum?
|
|
78
78
|
"""
|
|
79
|
+
if checksum is None:
|
|
80
|
+
return False
|
|
79
81
|
return re.match(MD5SUM_REGEX, checksum) is not None
|
|
80
82
|
|
|
81
83
|
|
|
@@ -131,7 +133,7 @@ def strip_stage_name(path: str) -> StagePath:
|
|
|
131
133
|
return StagePath(*path.split("/")[1:])
|
|
132
134
|
|
|
133
135
|
|
|
134
|
-
def build_md5_map(list_stage_cursor: DictCursor) -> Dict[StagePath, str]:
|
|
136
|
+
def build_md5_map(list_stage_cursor: DictCursor) -> Dict[StagePath, Optional[str]]:
|
|
135
137
|
"""
|
|
136
138
|
Returns a mapping of relative stage paths to their md5sums.
|
|
137
139
|
"""
|