prefect-client 2.19.2__py3-none-any.whl → 3.0.0rc1__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 (239) 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/system.py +22 -11
  26. prefect/blocks/webhook.py +2 -9
  27. prefect/client/base.py +4 -4
  28. prefect/client/cloud.py +8 -13
  29. prefect/client/orchestration.py +347 -341
  30. prefect/client/schemas/actions.py +92 -86
  31. prefect/client/schemas/filters.py +20 -40
  32. prefect/client/schemas/objects.py +151 -145
  33. prefect/client/schemas/responses.py +16 -24
  34. prefect/client/schemas/schedules.py +47 -35
  35. prefect/client/subscriptions.py +2 -2
  36. prefect/client/utilities.py +5 -2
  37. prefect/concurrency/asyncio.py +3 -1
  38. prefect/concurrency/events.py +1 -1
  39. prefect/concurrency/services.py +6 -3
  40. prefect/context.py +195 -27
  41. prefect/deployments/__init__.py +5 -6
  42. prefect/deployments/base.py +7 -5
  43. prefect/deployments/flow_runs.py +185 -0
  44. prefect/deployments/runner.py +50 -45
  45. prefect/deployments/schedules.py +28 -23
  46. prefect/deployments/steps/__init__.py +0 -1
  47. prefect/deployments/steps/core.py +1 -0
  48. prefect/deployments/steps/pull.py +7 -21
  49. prefect/engine.py +12 -2422
  50. prefect/events/actions.py +17 -23
  51. prefect/events/cli/automations.py +19 -6
  52. prefect/events/clients.py +14 -37
  53. prefect/events/filters.py +14 -18
  54. prefect/events/related.py +2 -2
  55. prefect/events/schemas/__init__.py +0 -5
  56. prefect/events/schemas/automations.py +55 -46
  57. prefect/events/schemas/deployment_triggers.py +7 -197
  58. prefect/events/schemas/events.py +34 -65
  59. prefect/events/schemas/labelling.py +10 -14
  60. prefect/events/utilities.py +2 -3
  61. prefect/events/worker.py +2 -3
  62. prefect/filesystems.py +6 -517
  63. prefect/{new_flow_engine.py → flow_engine.py} +313 -72
  64. prefect/flow_runs.py +377 -5
  65. prefect/flows.py +307 -166
  66. prefect/futures.py +186 -345
  67. prefect/infrastructure/__init__.py +0 -27
  68. prefect/infrastructure/provisioners/__init__.py +5 -3
  69. prefect/infrastructure/provisioners/cloud_run.py +11 -6
  70. prefect/infrastructure/provisioners/container_instance.py +11 -7
  71. prefect/infrastructure/provisioners/ecs.py +6 -4
  72. prefect/infrastructure/provisioners/modal.py +8 -5
  73. prefect/input/actions.py +2 -4
  74. prefect/input/run_input.py +5 -7
  75. prefect/logging/formatters.py +0 -2
  76. prefect/logging/handlers.py +3 -11
  77. prefect/logging/loggers.py +2 -2
  78. prefect/manifests.py +2 -1
  79. prefect/records/__init__.py +1 -0
  80. prefect/records/result_store.py +42 -0
  81. prefect/records/store.py +9 -0
  82. prefect/results.py +43 -39
  83. prefect/runner/runner.py +19 -15
  84. prefect/runner/server.py +6 -10
  85. prefect/runner/storage.py +3 -8
  86. prefect/runner/submit.py +2 -2
  87. prefect/runner/utils.py +2 -2
  88. prefect/serializers.py +24 -35
  89. prefect/server/api/collections_data/views/aggregate-worker-metadata.json +5 -14
  90. prefect/settings.py +70 -133
  91. prefect/states.py +17 -47
  92. prefect/task_engine.py +697 -58
  93. prefect/task_runners.py +269 -301
  94. prefect/task_server.py +53 -34
  95. prefect/tasks.py +327 -337
  96. prefect/transactions.py +220 -0
  97. prefect/types/__init__.py +61 -82
  98. prefect/utilities/asyncutils.py +195 -136
  99. prefect/utilities/callables.py +311 -43
  100. prefect/utilities/collections.py +23 -38
  101. prefect/utilities/dispatch.py +11 -3
  102. prefect/utilities/dockerutils.py +4 -0
  103. prefect/utilities/engine.py +140 -20
  104. prefect/utilities/importtools.py +97 -27
  105. prefect/utilities/pydantic.py +128 -38
  106. prefect/utilities/schema_tools/hydration.py +5 -1
  107. prefect/utilities/templating.py +12 -2
  108. prefect/variables.py +78 -61
  109. prefect/workers/__init__.py +0 -1
  110. prefect/workers/base.py +15 -17
  111. prefect/workers/process.py +3 -8
  112. prefect/workers/server.py +2 -2
  113. {prefect_client-2.19.2.dist-info → prefect_client-3.0.0rc1.dist-info}/METADATA +22 -21
  114. prefect_client-3.0.0rc1.dist-info/RECORD +176 -0
  115. prefect/_internal/pydantic/_base_model.py +0 -51
  116. prefect/_internal/pydantic/_compat.py +0 -82
  117. prefect/_internal/pydantic/_flags.py +0 -20
  118. prefect/_internal/pydantic/_types.py +0 -8
  119. prefect/_internal/pydantic/utilities/__init__.py +0 -0
  120. prefect/_internal/pydantic/utilities/config_dict.py +0 -72
  121. prefect/_internal/pydantic/utilities/field_validator.py +0 -150
  122. prefect/_internal/pydantic/utilities/model_construct.py +0 -56
  123. prefect/_internal/pydantic/utilities/model_copy.py +0 -55
  124. prefect/_internal/pydantic/utilities/model_dump.py +0 -136
  125. prefect/_internal/pydantic/utilities/model_dump_json.py +0 -112
  126. prefect/_internal/pydantic/utilities/model_fields.py +0 -50
  127. prefect/_internal/pydantic/utilities/model_fields_set.py +0 -29
  128. prefect/_internal/pydantic/utilities/model_json_schema.py +0 -82
  129. prefect/_internal/pydantic/utilities/model_rebuild.py +0 -80
  130. prefect/_internal/pydantic/utilities/model_validate.py +0 -75
  131. prefect/_internal/pydantic/utilities/model_validate_json.py +0 -68
  132. prefect/_internal/pydantic/utilities/model_validator.py +0 -87
  133. prefect/_internal/pydantic/utilities/type_adapter.py +0 -71
  134. prefect/_vendor/__init__.py +0 -0
  135. prefect/_vendor/fastapi/__init__.py +0 -25
  136. prefect/_vendor/fastapi/applications.py +0 -946
  137. prefect/_vendor/fastapi/background.py +0 -3
  138. prefect/_vendor/fastapi/concurrency.py +0 -44
  139. prefect/_vendor/fastapi/datastructures.py +0 -58
  140. prefect/_vendor/fastapi/dependencies/__init__.py +0 -0
  141. prefect/_vendor/fastapi/dependencies/models.py +0 -64
  142. prefect/_vendor/fastapi/dependencies/utils.py +0 -877
  143. prefect/_vendor/fastapi/encoders.py +0 -177
  144. prefect/_vendor/fastapi/exception_handlers.py +0 -40
  145. prefect/_vendor/fastapi/exceptions.py +0 -46
  146. prefect/_vendor/fastapi/logger.py +0 -3
  147. prefect/_vendor/fastapi/middleware/__init__.py +0 -1
  148. prefect/_vendor/fastapi/middleware/asyncexitstack.py +0 -25
  149. prefect/_vendor/fastapi/middleware/cors.py +0 -3
  150. prefect/_vendor/fastapi/middleware/gzip.py +0 -3
  151. prefect/_vendor/fastapi/middleware/httpsredirect.py +0 -3
  152. prefect/_vendor/fastapi/middleware/trustedhost.py +0 -3
  153. prefect/_vendor/fastapi/middleware/wsgi.py +0 -3
  154. prefect/_vendor/fastapi/openapi/__init__.py +0 -0
  155. prefect/_vendor/fastapi/openapi/constants.py +0 -2
  156. prefect/_vendor/fastapi/openapi/docs.py +0 -203
  157. prefect/_vendor/fastapi/openapi/models.py +0 -480
  158. prefect/_vendor/fastapi/openapi/utils.py +0 -485
  159. prefect/_vendor/fastapi/param_functions.py +0 -340
  160. prefect/_vendor/fastapi/params.py +0 -453
  161. prefect/_vendor/fastapi/requests.py +0 -4
  162. prefect/_vendor/fastapi/responses.py +0 -40
  163. prefect/_vendor/fastapi/routing.py +0 -1331
  164. prefect/_vendor/fastapi/security/__init__.py +0 -15
  165. prefect/_vendor/fastapi/security/api_key.py +0 -98
  166. prefect/_vendor/fastapi/security/base.py +0 -6
  167. prefect/_vendor/fastapi/security/http.py +0 -172
  168. prefect/_vendor/fastapi/security/oauth2.py +0 -227
  169. prefect/_vendor/fastapi/security/open_id_connect_url.py +0 -34
  170. prefect/_vendor/fastapi/security/utils.py +0 -10
  171. prefect/_vendor/fastapi/staticfiles.py +0 -1
  172. prefect/_vendor/fastapi/templating.py +0 -3
  173. prefect/_vendor/fastapi/testclient.py +0 -1
  174. prefect/_vendor/fastapi/types.py +0 -3
  175. prefect/_vendor/fastapi/utils.py +0 -235
  176. prefect/_vendor/fastapi/websockets.py +0 -7
  177. prefect/_vendor/starlette/__init__.py +0 -1
  178. prefect/_vendor/starlette/_compat.py +0 -28
  179. prefect/_vendor/starlette/_exception_handler.py +0 -80
  180. prefect/_vendor/starlette/_utils.py +0 -88
  181. prefect/_vendor/starlette/applications.py +0 -261
  182. prefect/_vendor/starlette/authentication.py +0 -159
  183. prefect/_vendor/starlette/background.py +0 -43
  184. prefect/_vendor/starlette/concurrency.py +0 -59
  185. prefect/_vendor/starlette/config.py +0 -151
  186. prefect/_vendor/starlette/convertors.py +0 -87
  187. prefect/_vendor/starlette/datastructures.py +0 -707
  188. prefect/_vendor/starlette/endpoints.py +0 -130
  189. prefect/_vendor/starlette/exceptions.py +0 -60
  190. prefect/_vendor/starlette/formparsers.py +0 -276
  191. prefect/_vendor/starlette/middleware/__init__.py +0 -17
  192. prefect/_vendor/starlette/middleware/authentication.py +0 -52
  193. prefect/_vendor/starlette/middleware/base.py +0 -220
  194. prefect/_vendor/starlette/middleware/cors.py +0 -176
  195. prefect/_vendor/starlette/middleware/errors.py +0 -265
  196. prefect/_vendor/starlette/middleware/exceptions.py +0 -74
  197. prefect/_vendor/starlette/middleware/gzip.py +0 -113
  198. prefect/_vendor/starlette/middleware/httpsredirect.py +0 -19
  199. prefect/_vendor/starlette/middleware/sessions.py +0 -82
  200. prefect/_vendor/starlette/middleware/trustedhost.py +0 -64
  201. prefect/_vendor/starlette/middleware/wsgi.py +0 -147
  202. prefect/_vendor/starlette/requests.py +0 -328
  203. prefect/_vendor/starlette/responses.py +0 -347
  204. prefect/_vendor/starlette/routing.py +0 -933
  205. prefect/_vendor/starlette/schemas.py +0 -154
  206. prefect/_vendor/starlette/staticfiles.py +0 -248
  207. prefect/_vendor/starlette/status.py +0 -199
  208. prefect/_vendor/starlette/templating.py +0 -231
  209. prefect/_vendor/starlette/testclient.py +0 -804
  210. prefect/_vendor/starlette/types.py +0 -30
  211. prefect/_vendor/starlette/websockets.py +0 -193
  212. prefect/agent.py +0 -698
  213. prefect/deployments/deployments.py +0 -1042
  214. prefect/deprecated/__init__.py +0 -0
  215. prefect/deprecated/data_documents.py +0 -350
  216. prefect/deprecated/packaging/__init__.py +0 -12
  217. prefect/deprecated/packaging/base.py +0 -96
  218. prefect/deprecated/packaging/docker.py +0 -146
  219. prefect/deprecated/packaging/file.py +0 -92
  220. prefect/deprecated/packaging/orion.py +0 -80
  221. prefect/deprecated/packaging/serializers.py +0 -171
  222. prefect/events/instrument.py +0 -135
  223. prefect/infrastructure/base.py +0 -323
  224. prefect/infrastructure/container.py +0 -818
  225. prefect/infrastructure/kubernetes.py +0 -920
  226. prefect/infrastructure/process.py +0 -289
  227. prefect/new_task_engine.py +0 -423
  228. prefect/pydantic/__init__.py +0 -76
  229. prefect/pydantic/main.py +0 -39
  230. prefect/software/__init__.py +0 -2
  231. prefect/software/base.py +0 -50
  232. prefect/software/conda.py +0 -199
  233. prefect/software/pip.py +0 -122
  234. prefect/software/python.py +0 -52
  235. prefect/workers/block.py +0 -218
  236. prefect_client-2.19.2.dist-info/RECORD +0 -292
  237. {prefect_client-2.19.2.dist-info → prefect_client-3.0.0rc1.dist-info}/LICENSE +0 -0
  238. {prefect_client-2.19.2.dist-info → prefect_client-3.0.0rc1.dist-info}/WHEEL +0 -0
  239. {prefect_client-2.19.2.dist-info → prefect_client-3.0.0rc1.dist-info}/top_level.txt +0 -0
