prefect-client 2.19.4__py3-none-any.whl → 3.0.0rc2__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 (242) hide show
  1. prefect/__init__.py +8 -56
  2. prefect/_internal/compatibility/deprecated.py +6 -115
  3. prefect/_internal/compatibility/experimental.py +4 -79
  4. prefect/_internal/concurrency/api.py +0 -34
  5. prefect/_internal/concurrency/calls.py +0 -6
  6. prefect/_internal/concurrency/cancellation.py +0 -3
  7. prefect/_internal/concurrency/event_loop.py +0 -20
  8. prefect/_internal/concurrency/inspection.py +3 -3
  9. prefect/_internal/concurrency/threads.py +35 -0
  10. prefect/_internal/concurrency/waiters.py +0 -28
  11. prefect/_internal/pydantic/__init__.py +0 -45
  12. prefect/_internal/pydantic/v1_schema.py +21 -22
  13. prefect/_internal/pydantic/v2_schema.py +0 -2
  14. prefect/_internal/pydantic/v2_validated_func.py +18 -23
  15. prefect/_internal/schemas/bases.py +44 -177
  16. prefect/_internal/schemas/fields.py +1 -43
  17. prefect/_internal/schemas/validators.py +60 -158
  18. prefect/artifacts.py +161 -14
  19. prefect/automations.py +39 -4
  20. prefect/blocks/abstract.py +1 -1
  21. prefect/blocks/core.py +268 -148
  22. prefect/blocks/fields.py +2 -57
  23. prefect/blocks/kubernetes.py +8 -12
  24. prefect/blocks/notifications.py +40 -20
  25. prefect/blocks/redis.py +168 -0
  26. prefect/blocks/system.py +22 -11
  27. prefect/blocks/webhook.py +2 -9
  28. prefect/client/base.py +4 -4
  29. prefect/client/cloud.py +8 -13
  30. prefect/client/orchestration.py +362 -340
  31. prefect/client/schemas/actions.py +92 -86
  32. prefect/client/schemas/filters.py +20 -40
  33. prefect/client/schemas/objects.py +158 -152
  34. prefect/client/schemas/responses.py +16 -24
  35. prefect/client/schemas/schedules.py +47 -35
  36. prefect/client/subscriptions.py +2 -2
  37. prefect/client/utilities.py +5 -2
  38. prefect/concurrency/asyncio.py +4 -2
  39. prefect/concurrency/events.py +1 -1
  40. prefect/concurrency/services.py +7 -4
  41. prefect/context.py +195 -27
  42. prefect/deployments/__init__.py +5 -6
  43. prefect/deployments/base.py +7 -5
  44. prefect/deployments/flow_runs.py +185 -0
  45. prefect/deployments/runner.py +50 -45
  46. prefect/deployments/schedules.py +28 -23
  47. prefect/deployments/steps/__init__.py +0 -1
  48. prefect/deployments/steps/core.py +1 -0
  49. prefect/deployments/steps/pull.py +7 -21
  50. prefect/engine.py +12 -2422
  51. prefect/events/actions.py +17 -23
  52. prefect/events/cli/automations.py +19 -6
  53. prefect/events/clients.py +14 -37
  54. prefect/events/filters.py +14 -18
  55. prefect/events/related.py +2 -2
  56. prefect/events/schemas/__init__.py +0 -5
  57. prefect/events/schemas/automations.py +55 -46
  58. prefect/events/schemas/deployment_triggers.py +7 -197
  59. prefect/events/schemas/events.py +36 -65
  60. prefect/events/schemas/labelling.py +10 -14
  61. prefect/events/utilities.py +2 -3
  62. prefect/events/worker.py +2 -3
  63. prefect/filesystems.py +6 -517
  64. prefect/{new_flow_engine.py → flow_engine.py} +315 -74
  65. prefect/flow_runs.py +379 -7
  66. prefect/flows.py +248 -165
  67. prefect/futures.py +187 -345
  68. prefect/infrastructure/__init__.py +0 -27
  69. prefect/infrastructure/provisioners/__init__.py +5 -3
  70. prefect/infrastructure/provisioners/cloud_run.py +11 -6
  71. prefect/infrastructure/provisioners/container_instance.py +11 -7
  72. prefect/infrastructure/provisioners/ecs.py +6 -4
  73. prefect/infrastructure/provisioners/modal.py +8 -5
  74. prefect/input/actions.py +2 -4
  75. prefect/input/run_input.py +9 -9
  76. prefect/logging/formatters.py +0 -2
  77. prefect/logging/handlers.py +3 -11
  78. prefect/logging/loggers.py +2 -2
  79. prefect/manifests.py +2 -1
  80. prefect/records/__init__.py +1 -0
  81. prefect/records/cache_policies.py +179 -0
  82. prefect/records/result_store.py +42 -0
  83. prefect/records/store.py +9 -0
  84. prefect/results.py +43 -39
  85. prefect/runner/runner.py +9 -9
  86. prefect/runner/server.py +6 -10
  87. prefect/runner/storage.py +3 -8
  88. prefect/runner/submit.py +2 -2
  89. prefect/runner/utils.py +2 -2
  90. prefect/serializers.py +24 -35
  91. prefect/server/api/collections_data/views/aggregate-worker-metadata.json +5 -14
  92. prefect/settings.py +76 -136
  93. prefect/states.py +22 -50
  94. prefect/task_engine.py +666 -56
  95. prefect/task_runners.py +272 -300
  96. prefect/task_runs.py +203 -0
  97. prefect/{task_server.py → task_worker.py} +89 -60
  98. prefect/tasks.py +358 -341
  99. prefect/transactions.py +224 -0
  100. prefect/types/__init__.py +61 -82
  101. prefect/utilities/asyncutils.py +195 -136
  102. prefect/utilities/callables.py +121 -41
  103. prefect/utilities/collections.py +23 -38
  104. prefect/utilities/dispatch.py +11 -3
  105. prefect/utilities/dockerutils.py +4 -0
  106. prefect/utilities/engine.py +140 -20
  107. prefect/utilities/importtools.py +26 -27
  108. prefect/utilities/pydantic.py +128 -38
  109. prefect/utilities/schema_tools/hydration.py +5 -1
  110. prefect/utilities/templating.py +12 -2
  111. prefect/variables.py +84 -62
  112. prefect/workers/__init__.py +0 -1
  113. prefect/workers/base.py +26 -18
  114. prefect/workers/process.py +3 -8
  115. prefect/workers/server.py +2 -2
  116. {prefect_client-2.19.4.dist-info → prefect_client-3.0.0rc2.dist-info}/METADATA +23 -21
  117. prefect_client-3.0.0rc2.dist-info/RECORD +179 -0
  118. prefect/_internal/pydantic/_base_model.py +0 -51
  119. prefect/_internal/pydantic/_compat.py +0 -82
  120. prefect/_internal/pydantic/_flags.py +0 -20
  121. prefect/_internal/pydantic/_types.py +0 -8
  122. prefect/_internal/pydantic/utilities/__init__.py +0 -0
  123. prefect/_internal/pydantic/utilities/config_dict.py +0 -72
  124. prefect/_internal/pydantic/utilities/field_validator.py +0 -150
  125. prefect/_internal/pydantic/utilities/model_construct.py +0 -56
  126. prefect/_internal/pydantic/utilities/model_copy.py +0 -55
  127. prefect/_internal/pydantic/utilities/model_dump.py +0 -136
  128. prefect/_internal/pydantic/utilities/model_dump_json.py +0 -112
  129. prefect/_internal/pydantic/utilities/model_fields.py +0 -50
  130. prefect/_internal/pydantic/utilities/model_fields_set.py +0 -29
  131. prefect/_internal/pydantic/utilities/model_json_schema.py +0 -82
  132. prefect/_internal/pydantic/utilities/model_rebuild.py +0 -80
  133. prefect/_internal/pydantic/utilities/model_validate.py +0 -75
  134. prefect/_internal/pydantic/utilities/model_validate_json.py +0 -68
  135. prefect/_internal/pydantic/utilities/model_validator.py +0 -87
  136. prefect/_internal/pydantic/utilities/type_adapter.py +0 -71
  137. prefect/_vendor/__init__.py +0 -0
  138. prefect/_vendor/fastapi/__init__.py +0 -25
  139. prefect/_vendor/fastapi/applications.py +0 -946
  140. prefect/_vendor/fastapi/background.py +0 -3
  141. prefect/_vendor/fastapi/concurrency.py +0 -44
  142. prefect/_vendor/fastapi/datastructures.py +0 -58
  143. prefect/_vendor/fastapi/dependencies/__init__.py +0 -0
  144. prefect/_vendor/fastapi/dependencies/models.py +0 -64
  145. prefect/_vendor/fastapi/dependencies/utils.py +0 -877
  146. prefect/_vendor/fastapi/encoders.py +0 -177
  147. prefect/_vendor/fastapi/exception_handlers.py +0 -40
  148. prefect/_vendor/fastapi/exceptions.py +0 -46
  149. prefect/_vendor/fastapi/logger.py +0 -3
  150. prefect/_vendor/fastapi/middleware/__init__.py +0 -1
  151. prefect/_vendor/fastapi/middleware/asyncexitstack.py +0 -25
  152. prefect/_vendor/fastapi/middleware/cors.py +0 -3
  153. prefect/_vendor/fastapi/middleware/gzip.py +0 -3
  154. prefect/_vendor/fastapi/middleware/httpsredirect.py +0 -3
  155. prefect/_vendor/fastapi/middleware/trustedhost.py +0 -3
  156. prefect/_vendor/fastapi/middleware/wsgi.py +0 -3
  157. prefect/_vendor/fastapi/openapi/__init__.py +0 -0
  158. prefect/_vendor/fastapi/openapi/constants.py +0 -2
  159. prefect/_vendor/fastapi/openapi/docs.py +0 -203
  160. prefect/_vendor/fastapi/openapi/models.py +0 -480
  161. prefect/_vendor/fastapi/openapi/utils.py +0 -485
  162. prefect/_vendor/fastapi/param_functions.py +0 -340
  163. prefect/_vendor/fastapi/params.py +0 -453
  164. prefect/_vendor/fastapi/requests.py +0 -4
  165. prefect/_vendor/fastapi/responses.py +0 -40
  166. prefect/_vendor/fastapi/routing.py +0 -1331
  167. prefect/_vendor/fastapi/security/__init__.py +0 -15
  168. prefect/_vendor/fastapi/security/api_key.py +0 -98
  169. prefect/_vendor/fastapi/security/base.py +0 -6
  170. prefect/_vendor/fastapi/security/http.py +0 -172
  171. prefect/_vendor/fastapi/security/oauth2.py +0 -227
  172. prefect/_vendor/fastapi/security/open_id_connect_url.py +0 -34
  173. prefect/_vendor/fastapi/security/utils.py +0 -10
  174. prefect/_vendor/fastapi/staticfiles.py +0 -1
  175. prefect/_vendor/fastapi/templating.py +0 -3
  176. prefect/_vendor/fastapi/testclient.py +0 -1
  177. prefect/_vendor/fastapi/types.py +0 -3
  178. prefect/_vendor/fastapi/utils.py +0 -235
  179. prefect/_vendor/fastapi/websockets.py +0 -7
  180. prefect/_vendor/starlette/__init__.py +0 -1
  181. prefect/_vendor/starlette/_compat.py +0 -28
  182. prefect/_vendor/starlette/_exception_handler.py +0 -80
  183. prefect/_vendor/starlette/_utils.py +0 -88
  184. prefect/_vendor/starlette/applications.py +0 -261
  185. prefect/_vendor/starlette/authentication.py +0 -159
  186. prefect/_vendor/starlette/background.py +0 -43
  187. prefect/_vendor/starlette/concurrency.py +0 -59
  188. prefect/_vendor/starlette/config.py +0 -151
  189. prefect/_vendor/starlette/convertors.py +0 -87
  190. prefect/_vendor/starlette/datastructures.py +0 -707
  191. prefect/_vendor/starlette/endpoints.py +0 -130
  192. prefect/_vendor/starlette/exceptions.py +0 -60
  193. prefect/_vendor/starlette/formparsers.py +0 -276
  194. prefect/_vendor/starlette/middleware/__init__.py +0 -17
  195. prefect/_vendor/starlette/middleware/authentication.py +0 -52
  196. prefect/_vendor/starlette/middleware/base.py +0 -220
  197. prefect/_vendor/starlette/middleware/cors.py +0 -176
  198. prefect/_vendor/starlette/middleware/errors.py +0 -265
  199. prefect/_vendor/starlette/middleware/exceptions.py +0 -74
  200. prefect/_vendor/starlette/middleware/gzip.py +0 -113
  201. prefect/_vendor/starlette/middleware/httpsredirect.py +0 -19
  202. prefect/_vendor/starlette/middleware/sessions.py +0 -82
  203. prefect/_vendor/starlette/middleware/trustedhost.py +0 -64
  204. prefect/_vendor/starlette/middleware/wsgi.py +0 -147
  205. prefect/_vendor/starlette/requests.py +0 -328
  206. prefect/_vendor/starlette/responses.py +0 -347
  207. prefect/_vendor/starlette/routing.py +0 -933
  208. prefect/_vendor/starlette/schemas.py +0 -154
  209. prefect/_vendor/starlette/staticfiles.py +0 -248
  210. prefect/_vendor/starlette/status.py +0 -199
  211. prefect/_vendor/starlette/templating.py +0 -231
  212. prefect/_vendor/starlette/testclient.py +0 -804
  213. prefect/_vendor/starlette/types.py +0 -30
  214. prefect/_vendor/starlette/websockets.py +0 -193
  215. prefect/agent.py +0 -698
  216. prefect/deployments/deployments.py +0 -1042
  217. prefect/deprecated/__init__.py +0 -0
  218. prefect/deprecated/data_documents.py +0 -350
  219. prefect/deprecated/packaging/__init__.py +0 -12
  220. prefect/deprecated/packaging/base.py +0 -96
  221. prefect/deprecated/packaging/docker.py +0 -146
  222. prefect/deprecated/packaging/file.py +0 -92
  223. prefect/deprecated/packaging/orion.py +0 -80
  224. prefect/deprecated/packaging/serializers.py +0 -171
  225. prefect/events/instrument.py +0 -135
  226. prefect/infrastructure/base.py +0 -323
  227. prefect/infrastructure/container.py +0 -818
  228. prefect/infrastructure/kubernetes.py +0 -920
  229. prefect/infrastructure/process.py +0 -289
  230. prefect/new_task_engine.py +0 -423
  231. prefect/pydantic/__init__.py +0 -76
  232. prefect/pydantic/main.py +0 -39
  233. prefect/software/__init__.py +0 -2
  234. prefect/software/base.py +0 -50
  235. prefect/software/conda.py +0 -199
  236. prefect/software/pip.py +0 -122
  237. prefect/software/python.py +0 -52
  238. prefect/workers/block.py +0 -218
  239. prefect_client-2.19.4.dist-info/RECORD +0 -292
  240. {prefect_client-2.19.4.dist-info → prefect_client-3.0.0rc2.dist-info}/LICENSE +0 -0
  241. {prefect_client-2.19.4.dist-info → prefect_client-3.0.0rc2.dist-info}/WHEEL +0 -0
  242. {prefect_client-2.19.4.dist-info → prefect_client-3.0.0rc2.dist-info}/top_level.txt +0 -0
