prefect-client 2.20.2__py3-none-any.whl → 3.0.0__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 (288) hide show
  1. prefect/__init__.py +74 -110
  2. prefect/_internal/compatibility/deprecated.py +6 -115
  3. prefect/_internal/compatibility/experimental.py +4 -79
  4. prefect/_internal/compatibility/migration.py +166 -0
  5. prefect/_internal/concurrency/__init__.py +2 -2
  6. prefect/_internal/concurrency/api.py +1 -35
  7. prefect/_internal/concurrency/calls.py +0 -6
  8. prefect/_internal/concurrency/cancellation.py +0 -3
  9. prefect/_internal/concurrency/event_loop.py +0 -20
  10. prefect/_internal/concurrency/inspection.py +3 -3
  11. prefect/_internal/concurrency/primitives.py +1 -0
  12. prefect/_internal/concurrency/services.py +23 -0
  13. prefect/_internal/concurrency/threads.py +35 -0
  14. prefect/_internal/concurrency/waiters.py +0 -28
  15. prefect/_internal/integrations.py +7 -0
  16. prefect/_internal/pydantic/__init__.py +0 -45
  17. prefect/_internal/pydantic/annotations/pendulum.py +2 -2
  18. prefect/_internal/pydantic/v1_schema.py +21 -22
  19. prefect/_internal/pydantic/v2_schema.py +0 -2
  20. prefect/_internal/pydantic/v2_validated_func.py +18 -23
  21. prefect/_internal/pytz.py +1 -1
  22. prefect/_internal/retries.py +61 -0
  23. prefect/_internal/schemas/bases.py +45 -177
  24. prefect/_internal/schemas/fields.py +1 -43
  25. prefect/_internal/schemas/validators.py +47 -233
  26. prefect/agent.py +3 -695
  27. prefect/artifacts.py +173 -14
  28. prefect/automations.py +39 -4
  29. prefect/blocks/abstract.py +1 -1
  30. prefect/blocks/core.py +423 -164
  31. prefect/blocks/fields.py +2 -57
  32. prefect/blocks/notifications.py +43 -28
  33. prefect/blocks/redis.py +168 -0
  34. prefect/blocks/system.py +67 -20
  35. prefect/blocks/webhook.py +2 -9
  36. prefect/cache_policies.py +239 -0
  37. prefect/client/__init__.py +4 -0
  38. prefect/client/base.py +33 -27
  39. prefect/client/cloud.py +65 -20
  40. prefect/client/collections.py +1 -1
  41. prefect/client/orchestration.py +667 -440
  42. prefect/client/schemas/actions.py +115 -100
  43. prefect/client/schemas/filters.py +46 -52
  44. prefect/client/schemas/objects.py +228 -178
  45. prefect/client/schemas/responses.py +18 -36
  46. prefect/client/schemas/schedules.py +55 -36
  47. prefect/client/schemas/sorting.py +2 -0
  48. prefect/client/subscriptions.py +8 -7
  49. prefect/client/types/flexible_schedule_list.py +11 -0
  50. prefect/client/utilities.py +9 -6
  51. prefect/concurrency/asyncio.py +60 -11
  52. prefect/concurrency/context.py +24 -0
  53. prefect/concurrency/events.py +2 -2
  54. prefect/concurrency/services.py +46 -16
  55. prefect/concurrency/sync.py +51 -7
  56. prefect/concurrency/v1/asyncio.py +143 -0
  57. prefect/concurrency/v1/context.py +27 -0
  58. prefect/concurrency/v1/events.py +61 -0
  59. prefect/concurrency/v1/services.py +116 -0
  60. prefect/concurrency/v1/sync.py +92 -0
  61. prefect/context.py +246 -149
  62. prefect/deployments/__init__.py +33 -18
  63. prefect/deployments/base.py +10 -15
  64. prefect/deployments/deployments.py +2 -1048
  65. prefect/deployments/flow_runs.py +178 -0
  66. prefect/deployments/runner.py +72 -173
  67. prefect/deployments/schedules.py +31 -25
  68. prefect/deployments/steps/__init__.py +0 -1
  69. prefect/deployments/steps/core.py +7 -0
  70. prefect/deployments/steps/pull.py +15 -21
  71. prefect/deployments/steps/utility.py +2 -1
  72. prefect/docker/__init__.py +20 -0
  73. prefect/docker/docker_image.py +82 -0
  74. prefect/engine.py +15 -2466
  75. prefect/events/actions.py +17 -23
  76. prefect/events/cli/automations.py +20 -7
  77. prefect/events/clients.py +142 -80
  78. prefect/events/filters.py +14 -18
  79. prefect/events/related.py +74 -75
  80. prefect/events/schemas/__init__.py +0 -5
  81. prefect/events/schemas/automations.py +55 -46
  82. prefect/events/schemas/deployment_triggers.py +7 -197
  83. prefect/events/schemas/events.py +46 -65
  84. prefect/events/schemas/labelling.py +10 -14
  85. prefect/events/utilities.py +4 -5
  86. prefect/events/worker.py +23 -8
  87. prefect/exceptions.py +15 -0
  88. prefect/filesystems.py +30 -529
  89. prefect/flow_engine.py +827 -0
  90. prefect/flow_runs.py +379 -7
  91. prefect/flows.py +470 -360
  92. prefect/futures.py +382 -331
  93. prefect/infrastructure/__init__.py +5 -26
  94. prefect/infrastructure/base.py +3 -320
  95. prefect/infrastructure/provisioners/__init__.py +5 -3
  96. prefect/infrastructure/provisioners/cloud_run.py +13 -8
  97. prefect/infrastructure/provisioners/container_instance.py +14 -9
  98. prefect/infrastructure/provisioners/ecs.py +10 -8
  99. prefect/infrastructure/provisioners/modal.py +8 -5
  100. prefect/input/__init__.py +4 -0
  101. prefect/input/actions.py +2 -4
  102. prefect/input/run_input.py +9 -9
  103. prefect/logging/formatters.py +2 -4
  104. prefect/logging/handlers.py +9 -14
  105. prefect/logging/loggers.py +5 -5
  106. prefect/main.py +72 -0
  107. prefect/plugins.py +2 -64
  108. prefect/profiles.toml +16 -2
  109. prefect/records/__init__.py +1 -0
  110. prefect/records/base.py +223 -0
  111. prefect/records/filesystem.py +207 -0
  112. prefect/records/memory.py +178 -0
  113. prefect/records/result_store.py +64 -0
  114. prefect/results.py +577 -504
  115. prefect/runner/runner.py +124 -51
  116. prefect/runner/server.py +32 -34
  117. prefect/runner/storage.py +3 -12
  118. prefect/runner/submit.py +2 -10
  119. prefect/runner/utils.py +2 -2
  120. prefect/runtime/__init__.py +1 -0
  121. prefect/runtime/deployment.py +1 -0
  122. prefect/runtime/flow_run.py +40 -5
  123. prefect/runtime/task_run.py +1 -0
  124. prefect/serializers.py +28 -39
  125. prefect/server/api/collections_data/views/aggregate-worker-metadata.json +5 -14
  126. prefect/settings.py +209 -332
  127. prefect/states.py +160 -63
  128. prefect/task_engine.py +1478 -57
  129. prefect/task_runners.py +383 -287
  130. prefect/task_runs.py +240 -0
  131. prefect/task_worker.py +463 -0
  132. prefect/tasks.py +684 -374
  133. prefect/transactions.py +410 -0
  134. prefect/types/__init__.py +72 -86
  135. prefect/types/entrypoint.py +13 -0
  136. prefect/utilities/annotations.py +4 -3
  137. prefect/utilities/asyncutils.py +227 -148
  138. prefect/utilities/callables.py +138 -48
  139. prefect/utilities/collections.py +134 -86
  140. prefect/utilities/dispatch.py +27 -14
  141. prefect/utilities/dockerutils.py +11 -4
  142. prefect/utilities/engine.py +186 -32
  143. prefect/utilities/filesystem.py +4 -5
  144. prefect/utilities/importtools.py +26 -27
  145. prefect/utilities/pydantic.py +128 -38
  146. prefect/utilities/schema_tools/hydration.py +18 -1
  147. prefect/utilities/schema_tools/validation.py +30 -0
  148. prefect/utilities/services.py +35 -9
  149. prefect/utilities/templating.py +12 -2
  150. prefect/utilities/timeout.py +20 -5
  151. prefect/utilities/urls.py +195 -0
  152. prefect/utilities/visualization.py +1 -0
  153. prefect/variables.py +78 -59
  154. prefect/workers/__init__.py +0 -1
  155. prefect/workers/base.py +237 -244
  156. prefect/workers/block.py +5 -226
  157. prefect/workers/cloud.py +6 -0
  158. prefect/workers/process.py +265 -12
  159. prefect/workers/server.py +29 -11
  160. {prefect_client-2.20.2.dist-info → prefect_client-3.0.0.dist-info}/METADATA +30 -26
  161. prefect_client-3.0.0.dist-info/RECORD +201 -0
  162. {prefect_client-2.20.2.dist-info → prefect_client-3.0.0.dist-info}/WHEEL +1 -1
  163. prefect/_internal/pydantic/_base_model.py +0 -51
  164. prefect/_internal/pydantic/_compat.py +0 -82
  165. prefect/_internal/pydantic/_flags.py +0 -20
  166. prefect/_internal/pydantic/_types.py +0 -8
  167. prefect/_internal/pydantic/utilities/config_dict.py +0 -72
  168. prefect/_internal/pydantic/utilities/field_validator.py +0 -150
  169. prefect/_internal/pydantic/utilities/model_construct.py +0 -56
  170. prefect/_internal/pydantic/utilities/model_copy.py +0 -55
  171. prefect/_internal/pydantic/utilities/model_dump.py +0 -136
  172. prefect/_internal/pydantic/utilities/model_dump_json.py +0 -112
  173. prefect/_internal/pydantic/utilities/model_fields.py +0 -50
  174. prefect/_internal/pydantic/utilities/model_fields_set.py +0 -29
  175. prefect/_internal/pydantic/utilities/model_json_schema.py +0 -82
  176. prefect/_internal/pydantic/utilities/model_rebuild.py +0 -80
  177. prefect/_internal/pydantic/utilities/model_validate.py +0 -75
  178. prefect/_internal/pydantic/utilities/model_validate_json.py +0 -68
  179. prefect/_internal/pydantic/utilities/model_validator.py +0 -87
  180. prefect/_internal/pydantic/utilities/type_adapter.py +0 -71
  181. prefect/_vendor/fastapi/__init__.py +0 -25
  182. prefect/_vendor/fastapi/applications.py +0 -946
  183. prefect/_vendor/fastapi/background.py +0 -3
  184. prefect/_vendor/fastapi/concurrency.py +0 -44
  185. prefect/_vendor/fastapi/datastructures.py +0 -58
  186. prefect/_vendor/fastapi/dependencies/__init__.py +0 -0
  187. prefect/_vendor/fastapi/dependencies/models.py +0 -64
  188. prefect/_vendor/fastapi/dependencies/utils.py +0 -877
  189. prefect/_vendor/fastapi/encoders.py +0 -177
  190. prefect/_vendor/fastapi/exception_handlers.py +0 -40
  191. prefect/_vendor/fastapi/exceptions.py +0 -46
  192. prefect/_vendor/fastapi/logger.py +0 -3
  193. prefect/_vendor/fastapi/middleware/__init__.py +0 -1
  194. prefect/_vendor/fastapi/middleware/asyncexitstack.py +0 -25
  195. prefect/_vendor/fastapi/middleware/cors.py +0 -3
  196. prefect/_vendor/fastapi/middleware/gzip.py +0 -3
  197. prefect/_vendor/fastapi/middleware/httpsredirect.py +0 -3
  198. prefect/_vendor/fastapi/middleware/trustedhost.py +0 -3
  199. prefect/_vendor/fastapi/middleware/wsgi.py +0 -3
  200. prefect/_vendor/fastapi/openapi/__init__.py +0 -0
  201. prefect/_vendor/fastapi/openapi/constants.py +0 -2
  202. prefect/_vendor/fastapi/openapi/docs.py +0 -203
  203. prefect/_vendor/fastapi/openapi/models.py +0 -480
  204. prefect/_vendor/fastapi/openapi/utils.py +0 -485
  205. prefect/_vendor/fastapi/param_functions.py +0 -340
  206. prefect/_vendor/fastapi/params.py +0 -453
  207. prefect/_vendor/fastapi/py.typed +0 -0
  208. prefect/_vendor/fastapi/requests.py +0 -4
  209. prefect/_vendor/fastapi/responses.py +0 -40
  210. prefect/_vendor/fastapi/routing.py +0 -1331
  211. prefect/_vendor/fastapi/security/__init__.py +0 -15
  212. prefect/_vendor/fastapi/security/api_key.py +0 -98
  213. prefect/_vendor/fastapi/security/base.py +0 -6
  214. prefect/_vendor/fastapi/security/http.py +0 -172
  215. prefect/_vendor/fastapi/security/oauth2.py +0 -227
  216. prefect/_vendor/fastapi/security/open_id_connect_url.py +0 -34
  217. prefect/_vendor/fastapi/security/utils.py +0 -10
  218. prefect/_vendor/fastapi/staticfiles.py +0 -1
  219. prefect/_vendor/fastapi/templating.py +0 -3
  220. prefect/_vendor/fastapi/testclient.py +0 -1
  221. prefect/_vendor/fastapi/types.py +0 -3
  222. prefect/_vendor/fastapi/utils.py +0 -235
  223. prefect/_vendor/fastapi/websockets.py +0 -7
  224. prefect/_vendor/starlette/__init__.py +0 -1
  225. prefect/_vendor/starlette/_compat.py +0 -28
  226. prefect/_vendor/starlette/_exception_handler.py +0 -80
  227. prefect/_vendor/starlette/_utils.py +0 -88
  228. prefect/_vendor/starlette/applications.py +0 -261
  229. prefect/_vendor/starlette/authentication.py +0 -159
  230. prefect/_vendor/starlette/background.py +0 -43
  231. prefect/_vendor/starlette/concurrency.py +0 -59
  232. prefect/_vendor/starlette/config.py +0 -151
  233. prefect/_vendor/starlette/convertors.py +0 -87
  234. prefect/_vendor/starlette/datastructures.py +0 -707
  235. prefect/_vendor/starlette/endpoints.py +0 -130
  236. prefect/_vendor/starlette/exceptions.py +0 -60
  237. prefect/_vendor/starlette/formparsers.py +0 -276
  238. prefect/_vendor/starlette/middleware/__init__.py +0 -17
  239. prefect/_vendor/starlette/middleware/authentication.py +0 -52
  240. prefect/_vendor/starlette/middleware/base.py +0 -220
  241. prefect/_vendor/starlette/middleware/cors.py +0 -176
  242. prefect/_vendor/starlette/middleware/errors.py +0 -265
  243. prefect/_vendor/starlette/middleware/exceptions.py +0 -74
  244. prefect/_vendor/starlette/middleware/gzip.py +0 -113
  245. prefect/_vendor/starlette/middleware/httpsredirect.py +0 -19
  246. prefect/_vendor/starlette/middleware/sessions.py +0 -82
  247. prefect/_vendor/starlette/middleware/trustedhost.py +0 -64
  248. prefect/_vendor/starlette/middleware/wsgi.py +0 -147
  249. prefect/_vendor/starlette/py.typed +0 -0
  250. prefect/_vendor/starlette/requests.py +0 -328
  251. prefect/_vendor/starlette/responses.py +0 -347
  252. prefect/_vendor/starlette/routing.py +0 -933
  253. prefect/_vendor/starlette/schemas.py +0 -154
  254. prefect/_vendor/starlette/staticfiles.py +0 -248
  255. prefect/_vendor/starlette/status.py +0 -199
  256. prefect/_vendor/starlette/templating.py +0 -231
  257. prefect/_vendor/starlette/testclient.py +0 -804
  258. prefect/_vendor/starlette/types.py +0 -30
  259. prefect/_vendor/starlette/websockets.py +0 -193
  260. prefect/blocks/kubernetes.py +0 -119
  261. prefect/deprecated/__init__.py +0 -0
  262. prefect/deprecated/data_documents.py +0 -350
  263. prefect/deprecated/packaging/__init__.py +0 -12
  264. prefect/deprecated/packaging/base.py +0 -96
  265. prefect/deprecated/packaging/docker.py +0 -146
  266. prefect/deprecated/packaging/file.py +0 -92
  267. prefect/deprecated/packaging/orion.py +0 -80
  268. prefect/deprecated/packaging/serializers.py +0 -171
  269. prefect/events/instrument.py +0 -135
  270. prefect/infrastructure/container.py +0 -824
  271. prefect/infrastructure/kubernetes.py +0 -920
  272. prefect/infrastructure/process.py +0 -289
  273. prefect/manifests.py +0 -20
  274. prefect/new_flow_engine.py +0 -449
  275. prefect/new_task_engine.py +0 -423
  276. prefect/pydantic/__init__.py +0 -76
  277. prefect/pydantic/main.py +0 -39
  278. prefect/software/__init__.py +0 -2
  279. prefect/software/base.py +0 -50
  280. prefect/software/conda.py +0 -199
  281. prefect/software/pip.py +0 -122
  282. prefect/software/python.py +0 -52
  283. prefect/task_server.py +0 -322
  284. prefect_client-2.20.2.dist-info/RECORD +0 -294
  285. /prefect/{_internal/pydantic/utilities → client/types}/__init__.py +0 -0
  286. /prefect/{_vendor → concurrency/v1}/__init__.py +0 -0
  287. {prefect_client-2.20.2.dist-info → prefect_client-3.0.0.dist-info}/LICENSE +0 -0
  288. {prefect_client-2.20.2.dist-info → prefect_client-3.0.0.dist-info}/top_level.txt +0 -0
