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.
Files changed (89) hide show
  1. prefect/__init__.py +0 -18
  2. prefect/_internal/compatibility/deprecated.py +108 -5
  3. prefect/_internal/compatibility/experimental.py +9 -8
  4. prefect/_internal/concurrency/api.py +23 -42
  5. prefect/_internal/concurrency/waiters.py +25 -22
  6. prefect/_internal/pydantic/__init__.py +16 -3
  7. prefect/_internal/pydantic/_base_model.py +39 -4
  8. prefect/_internal/pydantic/_compat.py +69 -452
  9. prefect/_internal/pydantic/_flags.py +5 -0
  10. prefect/_internal/pydantic/_types.py +8 -0
  11. prefect/_internal/pydantic/utilities/__init__.py +0 -0
  12. prefect/_internal/pydantic/utilities/config_dict.py +72 -0
  13. prefect/_internal/pydantic/utilities/field_validator.py +135 -0
  14. prefect/_internal/pydantic/utilities/model_construct.py +56 -0
  15. prefect/_internal/pydantic/utilities/model_copy.py +55 -0
  16. prefect/_internal/pydantic/utilities/model_dump.py +136 -0
  17. prefect/_internal/pydantic/utilities/model_dump_json.py +112 -0
  18. prefect/_internal/pydantic/utilities/model_fields.py +50 -0
  19. prefect/_internal/pydantic/utilities/model_fields_set.py +29 -0
  20. prefect/_internal/pydantic/utilities/model_json_schema.py +82 -0
  21. prefect/_internal/pydantic/utilities/model_rebuild.py +80 -0
  22. prefect/_internal/pydantic/utilities/model_validate.py +75 -0
  23. prefect/_internal/pydantic/utilities/model_validate_json.py +68 -0
  24. prefect/_internal/pydantic/utilities/model_validator.py +79 -0
  25. prefect/_internal/pydantic/utilities/type_adapter.py +71 -0
  26. prefect/_internal/schemas/bases.py +1 -17
  27. prefect/_internal/schemas/validators.py +425 -4
  28. prefect/agent.py +1 -1
  29. prefect/blocks/kubernetes.py +7 -3
  30. prefect/blocks/notifications.py +18 -18
  31. prefect/blocks/webhook.py +1 -1
  32. prefect/client/base.py +7 -0
  33. prefect/client/cloud.py +1 -1
  34. prefect/client/orchestration.py +51 -11
  35. prefect/client/schemas/actions.py +367 -297
  36. prefect/client/schemas/filters.py +28 -28
  37. prefect/client/schemas/objects.py +78 -147
  38. prefect/client/schemas/responses.py +240 -60
  39. prefect/client/schemas/schedules.py +6 -8
  40. prefect/concurrency/events.py +2 -2
  41. prefect/context.py +4 -2
  42. prefect/deployments/base.py +6 -13
  43. prefect/deployments/deployments.py +34 -9
  44. prefect/deployments/runner.py +9 -27
  45. prefect/deprecated/packaging/base.py +5 -6
  46. prefect/deprecated/packaging/docker.py +19 -25
  47. prefect/deprecated/packaging/file.py +10 -5
  48. prefect/deprecated/packaging/orion.py +9 -4
  49. prefect/deprecated/packaging/serializers.py +8 -58
  50. prefect/engine.py +55 -618
  51. prefect/events/actions.py +16 -1
  52. prefect/events/clients.py +45 -13
  53. prefect/events/filters.py +19 -2
  54. prefect/events/related.py +4 -4
  55. prefect/events/schemas/automations.py +13 -2
  56. prefect/events/schemas/deployment_triggers.py +73 -5
  57. prefect/events/schemas/events.py +1 -1
  58. prefect/events/utilities.py +12 -4
  59. prefect/events/worker.py +26 -8
  60. prefect/exceptions.py +3 -8
  61. prefect/filesystems.py +7 -7
  62. prefect/flows.py +7 -3
  63. prefect/infrastructure/provisioners/ecs.py +1 -0
  64. prefect/logging/configuration.py +2 -2
  65. prefect/manifests.py +1 -8
  66. prefect/profiles.toml +1 -1
  67. prefect/pydantic/__init__.py +74 -2
  68. prefect/pydantic/main.py +26 -2
  69. prefect/serializers.py +6 -31
  70. prefect/settings.py +72 -26
  71. prefect/software/python.py +3 -5
  72. prefect/task_server.py +2 -2
  73. prefect/utilities/callables.py +1 -1
  74. prefect/utilities/collections.py +2 -1
  75. prefect/utilities/dispatch.py +1 -0
  76. prefect/utilities/engine.py +629 -0
  77. prefect/utilities/pydantic.py +1 -1
  78. prefect/utilities/schema_tools/validation.py +2 -2
  79. prefect/utilities/visualization.py +1 -1
  80. prefect/variables.py +88 -12
  81. prefect/workers/base.py +20 -11
  82. prefect/workers/block.py +4 -8
  83. prefect/workers/process.py +2 -5
  84. {prefect_client-2.16.8.dist-info → prefect_client-2.17.0.dist-info}/METADATA +4 -3
  85. {prefect_client-2.16.8.dist-info → prefect_client-2.17.0.dist-info}/RECORD +88 -72
  86. prefect/_internal/schemas/transformations.py +0 -106
  87. {prefect_client-2.16.8.dist-info → prefect_client-2.17.0.dist-info}/LICENSE +0 -0
  88. {prefect_client-2.16.8.dist-info → prefect_client-2.17.0.dist-info}/WHEEL +0 -0
  89. {prefect_client-2.16.8.dist-info → prefect_client-2.17.0.dist-info}/top_level.txt +0 -0
