prefect-client 3.1.15__py3-none-any.whl → 3.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. prefect/_experimental/sla/objects.py +29 -1
  2. prefect/_internal/compatibility/deprecated.py +4 -4
  3. prefect/_internal/compatibility/migration.py +1 -1
  4. prefect/_internal/concurrency/calls.py +1 -2
  5. prefect/_internal/concurrency/cancellation.py +2 -4
  6. prefect/_internal/concurrency/threads.py +3 -3
  7. prefect/_internal/schemas/bases.py +3 -11
  8. prefect/_internal/schemas/validators.py +36 -60
  9. prefect/_result_records.py +235 -0
  10. prefect/_version.py +3 -3
  11. prefect/agent.py +1 -0
  12. prefect/automations.py +4 -8
  13. prefect/blocks/notifications.py +8 -8
  14. prefect/cache_policies.py +2 -0
  15. prefect/client/base.py +7 -8
  16. prefect/client/collections.py +3 -6
  17. prefect/client/orchestration/__init__.py +15 -263
  18. prefect/client/orchestration/_deployments/client.py +14 -6
  19. prefect/client/orchestration/_flow_runs/client.py +10 -6
  20. prefect/client/orchestration/_work_pools/__init__.py +0 -0
  21. prefect/client/orchestration/_work_pools/client.py +598 -0
  22. prefect/client/orchestration/base.py +9 -2
  23. prefect/client/schemas/actions.py +66 -2
  24. prefect/client/schemas/objects.py +22 -50
  25. prefect/client/schemas/schedules.py +7 -18
  26. prefect/client/types/flexible_schedule_list.py +2 -1
  27. prefect/context.py +2 -3
  28. prefect/deployments/flow_runs.py +1 -1
  29. prefect/deployments/runner.py +119 -43
  30. prefect/deployments/schedules.py +7 -1
  31. prefect/engine.py +4 -9
  32. prefect/events/schemas/automations.py +4 -2
  33. prefect/events/utilities.py +15 -13
  34. prefect/exceptions.py +1 -1
  35. prefect/flow_engine.py +19 -10
  36. prefect/flow_runs.py +4 -8
  37. prefect/flows.py +53 -22
  38. prefect/infrastructure/__init__.py +1 -0
  39. prefect/infrastructure/base.py +1 -0
  40. prefect/infrastructure/provisioners/__init__.py +3 -6
  41. prefect/infrastructure/provisioners/coiled.py +3 -3
  42. prefect/infrastructure/provisioners/container_instance.py +1 -0
  43. prefect/infrastructure/provisioners/ecs.py +6 -6
  44. prefect/infrastructure/provisioners/modal.py +3 -3
  45. prefect/input/run_input.py +5 -7
  46. prefect/locking/filesystem.py +4 -3
  47. prefect/main.py +1 -1
  48. prefect/results.py +42 -249
  49. prefect/runner/runner.py +9 -4
  50. prefect/runner/server.py +5 -5
  51. prefect/runner/storage.py +12 -10
  52. prefect/runner/submit.py +2 -4
  53. prefect/schedules.py +231 -0
  54. prefect/serializers.py +5 -5
  55. prefect/settings/__init__.py +2 -1
  56. prefect/settings/base.py +3 -3
  57. prefect/settings/models/root.py +4 -0
  58. prefect/settings/models/server/services.py +50 -9
  59. prefect/settings/sources.py +8 -4
  60. prefect/states.py +42 -11
  61. prefect/task_engine.py +10 -10
  62. prefect/task_runners.py +11 -22
  63. prefect/task_worker.py +9 -9
  64. prefect/tasks.py +22 -41
  65. prefect/telemetry/bootstrap.py +4 -6
  66. prefect/telemetry/services.py +2 -4
  67. prefect/types/__init__.py +2 -1
  68. prefect/types/_datetime.py +28 -1
  69. prefect/utilities/_engine.py +0 -1
  70. prefect/utilities/asyncutils.py +4 -8
  71. prefect/utilities/collections.py +13 -22
  72. prefect/utilities/dispatch.py +2 -4
  73. prefect/utilities/dockerutils.py +6 -6
  74. prefect/utilities/importtools.py +1 -68
  75. prefect/utilities/names.py +1 -1
  76. prefect/utilities/processutils.py +3 -6
  77. prefect/utilities/pydantic.py +4 -6
  78. prefect/utilities/schema_tools/hydration.py +6 -5
  79. prefect/utilities/templating.py +16 -10
  80. prefect/utilities/visualization.py +2 -4
  81. prefect/workers/base.py +3 -3
  82. prefect/workers/block.py +1 -0
  83. prefect/workers/cloud.py +1 -0
  84. prefect/workers/process.py +1 -0
  85. {prefect_client-3.1.15.dist-info → prefect_client-3.2.1.dist-info}/METADATA +1 -1
  86. {prefect_client-3.1.15.dist-info → prefect_client-3.2.1.dist-info}/RECORD +89 -85
  87. {prefect_client-3.1.15.dist-info → prefect_client-3.2.1.dist-info}/LICENSE +0 -0
  88. {prefect_client-3.1.15.dist-info → prefect_client-3.2.1.dist-info}/WHEEL +0 -0
  89. {prefect_client-3.1.15.dist-info → prefect_client-3.2.1.dist-info}/top_level.txt +0 -0
