flyte 0.2.0b3__py3-none-any.whl → 0.2.0b5__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.

Files changed (50) hide show
  1. flyte/_build.py +3 -2
  2. flyte/_deploy.py +4 -4
  3. flyte/_initialize.py +17 -3
  4. flyte/_internal/controllers/remote/_core.py +5 -4
  5. flyte/_internal/controllers/remote/_service_protocol.py +6 -6
  6. flyte/_protos/logs/dataplane/payload_pb2.py +28 -24
  7. flyte/_protos/logs/dataplane/payload_pb2.pyi +11 -2
  8. flyte/_protos/workflow/common_pb2.py +27 -0
  9. flyte/_protos/workflow/common_pb2.pyi +14 -0
  10. flyte/_protos/workflow/common_pb2_grpc.py +4 -0
  11. flyte/_protos/workflow/queue_service_pb2.py +39 -41
  12. flyte/_protos/workflow/queue_service_pb2.pyi +30 -28
  13. flyte/_protos/workflow/queue_service_pb2_grpc.py +15 -15
  14. flyte/_protos/workflow/run_definition_pb2.py +14 -14
  15. flyte/_protos/workflow/run_definition_pb2.pyi +4 -2
  16. flyte/_protos/workflow/task_definition_pb2.py +14 -13
  17. flyte/_protos/workflow/task_definition_pb2.pyi +7 -3
  18. flyte/_run.py +7 -5
  19. flyte/_trace.py +1 -6
  20. flyte/_version.py +2 -2
  21. flyte/cli/__init__.py +10 -0
  22. flyte/cli/_abort.py +26 -0
  23. flyte/{_cli → cli}/_common.py +2 -0
  24. flyte/{_cli → cli}/_create.py +1 -1
  25. flyte/{_cli → cli}/_delete.py +1 -1
  26. flyte/{_cli → cli}/_get.py +12 -3
  27. flyte/{_cli → cli}/_run.py +49 -16
  28. flyte/{_cli → cli}/main.py +10 -1
  29. flyte/config/_config.py +2 -0
  30. flyte/errors.py +9 -0
  31. flyte/io/_dir.py +2 -2
  32. flyte/io/_file.py +1 -4
  33. flyte/remote/_data.py +3 -3
  34. flyte/remote/_logs.py +80 -27
  35. flyte/remote/_project.py +8 -9
  36. flyte/remote/_run.py +194 -107
  37. flyte/remote/_secret.py +12 -12
  38. flyte/remote/_task.py +3 -3
  39. flyte/report/_report.py +4 -4
  40. flyte/syncify/__init__.py +5 -0
  41. flyte/syncify/_api.py +277 -0
  42. {flyte-0.2.0b3.dist-info → flyte-0.2.0b5.dist-info}/METADATA +2 -3
  43. {flyte-0.2.0b3.dist-info → flyte-0.2.0b5.dist-info}/RECORD +48 -43
  44. {flyte-0.2.0b3.dist-info → flyte-0.2.0b5.dist-info}/entry_points.txt +1 -1
  45. flyte/_api_commons.py +0 -3
  46. flyte/_cli/__init__.py +0 -0
  47. /flyte/{_cli → cli}/_deploy.py +0 -0
  48. /flyte/{_cli → cli}/_params.py +0 -0
  49. {flyte-0.2.0b3.dist-info → flyte-0.2.0b5.dist-info}/WHEEL +0 -0
  50. {flyte-0.2.0b3.dist-info → flyte-0.2.0b5.dist-info}/top_level.txt +0 -0
flyte/remote/_run.py CHANGED
@@ -11,15 +11,17 @@ 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._api_commons import syncer
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", "logs-ready"]
24
+
23
25
 
24
26
  def _action_time_phase(action: run_definition_pb2.Action | run_definition_pb2.ActionDetails) -> rich.repr.Result:
25
27
  """
@@ -104,14 +106,13 @@ class Run:
104
106
  raise RuntimeError("Run does not have an action")
105
107
  self.action = Action(self.pb2.action)
106
108
 
109
+ @syncify
107
110
  @classmethod
108
- @requires_client
109
- @syncer.wrap
110
111
  async def listall(
111
112
  cls,
112
113
  filters: str | None = None,
113
114
  sort_by: Tuple[str, Literal["asc", "desc"]] | None = None,
114
- ) -> Union[Iterator[Run], AsyncGenerator[Run, None]]:
115
+ ) -> AsyncIterator[Run]:
115
116
  """