@@ -5,7 +5,7 @@ import tempfile
5
5
  from copy import deepcopy
6
6
  from pathlib import Path
7
7
  from textwrap import dedent
8
- from typing import Any, Dict, Optional
8
+ from typing import TYPE_CHECKING, Any, Dict, Optional
9
9
  from uuid import UUID
10
10
 
11
11
  from anyio import run_process
@@ -17,7 +17,7 @@ from rich.prompt import Confirm
17
17
  from rich.syntax import Syntax
18
18
 
19
19
  from prefect.cli._prompts import prompt, prompt_select_from_table
20
- from prefect.client.orchestration import PrefectClient, ServerType
20
+ from prefect.client.orchestration import ServerType
21
21
  from prefect.client.schemas.actions import BlockDocumentCreate
22
22
  from prefect.client.utilities import inject_client
23
23
  from prefect.exceptions import ObjectAlreadyExists
@@ -27,6 +27,9 @@ from prefect.settings import (
27
27
  update_current_profile,
28
28
  )
29
29
 
30
+ if TYPE_CHECKING:
31
+ from prefect.client.orchestration import PrefectClient
32
+
30
33
 
31
34
  class CloudRunPushProvisioner:
32
35
  def __init__(self):
@@ -215,7 +218,7 @@ class CloudRunPushProvisioner:
215
218
  ) from e
