flyte 0.2.0b4__py3-none-any.whl → 0.2.0b7__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.
Potentially problematic release.
This version of flyte might be problematic. Click here for more details.
- flyte/__init__.py +2 -1
- flyte/_build.py +3 -2
- flyte/_code_bundle/_utils.py +0 -16
- flyte/_code_bundle/bundle.py +1 -1
- flyte/_deploy.py +4 -4
- flyte/_initialize.py +69 -26
- flyte/_internal/controllers/remote/_core.py +1 -1
- flyte/_protos/workflow/common_pb2.py +27 -0
- flyte/_protos/workflow/common_pb2.pyi +14 -0
- flyte/_protos/workflow/common_pb2_grpc.py +4 -0
- flyte/_protos/workflow/run_definition_pb2.py +14 -14
- flyte/_protos/workflow/run_definition_pb2.pyi +4 -2
- flyte/_protos/workflow/task_definition_pb2.py +14 -13
- flyte/_protos/workflow/task_definition_pb2.pyi +7 -3
- flyte/_run.py +7 -5
- flyte/_trace.py +1 -6
- flyte/_version.py +2 -2
- flyte/cli/_common.py +23 -15
- flyte/cli/_run.py +12 -6
- flyte/cli/main.py +15 -9
- flyte/config/__init__.py +2 -189
- flyte/config/_config.py +181 -172
- flyte/config/_internal.py +1 -1
- flyte/config/_reader.py +207 -0
- flyte/io/_dir.py +2 -2
- flyte/io/_file.py +1 -4
- flyte/remote/_data.py +3 -3
- flyte/remote/_logs.py +49 -26
- flyte/remote/_project.py +8 -9
- flyte/remote/_run.py +106 -61
- flyte/remote/_secret.py +12 -12
- flyte/remote/_task.py +3 -3
- flyte/report/_report.py +4 -4
- flyte/syncify/__init__.py +5 -0
- flyte/syncify/_api.py +277 -0
- flyte-0.2.0b7.dist-info/METADATA +156 -0
- {flyte-0.2.0b4.dist-info → flyte-0.2.0b7.dist-info}/RECORD +40 -35
- flyte/_api_commons.py +0 -3
- flyte-0.2.0b4.dist-info/METADATA +0 -179
- {flyte-0.2.0b4.dist-info → flyte-0.2.0b7.dist-info}/WHEEL +0 -0
- {flyte-0.2.0b4.dist-info → flyte-0.2.0b7.dist-info}/entry_points.txt +0 -0
- {flyte-0.2.0b4.dist-info → flyte-0.2.0b7.dist-info}/top_level.txt +0 -0
flyte/remote/_run.py
CHANGED
|
@@ -3,7 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
import asyncio
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
5
|
from datetime import datetime, timedelta, timezone
|
|
6
|
-
from typing import AsyncGenerator, AsyncIterator, Iterator, Literal, Tuple, Union, cast
|
|
6
|
+
from typing import AsyncGenerator, AsyncIterator, Iterator, List, Literal, Tuple, Union, cast
|
|
7
7
|
|
|
8
8
|
import grpc
|
|
9
9
|
import rich.repr
|
|
@@ -11,16 +11,16 @@ from google.protobuf import timestamp
|
|
|
11
11
|
from rich.console import Console
|
|
12
12
|
from rich.progress import Progress, SpinnerColumn, TextColumn, TimeElapsedColumn
|
|
13
13
|
|
|
14
|
-
from flyte.
|
|
15
|
-
from flyte._initialize import get_client, get_common_config, requires_client
|
|
14
|
+
from flyte._initialize import ensure_client, get_client, get_common_config
|
|
16
15
|
from flyte._protos.common import identifier_pb2, list_pb2
|
|
17
16
|
from flyte._protos.workflow import run_definition_pb2, run_service_pb2
|
|
17
|
+
from flyte.syncify import syncify
|
|
18
18
|
|
|
19
19
|
from .._protos.workflow.run_service_pb2 import WatchActionDetailsResponse
|
|
20
20
|
from ._console import get_run_url
|
|
21
21
|
from ._logs import Logs
|
|
22
22
|
|
|
23
|
-
WaitFor = Literal["terminal", "running"]
|
|
23
|
+
WaitFor = Literal["terminal", "running", "logs-ready"]
|
|
24
24
|
|
|
25
25
|
|
|
26
26
|
def _action_time_phase(action: run_definition_pb2.Action | run_definition_pb2.ActionDetails) -> rich.repr.Result:
|
|
@@ -46,33 +46,41 @@ def _action_time_phase(action: run_definition_pb2.Action | run_definition_pb2.Ac
|
|
|
46
46
|
yield "error", action.error_info if action.HasField("error_info") else "NA"
|
|
47
47
|
|
|
48
48
|
|
|
49
|
-
def _action_rich_repr(action: run_definition_pb2.Action
|
|
49
|
+
def _action_rich_repr(action: run_definition_pb2.Action) -> rich.repr.Result:
|
|
50
50
|
"""
|
|
51
51
|
Rich representation of the action.
|
|
52
52
|
"""
|
|
53
|
-
|
|
53
|
+
if action.metadata.HasField("task"):
|
|
54
|
+
yield "task", action.metadata.task.id.name
|
|
55
|
+
yield "type", "task"
|
|
54
56
|
yield "name", action.id.name
|
|
55
57
|
yield from _action_time_phase(action)
|
|
56
|
-
yield "
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
yield "parent", action.metadata.parent
|
|
58
|
+
yield "group", action.metadata.group
|
|
59
|
+
yield "parent", action.metadata.parent
|
|
60
|
+
yield "attempts", action.status.attempts
|
|
60
61
|
|
|
61
62
|
|
|
62
|
-
def
|
|
63
|
+
def _attempt_rich_repr(action: List[run_definition_pb2.ActionAttempt]) -> rich.repr.Result:
|
|
64
|
+
for attempt in action:
|
|
65
|
+
yield "attempt", attempt.attempt
|
|
66
|
+
yield "phase", run_definition_pb2.Phase.Name(attempt.phase)
|
|
67
|
+
yield "logs_available", attempt.logs_available
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _action_details_rich_repr(action: run_definition_pb2.ActionDetails) -> rich.repr.Result:
|
|
63
71
|
"""
|
|
64
72
|
Rich representation of the action details.
|
|
65
73
|
"""
|
|
66
74
|
yield "name", action.id.run.name
|
|
67
75
|
yield from _action_time_phase(action)
|
|
68
|
-
# yield "task", action.metadata.task.id.name
|
|
69
76
|
yield "task", action.resolved_task_spec.task_template.id.name
|
|
70
77
|
yield "task_type", action.resolved_task_spec.task_template.type
|
|
71
78
|
yield "task_version", action.resolved_task_spec.task_template.id.version
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
79
|
+
yield "attempts", action.attempts
|
|
80
|
+
yield "error_info", action.error_info if action.HasField("error_info") else "NA"
|
|
81
|
+
yield "phase", run_definition_pb2.Phase.Name(action.status.phase)
|
|
82
|
+
yield "group", action.metadata.group
|
|
83
|
+
yield "parent", action.metadata.parent
|
|
76
84
|
|
|
77
85
|
|
|
78
86
|
def _action_done_check(phase: run_definition_pb2.Phase) -> bool:
|
|
@@ -106,14 +114,13 @@ class Run:
|
|
|
106
114
|
raise RuntimeError("Run does not have an action")
|
|
107
115
|
self.action = Action(self.pb2.action)
|
|
108
116
|
|
|
117
|
+
@syncify
|
|
109
118
|
@classmethod
|
|
110
|
-
@requires_client
|
|
111
|
-
@syncer.wrap
|
|
112
119
|
async def listall(
|
|
113
120
|
cls,
|
|
114
121
|
filters: str | None = None,
|
|
115
122
|
sort_by: Tuple[str, Literal["asc", "desc"]] | None = None,
|
|
116
|
-
) ->
|
|
123
|
+
) -> AsyncIterator[Run]:
|
|
117
124
|
"""
|
|
118
125
|
Get all runs for the current project and domain.
|
|
119
126
|
|
|
@@ -121,6 +128,7 @@ class Run:
|
|
|
121
128
|
:param sort_by: The sorting criteria for the project list, in the format (field, order).
|
|
122
129
|
:return: An iterator of runs.
|
|
123
130
|
"""
|
|
131
|
+
ensure_client()
|
|
124
132
|
token = None
|
|
125
133
|
sort_by = sort_by or ("created_at", "asc")
|
|
126
134
|
sort_pb2 = list_pb2.Sort(
|
|
@@ -150,16 +158,16 @@ class Run:
|
|
|
150
158
|
if not token:
|
|
151
159
|
break
|
|
152
160
|
|
|
161
|
+
@syncify
|
|
153
162
|
@classmethod
|
|
154
|
-
@requires_client
|
|
155
|
-
@syncer.wrap
|
|
156
163
|
async def get(cls, name: str) -> Run:
|
|
157
164
|
"""
|
|
158
165
|
Get the current run.
|
|
159
166
|
|
|
160
167
|
:return: The current run.
|
|
161
168
|
"""
|
|
162
|
-
|
|
169
|
+
ensure_client()
|
|
170
|
+
run_details: RunDetails = await RunDetails.get.aio(name=name)
|
|
163
171
|
run = run_definition_pb2.Run(
|
|
164
172
|
action=run_definition_pb2.Action(
|
|
165
173
|
id=run_details.action_id,
|
|
@@ -181,9 +189,16 @@ class Run:
|
|
|
181
189
|
"""
|
|
182
190
|
Get the phase of the run.
|
|
183
191
|
"""
|
|
184
|
-
return
|
|
192
|
+
return self.action.phase
|
|
185
193
|
|
|
186
|
-
@
|
|
194
|
+
@property
|
|
195
|
+
def raw_phase(self) -> run_definition_pb2.Phase:
|
|
196
|
+
"""
|
|
197
|
+
Get the raw phase of the run.
|
|
198
|
+
"""
|
|
199
|
+
return self.action.raw_phase
|
|
200
|
+
|
|
201
|
+
@syncify
|
|
187
202
|
async def wait(self, quiet: bool = False, wait_for: Literal["terminal", "running"] = "terminal") -> None:
|
|
188
203
|
"""
|
|
189
204
|
Wait for the run to complete, displaying a rich progress panel with status transitions,
|
|
@@ -216,7 +231,6 @@ class Run:
|
|
|
216
231
|
return self._details
|
|
217
232
|
|
|
218
233
|
@property
|
|
219
|
-
@requires_client
|
|
220
234
|
def url(self) -> str:
|
|
221
235
|
"""
|
|
222
236
|
Get the URL of the run.
|
|
@@ -230,7 +244,7 @@ class Run:
|
|
|
230
244
|
run_name=self.name,
|
|
231
245
|
)
|
|
232
246
|
|
|
233
|
-
@
|
|
247
|
+
@syncify
|
|
234
248
|
async def abort(self):
|
|
235
249
|
"""
|
|
236
250
|
Aborts / Terminates the run.
|
|
@@ -264,7 +278,7 @@ class Run:
|
|
|
264
278
|
"""
|
|
265
279
|
Rich representation of the Run object.
|
|
266
280
|
"""
|
|
267
|
-
yield from _action_rich_repr(self.pb2.action
|
|
281
|
+
yield from _action_rich_repr(self.pb2.action)
|
|
268
282
|
|
|
269
283
|
def __repr__(self) -> str:
|
|
270
284
|
"""
|
|
@@ -291,13 +305,13 @@ class RunDetails:
|
|
|
291
305
|
"""
|
|
292
306
|
self.action_details = ActionDetails(self.pb2.action)
|
|
293
307
|
|
|
308
|
+
@syncify
|
|
294
309
|
@classmethod
|
|
295
|
-
@requires_client
|
|
296
|
-
@syncer.wrap
|
|
297
310
|
async def get_details(cls, run_id: run_definition_pb2.RunIdentifier) -> RunDetails:
|
|
298
311
|
"""
|
|
299
312
|
Get the details of the run. This is a placeholder for getting the run details.
|
|
300
313
|
"""
|
|
314
|
+
ensure_client()
|
|
301
315
|
resp = await get_client().run_service.GetRunDetails(
|
|
302
316
|
run_service_pb2.GetRunDetailsRequest(
|
|
303
317
|
run_id=run_id,
|
|
@@ -305,9 +319,8 @@ class RunDetails:
|
|
|
305
319
|
)
|
|
306
320
|
return cls(resp.details)
|
|
307
321
|
|
|
322
|
+
@syncify
|
|
308
323
|
@classmethod
|
|
309
|
-
@requires_client
|
|
310
|
-
@syncer.wrap
|
|
311
324
|
async def get(cls, name: str | None = None) -> RunDetails:
|
|
312
325
|
"""
|
|
313
326
|
Get a run by its ID or name. If both are provided, the ID will take precedence.
|
|
@@ -315,9 +328,9 @@ class RunDetails:
|
|
|
315
328
|
:param uri: The URI of the run.
|
|
316
329
|
:param name: The name of the run.
|
|
317
330
|
"""
|
|
331
|
+
ensure_client()
|
|
318
332
|
cfg = get_common_config()
|
|
319
333
|
return await RunDetails.get_details.aio(
|
|
320
|
-
cls,
|
|
321
334
|
run_id=run_definition_pb2.RunIdentifier(
|
|
322
335
|
org=cfg.org,
|
|
323
336
|
project=cfg.project,
|
|
@@ -370,7 +383,7 @@ class RunDetails:
|
|
|
370
383
|
"""
|
|
371
384
|
Rich representation of the Run object.
|
|
372
385
|
"""
|
|
373
|
-
yield from _action_details_rich_repr(self.pb2.action
|
|
386
|
+
yield from _action_details_rich_repr(self.pb2.action)
|
|
374
387
|
|
|
375
388
|
def __repr__(self) -> str:
|
|
376
389
|
"""
|
|
@@ -390,15 +403,14 @@ class Action:
|
|
|
390
403
|
pb2: run_definition_pb2.Action
|
|
391
404
|
_details: ActionDetails | None = None
|
|
392
405
|
|
|
406
|
+
@syncify
|
|
393
407
|
@classmethod
|
|
394
|
-
@requires_client
|
|
395
|
-
@syncer.wrap
|
|
396
408
|
async def listall(
|
|
397
409
|
cls,
|
|
398
410
|
for_run_name: str,
|
|
399
411
|
filters: str | None = None,
|
|
400
412
|
sort_by: Tuple[str, Literal["asc", "desc"]] | None = None,
|
|
401
|
-
) -> Union[Iterator[Action],
|
|
413
|
+
) -> Union[Iterator[Action], AsyncIterator[Action]]:
|
|
402
414
|
"""
|
|
403
415
|
Get all actions for a given run.
|
|
404
416
|
|
|
@@ -407,6 +419,7 @@ class Action:
|
|
|
407
419
|
:param sort_by: The sorting criteria for the project list, in the format (field, order).
|
|
408
420
|
:return: An iterator of projects.
|
|
409
421
|
"""
|
|
422
|
+
ensure_client()
|
|
410
423
|
token = None
|
|
411
424
|
sort_by = sort_by or ("created_at", "asc")
|
|
412
425
|
sort_pb2 = list_pb2.Sort(
|
|
@@ -436,9 +449,8 @@ class Action:
|
|
|
436
449
|
if not token:
|
|
437
450
|
break
|
|
438
451
|
|
|
452
|
+
@syncify
|
|
439
453
|
@classmethod
|
|
440
|
-
@requires_client
|
|
441
|
-
@syncer.wrap
|
|
442
454
|
async def get(cls, uri: str | None = None, /, run_name: str | None = None, name: str | None = None) -> Action:
|
|
443
455
|
"""
|
|
444
456
|
Get a run by its ID or name. If both are provided, the ID will take precedence.
|
|
@@ -447,9 +459,9 @@ class Action:
|
|
|
447
459
|
:param run_name: The name of the action.
|
|
448
460
|
:param name: The name of the action.
|
|
449
461
|
"""
|
|
462
|
+
ensure_client()
|
|
450
463
|
cfg = get_common_config()
|
|
451
464
|
details: ActionDetails = await ActionDetails.get_details.aio(
|
|
452
|
-
cls,
|
|
453
465
|
run_definition_pb2.ActionIdentifier(
|
|
454
466
|
run=run_definition_pb2.RunIdentifier(
|
|
455
467
|
org=cfg.org,
|
|
@@ -476,6 +488,13 @@ class Action:
|
|
|
476
488
|
"""
|
|
477
489
|
return run_definition_pb2.Phase.Name(self.pb2.status.phase)
|
|
478
490
|
|
|
491
|
+
@property
|
|
492
|
+
def raw_phase(self) -> run_definition_pb2.Phase:
|
|
493
|
+
"""
|
|
494
|
+
Get the raw phase of the action.
|
|
495
|
+
"""
|
|
496
|
+
return self.pb2.status.phase
|
|
497
|
+
|
|
479
498
|
@property
|
|
480
499
|
def name(self) -> str:
|
|
481
500
|
"""
|
|
@@ -515,10 +534,12 @@ class Action:
|
|
|
515
534
|
filter_system: bool = False,
|
|
516
535
|
):
|
|
517
536
|
details = await self.details()
|
|
537
|
+
if not details.is_running and not details.done():
|
|
538
|
+
# TODO we can short circuit here if the attempt is not the last one and it is done!
|
|
539
|
+
await self.wait(wait_for="logs-ready")
|
|
540
|
+
details = await self.details()
|
|
518
541
|
if not attempt:
|
|
519
542
|
attempt = details.attempts
|
|
520
|
-
if not details.is_running:
|
|
521
|
-
await self.wait(wait_for="running")
|
|
522
543
|
return await Logs.create_viewer(
|
|
523
544
|
action_id=self.action_id,
|
|
524
545
|
attempt=attempt,
|
|
@@ -533,7 +554,7 @@ class Action:
|
|
|
533
554
|
Get the details of the action. This is a placeholder for getting the action details.
|
|
534
555
|
"""
|
|
535
556
|
if not self._details:
|
|
536
|
-
self._details = await ActionDetails.get_details.aio(
|
|
557
|
+
self._details = await ActionDetails.get_details.aio(self.action_id)
|
|
537
558
|
return cast(ActionDetails, self._details)
|
|
538
559
|
|
|
539
560
|
async def watch(
|
|
@@ -543,14 +564,16 @@ class Action:
|
|
|
543
564
|
Watch the action for updates. This is a placeholder for watching the action.
|
|
544
565
|
"""
|
|
545
566
|
ad = None
|
|
546
|
-
async for ad in ActionDetails.watch.aio(
|
|
567
|
+
async for ad in ActionDetails.watch.aio(self.action_id):
|
|
547
568
|
if ad is None:
|
|
548
569
|
return
|
|
549
570
|
self._details = ad
|
|
550
571
|
yield ad
|
|
551
|
-
if wait_for == "running" and ad.
|
|
572
|
+
if wait_for == "running" and ad.is_running:
|
|
552
573
|
break
|
|
553
|
-
elif wait_for == "
|
|
574
|
+
elif wait_for == "logs-ready" and ad.logs_available():
|
|
575
|
+
break
|
|
576
|
+
if ad.done():
|
|
554
577
|
break
|
|
555
578
|
if cache_data_on_done and ad and ad.done():
|
|
556
579
|
await cast(ActionDetails, self._details).outputs()
|
|
@@ -597,6 +620,10 @@ class Action:
|
|
|
597
620
|
progress.start_task(task_id)
|
|
598
621
|
break
|
|
599
622
|
|
|
623
|
+
if ad.logs_available() and wait_for == "logs-ready":
|
|
624
|
+
progress.start_task(task_id)
|
|
625
|
+
break
|
|
626
|
+
|
|
600
627
|
# Update progress description with the current phase
|
|
601
628
|
progress.update(
|
|
602
629
|
task_id,
|
|
@@ -626,7 +653,7 @@ class Action:
|
|
|
626
653
|
"""
|
|
627
654
|
Check if the action is done.
|
|
628
655
|
"""
|
|
629
|
-
return _action_done_check(self.
|
|
656
|
+
return _action_done_check(self.raw_phase)
|
|
630
657
|
|
|
631
658
|
async def sync(self) -> Action:
|
|
632
659
|
"""
|
|
@@ -638,7 +665,7 @@ class Action:
|
|
|
638
665
|
"""
|
|
639
666
|
Rich representation of the Action object.
|
|
640
667
|
"""
|
|
641
|
-
yield from _action_rich_repr(self.pb2
|
|
668
|
+
yield from _action_rich_repr(self.pb2)
|
|
642
669
|
|
|
643
670
|
def __repr__(self) -> str:
|
|
644
671
|
"""
|
|
@@ -659,13 +686,13 @@ class ActionDetails:
|
|
|
659
686
|
_inputs: ActionInputs | None = None
|
|
660
687
|
_outputs: ActionOutputs | None = None
|
|
661
688
|
|
|
689
|
+
@syncify
|
|
662
690
|
@classmethod
|
|
663
|
-
@requires_client
|
|
664
|
-
@syncer.wrap
|
|
665
691
|
async def get_details(cls, action_id: run_definition_pb2.ActionIdentifier) -> ActionDetails:
|
|
666
692
|
"""
|
|
667
693
|
Get the details of the action. This is a placeholder for getting the action details.
|
|
668
694
|
"""
|
|
695
|
+
ensure_client()
|
|
669
696
|
resp = await get_client().run_service.GetActionDetails(
|
|
670
697
|
run_service_pb2.GetActionDetailsRequest(
|
|
671
698
|
action_id=action_id,
|
|
@@ -673,9 +700,8 @@ class ActionDetails:
|
|
|
673
700
|
)
|
|
674
701
|
return ActionDetails(resp.details)
|
|
675
702
|
|
|
703
|
+
@syncify
|
|
676
704
|
@classmethod
|
|
677
|
-
@requires_client
|
|
678
|
-
@syncer.wrap
|
|
679
705
|
async def get(
|
|
680
706
|
cls, uri: str | None = None, /, run_name: str | None = None, name: str | None = None
|
|
681
707
|
) -> ActionDetails:
|
|
@@ -686,11 +712,11 @@ class ActionDetails:
|
|
|
686
712
|
:param name: The name of the action.
|
|
687
713
|
:param run_name: The name of the run.
|
|
688
714
|
"""
|
|
715
|
+
ensure_client()
|
|
689
716
|
if not uri:
|
|
690
717
|
assert name is not None and run_name is not None, "Either uri or name and run_name must be provided"
|
|
691
718
|
cfg = get_common_config()
|
|
692
719
|
return await cls.get_details.aio(
|
|
693
|
-
cls,
|
|
694
720
|
run_definition_pb2.ActionIdentifier(
|
|
695
721
|
run=run_definition_pb2.RunIdentifier(
|
|
696
722
|
org=cfg.org,
|
|
@@ -702,13 +728,13 @@ class ActionDetails:
|
|
|
702
728
|
),
|
|
703
729
|
)
|
|
704
730
|
|
|
731
|
+
@syncify
|
|
705
732
|
@classmethod
|
|
706
|
-
|
|
707
|
-
@syncer.wrap
|
|
708
|
-
async def watch(cls, action_id: run_definition_pb2.ActionIdentifier) -> AsyncGenerator[ActionDetails, None]:
|
|
733
|
+
async def watch(cls, action_id: run_definition_pb2.ActionIdentifier) -> AsyncIterator[ActionDetails]:
|
|
709
734
|
"""
|
|
710
735
|
Watch the action for updates. This is a placeholder for watching the action.
|
|
711
736
|
"""
|
|
737
|
+
ensure_client()
|
|
712
738
|
if not action_id:
|
|
713
739
|
raise ValueError("Action ID is required")
|
|
714
740
|
|
|
@@ -740,7 +766,7 @@ class ActionDetails:
|
|
|
740
766
|
break
|
|
741
767
|
|
|
742
768
|
if cache_data_on_done and self.done():
|
|
743
|
-
await self._cache_data.aio(
|
|
769
|
+
await self._cache_data.aio()
|
|
744
770
|
|
|
745
771
|
@property
|
|
746
772
|
def phase(self) -> str:
|
|
@@ -749,6 +775,13 @@ class ActionDetails:
|
|
|
749
775
|
"""
|
|
750
776
|
return run_definition_pb2.Phase.Name(self.status.phase)
|
|
751
777
|
|
|
778
|
+
@property
|
|
779
|
+
def raw_phase(self) -> run_definition_pb2.Phase:
|
|
780
|
+
"""
|
|
781
|
+
Get the raw phase of the action.
|
|
782
|
+
"""
|
|
783
|
+
return self.status.phase
|
|
784
|
+
|
|
752
785
|
@property
|
|
753
786
|
def is_running(self) -> bool:
|
|
754
787
|
"""
|
|
@@ -824,7 +857,19 @@ class ActionDetails:
|
|
|
824
857
|
"""
|
|
825
858
|
return self.pb2.status.attempts
|
|
826
859
|
|
|
827
|
-
|
|
860
|
+
def logs_available(self, attempt: int | None = None) -> bool:
|
|
861
|
+
"""
|
|
862
|
+
Check if logs are available for the action, optionally for a specific attempt.
|
|
863
|
+
If attempt is None, it checks for the latest attempt.
|
|
864
|
+
"""
|
|
865
|
+
if attempt is None:
|
|
866
|
+
attempt = self.pb2.status.attempts
|
|
867
|
+
attempts = self.pb2.attempts
|
|
868
|
+
if attempts and len(attempts) >= attempt:
|
|
869
|
+
return attempts[attempt - 1].logs_available
|
|
870
|
+
return False
|
|
871
|
+
|
|
872
|
+
@syncify
|
|
828
873
|
async def _cache_data(self) -> bool:
|
|
829
874
|
"""
|
|
830
875
|
Cache the inputs and outputs of the action.
|
|
@@ -848,7 +893,7 @@ class ActionDetails:
|
|
|
848
893
|
Placeholder for inputs. This can be extended to handle inputs from the run context.
|
|
849
894
|
"""
|
|
850
895
|
if not self._inputs:
|
|
851
|
-
await self._cache_data.aio(
|
|
896
|
+
await self._cache_data.aio()
|
|
852
897
|
return cast(ActionInputs, self._inputs)
|
|
853
898
|
|
|
854
899
|
async def outputs(self) -> ActionOutputs:
|
|
@@ -856,7 +901,7 @@ class ActionDetails:
|
|
|
856
901
|
Placeholder for outputs. This can be extended to handle outputs from the run context.
|
|
857
902
|
"""
|
|
858
903
|
if not self._outputs:
|
|
859
|
-
if not await self._cache_data.aio(
|
|
904
|
+
if not await self._cache_data.aio():
|
|
860
905
|
raise RuntimeError(
|
|
861
906
|
"Action is not in a terminal state, outputs are not available. "
|
|
862
907
|
"Please wait for the action to complete."
|
|
@@ -868,13 +913,13 @@ class ActionDetails:
|
|
|
868
913
|
Check if the action is in a terminal state (completed or failed). This is a placeholder for checking the
|
|
869
914
|
action state.
|
|
870
915
|
"""
|
|
871
|
-
return _action_done_check(self.
|
|
916
|
+
return _action_done_check(self.raw_phase)
|
|
872
917
|
|
|
873
918
|
def __rich_repr__(self) -> rich.repr.Result:
|
|
874
919
|
"""
|
|
875
920
|
Rich representation of the Action object.
|
|
876
921
|
"""
|
|
877
|
-
yield from _action_details_rich_repr(self.pb2
|
|
922
|
+
yield from _action_details_rich_repr(self.pb2)
|
|
878
923
|
|
|
879
924
|
def __repr__(self) -> str:
|
|
880
925
|
"""
|
flyte/remote/_secret.py
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
|
-
from typing import
|
|
4
|
+
from typing import AsyncIterator, Literal, Union
|
|
5
5
|
|
|
6
6
|
import rich.repr
|
|
7
7
|
|
|
8
|
-
from flyte.
|
|
9
|
-
from flyte._initialize import get_client, get_common_config, requires_client
|
|
8
|
+
from flyte._initialize import ensure_client, get_client, get_common_config
|
|
10
9
|
from flyte._protos.secret import definition_pb2, payload_pb2
|
|
10
|
+
from flyte.syncify import syncify
|
|
11
11
|
|
|
12
12
|
SecretTypes = Literal["regular", "image_pull"]
|
|
13
13
|
|
|
@@ -16,10 +16,10 @@ SecretTypes = Literal["regular", "image_pull"]
|
|
|
16
16
|
class Secret:
|
|
17
17
|
pb2: definition_pb2.Secret
|
|
18
18
|
|
|
19
|
+
@syncify
|
|
19
20
|
@classmethod
|
|
20
|
-
@requires_client
|
|
21
|
-
@syncer.wrap
|
|
22
21
|
async def create(cls, name: str, value: Union[str, bytes], type: SecretTypes = "regular"):
|
|
22
|
+
ensure_client()
|
|
23
23
|
cfg = get_common_config()
|
|
24
24
|
secret_type = (
|
|
25
25
|
definition_pb2.SecretType.SECRET_TYPE_GENERIC
|
|
@@ -49,10 +49,10 @@ class Secret:
|
|
|
49
49
|
),
|
|
50
50
|
)
|
|
51
51
|
|
|
52
|
+
@syncify
|
|
52
53
|
@classmethod
|
|
53
|
-
@requires_client
|
|
54
|
-
@syncer.wrap
|
|
55
54
|
async def get(cls, name: str) -> Secret:
|
|
55
|
+
ensure_client()
|
|
56
56
|
cfg = get_common_config()
|
|
57
57
|
resp = await get_client().secrets_service.GetSecret(
|
|
58
58
|
request=payload_pb2.GetSecretRequest(
|
|
@@ -66,10 +66,10 @@ class Secret:
|
|
|
66
66
|
)
|
|
67
67
|
return Secret(pb2=resp.secret)
|
|
68
68
|
|
|
69
|
+
@syncify
|
|
69
70
|
@classmethod
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
async def listall(cls, limit: int = 100) -> Union[Iterator[Secret], AsyncGenerator[Secret, None]]:
|
|
71
|
+
async def listall(cls, limit: int = 100) -> AsyncIterator[Secret]:
|
|
72
|
+
ensure_client()
|
|
73
73
|
cfg = get_common_config()
|
|
74
74
|
token = None
|
|
75
75
|
while True:
|
|
@@ -88,10 +88,10 @@ class Secret:
|
|
|
88
88
|
if not token:
|
|
89
89
|
break
|
|
90
90
|
|
|
91
|
+
@syncify
|
|
91
92
|
@classmethod
|
|
92
|
-
@requires_client
|
|
93
|
-
@syncer.wrap
|
|
94
93
|
async def delete(cls, name):
|
|
94
|
+
ensure_client()
|
|
95
95
|
cfg = get_common_config()
|
|
96
96
|
await get_client().secrets_service.DeleteSecret( # type: ignore
|
|
97
97
|
request=payload_pb2.DeleteSecretRequest(
|
flyte/remote/_task.py
CHANGED
|
@@ -9,11 +9,11 @@ import rich.repr
|
|
|
9
9
|
|
|
10
10
|
import flyte
|
|
11
11
|
import flyte.errors
|
|
12
|
-
from flyte._api_commons import syncer
|
|
13
12
|
from flyte._context import internal_ctx
|
|
14
13
|
from flyte._initialize import get_client, get_common_config
|
|
15
14
|
from flyte._protos.workflow import task_definition_pb2, task_service_pb2
|
|
16
15
|
from flyte.models import NativeInterface
|
|
16
|
+
from flyte.syncify import syncify
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class LazyEntity:
|
|
@@ -32,7 +32,7 @@ class LazyEntity:
|
|
|
32
32
|
def name(self) -> str:
|
|
33
33
|
return self._name
|
|
34
34
|
|
|
35
|
-
@
|
|
35
|
+
@syncify
|
|
36
36
|
async def fetch(self) -> Task:
|
|
37
37
|
"""
|
|
38
38
|
Forwards all other attributes to task, causing the task to be fetched!
|
|
@@ -48,7 +48,7 @@ class LazyEntity:
|
|
|
48
48
|
"""
|
|
49
49
|
Forwards the call to the underlying task. The entity will be fetched if not already present
|
|
50
50
|
"""
|
|
51
|
-
tk = await self.fetch.aio(
|
|
51
|
+
tk = await self.fetch.aio()
|
|
52
52
|
return await tk(*args, **kwargs)
|
|
53
53
|
|
|
54
54
|
def __repr__(self) -> str:
|
flyte/report/_report.py
CHANGED
|
@@ -4,10 +4,10 @@ import string
|
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
5
|
from typing import TYPE_CHECKING, Dict, List, Union
|
|
6
6
|
|
|
7
|
-
from flyte._api_commons import syncer
|
|
8
7
|
from flyte._internal.runtime import io
|
|
9
8
|
from flyte._logging import logger
|
|
10
9
|
from flyte._tools import ipython_check
|
|
10
|
+
from flyte.syncify import syncify
|
|
11
11
|
|
|
12
12
|
if TYPE_CHECKING:
|
|
13
13
|
from IPython.core.display import HTML
|
|
@@ -112,7 +112,7 @@ def get_tab(name: str, /, create_if_missing: bool = True) -> Tab:
|
|
|
112
112
|
return report.get_tab(name, create_if_missing=create_if_missing)
|
|
113
113
|
|
|
114
114
|
|
|
115
|
-
@
|
|
115
|
+
@syncify
|
|
116
116
|
async def log(content: str, do_flush: bool = False):
|
|
117
117
|
"""
|
|
118
118
|
Log content to the main tab. The content should be a valid HTML string, but not a complete HTML document,
|
|
@@ -126,7 +126,7 @@ async def log(content: str, do_flush: bool = False):
|
|
|
126
126
|
await flush.aio()
|
|
127
127
|
|
|
128
128
|
|
|
129
|
-
@
|
|
129
|
+
@syncify
|
|
130
130
|
async def flush():
|
|
131
131
|
"""
|
|
132
132
|
Flush the report.
|
|
@@ -149,7 +149,7 @@ async def flush():
|
|
|
149
149
|
logger.debug(f"Report flushed to {final_path}")
|
|
150
150
|
|
|
151
151
|
|
|
152
|
-
@
|
|
152
|
+
@syncify
|
|
153
153
|
async def replace(content: str, do_flush: bool = False):
|
|
154
154
|
"""
|
|
155
155
|
Get the report. Replaces the content of the main tab.
|