116
117
  Get all runs for the current project and domain.
117
118
 
@@ -119,6 +120,7 @@ class Run:
119
120
  :param sort_by: The sorting criteria for the project list, in the format (field, order).
120
121
  :return: An iterator of runs.
121
122
  """
123
+ ensure_client()
122
124
  token = None
123
125
  sort_by = sort_by or ("created_at", "asc")
124
126
  sort_pb2 = list_pb2.Sort(
@@ -148,16 +150,16 @@ class Run:
148
150
  if not token:
149
151
  break
150
152
 
153
+ @syncify
151
154
  @classmethod
152
- @requires_client
153
- @syncer.wrap
154
155
  async def get(cls, name: str) -> Run:
155
156
  """
156
157
  Get the current run.
157
158
 
158
159
  :return: The current run.
159
160
  """
160
- run_details: RunDetails = await RunDetails.get.aio(RunDetails, name=name)
161
+ ensure_client()
162
+ run_details: RunDetails = await RunDetails.get.aio(name=name)
161
163
  run = run_definition_pb2.Run(
162
164
  action=run_definition_pb2.Action(
163
165
  id=run_details.action_id,
@@ -179,74 +181,38 @@ class Run:
179
181
  """
180
182
  Get the phase of the run.
181
183
  """
182
- return run_definition_pb2.Phase.Name(self.action.phase)
184
+ return self.action.phase
185
+
186
+ @property
187
+ def raw_phase(self) -> run_definition_pb2.Phase:
188
+ """
189
+ Get the raw phase of the run.
190
+ """
191
+ return self.action.raw_phase
183
192
 
184
- @syncer.wrap
185
- async def wait(self, quiet: bool = False) -> None:
193
+ @syncify
194
+ async def wait(self, quiet: bool = False, wait_for: Literal["terminal", "running"] = "terminal") -> None:
186
195
  """
187
196
  Wait for the run to complete, displaying a rich progress panel with status transitions,
188
197
  time elapsed, and error details in case of failure.
189
198
  """
190
- console = Console()
191
- if self.done():
192
- if not quiet:
193
- console.print(f"[bold green]Run '{self.name}' is already completed.[/bold green]")
194
- return
195
-
196
- try:
197
- with Progress(
198
- SpinnerColumn(),
199
- TextColumn("[progress.description]{task.description}"),
200
- TimeElapsedColumn(),
201
- console=console,
202
- transient=True,
203
- disable=quiet,
204
- ) as progress:
205
- task_id = progress.add_task(f"Waiting for run '{self.name}'...", start=False)
206
-
207
- async for ad in self.watch(cache_data_on_done=True):
208
- if ad is None:
209
- break
210
-
211
- # Update progress description with the current phase
212
- progress.update(
213
- task_id,
214
- description=f"Run: {self.name} in {ad.phase}, Runtime: {ad.runtime} secs "
215
- f"Attempts[{ad.attempts}]",
216
- )
217
- progress.start_task(task_id)
218
-
219
- # If the action is done, handle the final state
220
- if ad.done():
221
- progress.stop_task(task_id)
222
- if ad.pb2.status.phase == run_definition_pb2.PHASE_SUCCEEDED:
223
- console.print(f"[bold green]Run '{self.name}' completed successfully.[/bold green]")
224
- else:
225
- console.print(
226
- f"[bold red]Run '{self.name}' exited unsuccessfully in state {ad.phase}"
227
- f"with error: {ad.error_info}[/bold red]"
228
- )
229
- break
230
- except asyncio.CancelledError:
231
- # Handle cancellation gracefully
232
- pass
233
- except KeyboardInterrupt:
234
- # Handle keyboard interrupt gracefully
235
- console.print(f"\n[bold yellow]Run '{self.name}' was interrupted.[/bold yellow]")
199
+ return await self.action.wait(quiet=quiet, wait_for=wait_for)
236
200
 
237
201
  async def watch(self, cache_data_on_done: bool = False) -> AsyncGenerator[ActionDetails, None]:
238
202
  """
239
203
  Get the details of the run. This is a placeholder for getting the run details.
