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
prefect/deployments/runner.py
CHANGED
@@ -44,7 +44,11 @@ from rich.table import Table
|
|
44
44
|
|
45
45
|
from prefect._internal.concurrency.api import create_call, from_async
|
46
46
|
from prefect._internal.pydantic import HAS_PYDANTIC_V2
|
47
|
-
from prefect._internal.schemas.validators import
|
47
|
+
from prefect._internal.schemas.validators import (
|
48
|
+
reconcile_paused_deployment,
|
49
|
+
reconcile_schedules_runner,
|
50
|
+
validate_automation_names,
|
51
|
+
)
|
48
52
|
from prefect.runner.storage import RunnerStorage
|
49
53
|
from prefect.settings import (
|
50
54
|
PREFECT_DEFAULT_DOCKER_BUILD_NAMESPACE,
|
@@ -67,7 +71,6 @@ from prefect.client.schemas.schedules import (
|
|
67
71
|
from prefect.deployments.schedules import (
|
68
72
|
FlexibleScheduleList,
|
69
73
|
create_minimal_deployment_schedule,
|
70
|
-
normalize_to_minimal_deployment_schedules,
|
71
74
|
)
|
72
75
|
from prefect.events import DeploymentTriggerTypes
|
73
76
|
from prefect.exceptions import (
|
@@ -236,32 +239,11 @@ class RunnerDeployment(BaseModel):
|
|
236
239
|
|
237
240
|
@root_validator(pre=True)
|
238
241
|
def reconcile_paused(cls, values):
|
239
|
-
|
240
|
-
is_schedule_active = values.get("is_schedule_active")
|
241
|
-
|
242
|
-
if paused is not None:
|
243
|
-
values["paused"] = paused
|
244
|
-
values["is_schedule_active"] = not paused
|
245
|
-
elif is_schedule_active is not None:
|
246
|
-
values["paused"] = not is_schedule_active
|
247
|
-
values["is_schedule_active"] = is_schedule_active
|
248
|
-
else:
|
249
|
-
values["paused"] = False
|
250
|
-
values["is_schedule_active"] = True
|
251
|
-
|
252
|
-
return values
|
242
|
+
return reconcile_paused_deployment(values)
|
253
243
|
|
254
244
|
@root_validator(pre=True)
|
255
245
|
def reconcile_schedules(cls, values):
|
256
|
-
|
257
|
-
schedules = values.get("schedules")
|
258
|
-
|
259
|
-
if schedules is None and schedule is not None:
|
260
|
-
values["schedules"] = [create_minimal_deployment_schedule(schedule)]
|
261
|
-
elif schedules is not None and len(schedules) > 0:
|
262
|
-
values["schedules"] = normalize_to_minimal_deployment_schedules(schedules)
|
263
|
-
|
264
|
-
return values
|
246
|
+
return reconcile_schedules_runner(values)
|
265
247
|
|
266
248
|
@sync_compatible
|
267
249
|
async def apply(
|
@@ -324,9 +306,9 @@ class RunnerDeployment(BaseModel):
|
|
324
306
|
)
|
325
307
|
|
326
308
|
if work_pool_name:
|
327
|
-
create_payload["
|
309
|
+
create_payload["job_variables"] = self.job_variables
|
328
310
|
if image:
|
329
|
-
create_payload["
|
311
|
+
create_payload["job_variables"]["image"] = image
|
330
312
|
create_payload["path"] = None if self.storage else self._path
|
331
313
|
create_payload["pull_steps"] = (
|
332
314
|
[self.storage.to_pull_step()] if self.storage else []
|
@@ -4,7 +4,7 @@ This module is deprecated as of March 2024 and will not be available after Septe
|
|
4
4
|
"""
|
5
5
|
|
6
6
|
import abc
|
7
|
-
from typing import Generic, TypeVar
|
7
|
+
from typing import Generic, Type, TypeVar
|
8
8
|
|
9
9
|
from prefect._internal.compatibility.deprecated import deprecated_class
|
10
10
|
from prefect._internal.pydantic import HAS_PYDANTIC_V2
|
@@ -17,7 +17,7 @@ else:
|
|
17
17
|
from prefect.flows import Flow
|
18
18
|
from prefect.utilities.callables import ParameterSchema, parameter_schema
|
19
19
|
from prefect.utilities.dispatch import lookup_type
|
20
|
-
from prefect.utilities.pydantic import
|
20
|
+
from prefect.utilities.pydantic import add_type_dispatch
|
21
21
|
|
22
22
|
D = TypeVar("D")
|
23
23
|
|
@@ -81,10 +81,9 @@ class Packager(BaseModel, abc.ABC):
|
|
81
81
|
|
82
82
|
type: str
|
83
83
|
|
84
|
-
def base_manifest(self, flow: Flow) ->
|
85
|
-
manifest_cls = lookup_type(PackageManifest, self.type)
|
86
|
-
return
|
87
|
-
manifest_cls,
|
84
|
+
def base_manifest(self, flow: Flow) -> PackageManifest:
|
85
|
+
manifest_cls: Type[BaseModel] = lookup_type(PackageManifest, self.type)
|
86
|
+
return manifest_cls.construct(
|
88
87
|
type=self.type,
|
89
88
|
flow_name=flow.name,
|
90
89
|
flow_parameter_schema=parameter_schema(flow.fn),
|
@@ -10,6 +10,12 @@ from typing import Any, Mapping, Optional, Union
|
|
10
10
|
|
11
11
|
from prefect._internal.compatibility.deprecated import deprecated_class
|
12
12
|
from prefect._internal.pydantic import HAS_PYDANTIC_V2
|
13
|
+
from prefect._internal.schemas.validators import (
|
14
|
+
assign_default_base_image,
|
15
|
+
base_image_xor_dockerfile,
|
16
|
+
set_default_python_environment,
|
17
|
+
validate_registry_url,
|
18
|
+
)
|
13
19
|
|
14
20
|
if HAS_PYDANTIC_V2:
|
15
21
|
from pydantic.v1 import AnyHttpUrl, root_validator, validator
|
@@ -25,7 +31,6 @@ from prefect.utilities.asyncutils import run_sync_in_worker_thread
|
|
25
31
|
from prefect.utilities.dockerutils import (
|
26
32
|
ImageBuilder,
|
27
33
|
build_image,
|
28
|
-
get_prefect_image_name,
|
29
34
|
push_image,
|
30
35
|
to_run_command,
|
31
36
|
)
|
@@ -63,7 +68,7 @@ class DockerPackager(Packager):
|
|
63
68
|
registry, given by `registry_url`.
|
64
69
|
"""
|
65
70
|
|
66
|
-
type:
|
71
|
+
type: str = "docker"
|
67
72
|
|
68
73
|
base_image: Optional[str] = None
|
69
74
|
python_environment: Optional[Union[PythonEnvironment, CondaEnvironment]] = None
|
@@ -74,36 +79,19 @@ class DockerPackager(Packager):
|
|
74
79
|
|
75
80
|
@root_validator
|
76
81
|
def set_default_base_image(cls, values):
|
77
|
-
|
78
|
-
values["base_image"] = get_prefect_image_name(
|
79
|
-
flavor=(
|
80
|
-
"conda"
|
81
|
-
if isinstance(values.get("python_environment"), CondaEnvironment)
|
82
|
-
else None
|
83
|
-
)
|
84
|
-
)
|
85
|
-
return values
|
82
|
+
return assign_default_base_image(values)
|
86
83
|
|
87
84
|
@root_validator
|
88
85
|
def base_image_and_dockerfile_exclusive(cls, values: Mapping[str, Any]):
|
89
|
-
|
90
|
-
raise ValueError(
|
91
|
-
"Either `base_image` or `dockerfile` should be provided, but not both"
|
92
|
-
)
|
93
|
-
return values
|
86
|
+
return base_image_xor_dockerfile(values)
|
94
87
|
|
95
88
|
@root_validator
|
96
89
|
def default_python_environment(cls, values: Mapping[str, Any]):
|
97
|
-
|
98
|
-
values["python_environment"] = PythonEnvironment.from_environment()
|
99
|
-
return values
|
90
|
+
return set_default_python_environment(values)
|
100
91
|
|
101
92
|
@validator("registry_url", pre=True)
|
102
93
|
def ensure_registry_url_is_prefixed(cls, value):
|
103
|
-
|
104
|
-
if "://" not in value:
|
105
|
-
return "https://" + value
|
106
|
-
return value
|
94
|
+
validate_registry_url(value)
|
107
95
|
|
108
96
|
async def package(self, flow: Flow) -> DockerPackageManifest:
|
109
97
|
"""
|
@@ -117,8 +105,14 @@ class DockerPackager(Packager):
|
|
117
105
|
push_image, image_reference, self.registry_url, image_name
|
118
106
|
)
|
119
107
|
|
120
|
-
return
|
121
|
-
|
108
|
+
return DockerPackageManifest(
|
109
|
+
**{
|
110
|
+
**self.base_manifest(flow).dict(),
|
111
|
+
**{
|
112
|
+
"image": image_reference,
|
113
|
+
"image_flow_location": self.image_flow_location,
|
114
|
+
},
|
115
|
+
}
|
122
116
|
)
|
123
117
|
|
124
118
|
async def _build_image(self, flow: Flow) -> str:
|
@@ -34,7 +34,7 @@ class FilePackageManifest(PackageManifest):
|
|
34
34
|
This class is deprecated as of version March 2024 and will not be available after September 2024.
|
35
35
|
"""
|
36
36
|
|
37
|
-
type:
|
37
|
+
type: str = "file"
|
38
38
|
serializer: Serializer
|
39
39
|
key: str
|
40
40
|
filesystem_id: UUID
|
@@ -80,8 +80,13 @@ class FilePackager(Packager):
|
|
80
80
|
or await self.filesystem._save(is_anonymous=True)
|
81
81
|
)
|
82
82
|
|
83
|
-
return
|
84
|
-
|
85
|
-
|
86
|
-
|
83
|
+
return FilePackageManifest(
|
84
|
+
**{
|
85
|
+
**self.base_manifest(flow).dict(),
|
86
|
+
**{
|
87
|
+
"serializer": self.serializer,
|
88
|
+
"filesystem_id": filesystem_id,
|
89
|
+
"key": key,
|
90
|
+
},
|
91
|
+
}
|
87
92
|
)
|
@@ -31,7 +31,7 @@ class OrionPackageManifest(PackageManifest):
|
|
31
31
|
This class is deprecated as of version March 2024 and will not be available after September 2024.
|
32
32
|
"""
|
33
33
|
|
34
|
-
type:
|
34
|
+
type: str = "orion"
|
35
35
|
serializer: Serializer
|
36
36
|
block_document_id: UUID
|
37
37
|
|
@@ -69,7 +69,12 @@ class OrionPackager(Packager):
|
|
69
69
|
value={"flow": self.serializer.dumps(flow)}
|
70
70
|
)._save(is_anonymous=True)
|
71
71
|
|
72
|
-
return
|
73
|
-
|
74
|
-
|
72
|
+
return OrionPackageManifest(
|
73
|
+
**{
|
74
|
+
**self.base_manifest(flow).dict(),
|
75
|
+
**{
|
76
|
+
"serializer": self.serializer,
|
77
|
+
"block_document_id": block_document_id,
|
78
|
+
},
|
79
|
+
}
|
75
80
|
)
|
@@ -7,13 +7,17 @@ import base64
|
|
7
7
|
import inspect
|
8
8
|
import json
|
9
9
|
import os.path
|
10
|
-
import warnings
|
11
10
|
from pathlib import Path
|
12
11
|
from tempfile import TemporaryDirectory
|
13
12
|
from typing import Any, List
|
14
13
|
|
15
14
|
from prefect._internal.compatibility.deprecated import deprecated_class
|
16
15
|
from prefect._internal.pydantic import HAS_PYDANTIC_V2
|
16
|
+
from prefect._internal.schemas.validators import (
|
17
|
+
validate_picklelib,
|
18
|
+
validate_picklelib_and_modules,
|
19
|
+
validate_picklelib_version,
|
20
|
+
)
|
17
21
|
|
18
22
|
if HAS_PYDANTIC_V2:
|
19
23
|
import pydantic.v1 as pydantic
|
@@ -55,69 +59,15 @@ class PickleSerializer(Serializer):
|
|
55
59
|
|
56
60
|
@pydantic.validator("picklelib")
|
57
61
|
def check_picklelib(cls, value):
|
58
|
-
|
59
|
-
Check that the given pickle library is importable and has dumps/loads methods.
|
60
|
-
"""
|
61
|
-
try:
|
62
|
-
pickler = from_qualified_name(value)
|
63
|
-
except (ImportError, AttributeError) as exc:
|
64
|
-
raise ValueError(
|
65
|
-
f"Failed to import requested pickle library: {value!r}."
|
66
|
-
) from exc
|
67
|
-
|
68
|
-
if not callable(getattr(pickler, "dumps", None)):
|
69
|
-
raise ValueError(
|
70
|
-
f"Pickle library at {value!r} does not have a 'dumps' method."
|
71
|
-
)
|
72
|
-
|
73
|
-
if not callable(getattr(pickler, "loads", None)):
|
74
|
-
raise ValueError(
|
75
|
-
f"Pickle library at {value!r} does not have a 'loads' method."
|
76
|
-
)
|
77
|
-
|
78
|
-
return value
|
62
|
+
return validate_picklelib(value)
|
79
63
|
|
80
64
|
@pydantic.root_validator
|
81
65
|
def check_picklelib_version(cls, values):
|
82
|
-
|
83
|
-
Infers a default value for `picklelib_version` if null or ensures it matches
|
84
|
-
the version retrieved from the `pickelib`.
|
85
|
-
"""
|
86
|
-
picklelib = values.get("picklelib")
|
87
|
-
picklelib_version = values.get("picklelib_version")
|
88
|
-
|
89
|
-
if not picklelib:
|
90
|
-
raise ValueError("Unable to check version of unrecognized picklelib module")
|
91
|
-
|
92
|
-
pickler = from_qualified_name(picklelib)
|
93
|
-
pickler_version = getattr(pickler, "__version__", None)
|
94
|
-
|
95
|
-
if not picklelib_version:
|
96
|
-
values["picklelib_version"] = pickler_version
|
97
|
-
elif picklelib_version != pickler_version:
|
98
|
-
warnings.warn(
|
99
|
-
(
|
100
|
-
f"Mismatched {picklelib!r} versions. Found {pickler_version} in the"
|
101
|
-
f" environment but {picklelib_version} was requested. This may"
|
102
|
-
" cause the serializer to fail."
|
103
|
-
),
|
104
|
-
RuntimeWarning,
|
105
|
-
stacklevel=3,
|
106
|
-
)
|
107
|
-
|
108
|
-
return values
|
66
|
+
return validate_picklelib_version(values)
|
109
67
|
|
110
68
|
@pydantic.root_validator
|
111
69
|
def check_picklelib_and_modules(cls, values):
|
112
|
-
|
113
|
-
Prevents modules from being specified if picklelib is not cloudpickle
|
114
|
-
"""
|
115
|
-
if values.get("picklelib") != "cloudpickle" and values.get("pickle_modules"):
|
116
|
-
raise ValueError(
|
117
|
-
"`pickle_modules` cannot be used without 'cloudpickle'. Got"
|
118
|
-
f" {values.get('picklelib')!r}."
|
119
|
-
)
|
120
|
-
return values
|
70
|
+
return validate_picklelib_and_modules(values)
|
121
71
|
|
122
72
|
def dumps(self, obj: Any) -> bytes:
|
123
73
|
pickler = from_qualified_name(self.picklelib)
|