216
219
 
217
220
  async def _create_gcp_credentials_block(
218
- self, block_document_name: str, key: dict, client: PrefectClient
221
+ self, block_document_name: str, key: dict, client: "PrefectClient"
219
222
  ) -> UUID:
220
223
  credentials_block_type = await client.read_block_type_by_slug("gcp-credentials")
221
224
 
@@ -242,7 +245,9 @@ class CloudRunPushProvisioner:
242
245
  )
243
246
  return block_doc.id
244
247
 
245
- async def _create_provision_table(self, work_pool_name: str, client: PrefectClient):
248
+ async def _create_provision_table(
249
+ self, work_pool_name: str, client: "PrefectClient"
250
+ ):
246
251
  return Panel(
247
252
  dedent(
248
253
  f"""\
@@ -268,7 +273,7 @@ class CloudRunPushProvisioner:
268
273
  )
269
274
 
270
275
  async def _customize_resource_names(
271
- self, work_pool_name: str, client: PrefectClient
276
+ self, work_pool_name: str, client: "PrefectClient"
272
277
  ) -> bool:
273
278
  self._service_account_name = prompt(
274
279
  "Please enter a name for the service account",
@@ -294,7 +299,7 @@ class CloudRunPushProvisioner:
294
299
  self,
295
300
  work_pool_name: str,
296
301
  base_job_template: dict,
297
- client: Optional[PrefectClient] = None,
302
+ client: Optional["PrefectClient"] = None,
298
303
  ) -> Dict[str, Any]:
299
304
  assert client, "Client injection failed"
300
305
  await self._verify_gcloud_ready()
@@ -18,7 +18,7 @@ import subprocess
18
18
  import time
19
19
  from copy import deepcopy
20
20
  from textwrap import dedent
21
- from typing import Any, Dict, Optional
21
+ from typing import TYPE_CHECKING, Any, Dict, Optional
22
22
  from uuid import UUID
23
23
 
24
24
  from anyio import run_process
@@ -29,7 +29,6 @@ from rich.prompt import Confirm
29
29
  from rich.syntax import Syntax
30
30
 
31
31
  from prefect.cli._prompts import prompt, prompt_select_from_table
32
- from prefect.client.orchestration import PrefectClient
33
32
  from prefect.client.schemas.actions import BlockDocumentCreate
34
33
  from prefect.client.utilities import inject_client
35
34
  from prefect.exceptions import ObjectAlreadyExists, ObjectNotFound
@@ -38,6 +37,9 @@ from prefect.settings import (
38
37
  update_current_profile,
39
38
  )
40
39
 
40
+ if TYPE_CHECKING:
41
+ from prefect.client.orchestration import PrefectClient
42
+
41
43
 
42
44
  class AzureCLI:
43
45
  """
@@ -684,7 +686,7 @@ class ContainerInstancePushProvisioner:
684
686
  client_id: str,
685
687
  tenant_id: str,
686
688
  client_secret: str,
687
- client: PrefectClient,
689
+ client: "PrefectClient",
688
690
  ) -> UUID:
689
691
  """
690
692
  Creates a credentials block for Azure Container Instance.
@@ -755,7 +757,7 @@ class ContainerInstancePushProvisioner:
755
757
  raise e
756
758
 
757
759
  async def _aci_credentials_block_exists(
758
- self, block_name: str, client: PrefectClient
760
+ self, block_name: str, client: "PrefectClient"
759
761
  ) -> bool:
760
762
  """
761
763
  Checks if an ACI credentials block with the given name already exists.
@@ -782,7 +784,9 @@ class ContainerInstancePushProvisioner:
782
784
  else:
783
785
  return False
784
786
 
785
- async def _create_provision_table(self, work_pool_name: str, client: PrefectClient):
787
+ async def _create_provision_table(
788
+ self, work_pool_name: str, client: "PrefectClient"
789
+ ):
786
790
  return Panel(
787
791
  dedent(
788
792
  f"""\
@@ -809,7 +813,7 @@ class ContainerInstancePushProvisioner:
809
813
  )
810
814
 
811
815
  async def _customize_resource_names(
812
- self, work_pool_name: str, client: PrefectClient
816
+ self, work_pool_name: str, client: "PrefectClient"
813
817
  ) -> bool:
814
818
  self._resource_group_name = prompt(
815
819
  "Please enter a name for the resource group",
@@ -851,7 +855,7 @@ class ContainerInstancePushProvisioner:
851
855
  self,
852
856
  work_pool_name: str,
853
857
  base_job_template: Dict[str, Any],
854
- client: Optional[PrefectClient] = None,
858
+ client: Optional["PrefectClient"] = None,
855
859
  ) -> Dict[str, Any]:
856
860
  """
857
861
  Orchestrates the provisioning of Azure resources and setup for the push work pool.
@@ -9,7 +9,7 @@ import sys
9
9
  from copy import deepcopy
10
10
  from functools import partial
11
11
  from textwrap import dedent
12
- from typing import Any, Callable, Dict, List, Optional
12
+ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional
13
13
 
14
14
  import anyio
15
15
  from anyio import run_process
@@ -20,7 +20,6 @@ from rich.prompt import Confirm
20
20
  from rich.syntax import Syntax
21
21
 
22
22
  from prefect.cli._prompts import prompt
23
- from prefect.client.orchestration import PrefectClient
24
23
  from prefect.client.schemas.actions import BlockDocumentCreate
25
24
  from prefect.client.utilities import inject_client
26
25
  from prefect.exceptions import ObjectNotFound
@@ -31,6 +30,9 @@ from prefect.settings import (
31
30
  from prefect.utilities.collections import get_from_dict
32
31
  from prefect.utilities.importtools import lazy_import
33
32
 
33
+ if TYPE_CHECKING:
34
+ from prefect.client.orchestration import PrefectClient
35
+
34
36
  boto3 = lazy_import("boto3")
35
37
 
36
38
  current_console = contextvars.ContextVar("console", default=Console())
@@ -250,7 +252,7 @@ class CredentialsBlockResource:
250
252
 
251
253
  @inject_client
252
254
  async def requires_provisioning(
253
- self, client: Optional[PrefectClient] = None
255
+ self, client: Optional["PrefectClient"] = None
254
256
  ) -> bool:
255
257
  if self._requires_provisioning is None:
256
258
  try:
@@ -280,7 +282,7 @@ class CredentialsBlockResource:
280
282
  self,
281
283
  base_job_template: Dict[str, Any],
282
284
  advance: Callable[[], None],
283
- client: Optional[PrefectClient] = None,
285
+ client: Optional["PrefectClient"] = None,
284
286
  ):
285
287
  """
286
288
  Provisions an AWS credentials block.
@@ -2,20 +2,23 @@ import importlib
2
2
  import shlex
3
3
  import sys
4
4
  from copy import deepcopy
5
- from typing import Any, Dict, Optional, Tuple
5
+ from typing import TYPE_CHECKING, Any, Dict, Optional, Tuple
6
6
 
7
7
  from anyio import run_process
8
8
  from rich.console import Console
9
9
  from rich.progress import Progress, SpinnerColumn, TextColumn
10
10
  from rich.prompt import Confirm
11
11
 
12
- from prefect.client.orchestration import PrefectClient
13
12
  from prefect.client.schemas.actions import BlockDocumentCreate
14
13
  from prefect.client.schemas.objects import BlockDocument
15
14
  from prefect.client.utilities import inject_client
16
15
  from prefect.exceptions import ObjectNotFound
17
16
  from prefect.utilities.importtools import lazy_import
18
17
 
18
+ if TYPE_CHECKING:
19
+ from prefect.client.orchestration import PrefectClient
20
+
21
+
19
22
  modal = lazy_import("modal")
20
23
 
21
24
 
@@ -24,7 +27,7 @@ class ModalPushProvisioner:
24
27
  A infrastructure provisioner for Modal push work pools.
25
28
  """
26
29
 
27
- def __init__(self, client: Optional[PrefectClient] = None):
30
+ def __init__(self, client: Optional["PrefectClient"] = None):
28
31
  self._console = Console()
29
32
 
30
33
  @property
@@ -91,7 +94,7 @@ class ModalPushProvisioner:
91
94
  block_document_name: str,
92
95
  modal_token_id: str,
93
96
  modal_token_secret: str,
94
- client: PrefectClient,
97
+ client: "PrefectClient",
95
98
  ) -> BlockDocument:
96
99
  """
97
100
  Creates a ModalCredentials block containing the provided token ID and secret.
@@ -142,7 +145,7 @@ class ModalPushProvisioner:
142
145
  self,
143
146
  work_pool_name: str,
144
147
  base_job_template: Dict[str, Any],
145
- client: Optional[PrefectClient] = None,
148
+ client: Optional["PrefectClient"] = None,
146
149
  ) -> Dict[str, Any]:
147
150
  """
148
151
  Provisions resources necessary for a Modal push work pool.
prefect/input/actions.py CHANGED
@@ -4,7 +4,6 @@ from uuid import UUID
4
4
  import orjson
5
5
  import pydantic
6
6
 
7
- from prefect._internal.pydantic import HAS_PYDANTIC_V2
8
7
  from prefect.client.utilities import client_injector
9
8
  from prefect.context import FlowRunContext
10
9
  from prefect.exceptions import PrefectHTTPStatusError
@@ -14,8 +13,7 @@ if TYPE_CHECKING:
14
13
  from prefect.client.orchestration import PrefectClient
15
14
 
16
15
 
17
- if HAS_PYDANTIC_V2:
18
- from prefect._internal.pydantic.v2_schema import is_v2_model
16
+ from prefect._internal.pydantic.v2_schema import is_v2_model
19
17
 
20
18
 
21
19
  def ensure_flow_run_id(flow_run_id: Optional[UUID] = None) -> UUID:
@@ -41,7 +39,7 @@ async def create_flow_run_input_from_model(
41
39
  if context is not None and context.flow_run is not None:
42
40
  sender = f"prefect.flow-run.{context.flow_run.id}"
43
41
 
44
- if HAS_PYDANTIC_V2 and is_v2_model(model_instance):
42
+ if is_v2_model(model_instance):
45
43
  json_safe = orjson.loads(model_instance.model_dump_json())
46
44
  else:
47
45
  json_safe = orjson.loads(model_instance.json())
@@ -18,7 +18,8 @@ Sender flow:
18
18
  ```python
19
19
  import random
20
20
  from uuid import UUID
21
- from prefect import flow, get_run_logger
21
+ from prefect import flow
22
+ from prefect.logging import get_run_logger
22
23
  from prefect.input import RunInput
23
24
 
24
25
  class NumberData(RunInput):
@@ -43,7 +44,8 @@ Receiver flow:
43
44
  ```python
44
45
  import random
45
46
  from uuid import UUID
46
- from prefect import flow, get_run_logger
47
+ from prefect import flow
48
+ from prefect.logging import get_run_logger
47
49
  from prefect.input import RunInput
48
50
 
49
51
  class NumberData(RunInput):
@@ -77,8 +79,8 @@ from uuid import UUID, uuid4
77
79
 
78
80
  import anyio
79
81
  import pydantic
82
+ from pydantic import ConfigDict
80
83
 
81
- from prefect._internal.pydantic import HAS_PYDANTIC_V2
82
84
  from prefect.input.actions import (
83
85
  create_flow_run_input,
84
86
  create_flow_run_input_from_model,
@@ -92,8 +94,7 @@ if TYPE_CHECKING:
92
94
  from prefect.client.schemas.objects import FlowRunInput
93
95
  from prefect.states import State
94
96
 
95
- if HAS_PYDANTIC_V2:
96
- from prefect._internal.pydantic.v2_schema import create_v2_schema
97
+ from prefect._internal.pydantic.v2_schema import create_v2_schema, is_v2_model
97
98
 
98
99
  R = TypeVar("R", bound="RunInput")
99
100
  T = TypeVar("T", bound="object")
@@ -138,13 +139,12 @@ def keyset_from_base_key(base_key: str) -> Keyset:
138
139
 
139
140
  class RunInputMetadata(pydantic.BaseModel):
140
141
  key: str
141
- sender: Optional[str]
142
+ sender: Optional[str] = None
142
143
  receiver: UUID
143
144
 
144
145
 
145
146
  class RunInput(pydantic.BaseModel):
146
- class Config:
147
- extra = "forbid"
147
+ model_config = ConfigDict(extra="forbid")
148
148
 
149
149
  _description: Optional[str] = pydantic.PrivateAttr(default=None)
150
150
  _metadata: RunInputMetadata = pydantic.PrivateAttr()
@@ -168,7 +168,7 @@ class RunInput(pydantic.BaseModel):
168
168
  - flow_run_id (UUID, optional): the flow run ID to save the input for
169
169
  """
170
170
 
171
- if HAS_PYDANTIC_V2:
171
+ if is_v2_model(cls):
172
172
  schema = create_v2_schema(cls.__name__, model_base=cls)
173
173
  else:
174
174
  schema = cls.schema(by_alias=True)
@@ -48,7 +48,6 @@ class JsonFormatter(logging.Formatter):
48
48
 
49
49
  self.serializer = JSONSerializer(
50
50
  jsonlib="orjson",
51
- object_encoder="pydantic.json.pydantic_encoder",
52
51
  dumps_kwargs={"option": orjson.OPT_INDENT_2} if fmt == "pretty" else {},
53
52
  )
54
53
 
@@ -98,7 +97,6 @@ class PrefectFormatter(logging.Formatter):
98
97
  init_kwargs["defaults"] = defaults
99
98
  style_kwargs["defaults"] = defaults
100
99
 
101
- # validate added in 3.8
102
100
  init_kwargs["validate"] = validate
103
101
 
104
102
  super().__init__(format, datefmt, style, **init_kwargs)
@@ -119,21 +119,13 @@ class APILogHandler(logging.Handler):
119
119
  return APILogWorker.drain_all(timeout=5)
120
120
 
121
121
  @classmethod
122
- def aflush(cls):
122
+ async def aflush(cls):
123
123
  """
124
124
  Tell the `APILogWorker` to send any currently enqueued logs and block until
125
125
  completion.
126
-
127
- If called in a synchronous context, will only block up to 5s before returning.
128
126
  """
129
127
 
130
- if not get_running_loop():
131
- raise RuntimeError(
132
- "`aflush` cannot be used from a synchronous context; use `flush`"
133
- " instead."
134
- )
135
-
136
- return APILogWorker.drain_all()
128
+ return await APILogWorker.drain_all()
137
129
 
138
130
  def emit(self, record: logging.LogRecord):
139
131
  """
@@ -229,7 +221,7 @@ class APILogHandler(logging.Handler):
229
221
  getattr(record, "created", None) or time.time()
230
222
  ),
231
223
  message=self.format(record),
232
- ).dict(json_compatible=True)
224
+ ).model_dump(mode="json")
233
225
 
234
226
  log_size = log["__payload_size__"] = self._get_payload_size(log)
235
227
  if log_size > PREFECT_LOGGING_TO_API_MAX_LOG_SIZE.value():
@@ -5,7 +5,7 @@ import warnings
5
5
  from builtins import print
6
6
  from contextlib import contextmanager
7
7
  from functools import lru_cache
8
- from logging import LogRecord
8
+ from logging import LoggerAdapter, LogRecord
9
9
  from typing import TYPE_CHECKING, Dict, List, Optional, Union
10
10
 
11
11
  from typing_extensions import Self
@@ -161,7 +161,7 @@ def flow_run_logger(
161
161
  flow_run: Union["FlowRun", "ClientFlowRun"],
162
162
  flow: Optional["Flow"] = None,
163
163
  **kwargs: str,
164
- ):
164
+ ) -> LoggerAdapter:
165
165
  """
166
166
  Create a flow run logger with the run's metadata attached.
167
167
 
prefect/manifests.py CHANGED
@@ -4,7 +4,8 @@ Manifests are portable descriptions of one or more workflows within a given dire
4
4
  They are the foundational building blocks for defining Flow Deployments.
5
5
  """