@@ -3,29 +3,18 @@ Utilities for creating and working with Prefect REST API schemas.
3
3
  """
4
4
 
5
5
  import datetime
6
- import json
7
6
  import os
8
- from functools import partial
9
- from typing import Any, Dict, Generator, Optional, Set, TypeVar
7
+ from typing import Any, ClassVar, Optional, Set, TypeVar
10
8
  from uuid import UUID, uuid4
11
9
 
12
- import orjson
13
10
  import pendulum
14
- from packaging.version import Version
15
-
16
- from prefect._internal.pydantic import HAS_PYDANTIC_V2
17
-
18
- if HAS_PYDANTIC_V2:
19
- import pydantic.v1 as pydantic
20
- from pydantic.v1 import BaseModel, Field, SecretField
21
- from pydantic.v1.json import custom_pydantic_encoder
22
- else:
23
- import pydantic
24
- from pydantic import BaseModel, Field, SecretField
25
- from pydantic.json import custom_pydantic_encoder
26
-
27
- from prefect._internal.schemas.fields import DateTimeTZ
28
- from prefect._internal.schemas.serializers import orjson_dumps_extra_compatible
11
+ from pydantic import (
12
+ BaseModel,
13
+ ConfigDict,
14
+ Field,
15
+ )
16
+ from pydantic_extra_types.pendulum_dt import DateTime
17
+ from typing_extensions import Self
29
18
 
30
19
  T = TypeVar("T")
31
20
 
@@ -42,39 +31,17 @@ class PrefectBaseModel(BaseModel):
42
31
  subtle unintentional testing errors.
43
32
  """
