prefect-client 2.16.7__py3-none-any.whl → 2.16.9__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 (62) hide show
  1. prefect/_internal/compatibility/experimental.py +9 -8
  2. prefect/_internal/concurrency/api.py +23 -42
  3. prefect/_internal/concurrency/waiters.py +25 -22
  4. prefect/_internal/pydantic/__init__.py +12 -3
  5. prefect/_internal/pydantic/_base_model.py +7 -4
  6. prefect/_internal/pydantic/_compat.py +39 -453
  7. prefect/_internal/pydantic/_flags.py +2 -0
  8. prefect/_internal/pydantic/_types.py +8 -0
  9. prefect/_internal/pydantic/utilities/__init__.py +0 -0
  10. prefect/_internal/pydantic/utilities/model_construct.py +56 -0
  11. prefect/_internal/pydantic/utilities/model_copy.py +55 -0
  12. prefect/_internal/pydantic/utilities/model_dump.py +136 -0
  13. prefect/_internal/pydantic/utilities/model_dump_json.py +112 -0
  14. prefect/_internal/pydantic/utilities/model_fields.py +50 -0
  15. prefect/_internal/pydantic/utilities/model_json_schema.py +82 -0
  16. prefect/_internal/pydantic/utilities/model_rebuild.py +80 -0
  17. prefect/_internal/pydantic/utilities/model_validate.py +75 -0
  18. prefect/_internal/pydantic/utilities/model_validate_json.py +68 -0
  19. prefect/_internal/pydantic/utilities/type_adapter.py +71 -0
  20. prefect/_internal/schemas/bases.py +1 -17
  21. prefect/_internal/schemas/validators.py +425 -4
  22. prefect/blocks/kubernetes.py +7 -3
  23. prefect/client/cloud.py +1 -1
  24. prefect/client/orchestration.py +8 -8
  25. prefect/client/schemas/actions.py +348 -285
  26. prefect/client/schemas/objects.py +47 -126
  27. prefect/client/schemas/responses.py +231 -57
  28. prefect/concurrency/events.py +2 -2
  29. prefect/context.py +2 -1
  30. prefect/deployments/base.py +4 -3
  31. prefect/deployments/runner.py +7 -25
  32. prefect/deprecated/packaging/base.py +5 -6
  33. prefect/deprecated/packaging/docker.py +19 -25
  34. prefect/deprecated/packaging/file.py +10 -5
  35. prefect/deprecated/packaging/orion.py +9 -4
  36. prefect/deprecated/packaging/serializers.py +8 -58
  37. prefect/engine.py +23 -22
  38. prefect/events/actions.py +16 -1
  39. prefect/events/related.py +4 -4
  40. prefect/events/schemas/automations.py +13 -2
  41. prefect/events/schemas/deployment_triggers.py +73 -5
  42. prefect/events/schemas/events.py +1 -1
  43. prefect/flows.py +3 -0
  44. prefect/infrastructure/provisioners/ecs.py +1 -0
  45. prefect/logging/configuration.py +2 -2
  46. prefect/pydantic/__init__.py +48 -2
  47. prefect/pydantic/main.py +2 -2
  48. prefect/serializers.py +6 -31
  49. prefect/settings.py +40 -17
  50. prefect/software/python.py +3 -5
  51. prefect/utilities/callables.py +1 -1
  52. prefect/utilities/collections.py +2 -1
  53. prefect/utilities/schema_tools/validation.py +2 -2
  54. prefect/workers/base.py +19 -10
  55. prefect/workers/block.py +3 -7
  56. prefect/workers/process.py +2 -5
  57. {prefect_client-2.16.7.dist-info → prefect_client-2.16.9.dist-info}/METADATA +3 -2
  58. {prefect_client-2.16.7.dist-info → prefect_client-2.16.9.dist-info}/RECORD +61 -50
  59. prefect/_internal/schemas/transformations.py +0 -106
  60. {prefect_client-2.16.7.dist-info → prefect_client-2.16.9.dist-info}/LICENSE +0 -0
  61. {prefect_client-2.16.7.dist-info → prefect_client-2.16.9.dist-info}/WHEEL +0 -0
  62. {prefect_client-2.16.7.dist-info → prefect_client-2.16.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,136 @@
1
+ import typing
2
+ import warnings as python_warnings
3
+
4
+ from pydantic_core import from_json
5
+ from typing_extensions import Self
6
+
7
+ from prefect._internal.pydantic._base_model import BaseModel
8
+ from prefect._internal.pydantic._flags import USE_V2_MODELS
9
+
10
+ if typing.TYPE_CHECKING:
11
+ from prefect._internal.pydantic._types import IncEx
12
+
13
+ T = typing.TypeVar("T", bound="BaseModel")
14
+
15
+
16
+ def model_dump( # type: ignore[no-redef]
17
+ model_instance: "BaseModel",
18
+ *,
19
+ mode: typing.Union[typing.Literal["json", "python"], str] = "python",
20
+ include: "IncEx" = None,
21
+ exclude: "IncEx" = None,
22
+ by_alias: bool = False,
23
+ exclude_unset: bool = False,
24
+ exclude_defaults: bool = False,
25
+ exclude_none: bool = False,
26
+ round_trip: bool = False,
27
+ warnings: bool = True,
28
+ ) -> typing.Dict[str, typing.Any]:
29
+ """
30
+ Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.
31
+
32
+ Args:
33
+ mode: The mode in which `to_python` should run.
34
+ If mode is 'json', the output will only contain JSON serializable types.
35
+ If mode is 'python', the output may contain non-JSON-serializable Python objects.
36
+ include: A set of fields to include in the output.
37
+ exclude: A set of fields to exclude from the output.
38
+ context: Additional context to pass to the serializer.
39
+ by_alias: Whether to use the field's alias in the dictionary key if defined.
40
+ exclude_unset: Whether to exclude fields that have not been explicitly set.
41
+ exclude_defaults: Whether to exclude fields that are set to their default value.
42
+ exclude_none: Whether to exclude fields that have a value of `None`.
43
+ round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T].
44
+ warnings: Whether to log warnings when invalid fields are encountered.
45
+ serialize_as_any: Whether to serialize fields with duck-typing serialization behavior.
46
+
47
+ Returns:
48
+ A dictionary representation of the model.
49
+ """
50
+ if USE_V2_MODELS:
51
+ return model_instance.model_dump(
52
+ mode=mode,
53
+ include=include,
54
+ exclude=exclude,
55
+ by_alias=by_alias,
56
+ exclude_unset=exclude_unset,
57
+ exclude_defaults=exclude_defaults,
58
+ exclude_none=exclude_none,
59
+ round_trip=round_trip,
60
+ warnings=warnings,
61
+ )
62
+ else:
63
+ if mode == "json":
64
+ with python_warnings.catch_warnings():
65
+ python_warnings.simplefilter("ignore")
66
+ return from_json(
67
+ model_instance.json(
68
+ include=include,
69
+ exclude=exclude,
70
+ by_alias=by_alias,
71
+ exclude_unset=exclude_unset,
72
+ exclude_defaults=exclude_defaults,
73
+ exclude_none=exclude_none,
74
+ )
75
+ )
76
+
77
+ return getattr(model_instance, "dict")(
78
+ include=include,
79
+ exclude=exclude,
80
+ by_alias=by_alias,
81
+ exclude_unset=exclude_unset,
82
+ exclude_defaults=exclude_defaults,
83
+ exclude_none=exclude_none,
84
+ )
85
+
86
+
87
+ class ModelDumpMixin(BaseModel):
88
+ def model_dump(
89
+ self: "Self",
90
+ *,
91
+ mode: typing.Union[typing.Literal["json", "python"], str] = "python",
92
+ include: "IncEx" = None,
93
+ exclude: "IncEx" = None,
94
+ by_alias: bool = False,
95
+ exclude_unset: bool = False,
96
+ exclude_defaults: bool = False,
97
+ exclude_none: bool = False,
98
+ round_trip: bool = False,
99
+ warnings: bool = True,
100
+ ) -> typing.Dict[str, typing.Any]:
101
+ """
102
+ Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.
103
+
104
+ Args:
105
+ mode: The mode in which `to_python` should run.
106
+ If mode is 'json', the output will only contain JSON serializable types.
107
+ If mode is 'python', the output may contain non-JSON-serializable Python objects.
108
+ include: A set of fields to include in the output.
109
+ exclude: A set of fields to exclude from the output.
110
+ context: Additional context to pass to the serializer.
111
+ by_alias: Whether to use the field's alias in the dictionary key if defined.
112
+ exclude_unset: Whether to exclude fields that have not been explicitly set.
113
+ exclude_defaults: Whether to exclude fields that are set to their default value.
114
+ exclude_none: Whether to exclude fields that have a value of `None`.
115
+ round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T].
116
+ warnings: Whether to log warnings when invalid fields are encountered.
117
+ serialize_as_any: Whether to serialize fields with duck-typing serialization behavior.
118
+
119
+ Returns:
120
+ A dictionary representation of the model.
121
+ """
122
+ return model_dump(
123
+ self,
124
+ mode=mode,
125
+ include=include,
126
+ exclude=exclude,
127
+ by_alias=by_alias,
128
+ exclude_unset=exclude_unset,
129
+ exclude_defaults=exclude_defaults,
130
+ exclude_none=exclude_none,
131
+ round_trip=round_trip,
132
+ warnings=warnings,
133
+ )
134
+
135
+
136
+ __all__ = ["model_dump", "ModelDumpMixin"]
@@ -0,0 +1,112 @@
1
+ import typing
2
+
3
+ from typing_extensions import Self
4
+
5
+ from prefect._internal.pydantic._base_model import BaseModel
6
+ from prefect._internal.pydantic._flags import USE_V2_MODELS
7
+
8
+ if typing.TYPE_CHECKING:
9
+ from prefect._internal.pydantic._types import IncEx
10
+
11
+ T = typing.TypeVar("T", bound="BaseModel")
12
+
13
+
14
+ def model_dump_json(
15
+ model_instance: "BaseModel",
16
+ *,
17
+ indent: typing.Optional[int] = None,
18
+ include: "IncEx" = None,
19
+ exclude: "IncEx" = None,
20
+ by_alias: bool = False,
21
+ exclude_unset: bool = False,
22
+ exclude_defaults: bool = False,
23
+ exclude_none: bool = False,
24
+ round_trip: bool = False,
25
+ warnings: bool = True,
26
+ ) -> str:
27
+ """
28
+ Generate a JSON representation of the model, optionally specifying which fields to include or exclude.
29
+
30
+ Args:
31
+ indent: If provided, the number of spaces to indent the JSON output.
32
+ include: A list of fields to include in the output.
33
+ exclude: A list of fields to exclude from the output.
34
+ by_alias: Whether to use the field's alias in the dictionary key if defined.
35
+ exclude_unset: Whether to exclude fields that have not been explicitly set.
36
+ exclude_defaults: Whether to exclude fields that are set to their default value.
37
+ exclude_none: Whether to exclude fields that have a value of `None`.
38
+ round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T].
39
+ warnings: Whether to log warnings when invalid fields are encountered.
40
+
41
+ Returns:
42
+ A JSON representation of the model.
43
+ """
44
+ if USE_V2_MODELS:
45
+ return model_instance.model_dump_json(
46
+ indent=indent,
47
+ include=include,
48
+ exclude=exclude,
49
+ by_alias=by_alias,
50
+ exclude_unset=exclude_unset,
51
+ exclude_defaults=exclude_defaults,
52
+ exclude_none=exclude_none,
53
+ round_trip=round_trip,
54
+ warnings=warnings,
55
+ )
56
+ else:
57
+ return getattr(model_instance, "json")(
58
+ include=include,
59
+ exclude=exclude,
60
+ by_alias=by_alias,
61
+ exclude_unset=exclude_unset,
62
+ exclude_defaults=exclude_defaults,
63
+ exclude_none=exclude_none,
64
+ )
65
+
66
+
67
+ class ModelDumpJsonMixin(BaseModel):
68
+ def model_dump_json(
69
+ self: "Self",
70
+ *,
71
+ indent: typing.Optional[int] = None,
72
+ include: "IncEx" = None,
73
+ exclude: "IncEx" = None,
74
+ by_alias: bool = False,
75
+ exclude_unset: bool = False,
76
+ exclude_defaults: bool = False,
77
+ exclude_none: bool = False,
78
+ round_trip: bool = False,
79
+ warnings: bool = True,
80
+ ) -> str:
81
+ """
82
+ Generate a JSON representation of the model, optionally specifying which fields to include or exclude.
83
+
84
+ Args:
85
+ indent: If provided, the number of spaces to indent the JSON output.
86
+ include: A list of fields to include in the output.
87
+ exclude: A list of fields to exclude from the output.
88
+ by_alias: Whether to use the field's alias in the dictionary key if defined.
89
+ exclude_unset: Whether to exclude fields that have not been explicitly set.
90
+ exclude_defaults: Whether to exclude fields that are set to their default value.
91
+ exclude_none: Whether to exclude fields that have a value of `None`.
92
+ round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T].
93
+ warnings: Whether to log warnings when invalid fields are encountered.
94
+
95
+ Returns:
96
+ A JSON representation of the model.
97
+ """
98
+ return model_dump_json(
99
+ self,
100
+ indent=indent,
101
+ include=include,
102
+ exclude=exclude,
103
+ by_alias=by_alias,
104
+ exclude_unset=exclude_unset,
105
+ exclude_defaults=exclude_defaults,
106
+ exclude_none=exclude_none,
107
+ round_trip=round_trip,
108
+ warnings=warnings,
109
+ )
110
+
111
+
112
+ __all__ = ["model_dump_json", "ModelDumpJsonMixin"]
@@ -0,0 +1,50 @@
1
+ import operator
2
+ import typing
3
+
4
+ from prefect._internal.pydantic._base_model import BaseModel, FieldInfo
5
+ from prefect._internal.pydantic._flags import HAS_PYDANTIC_V2, USE_PYDANTIC_V2
6
+
7
+ T = typing.TypeVar("T")
8
+
9
+ if HAS_PYDANTIC_V2 and USE_PYDANTIC_V2:
10
+
11
+ class ModelFieldMixin(BaseModel): # type: ignore [no-redef]
12
+ pass
13
+
14
+ else:
15
+
16
+ def cast_model_field_to_field_info(model_field: typing.Any) -> FieldInfo:
17
+ class _FieldInfo(BaseModel):
18
+ model_field: typing.Any
19
+
20
+ @property
21
+ def annotation(self) -> typing.Any:
22
+ return getattr(self.model_field, "outer_type_")
23
+
24
+ @property
25
+ def frozen(self) -> bool:
26
+ return not operator.attrgetter("field_info.allow_mutation")(
27
+ self.model_field
28
+ )
29
+
30
+ @property
31
+ def json_schema_extra(self) -> typing.Dict[str, typing.Any]:
32
+ return operator.attrgetter("field_info.extra")(self.model_field)
33
+
34
+ def __getattr__(self, key: str) -> typing.Any:
35
+ return getattr(self.model_field, key)
36
+
37
+ def __repr__(self) -> str:
38
+ return repr(self.model_field)
39
+
40
+ return typing.cast(FieldInfo, _FieldInfo(model_field=model_field))
41
+
42
+ class ModelFieldMixin(BaseModel):
43
+ model_fields: typing.ClassVar[typing.Dict[str, FieldInfo]]
44
+
45
+ def __init_subclass__(cls, **kwargs: typing.Any) -> None:
46
+ cls.model_fields = {
47
+ field_name: cast_model_field_to_field_info(field)
48
+ for field_name, field in getattr(cls, "__fields__", {}).items()
49
+ }
50
+ super().__init_subclass__(**kwargs)
@@ -0,0 +1,82 @@
1
+ import typing
2
+
3
+ from typing_extensions import Self
4
+
5
+ from prefect._internal.pydantic._base_model import BaseModel
6
+ from prefect._internal.pydantic._flags import USE_V2_MODELS
7
+
8
+ if typing.TYPE_CHECKING:
9
+ from prefect._internal.pydantic._types import JsonSchemaMode
10
+
11
+ from prefect._internal.pydantic._types import DEFAULT_REF_TEMPLATE
12
+
13
+ T = typing.TypeVar("T", bound="BaseModel")
14
+
15
+
16
+ def model_json_schema(
17
+ model: typing.Type[T],
18
+ by_alias: bool = True,
19
+ ref_template: str = DEFAULT_REF_TEMPLATE,
20
+ schema_generator: typing.Any = None,
21
+ mode: "JsonSchemaMode" = "validation",
22
+ ) -> typing.Dict[str, typing.Any]:
23
+ """
24
+ Generates a JSON schema for a model class.
25
+
26
+ Args:
27
+ by_alias: Whether to use attribute aliases or not.
28
+ ref_template: The reference template.
29
+ schema_generator: To override the logic used to generate the JSON schema, as a subclass of
30
+ `GenerateJsonSchema` with your desired modifications
31
+ mode: The mode in which to generate the schema.
32
+
33
+ Returns:
34
+ The JSON schema for the given model class.
35
+ """
36
+ if USE_V2_MODELS:
37
+ return model.model_json_schema(
38
+ by_alias=by_alias,
39
+ ref_template=ref_template,
40
+ mode=mode,
41
+ # We've changed the type of schema_generator of 'schema_generator' to 'typing.Any',
42
+ # which is will throw an error if its None. So, we've to pass it only if its not None.
43
+ **{"schema_generator": schema_generator} if schema_generator else {},
44
+ )
45
+ else:
46
+ return getattr(model, "schema")(
47
+ by_alias=by_alias,
48
+ ref_template=ref_template,
49
+ )
50
+
51
+
52
+ class ModelJsonSchemaMixin(BaseModel):
53
+ @classmethod
54
+ def model_json_schema(
55
+ cls: typing.Type["Self"],
56
+ by_alias: bool = True,
57
+ ref_template: str = DEFAULT_REF_TEMPLATE,
58
+ schema_generator: typing.Any = None,
59
+ mode: "JsonSchemaMode" = "validation",
60
+ ) -> typing.Dict[str, typing.Any]:
61
+ """
62
+ Generates a JSON schema for a model class.
63
+
64
+ Args:
65
+ by_alias: Whether to use attribute aliases or not.
66
+ ref_template: The reference template.
67
+ schema_generator: To override the logic used to generate the JSON schema, as a subclass of
68
+ `GenerateJsonSchema` with your desired modifications
69
+ mode: The mode in which to generate the schema.
70
+
71
+ Returns:
72
+ The JSON schema for the given model class.
73
+ """
74
+ return model_json_schema(
75
+ cls,
76
+ by_alias=by_alias,
77
+ ref_template=ref_template,
78
+ mode=mode,
79
+ )
80
+
81
+
82
+ __all__ = ["model_json_schema", "ModelJsonSchemaMixin"]
@@ -0,0 +1,80 @@
1
+ import typing
2
+
3
+ from typing_extensions import Self
4
+
5
+ from prefect._internal.pydantic._base_model import BaseModel
6
+ from prefect._internal.pydantic._flags import USE_V2_MODELS
7
+
8
+ T = typing.TypeVar("T", bound="BaseModel")
9
+
10
+
11
+ def model_rebuild(
12
+ model_instance: typing.Type[T],
13
+ *,
14
+ force: bool = False,
15
+ raise_errors: bool = True,
16
+ _parent_namespace_depth: int = 2,
17
+ _types_namespace: typing.Optional[typing.Dict[str, typing.Any]] = None,
18
+ ) -> typing.Optional[bool]:
19
+ """Try to rebuild the pydantic-core schema for the model.
20
+
21
+ This may be necessary when one of the annotations is a ForwardRef which could not be resolved during
22
+ the initial attempt to build the schema, and automatic rebuilding fails.
23
+
24
+ Args:
25
+ force: Whether to force the rebuilding of the model schema, defaults to `False`.
26
+ raise_errors: Whether to raise errors, defaults to `True`.
27
+ _parent_namespace_depth: The depth level of the parent namespace, defaults to 2.
28
+ _types_namespace: The types namespace, defaults to `None`.
29
+
30
+ Returns:
31
+ Returns `None` if the schema is already "complete" and rebuilding was not required.
32
+ If rebuilding _was_ required, returns `True` if rebuilding was successful, otherwise `False`.
33
+ """
34
+
35
+ if USE_V2_MODELS:
36
+ return model_instance.model_rebuild(
37
+ force=force,
38
+ raise_errors=raise_errors,
39
+ _parent_namespace_depth=_parent_namespace_depth,
40
+ _types_namespace=_types_namespace,
41
+ )
42
+ else:
43
+ return getattr(model_instance, "update_forward_refs")()
44
+
45
+
46
+ class ModelRebuildMixin(BaseModel):
47
+ @classmethod
48
+ def model_rebuild(
49
+ cls: typing.Type["Self"],
50
+ *,
51
+ force: bool = False,
52
+ raise_errors: bool = True,
53
+ _parent_namespace_depth: int = 2,
54
+ _types_namespace: typing.Optional[typing.Dict[str, typing.Any]] = None,
55
+ ) -> typing.Optional[bool]:
56
+ """Try to rebuild the pydantic-core schema for the model.
57
+
58
+ This may be necessary when one of the annotations is a ForwardRef which could not be resolved during
59
+ the initial attempt to build the schema, and automatic rebuilding fails.
60
+
61
+ Args:
62
+ force: Whether to force the rebuilding of the model schema, defaults to `False`.
63
+ raise_errors: Whether to raise errors, defaults to `True`.
64
+ _parent_namespace_depth: The depth level of the parent namespace, defaults to 2.
65
+ _types_namespace: The types namespace, defaults to `None`.
66
+
67
+ Returns:
68
+ Returns `None` if the schema is already "complete" and rebuilding was not required.
69
+ If rebuilding _was_ required, returns `True` if rebuilding was successful, otherwise `False`.
70
+ """
71
+ return model_rebuild(
72
+ cls,
73
+ force=force,
74
+ raise_errors=raise_errors,
75
+ _parent_namespace_depth=_parent_namespace_depth,
76
+ _types_namespace=_types_namespace,
77
+ )
78
+
79
+
80
+ __all__ = ["model_rebuild", "ModelRebuildMixin"]
@@ -0,0 +1,75 @@
1
+ import typing
2
+
3
+ from typing_extensions import Self
4
+
5
+ from prefect._internal.pydantic._base_model import BaseModel
6
+ from prefect._internal.pydantic._flags import USE_V2_MODELS
7
+
8
+ T = typing.TypeVar("T", bound="BaseModel")
9
+
10
+
11
+ def model_validate(
12
+ model_instance: typing.Type[T],
13
+ obj: typing.Any,
14
+ *,
15
+ strict: typing.Optional[bool] = False,
16
+ from_attributes: typing.Optional[bool] = False,
17
+ context: typing.Optional[typing.Dict[str, typing.Any]] = None,
18
+ ) -> T:
19
+ """
20
+ Validate a pydantic model instance.
21
+
22
+ Args:
23
+ obj: The object to validate.
24
+ strict: Whether to enforce types strictly.
25
+ from_attributes: Whether to extract data from object attributes.
26
+ context: Additional context to pass to the validator.
27
+
28
+ Raises:
29
+ ValidationError: If the object could not be validated.
30
+
31
+ Returns:
32
+ The validated model instance.
33
+ """
34
+ if USE_V2_MODELS:
35
+ return model_instance.model_validate(
36
+ obj,
37
+ strict=strict,
38
+ from_attributes=from_attributes,
39
+ context=context,
40
+ )
41
+ else:
42
+ return getattr(model_instance, "validate")(obj)
43
+
44
+
45
+ class ModelValidateMixin(BaseModel):
46
+ @classmethod
47
+ def model_validate(
48
+ cls: typing.Type["Self"],
49
+ obj: typing.Any,
50
+ *,
51
+ strict: typing.Optional[bool] = False,
52
+ from_attributes: typing.Optional[bool] = False,
53
+ context: typing.Optional[typing.Dict[str, typing.Any]] = None,
54
+ ) -> "Self":
55
+ """
56
+ Validate a pydantic model instance.
57
+
58
+ Args:
59
+ obj: The object to validate.
60
+ strict: Whether to enforce types strictly.
61
+ from_attributes: Whether to extract data from object attributes.
62
+ context: Additional context to pass to the validator.
63
+
64
+ Raises:
65
+ ValidationError: If the object could not be validated.
66
+
67
+ Returns:
68
+ The validated model instance.
69
+ """
70
+ return model_validate(
71
+ cls, obj, strict=strict, from_attributes=from_attributes, context=context
72
+ )
73
+
74
+
75
+ __all__ = ["model_validate"]
@@ -0,0 +1,68 @@
1
+ import typing
2
+
3
+ from typing_extensions import Self
4
+
5
+ from prefect._internal.pydantic._base_model import BaseModel
6
+ from prefect._internal.pydantic._flags import USE_V2_MODELS
7
+
8
+ T = typing.TypeVar("T", bound="BaseModel")
9
+
10
+
11
+ def model_validate_json(
12
+ model: typing.Type[T],
13
+ json_data: typing.Union[str, bytes, bytearray],
14
+ *,
15
+ strict: typing.Optional[bool] = False,
16
+ context: typing.Optional[typing.Dict[str, typing.Any]] = None,
17
+ ) -> T:
18
+ """
19
+ Validate the given JSON data against the Pydantic model.
20
+
21
+ Args:
22
+ json_data: The JSON data to validate.
23
+ strict: Whether to enforce types strictly.
24
+ context: Extra variables to pass to the validator.
25
+
26
+ Returns:
27
+ The validated Pydantic model.
28
+
29
+ Raises:
30
+ ValueError: If `json_data` is not a JSON string.
31
+ """
32
+ if USE_V2_MODELS:
33
+ return model.model_validate_json(
34
+ json_data,
35
+ strict=strict,
36
+ context=context,
37
+ )
38
+ else:
39
+ return getattr(model, "parse_raw")(json_data)
40
+
41
+
42
+ class ModelValidateJsonMixin(BaseModel):
43
+ @classmethod
44
+ def model_validate_json(
45
+ cls: typing.Type["Self"],
46
+ json_data: typing.Union[str, bytes, bytearray],
47
+ *,
48
+ strict: typing.Optional[bool] = False,
49
+ context: typing.Optional[typing.Dict[str, typing.Any]] = None,
50
+ ) -> "Self":
51
+ """
52
+ Validate the given JSON data against the Pydantic model.
53
+
54
+ Args:
55
+ json_data: The JSON data to validate.
56
+ strict: Whether to enforce types strictly.
57
+ context: Extra variables to pass to the validator.
58
+
59
+ Returns:
60
+ The validated Pydantic model.
61
+
62
+ Raises:
63
+ ValueError: If `json_data` is not a JSON string.
64
+ """
65
+ return model_validate_json(cls, json_data, strict=strict, context=context)
66
+
67
+
68
+ __all__ = ["model_validate_json", "ModelValidateJsonMixin"]
@@ -0,0 +1,71 @@
1
+ import typing
2
+
3
+ from prefect._internal.pydantic._flags import USE_V2_MODELS
4
+
5
+ T = typing.TypeVar("T")
6
+
7
+ if USE_V2_MODELS:
8
+ from pydantic import TypeAdapter # type: ignore
9
+
10
+ else:
11
+ from pydantic import parse_obj_as # type: ignore
12
+
13
+ class TypeAdapter(typing.Generic[T]):
14
+ """
15
+ Type adapters provide a flexible way to perform validation and serialization based on a Python type.
16
+
17
+ A `TypeAdapter` instance exposes some of the functionality from `BaseModel` instance methods
18
+ for types that do not have such methods (such as dataclasses, primitive types, and more).
19
+
20
+ **Note:** `TypeAdapter` instances are not types, and cannot be used as type annotations for fields.
21
+
22
+ Attributes:
23
+ core_schema: The core schema for the type.
24
+ validator (SchemaValidator): The schema validator for the type.
25
+ serializer: The schema serializer for the type.
26
+ """
27
+
28
+ def __init__(self, type_: typing.Union[T, typing.Type[T]]) -> None:
29
+ self.type_ = type_
30
+
31
+ def validate_python(
32
+ self,
33
+ __object: typing.Any,
34
+ /,
35
+ *,
36
+ strict: typing.Optional[bool] = None,
37
+ from_attributes: typing.Optional[bool] = None,
38
+ context: typing.Optional[typing.Dict[str, typing.Any]] = None,
39
+ ) -> T:
40
+ return parse_obj_as(self.type_, __object) # type: ignore
41
+
42
+
43
+ def validate_python(
44
+ type_: typing.Union[T, typing.Type[T]],
45
+ __object: typing.Any,
46
+ /,
47
+ *,
48
+ strict: typing.Optional[bool] = None,
49
+ from_attributes: typing.Optional[bool] = None,
50
+ context: typing.Optional[typing.Dict[str, typing.Any]] = None,
51
+ ) -> T:
52
+ """Validate a Python object against the model.
53
+
54
+ Args:
55
+ type_: The type to validate against.
56
+ __object: The Python object to validate against the model.
57
+ strict: Whether to strictly check types.
58
+ from_attributes: Whether to extract data from object attributes.
59
+ context: Additional context to pass to the validator.
60
+
61
+ !!! note
62
+ When using `TypeAdapter` with a Pydantic `dataclass`, the use of the `from_attributes`
63
+ argument is not supported.
64
+
65
+ Returns:
66
+ The validated object.
67
+ """
68
+ return TypeAdapter(type_).validate_python(__object)
69
+
70
+
71
+ __all__ = ["TypeAdapter", "validate_python"]