6
6
 
7
- from prefect.pydantic import BaseModel, Field
7
+ from pydantic import BaseModel, Field
8
+
8
9
  from prefect.utilities.callables import ParameterSchema
9
10
 
10
11
 
@@ -0,0 +1 @@
1
+ from .store import RecordStore
@@ -0,0 +1,179 @@
1
+ import inspect
2
+ from dataclasses import dataclass
3
+ from typing import Any, Callable, Dict, Optional
4
+
5
+ from prefect.context import TaskRunContext
6
+ from prefect.utilities.hashing import hash_objects
7
+
8
+
9
+ @dataclass
10
+ class CachePolicy:
11
+ @classmethod
12
+ def from_cache_key_fn(
13
+ cls, cache_key_fn: Callable[["TaskRunContext", Dict[str, Any]], Optional[str]]
14
+ ) -> "CacheKeyFnPolicy":
15
+ """
16
+ Given a function generates a key policy.
17
+ """
18
+ return CacheKeyFnPolicy(cache_key_fn=cache_key_fn)
19
+
20
+ def compute_key(
21
+ self,
22
+ task_ctx: TaskRunContext,
23
+ inputs: Dict[str, Any],
24
+ flow_parameters: Dict[str, Any],
25
+ **kwargs,
26
+ ) -> Optional[str]:
27
+ raise NotImplementedError
28
+
29
+ def __sub__(self, other: str) -> "CompoundCachePolicy":
30
+ if not isinstance(other, str):
31
+ raise TypeError("Can only subtract strings from key policies.")
32
+ if isinstance(self, Inputs):
33
+ exclude = self.exclude or []
34
+ return Inputs(exclude=exclude + [other])
35
+ elif isinstance(self, CompoundCachePolicy):
36
+ new = Inputs(exclude=[other])
37
+ policies = self.policies or []
38
+ return CompoundCachePolicy(policies=policies + [new])
39
+ else:
40
+ new = Inputs(exclude=[other])
41
+ return CompoundCachePolicy(policies=[self, new])
42
+
43
+ def __add__(self, other: "CachePolicy") -> "CompoundCachePolicy":
44
+ # adding _None is a no-op
45
+ if isinstance(other, _None):
46
+ return self
47
+ elif isinstance(self, _None):
48
+ return other
49
+
50
+ if isinstance(self, CompoundCachePolicy):
51
+ policies = self.policies or []
52
+ return CompoundCachePolicy(policies=policies + [other])
53
+ elif isinstance(other, CompoundCachePolicy):
54
+ policies = other.policies or []
55
+ return CompoundCachePolicy(policies=policies + [self])
56
+ else:
57
+ return CompoundCachePolicy(policies=[self, other])
58
+
59
+
60
+ @dataclass
61
+ class CacheKeyFnPolicy(CachePolicy):
62
+ # making it optional for tests
63
+ cache_key_fn: Optional[
64
+ Callable[["TaskRunContext", Dict[str, Any]], Optional[str]]
65
+ ] = None
66
+
67
+ def compute_key(
68
+ self,
69
+ task_ctx: TaskRunContext,
70
+ inputs: Dict[str, Any],
71
+ flow_parameters: Dict[str, Any],
72
+ **kwargs,
73
+ ) -> Optional[str]:
74
+ if self.cache_key_fn:
75
+ return self.cache_key_fn(task_ctx, inputs)
76
+
77
+
78
+ @dataclass
79
+ class CompoundCachePolicy(CachePolicy):
80
+ policies: list = None
81
+
82
+ def compute_key(
83
+ self,
84
+ task_ctx: TaskRunContext,
85
+ inputs: Dict[str, Any],
86
+ flow_parameters: Dict[str, Any],
87
+ **kwargs,
88
+ ) -> Optional[str]:
89
+ keys = []
90
+ for policy in self.policies:
91
+ keys.append(
92
+ policy.compute_key(
93
+ task_ctx=task_ctx,
94
+ inputs=inputs,
95
+ flow_parameters=flow_parameters,
96
+ **kwargs,
97
+ )
98
+ )
99
+ return hash_objects(*keys)
100
+
101
+
102
+ @dataclass
103
+ class Default(CachePolicy):
104
+ "Execution run ID only"
105
+
106
+ def compute_key(
107
+ self,
108
+ task_ctx: TaskRunContext,
109
+ inputs: Dict[str, Any],
110
+ flow_parameters: Dict[str, Any],
111
+ **kwargs,
112
+ ) -> Optional[str]:
113
+ return str(task_ctx.task_run.id)
114
+
115
+
116
+ @dataclass
117
+ class _None(CachePolicy):
118
+ "ignore key policies altogether, always run - prevents persistence"
119
+
120
+ def compute_key(
121
+ self,
122
+ task_ctx: TaskRunContext,
123
+ inputs: Dict[str, Any],
124
+ flow_parameters: Dict[str, Any],
125
+ **kwargs,
126
+ ) -> Optional[str]:
127
+ return None
128
+
129
+
130
+ @dataclass
131
+ class TaskDef(CachePolicy):
132
+ def compute_key(
133
+ self,
134
+ task_ctx: TaskRunContext,
135
+ inputs: Dict[str, Any],
136
+ flow_parameters: Dict[str, Any],
137
+ **kwargs,
138
+ ) -> Optional[str]:
139
+ lines = inspect.getsource(task_ctx.task)
140
+ return hash_objects(lines)
141
+
142
+
143
+ @dataclass
144
+ class FlowParameters(CachePolicy):
145
+ pass
146
+
147
+
148
+ @dataclass
149
+ class Inputs(CachePolicy):
150
+ """
151
+ Exposes flag for whether to include flow parameters as well.
152
+
153
+ And exclude/include config.
154
+ """
155
+
156
+ exclude: list = None
157
+
158
+ def compute_key(
159
+ self,
160
+ task_ctx: TaskRunContext,
161
+ inputs: Dict[str, Any],
162
+ flow_parameters: Dict[str, Any],
163
+ **kwargs,
164
+ ) -> Optional[str]:
165
+ hashed_inputs = {}
166
+ inputs = inputs or {}
167
+ exclude = self.exclude or []
168
+
169
+ for key, val in inputs.items():
170
+ if key not in exclude:
171
+ hashed_inputs[key] = val
172
+
173
+ return hash_objects(hashed_inputs)
174
+
175
+
176
+ DEFAULT = Default()
177
+ INPUTS = Inputs()
178
+ NONE = _None()
179
+ TASKDEF = TaskDef()
@@ -0,0 +1,42 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any
3
+
4
+ from prefect.exceptions import ObjectNotFound
5
+ from prefect.results import BaseResult, PersistedResult, ResultFactory
6
+ from prefect.utilities.asyncutils import run_coro_as_sync
7
+
8
+ from .store import RecordStore
9
+
10
+
11
+ @dataclass
12
+ class ResultFactoryStore(RecordStore):
13
+ result_factory: ResultFactory
14
+ cache: PersistedResult = None
15
+
16
+ def exists(self, key: str) -> bool:
17
+ try:
18
+ result = self.read(key)
19
+ result.get(_sync=True)
20
+ self.cache = result
21
+ return True
22
+ except (ObjectNotFound, ValueError):
23
+ return False
24
+
25
+ def read(self, key: str) -> BaseResult:
26
+ if self.cache:
27
+ return self.cache
28
+ try:
29
+ result = PersistedResult(
30
+ serializer_type=self.result_factory.serializer.type,
31
+ storage_block_id=self.result_factory.storage_block_id,
32
+ storage_key=key,
33
+ )
34
+ return result
35
+ except Exception:
36
+ # this is a bit of a bandaid for functionality
37
+ raise ValueError("Result could not be read")
38
+
39
+ def write(self, key: str, value: Any) -> BaseResult:
40
+ if isinstance(value, BaseResult):
41
+ return value
42
+ return run_coro_as_sync(self.result_factory.create_result(obj=value, key=key))
@@ -0,0 +1,9 @@
1
+ class RecordStore:
2
+ def read(self, key: str):
3
+ raise NotImplementedError
4
+
5
+ def write(self, key: str, value: dict):
6
+ raise NotImplementedError
7
+
8
+ def exists(self, key: str) -> bool:
9
+ return False