44
33
 
45
- class Config:
46
- # extra attributes are forbidden in order to raise meaningful errors for
47
- # bad API payloads
48
- # We cannot load this setting through the normal pattern due to circular
49
- # imports; instead just check if its a truthy setting directly
50
- if os.getenv("PREFECT_TEST_MODE", "0").lower() in ["1", "true"]:
51
- extra = "forbid"
52
- else:
53
- extra = "ignore"
54
-
55
- json_encoders = {
56
- # Uses secret fields and strange logic to avoid a circular import error
57
- # for Secret dict in prefect.blocks.fields
58
- SecretField: lambda v: v.dict() if getattr(v, "dict", None) else str(v)
59
- }
60
-
61
- pydantic_version = getattr(pydantic, "__version__", None)
62
- if pydantic_version is not None and Version(pydantic_version) >= Version(
63
- "1.9.2"
64
- ):
65
- copy_on_model_validation = "none"
66
- else:
67
- copy_on_model_validation = False
34
+ _reset_fields: ClassVar[Set[str]] = set()
68
35
 
69
- # Use orjson for serialization
70
- json_loads = orjson.loads
71
- json_dumps = orjson_dumps_extra_compatible
72
-
73
- def _reset_fields(self) -> Set[str]:
74
- """A set of field names that are reset when the PrefectBaseModel is copied.
75
- These fields are also disregarded for equality comparisons.
76
- """
77
- return set()
36
+ model_config = ConfigDict(
37
+ ser_json_timedelta="float",
38
+ defer_build=True,
39
+ extra=(
40
+ "ignore"
41
+ if os.getenv("PREFECT_TEST_MODE", "0").lower() not in ["true", "1"]
42
+ else "forbid"
43
+ ),
44
+ )
78
45
 
