24
24
Callable ,
25
25
Coroutine ,
26
26
Generic ,
27
- Hashable ,
28
27
Iterable ,
29
28
NoReturn ,
30
29
Optional ,
43
42
from pydantic .v1 .decorator import ValidatedFunction as V1ValidatedFunction
44
43
from pydantic .v1 .errors import ConfigError # TODO
45
44
from rich .console import Console
46
- from typing_extensions import Literal , ParamSpec , Self
45
+ from typing_extensions import Literal , ParamSpec , TypeAlias
47
46
48
47
from prefect ._internal .concurrency .api import create_call , from_async
49
48
from prefect .blocks .core import Block
105
104
T = TypeVar ("T" ) # Generic type var for capturing the inner return type of async funcs
106
105
R = TypeVar ("R" ) # The return type of the user's function
107
106
P = ParamSpec ("P" ) # The parameters of the flow
108
- F = TypeVar ("F" , bound = "Flow" ) # The type of the flow
107
+ F = TypeVar ("F" , bound = "Flow[Any, Any]" ) # The type of the flow
108
+
109
+ StateHookCallable : TypeAlias = Callable [
110
+ [FlowSchema , FlowRun , State ], Union [Awaitable [None ], None ]
111
+ ]
109
112
110
113
logger = get_logger ("flows" )
111
114
@@ -195,15 +198,11 @@ def __init__(
195
198
result_serializer : Optional [ResultSerializer ] = None ,
196
199
cache_result_in_memory : bool = True ,
197
200
log_prints : Optional [bool ] = None ,
198
- on_completion : Optional [
199
- list [Callable [[FlowSchema , FlowRun , State ], None ]]
200
- ] = None ,
201
- on_failure : Optional [list [Callable [[FlowSchema , FlowRun , State ], None ]]] = None ,
202
- on_cancellation : Optional [
203
- list [Callable [[FlowSchema , FlowRun , State ], None ]]
204
- ] = None ,
205
- on_crashed : Optional [list [Callable [[FlowSchema , FlowRun , State ], None ]]] = None ,
206
- on_running : Optional [list [Callable [[FlowSchema , FlowRun , State ], None ]]] = None ,
201
+ on_completion : Optional [list [StateHookCallable ]] = None ,
202
+ on_failure : Optional [list [StateHookCallable ]] = None ,
203
+ on_cancellation : Optional [list [StateHookCallable ]] = None ,
204
+ on_crashed : Optional [list [StateHookCallable ]] = None ,
205
+ on_running : Optional [list [StateHookCallable ]] = None ,
207
206
):
208
207
if name is not None and not isinstance (name , str ):
209
208
raise TypeError (
@@ -375,7 +374,7 @@ def __init__(
375
374
def ismethod (self ) -> bool :
376
375
return hasattr (self .fn , "__prefect_self__" )
377
376
378
- def __get__ (self , instance , owner ):
377
+ def __get__ (self , instance : Any , owner : Any ):
379
378
"""
380
379
Implement the descriptor protocol so that the flow can be used as an instance method.
381
380
When an instance method is loaded, this method is called with the "self" instance as
@@ -402,24 +401,22 @@ def with_options(
402
401
retry_delay_seconds : Optional [Union [int , float ]] = None ,
403
402
description : Optional [str ] = None ,
404
403
flow_run_name : Optional [Union [Callable [[], str ], str ]] = None ,
405
- task_runner : Union [Type [TaskRunner ], TaskRunner , None ] = None ,
404
+ task_runner : Union [
405
+ Type [TaskRunner [PrefectFuture [R ]]], TaskRunner [PrefectFuture [R ]], None
406
+ ] = None ,
406
407
timeout_seconds : Union [int , float , None ] = None ,
407
408
validate_parameters : Optional [bool ] = None ,
408
409
persist_result : Optional [bool ] = NotSet , # type: ignore
409
410
result_storage : Optional [ResultStorage ] = NotSet , # type: ignore
410
411
result_serializer : Optional [ResultSerializer ] = NotSet , # type: ignore
411
412
cache_result_in_memory : Optional [bool ] = None ,
412
413
log_prints : Optional [bool ] = NotSet , # type: ignore
413
- on_completion : Optional [
414
- list [Callable [[FlowSchema , FlowRun , State ], None ]]
415
- ] = None ,
416
- on_failure : Optional [list [Callable [[FlowSchema , FlowRun , State ], None ]]] = None ,
417
- on_cancellation : Optional [
418
- list [Callable [[FlowSchema , FlowRun , State ], None ]]
419
- ] = None ,
420
- on_crashed : Optional [list [Callable [[FlowSchema , FlowRun , State ], None ]]] = None ,
421
- on_running : Optional [list [Callable [[FlowSchema , FlowRun , State ], None ]]] = None ,
422
- ) -> Self :
414
+ on_completion : Optional [list [StateHookCallable ]] = None ,
415
+ on_failure : Optional [list [StateHookCallable ]] = None ,
416
+ on_cancellation : Optional [list [StateHookCallable ]] = None ,
417
+ on_crashed : Optional [list [StateHookCallable ]] = None ,
418
+ on_running : Optional [list [StateHookCallable ]] = None ,
419
+ ) -> "Flow[P, R]" :
423
420
"""
424
421
Create a new flow from the current object, updating provided options.
425
422
@@ -645,7 +642,7 @@ async def to_deployment(
645
642
paused : Optional [bool ] = None ,
646
643
schedules : Optional ["FlexibleScheduleList" ] = None ,
647
644
concurrency_limit : Optional [Union [int , ConcurrencyLimitConfig , None ]] = None ,
648
- parameters : Optional [dict ] = None ,
645
+ parameters : Optional [dict [ str , Any ] ] = None ,
649
646
triggers : Optional [list [Union [DeploymentTriggerTypes , TriggerTypes ]]] = None ,
650
647
description : Optional [str ] = None ,
651
648
tags : Optional [list [str ]] = None ,
@@ -755,33 +752,23 @@ def my_other_flow(name):
755
752
entrypoint_type = entrypoint_type ,
756
753
)
757
754
758
- def on_completion (
759
- self , fn : Callable [[FlowSchema , FlowRun , State ], None ]
760
- ) -> Callable [[FlowSchema , FlowRun , State ], None ]:
755
+ def on_completion (self , fn : StateHookCallable ) -> StateHookCallable :
761
756
self .on_completion_hooks .append (fn )
762
757
return fn
763
758
764
- def on_cancellation (
765
- self , fn : Callable [[FlowSchema , FlowRun , State ], None ]
766
- ) -> Callable [[FlowSchema , FlowRun , State ], None ]:
759
+ def on_cancellation (self , fn : StateHookCallable ) -> StateHookCallable :
767
760
self .on_cancellation_hooks .append (fn )
768
761
return fn
769
762
770
- def on_crashed (
771
- self , fn : Callable [[FlowSchema , FlowRun , State ], None ]
772
- ) -> Callable [[FlowSchema , FlowRun , State ], None ]:
763
+ def on_crashed (self , fn : StateHookCallable ) -> StateHookCallable :
773
764
self .on_crashed_hooks .append (fn )
774
765
return fn
775
766
776
- def on_running (
777
- self , fn : Callable [[FlowSchema , FlowRun , State ], None ]
778
- ) -> Callable [[FlowSchema , FlowRun , State ], None ]:
767
+ def on_running (self , fn : StateHookCallable ) -> StateHookCallable :
779
768
self .on_running_hooks .append (fn )
780
769
return fn
781
770
782
- def on_failure (
783
- self , fn : Callable [[FlowSchema , FlowRun , State ], None ]
784
- ) -> Callable [[FlowSchema , FlowRun , State ], None ]:
771
+ def on_failure (self , fn : StateHookCallable ) -> StateHookCallable :
785
772
self .on_failure_hooks .append (fn )
786
773
return fn
787
774
@@ -1039,8 +1026,11 @@ def my_flow(name: str = "world"):
1039
1026
await storage .pull_code ()
1040
1027
1041
1028
full_entrypoint = str (storage .destination / entrypoint )
1042
- flow : Flow = await from_async .wait_for_call_in_new_thread (
1043
- create_call (load_flow_from_entrypoint , full_entrypoint )
1029
+ flow = cast (
1030
+ Flow [P , R ],
1031
+ await from_async .wait_for_call_in_new_thread (
1032
+ create_call (load_flow_from_entrypoint , full_entrypoint )
1033
+ ),
1044
1034
)
1045
1035
flow ._storage = storage
1046
1036
flow ._entrypoint = entrypoint
@@ -1442,17 +1432,11 @@ def flow(
1442
1432
result_serializer : Optional [ResultSerializer ] = None ,
1443
1433
cache_result_in_memory : bool = True ,
1444
1434
log_prints : Optional [bool ] = None ,
1445
- on_completion : Optional [
1446
- list [Callable [[FlowSchema , FlowRun , State ], Union [Awaitable [None ], None ]]]
1447
- ] = None ,
1448
- on_failure : Optional [
1449
- list [Callable [[FlowSchema , FlowRun , State ], Union [Awaitable [None ], None ]]]
1450
- ] = None ,
1451
- on_cancellation : Optional [
1452
- list [Callable [[FlowSchema , FlowRun , State ], None ]]
1453
- ] = None ,
1454
- on_crashed : Optional [list [Callable [[FlowSchema , FlowRun , State ], None ]]] = None ,
1455
- on_running : Optional [list [Callable [[FlowSchema , FlowRun , State ], None ]]] = None ,
1435
+ on_completion : Optional [list [StateHookCallable ]] = None ,
1436
+ on_failure : Optional [list [StateHookCallable ]] = None ,
1437
+ on_cancellation : Optional [list [StateHookCallable ]] = None ,
1438
+ on_crashed : Optional [list [StateHookCallable ]] = None ,
1439
+ on_running : Optional [list [StateHookCallable ]] = None ,
1456
1440
) -> Callable [[Callable [P , R ]], Flow [P , R ]]:
1457
1441
...
1458
1442
@@ -1474,17 +1458,11 @@ def flow(
1474
1458
result_serializer : Optional [ResultSerializer ] = None ,
1475
1459
cache_result_in_memory : bool = True ,
1476
1460
log_prints : Optional [bool ] = None ,
1477
- on_completion : Optional [
1478
- list [Callable [[FlowSchema , FlowRun , State ], Union [Awaitable [None ], None ]]]
1479
- ] = None ,
1480
- on_failure : Optional [
1481
- list [Callable [[FlowSchema , FlowRun , State ], Union [Awaitable [None ], None ]]]
1482
- ] = None ,
1483
- on_cancellation : Optional [
1484
- list [Callable [[FlowSchema , FlowRun , State ], None ]]
1485
- ] = None ,
1486
- on_crashed : Optional [list [Callable [[FlowSchema , FlowRun , State ], None ]]] = None ,
1487
- on_running : Optional [list [Callable [[FlowSchema , FlowRun , State ], None ]]] = None ,
1461
+ on_completion : Optional [list [StateHookCallable ]] = None ,
1462
+ on_failure : Optional [list [StateHookCallable ]] = None ,
1463
+ on_cancellation : Optional [list [StateHookCallable ]] = None ,
1464
+ on_crashed : Optional [list [StateHookCallable ]] = None ,
1465
+ on_running : Optional [list [StateHookCallable ]] = None ,
1488
1466
):
1489
1467
"""
1490
1468
Decorator to designate a function as a Prefect workflow.
@@ -1593,30 +1571,27 @@ def flow(
1593
1571
if isinstance (__fn , (classmethod , staticmethod )):
1594
1572
method_decorator = type (__fn ).__name__
1595
1573
raise TypeError (f"@{ method_decorator } should be applied on top of @flow" )
1596
- return cast (
1597
- Flow [P , R ],
1598
- Flow (
1599
- fn = __fn ,
1600
- name = name ,
1601
- version = version ,
1602
- flow_run_name = flow_run_name ,
1603
- task_runner = task_runner ,
1604
- description = description ,
1605
- timeout_seconds = timeout_seconds ,
1606
- validate_parameters = validate_parameters ,
1607
- retries = retries ,
1608
- retry_delay_seconds = retry_delay_seconds ,
1609
- persist_result = persist_result ,
1610
- result_storage = result_storage ,
1611
- result_serializer = result_serializer ,
1612
- cache_result_in_memory = cache_result_in_memory ,
1613
- log_prints = log_prints ,
1614
- on_completion = on_completion ,
1615
- on_failure = on_failure ,
1616
- on_cancellation = on_cancellation ,
1617
- on_crashed = on_crashed ,
1618
- on_running = on_running ,
1619
- ),
1574
+ return Flow (
1575
+ fn = __fn ,
1576
+ name = name ,
1577
+ version = version ,
1578
+ flow_run_name = flow_run_name ,
1579
+ task_runner = task_runner ,
1580
+ description = description ,
1581
+ timeout_seconds = timeout_seconds ,
1582
+ validate_parameters = validate_parameters ,
1583
+ retries = retries ,
1584
+ retry_delay_seconds = retry_delay_seconds ,
1585
+ persist_result = persist_result ,
1586
+ result_storage = result_storage ,
1587
+ result_serializer = result_serializer ,
1588
+ cache_result_in_memory = cache_result_in_memory ,
1589
+ log_prints = log_prints ,
1590
+ on_completion = on_completion ,
1591
+ on_failure = on_failure ,
1592
+ on_cancellation = on_cancellation ,
1593
+ on_crashed = on_crashed ,
1594
+ on_running = on_running ,
1620
1595
)
1621
1596
else :
1622
1597
return cast (
@@ -1668,10 +1643,10 @@ def _raise_on_name_with_banned_characters(name: Optional[str]) -> Optional[str]:
1668
1643
1669
1644
1670
1645
def select_flow (
1671
- flows : Iterable [Flow ],
1646
+ flows : Iterable [Flow [ P , R ] ],
1672
1647
flow_name : Optional [str ] = None ,
1673
1648
from_message : Optional [str ] = None ,
1674
- ) -> Flow :
1649
+ ) -> Flow [ P , R ] :
1675
1650
"""
1676
1651
Select the only flow in an iterable or a flow specified by name.
1677
1652
@@ -1716,7 +1691,7 @@ def select_flow(
1716
1691
def load_flow_from_entrypoint (
1717
1692
entrypoint : str ,
1718
1693
use_placeholder_flow : bool = True ,
1719
- ) -> Flow :
1694
+ ) -> Flow [ P , Any ] :
1720
1695
"""
1721
1696
Extract a flow object from a script at an entrypoint by running all of the code in the file.
1722
1697
@@ -1740,7 +1715,7 @@ def load_flow_from_entrypoint(
1740
1715
else :
1741
1716
path , func_name = entrypoint .rsplit ("." , maxsplit = 1 )
1742
1717
try :
1743
- flow = import_object (entrypoint )
1718
+ flow : Flow [ P , Any ] = import_object (entrypoint ) # pyright: ignore[reportRedeclaration]
1744
1719
except AttributeError as exc :
1745
1720
raise MissingFlowError (
1746
1721
f"Flow function with name { func_name !r} not found in { path !r} . "
@@ -1749,13 +1724,13 @@ def load_flow_from_entrypoint(
1749
1724
# If the flow has dependencies that are not installed in the current
1750
1725
# environment, fallback to loading the flow via AST parsing.
1751
1726
if use_placeholder_flow :
1752
- flow = safe_load_flow_from_entrypoint (entrypoint )
1727
+ flow : Optional [ Flow [ P , Any ]] = safe_load_flow_from_entrypoint (entrypoint )
1753
1728
if flow is None :
1754
1729
raise
1755
1730
else :
1756
1731
raise
1757
1732
1758
- if not isinstance (flow , Flow ):
1733
+ if not isinstance (flow , Flow ): # pyright: ignore[reportUnnecessaryIsInstance]
1759
1734
raise MissingFlowError (
1760
1735
f"Function with name { func_name !r} is not a flow. Make sure that it is "
1761
1736
"decorated with '@flow'."
@@ -1770,7 +1745,7 @@ def serve(
1770
1745
print_starting_message : bool = True ,
1771
1746
limit : Optional [int ] = None ,
1772
1747
** kwargs : Any ,
1773
- ):
1748
+ ) -> None :
1774
1749
"""
1775
1750
Serve the provided list of deployments.
1776
1751
@@ -1840,7 +1815,7 @@ async def aserve(
1840
1815
print_starting_message : bool = True ,
1841
1816
limit : Optional [int ] = None ,
1842
1817
** kwargs : Any ,
1843
- ):
1818
+ ) -> None :
1844
1819
"""
1845
1820
Asynchronously serve the provided list of deployments.
1846
1821
@@ -1945,7 +1920,7 @@ async def load_flow_from_flow_run(
1945
1920
ignore_storage : bool = False ,
1946
1921
storage_base_path : Optional [str ] = None ,
1947
1922
use_placeholder_flow : bool = True ,
1948
- ) -> Flow :
1923
+ ) -> Flow [ P , Any ] :
1949
1924
"""
1950
1925
Load a flow from the location/script provided in a deployment's storage document.
1951
1926
@@ -2024,7 +1999,7 @@ async def load_flow_from_flow_run(
2024
1999
return flow
2025
2000
2026
2001
2027
- def load_placeholder_flow (entrypoint : str , raises : Exception ):
2002
+ def load_placeholder_flow (entrypoint : str , raises : Exception ) -> Flow [ P , Any ] :
2028
2003
"""
2029
2004
Load a placeholder flow that is initialized with the same arguments as the
2030
2005
flow specified in the entrypoint. If called the flow will raise `raises`.
@@ -2202,7 +2177,7 @@ def _sanitize_and_load_flow(
2202
2177
2203
2178
def load_flow_arguments_from_entrypoint (
2204
2179
entrypoint : str , arguments : Optional [Union [list [str ], set [str ]]] = None
2205
- ) -> dict [Hashable , Any ]:
2180
+ ) -> dict [str , Any ]:
2206
2181
"""
2207
2182
Extract flow arguments from an entrypoint string.
2208
2183
@@ -2235,7 +2210,7 @@ def load_flow_arguments_from_entrypoint(
2235
2210
"log_prints" ,
2236
2211
}
2237
2212
2238
- result : dict [Hashable , Any ] = {}
2213
+ result : dict [str , Any ] = {}
2239
2214
2240
2215
for decorator in func_def .decorator_list :
2241
2216
if (
@@ -2248,7 +2223,7 @@ def load_flow_arguments_from_entrypoint(
2248
2223
2249
2224
if isinstance (keyword .value , ast .Constant ):
2250
2225
# Use the string value of the argument
2251
- result [keyword .arg ] = str (keyword .value .value )
2226
+ result [cast ( str , keyword .arg ) ] = str (keyword .value .value )
2252
2227
continue
2253
2228
2254
2229
# if the arg value is not a raw str (i.e. a variable or expression),
@@ -2261,7 +2236,7 @@ def load_flow_arguments_from_entrypoint(
2261
2236
2262
2237
try :
2263
2238
evaluated_value = eval (cleaned_value , namespace ) # type: ignore
2264
- result [keyword .arg ] = str (evaluated_value )
2239
+ result [cast ( str , keyword .arg ) ] = str (evaluated_value )
2265
2240
except Exception as e :
2266
2241
logger .info (
2267
2242
"Failed to parse @flow argument: `%s=%s` due to the following error. Ignoring and falling back to default behavior." ,
0 commit comments