snowflake-cli-labs 3.0.0rc0__py3-none-any.whl → 3.0.0rc2__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/cli_app.py +10 -1
- snowflake/cli/_app/snow_connector.py +91 -37
- snowflake/cli/_app/telemetry.py +8 -4
- snowflake/cli/_app/version_check.py +74 -0
- snowflake/cli/_plugins/connection/commands.py +3 -2
- snowflake/cli/_plugins/git/commands.py +55 -14
- snowflake/cli/_plugins/git/manager.py +14 -6
- snowflake/cli/_plugins/nativeapp/codegen/compiler.py +18 -2
- snowflake/cli/_plugins/nativeapp/codegen/setup/native_app_setup_processor.py +123 -42
- snowflake/cli/_plugins/nativeapp/codegen/setup/setup_driver.py.source +5 -2
- snowflake/cli/_plugins/nativeapp/codegen/snowpark/python_processor.py +6 -11
- snowflake/cli/_plugins/nativeapp/codegen/templates/templates_processor.py +111 -0
- snowflake/cli/_plugins/nativeapp/exceptions.py +3 -3
- snowflake/cli/_plugins/nativeapp/manager.py +74 -144
- snowflake/cli/_plugins/nativeapp/project_model.py +2 -9
- snowflake/cli/_plugins/nativeapp/run_processor.py +56 -260
- snowflake/cli/_plugins/nativeapp/same_account_install_method.py +74 -0
- snowflake/cli/_plugins/nativeapp/teardown_processor.py +17 -246
- snowflake/cli/_plugins/nativeapp/v2_conversions/v2_to_v1_decorator.py +91 -17
- snowflake/cli/_plugins/snowpark/commands.py +5 -65
- snowflake/cli/_plugins/snowpark/common.py +17 -1
- snowflake/cli/_plugins/snowpark/models.py +2 -1
- snowflake/cli/_plugins/snowpark/package/anaconda_packages.py +1 -35
- snowflake/cli/_plugins/sql/commands.py +1 -2
- snowflake/cli/_plugins/stage/commands.py +2 -2
- snowflake/cli/_plugins/stage/manager.py +46 -15
- snowflake/cli/_plugins/streamlit/commands.py +4 -63
- snowflake/cli/_plugins/streamlit/manager.py +13 -0
- snowflake/cli/_plugins/workspace/action_context.py +7 -0
- snowflake/cli/_plugins/workspace/commands.py +145 -32
- snowflake/cli/_plugins/workspace/manager.py +21 -4
- snowflake/cli/api/cli_global_context.py +136 -313
- snowflake/cli/api/commands/decorators.py +1 -1
- snowflake/cli/api/commands/flags.py +106 -102
- snowflake/cli/api/commands/snow_typer.py +15 -6
- snowflake/cli/api/config.py +18 -5
- snowflake/cli/api/connections.py +214 -0
- snowflake/cli/api/console/abc.py +4 -2
- snowflake/cli/api/constants.py +11 -0
- snowflake/cli/api/entities/application_entity.py +687 -2
- snowflake/cli/api/entities/application_package_entity.py +407 -9
- snowflake/cli/api/entities/common.py +7 -2
- snowflake/cli/api/entities/utils.py +80 -20
- snowflake/cli/api/exceptions.py +12 -2
- snowflake/cli/api/feature_flags.py +0 -2
- snowflake/cli/api/identifiers.py +3 -0
- snowflake/cli/api/project/definition.py +35 -1
- snowflake/cli/api/project/definition_conversion.py +352 -0
- snowflake/cli/api/project/schemas/entities/application_package_entity_model.py +17 -0
- snowflake/cli/api/project/schemas/entities/common.py +0 -12
- snowflake/cli/api/project/schemas/identifier_model.py +2 -2
- snowflake/cli/api/project/schemas/project_definition.py +102 -43
- snowflake/cli/api/rendering/jinja.py +2 -16
- snowflake/cli/api/rendering/project_definition_templates.py +5 -1
- snowflake/cli/api/rendering/sql_templates.py +14 -4
- snowflake/cli/api/secure_path.py +13 -18
- snowflake/cli/api/secure_utils.py +90 -1
- snowflake/cli/api/sql_execution.py +13 -0
- snowflake/cli/api/utils/definition_rendering.py +7 -7
- {snowflake_cli_labs-3.0.0rc0.dist-info → snowflake_cli_labs-3.0.0rc2.dist-info}/METADATA +9 -9
- {snowflake_cli_labs-3.0.0rc0.dist-info → snowflake_cli_labs-3.0.0rc2.dist-info}/RECORD +65 -61
- snowflake/cli/api/commands/typer_pre_execute.py +0 -26
- {snowflake_cli_labs-3.0.0rc0.dist-info → snowflake_cli_labs-3.0.0rc2.dist-info}/WHEEL +0 -0
- {snowflake_cli_labs-3.0.0rc0.dist-info → snowflake_cli_labs-3.0.0rc2.dist-info}/entry_points.txt +0 -0
- {snowflake_cli_labs-3.0.0rc0.dist-info → snowflake_cli_labs-3.0.0rc2.dist-info}/licenses/LICENSE +0 -0
|
@@ -14,32 +14,20 @@
|
|
|
14
14
|
|
|
15
15
|
from __future__ import annotations
|
|
16
16
|
|
|
17
|
-
import json
|
|
18
17
|
import time
|
|
19
18
|
from abc import ABC, abstractmethod
|
|
20
|
-
from contextlib import contextmanager
|
|
21
19
|
from datetime import datetime
|
|
22
20
|
from functools import cached_property
|
|
23
21
|
from pathlib import Path
|
|
24
22
|
from textwrap import dedent
|
|
25
|
-
from typing import Generator, List, Optional
|
|
23
|
+
from typing import Generator, List, Optional
|
|
26
24
|
|
|
27
|
-
from click import ClickException
|
|
28
25
|
from snowflake.cli._plugins.connection.util import make_snowsight_url
|
|
29
26
|
from snowflake.cli._plugins.nativeapp.artifacts import (
|
|
30
27
|
BundleMap,
|
|
31
|
-
build_bundle,
|
|
32
|
-
)
|
|
33
|
-
from snowflake.cli._plugins.nativeapp.codegen.compiler import (
|
|
34
|
-
NativeAppCompiler,
|
|
35
|
-
)
|
|
36
|
-
from snowflake.cli._plugins.nativeapp.constants import (
|
|
37
|
-
NAME_COL,
|
|
38
28
|
)
|
|
39
29
|
from snowflake.cli._plugins.nativeapp.exceptions import (
|
|
40
|
-
ApplicationPackageDoesNotExistError,
|
|
41
30
|
NoEventTableForAccount,
|
|
42
|
-
SetupScriptFailedValidation,
|
|
43
31
|
)
|
|
44
32
|
from snowflake.cli._plugins.nativeapp.project_model import (
|
|
45
33
|
NativeAppProjectModel,
|
|
@@ -47,8 +35,11 @@ from snowflake.cli._plugins.nativeapp.project_model import (
|
|
|
47
35
|
from snowflake.cli._plugins.stage.diff import (
|
|
48
36
|
DiffResult,
|
|
49
37
|
)
|
|
50
|
-
from snowflake.cli._plugins.stage.manager import StageManager
|
|
51
38
|
from snowflake.cli.api.console import cli_console as cc
|
|
39
|
+
from snowflake.cli.api.entities.application_entity import (
|
|
40
|
+
ApplicationEntity,
|
|
41
|
+
ApplicationOwnedObject,
|
|
42
|
+
)
|
|
52
43
|
from snowflake.cli.api.entities.application_package_entity import (
|
|
53
44
|
ApplicationPackageEntity,
|
|
54
45
|
)
|
|
@@ -57,10 +48,6 @@ from snowflake.cli.api.entities.utils import (
|
|
|
57
48
|
generic_sql_error_handler,
|
|
58
49
|
sync_deploy_root_with_stage,
|
|
59
50
|
)
|
|
60
|
-
from snowflake.cli.api.errno import (
|
|
61
|
-
DOES_NOT_EXIST_OR_NOT_AUTHORIZED,
|
|
62
|
-
)
|
|
63
|
-
from snowflake.cli.api.exceptions import SnowflakeSQLExecutionError
|
|
64
51
|
from snowflake.cli.api.project.schemas.entities.common import PostDeployHook
|
|
65
52
|
from snowflake.cli.api.project.schemas.native_app.native_app import NativeApp
|
|
66
53
|
from snowflake.cli.api.project.schemas.native_app.path_mapping import PathMapping
|
|
@@ -71,8 +58,6 @@ from snowflake.cli.api.project.util import (
|
|
|
71
58
|
from snowflake.cli.api.sql_execution import SqlExecutionMixin
|
|
72
59
|
from snowflake.connector import DictCursor, ProgrammingError
|
|
73
60
|
|
|
74
|
-
ApplicationOwnedObject = TypedDict("ApplicationOwnedObject", {"name": str, "type": str})
|
|
75
|
-
|
|
76
61
|
|
|
77
62
|
class NativeAppCommandProcessor(ABC):
|
|
78
63
|
@abstractmethod
|
|
@@ -149,20 +134,8 @@ class NativeAppManager(SqlExecutionMixin):
|
|
|
149
134
|
def application_warehouse(self) -> Optional[str]:
|
|
150
135
|
return self.na_project.application_warehouse
|
|
151
136
|
|
|
152
|
-
@contextmanager
|
|
153
137
|
def use_application_warehouse(self):
|
|
154
|
-
|
|
155
|
-
with self.use_warehouse(self.application_warehouse):
|
|
156
|
-
yield
|
|
157
|
-
else:
|
|
158
|
-
raise ClickException(
|
|
159
|
-
dedent(
|
|
160
|
-
f"""\
|
|
161
|
-
Application warehouse cannot be empty.
|
|
162
|
-
Please provide a value for it in your connection information or your project definition file.
|
|
163
|
-
"""
|
|
164
|
-
)
|
|
165
|
-
)
|
|
138
|
+
return ApplicationEntity.use_application_warehouse(self.application_warehouse)
|
|
166
139
|
|
|
167
140
|
@property
|
|
168
141
|
def project_identifier(self) -> str:
|
|
@@ -227,10 +200,14 @@ class NativeAppManager(SqlExecutionMixin):
|
|
|
227
200
|
"""
|
|
228
201
|
Populates the local deploy root from artifact sources.
|
|
229
202
|
"""
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
203
|
+
return ApplicationPackageEntity.bundle(
|
|
204
|
+
project_root=self.project_root,
|
|
205
|
+
deploy_root=self.deploy_root,
|
|
206
|
+
bundle_root=self.bundle_root,
|
|
207
|
+
generated_root=self.generated_root,
|
|
208
|
+
package_name=self.package_name,
|
|
209
|
+
artifacts=self.artifacts,
|
|
210
|
+
)
|
|
234
211
|
|
|
235
212
|
def sync_deploy_root_with_stage(
|
|
236
213
|
self,
|
|
@@ -257,14 +234,10 @@ class NativeAppManager(SqlExecutionMixin):
|
|
|
257
234
|
)
|
|
258
235
|
|
|
259
236
|
def get_existing_app_info(self) -> Optional[dict]:
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
with self.use_role(self.app_role):
|
|
265
|
-
return self.show_specific_object(
|
|
266
|
-
"applications", self.app_name, name_col=NAME_COL
|
|
267
|
-
)
|
|
237
|
+
return ApplicationEntity.get_existing_app_info(
|
|
238
|
+
app_name=self.app_name,
|
|
239
|
+
app_role=self.app_role,
|
|
240
|
+
)
|
|
268
241
|
|
|
269
242
|
def get_existing_app_pkg_info(self) -> Optional[dict]:
|
|
270
243
|
return ApplicationPackageEntity.get_existing_app_pkg_info(
|
|
@@ -272,32 +245,19 @@ class NativeAppManager(SqlExecutionMixin):
|
|
|
272
245
|
package_role=self.package_role,
|
|
273
246
|
)
|
|
274
247
|
|
|
275
|
-
def get_objects_owned_by_application(self)
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
results = self._execute_query(
|
|
281
|
-
f"show objects owned by application {self.app_name}"
|
|
282
|
-
).fetchall()
|
|
283
|
-
return [{"name": row[1], "type": row[2]} for row in results]
|
|
248
|
+
def get_objects_owned_by_application(self):
|
|
249
|
+
return ApplicationEntity.get_objects_owned_by_application(
|
|
250
|
+
app_name=self.app_name,
|
|
251
|
+
app_role=self.app_role,
|
|
252
|
+
)
|
|
284
253
|
|
|
285
254
|
def _application_objects_to_str(
|
|
286
255
|
self, application_objects: list[ApplicationOwnedObject]
|
|
287
256
|
) -> str:
|
|
288
|
-
|
|
289
|
-
Returns a list in an "(Object Type) Object Name" format. Database-level and schema-level object names are fully qualified:
|
|
290
|
-
(COMPUTE_POOL) POOL_NAME
|
|
291
|
-
(DATABASE) DB_NAME
|
|
292
|
-
(SCHEMA) DB_NAME.PUBLIC
|
|
293
|
-
...
|
|
294
|
-
"""
|
|
295
|
-
return "\n".join(
|
|
296
|
-
[self._application_object_to_str(obj) for obj in application_objects]
|
|
297
|
-
)
|
|
257
|
+
return ApplicationEntity.application_objects_to_str(application_objects)
|
|
298
258
|
|
|
299
|
-
def _application_object_to_str(self, obj: ApplicationOwnedObject)
|
|
300
|
-
return
|
|
259
|
+
def _application_object_to_str(self, obj: ApplicationOwnedObject):
|
|
260
|
+
return ApplicationEntity.application_object_to_str(obj)
|
|
301
261
|
|
|
302
262
|
def get_snowsight_url(self) -> str:
|
|
303
263
|
"""Returns the URL that can be used to visit this app via Snowsight."""
|
|
@@ -351,89 +311,59 @@ class NativeAppManager(SqlExecutionMixin):
|
|
|
351
311
|
validate: bool = True,
|
|
352
312
|
print_diff: bool = True,
|
|
353
313
|
) -> DiffResult:
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
self.
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
# 4. Execute post-deploy hooks
|
|
376
|
-
with self.use_package_warehouse():
|
|
377
|
-
self.execute_package_post_deploy_hooks()
|
|
378
|
-
|
|
379
|
-
if validate:
|
|
380
|
-
self.validate(use_scratch_stage=False)
|
|
314
|
+
return ApplicationPackageEntity.deploy(
|
|
315
|
+
console=cc,
|
|
316
|
+
project_root=self.project_root,
|
|
317
|
+
deploy_root=self.deploy_root,
|
|
318
|
+
bundle_root=self.bundle_root,
|
|
319
|
+
generated_root=self.generated_root,
|
|
320
|
+
artifacts=self.artifacts,
|
|
321
|
+
package_name=self.package_name,
|
|
322
|
+
package_role=self.package_role,
|
|
323
|
+
package_distribution=self.package_distribution,
|
|
324
|
+
prune=prune,
|
|
325
|
+
recursive=recursive,
|
|
326
|
+
paths=local_paths_to_sync,
|
|
327
|
+
print_diff=print_diff,
|
|
328
|
+
validate=validate,
|
|
329
|
+
stage_fqn=stage_fqn or self.stage_fqn,
|
|
330
|
+
package_warehouse=self.package_warehouse,
|
|
331
|
+
post_deploy_hooks=self.package_post_deploy_hooks,
|
|
332
|
+
package_scripts=self.package_scripts,
|
|
333
|
+
)
|
|
381
334
|
|
|
382
|
-
|
|
335
|
+
def deploy_to_scratch_stage_fn(self):
|
|
336
|
+
bundle_map = self.build_bundle()
|
|
337
|
+
self.deploy(
|
|
338
|
+
bundle_map=bundle_map,
|
|
339
|
+
prune=True,
|
|
340
|
+
recursive=True,
|
|
341
|
+
stage_fqn=self.scratch_stage_fqn,
|
|
342
|
+
validate=False,
|
|
343
|
+
print_diff=False,
|
|
344
|
+
)
|
|
383
345
|
|
|
384
346
|
def validate(self, use_scratch_stage: bool = False):
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
for error in validation_result.get("errors", []):
|
|
395
|
-
# Print them as warnings for now since we're going to be
|
|
396
|
-
# revamping CLI output soon
|
|
397
|
-
cc.warning(_validation_item_to_str(error))
|
|
398
|
-
|
|
399
|
-
# Then raise an exception if validation failed
|
|
400
|
-
if validation_result["status"] == "FAIL":
|
|
401
|
-
raise SetupScriptFailedValidation()
|
|
347
|
+
return ApplicationPackageEntity.validate_setup_script(
|
|
348
|
+
console=cc,
|
|
349
|
+
package_name=self.package_name,
|
|
350
|
+
package_role=self.package_role,
|
|
351
|
+
stage_fqn=self.stage_fqn,
|
|
352
|
+
use_scratch_stage=use_scratch_stage,
|
|
353
|
+
scratch_stage_fqn=self.scratch_stage_fqn,
|
|
354
|
+
deploy_to_scratch_stage_fn=self.deploy_to_scratch_stage_fn,
|
|
355
|
+
)
|
|
402
356
|
|
|
403
357
|
def get_validation_result(self, use_scratch_stage: bool):
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
stage_fqn=stage_fqn,
|
|
414
|
-
validate=False,
|
|
415
|
-
print_diff=False,
|
|
416
|
-
)
|
|
417
|
-
prefixed_stage_fqn = StageManager.get_standard_stage_prefix(stage_fqn)
|
|
418
|
-
try:
|
|
419
|
-
cursor = self._execute_query(
|
|
420
|
-
f"call system$validate_native_app_setup('{prefixed_stage_fqn}')"
|
|
421
|
-
)
|
|
422
|
-
except ProgrammingError as err:
|
|
423
|
-
if err.errno == DOES_NOT_EXIST_OR_NOT_AUTHORIZED:
|
|
424
|
-
raise ApplicationPackageDoesNotExistError(self.package_name)
|
|
425
|
-
generic_sql_error_handler(err)
|
|
426
|
-
else:
|
|
427
|
-
if not cursor.rowcount:
|
|
428
|
-
raise SnowflakeSQLExecutionError()
|
|
429
|
-
return json.loads(cursor.fetchone()[0])
|
|
430
|
-
finally:
|
|
431
|
-
if use_scratch_stage:
|
|
432
|
-
cc.step(f"Dropping stage {self.scratch_stage_fqn}.")
|
|
433
|
-
with self.use_role(self.package_role):
|
|
434
|
-
self._execute_query(
|
|
435
|
-
f"drop stage if exists {self.scratch_stage_fqn}"
|
|
436
|
-
)
|
|
358
|
+
return ApplicationPackageEntity.get_validation_result(
|
|
359
|
+
console=cc,
|
|
360
|
+
package_name=self.package_name,
|
|
361
|
+
package_role=self.package_role,
|
|
362
|
+
stage_fqn=self.stage_fqn,
|
|
363
|
+
use_scratch_stage=use_scratch_stage,
|
|
364
|
+
scratch_stage_fqn=self.scratch_stage_fqn,
|
|
365
|
+
deploy_to_scratch_stage_fn=self.deploy_to_scratch_stage_fn,
|
|
366
|
+
)
|
|
437
367
|
|
|
438
368
|
def get_events( # type: ignore [return]
|
|
439
369
|
self,
|
|
@@ -21,6 +21,7 @@ from typing import List, Optional
|
|
|
21
21
|
from snowflake.cli._plugins.nativeapp.artifacts import resolve_without_follow
|
|
22
22
|
from snowflake.cli._plugins.nativeapp.bundle_context import BundleContext
|
|
23
23
|
from snowflake.cli.api.cli_global_context import get_cli_context
|
|
24
|
+
from snowflake.cli.api.entities.common import get_sql_executor
|
|
24
25
|
from snowflake.cli.api.project.definition import (
|
|
25
26
|
default_app_package,
|
|
26
27
|
default_application,
|
|
@@ -34,14 +35,6 @@ from snowflake.cli.api.project.util import (
|
|
|
34
35
|
extract_schema,
|
|
35
36
|
to_identifier,
|
|
36
37
|
)
|
|
37
|
-
from snowflake.connector import DictCursor
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def current_role() -> str:
|
|
41
|
-
conn = get_cli_context().connection
|
|
42
|
-
*_, cursor = conn.execute_string("select current_role()", cursor_class=DictCursor)
|
|
43
|
-
role_result = cursor.fetchone()
|
|
44
|
-
return role_result["CURRENT_ROLE()"]
|
|
45
38
|
|
|
46
39
|
|
|
47
40
|
class NativeAppProjectModel:
|
|
@@ -198,7 +191,7 @@ class NativeAppProjectModel:
|
|
|
198
191
|
def _default_role(self) -> str:
|
|
199
192
|
role = default_role()
|
|
200
193
|
if role is None:
|
|
201
|
-
role = current_role()
|
|
194
|
+
role = get_sql_executor().current_role()
|
|
202
195
|
return role
|
|
203
196
|
|
|
204
197
|
@cached_property
|