79
46
  def __eq__(self, other: Any) -> bool:
80
47
  """Equaltiy operator that ignores the resettable fields of the PrefectBaseModel.
@@ -82,124 +49,47 @@ class PrefectBaseModel(BaseModel):
82
49
  NOTE: this equality operator will only be applied if the PrefectBaseModel is
83
50
  the left-hand operand. This is a limitation of Python.
84
51
  """
85
- copy_dict = self.dict(exclude=self._reset_fields())
52
+ copy_dict = self.model_dump(exclude=self._reset_fields)
86
53
  if isinstance(other, PrefectBaseModel):
87
- return copy_dict == other.dict(exclude=other._reset_fields())
54
+ return copy_dict == other.model_dump(exclude=other._reset_fields)
88
55
  if isinstance(other, BaseModel):
89
- return copy_dict == other.dict()
56
+ return copy_dict == other.model_dump()
90
57
  else:
91
58
  return copy_dict == other
92
59
 
93
- def json(self, *args, include_secrets: bool = False, **kwargs) -> str:
94
- """
95
- Returns a representation of the model as JSON.
96
-
97
- If `include_secrets=True`, then `SecretStr` and `SecretBytes` objects are
98
- fully revealed. Otherwise they are obfuscated.
99
-
100
- """
101
- if include_secrets:
102
- if "encoder" in kwargs:
103
- raise ValueError(
104
- "Alternative encoder provided; can not set encoder for"
105
- " SecretFields."
106
- )
107
- kwargs["encoder"] = partial(
108
- custom_pydantic_encoder,
109
- {SecretField: lambda v: v.get_secret_value() if v else None},
110
- )
111
- return super().json(*args, **kwargs)
112
-
113
- def dict(
114
- self, *args, shallow: bool = False, json_compatible: bool = False, **kwargs
115
- ) -> dict:
116
- """Returns a representation of the model as a Python dictionary.
117
-
118
- For more information on this distinction please see
119
- https://pydantic-docs.helpmanual.io/usage/exporting_models/#dictmodel-and-iteration
120
-
121
-
122
- Args:
123
- shallow (bool, optional): If True (default), nested Pydantic fields
124
- are also coerced to dicts. If false, they are left as Pydantic
125
- models.
126
- json_compatible (bool, optional): if True, objects are converted
127
- into json-compatible representations, similar to calling
128
- `json.loads(self.json())`. Not compatible with shallow=True.
129
-
130
- Returns:
131
- dict
132
- """
133
-
134
- if json_compatible and shallow:
135
- raise ValueError(
136
- "`json_compatible` can only be applied to the entire object."
137
- )
138
-
139
- # return a json-compatible representation of the object
140
- elif json_compatible:
141
- return json.loads(self.json(*args, **kwargs))
142
-
143
- # if shallow wasn't requested, return the standard pydantic behavior
144
- elif not shallow:
145
- return super().dict(*args, **kwargs)
146
-
147
- # if no options were requested, return simple dict transformation
148
- # to apply shallow conversion
149
- elif not args and not kwargs:
150
- return dict(self)
151
-
152
- # if options like include/exclude were provided, perform
153
- # a full dict conversion then overwrite with any shallow
154
- # differences
155
- else:
156
- deep_dict = super().dict(*args, **kwargs)
157
- shallow_dict = dict(self)
158
- for k, v in list(deep_dict.items()):
159
- if isinstance(v, dict) and isinstance(shallow_dict[k], BaseModel):
160
- deep_dict[k] = shallow_dict[k]
161
- return deep_dict
162
-
163
- def copy(
164
- self: T, *, update: Dict = None, reset_fields: bool = False, **kwargs: Any
165
- ) -> T:
166
- """
167
- Duplicate a model.
168
-
169
- Args:
170
- update: values to change/add to the model copy
171
- reset_fields: if True, reset the fields specified in `self._reset_fields`
172
- to their default value on the new model
173
- kwargs: kwargs to pass to `pydantic.BaseModel.copy`
174
-
175
- Returns:
176
- A new copy of the model
177
- """
178
- if reset_fields:
179
- update = update or dict()
180
- for field in self._reset_fields():
181
- update.setdefault(field, self.__fields__[field].get_default())
182
- return super().copy(update=update, **kwargs)
183
-
184
60
  def __rich_repr__(self):
