prefect-client 2.16.3__py3-none-any.whl → 2.16.5__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 +4 -1
- prefect/_internal/compatibility/deprecated.py +28 -0
- prefect/_internal/concurrency/calls.py +3 -2
- prefect/_internal/pydantic/__init__.py +2 -0
- prefect/_internal/pydantic/_compat.py +180 -0
- prefect/agent.py +14 -6
- prefect/artifacts.py +185 -0
- prefect/client/base.py +80 -10
- prefect/client/cloud.py +1 -1
- prefect/client/orchestration.py +62 -1
- prefect/client/schemas/actions.py +2 -0
- prefect/client/schemas/objects.py +16 -0
- prefect/client/schemas/responses.py +1 -0
- prefect/client/subscriptions.py +13 -7
- prefect/client/utilities.py +55 -28
- prefect/deployments/deployments.py +49 -23
- prefect/deployments/schedules.py +13 -0
- prefect/deprecated/data_documents.py +2 -2
- prefect/deprecated/packaging/__init__.py +12 -0
- prefect/{packaging → deprecated/packaging}/base.py +21 -0
- prefect/{packaging → deprecated/packaging}/docker.py +18 -2
- prefect/{packaging → deprecated/packaging}/file.py +21 -3
- prefect/{packaging → deprecated/packaging}/orion.py +21 -3
- prefect/{packaging → deprecated/packaging}/serializers.py +22 -1
- prefect/engine.py +10 -6
- prefect/events/clients.py +9 -3
- prefect/events/related.py +1 -1
- prefect/events/schemas.py +45 -1
- prefect/filesystems.py +39 -1
- prefect/flows.py +12 -4
- prefect/infrastructure/base.py +15 -0
- prefect/infrastructure/container.py +23 -0
- prefect/infrastructure/kubernetes.py +17 -0
- prefect/infrastructure/process.py +16 -0
- prefect/server/api/collections_data/views/aggregate-worker-metadata.json +14 -2
- prefect/settings.py +62 -8
- prefect/task_server.py +28 -5
- prefect/tasks.py +44 -3
- prefect/utilities/callables.py +3 -1
- prefect/utilities/schema_tools/__init__.py +11 -0
- prefect/variables.py +4 -4
- prefect/workers/base.py +6 -1
- {prefect_client-2.16.3.dist-info → prefect_client-2.16.5.dist-info}/METADATA +2 -1
- {prefect_client-2.16.3.dist-info → prefect_client-2.16.5.dist-info}/RECORD +47 -45
- {prefect_client-2.16.3.dist-info → prefect_client-2.16.5.dist-info}/WHEEL +1 -1
- prefect/packaging/__init__.py +0 -8
- {prefect_client-2.16.3.dist-info → prefect_client-2.16.5.dist-info}/LICENSE +0 -0
- {prefect_client-2.16.3.dist-info → prefect_client-2.16.5.dist-info}/top_level.txt +0 -0
prefect/client/orchestration.py
CHANGED
@@ -15,11 +15,21 @@ from typing import (
|
|
15
15
|
)
|
16
16
|
from uuid import UUID, uuid4
|
17
17
|
|
18
|
+
import certifi
|
18
19
|
import httpcore
|
19
20
|
import httpx
|
20
21
|
import pendulum
|
21
22
|
|
23
|
+
from prefect._internal.compatibility.experimental import (
|
24
|
+
EXPERIMENTAL_WARNING,
|
25
|
+
ExperimentalFeature,
|
26
|
+
experiment_enabled,
|
27
|
+
)
|
22
28
|
from prefect._internal.pydantic import HAS_PYDANTIC_V2
|
29
|
+
from prefect.settings import (
|
30
|
+
PREFECT_EXPERIMENTAL_WARN,
|
31
|
+
PREFECT_EXPERIMENTAL_WARN_FLOW_RUN_INFRA_OVERRIDES,
|
32
|
+
)
|
23
33
|
|
24
34
|
if HAS_PYDANTIC_V2:
|
25
35
|
import pydantic.v1 as pydantic
|
@@ -125,8 +135,10 @@ from prefect.settings import (
|
|
125
135
|
PREFECT_API_ENABLE_HTTP2,
|
126
136
|
PREFECT_API_KEY,
|
127
137
|
PREFECT_API_REQUEST_TIMEOUT,
|
138
|
+
PREFECT_API_SSL_CERT_FILE,
|
128
139
|
PREFECT_API_TLS_INSECURE_SKIP_VERIFY,
|
129
140
|
PREFECT_API_URL,
|
141
|
+
PREFECT_CLIENT_CSRF_SUPPORT_ENABLED,
|
130
142
|
PREFECT_CLOUD_API_URL,
|
131
143
|
PREFECT_UNIT_TEST_MODE,
|
132
144
|
)
|
@@ -211,6 +223,11 @@ class PrefectClient:
|
|
211
223
|
|
212
224
|
if PREFECT_API_TLS_INSECURE_SKIP_VERIFY:
|
213
225
|
httpx_settings.setdefault("verify", False)
|
226
|
+
else:
|
227
|
+
cert_file = PREFECT_API_SSL_CERT_FILE.value()
|
228
|
+
if not cert_file:
|
229
|
+
cert_file = certifi.where()
|
230
|
+
httpx_settings.setdefault("verify", cert_file)
|
214
231
|
|
215
232
|
if api_version is None:
|
216
233
|
api_version = SERVER_API_VERSION
|
@@ -307,7 +324,15 @@ class PrefectClient:
|
|
307
324
|
|
308
325
|
if not PREFECT_UNIT_TEST_MODE:
|
309
326
|
httpx_settings.setdefault("follow_redirects", True)
|
310
|
-
|
327
|
+
|
328
|
+
enable_csrf_support = (
|
329
|
+
self.server_type != ServerType.CLOUD
|
330
|
+
and PREFECT_CLIENT_CSRF_SUPPORT_ENABLED.value()
|
331
|
+
)
|
332
|
+
|
333
|
+
self._client = PrefectHttpxClient(
|
334
|
+
**httpx_settings, enable_csrf_support=enable_csrf_support
|
335
|
+
)
|
311
336
|
self._loop = None
|
312
337
|
|
313
338
|
# See https://www.python-httpx.org/advanced/#custom-transports
|
@@ -506,6 +531,7 @@ class PrefectClient:
|
|
506
531
|
idempotency_key: str = None,
|
507
532
|
parent_task_run_id: UUID = None,
|
508
533
|
work_queue_name: str = None,
|
534
|
+
job_variables: Optional[Dict[str, Any]] = None,
|
509
535
|
) -> FlowRun:
|
510
536
|
"""
|
511
537
|
Create a flow run for a deployment.
|
@@ -529,6 +555,7 @@ class PrefectClient:
|
|
529
555
|
work_queue_name: An optional work queue name to add this run to. If not provided,
|
530
556
|
will default to the deployment's set work queue. If one is provided that does not
|
531
557
|
exist, a new work queue will be created within the deployment's work pool.
|
558
|
+
job_variables: Optional variables that will be supplied to the flow run job.
|
532
559
|
|
533
560
|
Raises:
|
534
561
|
httpx.RequestError: if the Prefect API does not successfully create a run for any reason
|
@@ -536,6 +563,21 @@ class PrefectClient:
|
|
536
563
|
Returns:
|
537
564
|
The flow run model
|
538
565
|
"""
|
566
|
+
if job_variables is not None and experiment_enabled("flow_run_infra_overrides"):
|
567
|
+
if (
|
568
|
+
PREFECT_EXPERIMENTAL_WARN
|
569
|
+
and PREFECT_EXPERIMENTAL_WARN_FLOW_RUN_INFRA_OVERRIDES
|
570
|
+
):
|
571
|
+
warnings.warn(
|
572
|
+
EXPERIMENTAL_WARNING.format(
|
573
|
+
feature="Flow run job variables",
|
574
|
+
group="flow_run_infra_overrides",
|
575
|
+
help="To use this feature, update your workers to Prefect 2.16.4 or later. ",
|
576
|
+
),
|
577
|
+
ExperimentalFeature,
|
578
|
+
stacklevel=3,
|
579
|
+
)
|
580
|
+
|
539
581
|
parameters = parameters or {}
|
540
582
|
context = context or {}
|
541
583
|
state = state or prefect.states.Scheduled()
|
@@ -549,6 +591,7 @@ class PrefectClient:
|
|
549
591
|
name=name,
|
550
592
|
idempotency_key=idempotency_key,
|
551
593
|
parent_task_run_id=parent_task_run_id,
|
594
|
+
job_variables=job_variables,
|
552
595
|
)
|
553
596
|
|
554
597
|
# done separately to avoid including this field in payloads sent to older API versions
|
@@ -634,6 +677,7 @@ class PrefectClient:
|
|
634
677
|
tags: Optional[Iterable[str]] = None,
|
635
678
|
empirical_policy: Optional[FlowRunPolicy] = None,
|
636
679
|
infrastructure_pid: Optional[str] = None,
|
680
|
+
job_variables: Optional[dict] = None,
|
637
681
|
) -> httpx.Response:
|
638
682
|
"""
|
639
683
|
Update a flow run's details.
|
@@ -654,6 +698,21 @@ class PrefectClient:
|
|
654
698
|
Returns:
|
655
699
|
an `httpx.Response` object from the PATCH request
|
656
700
|
"""
|
701
|
+
if job_variables is not None and experiment_enabled("flow_run_infra_overrides"):
|
702
|
+
if (
|
703
|
+
PREFECT_EXPERIMENTAL_WARN
|
704
|
+
and PREFECT_EXPERIMENTAL_WARN_FLOW_RUN_INFRA_OVERRIDES
|
705
|
+
):
|
706
|
+
warnings.warn(
|
707
|
+
EXPERIMENTAL_WARNING.format(
|
708
|
+
feature="Flow run job variables",
|
709
|
+
group="flow_run_infra_overrides",
|
710
|
+
help="To use this feature, update your workers to Prefect 2.16.4 or later. ",
|
711
|
+
),
|
712
|
+
ExperimentalFeature,
|
713
|
+
stacklevel=3,
|
714
|
+
)
|
715
|
+
|
657
716
|
params = {}
|
658
717
|
if flow_version is not None:
|
659
718
|
params["flow_version"] = flow_version
|
@@ -667,6 +726,8 @@ class PrefectClient:
|
|
667
726
|
params["empirical_policy"] = empirical_policy
|
668
727
|
if infrastructure_pid:
|
669
728
|
params["infrastructure_pid"] = infrastructure_pid
|
729
|
+
if job_variables is not None:
|
730
|
+
params["job_variables"] = job_variables
|
670
731
|
|
671
732
|
flow_run_data = FlowRunUpdate(**params)
|
672
733
|
|
@@ -298,6 +298,7 @@ class FlowRunUpdate(ActionBaseModel):
|
|
298
298
|
empirical_policy: objects.FlowRunPolicy = FieldFrom(objects.FlowRun)
|
299
299
|
tags: List[str] = FieldFrom(objects.FlowRun)
|
300
300
|
infrastructure_pid: Optional[str] = FieldFrom(objects.FlowRun)
|
301
|
+
job_variables: Optional[dict] = FieldFrom(objects.FlowRun)
|
301
302
|
|
302
303
|
|
303
304
|
@copy_model_fields
|
@@ -380,6 +381,7 @@ class DeploymentFlowRunCreate(ActionBaseModel):
|
|
380
381
|
idempotency_key: Optional[str] = FieldFrom(objects.FlowRun)
|
381
382
|
parent_task_run_id: Optional[UUID] = FieldFrom(objects.FlowRun)
|
382
383
|
work_queue_name: Optional[str] = FieldFrom(objects.FlowRun)
|
384
|
+
job_variables: Optional[dict] = FieldFrom(objects.FlowRun)
|
383
385
|
|
384
386
|
|
385
387
|
@copy_model_fields
|
@@ -526,6 +526,9 @@ class FlowRun(ObjectBaseModel):
|
|
526
526
|
description="The state of the flow run.",
|
527
527
|
example=State(type=StateType.COMPLETED),
|
528
528
|
)
|
529
|
+
job_variables: Optional[dict] = Field(
|
530
|
+
default=None, description="Job variables for the flow run."
|
531
|
+
)
|
529
532
|
|
530
533
|
def __eq__(self, other: Any) -> bool:
|
531
534
|
"""
|
@@ -1629,3 +1632,16 @@ class GlobalConcurrencyLimit(ObjectBaseModel):
|
|
1629
1632
|
" is used as a rate limit."
|
1630
1633
|
),
|
1631
1634
|
)
|
1635
|
+
|
1636
|
+
|
1637
|
+
class CsrfToken(ObjectBaseModel):
|
1638
|
+
token: str = Field(
|
1639
|
+
default=...,
|
1640
|
+
description="The CSRF token",
|
1641
|
+
)
|
1642
|
+
client: str = Field(
|
1643
|
+
default=..., description="The client id associated with the CSRF token"
|
1644
|
+
)
|
1645
|
+
expiration: DateTimeTZ = Field(
|
1646
|
+
default=..., description="The expiration time of the CSRF token"
|
1647
|
+
)
|
@@ -190,6 +190,7 @@ class FlowRunResponse(ObjectBaseModel):
|
|
190
190
|
example="my-work-pool",
|
191
191
|
)
|
192
192
|
state: Optional[objects.State] = FieldFrom(objects.FlowRun)
|
193
|
+
job_variables: Optional[dict] = FieldFrom(objects.FlowRun)
|
193
194
|
|
194
195
|
def __eq__(self, other: Any) -> bool:
|
195
196
|
"""
|
prefect/client/subscriptions.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import asyncio
|
2
|
-
from typing import Generic, List, Optional, Type, TypeVar
|
2
|
+
from typing import Any, Dict, Generic, List, Optional, Type, TypeVar
|
3
3
|
|
4
4
|
import orjson
|
5
5
|
import websockets
|
@@ -71,23 +71,29 @@ class Subscription(Generic[S]):
|
|
71
71
|
).decode()
|
72
72
|
)
|
73
73
|
|
74
|
-
auth = orjson.loads(await websocket.recv())
|
75
|
-
assert auth["type"] == "auth_success"
|
74
|
+
auth: Dict[str, Any] = orjson.loads(await websocket.recv())
|
75
|
+
assert auth["type"] == "auth_success", auth.get("message")
|
76
76
|
|
77
|
-
message = {"type": "subscribe", "keys": self.keys}
|
78
|
-
|
79
|
-
|
77
|
+
message = {"type": "subscribe", "keys": self.keys}
|
78
|
+
if self.client_id:
|
79
|
+
message.update({"client_id": self.client_id})
|
80
80
|
|
81
81
|
await websocket.send(orjson.dumps(message).decode())
|
82
82
|
except (
|
83
83
|
AssertionError,
|
84
84
|
websockets.exceptions.ConnectionClosedError,
|
85
85
|
) as e:
|
86
|
+
if isinstance(e, AssertionError) or e.code == WS_1008_POLICY_VIOLATION:
|
87
|
+
if isinstance(e, AssertionError):
|
88
|
+
reason = e.args[0]
|
89
|
+
elif isinstance(e, websockets.exceptions.ConnectionClosedError):
|
90
|
+
reason = e.reason
|
91
|
+
|
86
92
|
if isinstance(e, AssertionError) or e.code == WS_1008_POLICY_VIOLATION:
|
87
93
|
raise Exception(
|
88
94
|
"Unable to authenticate to the subscription. Please "
|
89
95
|
"ensure the provided `PREFECT_API_KEY` you are using is "
|
90
|
-
"valid for this environment."
|
96
|
+
f"valid for this environment. Reason: {reason}"
|
91
97
|
) from e
|
92
98
|
raise
|
93
99
|
else:
|
prefect/client/utilities.py
CHANGED
@@ -1,16 +1,60 @@
|
|
1
1
|
"""
|
2
2
|
Utilities for working with clients.
|
3
3
|
"""
|
4
|
+
|
4
5
|
# This module must not import from `prefect.client` when it is imported to avoid
|
5
6
|
# circular imports for decorators such as `inject_client` which are widely used.
|
6
7
|
|
7
8
|
from functools import wraps
|
9
|
+
from typing import TYPE_CHECKING, Any, Callable, Coroutine, Optional, Tuple, cast
|
10
|
+
|
11
|
+
from typing_extensions import ParamSpec
|
12
|
+
|
13
|
+
if TYPE_CHECKING:
|
14
|
+
from prefect.client.orchestration import PrefectClient
|
15
|
+
|
16
|
+
P = ParamSpec("P")
|
17
|
+
|
18
|
+
|
19
|
+
def get_or_create_client(
|
20
|
+
client: Optional["PrefectClient"] = None,
|
21
|
+
) -> Tuple["PrefectClient", bool]:
|
22
|
+
"""
|
23
|
+
Returns provided client, infers a client from context if available, or creates a new client.
|
8
24
|
|
9
|
-
|
10
|
-
|
25
|
+
Args:
|
26
|
+
- client (PrefectClient, optional): an optional client to use
|
11
27
|
|
28
|
+
Returns:
|
29
|
+
- tuple: a tuple of the client and a boolean indicating if the client was inferred from context
|
30
|
+
"""
|
31
|
+
if client is not None:
|
32
|
+
return client, True
|
33
|
+
from prefect._internal.concurrency.event_loop import get_running_loop
|
34
|
+
from prefect.context import FlowRunContext, TaskRunContext
|
35
|
+
|
36
|
+
flow_run_context = FlowRunContext.get()
|
37
|
+
task_run_context = TaskRunContext.get()
|
38
|
+
|
39
|
+
if (
|
40
|
+
flow_run_context
|
41
|
+
and getattr(flow_run_context.client, "_loop") == get_running_loop()
|
42
|
+
):
|
43
|
+
return flow_run_context.client, True
|
44
|
+
elif (
|
45
|
+
task_run_context
|
46
|
+
and getattr(task_run_context.client, "_loop") == get_running_loop()
|
47
|
+
):
|
48
|
+
return task_run_context.client, True
|
49
|
+
else:
|
50
|
+
from prefect.client.orchestration import get_client as get_httpx_client
|
51
|
+
|
52
|
+
return get_httpx_client(), False
|
12
53
|
|
13
|
-
|
54
|
+
|
55
|
+
def inject_client(
|
56
|
+
fn: Callable[P, Coroutine[Any, Any, Any]],
|
57
|
+
) -> Callable[P, Coroutine[Any, Any, Any]]:
|
14
58
|
"""
|
15
59
|
Simple helper to provide a context managed client to a asynchronous function.
|
16
60
|
|
@@ -20,33 +64,16 @@ def inject_client(fn):
|
|
20
64
|
"""
|
21
65
|
|
22
66
|
@wraps(fn)
|
23
|
-
async def with_injected_client(*args, **kwargs):
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
task_run_context = TaskRunContext.get()
|
29
|
-
client = None
|
30
|
-
client_context = asyncnullcontext()
|
31
|
-
|
32
|
-
if "client" in kwargs and kwargs["client"] is not None:
|
33
|
-
# Client provided in kwargs
|
34
|
-
client = kwargs["client"]
|
35
|
-
elif flow_run_context and flow_run_context.client._loop == get_running_loop():
|
36
|
-
# Client available from flow run context
|
37
|
-
client = flow_run_context.client
|
38
|
-
elif task_run_context and task_run_context.client._loop == get_running_loop():
|
39
|
-
# Client available from task run context
|
40
|
-
client = task_run_context.client
|
41
|
-
|
67
|
+
async def with_injected_client(*args: P.args, **kwargs: P.kwargs) -> Any:
|
68
|
+
client = cast(Optional["PrefectClient"], kwargs.pop("client", None))
|
69
|
+
client, inferred = get_or_create_client(client)
|
70
|
+
if not inferred:
|
71
|
+
context = client
|
42
72
|
else:
|
43
|
-
|
44
|
-
client_context = get_client()
|
45
|
-
|
46
|
-
# Removes existing client to allow it to be set by setdefault below
|
47
|
-
kwargs.pop("client", None)
|
73
|
+
from prefect.utilities.asyncutils import asyncnullcontext
|
48
74
|
|
49
|
-
|
75
|
+
context = asyncnullcontext()
|
76
|
+
async with context as new_client:
|
50
77
|
kwargs.setdefault("client", new_client or client)
|
51
78
|
return await fn(*args, **kwargs)
|
52
79
|
|
@@ -16,6 +16,10 @@ import anyio
|
|
16
16
|
import pendulum
|
17
17
|
import yaml
|
18
18
|
|
19
|
+
from prefect._internal.compatibility.deprecated import (
|
20
|
+
deprecated_callable,
|
21
|
+
deprecated_class,
|
22
|
+
)
|
19
23
|
from prefect._internal.pydantic import HAS_PYDANTIC_V2
|
20
24
|
from prefect.client.schemas.actions import DeploymentScheduleCreate
|
21
25
|
|
@@ -24,12 +28,10 @@ if HAS_PYDANTIC_V2:
|
|
24
28
|
else:
|
25
29
|
from pydantic import BaseModel, Field, parse_obj_as, root_validator, validator
|
26
30
|
|
27
|
-
from prefect._internal.compatibility.experimental import experimental_field
|
28
31
|
from prefect.blocks.core import Block
|
29
32
|
from prefect.blocks.fields import SecretDict
|
30
33
|
from prefect.client.orchestration import PrefectClient, ServerType, get_client
|
31
34
|
from prefect.client.schemas.objects import (
|
32
|
-
DEFAULT_AGENT_WORK_POOL_NAME,
|
33
35
|
FlowRun,
|
34
36
|
MinimalDeploymentSchedule,
|
35
37
|
)
|
@@ -38,6 +40,7 @@ from prefect.client.utilities import inject_client
|
|
38
40
|
from prefect.context import FlowRunContext, PrefectObjectRegistry, TaskRunContext
|
39
41
|
from prefect.deployments.schedules import (
|
40
42
|
FlexibleScheduleList,
|
43
|
+
create_minimal_deployment_schedule,
|
41
44
|
normalize_to_minimal_deployment_schedules,
|
42
45
|
)
|
43
46
|
from prefect.deployments.steps.core import run_steps
|
@@ -53,6 +56,7 @@ from prefect.infrastructure import Infrastructure, Process
|
|
53
56
|
from prefect.logging.loggers import flow_run_logger, get_logger
|
54
57
|
from prefect.states import Scheduled
|
55
58
|
from prefect.tasks import Task
|
59
|
+
from prefect.utilities.annotations import NotSet
|
56
60
|
from prefect.utilities.asyncutils import run_sync_in_worker_thread, sync_compatible
|
57
61
|
from prefect.utilities.callables import ParameterSchema, parameter_schema
|
58
62
|
from prefect.utilities.filesystem import relative_path_to_current_platform, tmpchdir
|
@@ -75,6 +79,7 @@ async def run_deployment(
|
|
75
79
|
idempotency_key: Optional[str] = None,
|
76
80
|
work_queue_name: Optional[str] = None,
|
77
81
|
as_subflow: Optional[bool] = True,
|
82
|
+
job_variables: Optional[dict] = None,
|
78
83
|
) -> FlowRun:
|
79
84
|
"""
|
80
85
|
Create a flow run for a deployment and return it after completion or a timeout.
|
@@ -194,6 +199,7 @@ async def run_deployment(
|
|
194
199
|
idempotency_key=idempotency_key,
|
195
200
|
parent_task_run_id=parent_task_run_id,
|
196
201
|
work_queue_name=work_queue_name,
|
202
|
+
job_variables=job_variables,
|
197
203
|
)
|
198
204
|
|
199
205
|
flow_run_id = flow_run.id
|
@@ -293,6 +299,7 @@ async def load_flow_from_flow_run(
|
|
293
299
|
return flow
|
294
300
|
|
295
301
|
|
302
|
+
@deprecated_callable(start_date="Mar 2024")
|
296
303
|
def load_deployments_from_yaml(
|
297
304
|
path: str,
|
298
305
|
) -> PrefectObjectRegistry:
|
@@ -316,13 +323,20 @@ def load_deployments_from_yaml(
|
|
316
323
|
return registry
|
317
324
|
|
318
325
|
|
319
|
-
@
|
320
|
-
"
|
321
|
-
|
322
|
-
|
326
|
+
@deprecated_class(
|
327
|
+
start_date="Mar 2024",
|
328
|
+
help="Use `flow.deploy` to deploy your flows instead."
|
329
|
+
" Refer to the upgrade guide for more information:"
|
330
|
+
" https://docs.prefect.io/latest/guides/upgrade-guide-agents-to-workers/.",
|
323
331
|
)
|
324
332
|
class Deployment(BaseModel):
|
325
333
|
"""
|
334
|
+
DEPRECATION WARNING:
|
335
|
+
|
336
|
+
This class is deprecated as of March 2024 and will not be available after September 2024.
|
337
|
+
It has been replaced by `flow.deploy`, which offers enhanced functionality and better a better user experience.
|
338
|
+
For upgrade instructions, see https://docs.prefect.io/latest/guides/upgrade-guide-agents-to-workers/.
|
339
|
+
|
326
340
|
A Prefect Deployment definition, used for specifying and building deployments.
|
327
341
|
|
328
342
|
Args:
|
@@ -647,21 +661,27 @@ class Deployment(BaseModel):
|
|
647
661
|
)
|
648
662
|
return values
|
649
663
|
|
650
|
-
@validator("schedule")
|
651
|
-
def validate_schedule(cls, value):
|
652
|
-
if value:
|
653
|
-
cls._validate_schedule(value)
|
654
|
-
return value
|
655
|
-
|
656
664
|
@root_validator(pre=True)
|
657
|
-
def
|
658
|
-
|
659
|
-
|
660
|
-
values["schedules"]
|
661
|
-
)
|
665
|
+
def reconcile_schedules(cls, values):
|
666
|
+
schedule = values.get("schedule", NotSet)
|
667
|
+
schedules = values.get("schedules", NotSet)
|
662
668
|
|
663
|
-
|
664
|
-
|
669
|
+
if schedules is not NotSet:
|
670
|
+
values["schedules"] = normalize_to_minimal_deployment_schedules(schedules)
|
671
|
+
elif schedule is not NotSet:
|
672
|
+
values["schedule"] = None
|
673
|
+
|
674
|
+
if schedule is None:
|
675
|
+
values["schedules"] = []
|
676
|
+
else:
|
677
|
+
values["schedules"] = [
|
678
|
+
create_minimal_deployment_schedule(
|
679
|
+
schedule=schedule, active=values.get("is_schedule_active")
|
680
|
+
)
|
681
|
+
]
|
682
|
+
|
683
|
+
for schedule in values.get("schedules", []):
|
684
|
+
cls._validate_schedule(schedule.schedule)
|
665
685
|
|
666
686
|
return values
|
667
687
|
|
@@ -982,11 +1002,17 @@ class Deployment(BaseModel):
|
|
982
1002
|
|
983
1003
|
# note that `deployment.load` only updates settings that were *not*
|
984
1004
|
# provided at initialization
|
985
|
-
|
986
|
-
|
987
|
-
|
1005
|
+
|
1006
|
+
deployment_args = {
|
1007
|
+
"name": name,
|
1008
|
+
"flow_name": flow.name,
|
988
1009
|
**kwargs,
|
989
|
-
|
1010
|
+
}
|
1011
|
+
|
1012
|
+
if schedules is not None:
|
1013
|
+
deployment_args["schedules"] = schedules
|
1014
|
+
|
1015
|
+
deployment = cls(**deployment_args)
|
990
1016
|
deployment.flow_name = flow.name
|
991
1017
|
if not deployment.entrypoint:
|
992
1018
|
## first see if an entrypoint can be determined
|
prefect/deployments/schedules.py
CHANGED
@@ -3,6 +3,14 @@ from typing import List, Optional, Sequence, Union, get_args
|
|
3
3
|
from prefect.client.schemas.objects import MinimalDeploymentSchedule
|
4
4
|
from prefect.client.schemas.schedules import SCHEDULE_TYPES
|
5
5
|
|
6
|
+
try:
|
7
|
+
from prefect.server.schemas.schedules import SCHEDULE_TYPES as SERVER_SCHEDULE_TYPES
|
8
|
+
|
9
|
+
SERVER_SCHEDULE_TYPES = get_args(SERVER_SCHEDULE_TYPES)
|
10
|
+
except ImportError:
|
11
|
+
# `prefect-client` does not have access to the server schemas.
|
12
|
+
SERVER_SCHEDULE_TYPES = ()
|
13
|
+
|
6
14
|
FlexibleScheduleList = Sequence[Union[MinimalDeploymentSchedule, dict, SCHEDULE_TYPES]]
|
7
15
|
|
8
16
|
|
@@ -28,6 +36,11 @@ def normalize_to_minimal_deployment_schedules(
|
|
28
36
|
normalized.append(create_minimal_deployment_schedule(**obj))
|
29
37
|
elif isinstance(obj, MinimalDeploymentSchedule):
|
30
38
|
normalized.append(obj)
|
39
|
+
elif isinstance(obj, SERVER_SCHEDULE_TYPES):
|
40
|
+
raise ValueError(
|
41
|
+
"Server schema schedules are not supported. Please use "
|
42
|
+
"the schedule objects from `prefect.client.schemas.schedules`"
|
43
|
+
)
|
31
44
|
else:
|
32
45
|
raise ValueError(
|
33
46
|
"Invalid schedule provided. Must be a schedule object, a dict,"
|
@@ -32,7 +32,7 @@ from prefect._internal.compatibility.deprecated import (
|
|
32
32
|
from prefect._internal.schemas.bases import PrefectBaseModel
|
33
33
|
|
34
34
|
if TYPE_CHECKING:
|
35
|
-
from prefect.packaging.base import PackageManifest
|
35
|
+
from prefect.deprecated.packaging.base import PackageManifest
|
36
36
|
|
37
37
|
T = TypeVar("T", bound="DataDocument") # Generic for DataDocument class types
|
38
38
|
D = TypeVar("D", bound=Any) # Generic for DataDocument data types
|
@@ -243,7 +243,7 @@ class PackageManifestSerializer:
|
|
243
243
|
|
244
244
|
@staticmethod
|
245
245
|
def loads(blob: bytes) -> "PackageManifest":
|
246
|
-
from prefect.packaging.base import PackageManifest
|
246
|
+
from prefect.deprecated.packaging.base import PackageManifest
|
247
247
|
|
248
248
|
return PackageManifest.parse_raw(blob)
|
249
249
|
|
@@ -0,0 +1,12 @@
|
|
1
|
+
"""
|
2
|
+
DEPRECATION WARNING:
|
3
|
+
This module is deprecated as of March 2024 and will not be available after September 2024.
|
4
|
+
"""
|
5
|
+
from prefect.deprecated.packaging.docker import DockerPackager
|
6
|
+
from prefect.deprecated.packaging.file import FilePackager
|
7
|
+
from prefect.deprecated.packaging.orion import OrionPackager
|
8
|
+
|
9
|
+
# isort: split
|
10
|
+
|
11
|
+
# Register any packaging serializers
|
12
|
+
import prefect.deprecated.packaging.serializers
|
@@ -1,6 +1,12 @@
|
|
1
|
+
"""
|
2
|
+
DEPRECATION WARNING:
|
3
|
+
This module is deprecated as of March 2024 and will not be available after September 2024.
|
4
|
+
"""
|
5
|
+
|
1
6
|
import abc
|
2
7
|
from typing import Generic, TypeVar
|
3
8
|
|
9
|
+
from prefect._internal.compatibility.deprecated import deprecated_class
|
4
10
|
from prefect._internal.pydantic import HAS_PYDANTIC_V2
|
5
11
|
|
6
12
|
if HAS_PYDANTIC_V2:
|
@@ -16,9 +22,14 @@ from prefect.utilities.pydantic import PartialModel, add_type_dispatch
|
|
16
22
|
D = TypeVar("D")
|
17
23
|
|
18
24
|
|
25
|
+
@deprecated_class(start_date="Mar 2024")
|
19
26
|
@add_type_dispatch
|
20
27
|
class Serializer(BaseModel, Generic[D], abc.ABC):
|
21
28
|
"""
|
29
|
+
DEPRECATION WARNING:
|
30
|
+
|
31
|
+
This class is deprecated as of version March 2024 and will not be available after September 2024.
|
32
|
+
|
22
33
|
A serializer that can encode objects of type 'D' into bytes.
|
23
34
|
"""
|
24
35
|
|
@@ -31,9 +42,14 @@ class Serializer(BaseModel, Generic[D], abc.ABC):
|
|
31
42
|
"""Decode the blob of bytes into an object."""
|
32
43
|
|
33
44
|
|
45
|
+
@deprecated_class(start_date="Mar 2024")
|
34
46
|
@add_type_dispatch
|
35
47
|
class PackageManifest(BaseModel, abc.ABC):
|
36
48
|
"""
|
49
|
+
DEPRECATION WARNING:
|
50
|
+
|
51
|
+
This class is deprecated as of version March 2024 and will not be available after September 2024.
|
52
|
+
|
37
53
|
Describes a package.
|
38
54
|
"""
|
39
55
|
|
@@ -48,9 +64,14 @@ class PackageManifest(BaseModel, abc.ABC):
|
|
48
64
|
"""
|
49
65
|
|
50
66
|
|
67
|
+
@deprecated_class(start_date="Mar 2024")
|
51
68
|
@add_type_dispatch
|
52
69
|
class Packager(BaseModel, abc.ABC):
|
53
70
|
"""
|
71
|
+
DEPRECATION WARNING:
|
72
|
+
|
73
|
+
This class is deprecated as of version March 2024 and will not be available after September 2024.
|
74
|
+
|
54
75
|
Creates a package for a flow.
|
55
76
|
|
56
77
|
A package contains the flow and is typically stored outside of Prefect. To
|
@@ -1,8 +1,14 @@
|
|
1
|
+
"""
|
2
|
+
DEPRECATION WARNING:
|
3
|
+
This module is deprecated as of March 2024 and will not be available after September 2024.
|
4
|
+
"""
|
5
|
+
|
1
6
|
import json
|
2
7
|
import sys
|
3
8
|
from pathlib import Path
|
4
9
|
from typing import Any, Mapping, Optional, Union
|
5
10
|
|
11
|
+
from prefect._internal.compatibility.deprecated import deprecated_class
|
6
12
|
from prefect._internal.pydantic import HAS_PYDANTIC_V2
|
7
13
|
|
8
14
|
if HAS_PYDANTIC_V2:
|
@@ -11,9 +17,9 @@ else:
|
|
11
17
|
from pydantic import AnyHttpUrl, root_validator, validator
|
12
18
|
from typing_extensions import Literal
|
13
19
|
|
20
|
+
from prefect.deprecated.packaging.base import PackageManifest, Packager
|
21
|
+
from prefect.deprecated.packaging.serializers import SourceSerializer
|
14
22
|
from prefect.flows import Flow, load_flow_from_script
|
15
|
-
from prefect.packaging.base import PackageManifest, Packager
|
16
|
-
from prefect.packaging.serializers import SourceSerializer
|
17
23
|
from prefect.software import CondaEnvironment, PythonEnvironment
|
18
24
|
from prefect.utilities.asyncutils import run_sync_in_worker_thread
|
19
25
|
from prefect.utilities.dockerutils import (
|
@@ -26,8 +32,13 @@ from prefect.utilities.dockerutils import (
|
|
26
32
|
from prefect.utilities.slugify import slugify
|
27
33
|
|
28
34
|
|
35
|
+
@deprecated_class(start_date="Mar 2024")
|
29
36
|
class DockerPackageManifest(PackageManifest):
|
30
37
|
"""
|
38
|
+
DEPRECATION WARNING:
|
39
|
+
|
40
|
+
This class is deprecated as of version March 2024 and will not be available after September 2024.
|
41
|
+
|
31
42
|
Represents a flow packaged in a Docker image
|
32
43
|
"""
|
33
44
|
|
@@ -40,8 +51,13 @@ class DockerPackageManifest(PackageManifest):
|
|
40
51
|
return load_flow_from_script(self.image_flow_location, self.flow_name)
|
41
52
|
|
42
53
|
|
54
|
+
@deprecated_class(start_date="Mar 2024")
|
43
55
|
class DockerPackager(Packager):
|
44
56
|
"""
|
57
|
+
DEPRECATION WARNING:
|
58
|
+
|
59
|
+
This class is deprecated as of version March 2024 and will not be available after September 2024.
|
60
|
+
|
45
61
|
This packager builds a Docker image containing the flow and the runtime environment
|
46
62
|
necessary to run the flow. The resulting image is optionally pushed to a container
|
47
63
|
registry, given by `registry_url`.
|