240
204
  """
241
- async for ad in self.action.watch_details(cache_data_on_done=cache_data_on_done):
242
- if ad is None:
243
- return
244
- yield ad
205
+ return self.action.watch(cache_data_on_done=cache_data_on_done)
245
206
 
246
207
  async def show_logs(
247
- self, attempt: int | None = None, max_lines: int = 100, show_ts: bool = False, raw: bool = False
208
+ self,
209
+ attempt: int | None = None,
210
+ max_lines: int = 100,
211
+ show_ts: bool = False,
212
+ raw: bool = False,
213
+ filter_system: bool = False,
248
214
  ):
249
- await self.action.show_logs(attempt, max_lines, show_ts, raw)
215
+ await self.action.show_logs(attempt, max_lines, show_ts, raw, filter_system=filter_system)
250
216
 
251
217
  async def details(self) -> RunDetails:
252
218
  """
@@ -257,7 +223,6 @@ class Run:
257
223
  return self._details
258
224
 
259
225
  @property
260
- @requires_client
261
226
  def url(self) -> str:
262
227
  """
263
228
  Get the URL of the run.
@@ -271,16 +236,21 @@ class Run:
271
236
  run_name=self.name,
272
237
  )
273
238
 
274
- @syncer.wrap
275
- async def cancel(self) -> None:
239
+ @syncify
240
+ async def abort(self):
276
241
  """
277
- Cancel the run.
242
+ Aborts / Terminates the run.
278
243
  """
279
- await get_client().run_service.AbortRun(
280
- run_service_pb2.AbortRunRequest(
281
- run_id=self.pb2.action.id.run,
244
+ try:
245
+ await get_client().run_service.AbortRun(
246
+ run_service_pb2.AbortRunRequest(
247
+ run_id=self.pb2.action.id.run,
248
+ )
282
249
  )
283
- )
250
+ except grpc.aio.AioRpcError as e:
251
+ if e.code() == grpc.StatusCode.NOT_FOUND:
252
+ return
253
+ raise
284
254
 
285
255
  def done(self) -> bool:
286
256
  """
@@ -327,13 +297,13 @@ class RunDetails:
327
297
  """
328
298
  self.action_details = ActionDetails(self.pb2.action)
329
299
 
300
+ @syncify
330
301
  @classmethod
331
- @requires_client
332
- @syncer.wrap
333
302
  async def get_details(cls, run_id: run_definition_pb2.RunIdentifier) -> RunDetails:
334
303
  """
335
304
  Get the details of the run. This is a placeholder for getting the run details.
336
305
  """
306
+ ensure_client()
337
307
  resp = await get_client().run_service.GetRunDetails(
338
308
  run_service_pb2.GetRunDetailsRequest(
339
309
  run_id=run_id,
@@ -341,9 +311,8 @@ class RunDetails:
341
311
  )
342
312
  return cls(resp.details)
343
313
 
314
+ @syncify
344
315
  @classmethod
345
- @requires_client
346
- @syncer.wrap
347
316
  async def get(cls, name: str | None = None) -> RunDetails:
348
317
  """
349
318
  Get a run by its ID or name. If both are provided, the ID will take precedence.
@@ -351,9 +320,9 @@ class RunDetails:
351
320
  :param uri: The URI of the run.
352
321
  :param name: The name of the run.
353
322
  """
323
+ ensure_client()
354
324
  cfg = get_common_config()
355
325
  return await RunDetails.get_details.aio(
356
- cls,
357
326
  run_id=run_definition_pb2.RunIdentifier(
358
327
  org=cfg.org,
359
328
  project=cfg.project,
@@ -426,15 +395,14 @@ class Action:
426
395
  pb2: run_definition_pb2.Action
427
396
  _details: ActionDetails | None = None
428
397
 
398
+ @syncify
429
399
  @classmethod
430
- @requires_client
431
- @syncer.wrap
432
400
  async def listall(
433
401
  cls,
434
402
  for_run_name: str,
435
403
  filters: str | None = None,
436
404
  sort_by: Tuple[str, Literal["asc", "desc"]] | None = None,
437
- ) -> Union[Iterator[Action], AsyncGenerator[Action, None]]:
405
+ ) -> Union[Iterator[Action], AsyncIterator[Action]]:
438
406
  """
439
407
  Get all actions for a given run.
440
408
 
@@ -443,6 +411,7 @@ class Action:
443
411
  :param sort_by: The sorting criteria for the project list, in the format (field, order).
444
412
  :return: An iterator of projects.
445
413
  """
414
+ ensure_client()
446
415
  token = None
447
416
  sort_by = sort_by or ("created_at", "asc")
448
417
  sort_pb2 = list_pb2.Sort(
@@ -472,9 +441,8 @@ class Action:
472
441
  if not token:
473
442
  break
474
443
 
444
+ @syncify
475
445
  @classmethod
476
- @requires_client
477
- @syncer.wrap
478
446
  async def get(cls, uri: str | None = None, /, run_name: str | None = None, name: str | None = None) -> Action:
479
447
  """