prefect/task_runners.py CHANGED
@@ -84,8 +84,7 @@ class TaskRunner(abc.ABC, Generic[F]):
84
84
  parameters: dict[str, Any],
85
85
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
86
86
  dependencies: dict[str, set[TaskRunInput]] | None = None,
87
- ) -> F:
88
- ...
87
+ ) -> F: ...
89
88
 
90
89
  @overload
91
90
  @abc.abstractmethod
@@ -95,8 +94,7 @@ class TaskRunner(abc.ABC, Generic[F]):
95
94
  parameters: dict[str, Any],
96
95
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
97
96
  dependencies: dict[str, set[TaskRunInput]] | None = None,
98
- ) -> F:
99
- ...
97
+ ) -> F: ...
100
98
 
101
99
  @abc.abstractmethod
102
100
  def submit(
@@ -105,8 +103,7 @@ class TaskRunner(abc.ABC, Generic[F]):
105
103
  parameters: dict[str, Any],
106
104
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
107
105
  dependencies: dict[str, set[TaskRunInput]] | None = None,
108
- ) -> F:
109
- ...
106
+ ) -> F: ...
110
107
 
111
108
  def map(
112
109
  self,
@@ -251,8 +248,7 @@ class ThreadPoolTaskRunner(TaskRunner[PrefectConcurrentFuture[R]]):
251
248
  parameters: dict[str, Any],
252
249
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
253
250
  dependencies: dict[str, set[TaskRunInput]] | None = None,
254
- ) -> PrefectConcurrentFuture[R]:
255
- ...
251
+ ) -> PrefectConcurrentFuture[R]: ...
256
252
 
257
253
  @overload
258
254
  def submit(
@@ -261,8 +257,7 @@ class ThreadPoolTaskRunner(TaskRunner[PrefectConcurrentFuture[R]]):
261
257
  parameters: dict[str, Any],
262
258
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
263
259
  dependencies: dict[str, set[TaskRunInput]] | None = None,
264
- ) -> PrefectConcurrentFuture[R]:
265
- ...
260
+ ) -> PrefectConcurrentFuture[R]: ...
266
261
 
267
262
  def submit(
268
263
  self,
@@ -337,8 +332,7 @@ class ThreadPoolTaskRunner(TaskRunner[PrefectConcurrentFuture[R]]):
337
332
  task: "Task[P, Coroutine[Any, Any, R]]",
338
333
  parameters: dict[str, Any],
339
334
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
340
- ) -> PrefectFutureList[PrefectConcurrentFuture[R]]:
341
- ...
335
+ ) -> PrefectFutureList[PrefectConcurrentFuture[R]]: ...
342
336
 
343
337
  @overload
344
338
  def map(
@@ -346,8 +340,7 @@ class ThreadPoolTaskRunner(TaskRunner[PrefectConcurrentFuture[R]]):
346
340
  task: "Task[Any, R]",
347
341
  parameters: dict[str, Any],
348
342
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
349
- ) -> PrefectFutureList[PrefectConcurrentFuture[R]]:
350
- ...
343
+ ) -> PrefectFutureList[PrefectConcurrentFuture[R]]: ...
351
344
 
352
345
  def map(
353
346
  self,
@@ -402,8 +395,7 @@ class PrefectTaskRunner(TaskRunner[PrefectDistributedFuture[R]]):
402
395
  parameters: dict[str, Any],
403
396
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
404
397
  dependencies: dict[str, set[TaskRunInput]] | None = None,
405
- ) -> PrefectDistributedFuture[R]:
406
- ...
398
+ ) -> PrefectDistributedFuture[R]: ...
407
399
 
408
400
  @overload