185
61
  # Display all of the fields in the model if they differ from the default value
186
- for name, field in self.__fields__.items():
62
+ for name, field in self.model_fields.items():
187
63
  value = getattr(self, name)
188
64
 
189
65
  # Simplify the display of some common fields
190
- if field.type_ == UUID and value:
66
+ if field.annotation == UUID and value:
191
67
  value = str(value)
192
68
  elif (
193
- isinstance(field.type_, datetime.datetime)
69
+ isinstance(field.annotation, datetime.datetime)
194
70
  and name == "timestamp"
195
71
  and value
196
72
  ):
197
73
  value = pendulum.instance(value).isoformat()
198
- elif isinstance(field.type_, datetime.datetime) and value:
74
+ elif isinstance(field.annotation, datetime.datetime) and value:
199
75
  value = pendulum.instance(value).diff_for_humans()
200
76
 
201
77
  yield name, value, field.get_default()
202
78
 
79
+ def reset_fields(self: Self) -> Self:
80
+ """
81
+ Reset the fields of the model that are in the `_reset_fields` set.
82
+
83
+ Returns:
84
+ PrefectBaseModel: A new instance of the model with the reset fields.
85
+ """
86
+ return self.model_copy(
87
+ update={
88
+ field: self.model_fields[field].get_default(call_default_factory=True)
89
+ for field in self._reset_fields
90
+ }
91
+ )
92
+
203
93
 