480
448
  Get a run by its ID or name. If both are provided, the ID will take precedence.
@@ -483,9 +451,9 @@ class Action:
483
451
  :param run_name: The name of the action.
484
452
  :param name: The name of the action.
485
453
  """
454
+ ensure_client()
486
455
  cfg = get_common_config()
487
456
  details: ActionDetails = await ActionDetails.get_details.aio(
488
- cls,
489
457
  run_definition_pb2.ActionIdentifier(
490
458
  run=run_definition_pb2.RunIdentifier(
491
459
  org=cfg.org,
@@ -512,6 +480,13 @@ class Action:
512
480
  """
513
481
  return run_definition_pb2.Phase.Name(self.pb2.status.phase)
514
482
 
483
+ @property
484
+ def raw_phase(self) -> run_definition_pb2.Phase:
485
+ """
486
+ Get the raw phase of the action.
487
+ """
488
+ return self.pb2.status.phase
489
+
515
490
  @property
516
491
  def name(self) -> str:
517
492
  """
@@ -543,19 +518,27 @@ class Action:
543
518
  return self.pb2.id
544
519
 
545
520
  async def show_logs(
546
- self, attempt: int | None = None, max_lines: int = 30, show_ts: bool = False, raw: bool = False
521
+ self,
522
+ attempt: int | None = None,
523
+ max_lines: int = 30,
524
+ show_ts: bool = False,
525
+ raw: bool = False,
526
+ filter_system: bool = False,
547
527
  ):
548
528
  details = await self.details()
529
+ if not details.is_running and not details.done():
530
+ # TODO we can short circuit here if the attempt is not the last one and it is done!
531
+ await self.wait(wait_for="logs-ready")
532
+ details = await self.details()
549
533
  if not attempt:
550
534
  attempt = details.attempts
551
- if details.phase in [
552
- run_definition_pb2.PHASE_QUEUED,
553
- run_definition_pb2.PHASE_INITIALIZING,
554
- run_definition_pb2.PHASE_WAITING_FOR_RESOURCES,
555
- ]:
556
- raise RuntimeError("Action has not yet started, so logs are not available.")
557
535
  return await Logs.create_viewer(
558
- action_id=self.action_id, attempt=attempt, max_lines=max_lines, show_ts=show_ts, raw=raw
536
+ action_id=self.action_id,
537
+ attempt=attempt,
538
+ max_lines=max_lines,
539
+ show_ts=show_ts,
540
+ raw=raw,
541
+ filter_system=filter_system,
559
542
  )
560
543
 
561
544
  async def details(self) -> ActionDetails:
@@ -563,27 +546,106 @@ class Action:
563
546
  Get the details of the action. This is a placeholder for getting the action details.
564
547
  """
565
548
  if not self._details:
566
- self._details = await ActionDetails.get_details.aio(ActionDetails, self.action_id)
549
+ self._details = await ActionDetails.get_details.aio(self.action_id)
567
550
  return cast(ActionDetails, self._details)
568
551
 
569
- async def watch_details(self, cache_data_on_done: bool = False) -> AsyncGenerator[ActionDetails, None]:
552
+ async def watch(
553
+ self, cache_data_on_done: bool = False, wait_for: WaitFor = "terminal"
554
+ ) -> AsyncGenerator[ActionDetails, None]:
570
555
  """
571
556
  Watch the action for updates. This is a placeholder for watching the action.
572
557
  """
573
558
  ad = None
574
- async for ad in ActionDetails.watch.aio(ActionDetails, self.action_id):
559
+ async for ad in ActionDetails.watch.aio(self.action_id):
575
560
  if ad is None:
576
561
  return
577
562
  self._details = ad
578
563
  yield ad
564
+ if wait_for == "running" and ad.is_running:
565
+ break
566
+ elif wait_for == "logs-ready" and ad.logs_available():
567
+ break
568
+ if ad.done():
569
+ break
579
570
  if cache_data_on_done and ad and ad.done():
580
571
  await cast(ActionDetails, self._details).outputs()
581
572
 