@@ -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,79 @@
1
+ import functools
2
+ from typing import TYPE_CHECKING, Any, Callable, Literal, Optional, TypeVar
3
+
4
+ from prefect._internal.pydantic._flags import HAS_PYDANTIC_V2, USE_V2_MODELS
5
+
6
+ T = TypeVar("T", bound=Callable[..., Any])
7
+
8
+ if TYPE_CHECKING:
9
+ from prefect._internal.pydantic._compat import BaseModel
10
+
11
+
12
+ def model_validator(
13
+ _func: Optional[Callable] = None,
14
+ *,
15
+ mode: Literal["wrap", "before", "after"] = "before", # v2 only
16
+ pre: bool = False, # v1 only
17
+ skip_on_failure: bool = False, # v1 only
18
+ ) -> Any:
19
+ """Usage docs: https://docs.pydantic.dev/2.6/concepts/validators/#model-validators
20
+
21
+ A decorator designed for Pydantic model methods to facilitate additional validations.
22
+ It can be applied to instance methods, class methods, or static methods of a class,
23
+ wrapping around the designated function to inject validation logic.
24
+
25
+ The `model_validator` does not differentiate between the types of methods it decorates
26
+ (instance, class, or static methods). It generically wraps the given function,
27
+ allowing the class's mechanism to determine how the method is treated
28
+ (e.g., passing `self` for instance methods or `cls` for class methods).
29
+
30
+ The actual handling of method types (instance, class, or static) is governed by the class
31
+ definition itself, using Python's standard `@classmethod` and `@staticmethod` decorators
32
+ where appropriate. This decorator simply intercepts the method call, allowing for custom
33
+ validation logic before, after, or wrapping the original method call, depending on the
34
+ `mode` parameter.
35
+
36
+ Args:
37
+ _func: The function to be decorated. If None, the decorator is applied with parameters.
38
+ mode: Specifies when the validation should occur. 'before' or 'after' are for v1 compatibility,
39
+ 'wrap' introduces v2 behavior where the validation wraps the original call.
40
+ pre: (v1 only) If True, the validator is called before Pydantic's own validators.
41
+ skip_on_failure: (v1 only) If True, skips validation if an earlier validation failed.
42
+
43
+ Returns:
44
+ The decorated function with added validation logic.
45
+
46
+ Note:
47
+ - The behavior of the decorator changes depending on the version of Pydantic being used.
48
+ - The specific logic for validation should be defined within the decorated function.
49
+ """
50
+
51
+ def decorator(validate_func: T) -> T:
52
+ if USE_V2_MODELS:
53
+ from pydantic import model_validator
54
+
55
+ return model_validator(
56
+ mode=mode,
57
+ )(validate_func) # type: ignore
58
+
59
+ elif HAS_PYDANTIC_V2:
60
+ from pydantic.v1 import root_validator
61
+
62
+ else:
63
+ from pydantic import root_validator
64
+
65
+ @functools.wraps(validate_func)
66
+ def wrapper(
67
+ cls: "BaseModel",
68
+ v: Any,
69
+ ) -> Any:
70
+ return validate_func(cls, v)
71
+
72
+ return root_validator(
73
+ pre=pre,
74
+ skip_on_failure=skip_on_failure,
75
+ )(wrapper) # type: ignore
76
+
77
+ if _func is None:
78
+ return decorator
79
+ return decorator(_func)
@@ -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"]
@@ -1,6 +1,7 @@
1
1
  """
2
2
  Utilities for creating and working with Prefect REST API schemas.
3
3
  """
4
+
4
5
  import datetime
5
6
  import json
6
7
  import os
@@ -23,7 +24,6 @@ else:
23
24
  from pydantic import BaseModel, Field, SecretField
24
25
  from pydantic.json import custom_pydantic_encoder
25
26
 
26
- from prefect._internal.compatibility.experimental import experiment_enabled
27
27
  from prefect._internal.schemas.fields import DateTimeTZ
28
28
  from prefect._internal.schemas.serializers import orjson_dumps_extra_compatible
29
29
 
@@ -131,22 +131,6 @@ class PrefectBaseModel(BaseModel):
131
131
  dict
132
132
  """
133
133
 
134
- experimental_fields = [
135
- field
136
- for _, field in self.__fields__.items()
137
- if field.field_info.extra.get("experimental")
138
- ]
139
- experimental_fields_to_exclude = [
140
- field.name
141
- for field in experimental_fields
142
- if not experiment_enabled(field.field_info.extra["experimental-group"])
143
- ]
144
-
145
- if experimental_fields_to_exclude:
146
- kwargs["exclude"] = (kwargs.get("exclude") or set()).union(
147
- experimental_fields_to_exclude
148
- )
149
-
150
134
  if json_compatible and shallow:
151
135
  raise ValueError(
152
136
  "`json_compatible` can only be applied to the entire object."