409
401
  def submit(
@@ -412,8 +404,7 @@ class PrefectTaskRunner(TaskRunner[PrefectDistributedFuture[R]]):
412
404
  parameters: dict[str, Any],
413
405
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
414
406
  dependencies: dict[str, set[TaskRunInput]] | None = None,
415
- ) -> PrefectDistributedFuture[R]:
416
- ...
407
+ ) -> PrefectDistributedFuture[R]: ...
417
408
 
418
409
  def submit(
419
410
  self,
@@ -458,8 +449,7 @@ class PrefectTaskRunner(TaskRunner[PrefectDistributedFuture[R]]):
458
449
  task: "Task[P, Coroutine[Any, Any, R]]",
459
450
  parameters: dict[str, Any],
460
451
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
461
- ) -> PrefectFutureList[PrefectDistributedFuture[R]]:
462
- ...
452
+ ) -> PrefectFutureList[PrefectDistributedFuture[R]]: ...
463
453
 
464
454
  @overload
465
455
  def map(
@@ -467,8 +457,7 @@ class PrefectTaskRunner(TaskRunner[PrefectDistributedFuture[R]]):
467
457
  task: "Task[Any, R]",
468
458
  parameters: dict[str, Any],
469
459
  wait_for: Iterable[PrefectFuture[Any]] | None = None,
470
- ) -> PrefectFutureList[PrefectDistributedFuture[R]]:
471
- ...
460
+ ) -> PrefectFutureList[PrefectDistributedFuture[R]]: ...
472
461
 
473
462
  def map(
474
463
  self,
prefect/task_worker.py CHANGED
@@ -14,7 +14,6 @@ from uuid import UUID
14
14
 
15
15
  import anyio
16
16
  import anyio.abc
17
- import pendulum
18
17
  import uvicorn
19
18
  from exceptiongroup import BaseExceptionGroup # novermin
20
19
  from fastapi import FastAPI
@@ -35,6 +34,7 @@ from prefect.settings import (
35
34
  )
36
35
  from prefect.states import Pending
37
36
  from prefect.task_engine import run_task_async, run_task_sync
37
+ from prefect.types._datetime import DateTime
38
38
  from prefect.utilities.annotations import NotSet
39
39
  from prefect.utilities.asyncutils import asyncnullcontext, sync_compatible
40
40
  from prefect.utilities.engine import emit_task_run_state_change_event
@@ -107,7 +107,7 @@ class TaskWorker:
107
107
 
108
108
  self.task_keys: set[str] = set(t.task_key for t in tasks if isinstance(t, Task)) # pyright: ignore[reportUnnecessaryIsInstance]
109
109
 
110
- self._started_at: Optional[pendulum.DateTime] = None
110
+ self._started_at: Optional[DateTime] = None
111
111
  self.stopping: bool = False
112
112
 
113
113
  self._client = get_client()
@@ -124,7 +124,7 @@ class TaskWorker:
124
124
  self._executor = ThreadPoolExecutor(max_workers=limit if limit else None)
125
125
  self._limiter = anyio.CapacityLimiter(limit) if limit else None
126
126
 
127
- self.in_flight_task_runs: dict[str, dict[UUID, pendulum.DateTime]] = {
127
+ self.in_flight_task_runs: dict[str, dict[UUID, DateTime]] = {
128
128
  task_key: {} for task_key in self.task_keys
129
129
  }
130
130
  self.finished_task_runs: dict[str, int] = {
@@ -136,7 +136,7 @@ class TaskWorker:
136
136
  return f"{socket.gethostname()}-{os.getpid()}"
137
137
 
138
138
  @property
139
- def started_at(self) -> Optional[pendulum.DateTime]:
139
+ def started_at(self) -> Optional[DateTime]:
140
140
  return self._started_at
141
141
 
142
142
  @property
@@ -248,15 +248,15 @@ class TaskWorker:
248
248
 
249
249
  token_acquired = await self._acquire_token(task_run.id)
250
250
  if token_acquired:
251
- assert (
252
- self._runs_task_group is not None
253
- ), "Task group was not initialized"
251
+ assert self._runs_task_group is not None, (
252
+ "Task group was not initialized"
253
+ )
254
254
  self._runs_task_group.start_soon(
255
255
  self._safe_submit_scheduled_task_run, task_run
256
256
  )
257
257
 
258
258
  async def _safe_submit_scheduled_task_run(self, task_run: TaskRun):
259
- self.in_flight_task_runs[task_run.task_key][task_run.id] = pendulum.now()
259
+ self.in_flight_task_runs[task_run.task_key][task_run.id] = DateTime.now()
260
260
  try:
261
261
  await self._submit_scheduled_task_run(task_run)
262
262
  except BaseException as exc:
@@ -379,7 +379,7 @@ class TaskWorker:
379
379
  await self._exit_stack.enter_async_context(self._runs_task_group)
380
380
  self._exit_stack.enter_context(self._executor)
381
381
 
382
- self._started_at = pendulum.now()
382
+ self._started_at = DateTime.now()
383
383
  return self
384
384
 
385
385
  async def __aexit__(self, *exc_info: Any) -> None:
prefect/tasks.py CHANGED
@@ -226,8 +226,7 @@ class TaskRunNameCallbackWithParameters(Protocol):
226
226
  sig = inspect.signature(callable)
227
227
  return "parameters" in sig.parameters
228
228
 
229
- def __call__(self, parameters: dict[str, Any]) -> str:
230
- ...
229
+ def __call__(self, parameters: dict[str, Any]) -> str: ...
231
230
 
232
231
 
233
232
  StateHookCallable: TypeAlias = Callable[
@@ -483,9 +482,9 @@ class Task(Generic[P, R]):
483
482
  f"Invalid `retry_delay_seconds` provided; must be an int, float, list or callable. Received type {type(retry_delay_seconds)}"
484
483
  )
485
484
  else:
486
- self.retry_delay_seconds: Union[
487
- float, int, list[float], None
488
- ] = retry_delay_seconds
485
+ self.retry_delay_seconds: Union[float, int, list[float], None] = (
486
+ retry_delay_seconds
487
+ )
489
488
 
490
489
  if isinstance(self.retry_delay_seconds, list) and (
491
490
  len(self.retry_delay_seconds) > 50
@@ -978,8 +977,7 @@ class Task(Generic[P, R]):
978
977
  self: "Task[P, R]",
979
978
  *args: P.args,
980
979
  **kwargs: P.kwargs,
981
- ) -> R:
982
- ...
980
+ ) -> R: ...
983
981
 
984
982
  # Keyword parameters `return_state` and `wait_for` aren't allowed after the
985
983
  # ParamSpec `*args` parameter, so we lose return type typing when either of
@@ -992,8 +990,7 @@ class Task(Generic[P, R]):
992
990
  return_state: Literal[True] = True,
993
991
  wait_for: Optional[OneOrManyFutureOrResult[Any]] = None,
994
992
  **kwargs: P.kwargs,
995
- ) -> State[R]:
996
- ...
993
+ ) -> State[R]: ...
997
994
 