573
+ async def wait(self, quiet: bool = False, wait_for: WaitFor = "terminal") -> None:
574
+ """
575
+ Wait for the run to complete, displaying a rich progress panel with status transitions,
576
+ time elapsed, and error details in case of failure.
577
+ """
578
+ console = Console()
579
+ if self.done():
580
+ if not quiet:
581
+ if self.pb2.status.phase == run_definition_pb2.PHASE_SUCCEEDED:
582
+ console.print(
583
+ f"[bold green]Action '{self.name}' in Run '{self.run_name}'"
584
+ f" completed successfully.[/bold green]"
585
+ )
586
+ else:
587
+ details = await self.details()
588
+ console.print(
589
+ f"[bold red]Action '{self.name}' in Run '{self.run_name}'"
590
+ f" exited unsuccessfully in state {self.phase} with error: {details.error_info}[/bold red]"
591
+ )
592
+ return
593
+
594
+ try:
595
+ with Progress(
596
+ SpinnerColumn(),
597
+ TextColumn("[progress.description]{task.description}"),
598
+ TimeElapsedColumn(),
599
+ console=console,
600
+ transient=True,
601
+ disable=quiet,
602
+ ) as progress:
603
+ task_id = progress.add_task(f"Waiting for run '{self.name}'...", start=False)
604
+ progress.start_task(task_id)
605
+
606
+ async for ad in self.watch(cache_data_on_done=True, wait_for=wait_for):
607
+ if ad is None:
608
+ progress.stop_task(task_id)
609
+ break
610
+
611
+ if ad.is_running and wait_for == "running":
612
+ progress.start_task(task_id)
613
+ break
614
+
615
+ if ad.logs_available() and wait_for == "logs-ready":
616
+ progress.start_task(task_id)
617
+ break
618
+
619
+ # Update progress description with the current phase
620
+ progress.update(
621
+ task_id,
622
+ description=f"Run: {self.name} in {ad.phase}, Runtime: {ad.runtime} secs "
623
+ f"Attempts[{ad.attempts}]",
624
+ )
625
+
626
+ # If the action is done, handle the final state
627
+ if ad.done():
628
+ progress.stop_task(task_id)
629
+ if ad.pb2.status.phase == run_definition_pb2.PHASE_SUCCEEDED:
630
+ console.print(f"[bold green]Run '{self.name}' completed successfully.[/bold green]")
631
+ else:
632
+ console.print(
633
+ f"[bold red]Run '{self.name}' exited unsuccessfully in state {ad.phase}"
634
+ f"with error: {ad.error_info}[/bold red]"
635
+ )
636
+ break
637
+ except asyncio.CancelledError:
638
+ # Handle cancellation gracefully
639
+ pass
640
+ except KeyboardInterrupt:
641
+ # Handle keyboard interrupt gracefully
642
+ pass
643
+
582
644
  def done(self) -> bool:
583
645
  """
584
646
  Check if the action is done.
585
647
  """
586
- return _action_done_check(self.pb2.status.phase)
648
+ return _action_done_check(self.raw_phase)
587
649
 
588
650
  async def sync(self) -> Action:
589
651
  """
@@ -616,13 +678,13 @@ class ActionDetails:
616
678
  _inputs: ActionInputs | None = None
617
679
  _outputs: ActionOutputs | None = None
618
680
 
681
+ @syncify
619
682
  @classmethod
620
- @requires_client
621
- @syncer.wrap
622
683
  async def get_details(cls, action_id: run_definition_pb2.ActionIdentifier) -> ActionDetails:
623
684
  """
624
685
  Get the details of the action. This is a placeholder for getting the action details.
625
686
  """
687
+ ensure_client()
626
688
  resp = await get_client().run_service.GetActionDetails(
627
689
  run_service_pb2.GetActionDetailsRequest(
628
690
  action_id=action_id,
@@ -630,9 +692,8 @@ class ActionDetails:
630
692
  )
631
693
  return ActionDetails(resp.details)
632
694
 
695
+ @syncify
633
696
  @classmethod
634
- @requires_client
635
- @syncer.wrap
636
697
  async def get(
637
698
  cls, uri: str | None = None, /, run_name: str | None = None, name: str | None = None
638
699
  ) -> ActionDetails:
@@ -643,11 +704,11 @@ class ActionDetails:
643
704
  :param name: The name of the action.
644
705
  :param run_name: The name of the run.
645
706
  """
707
+ ensure_client()
646
708
  if not uri:
647
709
  assert name is not None and run_name is not None, "Either uri or name and run_name must be provided"
648
710
  cfg = get_common_config()