prefect/results.py CHANGED
@@ -16,13 +16,14 @@ from typing import (
16
16
  )
17
17
  from uuid import UUID
18
18
 
19
+ from pydantic import BaseModel, ConfigDict, Field, PrivateAttr, ValidationError
20
+ from pydantic_core import PydanticUndefinedType
19
21
  from typing_extensions import ParamSpec, Self
20
22
 
21
23
  import prefect
22
- from prefect._internal.pydantic import HAS_PYDANTIC_V2
23
24
  from prefect.blocks.core import Block
24
25
  from prefect.client.utilities import inject_client
25
- from prefect.exceptions import MissingResult
26
+ from prefect.exceptions import MissingResult, ObjectAlreadyExists
26
27
  from prefect.filesystems import (
27
28
  LocalFileSystem,
28
29
  ReadableFileSystem,
@@ -41,13 +42,6 @@ from prefect.utilities.annotations import NotSet
41
42
  from prefect.utilities.asyncutils import sync_compatible
42
43
  from prefect.utilities.pydantic import get_dispatch_key, lookup_type, register_base_type
43
44
 
44
- if HAS_PYDANTIC_V2:
45
- import pydantic.v1 as pydantic
46
-
47
- else:
48
- import pydantic
49
-
50
-
51
45
  if TYPE_CHECKING:
52
46
  from prefect import Flow, Task
53
47
  from prefect.client.orchestration import PrefectClient
@@ -84,14 +78,14 @@ _default_task_scheduling_storages: Dict[Tuple[str, str], WritableFileSystem] = {
84
78
 
85
79
  async def get_or_create_default_task_scheduling_storage() -> ResultStorage:
86
80
  """
87
- Generate a default file system for autonomous task parameter/result storage.
81
+ Generate a default file system for background task parameter/result storage.
88
82
  """
89
83
  default_storage_name, storage_path = cache_key = (
90
84
  PREFECT_TASK_SCHEDULING_DEFAULT_STORAGE_BLOCK.value(),
91
85
  PREFECT_LOCAL_STORAGE_PATH.value(),
92
86
  )
93
87
 
94
- async def get_storage():
88
+ async def get_storage() -> WritableFileSystem:
95
89
  try:
96
90
  return await Block.load(default_storage_name)
97
91
  except ValueError as e:
@@ -110,12 +104,14 @@ async def get_or_create_default_task_scheduling_storage() -> ResultStorage:
110
104
 
111
105
  try:
112
106
  await block.save(name, overwrite=False)
113
- return block
114
107
  except ValueError as e:
115
108
  if "already in use" not in str(e):
116
109
  raise e
110
+ except ObjectAlreadyExists:
111
+ # Another client created the block before we reached this line
112
+ block = await Block.load(default_storage_name)
117
113
 
118
- return await Block.load(default_storage_name)
114
+ return block
119
115
 
120
116
  try:
121
117
  return _default_task_scheduling_storages[cache_key]
@@ -171,14 +167,14 @@ def task_features_require_result_persistence(task: "Task") -> bool:
171
167
  return False
172
168
 
173
169
 
174
- def _format_user_supplied_storage_key(key):
170
+ def _format_user_supplied_storage_key(key: str) -> str:
175
171
  # Note here we are pinning to task runs since flow runs do not support storage keys
176
172
  # yet; we'll need to split logic in the future or have two separate functions
177
173
  runtime_vars = {key: getattr(prefect.runtime, key) for key in dir(prefect.runtime)}
178
174
  return key.format(**runtime_vars, parameters=prefect.runtime.task_run.parameters)
179
175
 
180
176
 
181
- class ResultFactory(pydantic.BaseModel):
177
+ class ResultFactory(BaseModel):
182
178
  """
183
179
  A utility to generate `Result` types.
184
180
  """
@@ -186,7 +182,7 @@ class ResultFactory(pydantic.BaseModel):
186
182
  persist_result: bool
187
183
  cache_result_in_memory: bool
188
184
  serializer: Serializer
189
- storage_block_id: Optional[uuid.UUID]
185
+ storage_block_id: Optional[uuid.UUID] = None
190
186
  storage_block: WritableFileSystem
191
187
  storage_key_fn: Callable[[], str]
192
188
 
@@ -430,7 +426,7 @@ class ResultFactory(pydantic.BaseModel):
430
426
  )
431
427
 
432
428
  @sync_compatible
433
- async def create_result(self, obj: R) -> Union[R, "BaseResult[R]"]:
429
+ async def create_result(self, obj: R, key: str = None) -> Union[R, "BaseResult[R]"]:
434
430
  """
435
431
  Create a result type for the given object.
436
432
 
@@ -450,11 +446,20 @@ class ResultFactory(pydantic.BaseModel):
450
446
  if type(obj) in LITERAL_TYPES:
451
447
  return await LiteralResult.create(obj)
452
448
 
449
+ if key:
450
+
451
+ def key_fn():
452
+ return key
453
+
454
+ storage_key_fn = key_fn
455
+ else:
456
+ storage_key_fn = self.storage_key_fn
457
+
453
458
  return await PersistedResult.create(
454
459
  obj,
455
460
  storage_block=self.storage_block,
456
461
  storage_block_id=self.storage_block_id,
457
- storage_key_fn=self.storage_key_fn,
462
+ storage_key_fn=storage_key_fn,
458
463
  serializer=self.serializer,
459
464
  cache_object=should_cache_object,
460
465
  )
@@ -475,17 +480,19 @@ class ResultFactory(pydantic.BaseModel):
475
480
  assert (
476
481
  self.storage_block_id is not None
477
482
  ), "Unexpected storage block ID. Was it persisted?"
478
- blob = PersistedResultBlob.parse_raw(
483
+ blob = PersistedResultBlob.model_validate_json(
479
484
  await self.storage_block.read_path(f"parameters/{identifier}")
480
485
  )
481
486
  return self.serializer.loads(blob.data)
482
487
 
483
488
 
484
489
  @register_base_type
485
- class BaseResult(pydantic.BaseModel, abc.ABC, Generic[R]):
490
+ class BaseResult(BaseModel, abc.ABC, Generic[R]):
491
+ model_config = ConfigDict(extra="forbid")
492
+
486
493
  type: str
487
- artifact_type: Optional[str]
488
- artifact_description: Optional[str]
494
+ artifact_type: Optional[str] = None
495
+ artifact_description: Optional[str] = None
489
496
 
490
497
  def __init__(self, **data: Any) -> None:
491
498
  type_string = get_dispatch_key(self) if type(self) != BaseResult else "__base__"
@@ -497,12 +504,12 @@ class BaseResult(pydantic.BaseModel, abc.ABC, Generic[R]):
497
504
  try:
498
505
  subcls = lookup_type(cls, dispatch_key=kwargs["type"])
499
506
  except KeyError as exc:
500
- raise pydantic.ValidationError(errors=[exc], model=cls)
507
+ raise ValidationError(errors=[exc], model=cls)
501
508
  return super().__new__(subcls)
502
509
  else:
503
510
  return super().__new__(cls)
504
511
 
505
- _cache: Any = pydantic.PrivateAttr(NotSet)
512
+ _cache: Any = PrivateAttr(NotSet)
506
513
 
507
514
  def _cache_object(self, obj: Any) -> None:
508
515
  self._cache = obj
@@ -524,12 +531,10 @@ class BaseResult(pydantic.BaseModel, abc.ABC, Generic[R]):
524
531
  ) -> "BaseResult[R]":
525
532
  ...
526
533
 
527
- class Config:
528
- extra = "forbid"
529
-
530
534
  @classmethod
531
535
  def __dispatch_key__(cls, **kwargs):
532
- return cls.__fields__.get("type").get_default()
536
+ default = cls.model_fields.get("type").get_default()
537
+ return cls.__name__ if isinstance(default, PydanticUndefinedType) else default
533
538
 
534
539
 
535
540
  class UnpersistedResult(BaseResult):
@@ -537,7 +542,7 @@ class UnpersistedResult(BaseResult):
537
542
  Result type for results that are not persisted outside of local memory.
538
543
  """
539
544
 
540
- type = "unpersisted"
545
+ type: str = "unpersisted"
541
546
 
542
547
  @sync_compatible
543
548
  async def get(self) -> R:
@@ -572,8 +577,8 @@ class LiteralResult(BaseResult):
572
577
  They are not persisted to external result storage.
573
578
  """
574
579
 
575
- type = "literal"
576
- value: Any
580
+ type: str = "literal"
581
+ value: Any = None
577
582
 
578
583
  def has_cached_object(self) -> bool:
579
584
  # This result type always has the object cached in memory
@@ -609,13 +614,13 @@ class PersistedResult(BaseResult):
609
614
  content was written.
610
615
  """
611
616
 
612
- type = "reference"
617
+ type: str = "reference"
613
618
 
614
619
  serializer_type: str
615
620
  storage_block_id: uuid.UUID
616
621
  storage_key: str
617
622
 
618
- _should_cache_object: bool = pydantic.PrivateAttr(default=True)
623
+ _should_cache_object: bool = PrivateAttr(default=True)
619
624
 
620
625
  @sync_compatible
621
626
  @inject_client
@@ -643,7 +648,7 @@ class PersistedResult(BaseResult):
643
648
  block_document = await client.read_block_document(self.storage_block_id)
644
649
  storage_block: ReadableFileSystem = Block._from_block_document(block_document)
645
650
  content = await storage_block.read_path(self.storage_key)
646
- blob = PersistedResultBlob.parse_raw(content)
651
+ blob = PersistedResultBlob.model_validate_json(content)
647
652
  return blob
648
653
 
649
654
  @staticmethod
@@ -686,7 +691,6 @@ class PersistedResult(BaseResult):
686
691
  raise TypeError(
687
692
  f"Expected type 'str' for result storage key; got value {key!r}"
688
693
  )
689
-
690
694
  await storage_block.write_path(key, content=blob.to_bytes())
691
695
 
692
696
  description = f"Result of type `{type(obj).__name__}`"
@@ -716,7 +720,7 @@ class PersistedResult(BaseResult):
716
720
  return result
717
721
 
718
722
 
719
- class PersistedResultBlob(pydantic.BaseModel):
723
+ class PersistedResultBlob(BaseModel):
720
724
  """
721
725
  The format of the content stored by a persisted result.
722
726
 
@@ -725,10 +729,10 @@ class PersistedResultBlob(pydantic.BaseModel):
725
729
 
726
730
  serializer: Serializer
727
731
  data: bytes
728
- prefect_version: str = pydantic.Field(default=prefect.__version__)
732
+ prefect_version: str = Field(default=prefect.__version__)
729
733
 
730
734
  def to_bytes(self) -> bytes:
731
- return self.json().encode()
735
+ return self.model_dump_json(serialize_as_any=True).encode()
732
736
 
733
737
 
734
738
  class UnknownResult(BaseResult):
@@ -742,7 +746,7 @@ class UnknownResult(BaseResult):
742
746
  completed task.
743
747
  """
744
748
 
745
- type = "unknown"
749
+ type: str = "unknown"
746
750
  value: None
747
751
 
748
752
  def has_cached_object(self) -> bool:
prefect/runner/runner.py CHANGED
@@ -71,19 +71,15 @@ from prefect.client.schemas.objects import (
71
71
  StateType,
72
72
  )
73
73
  from prefect.client.schemas.schedules import SCHEDULE_TYPES
74
- from prefect.deployments.deployments import load_flow_from_flow_run
75
74
  from prefect.deployments.runner import (
76
75
  EntrypointType,
77
76
  RunnerDeployment,
78
77
  )
79
78
  from prefect.deployments.schedules import FlexibleScheduleList
80
79
  from prefect.events import DeploymentTriggerTypes, TriggerTypes
81
- from prefect.exceptions import (
82
- Abort,
83
- )
84
- from prefect.flows import Flow
80
+ from prefect.exceptions import Abort, ObjectNotFound
81
+ from prefect.flows import Flow, load_flow_from_flow_run
85
82
  from prefect.logging.loggers import PrefectLogAdapter, flow_run_logger, get_logger
86
- from prefect.runner.server import start_webserver
87
83
  from prefect.runner.storage import RunnerStorage
88
84
  from prefect.settings import (
89
85
  PREFECT_API_URL,
@@ -233,7 +229,7 @@ class Runner:
233
229
  description: Optional[str] = None,
234
230
  tags: Optional[List[str]] = None,
235
231
  version: Optional[str] = None,
236
- enforce_parameter_schema: bool = False,
232
+ enforce_parameter_schema: bool = True,
237
233
  entrypoint_type: EntrypointType = EntrypointType.FILE_PATH,
238
234
  ) -> UUID:
239
235
  """
@@ -366,6 +362,8 @@ class Runner:
366
362
  runner.start()
367
363
  ```
368
364
  """
365
+ from prefect.runner.server import start_webserver
366
+
369
367
  _register_signal(signal.SIGTERM, self.handle_sigterm)
370
368
 
371
369
  webserver = webserver if webserver is not None else self.webserver
@@ -1082,7 +1080,7 @@ class Runner:
1082
1080
  state_updates = state_updates or {}
1083
1081
  state_updates.setdefault("name", "Cancelled")
1084
1082
  state_updates.setdefault("type", StateType.CANCELLED)
1085
- state = flow_run.state.copy(update=state_updates)
1083
+ state = flow_run.state.model_copy(update=state_updates)
1086
1084
 
1087
1085
  await self._client.set_flow_run_state(flow_run.id, state, force=True)
1088
1086
 
@@ -1130,12 +1128,18 @@ class Runner:
1130
1128
  Run the hooks for a flow.
1131
1129
  """
1132
1130
  if state.is_cancelling():
1133
- flow = await load_flow_from_flow_run(
1134
- flow_run, client=self._client, storage_base_path=str(self._tmp_dir)
1135
- )
1136
- hooks = flow.on_cancellation or []
1131
+ try:
1132
+ flow = await load_flow_from_flow_run(
1133
+ flow_run, storage_base_path=str(self._tmp_dir)
1134
+ )
1135
+ hooks = flow.on_cancellation_hooks or []
1137
1136
 
1138
- await _run_hooks(hooks, flow_run, flow, state)
1137
+ await _run_hooks(hooks, flow_run, flow, state)
1138
+ except ObjectNotFound:
1139
+ run_logger = self._get_flow_run_logger(flow_run)
1140
+ run_logger.warning(
1141
+ f"Runner cannot retrieve flow to execute cancellation hooks for flow run {flow_run.id!r}."
1142
+ )
1139
1143
 
1140
1144
  async def _run_on_crashed_hooks(
1141
1145
  self,
@@ -1147,9 +1151,9 @@ class Runner:
1147
1151
  """
1148
1152
  if state.is_crashed():
1149
1153
  flow = await load_flow_from_flow_run(
1150
- flow_run, client=self._client, storage_base_path=str(self._tmp_dir)
1154
+ flow_run, storage_base_path=str(self._tmp_dir)
1151
1155
  )
1152
- hooks = flow.on_crashed or []
1156
+ hooks = flow.on_crashed_hooks or []
1153
1157
 
1154
1158
  await _run_hooks(hooks, flow_run, flow, state)
1155
1159
 
prefect/runner/server.py CHANGED
@@ -3,11 +3,10 @@ from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Tuple
3
3
 
4
4
  import pendulum
5
5
  import uvicorn
6
- from prefect._vendor.fastapi import APIRouter, FastAPI, HTTPException, status
7
- from prefect._vendor.fastapi.responses import JSONResponse
6
+ from fastapi import APIRouter, FastAPI, HTTPException, status
7
+ from fastapi.responses import JSONResponse
8
8
  from typing_extensions import Literal
9
9
 
10
- from prefect._internal.pydantic import HAS_PYDANTIC_V2
11
10
  from prefect._internal.schemas.validators import validate_values_conform_to_schema
12
11
  from prefect.client.orchestration import get_client
13
12
  from prefect.exceptions import MissingFlowError, ScriptError
@@ -30,10 +29,7 @@ if TYPE_CHECKING:
30
29
  from prefect.client.schemas.responses import DeploymentResponse
31
30
  from prefect.runner import Runner
32
31
 
33
- if HAS_PYDANTIC_V2:
34
- from pydantic.v1 import BaseModel
35
- else:
36
- from pydantic import BaseModel
32
+ from pydantic import BaseModel
37
33
 
38
34
  logger = get_logger("webserver")
39
35
 
@@ -161,7 +157,7 @@ async def get_subflow_schemas(runner: "Runner") -> Dict[str, Dict]:
161
157
  script = deployment.entrypoint.split(":")[0]
162
158
  subflows = load_flows_from_script(script)
163
159
  for flow in subflows:
164
- schemas[flow.name] = flow.parameters.dict()
160
+ schemas[flow.name] = flow.parameters.model_dump()
165
161
 
166
162
  return schemas
167
163
 
@@ -183,7 +179,7 @@ def _flow_schema_changed(flow: Flow, schemas: Dict[str, Dict]) -> bool:
183
179
  flow_name_with_dashes = flow.name.replace("_", "-")
184
180
 
185
181
  schema = schemas.get(flow.name, None) or schemas.get(flow_name_with_dashes, None)
186
- if schema is not None and flow.parameters.dict() != schema:
182
+ if schema is not None and flow.parameters.model_dump() != schema:
187
183
  return True
188
184
  return False
189
185
 
@@ -236,7 +232,7 @@ def _build_generic_endpoint_for_flows(
236
232
 
237
233
  return JSONResponse(
238
234
  status_code=status.HTTP_201_CREATED,
239
- content=flow_run.dict(json_compatible=True),
235
+ content=flow_run.model_dump(mode="json"),
240
236
  )
241
237
 
242
238
  return _create_flow_run_for_flow_from_fqn
prefect/runner/storage.py CHANGED
@@ -8,20 +8,15 @@ from uuid import uuid4
8
8
 
9
9
  import fsspec
10
10
  from anyio import run_process
11
+ from pydantic import SecretStr
11
12
 
12
13
  from prefect._internal.concurrency.api import create_call, from_async
13
- from prefect._internal.pydantic import HAS_PYDANTIC_V2
14
14
  from prefect.blocks.core import Block, BlockNotSavedError
15
15
  from prefect.blocks.system import Secret
16
16
  from prefect.filesystems import ReadableDeploymentStorage, WritableDeploymentStorage
17
17
  from prefect.logging.loggers import get_logger
18
18
  from prefect.utilities.collections import visit_collection
19
19
 
20
- if HAS_PYDANTIC_V2:
21
- from pydantic.v1 import SecretStr
22
- else:
23
- from pydantic import SecretStr
24
-
25
20
 
26
21
  @runtime_checkable
27
22
  class RunnerStorage(Protocol):
@@ -159,7 +154,7 @@ class GitRepository:
159
154
  url_components = urlparse(self._url)
160
155
 
161
156
  credentials = (
162
- self._credentials.dict()
157
+ self._credentials.model_dump()
163
158
  if isinstance(self._credentials, Block)
164
159
  else deepcopy(self._credentials)
165
160
  )
@@ -392,7 +387,7 @@ class RemoteStorage:
392
387
  if hasattr(obj, "value"):
393
388
  return obj.value
394
389
  else:
395
- return obj.dict()
390
+ return obj.model_dump()
396
391
  return obj
397
392
 
398
393
  settings_with_block_values = visit_collection(
prefect/runner/submit.py CHANGED
@@ -43,7 +43,7 @@ async def _submit_flow_to_runner(
43
43
  Returns:
44
44
  A `FlowRun` object representing the flow run that was submitted.
45
45
  """
46
- from prefect.engine import (
46
+ from prefect.utilities.engine import (
47
47
  _dynamic_key_for_task_run,
48
48
  collect_task_run_inputs,
49
49
  resolve_inputs,
@@ -90,7 +90,7 @@ async def _submit_flow_to_runner(
90
90
  )
91
91
  response.raise_for_status()
92
92
 
93
- return FlowRun.parse_obj(response.json())
93
+ return FlowRun.model_validate(response.json())
94
94
 
95
95
 
96
96
  @overload
prefect/runner/utils.py CHANGED
@@ -1,8 +1,8 @@
1
1
  from copy import deepcopy
2
2
  from typing import Any, Dict
3
3
 
4
- from prefect._vendor.fastapi import FastAPI
5
- from prefect._vendor.fastapi.openapi.utils import get_openapi
4
+ from fastapi import FastAPI
5
+ from fastapi.openapi.utils import get_openapi
6
6
 
7
7
  from prefect import __version__ as PREFECT_VERSION
8
8
 
prefect/serializers.py CHANGED
@@ -15,6 +15,14 @@ import abc
15
15
  import base64
16
16
  from typing import Any, Dict, Generic, Optional, Type, TypeVar
17
17
 
18
+ from pydantic import (
19
+ BaseModel,
20
+ ConfigDict,
21
+ Field,
22
+ TypeAdapter,
23
+ ValidationError,
24
+ field_validator,
25
+ )
18
26
  from typing_extensions import Literal, Self
19
27
 
20
28
  from prefect._internal.schemas.validators import (
@@ -23,32 +31,11 @@ from prefect._internal.schemas.validators import (
23
31
  validate_dump_kwargs,
24
32
  validate_load_kwargs,
25
33
  validate_picklelib,
26
- validate_picklelib_version,
27
34
  )
28
- from prefect.pydantic import HAS_PYDANTIC_V2
29
35
  from prefect.utilities.dispatch import get_dispatch_key, lookup_type, register_base_type
30
36
  from prefect.utilities.importtools import from_qualified_name, to_qualified_name
31
37
  from prefect.utilities.pydantic import custom_pydantic_encoder
32
38
 
33
- if HAS_PYDANTIC_V2:
34
- from pydantic.v1 import (
35
- BaseModel,
36
- Field,
37
- ValidationError,
38
- parse_obj_as,
39
- root_validator,
40
- validator,
41
- )
42
- else:
43
- from pydantic import (
44
- BaseModel,
45
- Field,
46
- ValidationError,
47
- parse_obj_as,
48
- root_validator,
49
- validator,
50
- )
51
-
52
39
  D = TypeVar("D")
53
40
 
54
41
 
@@ -73,7 +60,9 @@ def prefect_json_object_decoder(result: dict):
73
60
  with `prefect_json_object_encoder`
74
61
  """
75
62
  if "__class__" in result:
76
- return parse_obj_as(from_qualified_name(result["__class__"]), result["data"])
63
+ return TypeAdapter(from_qualified_name(result["__class__"])).validate_python(
64
+ result["data"]
65
+ )
77
66
  elif "__exc_type__" in result:
78
67
  return from_qualified_name(result["__exc_type__"])(result["message"])
79
68
  else:
@@ -112,12 +101,12 @@ class Serializer(BaseModel, Generic[D], abc.ABC):
112
101
  def loads(self, blob: bytes) -> D:
113
102
  """Decode the blob of bytes into an object."""
114
103
 
115
- class Config:
116
- extra = "forbid"
104
+ model_config = ConfigDict(extra="forbid")
117
105
 
118
106
  @classmethod
119
- def __dispatch_key__(cls):
120
- return cls.__fields__.get("type").get_default()
107
+ def __dispatch_key__(cls) -> str:
108
+ type_str = cls.model_fields["type"].default
109
+ return type_str if isinstance(type_str, str) else None
121
110
 
122
111
 
123
112
  class PickleSerializer(Serializer):
@@ -133,15 +122,15 @@ class PickleSerializer(Serializer):
133
122
  type: Literal["pickle"] = "pickle"
134
123
 
135
124
  picklelib: str = "cloudpickle"
136
- picklelib_version: str = None
125
+ picklelib_version: Optional[str] = None
137
126
 
138
- @validator("picklelib")
127
+ @field_validator("picklelib")
139
128
  def check_picklelib(cls, value):
140
129
  return validate_picklelib(value)
141
130
 
142
- @root_validator
143
- def check_picklelib_version(cls, values):
144
- return validate_picklelib_version(values)
131
+ # @model_validator(mode="before")
132
+ # def check_picklelib_version(cls, values):
133
+ # return validate_picklelib_version(values)
145
134
 
146
135
  def dumps(self, obj: Any) -> bytes:
147
136
  pickler = from_qualified_name(self.picklelib)
@@ -185,11 +174,11 @@ class JSONSerializer(Serializer):
185
174
  dumps_kwargs: Dict[str, Any] = Field(default_factory=dict)
186
175
  loads_kwargs: Dict[str, Any] = Field(default_factory=dict)
187
176
 
188
- @validator("dumps_kwargs")
177
+ @field_validator("dumps_kwargs")
189
178
  def dumps_kwargs_cannot_contain_default(cls, value):
190
179
  return validate_dump_kwargs(value)
191
180
 
192
- @validator("loads_kwargs")
181
+ @field_validator("loads_kwargs")
193
182
  def loads_kwargs_cannot_contain_object_hook(cls, value):
194
183
  return validate_load_kwargs(value)
195
184
 
@@ -229,11 +218,11 @@ class CompressedSerializer(Serializer):
229
218
  serializer: Serializer
230
219
  compressionlib: str = "lzma"
231
220
 
232
- @validator("serializer", pre=True)
221
+ @field_validator("serializer", mode="before")
233
222
  def validate_serializer(cls, value):
234
223
  return cast_type_names_to_serializers(value)
235
224
 
236
- @validator("compressionlib")
225
+ @field_validator("compressionlib")
237
226
  def check_compressionlib(cls, value):
238
227
  return validate_compressionlib(value)
239
228
 
@@ -1,14 +1,5 @@
1
1
  {
2
2
  "prefect": {
3
- "prefect-agent": {
4
- "type": "prefect-agent",
5
- "documentation_url": "https://docs.prefect.io/latest/concepts/work-pools/#agent-overview",
6
- "display_name": "Prefect Agent",
7
- "logo_url": "https://cdn.sanity.io/images/3ugk85nk/production/c771bb53894c877e169c8db158c5598558b8f175-24x24.svg",
8
- "install_command": "pip install prefect",
9
- "default_base_job_configuration": {},
10
- "description": "Execute flow runs on heterogeneous infrastructure using infrastructure blocks."
11
- },
12
3
  "process": {
13
4
  "default_base_job_configuration": {
14
5
  "job_configuration": {
@@ -806,7 +797,7 @@
806
797
  "image": {
807
798
  "title": "Image",
808
799
  "description": "The image reference of a container image to use for created jobs. If not set, the latest Prefect image will be used.",
809
- "example": "docker.io/prefecthq/prefect:2-latest",
800
+ "example": "docker.io/prefecthq/prefect:3-latest",
810
801
  "type": "string"
811
802
  },
812
803
  "registry_credentials": {
@@ -1040,7 +1031,7 @@
1040
1031
  "image": {
1041
1032
  "title": "Image Name",
1042
1033
  "description": "The image to use for a new Cloud Run Job. If not set, the latest Prefect image will be used. See https://cloud.google.com/run/docs/deploying#images.",
1043
- "example": "docker.io/prefecthq/prefect:2-latest",
1034
+ "example": "docker.io/prefecthq/prefect:3-latest",
1044
1035
  "type": "string"
1045
1036
  },
1046
1037
  "cpu": {
@@ -1211,7 +1202,7 @@
1211
1202
  "image": {
1212
1203
  "title": "Image Name",
1213
1204
  "description": "The image to use for the Cloud Run job. If not provided the default Prefect image will be used.",
1214
- "default": "prefecthq/prefect:2-latest",
1205
+ "default": "prefecthq/prefect:3-latest",
1215
1206
  "type": "string"
1216
1207
  },
1217
1208
  "args": {
@@ -1600,7 +1591,7 @@
1600
1591
  "image": {
1601
1592
  "title": "Image",
1602
1593
  "description": "The image reference of a container image to use for created jobs. If not set, the latest Prefect image will be used.",
1603
- "example": "docker.io/prefecthq/prefect:2-latest",
1594
+ "example": "docker.io/prefecthq/prefect:3-latest",
1604
1595
  "type": "string"
1605
1596
  },
1606
1597
  "service_account_name": {
@@ -1688,4 +1679,4 @@
1688
1679
  "type": "kubernetes"
1689
1680
  }
1690
1681
  }
1691
- }
1682
+ }