998
995
  @overload
999
996
  def __call__(
@@ -1002,8 +999,7 @@ class Task(Generic[P, R]):
1002
999
  return_state: Literal[False] = False,
1003
1000
  wait_for: Optional[OneOrManyFutureOrResult[Any]] = None,
1004
1001
  **kwargs: P.kwargs,
1005
- ) -> R:
1006
- ...
1002
+ ) -> R: ...
1007
1003
 
1008
1004
  def __call__(
1009
1005
  self: "Union[Task[P, R], Task[P, NoReturn]]",
@@ -1046,8 +1042,7 @@ class Task(Generic[P, R]):
1046
1042
  self: "Task[P, R]",
1047
1043
  *args: P.args,
1048
1044
  **kwargs: P.kwargs,
1049
- ) -> PrefectFuture[R]:
1050
- ...
1045
+ ) -> PrefectFuture[R]: ...
1051
1046
 
1052
1047
  @overload
1053
1048
  def submit(
@@ -1056,8 +1051,7 @@ class Task(Generic[P, R]):
1056
1051
  return_state: Literal[False],
1057
1052
  wait_for: Optional[OneOrManyFutureOrResult[Any]] = None,
1058
1053
  **kwargs: P.kwargs,
1059
- ) -> PrefectFuture[R]:
1060
- ...
1054
+ ) -> PrefectFuture[R]: ...
1061
1055
 
1062
1056
  @overload
1063
1057
  def submit(
@@ -1066,8 +1060,7 @@ class Task(Generic[P, R]):
1066
1060
  return_state: Literal[False],
1067
1061
  wait_for: Optional[OneOrManyFutureOrResult[Any]] = None,
1068
1062
  **kwargs: P.kwargs,
1069
- ) -> PrefectFuture[R]:
1070
- ...
1063
+ ) -> PrefectFuture[R]: ...
1071
1064
 
1072
1065
  @overload