649
711
  return await cls.get_details.aio(
650
- cls,
651
712
  run_definition_pb2.ActionIdentifier(
652
713
  run=run_definition_pb2.RunIdentifier(
653
714
  org=cfg.org,
@@ -659,13 +720,13 @@ class ActionDetails:
659
720
  ),
660
721
  )
661
722
 
723
+ @syncify
662
724
  @classmethod
663
- @requires_client
664
- @syncer.wrap
665
- async def watch(cls, action_id: run_definition_pb2.ActionIdentifier) -> AsyncGenerator[ActionDetails, None]:
725
+ async def watch(cls, action_id: run_definition_pb2.ActionIdentifier) -> AsyncIterator[ActionDetails]:
666
726
  """
667
727
  Watch the action for updates. This is a placeholder for watching the action.
668
728
  """
729
+ ensure_client()
669
730
  if not action_id:
670
731
  raise ValueError("Action ID is required")
671
732
 
@@ -697,7 +758,7 @@ class ActionDetails:
697
758
  break
698
759
 
699
760
  if cache_data_on_done and self.done():
700
- await self._cache_data.aio(self)
761
+ await self._cache_data.aio()
701
762
 
702
763
  @property
703
764
  def phase(self) -> str:
@@ -706,6 +767,20 @@ class ActionDetails:
706
767
  """
707
768
  return run_definition_pb2.Phase.Name(self.status.phase)
708
769
 
770
+ @property
771
+ def raw_phase(self) -> run_definition_pb2.Phase:
772
+ """
773
+ Get the raw phase of the action.
774
+ """
775
+ return self.status.phase
776
+
777
+ @property
778
+ def is_running(self) -> bool:
779
+ """
780
+ Check if the action is currently running.
781
+ """
782
+ return self.status.phase == run_definition_pb2.PHASE_RUNNING
783
+
709
784
  @property
710
785
  def name(self) -> str:
711
786
  """
@@ -774,7 +849,19 @@ class ActionDetails:
774
849
  """
775
850
  return self.pb2.status.attempts
776
851
 
777
- @syncer.wrap
852
+ def logs_available(self, attempt: int | None = None) -> bool:
853
+ """
854
+ Check if logs are available for the action, optionally for a specific attempt.
855
+ If attempt is None, it checks for the latest attempt.
856
+ """
857
+ if attempt is None:
858
+ attempt = self.pb2.status.attempts
859
+ attempts = self.pb2.attempts
860
+ if attempts and len(attempts) >= attempt:
861
+ return attempts[attempt - 1].logs_available
862
+ return False
863
+
864
+ @syncify
778
865
  async def _cache_data(self) -> bool:
779
866
  """
780
867
  Cache the inputs and outputs of the action.
@@ -798,7 +885,7 @@ class ActionDetails:
798
885
  Placeholder for inputs. This can be extended to handle inputs from the run context.
799
886
  """
800
887
  if not self._inputs:
801
- await self._cache_data.aio(self)
888
+ await self._cache_data.aio()
802
889
  return cast(ActionInputs, self._inputs)
803
890
 
804
891
  async def outputs(self) -> ActionOutputs:
@@ -806,7 +893,7 @@ class ActionDetails:
806
893
  Placeholder for outputs. This can be extended to handle outputs from the run context.
807
894
  """
808
895
  if not self._outputs:
809
- if not await self._cache_data.aio(self):
896
+ if not await self._cache_data.aio():
810
897
  raise RuntimeError(
811
898
  "Action is not in a terminal state, outputs are not available. "
812
899
  "Please wait for the action to complete."
@@ -818,7 +905,7 @@ class ActionDetails:
818
905
  Check if the action is in a terminal state (completed or failed). This is a placeholder for checking the
819
906
  action state.
820
907
  """
821
- return _action_done_check(self.pb2.status.phase)
908
+ return _action_done_check(self.raw_phase)
822
909
 
823
910
  def __rich_repr__(self) -> rich.repr.Result:
824
911
  """
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 AsyncGenerator, Iterator, Literal, Union
4
+ from typing import AsyncIterator, Literal, Union
5
5
 
6
6
  import rich.repr
7
7
 
8
- from flyte._api_commons import syncer
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
- @requires_client
71
- @syncer.wrap
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
- @syncer.wrap
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(self)
51
+ tk = await self.fetch.aio()
52
52
  return await tk(*args, **kwargs)
53
53
 
54
54
  def __repr__(self) -> str: