prefect-client 3.4.7.dev5__py3-none-any.whl → 3.4.7.dev7__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.
prefect/_build_info.py CHANGED
@@ -1,5 +1,5 @@
1
1
  # Generated by versioningit
2
- __version__ = "3.4.7.dev5"
3
- __build_date__ = "2025-06-19 08:09:38.201573+00:00"
4
- __git_commit__ = "3636ab85f878dffcfcb3a5f9a67055bd0219e63f"
2
+ __version__ = "3.4.7.dev7"
3
+ __build_date__ = "2025-06-24 08:09:27.221869+00:00"
4
+ __git_commit__ = "3614ff28a5600b1965c957a04e880aaf38442ad5"
5
5
  __dirty__ = False
@@ -101,10 +101,11 @@ from prefect.client.schemas.filters import (
101
101
  WorkQueueFilterName,
102
102
  )
103
103
  from prefect.client.schemas.objects import (
104
- Constant,
104
+ TaskRunResult,
105
+ FlowRunResult,
105
106
  Parameter,
107
+ Constant,
106
108
  TaskRunPolicy,
107
- TaskRunResult,
108
109
  WorkQueue,
109
110
  WorkQueueStatusDetail,
110
111
  )
@@ -778,13 +779,7 @@ class PrefectClient(
778
779
  task_inputs: Optional[
779
780
  dict[
780
781
  str,
781
- list[
782
- Union[
783
- TaskRunResult,
784
- Parameter,
785
- Constant,
786
- ]
787
- ],
782
+ list[Union[TaskRunResult, FlowRunResult, Parameter, Constant]],
788
783
  ]
789
784
  ] = None,
790
785
  ) -> TaskRun:
@@ -1440,6 +1435,7 @@ class SyncPrefectClient(
1440
1435
  list[
1441
1436
  Union[
1442
1437
  TaskRunResult,
1438
+ FlowRunResult,
1443
1439
  Parameter,
1444
1440
  Constant,
1445
1441
  ]
@@ -297,7 +297,7 @@ class DeploymentClient(BaseClient):
297
297
  deployment_id: the deployment ID of interest
298
298
 
299
299
  Returns:
300
- a [Deployment model][prefect.client.schemas.objects.Deployment] representation of the deployment
300
+ a Deployment model representation of the deployment
301
301
  """
302
302
 
303
303
  from prefect.client.schemas.responses import DeploymentResponse
@@ -961,7 +961,7 @@ class DeploymentAsyncClient(BaseAsyncClient):
961
961
  deployment_id: the deployment ID of interest
962
962
 
963
963
  Returns:
964
- a [Deployment model][prefect.client.schemas.objects.Deployment] representation of the deployment
964
+ a Deployment model representation of the deployment
965
965
  """
966
966
 
967
967
  from prefect.client.schemas.responses import DeploymentResponse
@@ -31,7 +31,7 @@ class FlowClient(BaseClient):
31
31
  Create a flow in the Prefect API.
32
32
 
33
33
  Args:
34
- flow: a [Flow][prefect.flows.Flow] object
34
+ flow: a `Flow` object
35
35
 
36
36
  Raises:
37
37
  httpx.RequestError: if a flow was not created for any reason
@@ -78,7 +78,7 @@ class FlowClient(BaseClient):
78
78
  flow_id: the flow ID of interest
79
79
 
80
80
  Returns:
81
- a [Flow model][prefect.client.schemas.objects.Flow] representation of the flow
81
+ a Flow model representation of the flow
82
82
  """
83
83
  response = self.request("GET", "/flows/{id}", path_params={"id": flow_id})
84
84
  from prefect.client.schemas.objects import Flow
@@ -190,7 +190,7 @@ class FlowAsyncClient(BaseAsyncClient):
190
190
  Create a flow in the Prefect API.
191
191
 
192
192
  Args:
193
- flow: a [Flow][prefect.flows.Flow] object
193
+ flow: a `Flow` object
194
194
 
195
195
  Raises:
196
196
  httpx.RequestError: if a flow was not created for any reason
@@ -237,7 +237,7 @@ class FlowAsyncClient(BaseAsyncClient):
237
237
  flow_id: the flow ID of interest
238
238
 
239
239
  Returns:
240
- a [Flow model][prefect.client.schemas.objects.Flow] representation of the flow
240
+ a Flow model representation of the flow
241
241
  """
242
242
  response = await self.request("GET", "/flows/{id}", path_params={"id": flow_id})
243
243
  from prefect.client.schemas.objects import Flow
@@ -11,11 +11,12 @@ if TYPE_CHECKING:
11
11
  BlockType,
12
12
  FlowRun,
13
13
  FlowRunPolicy,
14
+ FlowRunResult,
14
15
  State,
15
16
  StateDetails,
16
17
  StateType,
17
18
  TaskRun,
18
- TaskRunInput,
19
+ RunInput,
19
20
  TaskRunPolicy,
20
21
  TaskRunResult,
21
22
  Workspace,
@@ -36,6 +37,7 @@ _public_api = {
36
37
  "DEFAULT_BLOCK_SCHEMA_VERSION": (__package__, ".objects"),
37
38
  "FlowRun": (__package__, ".objects"),
38
39
  "FlowRunPolicy": (__package__, ".objects"),
40
+ "FlowRunResult": (__package__, ".objects"),
39
41
  "OrchestrationResult": (__package__, ".responses"),
40
42
  "SetStateStatus": (__package__, ".responses"),
41
43
  "State": (__package__, ".objects"),
@@ -60,6 +62,7 @@ __all__ = [
60
62
  "DEFAULT_BLOCK_SCHEMA_VERSION",
61
63
  "FlowRun",
62
64
  "FlowRunPolicy",
65
+ "FlowRunResult",
63
66
  "OrchestrationResult",
64
67
  "SetStateStatus",
65
68
  "State",
@@ -70,7 +73,7 @@ __all__ = [
70
73
  "StateRejectDetails",
71
74
  "StateType",
72
75
  "TaskRun",
73
- "TaskRunInput",
76
+ "RunInput",
74
77
  "TaskRunPolicy",
75
78
  "TaskRunResult",
76
79
  "Workspace",
@@ -443,6 +443,7 @@ class TaskRunCreate(ActionBaseModel):
443
443
  list[
444
444
  Union[
445
445
  objects.TaskRunResult,
446
+ objects.FlowRunResult,
446
447
  objects.Parameter,
447
448
  objects.Constant,
448
449
  ]
@@ -462,6 +462,9 @@ class DeploymentFilterId(PrefectBaseModel):
462
462
  any_: Optional[List[UUID]] = Field(
463
463
  default=None, description="A list of deployment ids to include"
464
464
  )
465
+ not_any_: Optional[List[UUID]] = Field(
466
+ default=None, description="A list of deployment ids to exclude"
467
+ )
465
468
 
466
469
 
467
470
  class DeploymentFilterName(PrefectBaseModel):
@@ -81,6 +81,11 @@ DEFAULT_BLOCK_SCHEMA_VERSION: Literal["non-versioned"] = "non-versioned"
81
81
  DEFAULT_AGENT_WORK_POOL_NAME: Literal["default-agent-pool"] = "default-agent-pool"
82
82
 
83
83
 
84
+ class RunType(AutoEnum):
85
+ FLOW_RUN = "flow_run"
86
+ TASK_RUN = "task_run"
87
+
88
+
84
89
  class StateType(AutoEnum):
85
90
  """Enumeration of state types."""
86
91
 
@@ -164,7 +169,6 @@ class ConcurrencyLimitConfig(PrefectBaseModel):
164
169
  class StateDetails(PrefectBaseModel):
165
170
  flow_run_id: Optional[UUID] = None
166
171
  task_run_id: Optional[UUID] = None
167
- # for task runs that represent subflows, the subflow's run ID
168
172
  child_flow_run_id: Optional[UUID] = None
169
173
  scheduled_time: Optional[DateTime] = None
170
174
  cache_key: Optional[str] = None
@@ -182,6 +186,16 @@ class StateDetails(PrefectBaseModel):
182
186
  # Captures the trace_id and span_id of the span where this state was created
183
187
  traceparent: Optional[str] = None
184
188
 
189
+ def to_run_result(
190
+ self, run_type: RunType
191
+ ) -> Optional[Union[FlowRunResult, TaskRunResult]]:
192
+ if run_type == run_type.FLOW_RUN and self.flow_run_id:
193
+ return FlowRunResult(id=self.flow_run_id)
194
+ elif run_type == run_type.TASK_RUN and self.task_run_id:
195
+ return TaskRunResult(id=self.task_run_id)
196
+ else:
197
+ return None
198
+
185
199
 
186
200
  def data_discriminator(x: Any) -> str:
187
201
  if isinstance(x, dict) and "storage_key" in x:
@@ -734,7 +748,7 @@ class TaskRunPolicy(PrefectBaseModel):
734
748
  return validate_not_negative(v)
735
749
 
736
750
 
737
- class TaskRunInput(PrefectBaseModel):
751
+ class RunInput(PrefectBaseModel):
738
752
  """
739
753
  Base class for classes that represent inputs to task runs, which
740
754
  could include, constants, parameters, or other task runs.
@@ -747,21 +761,26 @@ class TaskRunInput(PrefectBaseModel):
747
761
  input_type: str
748
762
 
749
763
 
750
- class TaskRunResult(TaskRunInput):
764
+ class TaskRunResult(RunInput):
751
765
  """Represents a task run result input to another task run."""
752
766
 
753
767
  input_type: Literal["task_run"] = "task_run"
754
768
  id: UUID
755
769
 
756
770
 
757
- class Parameter(TaskRunInput):
771
+ class FlowRunResult(RunInput):
772
+ input_type: Literal["flow_run"] = "flow_run"
773
+ id: UUID
774
+
775
+
776
+ class Parameter(RunInput):
758
777
  """Represents a parameter input to a task run."""
759
778
 
760
779
  input_type: Literal["parameter"] = "parameter"
761
780
  name: str
762
781
 
763
782
 
764
- class Constant(TaskRunInput):
783
+ class Constant(RunInput):
765
784
  """Represents constant input value to a task run."""
766
785
 
767
786
  input_type: Literal["constant"] = "constant"
@@ -811,7 +830,9 @@ class TaskRun(TimeSeriesBaseModel, ObjectBaseModel):
811
830
  state_id: Optional[UUID] = Field(
812
831
  default=None, description="The id of the current task run state."
813
832
  )
814
- task_inputs: dict[str, list[Union[TaskRunResult, Parameter, Constant]]] = Field(
833
+ task_inputs: dict[
834
+ str, list[Union[TaskRunResult, FlowRunResult, Parameter, Constant]]
835
+ ] = Field(
815
836
  default_factory=dict,
816
837
  description=(
817
838
  "Tracks the source of inputs to a task run. Used for internal bookkeeping. "
prefect/context.py CHANGED
@@ -34,6 +34,7 @@ from prefect._internal.compatibility.migration import getattr_migration
34
34
  from prefect.assets import Asset
35
35
  from prefect.client.orchestration import PrefectClient, SyncPrefectClient, get_client
36
36
  from prefect.client.schemas import FlowRun, TaskRun
37
+ from prefect.client.schemas.objects import RunType
37
38
  from prefect.events.worker import EventsWorker
38
39
  from prefect.exceptions import MissingContextError
39
40
  from prefect.results import (
@@ -363,7 +364,7 @@ class EngineContext(RunContext):
363
364
  flow: The flow instance associated with the run
364
365
  flow_run: The API metadata for the flow run
365
366
  task_runner: The task runner instance being used for the flow run
366
- task_run_results: A mapping of result ids to task run states for this flow run
367
+ run_results: A mapping of result ids to run states for this flow run
367
368
  log_prints: Whether to log print statements from the flow run
368
369
  parameters: The parameters passed to the flow run
369
370
  detached: Flag indicating if context has been serialized and sent to remote infrastructure
@@ -394,9 +395,10 @@ class EngineContext(RunContext):
394
395
  # Counter for flow pauses
395
396
  observed_flow_pauses: dict[str, int] = Field(default_factory=dict)
396
397
 
397
- # Tracking for result from task runs in this flow run for dependency tracking
398
- # Holds the ID of the object returned by the task run and task run state
399
- task_run_results: dict[int, State] = Field(default_factory=dict)
398
+ # Tracking for result from task runs and sub flows in this flow run for
399
+ # dependency tracking. Holds the ID of the object returned by
400
+ # the run and state
401
+ run_results: dict[int, tuple[State, RunType]] = Field(default_factory=dict)
400
402
 
401
403
  # Tracking information needed to track asset linage between
402
404
  # tasks and materialization
prefect/flow_engine.py CHANGED
@@ -105,7 +105,7 @@ from prefect.utilities.callables import (
105
105
  from prefect.utilities.collections import visit_collection
106
106
  from prefect.utilities.engine import (
107
107
  capture_sigterm,
108
- link_state_to_result,
108
+ link_state_to_flow_run_result,
109
109
  propose_state,
110
110
  propose_state_sync,
111
111
  resolve_to_final_result,
@@ -338,6 +338,7 @@ class FlowRunEngine(BaseFlowRunEngine[P, R]):
338
338
  self._return_value, State
339
339
  ):
340
340
  _result = self._return_value
341
+ link_state_to_flow_run_result(self.state, _result)
341
342
 
342
343
  if asyncio.iscoroutine(_result):
343
344
  # getting the value for a BaseResult may return an awaitable
@@ -373,6 +374,7 @@ class FlowRunEngine(BaseFlowRunEngine[P, R]):
373
374
  self.set_state(terminal_state)
374
375
  self._return_value = resolved_result
375
376
 
377
+ link_state_to_flow_run_result(terminal_state, resolved_result)
376
378
  self._telemetry.end_span_on_success()
377
379
 
378
380
  return result
@@ -903,6 +905,7 @@ class AsyncFlowRunEngine(BaseFlowRunEngine[P, R]):
903
905
  self._return_value, State
904
906
  ):
905
907
  _result = self._return_value
908
+ link_state_to_flow_run_result(self.state, _result)
906
909
 
907
910
  if asyncio.iscoroutine(_result):
908
911
  # getting the value for a BaseResult may return an awaitable
@@ -1426,7 +1429,7 @@ def run_generator_flow_sync(
1426
1429
  while True:
1427
1430
  gen_result = next(gen)
1428
1431
  # link the current state to the result for dependency tracking
1429
- link_state_to_result(engine.state, gen_result)
1432
+ link_state_to_flow_run_result(engine.state, gen_result)
1430
1433
  yield gen_result
1431
1434
  except StopIteration as exc:
1432
1435
  engine.handle_success(exc.value)
@@ -1468,7 +1471,7 @@ async def run_generator_flow_async(
1468
1471
  # can't use anext in Python < 3.10
1469
1472
  gen_result = await gen.__anext__()
1470
1473
  # link the current state to the result for dependency tracking
1471
- link_state_to_result(engine.state, gen_result)
1474
+ link_state_to_flow_run_result(engine.state, gen_result)
1472
1475
  yield gen_result
1473
1476
  except (StopAsyncIteration, GeneratorExit) as exc:
1474
1477
  await engine.handle_success(None)
prefect/flows.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- Module containing the base workflow class and decorator - for most use cases, using the [`@flow` decorator][prefect.flows.flow] is preferred.
2
+ Module containing the base workflow class and decorator - for most use cases, using the `@flow` decorator is preferred.
3
3
  """
4
4
 
5
5
  from __future__ import annotations
@@ -145,9 +145,6 @@ class Flow(Generic[P, R]):
145
145
  """
146
146
  A Prefect workflow definition.
147
147
 
148
- !!! note
149
- We recommend using the [`@flow` decorator][prefect.flows.flow] for most use-cases.
150
-
151
148
  Wraps a function with an entrypoint to the Prefect engine. To preserve the input
152
149
  and output types, we use the generic type variables `P` and `R` for "Parameters" and
153
150
  "Returns" respectively.
@@ -500,23 +497,29 @@ class Flow(Generic[P, R]):
500
497
 
501
498
  Create a new flow from an existing flow and update the name:
502
499
 
503
- >>> @flow(name="My flow")
504
- >>> def my_flow():
505
- >>> return 1
506
- >>>
507
- >>> new_flow = my_flow.with_options(name="My new flow")
500
+ ```python
501
+ from prefect import flow
502
+
503
+ @flow(name="My flow")
504
+ def my_flow():
505
+ return 1
506
+
507
+ new_flow = my_flow.with_options(name="My new flow")
508
+ ```
508
509
 
509
510
  Create a new flow from an existing flow, update the task runner, and call
510
511
  it without an intermediate variable:
511
512
 
512
- >>> from prefect.task_runners import ThreadPoolTaskRunner
513
- >>>
514
- >>> @flow
515
- >>> def my_flow(x, y):
516
- >>> return x + y
517
- >>>
518
- >>> state = my_flow.with_options(task_runner=ThreadPoolTaskRunner)(1, 3)
519
- >>> assert state.result() == 4
513
+ ```python
514
+ from prefect.task_runners import ThreadPoolTaskRunner
515
+
516
+ @flow
517
+ def my_flow(x, y):
518
+ return x + y
519
+
520
+ state = my_flow.with_options(task_runner=ThreadPoolTaskRunner)(1, 3)
521
+ assert state.result() == 4
522
+ ```
520
523
  """
521
524
  new_task_runner = (
522
525
  task_runner() if isinstance(task_runner, type) else task_runner
@@ -1653,22 +1656,27 @@ class Flow(Generic[P, R]):
1653
1656
 
1654
1657
  Define a flow
1655
1658
 
1656
- >>> @flow
1657
- >>> def my_flow(name):
1658
- >>> print(f"hello {name}")
1659
- >>> return f"goodbye {name}"
1659
+ ```python
1660
+ @flow
1661
+ def my_flow(name):
1662
+ print(f"hello {name}")
1663
+ return f"goodbye {name}"
1664
+ ```
1660
1665
 
1661
1666
  Run a flow
1662
1667
 
1663
- >>> my_flow("marvin")
1664
- hello marvin
1665
- "goodbye marvin"
1668
+ ```python
1669
+ my_flow("marvin")
1670
+ ```
1666
1671
 
1667
1672
  Run a flow with additional tags
1668
1673
 
1669
- >>> from prefect import tags
1670
- >>> with tags("db", "blue"):
1671
- >>> my_flow("foo")
1674
+ ```python
1675
+ from prefect import tags
1676
+
1677
+ with tags("db", "blue"):
1678
+ my_flow("foo")
1679
+ ```
1672
1680
  """
1673
1681
  from prefect.utilities.visualization import (
1674
1682
  get_task_viz_tracker,
@@ -1907,36 +1915,47 @@ class FlowDecorator:
1907
1915
  Examples:
1908
1916
  Define a simple flow
1909
1917
 
1910
- >>> from prefect import flow
1911
- >>> @flow
1912
- >>> def add(x, y):
1913
- >>> return x + y
1918
+ ```python
1919
+ from prefect import flow
1920
+
1921
+ @flow
1922
+ def add(x, y):
1923
+ return x + y
1924
+ ```
1914
1925
 
1915
1926
  Define an async flow
1916
1927
 
1917
- >>> @flow
1918
- >>> async def add(x, y):
1919
- >>> return x + y
1928
+ ```python
1929
+ @flow
1930
+ async def add(x, y):
1931
+ return x + y
1932
+ ```
1920
1933
 
1921
1934
  Define a flow with a version and description
1922
1935
 
1923
- >>> @flow(version="first-flow", description="This flow is empty!")
1924
- >>> def my_flow():
1925
- >>> pass
1936
+ ```python
1937
+ @flow(version="first-flow", description="This flow is empty!")
1938
+ def my_flow():
1939
+ pass
1940
+ ```
1926
1941
 
1927
1942
  Define a flow with a custom name
1928
1943
 
1929
- >>> @flow(name="The Ultimate Flow")
1930
- >>> def my_flow():
1931
- >>> pass
1944
+ ```python
1945
+ @flow(name="The Ultimate Flow")
1946
+ def my_flow():
1947
+ pass
1948
+ ```
1932
1949
 
1933
1950
  Define a flow that submits its tasks to dask
1934
1951
 
1935
- >>> from prefect_dask.task_runners import DaskTaskRunner
1936
- >>>
1937
- >>> @flow(task_runner=DaskTaskRunner)
1938
- >>> def my_flow():
1939
- >>> pass
1952
+ ```python
1953
+ from prefect_dask.task_runners import DaskTaskRunner
1954
+
1955
+ @flow(task_runner=DaskTaskRunner)
1956
+ def my_flow():
1957
+ pass
1958
+ ```
1940
1959
  """
1941
1960
  if __fn:
1942
1961
  return Flow(
prefect/runner/submit.py CHANGED
@@ -17,7 +17,13 @@ from prefect.client.schemas.filters import (
17
17
  FlowRunFilterParentFlowRunId,
18
18
  TaskRunFilter,
19
19
  )
20
- from prefect.client.schemas.objects import Constant, FlowRun, Parameter, TaskRunResult
20
+ from prefect.client.schemas.objects import (
21
+ Constant,
22
+ FlowRun,
23
+ FlowRunResult,
24
+ Parameter,
25
+ TaskRunResult,
26
+ )
21
27
  from prefect.context import FlowRunContext
22
28
  from prefect.flows import Flow
23
29
  from prefect.logging import get_logger
@@ -66,9 +72,9 @@ async def _submit_flow_to_runner(
66
72
 
67
73
  parent_flow_run_context = FlowRunContext.get()
68
74
 
69
- task_inputs: dict[str, list[TaskRunResult | Parameter | Constant]] = {
70
- k: list(await collect_task_run_inputs(v)) for k, v in parameters.items()
71
- }
75
+ task_inputs: dict[
76
+ str, list[Union[TaskRunResult, FlowRunResult, Parameter, Constant]]
77
+ ] = {k: list(await collect_task_run_inputs(v)) for k, v in parameters.items()}
72
78
  parameters = await resolve_inputs(parameters)
73
79
  dummy_task = Task(name=flow.name, fn=flow.fn, version=flow.version)
74
80
  parent_task_run = await client.create_task_run(
prefect/task_engine.py CHANGED
@@ -37,7 +37,7 @@ import prefect.types._datetime
37
37
  from prefect.cache_policies import CachePolicy
38
38
  from prefect.client.orchestration import PrefectClient, SyncPrefectClient, get_client
39
39
  from prefect.client.schemas import TaskRun
40
- from prefect.client.schemas.objects import State, TaskRunInput
40
+ from prefect.client.schemas.objects import RunInput, State
41
41
  from prefect.concurrency.context import ConcurrencyContext
42
42
  from prefect.concurrency.v1.asyncio import concurrency as aconcurrency
43
43
  from prefect.concurrency.v1.context import ConcurrencyContext as ConcurrencyContextV1
@@ -96,7 +96,7 @@ from prefect.utilities.callables import call_with_parameters, parameters_to_args
96
96
  from prefect.utilities.collections import visit_collection
97
97
  from prefect.utilities.engine import (
98
98
  emit_task_run_state_change_event,
99
- link_state_to_result,
99
+ link_state_to_task_run_result,
100
100
  resolve_to_final_result,
101
101
  )
102
102
  from prefect.utilities.math import clamped_poisson_interval
@@ -453,7 +453,7 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
453
453
  else:
454
454
  result = state.data
455
455
 
456
- link_state_to_result(new_state, result)
456
+ link_state_to_task_run_result(new_state, result)
457
457
 
458
458
  # emit a state change event
459
459
  self._last_event = emit_task_run_state_change_event(
@@ -683,7 +683,7 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
683
683
  def initialize_run(
684
684
  self,
685
685
  task_run_id: Optional[UUID] = None,
686
- dependencies: Optional[dict[str, set[TaskRunInput]]] = None,
686
+ dependencies: Optional[dict[str, set[RunInput]]] = None,
687
687
  ) -> Generator[Self, Any, Any]:
688
688
  """
689
689
  Enters a client context and creates a task run if needed.
@@ -777,7 +777,7 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
777
777
  def start(
778
778
  self,
779
779
  task_run_id: Optional[UUID] = None,
780
- dependencies: Optional[dict[str, set[TaskRunInput]]] = None,
780
+ dependencies: Optional[dict[str, set[RunInput]]] = None,
781
781
  ) -> Generator[None, None, None]:
782
782
  with self.initialize_run(task_run_id=task_run_id, dependencies=dependencies):
783
783
  with (
@@ -1038,7 +1038,7 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
1038
1038
  else:
1039
1039
  result = new_state.data
1040
1040
 
1041
- link_state_to_result(new_state, result)
1041
+ link_state_to_task_run_result(new_state, result)
1042
1042
 
1043
1043
  # emit a state change event
1044
1044
  self._last_event = emit_task_run_state_change_event(
@@ -1267,7 +1267,7 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
1267
1267
  async def initialize_run(
1268
1268
  self,
1269
1269
  task_run_id: Optional[UUID] = None,
1270
- dependencies: Optional[dict[str, set[TaskRunInput]]] = None,
1270
+ dependencies: Optional[dict[str, set[RunInput]]] = None,
1271
1271
  ) -> AsyncGenerator[Self, Any]:
1272
1272
  """
1273
1273
  Enters a client context and creates a task run if needed.
@@ -1359,7 +1359,7 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
1359
1359
  async def start(
1360
1360
  self,
1361
1361
  task_run_id: Optional[UUID] = None,
1362
- dependencies: Optional[dict[str, set[TaskRunInput]]] = None,
1362
+ dependencies: Optional[dict[str, set[RunInput]]] = None,
1363
1363
  ) -> AsyncGenerator[None, None]:
1364
1364
  async with self.initialize_run(
1365
1365
  task_run_id=task_run_id, dependencies=dependencies
@@ -1465,7 +1465,7 @@ def run_task_sync(
1465
1465
  parameters: Optional[dict[str, Any]] = None,
1466
1466
  wait_for: Optional["OneOrManyFutureOrResult[Any]"] = None,
1467
1467
  return_type: Literal["state", "result"] = "result",
1468
- dependencies: Optional[dict[str, set[TaskRunInput]]] = None,
1468
+ dependencies: Optional[dict[str, set[RunInput]]] = None,
1469
1469
  context: Optional[dict[str, Any]] = None,
1470
1470
  ) -> Union[R, State, None]:
1471
1471
  engine = SyncTaskRunEngine[P, R](
@@ -1496,7 +1496,7 @@ async def run_task_async(
1496
1496
  parameters: Optional[dict[str, Any]] = None,
1497
1497
  wait_for: Optional["OneOrManyFutureOrResult[Any]"] = None,
1498
1498
  return_type: Literal["state", "result"] = "result",
1499
- dependencies: Optional[dict[str, set[TaskRunInput]]] = None,
1499
+ dependencies: Optional[dict[str, set[RunInput]]] = None,
1500
1500
  context: Optional[dict[str, Any]] = None,
1501
1501
  ) -> Union[R, State, None]:
1502
1502
  engine = AsyncTaskRunEngine[P, R](
@@ -1527,7 +1527,7 @@ def run_generator_task_sync(
1527
1527
  parameters: Optional[dict[str, Any]] = None,
1528
1528
  wait_for: Optional["OneOrManyFutureOrResult[Any]"] = None,
1529
1529
  return_type: Literal["state", "result"] = "result",
1530
- dependencies: Optional[dict[str, set[TaskRunInput]]] = None,
1530
+ dependencies: Optional[dict[str, set[RunInput]]] = None,
1531
1531
  context: Optional[dict[str, Any]] = None,
1532
1532
  ) -> Generator[R, None, None]:
1533
1533
  if return_type != "result":
@@ -1568,7 +1568,7 @@ def run_generator_task_sync(
1568
1568
  # dictionary in an unbounded way, so finding a
1569
1569
  # way to periodically clean it up (using
1570
1570
  # weakrefs or similar) would be good
1571
- link_state_to_result(engine.state, gen_result)
1571
+ link_state_to_task_run_result(engine.state, gen_result)
1572
1572
  yield gen_result
1573
1573
  except StopIteration as exc:
1574
1574
  engine.handle_success(exc.value, transaction=txn)
@@ -1586,7 +1586,7 @@ async def run_generator_task_async(
1586
1586
  parameters: Optional[dict[str, Any]] = None,
1587
1587
  wait_for: Optional["OneOrManyFutureOrResult[Any]"] = None,
1588
1588
  return_type: Literal["state", "result"] = "result",
1589
- dependencies: Optional[dict[str, set[TaskRunInput]]] = None,
1589
+ dependencies: Optional[dict[str, set[RunInput]]] = None,
1590
1590
  context: Optional[dict[str, Any]] = None,
1591
1591
  ) -> AsyncGenerator[R, None]:
1592
1592
  if return_type != "result":
@@ -1627,7 +1627,7 @@ async def run_generator_task_async(
1627
1627
  # dictionary in an unbounded way, so finding a
1628
1628
  # way to periodically clean it up (using
1629
1629
  # weakrefs or similar) would be good
1630
- link_state_to_result(engine.state, gen_result)
1630
+ link_state_to_task_run_result(engine.state, gen_result)
1631
1631
  yield gen_result
1632
1632
  except (StopAsyncIteration, GeneratorExit) as exc:
1633
1633
  await engine.handle_success(None, transaction=txn)
@@ -1647,7 +1647,7 @@ def run_task(
1647
1647
  parameters: Optional[dict[str, Any]] = None,
1648
1648
  wait_for: Optional["OneOrManyFutureOrResult[Any]"] = None,
1649
1649
  return_type: Literal["state"] = "state",
1650
- dependencies: Optional[dict[str, set[TaskRunInput]]] = None,
1650
+ dependencies: Optional[dict[str, set[RunInput]]] = None,
1651
1651
  context: Optional[dict[str, Any]] = None,
1652
1652
  ) -> State[R]: ...
1653
1653
 
@@ -1660,7 +1660,7 @@ def run_task(
1660
1660
  parameters: Optional[dict[str, Any]] = None,
1661
1661
  wait_for: Optional["OneOrManyFutureOrResult[Any]"] = None,
1662
1662
  return_type: Literal["result"] = "result",
1663
- dependencies: Optional[dict[str, set[TaskRunInput]]] = None,
1663
+ dependencies: Optional[dict[str, set[RunInput]]] = None,
1664
1664
  context: Optional[dict[str, Any]] = None,
1665
1665
  ) -> R: ...
1666
1666
 
@@ -1672,7 +1672,7 @@ def run_task(
1672
1672
  parameters: Optional[dict[str, Any]] = None,
1673
1673
  wait_for: Optional["OneOrManyFutureOrResult[Any]"] = None,
1674
1674
  return_type: Literal["state", "result"] = "result",
1675
- dependencies: Optional[dict[str, set[TaskRunInput]]] = None,
1675
+ dependencies: Optional[dict[str, set[RunInput]]] = None,
1676
1676
  context: Optional[dict[str, Any]] = None,
1677
1677
  ) -> Union[R, State, None, Coroutine[Any, Any, Union[R, State, None]]]:
1678
1678
  """
prefect/task_runners.py CHANGED
@@ -19,7 +19,7 @@ from typing import (
19
19
  from typing_extensions import ParamSpec, Self, TypeVar
20
20
 
21
21
  from prefect._internal.uuid7 import uuid7
22
- from prefect.client.schemas.objects import TaskRunInput
22
+ from prefect.client.schemas.objects import RunInput
23
23
  from prefect.exceptions import MappingLengthMismatch, MappingMissingIterable
24
24
  from prefect.futures import (
25
25
  PrefectConcurrentFuture,
@@ -81,7 +81,7 @@ class TaskRunner(abc.ABC, Generic[F]):
81
81
  task: "Task[P, Coroutine[Any, Any, R]]",
82
82
  parameters: dict[str, Any],
83
83
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
84
- dependencies: dict[str, set[TaskRunInput]] | None = None,
84
+ dependencies: dict[str, set[RunInput]] | None = None,
85
85
  ) -> F: ...
86
86
 
87
87
  @overload
@@ -91,7 +91,7 @@ class TaskRunner(abc.ABC, Generic[F]):
91
91
  task: "Task[Any, R]",
92
92
  parameters: dict[str, Any],
93
93
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
94
- dependencies: dict[str, set[TaskRunInput]] | None = None,
94
+ dependencies: dict[str, set[RunInput]] | None = None,
95
95
  ) -> F: ...
96
96
 
97
97
  @abc.abstractmethod
@@ -100,7 +100,7 @@ class TaskRunner(abc.ABC, Generic[F]):
100
100
  task: "Task[P, R]",
101
101
  parameters: dict[str, Any],
102
102
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
103
- dependencies: dict[str, set[TaskRunInput]] | None = None,
103
+ dependencies: dict[str, set[RunInput]] | None = None,
104
104
  ) -> F: ...
105
105
 
106
106
  def map(
@@ -262,7 +262,7 @@ class ThreadPoolTaskRunner(TaskRunner[PrefectConcurrentFuture[R]]):
262
262
  task: "Task[P, Coroutine[Any, Any, R]]",
263
263
  parameters: dict[str, Any],
264
264
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
265
- dependencies: dict[str, set[TaskRunInput]] | None = None,
265
+ dependencies: dict[str, set[RunInput]] | None = None,
266
266
  ) -> PrefectConcurrentFuture[R]: ...
267
267
 
268
268
  @overload
@@ -271,7 +271,7 @@ class ThreadPoolTaskRunner(TaskRunner[PrefectConcurrentFuture[R]]):
271
271
  task: "Task[Any, R]",
272
272
  parameters: dict[str, Any],
273
273
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
274
- dependencies: dict[str, set[TaskRunInput]] | None = None,
274
+ dependencies: dict[str, set[RunInput]] | None = None,
275
275
  ) -> PrefectConcurrentFuture[R]: ...
276
276
 
277
277
  def submit(
@@ -279,7 +279,7 @@ class ThreadPoolTaskRunner(TaskRunner[PrefectConcurrentFuture[R]]):
279
279
  task: "Task[P, R | Coroutine[Any, Any, R]]",
280
280
  parameters: dict[str, Any],
281
281
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
282
- dependencies: dict[str, set[TaskRunInput]] | None = None,
282
+ dependencies: dict[str, set[RunInput]] | None = None,
283
283
  ) -> PrefectConcurrentFuture[R]:
284
284
  """
285
285
  Submit a task to the task run engine running in a separate thread.
@@ -415,7 +415,7 @@ class PrefectTaskRunner(TaskRunner[PrefectDistributedFuture[R]]):
415
415
  task: "Task[P, Coroutine[Any, Any, R]]",
416
416
  parameters: dict[str, Any],
417
417
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
418
- dependencies: dict[str, set[TaskRunInput]] | None = None,
418
+ dependencies: dict[str, set[RunInput]] | None = None,
419
419
  ) -> PrefectDistributedFuture[R]: ...
420
420
 
421
421
  @overload
@@ -424,7 +424,7 @@ class PrefectTaskRunner(TaskRunner[PrefectDistributedFuture[R]]):
424
424
  task: "Task[Any, R]",
425
425
  parameters: dict[str, Any],
426
426
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
427
- dependencies: dict[str, set[TaskRunInput]] | None = None,
427
+ dependencies: dict[str, set[RunInput]] | None = None,
428
428
  ) -> PrefectDistributedFuture[R]: ...
429
429
 
430
430
  def submit(
@@ -432,7 +432,7 @@ class PrefectTaskRunner(TaskRunner[PrefectDistributedFuture[R]]):
432
432
  task: "Task[P, R]",
433
433
  parameters: dict[str, Any],
434
434
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
435
- dependencies: dict[str, set[TaskRunInput]] | None = None,
435
+ dependencies: dict[str, set[RunInput]] | None = None,
436
436
  ) -> PrefectDistributedFuture[R]:
437
437
  """
438
438
  Submit a task to the task run engine running in a separate thread.
prefect/tasks.py CHANGED
@@ -1,5 +1,5 @@
1
1
  """
2
- Module containing the base workflow task class and decorator - for most use cases, using the [`@task` decorator][prefect.tasks.task] is preferred.
2
+ Module containing the base workflow task class and decorator - for most use cases, using the `@task` decorator is preferred.
3
3
  """
4
4
 
5
5
  # This file requires type-checking with pyright because mypy does not yet support PEP612
@@ -47,8 +47,8 @@ from prefect.cache_policies import DEFAULT, NO_CACHE, CachePolicy
47
47
  from prefect.client.orchestration import get_client
48
48
  from prefect.client.schemas import TaskRun
49
49
  from prefect.client.schemas.objects import (
50
+ RunInput,
50
51
  StateDetails,
51
- TaskRunInput,
52
52
  TaskRunPolicy,
53
53
  TaskRunResult,
54
54
  )
@@ -244,12 +244,17 @@ def _infer_parent_task_runs(
244
244
  # tracked within the same flow run.
245
245
  if flow_run_context:
246
246
  for v in parameters.values():
247
+ upstream_state = None
248
+
247
249
  if isinstance(v, State):
248
250
  upstream_state = v
249
251
  elif isinstance(v, PrefectFuture):
250
252
  upstream_state = v.state
251
253
  else:
252
- upstream_state = flow_run_context.task_run_results.get(id(v))
254
+ res = flow_run_context.run_results.get(id(v))
255
+ if res:
256
+ upstream_state, _ = res
257
+
253
258
  if upstream_state and upstream_state.is_running():
254
259
  parents.append(
255
260
  TaskRunResult(id=upstream_state.state_details.task_run_id)
@@ -296,9 +301,6 @@ class Task(Generic[P, R]):
296
301
  """
297
302
  A Prefect task definition.
298
303
 
299
- !!! note
300
- We recommend using [the `@task` decorator][prefect.tasks.task] for most use-cases.
301
-
302
304
  Wraps a function with an entrypoint to the Prefect engine. Calling this class within a flow function
303
305
  creates a new task run.
304
306
 
@@ -840,7 +842,7 @@ class Task(Generic[P, R]):
840
842
  flow_run_context: Optional[FlowRunContext] = None,
841
843
  parent_task_run_context: Optional[TaskRunContext] = None,
842
844
  wait_for: Optional[OneOrManyFutureOrResult[Any]] = None,
843
- extra_task_inputs: Optional[dict[str, set[TaskRunInput]]] = None,
845
+ extra_task_inputs: Optional[dict[str, set[RunInput]]] = None,
844
846
  deferred: bool = False,
845
847
  ) -> TaskRun:
846
848
  from prefect.utilities._engine import dynamic_key_for_task_run
@@ -943,7 +945,7 @@ class Task(Generic[P, R]):
943
945
  flow_run_context: Optional[FlowRunContext] = None,
944
946
  parent_task_run_context: Optional[TaskRunContext] = None,
945
947
  wait_for: Optional[OneOrManyFutureOrResult[Any]] = None,
946
- extra_task_inputs: Optional[dict[str, set[TaskRunInput]]] = None,
948
+ extra_task_inputs: Optional[dict[str, set[RunInput]]] = None,
947
949
  deferred: bool = False,
948
950
  ) -> TaskRun:
949
951
  from prefect.utilities._engine import dynamic_key_for_task_run
@@ -1530,7 +1532,7 @@ class Task(Generic[P, R]):
1530
1532
  args: Optional[tuple[Any, ...]] = None,
1531
1533
  kwargs: Optional[dict[str, Any]] = None,
1532
1534
  wait_for: Optional[Iterable[PrefectFuture[R]]] = None,
1533
- dependencies: Optional[dict[str, set[TaskRunInput]]] = None,
1535
+ dependencies: Optional[dict[str, set[RunInput]]] = None,
1534
1536
  ) -> PrefectDistributedFuture[R]:
1535
1537
  """
1536
1538
  Create a pending task run for a task worker to execute.
@@ -24,8 +24,11 @@ from typing_extensions import TypeIs
24
24
  import prefect
25
25
  import prefect.exceptions
26
26
  from prefect._internal.concurrency.cancellation import get_deadline
27
- from prefect.client.schemas import OrchestrationResult, TaskRun
28
- from prefect.client.schemas.objects import TaskRunInput, TaskRunResult
27
+ from prefect.client.schemas import FlowRunResult, OrchestrationResult, TaskRun
28
+ from prefect.client.schemas.objects import (
29
+ RunType,
30
+ TaskRunResult,
31
+ )
29
32
  from prefect.client.schemas.responses import (
30
33
  SetStateStatus,
31
34
  StateAbortDetails,
@@ -60,7 +63,9 @@ engine_logger: Logger = get_logger("engine")
60
63
  T = TypeVar("T")
61
64
 
62
65
 
63
- async def collect_task_run_inputs(expr: Any, max_depth: int = -1) -> set[TaskRunResult]:
66
+ async def collect_task_run_inputs(
67
+ expr: Any, max_depth: int = -1
68
+ ) -> set[Union[TaskRunResult, FlowRunResult]]:
64
69
  """
65
70
  This function recurses through an expression to generate a set of any discernible
66
71
  task run inputs it finds in the data structure. It produces a set of all inputs
@@ -73,7 +78,7 @@ async def collect_task_run_inputs(expr: Any, max_depth: int = -1) -> set[TaskRun
73
78
  """
74
79
  # TODO: This function needs to be updated to detect parameters and constants
75
80
 
76
- inputs: set[TaskRunResult] = set()
81
+ inputs: set[Union[TaskRunResult, FlowRunResult]] = set()
77
82
 
78
83
  def add_futures_and_states_to_inputs(obj: Any) -> None:
79
84
  if isinstance(obj, PrefectFuture):
@@ -89,9 +94,12 @@ async def collect_task_run_inputs(expr: Any, max_depth: int = -1) -> set[TaskRun
89
94
  elif isinstance(obj, quote):
90
95
  raise StopVisiting
91
96
  else:
92
- state = get_state_for_result(obj)
93
- if state and state.state_details.task_run_id:
94
- inputs.add(TaskRunResult(id=state.state_details.task_run_id))
97
+ res = get_state_for_result(obj)
98
+ if res:
99
+ state, run_type = res
100
+ run_result = state.state_details.to_run_result(run_type)
101
+ if run_result:
102
+ inputs.add(run_result)
95
103
 
96
104
  visit_collection(
97
105
  expr,
@@ -105,7 +113,7 @@ async def collect_task_run_inputs(expr: Any, max_depth: int = -1) -> set[TaskRun
105
113
 
106
114
  def collect_task_run_inputs_sync(
107
115
  expr: Any, future_cls: Any = PrefectFuture, max_depth: int = -1
108
- ) -> set[TaskRunInput]:
116
+ ) -> set[Union[TaskRunResult, FlowRunResult]]:
109
117
  """
110
118
  This function recurses through an expression to generate a set of any discernible
111
119
  task run inputs it finds in the data structure. It produces a set of all inputs
@@ -118,7 +126,7 @@ def collect_task_run_inputs_sync(
118
126
  """
119
127
  # TODO: This function needs to be updated to detect parameters and constants
120
128
 
121
- inputs: set[TaskRunInput] = set()
129
+ inputs: set[Union[TaskRunResult, FlowRunResult]] = set()
122
130
 
123
131
  def add_futures_and_states_to_inputs(obj: Any) -> None:
124
132
  if isinstance(obj, future_cls) and hasattr(obj, "task_run_id"):
@@ -138,9 +146,12 @@ def collect_task_run_inputs_sync(
138
146
  elif isinstance(obj, quote):
139
147
  raise StopVisiting
140
148
  else:
141
- state = get_state_for_result(obj)
142
- if state and state.state_details.task_run_id:
143
- inputs.add(TaskRunResult(id=state.state_details.task_run_id))
149
+ res = get_state_for_result(obj)
150
+ if res:
151
+ state, run_type = res
152
+ run_result = state.state_details.to_run_result(run_type)
153
+ if run_result:
154
+ inputs.add(run_result)
144
155
 
145
156
  visit_collection(
146
157
  expr,
@@ -299,12 +310,11 @@ def _is_result_record(data: Any) -> TypeIs[ResultRecord[Any]]:
299
310
  async def propose_state(
300
311
  client: "PrefectClient",
301
312
  state: State[Any],
313
+ flow_run_id: UUID,
302
314
  force: bool = False,
303
- task_run_id: Optional[UUID] = None,
304
- flow_run_id: Optional[UUID] = None,
305
315
  ) -> State[Any]:
306
316
  """
307
- Propose a new state for a flow run or task run, invoking Prefect orchestration logic.
317
+ Propose a new state for a flow run, invoking Prefect orchestration logic.
308
318
 
309
319
  If the proposed state is accepted, the provided `state` will be augmented with
310
320
  details and returned.
@@ -319,25 +329,21 @@ async def propose_state(
319
329
  error will be raised.
320
330
 
321
331
  Args:
322
- state: a new state for the task or flow run
323
- task_run_id: an optional task run id, used when proposing task run states
332
+ state: a new state for a flow run
324
333
  flow_run_id: an optional flow run id, used when proposing flow run states
325
334
 
326
335
  Returns:
327
- a [State model][prefect.client.schemas.objects.State] representation of the
328
- flow or task run state
336
+ a State model representation of the flow run state
329
337
 
330
338
  Raises:
331
- ValueError: if neither task_run_id or flow_run_id is provided
332
339
  prefect.exceptions.Abort: if an ABORT instruction is received from
333
340
  the Prefect API
334
341
  """
335
342
 
336
- # Determine if working with a task run or flow run
337
- if not task_run_id and not flow_run_id:
338
- raise ValueError("You must provide either a `task_run_id` or `flow_run_id`")
343
+ if not flow_run_id:
344
+ raise ValueError("You must provide a `flow_run_id`")
339
345
 
340
- # Handle task and sub-flow tracing
346
+ # Handle sub-flow tracing
341
347
  if state.is_final():
342
348
  result: Any
343
349
  if _is_result_record(state.data):
@@ -345,7 +351,7 @@ async def propose_state(
345
351
  else:
346
352
  result = state.data
347
353
 
348
- link_state_to_result(state, result)
354
+ link_state_to_flow_run_result(state, result)
349
355
 
350
356
  # Handle repeated WAITs in a loop instead of recursively, to avoid
351
357
  # reaching max recursion depth in extreme cases.
@@ -364,18 +370,8 @@ async def propose_state(
364
370
  response = await set_state_func()
365
371
  return response
366
372
 
367
- # Attempt to set the state
368
- if task_run_id:
369
- set_state = partial(client.set_task_run_state, task_run_id, state, force=force)
370
- response = await set_state_and_handle_waits(set_state)
371
- elif flow_run_id:
372
- set_state = partial(client.set_flow_run_state, flow_run_id, state, force=force)
373
- response = await set_state_and_handle_waits(set_state)
374
- else:
375
- raise ValueError(
376
- "Neither flow run id or task run id were provided. At least one must "
377
- "be given."
378
- )
373
+ set_state = partial(client.set_flow_run_state, flow_run_id, state, force=force)
374
+ response = await set_state_and_handle_waits(set_state)
379
375
 
380
376
  # Parse the response to return the new state
381
377
  if response.status == SetStateStatus.ACCEPT:
@@ -412,12 +408,11 @@ async def propose_state(
412
408
  def propose_state_sync(
413
409
  client: "SyncPrefectClient",
414
410
  state: State[Any],
411
+ flow_run_id: UUID,
415
412
  force: bool = False,
416
- task_run_id: Optional[UUID] = None,
417
- flow_run_id: Optional[UUID] = None,
418
413
  ) -> State[Any]:
419
414
  """
420
- Propose a new state for a flow run or task run, invoking Prefect orchestration logic.
415
+ Propose a new state for a flow run, invoking Prefect orchestration logic.
421
416
 
422
417
  If the proposed state is accepted, the provided `state` will be augmented with
423
418
  details and returned.
@@ -432,32 +427,26 @@ def propose_state_sync(
432
427
  error will be raised.
433
428
 
434
429
  Args:
435
- state: a new state for the task or flow run
436
- task_run_id: an optional task run id, used when proposing task run states
430
+ state: a new state for the flow run
437
431
  flow_run_id: an optional flow run id, used when proposing flow run states
438
432
 
439
433
  Returns:
440
- a [State model][prefect.client.schemas.objects.State] representation of the
441
- flow or task run state
434
+ a State model representation of the flow run state
442
435
 
443
436
  Raises:
444
- ValueError: if neither task_run_id or flow_run_id is provided
437
+ ValueError: if flow_run_id is not provided
445
438
  prefect.exceptions.Abort: if an ABORT instruction is received from
446
439
  the Prefect API
447
440
  """
448
441
 
449
- # Determine if working with a task run or flow run
450
- if not task_run_id and not flow_run_id:
451
- raise ValueError("You must provide either a `task_run_id` or `flow_run_id`")
452
-
453
- # Handle task and sub-flow tracing
442
+ # Handle sub-flow tracing
454
443
  if state.is_final():
455
444
  if _is_result_record(state.data):
456
445
  result = state.data.result
457
446
  else:
458
447
  result = state.data
459
448
 
460
- link_state_to_result(state, result)
449
+ link_state_to_flow_run_result(state, result)
461
450
 
462
451
  # Handle repeated WAITs in a loop instead of recursively, to avoid
463
452
  # reaching max recursion depth in extreme cases.
@@ -477,17 +466,8 @@ def propose_state_sync(
477
466
  return response
478
467
 
479
468
  # Attempt to set the state
480
- if task_run_id:
481
- set_state = partial(client.set_task_run_state, task_run_id, state, force=force)
482
- response = set_state_and_handle_waits(set_state)
483
- elif flow_run_id:
484
- set_state = partial(client.set_flow_run_state, flow_run_id, state, force=force)
485
- response = set_state_and_handle_waits(set_state)
486
- else:
487
- raise ValueError(
488
- "Neither flow run id or task run id were provided. At least one must "
489
- "be given."
490
- )
469
+ set_state = partial(client.set_flow_run_state, flow_run_id, state, force=force)
470
+ response = set_state_and_handle_waits(set_state)
491
471
 
492
472
  # Parse the response to return the new state
493
473
  if response.status == SetStateStatus.ACCEPT:
@@ -519,7 +499,7 @@ def propose_state_sync(
519
499
  )
520
500
 
521
501
 
522
- def get_state_for_result(obj: Any) -> Optional[State]:
502
+ def get_state_for_result(obj: Any) -> Optional[tuple[State, RunType]]:
523
503
  """
524
504
  Get the state related to a result object.
525
505
 
@@ -527,10 +507,20 @@ def get_state_for_result(obj: Any) -> Optional[State]:
527
507
  """
528
508
  flow_run_context = FlowRunContext.get()
529
509
  if flow_run_context:
530
- return flow_run_context.task_run_results.get(id(obj))
510
+ return flow_run_context.run_results.get(id(obj))
511
+
512
+
513
+ def link_state_to_flow_run_result(state: State, result: Any) -> None:
514
+ """Creates a link between a state and flow run result"""
515
+ link_state_to_result(state, result, RunType.FLOW_RUN)
516
+
517
+
518
+ def link_state_to_task_run_result(state: State, result: Any) -> None:
519
+ """Creates a link between a state and task run result"""
520
+ link_state_to_result(state, result, RunType.TASK_RUN)
531
521
 
532
522
 
533
- def link_state_to_result(state: State, result: Any) -> None:
523
+ def link_state_to_result(state: State, result: Any, run_type: RunType) -> None:
534
524
  """
535
525
  Caches a link between a state and a result and its components using
536
526
  the `id` of the components to map to the state. The cache is persisted to the
@@ -586,7 +576,7 @@ def link_state_to_result(state: State, result: Any) -> None:
586
576
  ):
587
577
  state.state_details.untrackable_result = True
588
578
  return
589
- flow_run_context.task_run_results[id(obj)] = linked_state
579
+ flow_run_context.run_results[id(obj)] = (linked_state, run_type)
590
580
 
591
581
  visit_collection(expr=result, visit_fn=link_if_trackable, max_depth=1)
592
582
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prefect-client
3
- Version: 3.4.7.dev5
3
+ Version: 3.4.7.dev7
4
4
  Summary: Workflow orchestration and management.
5
5
  Project-URL: Changelog, https://github.com/PrefectHQ/prefect/releases
6
6
  Project-URL: Documentation, https://docs.prefect.io
@@ -2,7 +2,7 @@ prefect/.prefectignore,sha256=awSprvKT0vI8a64mEOLrMxhxqcO-b0ERQeYpA2rNKVQ,390
2
2
  prefect/AGENTS.md,sha256=qmCZAuKIF9jQyp5TrW_T8bsM_97-QaiCoQp71A_b2Lg,1008
3
3
  prefect/__init__.py,sha256=iCdcC5ZmeewikCdnPEP6YBAjPNV5dvfxpYCTpw30Hkw,3685
4
4
  prefect/__main__.py,sha256=WFjw3kaYJY6pOTA7WDOgqjsz8zUEUZHCcj3P5wyVa-g,66
5
- prefect/_build_info.py,sha256=j5vWqNJWh9LFc4M6XTXV72BgaN0wiTsLUGw4b6gVmco,185
5
+ prefect/_build_info.py,sha256=cJqOi7wQGRupy4Rsu7Su9cZXMkfbV29ES1HTg1M-8LQ,185
6
6
  prefect/_result_records.py,sha256=S6QmsODkehGVSzbMm6ig022PYbI6gNKz671p_8kBYx4,7789
7
7
  prefect/_versioning.py,sha256=YqR5cxXrY4P6LM1Pmhd8iMo7v_G2KJpGNdsf4EvDFQ0,14132
8
8
  prefect/_waiters.py,sha256=Ia2ITaXdHzevtyWIgJoOg95lrEXQqNEOquHvw3T33UQ,9026
@@ -10,13 +10,13 @@ prefect/agent.py,sha256=dPvG1jDGD5HSH7aM2utwtk6RaJ9qg13XjkA0lAIgQmY,287
10
10
  prefect/artifacts.py,sha256=dMBUOAWnUamzjb5HSqwB5-GR2Qb-Gxee26XG5NDCUuw,22720
11
11
  prefect/automations.py,sha256=ZzPxn2tINdlXTQo805V4rIlbXuNWxd7cdb3gTJxZIeY,12567
12
12
  prefect/cache_policies.py,sha256=jH1aDW6vItTcsEytuTCrNYyjbq87IQPwdOgF0yxiUts,12749
13
- prefect/context.py,sha256=9IbfzBrhd6nqVicgcqeAqihRxKUYYZDg-psTByCYcZo,32589
13
+ prefect/context.py,sha256=2yhyJmomB0S8n18vCYZIykqZFmUAiqTH06qigAsoGtk,32648
14
14
  prefect/engine.py,sha256=uB5JN4l045i5JTlRQNT1x7MwlSiGQ5Bop2Q6jHHOgxY,3699
15
15
  prefect/exceptions.py,sha256=wZLQQMRB_DyiYkeEdIC5OKwbba5A94Dlnics-lrWI7A,11581
16
16
  prefect/filesystems.py,sha256=v5YqGB4uXf9Ew2VuB9VCSkawvYMMVvEtZf7w1VmAmr8,18036
17
- prefect/flow_engine.py,sha256=hZpTYEtwTPMtwVoTCrfD93igN7rlKeG_0kyCvdU4aYE,58876
17
+ prefect/flow_engine.py,sha256=JwnMqtrSgDVtsw4cyUOBkHhlNXhysb5SSNZtRe-NpqE,59100
18
18
  prefect/flow_runs.py,sha256=d3jfmrIPP3C19IJREvpkuN6fxksX3Lzo-LlHOB-_E2I,17419
19
- prefect/flows.py,sha256=xJKlXgVVdlZh45uE73PjA90qqmArVM2hzHgsniu02CY,120945
19
+ prefect/flows.py,sha256=zKmskX31aW8NlArC9QkbXsFGxatcdwQMIQe2PHHcDqQ,120984
20
20
  prefect/futures.py,sha256=U1SdxwOWNdQz_xtlZ6J-_zjRntxbqu7kz53YRov-Dew,25000
21
21
  prefect/main.py,sha256=8V-qLB4GjEVCkGRgGXeaIk-JIXY8Z9FozcNluj4Sm9E,2589
22
22
  prefect/plugins.py,sha256=FPRLR2mWVBMuOnlzeiTD9krlHONZH2rtYLD753JQDNQ,2516
@@ -25,11 +25,11 @@ prefect/results.py,sha256=Amm3TQu8U_oakSn__tCogIJ5DsTj0w_kLzuENWsxK6A,36824
25
25
  prefect/schedules.py,sha256=dhq4OhImRvcmtxF7UH1m8RbwYdHT5RQsp_FrxVXfODE,7289
26
26
  prefect/serializers.py,sha256=MICSdT_1iL2SSq9cYatJ8T7wqPS97uyw9ew5Fh86-NM,9789
27
27
  prefect/states.py,sha256=rh7l1bnIYpTXdlXt5nnpz66y9KLjBWAJrN9Eo5RwgQs,26023
28
- prefect/task_engine.py,sha256=j7i_UiLvijV4Vut1Bw5-72kSlOqAPxqeS7-3cMVEBPA,65509
29
- prefect/task_runners.py,sha256=ptgE5wuXg_IVHM0j7d6l7ELAVg3SXSy4vggnoHRF8dA,17040
28
+ prefect/task_engine.py,sha256=-uGGvLnXVeGNzA3Hki6-epUEY00P3l3QBXTcahjfEM4,65506
29
+ prefect/task_runners.py,sha256=Mc9KIbY2uqxQcO1XHPh6hId0Qk1ukjCaGHCn4LKo3tg,17000
30
30
  prefect/task_runs.py,sha256=7LIzfo3fondCyEUpU05sYFN5IfpZigBDXrhG5yc-8t0,9039
31
31
  prefect/task_worker.py,sha256=RifZ3bOl6ppoYPiOAd4TQp2_GEw9eDQoW483rq1q52Q,20805
32
- prefect/tasks.py,sha256=d4bJUiyNAtXqUotU7cHdk2IFV0OZQDdJ9jkkno8HdIs,78220
32
+ prefect/tasks.py,sha256=CKPF22f_6L5jQFtGgykMdTsQqwF7OnfWu5jjn1F-bLw,78165
33
33
  prefect/transactions.py,sha256=uIoPNudzJzH6NrMJhrgr5lyh6JxOJQqT1GvrXt69yNw,26068
34
34
  prefect/variables.py,sha256=dCK3vX7TbkqXZhnNT_v7rcGh3ISRqoR6pJVLpoll3Js,8342
35
35
  prefect/_experimental/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -91,7 +91,7 @@ prefect/client/collections.py,sha256=t9XkVU_onQMZ871L21F1oZnAiPSQeeVfd_MuDEBS3iM
91
91
  prefect/client/constants.py,sha256=Z_GG8KF70vbbXxpJuqW5pLnwzujTVeHbcYYRikNmGH0,29
92
92
  prefect/client/subscriptions.py,sha256=PTYi1Pp7rX-aGdcxZkxRBZkZnpzBt1P17APsm05EDR8,4376
93
93
  prefect/client/utilities.py,sha256=UEJD6nwYg2mD8-GSmru-E2ofXaBlmSFZ2-8T_5rIK6c,3472
94
- prefect/client/orchestration/__init__.py,sha256=lG3IW4XfbBkgZyPiSrxeyBhTqt3YfFcBHnEXDVrNmLs,56220
94
+ prefect/client/orchestration/__init__.py,sha256=vVTJKc79HFK1deKiQRY_4O2rLgeH99w3rcnCYp8y7Qc,56160
95
95
  prefect/client/orchestration/base.py,sha256=HM6ryHBZSzuHoCFQM9u5qR5k1dN9Bbr_ah6z1UPNbZQ,1542
96
96
  prefect/client/orchestration/routes.py,sha256=_-HC-EmgMhsYdmGwZTxIXlINaVzYuX7RZAvzjHbVp-4,4266
97
97
  prefect/client/orchestration/_artifacts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -107,21 +107,21 @@ prefect/client/orchestration/_blocks_types/client.py,sha256=alA4xD-yp3mycAbzMyRu
107
107
  prefect/client/orchestration/_concurrency_limits/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
108
108
  prefect/client/orchestration/_concurrency_limits/client.py,sha256=r_oyY7hQbgyG1rntwe7WWcsraQHBKhk6MOPFUAHWiVc,23678
109
109
  prefect/client/orchestration/_deployments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
110
- prefect/client/orchestration/_deployments/client.py,sha256=KMA_ldpBiUVqvV2-FSOgARyb3objs8MAAe1uD-RXcaE,48477
110
+ prefect/client/orchestration/_deployments/client.py,sha256=h42dzlVStzTcmnXtQfIVoKTI3rarsJgoQeSKnTwGIyg,48387
111
111
  prefect/client/orchestration/_flow_runs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
112
112
  prefect/client/orchestration/_flow_runs/client.py,sha256=fjh5J-LG8tsny7BGYEvynbuGuHDAudYHpx-PamL0GYQ,32220
113
113
  prefect/client/orchestration/_flows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
114
- prefect/client/orchestration/_flows/client.py,sha256=21rqVFm-AsqFK1S-vK2TyXKZ_oL65SN0_hiiddi6vIo,11006
114
+ prefect/client/orchestration/_flows/client.py,sha256=GLMT5qC_z-Ys7koz5UU5zYOPUOiXW7tUIBNgK7uY_Wc,10888
115
115
  prefect/client/orchestration/_logs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
116
116
  prefect/client/orchestration/_logs/client.py,sha256=DYgdeVV_6ORIOuqZapDWZXuFjIUtWreAyl2uHWpGZfA,2996
117
117
  prefect/client/orchestration/_variables/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
118
118
  prefect/client/orchestration/_variables/client.py,sha256=wKBbZBLGgs5feDCil-xxKt36dibUEB5Ll62uPtvQGmc,5284
119
119
  prefect/client/orchestration/_work_pools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
120
120
  prefect/client/orchestration/_work_pools/client.py,sha256=s1DfUQQBgB2sLiVVPhLNTlkueUDE6uFsh4mAzcSA1OE,19881
121
- prefect/client/schemas/__init__.py,sha256=InZcDzdeWA2oaV0TlyvoMcyLcbi_aaqU1U9D6Gx-eoU,2747
122
- prefect/client/schemas/actions.py,sha256=E46Mdq7vAq8hhYmMj6zqUF20uAPXZricViZcIYmgEf0,32443
123
- prefect/client/schemas/filters.py,sha256=qa--NNZduuSOcL1xw-YMd4FVIKMrDnBwPPY4m5Di0GA,35963
124
- prefect/client/schemas/objects.py,sha256=JYcHShcR4JUBjc1VrsMaJ0QYd3H9peXbXtT9U4Lhkc8,57708
121
+ prefect/client/schemas/__init__.py,sha256=9eCE4tzSxsB-uhXNagrb78jz1xtI4QPoZuH6TNav8M4,2831
122
+ prefect/client/schemas/actions.py,sha256=R6WwzxBj1SuwUqGX0g6zEDxtdoNR7lTQLSpytP2HOgA,32482
123
+ prefect/client/schemas/filters.py,sha256=uEGvai0VtrvUtojFME-oflQ1T-Diw-TUrQwk4PwBOtU,36085
124
+ prefect/client/schemas/objects.py,sha256=vL1yN-IqQynpVH9Sp0-aYyTfRHfy3eIsLnTAfw6aCbI,58215
125
125
  prefect/client/schemas/responses.py,sha256=Zdcx7jlIaluEa2uYIOE5mK1HsJvWPErRAcaWM20oY_I,17336
126
126
  prefect/client/schemas/schedules.py,sha256=sxLFk0SmFY7X1Y9R9HyGDqOS3U5NINBWTciUU7vTTic,14836
127
127
  prefect/client/schemas/sorting.py,sha256=L-2Mx-igZPtsUoRUguTcG3nIEstMEMPD97NwPM2Ox5s,2579
@@ -196,7 +196,7 @@ prefect/runner/_observers.py,sha256=PpyXQL5bjp86AnDFEzcFPS5ayL6ExqcYgyuBMMQCO9Q,
196
196
  prefect/runner/runner.py,sha256=bucchmFv7g4lYaxDyPtkRXZgyaBmyRpS23maMUT0AQg,59574
197
197
  prefect/runner/server.py,sha256=5vMIJcgunjiDVzJEig09yOP8EbhcW6s-9zNUt101b44,11994
198
198
  prefect/runner/storage.py,sha256=n-65YoEf7KNVInnmMPeP5TVFJOa2zOS8w9en9MHi6uo,31328
199
- prefect/runner/submit.py,sha256=b5n1M12DFQsxo6FazZnDbblRcIE7H3xrpecDMb4CjJY,9512
199
+ prefect/runner/submit.py,sha256=vJK4N7Vi1dd6Ts3_BkelyitP-lDelcSEjzqpqJhJO6g,9572
200
200
  prefect/runner/utils.py,sha256=19DbhyiV6nvSpTXmnWlt7qPNt1jrz1jscznYrRVGurw,3413
201
201
  prefect/runtime/__init__.py,sha256=JswiTlYRup2zXOYu8AqJ7czKtgcw9Kxo0tTbS6aWCqY,407
202
202
  prefect/runtime/deployment.py,sha256=0A_cUVpYiFk3ciJw2ixy95dk9xBJcjisyF69pakSCcQ,5091
@@ -302,7 +302,7 @@ prefect/utilities/compat.py,sha256=nnPA3lf2f4Y-l645tYFFNmj5NDPaYvjqa9pbGKZ3WKE,5
302
302
  prefect/utilities/context.py,sha256=23SDMgdt07SjmB1qShiykHfGgiv55NBzdbMXM3fE9CI,1447
303
303
  prefect/utilities/dispatch.py,sha256=u6GSGSO3_6vVoIqHVc849lsKkC-I1wUl6TX134GwRBo,6310
304
304
  prefect/utilities/dockerutils.py,sha256=6DLVyzE195IzeQSWERiK1t3bDMnYBLe0zXIpMQ4r0c0,21659
305
- prefect/utilities/engine.py,sha256=Ltu-Elpb6AjxPumjyqfl3yb2r61UMxO-l6zHXAZ5erM,29190
305
+ prefect/utilities/engine.py,sha256=nMtKaTDOIbMbUmDR3PcA_BOjOFKuginmrOERwfzub04,28316
306
306
  prefect/utilities/filesystem.py,sha256=Pwesv71PGFhf3lPa1iFyMqZZprBjy9nEKCVxTkf_hXw,5710
307
307
  prefect/utilities/generics.py,sha256=o77e8a5iwmrisOf42wLp2WI9YvSw2xDW4vFdpdEwr3I,543
308
308
  prefect/utilities/hashing.py,sha256=7jRy26s46IJAFRmVnCnoK9ek9N4p_UfXxQQvu2tW6dM,2589
@@ -329,7 +329,7 @@ prefect/workers/cloud.py,sha256=dPvG1jDGD5HSH7aM2utwtk6RaJ9qg13XjkA0lAIgQmY,287
329
329
  prefect/workers/process.py,sha256=Yi5D0U5AQ51wHT86GdwtImXSefe0gJf3LGq4r4z9zwM,11090
330
330
  prefect/workers/server.py,sha256=2pmVeJZiVbEK02SO6BEZaBIvHMsn6G8LzjW8BXyiTtk,1952
331
331
  prefect/workers/utilities.py,sha256=VfPfAlGtTuDj0-Kb8WlMgAuOfgXCdrGAnKMapPSBrwc,2483
332
- prefect_client-3.4.7.dev5.dist-info/METADATA,sha256=2MOLNYyWyvWP14kqrkU6eHZOXb2soCwenx0Oy3ie_zI,7517
333
- prefect_client-3.4.7.dev5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
334
- prefect_client-3.4.7.dev5.dist-info/licenses/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
335
- prefect_client-3.4.7.dev5.dist-info/RECORD,,
332
+ prefect_client-3.4.7.dev7.dist-info/METADATA,sha256=YJvQqTJ9Dj42ijE5NXHSfOkx0rZ7cSaNJyaRanfYQE8,7517
333
+ prefect_client-3.4.7.dev7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
334
+ prefect_client-3.4.7.dev7.dist-info/licenses/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
335
+ prefect_client-3.4.7.dev7.dist-info/RECORD,,