1073
1066
  def submit(
@@ -1076,8 +1069,7 @@ class Task(Generic[P, R]):
1076
1069
  return_state: Literal[True],
1077
1070
  wait_for: Optional[OneOrManyFutureOrResult[Any]] = None,
1078
1071
  **kwargs: P.kwargs,
1079
- ) -> State[R]:
1080
- ...
1072
+ ) -> State[R]: ...
1081
1073
 
1082
1074
  @overload
1083
1075
  def submit(
@@ -1086,8 +1078,7 @@ class Task(Generic[P, R]):
1086
1078
  return_state: Literal[True],
1087
1079
  wait_for: Optional[OneOrManyFutureOrResult[Any]] = None,
1088
1080
  **kwargs: P.kwargs,
1089
- ) -> State[R]:
1090
- ...
1081
+ ) -> State[R]: ...
1091
1082
 
1092
1083
  def submit(
1093
1084
  self: "Union[Task[P, R], Task[P, Coroutine[Any, Any, R]]]",
@@ -1221,8 +1212,7 @@ class Task(Generic[P, R]):
1221
1212
  wait_for: Optional[Iterable[Union[PrefectFuture[R], R]]] = ...,
1222
1213
  deferred: bool = ...,
1223
1214
  **kwargs: Any,
1224
- ) -> list[State[R]]:
1225
- ...
1215
+ ) -> list[State[R]]: ...
1226
1216
 
1227
1217
  @overload
1228
1218
  def map(
@@ -1231,8 +1221,7 @@ class Task(Generic[P, R]):
1231
1221
  wait_for: Optional[Iterable[Union[PrefectFuture[R], R]]] = ...,
1232
1222
  deferred: bool = ...,
1233
1223
  **kwargs: Any,
1234
- ) -> PrefectFutureList[R]:
1235
- ...
1224
+ ) -> PrefectFutureList[R]: ...
1236
1225
 
1237
1226
  @overload
1238
1227
  def map(
@@ -1242,8 +1231,7 @@ class Task(Generic[P, R]):
1242
1231
  wait_for: Optional[Iterable[Union[PrefectFuture[R], R]]] = ...,
1243
1232
  deferred: bool = ...,
1244
1233
  **kwargs: Any,
1245
- ) -> list[State[R]]:
1246
- ...
1234
+ ) -> list[State[R]]: ...
1247
1235
 
1248
1236
  @overload
1249
1237
  def map(
@@ -1252,8 +1240,7 @@ class Task(Generic[P, R]):
1252
1240
  wait_for: Optional[Iterable[Union[PrefectFuture[R], R]]] = ...,
1253
1241
  deferred: bool = ...,
1254
1242
  **kwargs: Any,
1255
- ) -> PrefectFutureList[R]:
1256
- ...
1243
+ ) -> PrefectFutureList[R]: ...
1257
1244
 
1258
1245
  @overload
1259
1246
  def map(
@@ -1263,8 +1250,7 @@ class Task(Generic[P, R]):
1263
1250
  wait_for: Optional[Iterable[Union[PrefectFuture[R], R]]] = ...,
1264
1251
  deferred: bool = ...,
1265
1252
  **kwargs: Any,
1266
- ) -> list[State[R]]:
1267
- ...
1253
+ ) -> list[State[R]]: ...
1268
1254
 
1269
1255
  @overload
1270
1256
  def map(
@@ -1274,8 +1260,7 @@ class Task(Generic[P, R]):
1274
1260
  wait_for: Optional[Iterable[Union[PrefectFuture[R], R]]] = ...,
1275
1261
  deferred: bool = ...,
1276
1262
  **kwargs: Any,
1277
- ) -> PrefectFutureList[R]:
1278
- ...
1263
+ ) -> PrefectFutureList[R]: ...
1279
1264
 
1280
1265
  def map(
1281
1266
  self,
@@ -1610,8 +1595,7 @@ class Task(Generic[P, R]):
1610
1595
 
1611
1596
 
1612
1597
  @overload
1613
- def task(__fn: Callable[P, R]) -> Task[P, R]:
1614
- ...
1598
+ def task(__fn: Callable[P, R]) -> Task[P, R]: ...
1615
1599
 
1616
1600
 
1617
1601
  # see https://github.com/PrefectHQ/prefect/issues/16380
@@ -1646,8 +1630,7 @@ def task(
1646
1630
  on_failure: Optional[list[StateHookCallable]] = None,
1647
1631
  retry_condition_fn: Literal[None] = None,
1648
1632
  viz_return_value: Any = None,
1649
- ) -> Callable[[Callable[P, R]], Task[P, R]]:
1650
- ...
1633
+ ) -> Callable[[Callable[P, R]], Task[P, R]]: ...
1651
1634
 
