prefect-client 3.1.11__py3-none-any.whl → 3.1.13__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.
Files changed (133) hide show
  1. prefect/_experimental/sla/__init__.py +0 -0
  2. prefect/_experimental/sla/client.py +92 -0
  3. prefect/_experimental/sla/objects.py +61 -0
  4. prefect/_internal/concurrency/services.py +2 -2
  5. prefect/_internal/concurrency/threads.py +6 -0
  6. prefect/_internal/retries.py +6 -3
  7. prefect/_internal/schemas/validators.py +6 -4
  8. prefect/_version.py +3 -3
  9. prefect/artifacts.py +4 -1
  10. prefect/automations.py +236 -30
  11. prefect/blocks/__init__.py +3 -3
  12. prefect/blocks/abstract.py +57 -31
  13. prefect/blocks/core.py +181 -82
  14. prefect/blocks/notifications.py +134 -73
  15. prefect/blocks/redis.py +13 -9
  16. prefect/blocks/system.py +24 -11
  17. prefect/blocks/webhook.py +7 -5
  18. prefect/cache_policies.py +23 -22
  19. prefect/client/orchestration/__init__.py +103 -2006
  20. prefect/client/orchestration/_automations/__init__.py +0 -0
  21. prefect/client/orchestration/_automations/client.py +329 -0
  22. prefect/client/orchestration/_blocks_documents/__init__.py +0 -0
  23. prefect/client/orchestration/_blocks_documents/client.py +334 -0
  24. prefect/client/orchestration/_blocks_schemas/__init__.py +0 -0
  25. prefect/client/orchestration/_blocks_schemas/client.py +200 -0
  26. prefect/client/orchestration/_blocks_types/__init__.py +0 -0
  27. prefect/client/orchestration/_blocks_types/client.py +380 -0
  28. prefect/client/orchestration/_deployments/__init__.py +0 -0
  29. prefect/client/orchestration/_deployments/client.py +1128 -0
  30. prefect/client/orchestration/_flow_runs/__init__.py +0 -0
  31. prefect/client/orchestration/_flow_runs/client.py +903 -0
  32. prefect/client/orchestration/_flows/__init__.py +0 -0
  33. prefect/client/orchestration/_flows/client.py +343 -0
  34. prefect/client/orchestration/_logs/client.py +16 -14
  35. prefect/client/schemas/__init__.py +68 -28
  36. prefect/client/schemas/objects.py +5 -5
  37. prefect/client/utilities.py +3 -3
  38. prefect/context.py +15 -1
  39. prefect/deployments/base.py +13 -4
  40. prefect/deployments/flow_runs.py +5 -1
  41. prefect/deployments/runner.py +37 -1
  42. prefect/deployments/steps/core.py +1 -1
  43. prefect/deployments/steps/pull.py +8 -3
  44. prefect/deployments/steps/utility.py +2 -2
  45. prefect/docker/docker_image.py +13 -9
  46. prefect/engine.py +33 -11
  47. prefect/events/cli/automations.py +4 -4
  48. prefect/events/clients.py +17 -14
  49. prefect/events/schemas/automations.py +12 -8
  50. prefect/events/schemas/events.py +5 -1
  51. prefect/events/worker.py +1 -1
  52. prefect/filesystems.py +7 -3
  53. prefect/flow_engine.py +64 -47
  54. prefect/flows.py +128 -74
  55. prefect/futures.py +14 -7
  56. prefect/infrastructure/provisioners/__init__.py +2 -0
  57. prefect/infrastructure/provisioners/cloud_run.py +4 -4
  58. prefect/infrastructure/provisioners/coiled.py +249 -0
  59. prefect/infrastructure/provisioners/container_instance.py +4 -3
  60. prefect/infrastructure/provisioners/ecs.py +55 -43
  61. prefect/infrastructure/provisioners/modal.py +5 -4
  62. prefect/input/actions.py +5 -1
  63. prefect/input/run_input.py +157 -43
  64. prefect/logging/configuration.py +3 -3
  65. prefect/logging/filters.py +2 -2
  66. prefect/logging/formatters.py +15 -11
  67. prefect/logging/handlers.py +24 -14
  68. prefect/logging/highlighters.py +5 -5
  69. prefect/logging/loggers.py +28 -18
  70. prefect/logging/logging.yml +1 -1
  71. prefect/main.py +3 -1
  72. prefect/results.py +166 -86
  73. prefect/runner/runner.py +38 -29
  74. prefect/runner/server.py +3 -1
  75. prefect/runner/storage.py +18 -18
  76. prefect/runner/submit.py +19 -12
  77. prefect/runtime/deployment.py +15 -8
  78. prefect/runtime/flow_run.py +19 -6
  79. prefect/runtime/task_run.py +7 -3
  80. prefect/settings/base.py +17 -7
  81. prefect/settings/legacy.py +4 -4
  82. prefect/settings/models/api.py +4 -3
  83. prefect/settings/models/cli.py +4 -3
  84. prefect/settings/models/client.py +7 -4
  85. prefect/settings/models/cloud.py +9 -3
  86. prefect/settings/models/deployments.py +4 -3
  87. prefect/settings/models/experiments.py +4 -8
  88. prefect/settings/models/flows.py +4 -3
  89. prefect/settings/models/internal.py +4 -3
  90. prefect/settings/models/logging.py +8 -6
  91. prefect/settings/models/results.py +4 -3
  92. prefect/settings/models/root.py +11 -16
  93. prefect/settings/models/runner.py +8 -5
  94. prefect/settings/models/server/api.py +6 -3
  95. prefect/settings/models/server/database.py +120 -25
  96. prefect/settings/models/server/deployments.py +4 -3
  97. prefect/settings/models/server/ephemeral.py +7 -4
  98. prefect/settings/models/server/events.py +6 -3
  99. prefect/settings/models/server/flow_run_graph.py +4 -3
  100. prefect/settings/models/server/root.py +4 -3
  101. prefect/settings/models/server/services.py +15 -12
  102. prefect/settings/models/server/tasks.py +7 -4
  103. prefect/settings/models/server/ui.py +4 -3
  104. prefect/settings/models/tasks.py +10 -5
  105. prefect/settings/models/testing.py +4 -3
  106. prefect/settings/models/worker.py +7 -4
  107. prefect/settings/profiles.py +13 -12
  108. prefect/settings/sources.py +20 -19
  109. prefect/states.py +74 -51
  110. prefect/task_engine.py +43 -33
  111. prefect/task_runners.py +85 -72
  112. prefect/task_runs.py +20 -11
  113. prefect/task_worker.py +14 -9
  114. prefect/tasks.py +36 -28
  115. prefect/telemetry/bootstrap.py +13 -9
  116. prefect/telemetry/run_telemetry.py +15 -13
  117. prefect/telemetry/services.py +4 -0
  118. prefect/transactions.py +3 -3
  119. prefect/types/__init__.py +3 -1
  120. prefect/utilities/_deprecated.py +38 -0
  121. prefect/utilities/engine.py +11 -4
  122. prefect/utilities/filesystem.py +2 -2
  123. prefect/utilities/generics.py +1 -1
  124. prefect/utilities/pydantic.py +21 -36
  125. prefect/utilities/templating.py +25 -1
  126. prefect/workers/base.py +58 -33
  127. prefect/workers/process.py +20 -15
  128. prefect/workers/server.py +4 -5
  129. {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/METADATA +3 -3
  130. {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/RECORD +133 -114
  131. {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/LICENSE +0 -0
  132. {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/WHEEL +0 -0
  133. {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/top_level.txt +0 -0
prefect/states.py CHANGED
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import asyncio
2
4
  import datetime
3
5
  import sys
@@ -6,7 +8,7 @@ import uuid
6
8
  import warnings
7
9
  from collections import Counter
8
10
  from types import GeneratorType, TracebackType
9
- from typing import Any, Dict, Iterable, Optional, Type
11
+ from typing import TYPE_CHECKING, Any, Dict, Iterable, Optional, Type
10
12
 
11
13
  import anyio
12
14
  import httpx
@@ -28,17 +30,19 @@ from prefect.exceptions import (
28
30
  UnfinishedRun,
29
31
  )
30
32
  from prefect.logging.loggers import get_logger, get_run_logger
31
- from prefect.results import (
32
- R,
33
- ResultRecord,
34
- ResultRecordMetadata,
35
- ResultStore,
36
- )
37
33
  from prefect.utilities.annotations import BaseAnnotation
38
34
  from prefect.utilities.asyncutils import in_async_main_thread, sync_compatible
39
35
  from prefect.utilities.collections import ensure_iterable
40
36
 
41
- logger = get_logger("states")
37
+ if TYPE_CHECKING:
38
+ import logging
39
+
40
+ from prefect.results import (
41
+ R,
42
+ ResultStore,
43
+ )
44
+
45
+ logger: "logging.Logger" = get_logger("states")
42
46
 
43
47
 
44
48
  @deprecated.deprecated_parameter(
@@ -49,11 +53,11 @@ logger = get_logger("states")
49
53
  help="Please ensure you are awaiting the call to `result()` when calling in an async context.",
50
54
  )
51
55
  def get_state_result(
52
- state: State[R],
56
+ state: "State[R]",
53
57
  raise_on_failure: bool = True,
54
58
  fetch: bool = True,
55
59
  retry_result_failure: bool = True,
56
- ) -> R:
60
+ ) -> "R":
57
61
  """
58
62
  Get the result from a state.
59
63
 
@@ -86,13 +90,18 @@ RESULT_READ_RETRY_DELAY = 0.25
86
90
 
87
91
 
88
92
  async def _get_state_result_data_with_retries(
89
- state: State[R], retry_result_failure: bool = True
90
- ) -> R:
93
+ state: "State[R]", retry_result_failure: bool = True
94
+ ) -> "R":
91
95
  # Results may be written asynchronously, possibly after their corresponding
92
96
  # state has been written and events have been emitted, so we should give some
93
97
  # grace here about missing results. The exception below could come in the form
94
98
  # of a missing file, a short read, or other types of errors depending on the
95
99
  # result storage backend.
100
+ from prefect.results import (
101
+ ResultRecord,
102
+ ResultRecordMetadata,
103
+ )
104
+
96
105
  if retry_result_failure is False:
97
106
  max_attempts = 1
98
107
  else:
@@ -120,11 +129,16 @@ async def _get_state_result_data_with_retries(
120
129
 
121
130
  @sync_compatible
122
131
  async def _get_state_result(
123
- state: State[R], raise_on_failure: bool, retry_result_failure: bool = True
124
- ) -> R:
132
+ state: "State[R]", raise_on_failure: bool, retry_result_failure: bool = True
133
+ ) -> "R":
125
134
  """
126
135
  Internal implementation for `get_state_result` without async backwards compatibility
127
136
  """
137
+ from prefect.results import (
138
+ ResultRecord,
139
+ ResultRecordMetadata,
140
+ )
141
+
128
142
  if state.is_paused():
129
143
  # Paused states are not truly terminal and do not have results associated with them
130
144
  raise PausedRun("Run is paused, its result is not available.", state=state)
@@ -181,7 +195,7 @@ def format_exception(exc: BaseException, tb: TracebackType = None) -> str:
181
195
 
182
196
  async def exception_to_crashed_state(
183
197
  exc: BaseException,
184
- result_store: Optional[ResultStore] = None,
198
+ result_store: Optional["ResultStore"] = None,
185
199
  ) -> State:
186
200
  """
187
201
  Takes an exception that occurs _outside_ of user code and converts it to a
@@ -233,10 +247,10 @@ async def exception_to_crashed_state(
233
247
 
234
248
  async def exception_to_failed_state(
235
249
  exc: Optional[BaseException] = None,
236
- result_store: Optional[ResultStore] = None,
250
+ result_store: Optional["ResultStore"] = None,
237
251
  write_result: bool = False,
238
- **kwargs,
239
- ) -> State:
252
+ **kwargs: Any,
253
+ ) -> State[BaseException]:
240
254
  """
241
255
  Convenience function for creating `Failed` states from exceptions
242
256
  """
@@ -285,12 +299,12 @@ async def exception_to_failed_state(
285
299
 
286
300
 
287
301
  async def return_value_to_state(
288
- retval: R,
289
- result_store: ResultStore,
302
+ retval: "R",
303
+ result_store: "ResultStore",
290
304
  key: Optional[str] = None,
291
305
  expiration: Optional[datetime.datetime] = None,
292
306
  write_result: bool = False,
293
- ) -> State[R]:
307
+ ) -> "State[R]":
294
308
  """
295
309
  Given a return value from a user's function, create a `State` the run should
296
310
  be placed in.
@@ -311,6 +325,11 @@ async def return_value_to_state(
311
325
  Callers should resolve all futures into states before passing return values to this
312
326
  function.
313
327
  """
328
+ from prefect.results import (
329
+ ResultRecord,
330
+ ResultRecordMetadata,
331
+ )
332
+
314
333
  try:
315
334
  local_logger = get_run_logger()
316
335
  except MissingContextError:
@@ -443,6 +462,10 @@ async def get_state_exception(state: State) -> BaseException:
443
462
  - `CrashedRun` if the state type is CRASHED.
444
463
  - `CancelledRun` if the state type is CANCELLED.
445
464
  """
465
+ from prefect.results import (
466
+ ResultRecord,
467
+ ResultRecordMetadata,
468
+ )
446
469
 
447
470
  if state.is_failed():
448
471
  wrapper = FailedRun
@@ -534,17 +557,17 @@ def is_state_iterable(obj: Any) -> TypeGuard[Iterable[State]]:
534
557
 
535
558
 
536
559
  class StateGroup:
537
- def __init__(self, states: Iterable[State]) -> None:
538
- self.states = states
539
- self.type_counts = self._get_type_counts(states)
540
- self.total_count = len(states)
541
- self.cancelled_count = self.type_counts[StateType.CANCELLED]
542
- self.final_count = sum(state.is_final() for state in states)
543
- self.not_final_count = self.total_count - self.final_count
544
- self.paused_count = self.type_counts[StateType.PAUSED]
560
+ def __init__(self, states: list[State]) -> None:
561
+ self.states: list[State] = states
562
+ self.type_counts: dict[StateType, int] = self._get_type_counts(states)
563
+ self.total_count: int = len(states)
564
+ self.cancelled_count: int = self.type_counts[StateType.CANCELLED]
565
+ self.final_count: int = sum(state.is_final() for state in states)
566
+ self.not_final_count: int = self.total_count - self.final_count
567
+ self.paused_count: int = self.type_counts[StateType.PAUSED]
545
568
 
546
569
  @property
547
- def fail_count(self):
570
+ def fail_count(self) -> int:
548
571
  return self.type_counts[StateType.FAILED] + self.type_counts[StateType.CRASHED]
549
572
 
550
573
  def all_completed(self) -> bool:
@@ -586,7 +609,7 @@ class StateGroup:
586
609
  return f"StateGroup<{self.counts_message()}>"
587
610
 
588
611
 
589
- def _traced(cls: Type[State[R]], **kwargs: Any) -> State[R]:
612
+ def _traced(cls: Type["State[R]"], **kwargs: Any) -> "State[R]":
590
613
  state_details = StateDetails.model_validate(kwargs.pop("state_details", {}))
591
614
 
592
615
  carrier = {}
@@ -597,10 +620,10 @@ def _traced(cls: Type[State[R]], **kwargs: Any) -> State[R]:
597
620
 
598
621
 
599
622
  def Scheduled(
600
- cls: Type[State[R]] = State,
623
+ cls: Type["State[R]"] = State,
601
624
  scheduled_time: Optional[datetime.datetime] = None,
602
625
  **kwargs: Any,
603
- ) -> State[R]:
626
+ ) -> "State[R]":
604
627
  """Convenience function for creating `Scheduled` states.
605
628
 
606
629
  Returns:
@@ -616,7 +639,7 @@ def Scheduled(
616
639
  return _traced(cls, type=StateType.SCHEDULED, state_details=state_details, **kwargs)
617
640
 
618
641
 
619
- def Completed(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
642
+ def Completed(cls: Type["State[R]"] = State, **kwargs: Any) -> "State[R]":
620
643
  """Convenience function for creating `Completed` states.
621
644
 
622
645
  Returns:
@@ -626,7 +649,7 @@ def Completed(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
626
649
  return _traced(cls, type=StateType.COMPLETED, **kwargs)
627
650
 
628
651
 
629
- def Running(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
652
+ def Running(cls: Type["State[R]"] = State, **kwargs: Any) -> "State[R]":
630
653
  """Convenience function for creating `Running` states.
631
654
 
632
655
  Returns:
@@ -635,7 +658,7 @@ def Running(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
635
658
  return _traced(cls, type=StateType.RUNNING, **kwargs)
636
659
 
637
660
 
638
- def Failed(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
661
+ def Failed(cls: Type["State[R]"] = State, **kwargs: Any) -> "State[R]":
639
662
  """Convenience function for creating `Failed` states.
640
663
 
641
664
  Returns:
@@ -644,7 +667,7 @@ def Failed(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
644
667
  return _traced(cls, type=StateType.FAILED, **kwargs)
645
668
 
646
669
 
647
- def Crashed(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
670
+ def Crashed(cls: Type["State[R]"] = State, **kwargs: Any) -> "State[R]":
648
671
  """Convenience function for creating `Crashed` states.
649
672
 
650
673
  Returns:
@@ -653,7 +676,7 @@ def Crashed(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
653
676
  return _traced(cls, type=StateType.CRASHED, **kwargs)
654
677
 
655
678
 
656
- def Cancelling(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
679
+ def Cancelling(cls: Type["State[R]"] = State, **kwargs: Any) -> "State[R]":
657
680
  """Convenience function for creating `Cancelling` states.
658
681
 
659
682
  Returns:
@@ -662,7 +685,7 @@ def Cancelling(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
662
685
  return _traced(cls, type=StateType.CANCELLING, **kwargs)
663
686
 
664
687
 
665
- def Cancelled(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
688
+ def Cancelled(cls: Type["State[R]"] = State, **kwargs: Any) -> "State[R]":
666
689
  """Convenience function for creating `Cancelled` states.
667
690
 
668
691
  Returns:
@@ -671,7 +694,7 @@ def Cancelled(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
671
694
  return _traced(cls, type=StateType.CANCELLED, **kwargs)
672
695
 
673
696
 
674
- def Pending(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
697
+ def Pending(cls: Type["State[R]"] = State, **kwargs: Any) -> "State[R]":
675
698
  """Convenience function for creating `Pending` states.
676
699
 
677
700
  Returns:
@@ -681,13 +704,13 @@ def Pending(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
681
704
 
682
705
 
683
706
  def Paused(
684
- cls: Type[State[R]] = State,
707
+ cls: Type["State[R]"] = State,
685
708
  timeout_seconds: Optional[int] = None,
686
709
  pause_expiration_time: Optional[datetime.datetime] = None,
687
710
  reschedule: bool = False,
688
711
  pause_key: Optional[str] = None,
689
712
  **kwargs: Any,
690
- ) -> State[R]:
713
+ ) -> "State[R]":
691
714
  """Convenience function for creating `Paused` states.
692
715
 
693
716
  Returns:
@@ -717,12 +740,12 @@ def Paused(
717
740
 
718
741
 
719
742
  def Suspended(
720
- cls: Type[State[R]] = State,
743
+ cls: Type["State[R]"] = State,
721
744
  timeout_seconds: Optional[int] = None,
722
745
  pause_expiration_time: Optional[datetime.datetime] = None,
723
746
  pause_key: Optional[str] = None,
724
747
  **kwargs: Any,
725
- ):
748
+ ) -> "State[R]":
726
749
  """Convenience function for creating `Suspended` states.
727
750
 
728
751
  Returns:
@@ -740,10 +763,10 @@ def Suspended(
740
763
 
741
764
 
742
765
  def AwaitingRetry(
743
- cls: Type[State[R]] = State,
766
+ cls: Type["State[R]"] = State,
744
767
  scheduled_time: Optional[datetime.datetime] = None,
745
768
  **kwargs: Any,
746
- ) -> State[R]:
769
+ ) -> "State[R]":
747
770
  """Convenience function for creating `AwaitingRetry` states.
748
771
 
749
772
  Returns:
@@ -755,10 +778,10 @@ def AwaitingRetry(
755
778
 
756
779
 
757
780
  def AwaitingConcurrencySlot(
758
- cls: Type[State[R]] = State,
781
+ cls: Type["State[R]"] = State,
759
782
  scheduled_time: Optional[datetime.datetime] = None,
760
783
  **kwargs: Any,
761
- ) -> State[R]:
784
+ ) -> "State[R]":
762
785
  """Convenience function for creating `AwaitingConcurrencySlot` states.
763
786
 
764
787
  Returns:
@@ -769,7 +792,7 @@ def AwaitingConcurrencySlot(
769
792
  )
770
793
 
771
794
 
772
- def Retrying(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
795
+ def Retrying(cls: Type["State[R]"] = State, **kwargs: Any) -> "State[R]":
773
796
  """Convenience function for creating `Retrying` states.
774
797
 
775
798
  Returns:
@@ -779,10 +802,10 @@ def Retrying(cls: Type[State[R]] = State, **kwargs: Any) -> State[R]:
779
802
 
780
803
 
781
804
  def Late(
782
- cls: Type[State[R]] = State,
805
+ cls: Type["State[R]"] = State,
783
806
  scheduled_time: Optional[datetime.datetime] = None,
784
807
  **kwargs: Any,
785
- ) -> State[R]:
808
+ ) -> "State[R]":
786
809
  """Convenience function for creating `Late` states.
787
810
 
788
811
  Returns:
prefect/task_engine.py CHANGED
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import asyncio
2
4
  import inspect
3
5
  import logging
@@ -28,8 +30,9 @@ from uuid import UUID
28
30
  import anyio
29
31
  import pendulum
30
32
  from opentelemetry import trace
31
- from typing_extensions import ParamSpec
33
+ from typing_extensions import ParamSpec, Self
32
34
 
35
+ from prefect.cache_policies import CachePolicy
33
36
  from prefect.client.orchestration import PrefectClient, SyncPrefectClient, get_client
34
37
  from prefect.client.schemas import TaskRun
35
38
  from prefect.client.schemas.objects import State, TaskRunInput
@@ -55,7 +58,7 @@ from prefect.exceptions import (
55
58
  from prefect.logging.loggers import get_logger, patch_print, task_run_logger
56
59
  from prefect.results import (
57
60
  ResultRecord,
58
- _format_user_supplied_storage_key,
61
+ _format_user_supplied_storage_key, # type: ignore[reportPrivateUsage]
59
62
  get_result_store,
60
63
  should_persist_result,
61
64
  )
@@ -115,20 +118,20 @@ class BaseTaskRunEngine(Generic[P, R]):
115
118
  # holds the return value from the user code
116
119
  _return_value: Union[R, Type[NotSet]] = NotSet
117
120
  # holds the exception raised by the user code, if any
118
- _raised: Union[Exception, Type[NotSet]] = NotSet
121
+ _raised: Union[Exception, BaseException, Type[NotSet]] = NotSet
119
122
  _initial_run_context: Optional[TaskRunContext] = None
120
123
  _is_started: bool = False
121
124
  _task_name_set: bool = False
122
125
  _last_event: Optional[PrefectEvent] = None
123
126
  _telemetry: RunTelemetry = field(default_factory=RunTelemetry)
124
127
 
125
- def __post_init__(self):
128
+ def __post_init__(self) -> None:
126
129
  if self.parameters is None:
127
130
  self.parameters = {}
128
131
 
129
132
  @property
130
133
  def state(self) -> State:
131
- if not self.task_run:
134
+ if not self.task_run or not self.task_run.state:
132
135
  raise ValueError("Task run is not set")
133
136
  return self.task_run.state
134
137
 
@@ -142,8 +145,8 @@ class BaseTaskRunEngine(Generic[P, R]):
142
145
  return False
143
146
 
144
147
  def compute_transaction_key(self) -> Optional[str]:
145
- key = None
146
- if self.task.cache_policy:
148
+ key: Optional[str] = None
149
+ if self.task.cache_policy and isinstance(self.task.cache_policy, CachePolicy):
147
150
  flow_run_context = FlowRunContext.get()
148
151
  task_run_context = TaskRunContext.get()
149
152
 
@@ -153,10 +156,12 @@ class BaseTaskRunEngine(Generic[P, R]):
153
156
  parameters = None
154
157
 
155
158
  try:
159
+ if not task_run_context:
160
+ raise ValueError("Task run context is not set")
156
161
  key = self.task.cache_policy.compute_key(
157
162
  task_ctx=task_run_context,
158
- inputs=self.parameters,
159
- flow_parameters=parameters,
163
+ inputs=self.parameters or {},
164
+ flow_parameters=parameters or {},
160
165
  )
161
166
  except Exception:
162
167
  self.logger.exception(
@@ -169,7 +174,7 @@ class BaseTaskRunEngine(Generic[P, R]):
169
174
 
170
175
  def _resolve_parameters(self):
171
176
  if not self.parameters:
172
- return {}
177
+ return None
173
178
 
174
179
  resolved_parameters = {}
175
180
  for parameter, value in self.parameters.items():
@@ -227,10 +232,8 @@ class BaseTaskRunEngine(Generic[P, R]):
227
232
  if self.task_run and self.task_run.start_time and not self.task_run.end_time:
228
233
  self.task_run.end_time = state.timestamp
229
234
 
230
- if self.task_run.state.is_running():
231
- self.task_run.total_run_time += (
232
- state.timestamp - self.task_run.state.timestamp
233
- )
235
+ if self.state.is_running():
236
+ self.task_run.total_run_time += state.timestamp - self.state.timestamp
234
237
 
235
238
  def is_running(self) -> bool:
236
239
  """Whether or not the engine is currently running a task."""
@@ -238,7 +241,7 @@ class BaseTaskRunEngine(Generic[P, R]):
238
241
  return False
239
242
  return task_run.state.is_running() or task_run.state.is_scheduled()
240
243
 
241
- def log_finished_message(self):
244
+ def log_finished_message(self) -> None:
242
245
  if not self.task_run:
243
246
  return
244
247
 
@@ -294,6 +297,7 @@ class BaseTaskRunEngine(Generic[P, R]):
294
297
 
295
298
  @dataclass
296
299
  class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
300
+ task_run: Optional[TaskRun] = None
297
301
  _client: Optional[SyncPrefectClient] = None
298
302
 
299
303
  @property
@@ -336,7 +340,7 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
336
340
  )
337
341
  return False
338
342
 
339
- def call_hooks(self, state: Optional[State] = None):
343
+ def call_hooks(self, state: Optional[State] = None) -> None:
340
344
  if state is None:
341
345
  state = self.state
342
346
  task = self.task
@@ -371,7 +375,7 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
371
375
  else:
372
376
  self.logger.info(f"Hook {hook_name!r} finished running successfully")
373
377
 
374
- def begin_run(self):
378
+ def begin_run(self) -> None:
375
379
  try:
376
380
  self._resolve_parameters()
377
381
  self._set_custom_task_run_name()
@@ -390,6 +394,7 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
390
394
 
391
395
  new_state = Running()
392
396
 
397
+ assert self.task_run is not None, "Task run is not set"
393
398
  self.task_run.start_time = new_state.timestamp
394
399
 
395
400
  flow_run_context = FlowRunContext.get()
@@ -406,7 +411,7 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
406
411
  # result reference that no longer exists
407
412
  if state.is_completed():
408
413
  try:
409
- state.result(retry_result_failure=False, _sync=True)
414
+ state.result(retry_result_failure=False, _sync=True) # type: ignore[reportCallIssue]
410
415
  except Exception:
411
416
  state = self.set_state(new_state, force=True)
412
417
 
@@ -422,7 +427,7 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
422
427
  time.sleep(interval)
423
428
  state = self.set_state(new_state)
424
429
 
425
- def set_state(self, state: State, force: bool = False) -> State:
430
+ def set_state(self, state: State[R], force: bool = False) -> State[R]:
426
431
  last_state = self.state
427
432
  if not self.task_run:
428
433
  raise ValueError("Task run is not set")
@@ -537,7 +542,7 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
537
542
  new_state = Retrying()
538
543
 
539
544
  self.logger.info(
540
- "Task run failed with exception: %r - " "Retry %s/%s will start %s",
545
+ "Task run failed with exception: %r - Retry %s/%s will start %s",
541
546
  exc,
542
547
  self.retries + 1,
543
548
  self.task.retries,
@@ -545,7 +550,7 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
545
550
  )
546
551
 
547
552
  self.set_state(new_state, force=True)
548
- self.retries = self.retries + 1
553
+ self.retries: int = self.retries + 1
549
554
  return True
550
555
  elif self.retries >= self.task.retries:
551
556
  self.logger.error(
@@ -639,7 +644,9 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
639
644
  stack.enter_context(ConcurrencyContextV1())
640
645
  stack.enter_context(ConcurrencyContext())
641
646
 
642
- self.logger = task_run_logger(task_run=self.task_run, task=self.task) # type: ignore
647
+ self.logger: "logging.Logger" = task_run_logger(
648
+ task_run=self.task_run, task=self.task
649
+ ) # type: ignore
643
650
 
644
651
  yield
645
652
 
@@ -648,7 +655,7 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
648
655
  self,
649
656
  task_run_id: Optional[UUID] = None,
650
657
  dependencies: Optional[dict[str, set[TaskRunInput]]] = None,
651
- ) -> Generator["SyncTaskRunEngine", Any, Any]:
658
+ ) -> Generator[Self, Any, Any]:
652
659
  """
653
660
  Enters a client context and creates a task run if needed.
654
661
  """
@@ -718,7 +725,7 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
718
725
  self._is_started = False
719
726
  self._client = None
720
727
 
721
- async def wait_until_ready(self):
728
+ async def wait_until_ready(self) -> None:
722
729
  """Waits until the scheduled time (if its the future), then enters Running."""
723
730
  if scheduled_time := self.state.state_details.scheduled_time:
724
731
  sleep_time = (scheduled_time - pendulum.now("utc")).total_seconds()
@@ -825,6 +832,7 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
825
832
 
826
833
  @dataclass
827
834
  class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
835
+ task_run: TaskRun | None = None
828
836
  _client: Optional[PrefectClient] = None
829
837
 
830
838
  @property
@@ -866,7 +874,7 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
866
874
  )
867
875
  return False
868
876
 
869
- async def call_hooks(self, state: Optional[State] = None):
877
+ async def call_hooks(self, state: Optional[State] = None) -> None:
870
878
  if state is None:
871
879
  state = self.state
872
880
  task = self.task
@@ -901,7 +909,7 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
901
909
  else:
902
910
  self.logger.info(f"Hook {hook_name!r} finished running successfully")
903
911
 
904
- async def begin_run(self):
912
+ async def begin_run(self) -> None:
905
913
  try:
906
914
  self._resolve_parameters()
907
915
  self._set_custom_task_run_name()
@@ -1067,7 +1075,7 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
1067
1075
  new_state = Retrying()
1068
1076
 
1069
1077
  self.logger.info(
1070
- "Task run failed with exception: %r - " "Retry %s/%s will start %s",
1078
+ "Task run failed with exception: %r - Retry %s/%s will start %s",
1071
1079
  exc,
1072
1080
  self.retries + 1,
1073
1081
  self.task.retries,
@@ -1075,7 +1083,7 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
1075
1083
  )
1076
1084
 
1077
1085
  await self.set_state(new_state, force=True)
1078
- self.retries = self.retries + 1
1086
+ self.retries: int = self.retries + 1
1079
1087
  return True
1080
1088
  elif self.retries >= self.task.retries:
1081
1089
  self.logger.error(
@@ -1169,7 +1177,9 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
1169
1177
  )
1170
1178
  stack.enter_context(ConcurrencyContext())
1171
1179
 
1172
- self.logger = task_run_logger(task_run=self.task_run, task=self.task) # type: ignore
1180
+ self.logger: "logging.Logger" = task_run_logger(
1181
+ task_run=self.task_run, task=self.task
1182
+ ) # type: ignore
1173
1183
 
1174
1184
  yield
1175
1185
 
@@ -1178,7 +1188,7 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
1178
1188
  self,
1179
1189
  task_run_id: Optional[UUID] = None,
1180
1190
  dependencies: Optional[dict[str, set[TaskRunInput]]] = None,
1181
- ) -> AsyncGenerator["AsyncTaskRunEngine", Any]:
1191
+ ) -> AsyncGenerator[Self, Any]:
1182
1192
  """
1183
1193
  Enters a client context and creates a task run if needed.
1184
1194
  """
@@ -1246,7 +1256,7 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
1246
1256
  self._is_started = False
1247
1257
  self._client = None
1248
1258
 
1249
- async def wait_until_ready(self):
1259
+ async def wait_until_ready(self) -> None:
1250
1260
  """Waits until the scheduled time (if its the future), then enters Running."""
1251
1261
  if scheduled_time := self.state.state_details.scheduled_time:
1252
1262
  sleep_time = (scheduled_time - pendulum.now("utc")).total_seconds()
@@ -1341,7 +1351,7 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
1341
1351
  if transaction.is_committed():
1342
1352
  result = transaction.read()
1343
1353
  else:
1344
- if self.task_run.tags:
1354
+ if self.task_run and self.task_run.tags:
1345
1355
  # Acquire a concurrency slot for each tag, but only if a limit
1346
1356
  # matching the tag already exists.
1347
1357
  async with aconcurrency(list(self.task_run.tags), self.task_run.id):
@@ -1546,7 +1556,7 @@ def run_task(
1546
1556
  Returns:
1547
1557
  The result of the task run
1548
1558
  """
1549
- kwargs = dict(
1559
+ kwargs: dict[str, Any] = dict(
1550
1560
  task=task,
1551
1561
  task_run_id=task_run_id,
1552
1562
  task_run=task_run,