prefect-client 2.16.8__py3-none-any.whl → 2.17.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.
- prefect/__init__.py +0 -18
- prefect/_internal/compatibility/deprecated.py +108 -5
- prefect/_internal/compatibility/experimental.py +9 -8
- prefect/_internal/concurrency/api.py +23 -42
- prefect/_internal/concurrency/waiters.py +25 -22
- prefect/_internal/pydantic/__init__.py +16 -3
- prefect/_internal/pydantic/_base_model.py +39 -4
- prefect/_internal/pydantic/_compat.py +69 -452
- prefect/_internal/pydantic/_flags.py +5 -0
- prefect/_internal/pydantic/_types.py +8 -0
- prefect/_internal/pydantic/utilities/__init__.py +0 -0
- prefect/_internal/pydantic/utilities/config_dict.py +72 -0
- prefect/_internal/pydantic/utilities/field_validator.py +135 -0
- prefect/_internal/pydantic/utilities/model_construct.py +56 -0
- prefect/_internal/pydantic/utilities/model_copy.py +55 -0
- prefect/_internal/pydantic/utilities/model_dump.py +136 -0
- prefect/_internal/pydantic/utilities/model_dump_json.py +112 -0
- prefect/_internal/pydantic/utilities/model_fields.py +50 -0
- prefect/_internal/pydantic/utilities/model_fields_set.py +29 -0
- prefect/_internal/pydantic/utilities/model_json_schema.py +82 -0
- prefect/_internal/pydantic/utilities/model_rebuild.py +80 -0
- prefect/_internal/pydantic/utilities/model_validate.py +75 -0
- prefect/_internal/pydantic/utilities/model_validate_json.py +68 -0
- prefect/_internal/pydantic/utilities/model_validator.py +79 -0
- prefect/_internal/pydantic/utilities/type_adapter.py +71 -0
- prefect/_internal/schemas/bases.py +1 -17
- prefect/_internal/schemas/validators.py +425 -4
- prefect/agent.py +1 -1
- prefect/blocks/kubernetes.py +7 -3
- prefect/blocks/notifications.py +18 -18
- prefect/blocks/webhook.py +1 -1
- prefect/client/base.py +7 -0
- prefect/client/cloud.py +1 -1
- prefect/client/orchestration.py +51 -11
- prefect/client/schemas/actions.py +367 -297
- prefect/client/schemas/filters.py +28 -28
- prefect/client/schemas/objects.py +78 -147
- prefect/client/schemas/responses.py +240 -60
- prefect/client/schemas/schedules.py +6 -8
- prefect/concurrency/events.py +2 -2
- prefect/context.py +4 -2
- prefect/deployments/base.py +6 -13
- prefect/deployments/deployments.py +34 -9
- prefect/deployments/runner.py +9 -27
- prefect/deprecated/packaging/base.py +5 -6
- prefect/deprecated/packaging/docker.py +19 -25
- prefect/deprecated/packaging/file.py +10 -5
- prefect/deprecated/packaging/orion.py +9 -4
- prefect/deprecated/packaging/serializers.py +8 -58
- prefect/engine.py +55 -618
- prefect/events/actions.py +16 -1
- prefect/events/clients.py +45 -13
- prefect/events/filters.py +19 -2
- prefect/events/related.py +4 -4
- prefect/events/schemas/automations.py +13 -2
- prefect/events/schemas/deployment_triggers.py +73 -5
- prefect/events/schemas/events.py +1 -1
- prefect/events/utilities.py +12 -4
- prefect/events/worker.py +26 -8
- prefect/exceptions.py +3 -8
- prefect/filesystems.py +7 -7
- prefect/flows.py +7 -3
- prefect/infrastructure/provisioners/ecs.py +1 -0
- prefect/logging/configuration.py +2 -2
- prefect/manifests.py +1 -8
- prefect/profiles.toml +1 -1
- prefect/pydantic/__init__.py +74 -2
- prefect/pydantic/main.py +26 -2
- prefect/serializers.py +6 -31
- prefect/settings.py +72 -26
- prefect/software/python.py +3 -5
- prefect/task_server.py +2 -2
- prefect/utilities/callables.py +1 -1
- prefect/utilities/collections.py +2 -1
- prefect/utilities/dispatch.py +1 -0
- prefect/utilities/engine.py +629 -0
- prefect/utilities/pydantic.py +1 -1
- prefect/utilities/schema_tools/validation.py +2 -2
- prefect/utilities/visualization.py +1 -1
- prefect/variables.py +88 -12
- prefect/workers/base.py +20 -11
- prefect/workers/block.py +4 -8
- prefect/workers/process.py +2 -5
- {prefect_client-2.16.8.dist-info → prefect_client-2.17.0.dist-info}/METADATA +4 -3
- {prefect_client-2.16.8.dist-info → prefect_client-2.17.0.dist-info}/RECORD +88 -72
- prefect/_internal/schemas/transformations.py +0 -106
- {prefect_client-2.16.8.dist-info → prefect_client-2.17.0.dist-info}/LICENSE +0 -0
- {prefect_client-2.16.8.dist-info → prefect_client-2.17.0.dist-info}/WHEEL +0 -0
- {prefect_client-2.16.8.dist-info → prefect_client-2.17.0.dist-info}/top_level.txt +0 -0
@@ -1,464 +1,81 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
HAS_PYDANTIC_V2,
|
7
|
-
USE_PYDANTIC_V2,
|
8
|
-
)
|
9
|
-
from prefect.logging.loggers import get_logger
|
1
|
+
"""
|
2
|
+
Functions within this module check for Pydantic V2 compatibility and provide mechanisms for copying,
|
3
|
+
dumping, and validating models in a way that is agnostic to the underlying Pydantic version.
|
4
|
+
"""
|
5
|
+
import typing
|
10
6
|
|
11
7
|
from ._base_model import BaseModel as PydanticBaseModel
|
8
|
+
from ._base_model import (
|
9
|
+
ConfigDict,
|
10
|
+
Field,
|
11
|
+
FieldInfo,
|
12
|
+
PrivateAttr,
|
13
|
+
SecretStr,
|
14
|
+
ValidationError,
|
15
|
+
)
|
16
|
+
from ._flags import HAS_PYDANTIC_V2, USE_PYDANTIC_V2
|
17
|
+
from .utilities.config_dict import ConfigMixin
|
18
|
+
from .utilities.field_validator import field_validator
|
19
|
+
from .utilities.model_construct import ModelConstructMixin, model_construct
|
20
|
+
from .utilities.model_copy import ModelCopyMixin, model_copy
|
21
|
+
from .utilities.model_dump import ModelDumpMixin, model_dump
|
22
|
+
from .utilities.model_dump_json import ModelDumpJsonMixin, model_dump_json
|
23
|
+
from .utilities.model_fields import ModelFieldMixin
|
24
|
+
from .utilities.model_fields_set import ModelFieldsSetMixin, model_fields_set
|
25
|
+
from .utilities.model_json_schema import ModelJsonSchemaMixin, model_json_schema
|
26
|
+
from .utilities.model_validate import ModelValidateMixin, model_validate
|
27
|
+
from .utilities.model_validate_json import ModelValidateJsonMixin, model_validate_json
|
28
|
+
from .utilities.model_validator import model_validator
|
29
|
+
from .utilities.type_adapter import TypeAdapter, validate_python
|
30
|
+
|
31
|
+
if typing.TYPE_CHECKING:
|
12
32
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
T = TypeVar("T")
|
17
|
-
B = TypeVar("B", bound=PydanticBaseModel)
|
18
|
-
|
19
|
-
if HAS_PYDANTIC_V2:
|
20
|
-
from pydantic import (
|
21
|
-
TypeAdapter as BaseTypeAdapter,
|
22
|
-
)
|
23
|
-
from pydantic import (
|
24
|
-
parse_obj_as, # type: ignore
|
25
|
-
)
|
26
|
-
from pydantic.json_schema import GenerateJsonSchema # type: ignore
|
27
|
-
else:
|
28
|
-
from pydantic import parse_obj_as # type: ignore
|
29
|
-
|
30
|
-
if HAS_PYDANTIC_V2 and USE_PYDANTIC_V2:
|
31
|
-
TypeAdapter = BaseTypeAdapter # type: ignore
|
32
|
-
|
33
|
-
else:
|
34
|
-
|
35
|
-
class TypeAdapter(Generic[T]):
|
36
|
-
def __init__(self, type_: Union[T, Type[T]]) -> None:
|
37
|
-
self.type_ = type_
|
38
|
-
|
39
|
-
def validate_python(
|
40
|
-
self,
|
41
|
-
__object: Any,
|
42
|
-
/,
|
43
|
-
*,
|
44
|
-
strict: Optional[bool] = None,
|
45
|
-
from_attributes: Optional[bool] = None,
|
46
|
-
context: Optional[Dict[str, Any]] = None,
|
47
|
-
) -> Any:
|
48
|
-
return parse_obj_as(self.type_, __object) # type: ignore
|
49
|
-
|
50
|
-
|
51
|
-
# BaseModel methods and definitions
|
52
|
-
|
53
|
-
|
54
|
-
def model_copy(
|
55
|
-
model_instance: PydanticBaseModel,
|
56
|
-
*,
|
57
|
-
update: Optional[Dict[str, Any]] = None,
|
58
|
-
deep: bool = False,
|
59
|
-
) -> PydanticBaseModel:
|
60
|
-
"""Usage docs: https://docs.pydantic.dev/2.7/concepts/serialization/#model_copy
|
61
|
-
|
62
|
-
Returns a copy of the model.
|
63
|
-
|
64
|
-
Args:
|
65
|
-
update: Values to change/add in the new model. Note: the data is not validated
|
66
|
-
before creating the new model. You should trust this data.
|
67
|
-
deep: Set to `True` to make a deep copy of the model.
|
68
|
-
|
69
|
-
Returns:
|
70
|
-
New model instance.
|
71
|
-
"""
|
72
|
-
if not hasattr(model_instance, "copy") and not hasattr(
|
73
|
-
model_instance, "model_copy"
|
74
|
-
):
|
75
|
-
raise TypeError("Expected a Pydantic model instance")
|
76
|
-
|
77
|
-
if HAS_PYDANTIC_V2 and USE_PYDANTIC_V2:
|
78
|
-
return model_instance.model_copy(update=update, deep=deep)
|
79
|
-
|
80
|
-
return model_instance.copy(update=update, deep=deep) # type: ignore
|
81
|
-
|
82
|
-
|
83
|
-
def model_dump_json(
|
84
|
-
model_instance: PydanticBaseModel,
|
85
|
-
*,
|
86
|
-
indent: Optional[int] = None,
|
87
|
-
include: IncEx = None,
|
88
|
-
exclude: IncEx = None,
|
89
|
-
by_alias: bool = False,
|
90
|
-
exclude_unset: bool = False,
|
91
|
-
exclude_defaults: bool = False,
|
92
|
-
exclude_none: bool = False,
|
93
|
-
round_trip: bool = False,
|
94
|
-
warnings: bool = True,
|
95
|
-
) -> str:
|
96
|
-
"""
|
97
|
-
Generate a JSON representation of the model, optionally specifying which fields to include or exclude.
|
98
|
-
|
99
|
-
Args:
|
100
|
-
indent: If provided, the number of spaces to indent the JSON output.
|
101
|
-
include: A list of fields to include in the output.
|
102
|
-
exclude: A list of fields to exclude from the output.
|
103
|
-
by_alias: Whether to use the field's alias in the dictionary key if defined.
|
104
|
-
exclude_unset: Whether to exclude fields that have not been explicitly set.
|
105
|
-
exclude_defaults: Whether to exclude fields that are set to their default value.
|
106
|
-
exclude_none: Whether to exclude fields that have a value of `None`.
|
107
|
-
round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T].
|
108
|
-
warnings: Whether to log warnings when invalid fields are encountered.
|
109
|
-
|
110
|
-
Returns:
|
111
|
-
A JSON representation of the model.
|
112
|
-
"""
|
113
|
-
if not hasattr(model_instance, "json") and not hasattr(
|
114
|
-
model_instance, "model_dump_json"
|
115
|
-
):
|
116
|
-
raise TypeError("Expected a Pydantic model instance")
|
117
|
-
|
118
|
-
if HAS_PYDANTIC_V2 and USE_PYDANTIC_V2:
|
119
|
-
return model_instance.model_dump_json(
|
120
|
-
indent=indent,
|
121
|
-
include=include,
|
122
|
-
exclude=exclude,
|
123
|
-
by_alias=by_alias,
|
124
|
-
exclude_unset=exclude_unset,
|
125
|
-
exclude_defaults=exclude_defaults,
|
126
|
-
exclude_none=exclude_none,
|
127
|
-
round_trip=round_trip,
|
128
|
-
warnings=warnings,
|
129
|
-
)
|
130
|
-
|
131
|
-
return model_instance.json( # type: ignore
|
132
|
-
include=include,
|
133
|
-
exclude=exclude,
|
134
|
-
by_alias=by_alias,
|
135
|
-
exclude_unset=exclude_unset,
|
136
|
-
exclude_defaults=exclude_defaults,
|
137
|
-
exclude_none=exclude_none,
|
138
|
-
)
|
139
|
-
|
140
|
-
|
141
|
-
def model_dump(
|
142
|
-
model_instance: PydanticBaseModel,
|
143
|
-
*,
|
144
|
-
mode: Union[Literal["json", "python"], str] = "python",
|
145
|
-
include: IncEx = None,
|
146
|
-
exclude: IncEx = None,
|
147
|
-
by_alias: bool = False,
|
148
|
-
exclude_unset: bool = False,
|
149
|
-
exclude_defaults: bool = False,
|
150
|
-
exclude_none: bool = False,
|
151
|
-
round_trip: bool = False,
|
152
|
-
warnings: bool = True,
|
153
|
-
) -> Dict[str, Any]:
|
154
|
-
"""
|
155
|
-
Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.
|
156
|
-
|
157
|
-
Args:
|
158
|
-
mode: The mode in which `to_python` should run.
|
159
|
-
If mode is 'json', the output will only contain JSON serializable types.
|
160
|
-
If mode is 'python', the output may contain non-JSON-serializable Python objects.
|
161
|
-
include: A list of fields to include in the output.
|
162
|
-
exclude: A list of fields to exclude from the output.
|
163
|
-
by_alias: Whether to use the field's alias in the dictionary key if defined.
|
164
|
-
exclude_unset: Whether to exclude fields that have not been explicitly set.
|
165
|
-
exclude_defaults: Whether to exclude fields that are set to their default value.
|
166
|
-
exclude_none: Whether to exclude fields that have a value of `None`.
|
167
|
-
round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T].
|
168
|
-
warnings: Whether to log warnings when invalid fields are encountered.
|
169
|
-
|
170
|
-
Returns:
|
171
|
-
A dictionary representation of the model.
|
172
|
-
"""
|
173
|
-
if not hasattr(model_instance, "dict") and not hasattr(
|
174
|
-
model_instance, "model_dump"
|
175
|
-
):
|
176
|
-
raise TypeError("Expected a Pydantic model instance")
|
177
|
-
|
178
|
-
if HAS_PYDANTIC_V2 and USE_PYDANTIC_V2:
|
179
|
-
return model_instance.model_dump(
|
180
|
-
mode=mode,
|
181
|
-
include=include,
|
182
|
-
exclude=exclude,
|
183
|
-
by_alias=by_alias,
|
184
|
-
exclude_unset=exclude_unset,
|
185
|
-
exclude_defaults=exclude_defaults,
|
186
|
-
exclude_none=exclude_none,
|
187
|
-
round_trip=round_trip,
|
188
|
-
warnings=warnings,
|
189
|
-
)
|
190
|
-
|
191
|
-
return getattr(model_instance, "dict")(
|
192
|
-
include=include,
|
193
|
-
exclude=exclude,
|
194
|
-
by_alias=by_alias,
|
195
|
-
exclude_unset=exclude_unset,
|
196
|
-
exclude_defaults=exclude_defaults,
|
197
|
-
exclude_none=exclude_none,
|
198
|
-
)
|
199
|
-
|
200
|
-
|
201
|
-
DEFAULT_REF_TEMPLATE = "#/$defs/{model}"
|
202
|
-
JsonSchemaMode = Literal["validation", "serialization"]
|
203
|
-
|
204
|
-
|
205
|
-
def model_json_schema(
|
206
|
-
model: Type[PydanticBaseModel],
|
207
|
-
*,
|
208
|
-
by_alias: bool = True,
|
209
|
-
ref_template: str = DEFAULT_REF_TEMPLATE,
|
210
|
-
schema_generator: Any = None,
|
211
|
-
mode: JsonSchemaMode = "validation",
|
212
|
-
) -> Dict[str, Any]:
|
213
|
-
"""
|
214
|
-
Generates a JSON schema for a model class.
|
215
|
-
|
216
|
-
Parameters
|
217
|
-
----------
|
218
|
-
by_alias : bool, optional
|
219
|
-
Whether to use attribute aliases or not, by default True
|
220
|
-
ref_template : str, optional
|
221
|
-
The reference template, by default DEFAULT_REF_TEMPLATE
|
222
|
-
schema_generator : type[GenerateEmptySchemaForUserClasses], optional
|
223
|
-
To override the logic used to generate the JSON schema, as a subclass of GenerateEmptySchemaForUserClasses with your desired modifications, by default GenerateEmptySchemaForUserClasses
|
224
|
-
mode : JsonSchemaMode, optional
|
225
|
-
The mode in which to generate the schema, by default 'validation'
|
226
|
-
|
227
|
-
Returns
|
228
|
-
-------
|
229
|
-
dict[str, Any]
|
230
|
-
The JSON schema for the given model class.
|
231
|
-
"""
|
232
|
-
if not hasattr(model, "schema") and not hasattr(model, "model_json_schema"):
|
233
|
-
raise TypeError("Expected a Pydantic model type")
|
234
|
-
|
235
|
-
if HAS_PYDANTIC_V2 and USE_PYDANTIC_V2:
|
236
|
-
schema_generator = GenerateJsonSchema # type: ignore
|
237
|
-
return model.model_json_schema(
|
238
|
-
by_alias=by_alias,
|
239
|
-
ref_template=ref_template,
|
240
|
-
schema_generator=schema_generator,
|
241
|
-
mode=mode,
|
242
|
-
)
|
243
|
-
|
244
|
-
return model.schema( # type: ignore
|
245
|
-
by_alias=by_alias,
|
246
|
-
ref_template=ref_template,
|
247
|
-
)
|
248
|
-
|
249
|
-
|
250
|
-
def model_validate(
|
251
|
-
model: Type[B],
|
252
|
-
obj: Any,
|
253
|
-
*,
|
254
|
-
strict: Optional[bool] = False,
|
255
|
-
from_attributes: Optional[bool] = False,
|
256
|
-
context: Optional[Dict[str, Any]] = None,
|
257
|
-
) -> B:
|
258
|
-
"""Validate a pydantic model instance.
|
259
|
-
|
260
|
-
Args:
|
261
|
-
obj: The object to validate.
|
262
|
-
strict: Whether to enforce types strictly.
|
263
|
-
from_attributes: Whether to extract data from object attributes.
|
264
|
-
context: Additional context to pass to the validator.
|
265
|
-
|
266
|
-
Raises:
|
267
|
-
ValidationError: If the object could not be validated.
|
268
|
-
|
269
|
-
Returns:
|
270
|
-
The validated model instance.
|
271
|
-
"""
|
272
|
-
if not hasattr(model, "parse_obj") and not hasattr(model, "model_validate"):
|
273
|
-
raise TypeError("Expected a Pydantic model type")
|
274
|
-
|
275
|
-
if HAS_PYDANTIC_V2 and USE_PYDANTIC_V2:
|
276
|
-
return model.model_validate(
|
277
|
-
obj=obj,
|
278
|
-
strict=strict,
|
279
|
-
from_attributes=from_attributes,
|
280
|
-
context=context,
|
281
|
-
)
|
282
|
-
|
283
|
-
return getattr(model, "parse_obj")(obj)
|
284
|
-
|
285
|
-
|
286
|
-
def model_validate_json(
|
287
|
-
model: Type[B],
|
288
|
-
json_data: Union[str, bytes, bytearray],
|
289
|
-
*,
|
290
|
-
strict: Optional[bool] = False,
|
291
|
-
context: Optional[Dict[str, Any]] = None,
|
292
|
-
) -> B:
|
293
|
-
"""Validate the given JSON data against the Pydantic model.
|
294
|
-
|
295
|
-
Args:
|
296
|
-
json_data: The JSON data to validate.
|
297
|
-
strict: Whether to enforce types strictly.
|
298
|
-
context: Extra variables to pass to the validator.
|
299
|
-
|
300
|
-
Returns:
|
301
|
-
The validated Pydantic model.
|
302
|
-
|
303
|
-
Raises:
|
304
|
-
ValueError: If `json_data` is not a JSON string.
|
305
|
-
"""
|
306
|
-
if not hasattr(model, "parse_raw") and not hasattr(model, "model_validate_json"):
|
307
|
-
raise TypeError("Expected a Pydantic model type")
|
308
|
-
|
309
|
-
if HAS_PYDANTIC_V2 and USE_PYDANTIC_V2:
|
310
|
-
return model.model_validate_json(
|
311
|
-
json_data=json_data,
|
312
|
-
strict=strict,
|
313
|
-
context=context,
|
314
|
-
)
|
315
|
-
|
316
|
-
return getattr(model, "parse_raw")(json_data)
|
317
|
-
|
33
|
+
class BaseModel(PydanticBaseModel): # type: ignore
|
34
|
+
pass
|
318
35
|
|
319
|
-
|
36
|
+
elif HAS_PYDANTIC_V2 and USE_PYDANTIC_V2:
|
320
37
|
# In this case, there's no functionality to add, so we just alias the Pydantic v2 BaseModel
|
321
38
|
class BaseModel(PydanticBaseModel): # type: ignore
|
322
39
|
pass
|
323
40
|
|
324
41
|
else:
|
325
42
|
# In this case, we're working with a Pydantic v1 model, so we need to add Pydantic v2 functionality
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
mode=mode,
|
343
|
-
include=include,
|
344
|
-
exclude=exclude,
|
345
|
-
by_alias=by_alias,
|
346
|
-
exclude_unset=exclude_unset,
|
347
|
-
exclude_defaults=exclude_defaults,
|
348
|
-
exclude_none=exclude_none,
|
349
|
-
round_trip=round_trip,
|
350
|
-
warnings=warnings,
|
351
|
-
)
|
352
|
-
|
353
|
-
def model_dump_json(
|
354
|
-
self,
|
355
|
-
*,
|
356
|
-
indent: Optional[int] = None,
|
357
|
-
include: Optional[IncEx] = None,
|
358
|
-
exclude: Optional[IncEx] = None,
|
359
|
-
by_alias: bool = False,
|
360
|
-
exclude_unset: bool = False,
|
361
|
-
exclude_defaults: bool = False,
|
362
|
-
exclude_none: bool = False,
|
363
|
-
round_trip: bool = False,
|
364
|
-
warnings: bool = True,
|
365
|
-
) -> str:
|
366
|
-
return model_dump_json(
|
367
|
-
model_instance=self,
|
368
|
-
indent=indent,
|
369
|
-
include=include,
|
370
|
-
exclude=exclude,
|
371
|
-
by_alias=by_alias,
|
372
|
-
exclude_unset=exclude_unset,
|
373
|
-
exclude_defaults=exclude_defaults,
|
374
|
-
exclude_none=exclude_none,
|
375
|
-
round_trip=round_trip,
|
376
|
-
warnings=warnings,
|
377
|
-
)
|
378
|
-
|
379
|
-
def model_copy(
|
380
|
-
self: "Self",
|
381
|
-
*,
|
382
|
-
update: Optional[Dict[str, Any]] = None,
|
383
|
-
deep: bool = False,
|
384
|
-
) -> "Self":
|
385
|
-
return super().model_copy(update=update, deep=deep)
|
386
|
-
|
387
|
-
@classmethod
|
388
|
-
def model_json_schema(
|
389
|
-
cls,
|
390
|
-
by_alias: bool = True,
|
391
|
-
ref_template: str = DEFAULT_REF_TEMPLATE,
|
392
|
-
schema_generator: Any = None,
|
393
|
-
mode: JsonSchemaMode = "validation",
|
394
|
-
) -> Dict[str, Any]:
|
395
|
-
return model_json_schema(
|
396
|
-
cls,
|
397
|
-
by_alias=by_alias,
|
398
|
-
ref_template=ref_template,
|
399
|
-
schema_generator=schema_generator,
|
400
|
-
mode=mode,
|
401
|
-
)
|
402
|
-
|
403
|
-
@classmethod
|
404
|
-
def model_validate(
|
405
|
-
cls: Type["Self"],
|
406
|
-
obj: Any,
|
407
|
-
*,
|
408
|
-
strict: Optional[bool] = False,
|
409
|
-
from_attributes: Optional[bool] = False,
|
410
|
-
context: Optional[Dict[str, Any]] = None,
|
411
|
-
) -> "Self":
|
412
|
-
return model_validate(
|
413
|
-
cls,
|
414
|
-
obj,
|
415
|
-
strict=strict,
|
416
|
-
from_attributes=from_attributes,
|
417
|
-
context=context,
|
418
|
-
)
|
419
|
-
|
420
|
-
@classmethod
|
421
|
-
def model_validate_json(
|
422
|
-
cls: Type["Self"],
|
423
|
-
json_data: Union[str, bytes, bytearray],
|
424
|
-
*,
|
425
|
-
strict: Optional[bool] = False,
|
426
|
-
context: Optional[Dict[str, Any]] = None,
|
427
|
-
) -> "Self":
|
428
|
-
return model_validate_json(
|
429
|
-
cls,
|
430
|
-
json_data,
|
431
|
-
strict=strict,
|
432
|
-
context=context,
|
433
|
-
)
|
434
|
-
|
435
|
-
|
436
|
-
# TypeAdapter methods and definitions
|
437
|
-
|
438
|
-
|
439
|
-
def validate_python(
|
440
|
-
type_: Union[T, Type[T]],
|
441
|
-
__object: Any,
|
442
|
-
/,
|
443
|
-
*,
|
444
|
-
strict: Optional[bool] = None,
|
445
|
-
from_attributes: Optional[bool] = None,
|
446
|
-
context: Optional[Dict[str, Any]] = None,
|
447
|
-
) -> T:
|
448
|
-
"""Validate a Python object against the model.
|
449
|
-
|
450
|
-
Args:
|
451
|
-
type_: The type to validate against.
|
452
|
-
__object: The Python object to validate against the model.
|
453
|
-
strict: Whether to strictly check types.
|
454
|
-
from_attributes: Whether to extract data from object attributes.
|
455
|
-
context: Additional context to pass to the validator.
|
43
|
+
# TODO: Find a smarter way of attaching these methods so that they don't need to be redefined
|
44
|
+
|
45
|
+
class BaseModel(
|
46
|
+
ModelConstructMixin,
|
47
|
+
ModelCopyMixin,
|
48
|
+
ModelDumpMixin,
|
49
|
+
ModelDumpJsonMixin,
|
50
|
+
ModelJsonSchemaMixin,
|
51
|
+
ModelValidateMixin,
|
52
|
+
ModelValidateJsonMixin,
|
53
|
+
ModelFieldMixin,
|
54
|
+
ConfigMixin,
|
55
|
+
ModelFieldsSetMixin,
|
56
|
+
PydanticBaseModel,
|
57
|
+
):
|
58
|
+
pass
|
456
59
|
|
457
|
-
!!! note
|
458
|
-
When using `TypeAdapter` with a Pydantic `dataclass`, the use of the `from_attributes`
|
459
|
-
argument is not supported.
|
460
60
|
|
461
|
-
|
462
|
-
|
463
|
-
""
|
464
|
-
|
61
|
+
__all__ = [
|
62
|
+
"model_construct",
|
63
|
+
"model_copy",
|
64
|
+
"model_dump",
|
65
|
+
"model_dump_json",
|
66
|
+
"model_json_schema",
|
67
|
+
"model_validate",
|
68
|
+
"model_validate_json",
|
69
|
+
"model_fields_set",
|
70
|
+
"TypeAdapter",
|
71
|
+
"validate_python",
|
72
|
+
"BaseModel",
|
73
|
+
"Field",
|
74
|
+
"FieldInfo",
|
75
|
+
"field_validator",
|
76
|
+
"model_validator",
|
77
|
+
"PrivateAttr",
|
78
|
+
"SecretStr",
|
79
|
+
"ConfigDict",
|
80
|
+
"ValidationError",
|
81
|
+
]
|
@@ -1,3 +1,6 @@
|
|
1
|
+
"""
|
2
|
+
This file defines flags that determine whether Pydantic V2 is available and whether its features should be used.
|
3
|
+
"""
|
1
4
|
import os
|
2
5
|
|
3
6
|
# Retrieve current version of Pydantic installed in environment
|
@@ -11,5 +14,7 @@ USE_PYDANTIC_V2 = os.environ.get(
|
|
11
14
|
"PREFECT_EXPERIMENTAL_ENABLE_PYDANTIC_V2_INTERNALS", False
|
12
15
|
) in {"1", "true", "True"}
|
13
16
|
|
17
|
+
USE_V2_MODELS = HAS_PYDANTIC_V2 and USE_PYDANTIC_V2
|
18
|
+
|
14
19
|
# Set to True if Pydantic v2 is present but not enabled, indicating deprecation warnings may occur.
|
15
20
|
EXPECT_DEPRECATION_WARNINGS = HAS_PYDANTIC_V2 and not USE_PYDANTIC_V2
|
@@ -0,0 +1,8 @@
|
|
1
|
+
from typing import Any, Dict, Literal, Set, Union
|
2
|
+
|
3
|
+
from typing_extensions import TypeAlias
|
4
|
+
|
5
|
+
IncEx: TypeAlias = "Union[Set[int], Set[str], Dict[int, Any], Dict[str, Any], None]"
|
6
|
+
|
7
|
+
DEFAULT_REF_TEMPLATE = "#/$defs/{model}"
|
8
|
+
JsonSchemaMode = Literal["validation", "serialization"]
|
File without changes
|
@@ -0,0 +1,72 @@
|
|
1
|
+
import typing
|
2
|
+
|
3
|
+
from prefect._internal.pydantic._base_model import BaseModel, ConfigDict
|
4
|
+
from prefect._internal.pydantic._flags import HAS_PYDANTIC_V2, USE_PYDANTIC_V2
|
5
|
+
|
6
|
+
if HAS_PYDANTIC_V2:
|
7
|
+
from pydantic.v1.main import ModelMetaclass as PydanticModelMetaclass
|
8
|
+
else:
|
9
|
+
from pydantic.main import ModelMetaclass as PydanticModelMetaclass
|
10
|
+
|
11
|
+
|
12
|
+
if USE_PYDANTIC_V2:
|
13
|
+
|
14
|
+
class ConfigMixin(BaseModel): # type: ignore
|
15
|
+
pass
|
16
|
+
|
17
|
+
else:
|
18
|
+
T = typing.TypeVar("T")
|
19
|
+
|
20
|
+
CONFIG_V1_V2_KEYS: typing.Dict[str, str] = {
|
21
|
+
"allow_population_by_field_name": "populate_by_name",
|
22
|
+
"anystr_lower": "str_to_lower",
|
23
|
+
"anystr_strip_whitespace": "str_strip_whitespace",
|
24
|
+
"anystr_upper": "str_to_upper",
|
25
|
+
"keep_untouched": "ignored_types",
|
26
|
+
"max_anystr_length": "str_max_length",
|
27
|
+
"min_anystr_length": "str_min_length",
|
28
|
+
"orm_mode": "from_attributes",
|
29
|
+
"schema_extra": "json_schema_extra",
|
30
|
+
"validate_all": "validate_default",
|
31
|
+
"copy_on_model_validation": "revalidate_instances",
|
32
|
+
}
|
33
|
+
|
34
|
+
CONFIG_V2_V1_KEYS: typing.Dict[str, str] = {
|
35
|
+
v: k for k, v in CONFIG_V1_V2_KEYS.items()
|
36
|
+
}
|
37
|
+
|
38
|
+
def _convert_v2_config_to_v1_config(
|
39
|
+
config_dict: typing.Union[ConfigDict, typing.Dict[str, typing.Any]],
|
40
|
+
) -> type:
|
41
|
+
deprecated_renamed_keys = CONFIG_V2_V1_KEYS.keys() & config_dict.keys()
|
42
|
+
output: typing.Dict[str, typing.Any] = {}
|
43
|
+
for k in sorted(deprecated_renamed_keys):
|
44
|
+
if CONFIG_V2_V1_KEYS[k] == "copy_on_model_validation":
|
45
|
+
value = config_dict.get(k)
|
46
|
+
if value == "never":
|
47
|
+
output[CONFIG_V2_V1_KEYS[k]] = "none"
|
48
|
+
if value == "always":
|
49
|
+
output[CONFIG_V2_V1_KEYS[k]] = "deep"
|
50
|
+
if value == "subclass-instances":
|
51
|
+
output[CONFIG_V2_V1_KEYS[k]] = "deep"
|
52
|
+
else:
|
53
|
+
output[CONFIG_V2_V1_KEYS[k]] = config_dict.get(k)
|
54
|
+
return type("Config", (), output)
|
55
|
+
|
56
|
+
class ConfigMeta(PydanticModelMetaclass): # type: ignore
|
57
|
+
def __new__( # type: ignore
|
58
|
+
cls,
|
59
|
+
name: str,
|
60
|
+
bases: typing.Any,
|
61
|
+
namespace: typing.Dict[str, typing.Any],
|
62
|
+
**kwargs: typing.Any,
|
63
|
+
): # type: ignore
|
64
|
+
if model_config := namespace.get("model_config"):
|
65
|
+
namespace["Config"] = _convert_v2_config_to_v1_config(model_config)
|
66
|
+
return super().__new__(cls, name, bases, namespace, **kwargs) # type: ignore
|
67
|
+
|
68
|
+
class ConfigMixin(BaseModel, metaclass=ConfigMeta):
|
69
|
+
model_config: typing.ClassVar[ConfigDict]
|
70
|
+
|
71
|
+
|
72
|
+
__all__ = ["ConfigMixin"]
|