1652
1635
 
1653
1636
  # see https://github.com/PrefectHQ/prefect/issues/16380
@@ -1682,8 +1665,7 @@ def task(
1682
1665
  on_failure: Optional[list[StateHookCallable]] = None,
1683
1666
  retry_condition_fn: Optional[Callable[[Task[P, R], TaskRun, State], bool]] = None,
1684
1667
  viz_return_value: Any = None,
1685
- ) -> Callable[[Callable[P, R]], Task[P, R]]:
1686
- ...
1668
+ ) -> Callable[[Callable[P, R]], Task[P, R]]: ...
1687
1669
 
1688
1670
 
1689
1671
  @overload # TODO: do we need this overload?
@@ -1719,8 +1701,7 @@ def task(
1719
1701
  on_failure: Optional[list[StateHookCallable]] = None,
1720
1702
  retry_condition_fn: Optional[Callable[[Task[P, Any], TaskRun, State], bool]] = None,
1721
1703
  viz_return_value: Any = None,
1722
- ) -> Callable[[Callable[P, R]], Task[P, R]]:
1723
- ...
1704
+ ) -> Callable[[Callable[P, R]], Task[P, R]]: ...
1724
1705
 
1725
1706
 
1726
1707
  def task(
@@ -15,12 +15,10 @@ if TYPE_CHECKING:
15
15
  from opentelemetry.sdk.trace import TracerProvider
16
16
 
17
17
 
18
- def setup_telemetry() -> (
19
- Union[
20
- tuple["TracerProvider", "MeterProvider", "LoggerProvider"],
21
- tuple[None, None, None],
22
- ]
23
- ):
18
+ def setup_telemetry() -> Union[
19
+ tuple["TracerProvider", "MeterProvider", "LoggerProvider"],
20
+ tuple[None, None, None],
21
+ ]:
24
22
  settings = prefect.settings.get_current_settings()
25
23
 
26
24
  server_type = determine_server_type()
@@ -15,11 +15,9 @@ T_contra = TypeVar("T_contra", contravariant=True)
15
15
 
16
16
 
17
17
  class OTLPExporter(Protocol[T_contra]):
18
- def export(self, __items: Sequence[T_contra]) -> Any:
19
- ...
18
+ def export(self, __items: Sequence[T_contra]) -> Any: ...
20
19
 
21
- def shutdown(self) -> Any:
22
- ...
20
+ def shutdown(self) -> Any: ...
23
21
 
24
22
 
25
23
  class BaseQueueingExporter(BatchedQueueService[BatchItem]):
prefect/types/__init__.py CHANGED
@@ -106,7 +106,8 @@ KeyValueLabels = Annotated[
106
106
 
107
107
 
108
108
  ListOfNonEmptyStrings = Annotated[
109
- List[str], BeforeValidator(lambda x: [s for s in x if s.strip()])
109
+ List[str],
110
+ BeforeValidator(lambda x: [str(s) for s in x if str(s).strip()]),
110
111
  ]
111
112
 
112
113
 
@@ -1,10 +1,14 @@
1
1
  from __future__ import annotations
2
2
 
3
+ from typing import Any
4
+
3
5
  import pendulum
6
+ import pendulum.tz
4
7
  from pendulum.date import Date as PendulumDate
5
8
  from pendulum.datetime import DateTime as PendulumDateTime
6
9
  from pendulum.duration import Duration as PendulumDuration
7
10
  from pendulum.time import Time as PendulumTime
11
+ from pendulum.tz.timezone import FixedTimezone, Timezone
8
12
  from pydantic_extra_types.pendulum_dt import Date as PydanticDate
9
13
  from pydantic_extra_types.pendulum_dt import DateTime as PydanticDateTime
10
14
  from typing_extensions import TypeAlias
@@ -15,5 +19,28 @@ Date: TypeAlias = PydanticDate
15
19
 
16
20
  def parse_datetime(
17
21
  value: str,
22
+ **options: Any,
18
23
  ) -> PendulumDateTime | PendulumDate | PendulumTime | PendulumDuration:
19
- return pendulum.parse(value)
24
+ return pendulum.parse(value, **options)
25
+
26
+
27
+ def format_diff(
28
+ diff: PendulumDuration,
29
+ is_now: bool = True,
30
+ absolute: bool = False,
31
+ locale: str | None = None,
32
+ ) -> str:
33
+ return pendulum.format_diff(diff, is_now, absolute, locale)
34
+
35
+
36
+ def local_timezone() -> Timezone | FixedTimezone:
37
+ return pendulum.tz.local_timezone()
38
+
39
+
40
+ def from_format(
41
+ value: str,
42
+ fmt: str,
43
+ tz: str | Timezone = pendulum.tz.UTC,
44
+ locale: str | None = None,
45
+ ) -> DateTime:
46
+ return DateTime.instance(pendulum.from_format(value, fmt, tz, locale))
@@ -1,6 +1,5 @@
1
1
  """Internal engine utilities"""
2
2
 
3
-
4
3
  from collections.abc import Callable
5
4
  from functools import partial
6
5
  from typing import TYPE_CHECKING, Any, Union
@@ -129,8 +129,7 @@ def run_coro_as_sync(
129
129
  *,
130
130
  force_new_thread: bool = ...,
131
131
  wait_for_result: Literal[True] = ...,
132
- ) -> R:
133
- ...
132
+ ) -> R: ...
134
133
 
135
134
 
136
135
  @overload
@@ -139,8 +138,7 @@ def run_coro_as_sync(
139
138
  *,
140
139
  force_new_thread: bool = ...,
141
140
  wait_for_result: Literal[False] = False,
142
- ) -> R:
143
- ...
141
+ ) -> R: ...
144
142
 
145
143
 
146
144
  def run_coro_as_sync(
@@ -366,15 +364,13 @@ def sync_compatible(
366
364
  @overload
367
365
  def asyncnullcontext(
368
366
  value: None = None, *args: Any, **kwargs: Any
369
- ) -> AbstractAsyncContextManager[None, None]:
370
- ...
367
+ ) -> AbstractAsyncContextManager[None, None]: ...
371
368
 
372
369
 
373
370
  @overload
374
371
  def asyncnullcontext(
375
372
  value: R, *args: Any, **kwargs: Any
376
- ) -> AbstractAsyncContextManager[R, None]:
377
- ...
373
+ ) -> AbstractAsyncContextManager[R, None]: ...
378
374
 
379
375
 
380
376
  @asynccontextmanager
@@ -253,8 +253,7 @@ def visit_collection(
253
253
  context: dict[str, VT] = ...,
254
254
  remove_annotations: bool = ...,
255
255
  _seen: Optional[set[int]] = ...,
256
- ) -> Any:
257
- ...
256
+ ) -> Any: ...
258
257
 
259
258
 
260
259
  @overload
@@ -267,8 +266,7 @@ def visit_collection(
267
266
  context: None = None,
268
267
  remove_annotations: bool = ...,
269
268
  _seen: Optional[set[int]] = ...,
270
- ) -> Any:
271
- ...
269
+ ) -> Any: ...
272
270
 
273
271
 
274
272
  @overload
@@ -281,8 +279,7 @@ def visit_collection(
281
279
  context: dict[str, VT] = ...,
282
280
  remove_annotations: bool = ...,
283
281
  _seen: Optional[set[int]] = ...,
284
- ) -> Optional[Any]:
285
- ...
282
+ ) -> Optional[Any]: ...
286
283
 
287
284
 
288
285
  @overload
@@ -295,8 +292,7 @@ def visit_collection(
295
292
  context: None = None,
296
293
  remove_annotations: bool = ...,
297
294
  _seen: Optional[set[int]] = ...,
298
- ) -> Optional[Any]:
299
- ...
295
+ ) -> Optional[Any]: ...
300
296
 
301
297
 
302
298
  @overload
@@ -309,8 +305,7 @@ def visit_collection(
309
305
  context: dict[str, VT] = ...,
310
306
  remove_annotations: bool = ...,
311
307
  _seen: Optional[set[int]] = ...,
312
- ) -> None:
313
- ...
308
+ ) -> None: ...
314
309
 
315
310
 