204
94
  class IDBaseModel(PrefectBaseModel):
205
95
  """
@@ -208,11 +98,9 @@ class IDBaseModel(PrefectBaseModel):
208
98
  The ID is reset on copy() and not included in equality comparisons.
209
99
  """
210
100
 
101
+ _reset_fields: ClassVar[Set[str]] = {"id"}
211
102
  id: UUID = Field(default_factory=uuid4)
212
103
 
213
- def _reset_fields(self) -> Set[str]:
214
- return super()._reset_fields().union({"id"})
215
-
216
104
 
217
105
  class ObjectBaseModel(IDBaseModel):
218
106
  """
@@ -223,32 +111,12 @@ class ObjectBaseModel(IDBaseModel):
223
111
  equality comparisons.
224
112
  """
225
113
 
226
- class Config:
227
- orm_mode = True
228
-
229
- created: Optional[DateTimeTZ] = Field(default=None, repr=False)
230
- updated: Optional[DateTimeTZ] = Field(default=None, repr=False)
114
+ _reset_fields: ClassVar[Set[str]] = {"id", "created", "updated"}
115
+ model_config = ConfigDict(from_attributes=True)
231
116
 
232
- def _reset_fields(self) -> Set[str]:
233
- return super()._reset_fields().union({"created", "updated"})
117
+ created: Optional[DateTime] = Field(default=None, repr=False)
118
+ updated: Optional[DateTime] = Field(default=None, repr=False)
234
119
 
