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 +3 -3
- prefect/client/orchestration/__init__.py +5 -9
- prefect/client/orchestration/_deployments/client.py +2 -2
- prefect/client/orchestration/_flows/client.py +4 -4
- prefect/client/schemas/__init__.py +5 -2
- prefect/client/schemas/actions.py +1 -0
- prefect/client/schemas/filters.py +3 -0
- prefect/client/schemas/objects.py +27 -6
- prefect/context.py +6 -4
- prefect/flow_engine.py +6 -3
- prefect/flows.py +64 -45
- prefect/runner/submit.py +10 -4
- prefect/task_engine.py +17 -17
- prefect/task_runners.py +10 -10
- prefect/tasks.py +11 -9
- prefect/utilities/engine.py +56 -66
- {prefect_client-3.4.7.dev5.dist-info → prefect_client-3.4.7.dev7.dist-info}/METADATA +1 -1
- {prefect_client-3.4.7.dev5.dist-info → prefect_client-3.4.7.dev7.dist-info}/RECORD +20 -20
- {prefect_client-3.4.7.dev5.dist-info → prefect_client-3.4.7.dev7.dist-info}/WHEEL +0 -0
- {prefect_client-3.4.7.dev5.dist-info → prefect_client-3.4.7.dev7.dist-info}/licenses/LICENSE +0 -0
prefect/_build_info.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Generated by versioningit
|
2
|
-
__version__ = "3.4.7.
|
3
|
-
__build_date__ = "2025-06-
|
4
|
-
__git_commit__ = "
|
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
|
-
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
-
|
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
|
-
"
|
76
|
+
"RunInput",
|
74
77
|
"TaskRunPolicy",
|
75
78
|
"TaskRunResult",
|
76
79
|
"Workspace",
|
@@ -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
|
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(
|
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
|
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(
|
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[
|
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
|
-
|
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
|
398
|
-
# Holds the ID of the object returned by
|
399
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
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
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
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
|
-
|
1657
|
-
|
1658
|
-
|
1659
|
-
|
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
|
-
|
1664
|
-
|
1665
|
-
|
1668
|
+
```python
|
1669
|
+
my_flow("marvin")
|
1670
|
+
```
|
1666
1671
|
|
1667
1672
|
Run a flow with additional tags
|
1668
1673
|
|
1669
|
-
|
1670
|
-
|
1671
|
-
|
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
|
-
|
1911
|
-
|
1912
|
-
|
1913
|
-
|
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
|
-
|
1918
|
-
|
1919
|
-
|
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
|
-
|
1924
|
-
|
1925
|
-
|
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
|
-
|
1930
|
-
|
1931
|
-
|
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
|
-
|
1936
|
-
|
1937
|
-
|
1938
|
-
|
1939
|
-
|
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
|
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[
|
70
|
-
|
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
|
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
|
-
|
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
|
-
|
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[
|
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[
|
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
|
-
|
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[
|
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[
|
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[
|
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[
|
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[
|
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
|
-
|
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[
|
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
|
-
|
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[
|
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[
|
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[
|
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
|
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[
|
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[
|
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[
|
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[
|
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[
|
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[
|
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[
|
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[
|
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[
|
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
|
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
|
-
|
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[
|
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[
|
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[
|
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.
|
prefect/utilities/engine.py
CHANGED
@@ -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
|
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(
|
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
|
-
|
93
|
-
if
|
94
|
-
|
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[
|
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[
|
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
|
-
|
142
|
-
if
|
143
|
-
|
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
|
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
|
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
|
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
|
-
|
337
|
-
|
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
|
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
|
-
|
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
|
-
|
368
|
-
|
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
|
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
|
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
|
441
|
-
flow or task run state
|
434
|
+
a State model representation of the flow run state
|
442
435
|
|
443
436
|
Raises:
|
444
|
-
ValueError: if
|
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
|
-
#
|
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
|
-
|
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
|
-
|
481
|
-
|
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.
|
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.
|
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
|
|
@@ -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=
|
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=
|
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=
|
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=
|
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
|
29
|
-
prefect/task_runners.py,sha256=
|
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=
|
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=
|
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=
|
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=
|
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=
|
122
|
-
prefect/client/schemas/actions.py,sha256=
|
123
|
-
prefect/client/schemas/filters.py,sha256=
|
124
|
-
prefect/client/schemas/objects.py,sha256=
|
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=
|
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=
|
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.
|
333
|
-
prefect_client-3.4.7.
|
334
|
-
prefect_client-3.4.7.
|
335
|
-
prefect_client-3.4.7.
|
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,,
|
File without changes
|
{prefect_client-3.4.7.dev5.dist-info → prefect_client-3.4.7.dev7.dist-info}/licenses/LICENSE
RENAMED
File without changes
|