316
311
  def visit_collection(
@@ -545,13 +540,11 @@ def visit_collection(
545
540
  @overload
546
541
  def remove_nested_keys(
547
542
  keys_to_remove: list[HashableT], obj: NestedDict[HashableT, VT]
548
- ) -> NestedDict[HashableT, VT]:
549
- ...
543
+ ) -> NestedDict[HashableT, VT]: ...
550
544
 
551
545
 
552
546
  @overload
553
- def remove_nested_keys(keys_to_remove: list[HashableT], obj: Any) -> Any:
554
- ...
547
+ def remove_nested_keys(keys_to_remove: list[HashableT], obj: Any) -> Any: ...
555
548
 
556
549
 
557
550
  def remove_nested_keys(
@@ -579,13 +572,13 @@ def remove_nested_keys(
579
572
 
580
573
 
581
574
  @overload
582
- def distinct(iterable: Iterable[HashableT], key: None = None) -> Iterator[HashableT]:
583
- ...
575
+ def distinct(
576
+ iterable: Iterable[HashableT], key: None = None
577
+ ) -> Iterator[HashableT]: ...
584
578
 
585
579
 
586
580
  @overload
587
- def distinct(iterable: Iterable[T], key: Callable[[T], Hashable]) -> Iterator[T]:
588
- ...
581
+ def distinct(iterable: Iterable[T], key: Callable[[T], Hashable]) -> Iterator[T]: ...
589
582
 
590
583
 
591
584
  def distinct(
@@ -609,15 +602,13 @@ def distinct(
609
602
  @overload
610
603
  def get_from_dict(
611
604
  dct: NestedDict[str, VT], keys: Union[str, list[str]], default: None = None
612
- ) -> Optional[VT]:
613
- ...
605
+ ) -> Optional[VT]: ...
614
606
 
615
607
 
616
608
  @overload
617
609
  def get_from_dict(
618
610
  dct: NestedDict[str, VT], keys: Union[str, list[str]], default: R
619
- ) -> Union[VT, R]:
620
- ...
611
+ ) -> Union[VT, R]: ...
621
612
 
622
613
 
623
614
  def get_from_dict(
@@ -45,15 +45,13 @@ def get_registry_for_type(cls: T) -> Optional[dict[str, T]]:
45
45
  @overload
46
46
  def get_dispatch_key(
47
47
  cls_or_instance: Any, allow_missing: Literal[False] = False
48
- ) -> str:
49
- ...
48
+ ) -> str: ...
50
49
 
51
50
 
52
51
  @overload
53
52
  def get_dispatch_key(
54
53
  cls_or_instance: Any, allow_missing: Literal[True] = ...
55
- ) -> Optional[str]:
56
- ...
54
+ ) -> Optional[str]: ...
57
55
 
58
56
 
59
57
  def get_dispatch_key(
@@ -331,7 +331,7 @@ class ImageBuilder:
331
331
  def assert_has_line(self, line: str) -> None:
332
332
  """Asserts that the given line is in the Dockerfile"""
333
333
  all_lines = "\n".join(
334
- [f" {i+1:>3}: {line}" for i, line in enumerate(self.dockerfile_lines)]
334
+ [f" {i + 1:>3}: {line}" for i, line in enumerate(self.dockerfile_lines)]
335
335
  )
336
336
  message = (
337
337
  f"Expected {line!r} not found in Dockerfile. Dockerfile:\n{all_lines}"
@@ -347,12 +347,12 @@ class ImageBuilder:
347
347
 
348
348
  surrounding_lines = "\n".join(
349
349
  [
350
- f" {i+1:>3}: {line}"
350
+ f" {i + 1:>3}: {line}"
351
351
  for i, line in enumerate(self.dockerfile_lines[i - 2 : i + 2])
352
352
  ]
353
353
  )
354
354
  message = (
355
- f"Unexpected {line!r} found in Dockerfile at line {i+1}. "
355
+ f"Unexpected {line!r} found in Dockerfile at line {i + 1}. "
356
356
  f"Surrounding lines:\n{surrounding_lines}"
357
357
  )
358
358
 
@@ -368,7 +368,7 @@ class ImageBuilder:
368
368
 
369
369
  surrounding_lines = "\n".join(
370
370
  [
371
- f" {i+1:>3}: {line}"
371
+ f" {i + 1:>3}: {line}"
372
372
  for i, line in enumerate(
373
373
  self.dockerfile_lines[second_index - 2 : first_index + 2]
374
374
  )
@@ -377,8 +377,8 @@ class ImageBuilder:
377
377
 
378
378
  message = (
379
379
  f"Expected {first!r} to appear before {second!r} in the Dockerfile, but "
380
- f"{first!r} was at line {first_index+1} and {second!r} as at line "
381
- f"{second_index+1}. Surrounding lines:\n{surrounding_lines}"
380
+ f"{first!r} was at line {first_index + 1} and {second!r} as at line "
381
+ f"{second_index + 1}. Surrounding lines:\n{surrounding_lines}"
382
382
  )
383
383
 
384
384
  assert first_index < second_index, message