235
120
 
236
121
  class ActionBaseModel(PrefectBaseModel):
237
- class Config:
238
- extra = "forbid"
239
-
240
- def __iter__(self):
241
- # By default, `pydantic.BaseModel.__iter__` yields from `self.__dict__` directly
242
- # instead of going through `_iter`. We want tor retain our custom logic in
243
- # `_iter` during `dict(model)` calls which is what Pydantic uses for
244
- # `parse_obj(model)`
245
- yield from self._iter(to_dict=True)
246
-
247
- def _iter(self, *args, **kwargs) -> Generator[tuple, None, None]:
248
- # Drop fields that are marked as `ignored` from json and dictionary outputs
249
- exclude = kwargs.pop("exclude", None) or set()
250
- for name, field in self.__fields__.items():
251
- if field.field_info.extra.get("ignored"):
252
- exclude.add(name)
253
-
254
- return super()._iter(*args, **kwargs, exclude=exclude)
122
+ model_config: ConfigDict = ConfigDict(extra="forbid")
@@ -1,49 +1,7 @@
1
- import datetime
2
1
  from typing import Optional
3
2
  from uuid import UUID
4
3
 
5
- import pendulum
6
- from typing_extensions import TypeAlias
7
-
8
- from prefect._internal.pydantic import HAS_PYDANTIC_V2
9
-
10
- if HAS_PYDANTIC_V2:
11
- from pydantic.v1 import BaseModel, Field
12
- else:
13
- from pydantic import BaseModel, Field
14
-
15
-
16
- # Rather than subclassing pendulum.DateTime to add our pydantic-specific validation,
17
- # which will lead to a lot of funky typing issues, we'll just monkeypatch the pydantic
18
- # validators onto the class. Retaining this type alias means that we can still use it
19
- # as we have been in class definitions, also guaranteeing that we'll be applying these
20
- # validators by importing this module.
21
-
22
- DateTimeTZ: TypeAlias = pendulum.DateTime
23
-
24
-
25
- def _datetime_patched_classmethod(function):
26
- if hasattr(DateTimeTZ, function.__name__):
27
- return function
28
- setattr(DateTimeTZ, function.__name__, classmethod(function))
29
- return function
30
-
31
-
32
- @_datetime_patched_classmethod
33
- def __get_validators__(cls):
34
- yield getattr(cls, "validate")
35
-
36
-
37
- @_datetime_patched_classmethod
38
- def validate(cls, v) -> pendulum.DateTime:
39
- if isinstance(v, str):
40
- parsed = pendulum.parse(v)
41
- assert isinstance(parsed, pendulum.DateTime)
42
- return parsed
43
- elif isinstance(v, datetime.datetime):
44
- return pendulum.instance(v)
45
- else:
46
- raise ValueError("Unrecognized datetime.")
4
+ from pydantic import BaseModel, Field
47
5
 
48
6
 
49
7
  class CreatedBy(BaseModel):