snowflake-cli 3.0.2__py3-none-any.whl → 3.1.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/cli_app.py +3 -0
- snowflake/cli/_app/dev/docs/templates/overview.rst.jinja2 +1 -1
- snowflake/cli/_app/dev/docs/templates/usage.rst.jinja2 +2 -2
- snowflake/cli/_app/telemetry.py +69 -4
- snowflake/cli/_plugins/connection/commands.py +40 -2
- snowflake/cli/_plugins/git/commands.py +6 -3
- snowflake/cli/_plugins/git/manager.py +5 -0
- snowflake/cli/_plugins/nativeapp/artifacts.py +13 -3
- snowflake/cli/_plugins/nativeapp/codegen/artifact_processor.py +1 -1
- snowflake/cli/_plugins/nativeapp/codegen/compiler.py +7 -0
- snowflake/cli/_plugins/nativeapp/codegen/sandbox.py +10 -10
- snowflake/cli/_plugins/nativeapp/codegen/setup/native_app_setup_processor.py +2 -2
- snowflake/cli/_plugins/nativeapp/codegen/snowpark/extension_function_utils.py +1 -1
- snowflake/cli/_plugins/nativeapp/codegen/snowpark/python_processor.py +8 -8
- snowflake/cli/_plugins/nativeapp/commands.py +135 -186
- snowflake/cli/_plugins/nativeapp/entities/application.py +176 -24
- snowflake/cli/_plugins/nativeapp/entities/application_package.py +112 -136
- snowflake/cli/_plugins/nativeapp/exceptions.py +12 -0
- snowflake/cli/_plugins/nativeapp/manager.py +3 -26
- snowflake/cli/_plugins/nativeapp/v2_conversions/{v2_to_v1_decorator.py → compat.py} +131 -72
- snowflake/cli/_plugins/nativeapp/version/commands.py +30 -29
- snowflake/cli/_plugins/nativeapp/version/version_processor.py +1 -43
- snowflake/cli/_plugins/snowpark/common.py +60 -18
- snowflake/cli/_plugins/snowpark/package/anaconda_packages.py +2 -2
- snowflake/cli/_plugins/spcs/image_repository/commands.py +4 -37
- snowflake/cli/_plugins/spcs/image_repository/manager.py +4 -1
- snowflake/cli/_plugins/spcs/services/commands.py +36 -4
- snowflake/cli/_plugins/spcs/services/manager.py +36 -4
- snowflake/cli/_plugins/stage/commands.py +8 -3
- snowflake/cli/_plugins/stage/diff.py +16 -16
- snowflake/cli/_plugins/stage/manager.py +164 -73
- snowflake/cli/_plugins/stage/md5.py +1 -1
- snowflake/cli/_plugins/workspace/commands.py +21 -1
- snowflake/cli/_plugins/workspace/context.py +38 -0
- snowflake/cli/_plugins/workspace/manager.py +23 -13
- snowflake/cli/api/cli_global_context.py +3 -3
- snowflake/cli/api/commands/flags.py +23 -7
- snowflake/cli/api/config.py +7 -4
- snowflake/cli/api/connections.py +12 -1
- snowflake/cli/api/entities/common.py +4 -2
- snowflake/cli/api/entities/utils.py +17 -37
- snowflake/cli/api/exceptions.py +32 -0
- snowflake/cli/api/identifiers.py +8 -0
- snowflake/cli/api/project/definition_conversion.py +139 -40
- snowflake/cli/api/project/schemas/entities/common.py +11 -0
- snowflake/cli/api/project/schemas/project_definition.py +30 -25
- snowflake/cli/api/sql_execution.py +5 -7
- snowflake/cli/api/stage_path.py +241 -0
- snowflake/cli/api/utils/definition_rendering.py +3 -5
- {snowflake_cli-3.0.2.dist-info → snowflake_cli-3.1.0.dist-info}/METADATA +11 -11
- {snowflake_cli-3.0.2.dist-info → snowflake_cli-3.1.0.dist-info}/RECORD +55 -55
- snowflake/cli/_plugins/nativeapp/teardown_processor.py +0 -70
- snowflake/cli/_plugins/workspace/action_context.py +0 -18
- {snowflake_cli-3.0.2.dist-info → snowflake_cli-3.1.0.dist-info}/WHEEL +0 -0
- {snowflake_cli-3.0.2.dist-info → snowflake_cli-3.1.0.dist-info}/entry_points.txt +0 -0
- {snowflake_cli-3.0.2.dist-info → snowflake_cli-3.1.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -22,7 +22,6 @@ from textwrap import dedent
|
|
|
22
22
|
from typing import Generator, Iterable, List, Optional, cast
|
|
23
23
|
|
|
24
24
|
import typer
|
|
25
|
-
from click.exceptions import ClickException
|
|
26
25
|
from snowflake.cli._plugins.nativeapp.common_flags import (
|
|
27
26
|
ForceOption,
|
|
28
27
|
InteractiveOption,
|
|
@@ -32,19 +31,9 @@ from snowflake.cli._plugins.nativeapp.entities.application import ApplicationEnt
|
|
|
32
31
|
from snowflake.cli._plugins.nativeapp.entities.application_package import (
|
|
33
32
|
ApplicationPackageEntityModel,
|
|
34
33
|
)
|
|
35
|
-
from snowflake.cli._plugins.nativeapp.
|
|
36
|
-
from snowflake.cli._plugins.nativeapp.policy import (
|
|
37
|
-
AllowAlwaysPolicy,
|
|
38
|
-
AskAlwaysPolicy,
|
|
39
|
-
DenyAlwaysPolicy,
|
|
40
|
-
)
|
|
41
|
-
from snowflake.cli._plugins.nativeapp.run_processor import NativeAppRunProcessor
|
|
42
|
-
from snowflake.cli._plugins.nativeapp.teardown_processor import (
|
|
43
|
-
NativeAppTeardownProcessor,
|
|
44
|
-
)
|
|
45
|
-
from snowflake.cli._plugins.nativeapp.v2_conversions.v2_to_v1_decorator import (
|
|
34
|
+
from snowflake.cli._plugins.nativeapp.v2_conversions.compat import (
|
|
46
35
|
find_entity,
|
|
47
|
-
|
|
36
|
+
force_project_definition_v2,
|
|
48
37
|
)
|
|
49
38
|
from snowflake.cli._plugins.nativeapp.version.commands import app as versions_app
|
|
50
39
|
from snowflake.cli._plugins.stage.diff import (
|
|
@@ -67,8 +56,6 @@ from snowflake.cli.api.output.types import (
|
|
|
67
56
|
ObjectResult,
|
|
68
57
|
StreamResult,
|
|
69
58
|
)
|
|
70
|
-
from snowflake.cli.api.project.project_verification import assert_project_type
|
|
71
|
-
from snowflake.cli.api.project.schemas.project_definition import ProjectDefinitionV1
|
|
72
59
|
from typing_extensions import Annotated
|
|
73
60
|
|
|
74
61
|
app = SnowTyperFactory(
|
|
@@ -80,57 +67,52 @@ app.add_typer(versions_app)
|
|
|
80
67
|
log = logging.getLogger(__name__)
|
|
81
68
|
|
|
82
69
|
|
|
83
|
-
@app.command("init", hidden=True)
|
|
84
|
-
def app_init(**options):
|
|
85
|
-
"""
|
|
86
|
-
*** Deprecated. Use snow init instead ***
|
|
87
|
-
|
|
88
|
-
Initializes a Snowflake Native App project.
|
|
89
|
-
"""
|
|
90
|
-
|
|
91
|
-
raise ClickException("This command has been removed. Use `snow init` instead.")
|
|
92
|
-
|
|
93
|
-
|
|
94
70
|
@app.command("bundle")
|
|
95
71
|
@with_project_definition()
|
|
96
|
-
@
|
|
72
|
+
@force_project_definition_v2()
|
|
97
73
|
def app_bundle(
|
|
98
74
|
**options,
|
|
99
75
|
) -> CommandResult:
|
|
100
76
|
"""
|
|
101
77
|
Prepares a local folder with configured app artifacts.
|
|
102
78
|
"""
|
|
103
|
-
|
|
104
|
-
assert_project_type("native_app")
|
|
105
|
-
|
|
106
79
|
cli_context = get_cli_context()
|
|
107
|
-
|
|
108
|
-
project_definition=cli_context.project_definition
|
|
80
|
+
ws = WorkspaceManager(
|
|
81
|
+
project_definition=cli_context.project_definition,
|
|
109
82
|
project_root=cli_context.project_root,
|
|
110
83
|
)
|
|
111
|
-
|
|
112
|
-
|
|
84
|
+
package_id = options["package_entity_id"]
|
|
85
|
+
package = cli_context.project_definition.entities[package_id]
|
|
86
|
+
ws.perform_action(
|
|
87
|
+
package_id,
|
|
88
|
+
EntityActions.BUNDLE,
|
|
89
|
+
)
|
|
90
|
+
return MessageResult(f"Bundle generated at {ws.project_root / package.deploy_root}")
|
|
113
91
|
|
|
114
92
|
|
|
115
93
|
@app.command("diff", requires_connection=True, hidden=True)
|
|
116
94
|
@with_project_definition()
|
|
117
|
-
@
|
|
95
|
+
@force_project_definition_v2()
|
|
118
96
|
def app_diff(
|
|
119
97
|
**options,
|
|
120
|
-
) -> CommandResult:
|
|
98
|
+
) -> CommandResult | None:
|
|
121
99
|
"""
|
|
122
100
|
Performs a diff between the app's source stage and the local deploy root.
|
|
123
101
|
"""
|
|
124
|
-
assert_project_type("native_app")
|
|
125
|
-
|
|
126
102
|
cli_context = get_cli_context()
|
|
127
|
-
|
|
128
|
-
project_definition=cli_context.project_definition
|
|
103
|
+
ws = WorkspaceManager(
|
|
104
|
+
project_definition=cli_context.project_definition,
|
|
129
105
|
project_root=cli_context.project_root,
|
|
130
106
|
)
|
|
131
|
-
|
|
107
|
+
package_id = options["package_entity_id"]
|
|
108
|
+
package = cli_context.project_definition.entities[package_id]
|
|
109
|
+
bundle_map = ws.perform_action(
|
|
110
|
+
package_id,
|
|
111
|
+
EntityActions.BUNDLE,
|
|
112
|
+
)
|
|
113
|
+
stage_fqn = f"{package.fqn.name}.{package.stage}"
|
|
132
114
|
diff: DiffResult = compute_stage_diff(
|
|
133
|
-
local_root=Path(
|
|
115
|
+
local_root=Path(package.deploy_root), stage_fqn=stage_fqn
|
|
134
116
|
)
|
|
135
117
|
if cli_context.output_format == OutputFormat.JSON:
|
|
136
118
|
return ObjectResult(diff.to_dict())
|
|
@@ -141,7 +123,7 @@ def app_diff(
|
|
|
141
123
|
|
|
142
124
|
@app.command("run", requires_connection=True)
|
|
143
125
|
@with_project_definition()
|
|
144
|
-
@
|
|
126
|
+
@force_project_definition_v2(app_required=True)
|
|
145
127
|
def app_run(
|
|
146
128
|
version: Optional[str] = typer.Option(
|
|
147
129
|
None,
|
|
@@ -170,42 +152,35 @@ def app_run(
|
|
|
170
152
|
Creates an application package in your Snowflake account, uploads code files to its stage,
|
|
171
153
|
then creates or upgrades an application object from the application package.
|
|
172
154
|
"""
|
|
173
|
-
|
|
174
|
-
assert_project_type("native_app")
|
|
175
|
-
|
|
176
|
-
is_interactive = False
|
|
177
|
-
if force:
|
|
178
|
-
policy = AllowAlwaysPolicy()
|
|
179
|
-
elif interactive:
|
|
180
|
-
is_interactive = True
|
|
181
|
-
policy = AskAlwaysPolicy()
|
|
182
|
-
else:
|
|
183
|
-
policy = DenyAlwaysPolicy()
|
|
184
|
-
|
|
185
155
|
cli_context = get_cli_context()
|
|
186
|
-
|
|
187
|
-
project_definition=cli_context.project_definition
|
|
156
|
+
ws = WorkspaceManager(
|
|
157
|
+
project_definition=cli_context.project_definition,
|
|
188
158
|
project_root=cli_context.project_root,
|
|
189
159
|
)
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
160
|
+
app_id = options["app_entity_id"]
|
|
161
|
+
app_model = cli_context.project_definition.entities[app_id]
|
|
162
|
+
ws.perform_action(
|
|
163
|
+
app_id,
|
|
164
|
+
EntityActions.DEPLOY,
|
|
165
|
+
validate=validate,
|
|
194
166
|
version=version,
|
|
195
167
|
patch=patch,
|
|
196
168
|
from_release_directive=from_release_directive,
|
|
197
|
-
|
|
198
|
-
|
|
169
|
+
prune=True,
|
|
170
|
+
recursive=True,
|
|
171
|
+
paths=[],
|
|
172
|
+
interactive=interactive,
|
|
173
|
+
force=force,
|
|
199
174
|
)
|
|
175
|
+
app = ws.get_entity(app_id)
|
|
200
176
|
return MessageResult(
|
|
201
|
-
f"Your application object ({
|
|
202
|
-
+ processor.get_snowsight_url()
|
|
177
|
+
f"Your application object ({app_model.fqn.name}) is now available:\n{app.get_snowsight_url()}"
|
|
203
178
|
)
|
|
204
179
|
|
|
205
180
|
|
|
206
181
|
@app.command("open", requires_connection=True)
|
|
207
182
|
@with_project_definition()
|
|
208
|
-
@
|
|
183
|
+
@force_project_definition_v2(app_required=True)
|
|
209
184
|
def app_open(
|
|
210
185
|
**options,
|
|
211
186
|
) -> CommandResult:
|
|
@@ -213,16 +188,15 @@ def app_open(
|
|
|
213
188
|
Opens the Snowflake Native App inside of your browser,
|
|
214
189
|
once it has been installed in your account.
|
|
215
190
|
"""
|
|
216
|
-
|
|
217
|
-
assert_project_type("native_app")
|
|
218
|
-
|
|
219
191
|
cli_context = get_cli_context()
|
|
220
|
-
|
|
221
|
-
project_definition=cli_context.project_definition
|
|
192
|
+
ws = WorkspaceManager(
|
|
193
|
+
project_definition=cli_context.project_definition,
|
|
222
194
|
project_root=cli_context.project_root,
|
|
223
195
|
)
|
|
224
|
-
|
|
225
|
-
|
|
196
|
+
app_id = options["app_entity_id"]
|
|
197
|
+
app = ws.get_entity(app_id)
|
|
198
|
+
if app.get_existing_app_info():
|
|
199
|
+
typer.launch(app.get_snowsight_url())
|
|
226
200
|
return MessageResult(f"Snowflake Native App opened in browser.")
|
|
227
201
|
else:
|
|
228
202
|
return MessageResult(
|
|
@@ -232,9 +206,7 @@ def app_open(
|
|
|
232
206
|
|
|
233
207
|
@app.command("teardown", requires_connection=True)
|
|
234
208
|
@with_project_definition()
|
|
235
|
-
|
|
236
|
-
# be aware of PDFv2 definitions that have multiple apps created from the same package,
|
|
237
|
-
# which all need to be torn down.
|
|
209
|
+
@force_project_definition_v2(single_app_and_package=False)
|
|
238
210
|
def app_teardown(
|
|
239
211
|
force: Optional[bool] = ForceOption,
|
|
240
212
|
cascade: Optional[bool] = typer.Option(
|
|
@@ -243,7 +215,7 @@ def app_teardown(
|
|
|
243
215
|
show_default=False,
|
|
244
216
|
),
|
|
245
217
|
interactive: bool = InteractiveOption,
|
|
246
|
-
# Same as the param auto-added by @
|
|
218
|
+
# Same as the param auto-added by @force_project_definition_v2 if single_app_and_package were true
|
|
247
219
|
package_entity_id: Optional[str] = typer.Option(
|
|
248
220
|
default="",
|
|
249
221
|
help="The ID of the package entity on which to operate when definition_version is 2 or higher.",
|
|
@@ -255,58 +227,49 @@ def app_teardown(
|
|
|
255
227
|
"""
|
|
256
228
|
cli_context = get_cli_context()
|
|
257
229
|
project = cli_context.project_definition
|
|
258
|
-
if isinstance(project, ProjectDefinitionV1):
|
|
259
|
-
# Old behaviour, not multi-app aware so we can use the old processor
|
|
260
|
-
processor = NativeAppTeardownProcessor(
|
|
261
|
-
project_definition=cli_context.project_definition.native_app,
|
|
262
|
-
project_root=cli_context.project_root,
|
|
263
|
-
)
|
|
264
|
-
processor.process(interactive, force, cascade)
|
|
265
|
-
else:
|
|
266
|
-
# New behaviour, multi-app aware so teardown all the apps created from the package
|
|
267
|
-
|
|
268
|
-
# Determine the package entity to drop, there must be one
|
|
269
|
-
app_package_entity = find_entity(
|
|
270
|
-
project,
|
|
271
|
-
ApplicationPackageEntityModel,
|
|
272
|
-
package_entity_id,
|
|
273
|
-
disambiguation_option="--package-entity-id",
|
|
274
|
-
required=True,
|
|
275
|
-
)
|
|
276
|
-
assert app_package_entity is not None # satisfy mypy
|
|
277
230
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
231
|
+
# Determine the package entity to drop, there must be one
|
|
232
|
+
app_package_entity = find_entity(
|
|
233
|
+
project,
|
|
234
|
+
ApplicationPackageEntityModel,
|
|
235
|
+
package_entity_id,
|
|
236
|
+
disambiguation_option="--package-entity-id",
|
|
237
|
+
required=True,
|
|
238
|
+
)
|
|
239
|
+
assert app_package_entity is not None # satisfy mypy
|
|
240
|
+
|
|
241
|
+
# Same implementation as `snow ws drop`
|
|
242
|
+
ws = WorkspaceManager(
|
|
243
|
+
project_definition=cli_context.project_definition,
|
|
244
|
+
project_root=cli_context.project_root,
|
|
245
|
+
)
|
|
246
|
+
for app_entity in project.get_entities_by_type(
|
|
247
|
+
ApplicationEntityModel.get_type()
|
|
248
|
+
).values():
|
|
249
|
+
# Drop each app
|
|
250
|
+
if app_entity.from_.target == app_package_entity.entity_id:
|
|
251
|
+
ws.perform_action(
|
|
252
|
+
app_entity.entity_id,
|
|
253
|
+
EntityActions.DROP,
|
|
254
|
+
force_drop=force,
|
|
255
|
+
interactive=interactive,
|
|
256
|
+
cascade=cascade,
|
|
257
|
+
)
|
|
258
|
+
# Then drop the package
|
|
259
|
+
ws.perform_action(
|
|
260
|
+
app_package_entity.entity_id,
|
|
261
|
+
EntityActions.DROP,
|
|
262
|
+
force_drop=force,
|
|
263
|
+
interactive=interactive,
|
|
264
|
+
cascade=cascade,
|
|
265
|
+
)
|
|
303
266
|
|
|
304
267
|
return MessageResult(f"Teardown is now complete.")
|
|
305
268
|
|
|
306
269
|
|
|
307
270
|
@app.command("deploy", requires_connection=True)
|
|
308
271
|
@with_project_definition()
|
|
309
|
-
@
|
|
272
|
+
@force_project_definition_v2()
|
|
310
273
|
def app_deploy(
|
|
311
274
|
prune: Optional[bool] = typer.Option(
|
|
312
275
|
default=None,
|
|
@@ -338,16 +301,6 @@ def app_deploy(
|
|
|
338
301
|
Creates an application package in your Snowflake account and syncs the local changes to the stage without creating or updating the application.
|
|
339
302
|
Running this command with no arguments at all, as in `snow app deploy`, is a shorthand for `snow app deploy --prune --recursive`.
|
|
340
303
|
"""
|
|
341
|
-
|
|
342
|
-
assert_project_type("native_app")
|
|
343
|
-
|
|
344
|
-
if force:
|
|
345
|
-
policy = AllowAlwaysPolicy()
|
|
346
|
-
elif interactive:
|
|
347
|
-
policy = AskAlwaysPolicy()
|
|
348
|
-
else:
|
|
349
|
-
policy = DenyAlwaysPolicy()
|
|
350
|
-
|
|
351
304
|
has_paths = paths is not None and len(paths) > 0
|
|
352
305
|
if prune is None and recursive is None and not has_paths:
|
|
353
306
|
prune = True
|
|
@@ -357,24 +310,24 @@ def app_deploy(
|
|
|
357
310
|
prune = False
|
|
358
311
|
if recursive is None:
|
|
359
312
|
recursive = False
|
|
360
|
-
|
|
361
313
|
if has_paths and prune:
|
|
362
314
|
raise IncompatibleParametersError(["paths", "--prune"])
|
|
363
315
|
|
|
364
316
|
cli_context = get_cli_context()
|
|
365
|
-
|
|
366
|
-
project_definition=cli_context.project_definition
|
|
317
|
+
ws = WorkspaceManager(
|
|
318
|
+
project_definition=cli_context.project_definition,
|
|
367
319
|
project_root=cli_context.project_root,
|
|
368
320
|
)
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
321
|
+
package_id = options["package_entity_id"]
|
|
322
|
+
ws.perform_action(
|
|
323
|
+
package_id,
|
|
324
|
+
EntityActions.DEPLOY,
|
|
373
325
|
prune=prune,
|
|
374
326
|
recursive=recursive,
|
|
375
|
-
|
|
327
|
+
paths=paths,
|
|
376
328
|
validate=validate,
|
|
377
|
-
|
|
329
|
+
interactive=interactive,
|
|
330
|
+
force=force,
|
|
378
331
|
)
|
|
379
332
|
|
|
380
333
|
return MessageResult(
|
|
@@ -384,25 +337,29 @@ def app_deploy(
|
|
|
384
337
|
|
|
385
338
|
@app.command("validate", requires_connection=True)
|
|
386
339
|
@with_project_definition()
|
|
387
|
-
@
|
|
340
|
+
@force_project_definition_v2()
|
|
388
341
|
def app_validate(
|
|
389
342
|
**options,
|
|
390
343
|
):
|
|
391
344
|
"""
|
|
392
345
|
Validates a deployed Snowflake Native App's setup script.
|
|
393
346
|
"""
|
|
394
|
-
|
|
395
|
-
assert_project_type("native_app")
|
|
396
|
-
|
|
397
347
|
cli_context = get_cli_context()
|
|
398
|
-
|
|
399
|
-
project_definition=cli_context.project_definition
|
|
348
|
+
ws = WorkspaceManager(
|
|
349
|
+
project_definition=cli_context.project_definition,
|
|
400
350
|
project_root=cli_context.project_root,
|
|
401
351
|
)
|
|
352
|
+
package_id = options["package_entity_id"]
|
|
353
|
+
package = ws.get_entity(package_id)
|
|
402
354
|
if cli_context.output_format == OutputFormat.JSON:
|
|
403
|
-
return ObjectResult(
|
|
355
|
+
return ObjectResult(package.get_validation_result(use_scratch_stage=True))
|
|
404
356
|
|
|
405
|
-
|
|
357
|
+
ws.perform_action(
|
|
358
|
+
package_id,
|
|
359
|
+
EntityActions.VALIDATE,
|
|
360
|
+
interactive=False,
|
|
361
|
+
force=True,
|
|
362
|
+
)
|
|
406
363
|
return MessageResult("Snowflake Native App validation succeeded.")
|
|
407
364
|
|
|
408
365
|
|
|
@@ -419,7 +376,7 @@ DEFAULT_EVENT_FOLLOW_LAST = 20
|
|
|
419
376
|
|
|
420
377
|
@app.command("events", requires_connection=True)
|
|
421
378
|
@with_project_definition()
|
|
422
|
-
@
|
|
379
|
+
@force_project_definition_v2(app_required=True)
|
|
423
380
|
def app_events(
|
|
424
381
|
since: str = typer.Option(
|
|
425
382
|
default="",
|
|
@@ -499,48 +456,40 @@ def app_events(
|
|
|
499
456
|
if first >= 0:
|
|
500
457
|
raise IncompatibleParametersError(["--follow", "--first"])
|
|
501
458
|
|
|
502
|
-
|
|
459
|
+
cli_context = get_cli_context()
|
|
460
|
+
ws = WorkspaceManager(
|
|
461
|
+
project_definition=cli_context.project_definition,
|
|
462
|
+
project_root=cli_context.project_root,
|
|
463
|
+
)
|
|
464
|
+
app_id = options["app_entity_id"]
|
|
503
465
|
|
|
504
466
|
record_type_names = [r.name for r in record_types]
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
467
|
+
|
|
468
|
+
if follow and last == -1 and not since:
|
|
469
|
+
# If we don't have a value for --last or --since, assume a value
|
|
470
|
+
# for --last so we at least print something before starting the stream
|
|
471
|
+
last = DEFAULT_EVENT_FOLLOW_LAST
|
|
472
|
+
stream: Iterable[CommandResult] = (
|
|
473
|
+
EventResult(event)
|
|
474
|
+
for event in ws.perform_action(
|
|
475
|
+
app_id,
|
|
476
|
+
EntityActions.EVENTS,
|
|
477
|
+
since=since,
|
|
478
|
+
until=until,
|
|
479
|
+
record_types=record_type_names,
|
|
480
|
+
scopes=scopes,
|
|
481
|
+
consumer_org=consumer_org,
|
|
482
|
+
consumer_account=consumer_account,
|
|
483
|
+
consumer_app_hash=consumer_app_hash,
|
|
484
|
+
first=first,
|
|
485
|
+
last=last,
|
|
486
|
+
follow=follow,
|
|
487
|
+
interval_seconds=follow_interval,
|
|
488
|
+
)
|
|
508
489
|
)
|
|
509
490
|
if follow:
|
|
510
|
-
if last == -1 and not since:
|
|
511
|
-
# If we don't have a value for --last or --since, assume a value
|
|
512
|
-
# for --last so we at least print something before starting the stream
|
|
513
|
-
last = DEFAULT_EVENT_FOLLOW_LAST
|
|
514
|
-
stream: Iterable[CommandResult] = (
|
|
515
|
-
EventResult(event)
|
|
516
|
-
for event in manager.stream_events(
|
|
517
|
-
since=since,
|
|
518
|
-
last=last,
|
|
519
|
-
interval_seconds=follow_interval,
|
|
520
|
-
record_types=record_type_names,
|
|
521
|
-
scopes=scopes,
|
|
522
|
-
consumer_org=consumer_org,
|
|
523
|
-
consumer_account=consumer_account,
|
|
524
|
-
consumer_app_hash=consumer_app_hash,
|
|
525
|
-
)
|
|
526
|
-
)
|
|
527
491
|
# Append a newline at the end to make the CLI output clean when we hit Ctrl-C
|
|
528
492
|
stream = itertools.chain(stream, [MessageResult("")])
|
|
529
|
-
else:
|
|
530
|
-
stream = (
|
|
531
|
-
EventResult(event)
|
|
532
|
-
for event in manager.get_events(
|
|
533
|
-
since=since,
|
|
534
|
-
until=until,
|
|
535
|
-
record_types=record_type_names,
|
|
536
|
-
scopes=scopes,
|
|
537
|
-
first=first,
|
|
538
|
-
last=last,
|
|
539
|
-
consumer_org=consumer_org,
|
|
540
|
-
consumer_account=consumer_account,
|
|
541
|
-
consumer_app_hash=consumer_app_hash,
|
|
542
|
-
)
|
|
543
|
-
)
|
|
544
493
|
|
|
545
494
|
# Cast the stream to a Generator since that's what StreamResult wants
|
|
546
495
|
return StreamResult(cast(Generator[CommandResult, None, None], stream))
|