prefect-client 3.1.10__py3-none-any.whl → 3.1.12__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/_experimental/lineage.py +7 -8
- prefect/_experimental/sla/__init__.py +0 -0
- prefect/_experimental/sla/client.py +66 -0
- prefect/_experimental/sla/objects.py +53 -0
- prefect/_internal/_logging.py +15 -3
- prefect/_internal/compatibility/async_dispatch.py +22 -16
- prefect/_internal/compatibility/deprecated.py +42 -18
- prefect/_internal/compatibility/migration.py +2 -2
- prefect/_internal/concurrency/inspection.py +12 -14
- prefect/_internal/concurrency/primitives.py +2 -2
- prefect/_internal/concurrency/services.py +154 -80
- prefect/_internal/concurrency/waiters.py +13 -9
- prefect/_internal/pydantic/annotations/pendulum.py +7 -7
- prefect/_internal/pytz.py +4 -3
- prefect/_internal/retries.py +10 -5
- prefect/_internal/schemas/bases.py +19 -10
- prefect/_internal/schemas/validators.py +227 -388
- prefect/_version.py +3 -3
- prefect/automations.py +236 -30
- prefect/blocks/__init__.py +3 -3
- prefect/blocks/abstract.py +53 -30
- prefect/blocks/core.py +183 -84
- prefect/blocks/notifications.py +133 -73
- prefect/blocks/redis.py +13 -9
- prefect/blocks/system.py +24 -11
- prefect/blocks/webhook.py +7 -5
- prefect/cache_policies.py +3 -2
- prefect/client/orchestration/__init__.py +1957 -0
- prefect/client/orchestration/_artifacts/__init__.py +0 -0
- prefect/client/orchestration/_artifacts/client.py +239 -0
- prefect/client/orchestration/_automations/__init__.py +0 -0
- prefect/client/orchestration/_automations/client.py +329 -0
- prefect/client/orchestration/_blocks_documents/__init__.py +0 -0
- prefect/client/orchestration/_blocks_documents/client.py +334 -0
- prefect/client/orchestration/_blocks_schemas/__init__.py +0 -0
- prefect/client/orchestration/_blocks_schemas/client.py +200 -0
- prefect/client/orchestration/_blocks_types/__init__.py +0 -0
- prefect/client/orchestration/_blocks_types/client.py +380 -0
- prefect/client/orchestration/_concurrency_limits/__init__.py +0 -0
- prefect/client/orchestration/_concurrency_limits/client.py +762 -0
- prefect/client/orchestration/_deployments/__init__.py +0 -0
- prefect/client/orchestration/_deployments/client.py +1128 -0
- prefect/client/orchestration/_flow_runs/__init__.py +0 -0
- prefect/client/orchestration/_flow_runs/client.py +903 -0
- prefect/client/orchestration/_flows/__init__.py +0 -0
- prefect/client/orchestration/_flows/client.py +343 -0
- prefect/client/orchestration/_logs/__init__.py +0 -0
- prefect/client/orchestration/_logs/client.py +97 -0
- prefect/client/orchestration/_variables/__init__.py +0 -0
- prefect/client/orchestration/_variables/client.py +157 -0
- prefect/client/orchestration/base.py +46 -0
- prefect/client/orchestration/routes.py +145 -0
- prefect/client/schemas/__init__.py +68 -28
- prefect/client/schemas/actions.py +2 -2
- prefect/client/schemas/filters.py +5 -0
- prefect/client/schemas/objects.py +8 -15
- prefect/client/schemas/schedules.py +22 -10
- prefect/concurrency/_asyncio.py +87 -0
- prefect/concurrency/{events.py → _events.py} +10 -10
- prefect/concurrency/asyncio.py +20 -104
- prefect/concurrency/context.py +6 -4
- prefect/concurrency/services.py +26 -74
- prefect/concurrency/sync.py +23 -44
- prefect/concurrency/v1/_asyncio.py +63 -0
- prefect/concurrency/v1/{events.py → _events.py} +13 -15
- prefect/concurrency/v1/asyncio.py +27 -80
- prefect/concurrency/v1/context.py +6 -4
- prefect/concurrency/v1/services.py +33 -79
- prefect/concurrency/v1/sync.py +18 -37
- prefect/context.py +66 -45
- prefect/deployments/base.py +10 -144
- prefect/deployments/flow_runs.py +12 -2
- prefect/deployments/runner.py +53 -4
- prefect/deployments/steps/pull.py +13 -0
- prefect/engine.py +17 -4
- prefect/events/clients.py +7 -1
- prefect/events/schemas/events.py +3 -2
- prefect/filesystems.py +6 -2
- prefect/flow_engine.py +101 -85
- prefect/flows.py +10 -1
- prefect/input/run_input.py +2 -1
- prefect/logging/logging.yml +1 -1
- prefect/main.py +1 -3
- prefect/results.py +2 -307
- prefect/runner/runner.py +4 -2
- prefect/runner/storage.py +87 -21
- prefect/serializers.py +32 -25
- prefect/settings/legacy.py +4 -4
- prefect/settings/models/api.py +3 -3
- prefect/settings/models/cli.py +3 -3
- prefect/settings/models/client.py +5 -3
- prefect/settings/models/cloud.py +8 -3
- prefect/settings/models/deployments.py +3 -3
- prefect/settings/models/experiments.py +4 -7
- prefect/settings/models/flows.py +3 -3
- prefect/settings/models/internal.py +4 -2
- prefect/settings/models/logging.py +4 -3
- prefect/settings/models/results.py +3 -3
- prefect/settings/models/root.py +3 -2
- prefect/settings/models/runner.py +4 -4
- prefect/settings/models/server/api.py +3 -3
- prefect/settings/models/server/database.py +11 -4
- prefect/settings/models/server/deployments.py +6 -2
- prefect/settings/models/server/ephemeral.py +4 -2
- prefect/settings/models/server/events.py +3 -2
- prefect/settings/models/server/flow_run_graph.py +6 -2
- prefect/settings/models/server/root.py +3 -3
- prefect/settings/models/server/services.py +26 -11
- prefect/settings/models/server/tasks.py +6 -3
- prefect/settings/models/server/ui.py +3 -3
- prefect/settings/models/tasks.py +5 -5
- prefect/settings/models/testing.py +3 -3
- prefect/settings/models/worker.py +5 -3
- prefect/settings/profiles.py +15 -2
- prefect/states.py +61 -45
- prefect/task_engine.py +54 -75
- prefect/task_runners.py +56 -55
- prefect/task_worker.py +2 -2
- prefect/tasks.py +90 -36
- prefect/telemetry/bootstrap.py +10 -9
- prefect/telemetry/run_telemetry.py +13 -8
- prefect/telemetry/services.py +4 -0
- prefect/transactions.py +4 -15
- prefect/utilities/_git.py +34 -0
- prefect/utilities/asyncutils.py +1 -1
- prefect/utilities/engine.py +3 -19
- prefect/utilities/generics.py +18 -0
- prefect/utilities/templating.py +25 -1
- prefect/workers/base.py +6 -3
- prefect/workers/process.py +1 -1
- {prefect_client-3.1.10.dist-info → prefect_client-3.1.12.dist-info}/METADATA +2 -2
- {prefect_client-3.1.10.dist-info → prefect_client-3.1.12.dist-info}/RECORD +135 -109
- prefect/client/orchestration.py +0 -4523
- prefect/records/__init__.py +0 -1
- prefect/records/base.py +0 -235
- prefect/records/filesystem.py +0 -213
- prefect/records/memory.py +0 -184
- prefect/records/result_store.py +0 -70
- {prefect_client-3.1.10.dist-info → prefect_client-3.1.12.dist-info}/LICENSE +0 -0
- {prefect_client-3.1.10.dist-info → prefect_client-3.1.12.dist-info}/WHEEL +0 -0
- {prefect_client-3.1.10.dist-info → prefect_client-3.1.12.dist-info}/top_level.txt +0 -0
File without changes
|
@@ -0,0 +1,239 @@
|
|
1
|
+
from typing import TYPE_CHECKING, Annotated, Optional
|
2
|
+
|
3
|
+
from httpx import HTTPStatusError
|
4
|
+
from pydantic import Field
|
5
|
+
from typing_extensions import TypedDict, Unpack
|
6
|
+
|
7
|
+
from prefect.client.orchestration.base import BaseAsyncClient, BaseClient
|
8
|
+
from prefect.exceptions import ObjectNotFound
|
9
|
+
|
10
|
+
if TYPE_CHECKING:
|
11
|
+
from uuid import UUID
|
12
|
+
|
13
|
+
from prefect.client.schemas.actions import ArtifactCreate, ArtifactUpdate
|
14
|
+
from prefect.client.schemas.filters import (
|
15
|
+
ArtifactCollectionFilter,
|
16
|
+
ArtifactFilter,
|
17
|
+
FlowRunFilter,
|
18
|
+
TaskRunFilter,
|
19
|
+
)
|
20
|
+
from prefect.client.schemas.objects import Artifact, ArtifactCollection
|
21
|
+
from prefect.client.schemas.sorting import ArtifactCollectionSort, ArtifactSort
|
22
|
+
|
23
|
+
|
24
|
+
class BaseArtifactReadParams(TypedDict, total=False):
|
25
|
+
flow_run_filter: Annotated[Optional["FlowRunFilter"], Field(default=None)]
|
26
|
+
task_run_filter: Annotated[Optional["TaskRunFilter"], Field(default=None)]
|
27
|
+
limit: Annotated[Optional[int], Field(default=None)]
|
28
|
+
offset: Annotated[int, Field(default=0)]
|
29
|
+
|
30
|
+
|
31
|
+
class ArtifactReadParams(BaseArtifactReadParams, total=False):
|
32
|
+
artifact_filter: Annotated[Optional["ArtifactFilter"], Field(default=None)]
|
33
|
+
sort: Annotated[Optional["ArtifactSort"], Field(default=None)]
|
34
|
+
|
35
|
+
|
36
|
+
class ArtifactCollectionReadParams(BaseArtifactReadParams, total=False):
|
37
|
+
artifact_filter: Annotated[
|
38
|
+
Optional["ArtifactCollectionFilter"], Field(default=None)
|
39
|
+
]
|
40
|
+
sort: Annotated[Optional["ArtifactCollectionSort"], Field(default=None)]
|
41
|
+
|
42
|
+
|
43
|
+
class ArtifactClient(BaseClient):
|
44
|
+
def create_artifact(self, artifact: "ArtifactCreate") -> "Artifact":
|
45
|
+
response = self.request(
|
46
|
+
"POST",
|
47
|
+
"/artifacts/",
|
48
|
+
json=artifact.model_dump(mode="json", exclude_unset=True),
|
49
|
+
)
|
50
|
+
from prefect.client.schemas.objects import Artifact
|
51
|
+
|
52
|
+
return Artifact.model_validate(response.json())
|
53
|
+
|
54
|
+
def update_artifact(self, artifact_id: "UUID", artifact: "ArtifactUpdate") -> None:
|
55
|
+
self.request(
|
56
|
+
"PATCH",
|
57
|
+
"/artifacts/{id}",
|
58
|
+
json=artifact.model_dump(mode="json", exclude_unset=True),
|
59
|
+
path_params={"id": artifact_id},
|
60
|
+
)
|
61
|
+
return None
|
62
|
+
|
63
|
+
def delete_artifact(self, artifact_id: "UUID") -> None:
|
64
|
+
try:
|
65
|
+
self.request(
|
66
|
+
"DELETE",
|
67
|
+
"/artifacts/{id}",
|
68
|
+
path_params={"id": artifact_id},
|
69
|
+
)
|
70
|
+
except HTTPStatusError as e:
|
71
|
+
if e.response.status_code == 404:
|
72
|
+
raise ObjectNotFound(http_exc=e) from e
|
73
|
+
else:
|
74
|
+
raise
|
75
|
+
return None
|
76
|
+
|
77
|
+
def read_artifacts(
|
78
|
+
self, **kwargs: Unpack["ArtifactReadParams"]
|
79
|
+
) -> list["Artifact"]:
|
80
|
+
response = self.request(
|
81
|
+
"POST",
|
82
|
+
"/artifacts/filter",
|
83
|
+
json={
|
84
|
+
"artifacts": (
|
85
|
+
artifact_filter.model_dump(mode="json", exclude_unset=True)
|
86
|
+
if (artifact_filter := kwargs.get("artifact_filter"))
|
87
|
+
else None
|
88
|
+
),
|
89
|
+
"flow_runs": (
|
90
|
+
flow_run_filter.model_dump(mode="json", exclude_unset=True)
|
91
|
+
if (flow_run_filter := kwargs.get("flow_run_filter"))
|
92
|
+
else None
|
93
|
+
),
|
94
|
+
"task_runs": (
|
95
|
+
task_run_filter.model_dump(mode="json", exclude_unset=True)
|
96
|
+
if (task_run_filter := kwargs.get("task_run_filter"))
|
97
|
+
else None
|
98
|
+
),
|
99
|
+
"limit": kwargs.get("limit"),
|
100
|
+
"offset": kwargs.get("offset"),
|
101
|
+
"sort": kwargs.get("sort"),
|
102
|
+
},
|
103
|
+
)
|
104
|
+
from prefect.client.schemas.objects import Artifact
|
105
|
+
|
106
|
+
return Artifact.model_validate_list(response.json())
|
107
|
+
|
108
|
+
|
109
|
+
class ArtifactAsyncClient(BaseAsyncClient):
|
110
|
+
async def create_artifact(self, artifact: "ArtifactCreate") -> "Artifact":
|
111
|
+
response = await self.request(
|
112
|
+
"POST",
|
113
|
+
"/artifacts/",
|
114
|
+
json=artifact.model_dump(mode="json", exclude_unset=True),
|
115
|
+
)
|
116
|
+
from prefect.client.schemas.objects import Artifact
|
117
|
+
|
118
|
+
return Artifact.model_validate(response.json())
|
119
|
+
|
120
|
+
async def update_artifact(
|
121
|
+
self, artifact_id: "UUID", artifact: "ArtifactUpdate"
|
122
|
+
) -> None:
|
123
|
+
await self.request(
|
124
|
+
"PATCH",
|
125
|
+
"/artifacts/{id}",
|
126
|
+
path_params={"id": artifact_id},
|
127
|
+
json=artifact.model_dump(mode="json", exclude_unset=True),
|
128
|
+
)
|
129
|
+
return None
|
130
|
+
|
131
|
+
async def read_artifacts(
|
132
|
+
self, **kwargs: Unpack["ArtifactReadParams"]
|
133
|
+
) -> list["Artifact"]:
|
134
|
+
response = await self.request(
|
135
|
+
"POST",
|
136
|
+
"/artifacts/filter",
|
137
|
+
json={
|
138
|
+
"artifacts": (
|
139
|
+
artifact_filter.model_dump(mode="json", exclude_unset=True)
|
140
|
+
if (artifact_filter := kwargs.get("artifact_filter"))
|
141
|
+
else None
|
142
|
+
),
|
143
|
+
"flow_runs": (
|
144
|
+
flow_run_filter.model_dump(mode="json", exclude_unset=True)
|
145
|
+
if (flow_run_filter := kwargs.get("flow_run_filter"))
|
146
|
+
else None
|
147
|
+
),
|
148
|
+
"task_runs": (
|
149
|
+
task_run_filter.model_dump(mode="json", exclude_unset=True)
|
150
|
+
if (task_run_filter := kwargs.get("task_run_filter"))
|
151
|
+
else None
|
152
|
+
),
|
153
|
+
"limit": kwargs.get("limit", None),
|
154
|
+
"offset": kwargs.get("offset", 0),
|
155
|
+
"sort": kwargs.get("sort", None),
|
156
|
+
},
|
157
|
+
)
|
158
|
+
from prefect.client.schemas.objects import Artifact
|
159
|
+
|
160
|
+
return Artifact.model_validate_list(response.json())
|
161
|
+
|
162
|
+
async def delete_artifact(self, artifact_id: "UUID") -> None:
|
163
|
+
try:
|
164
|
+
await self.request(
|
165
|
+
"DELETE",
|
166
|
+
"/artifacts/{id}",
|
167
|
+
path_params={"id": artifact_id},
|
168
|
+
)
|
169
|
+
except HTTPStatusError as e:
|
170
|
+
if e.response.status_code == 404:
|
171
|
+
raise ObjectNotFound(http_exc=e) from e
|
172
|
+
else:
|
173
|
+
raise
|
174
|
+
|
175
|
+
|
176
|
+
class ArtifactCollectionClient(BaseClient):
|
177
|
+
def read_latest_artifacts(
|
178
|
+
self, **kwargs: Unpack["ArtifactCollectionReadParams"]
|
179
|
+
) -> list["ArtifactCollection"]:
|
180
|
+
response = self.request(
|
181
|
+
"POST",
|
182
|
+
"/artifacts/latest/filter",
|
183
|
+
json={
|
184
|
+
"artifacts": (
|
185
|
+
artifact_filter.model_dump(mode="json", exclude_unset=True)
|
186
|
+
if (artifact_filter := kwargs.get("artifact_filter"))
|
187
|
+
else None
|
188
|
+
),
|
189
|
+
"flow_runs": (
|
190
|
+
flow_run_filter.model_dump(mode="json", exclude_unset=True)
|
191
|
+
if (flow_run_filter := kwargs.get("flow_run_filter"))
|
192
|
+
else None
|
193
|
+
),
|
194
|
+
"task_runs": (
|
195
|
+
task_run_filter.model_dump(mode="json", exclude_unset=True)
|
196
|
+
if (task_run_filter := kwargs.get("task_run_filter"))
|
197
|
+
else None
|
198
|
+
),
|
199
|
+
"limit": kwargs.get("limit", None),
|
200
|
+
"offset": kwargs.get("offset", 0),
|
201
|
+
"sort": kwargs.get("sort", None),
|
202
|
+
},
|
203
|
+
)
|
204
|
+
from prefect.client.schemas.objects import ArtifactCollection
|
205
|
+
|
206
|
+
return ArtifactCollection.model_validate_list(response.json())
|
207
|
+
|
208
|
+
|
209
|
+
class ArtifactCollectionAsyncClient(BaseAsyncClient):
|
210
|
+
async def read_latest_artifacts(
|
211
|
+
self, **kwargs: Unpack["ArtifactCollectionReadParams"]
|
212
|
+
) -> list["ArtifactCollection"]:
|
213
|
+
response = await self.request(
|
214
|
+
"POST",
|
215
|
+
"/artifacts/latest/filter",
|
216
|
+
json={
|
217
|
+
"artifacts": (
|
218
|
+
artifact_filter.model_dump(mode="json", exclude_unset=True)
|
219
|
+
if (artifact_filter := kwargs.get("artifact_filter"))
|
220
|
+
else None
|
221
|
+
),
|
222
|
+
"flow_runs": (
|
223
|
+
flow_run_filter.model_dump(mode="json", exclude_unset=True)
|
224
|
+
if (flow_run_filter := kwargs.get("flow_run_filter"))
|
225
|
+
else None
|
226
|
+
),
|
227
|
+
"task_runs": (
|
228
|
+
task_run_filter.model_dump(mode="json", exclude_unset=True)
|
229
|
+
if (task_run_filter := kwargs.get("task_run_filter"))
|
230
|
+
else None
|
231
|
+
),
|
232
|
+
"limit": kwargs.get("limit", None),
|
233
|
+
"offset": kwargs.get("offset", 0),
|
234
|
+
"sort": kwargs.get("sort", None),
|
235
|
+
},
|
236
|
+
)
|
237
|
+
from prefect.client.schemas.objects import ArtifactCollection
|
238
|
+
|
239
|
+
return ArtifactCollection.model_validate_list(response.json())
|
File without changes
|
@@ -0,0 +1,329 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from typing import TYPE_CHECKING
|
4
|
+
|
5
|
+
from httpx import HTTPStatusError
|
6
|
+
|
7
|
+
from prefect.client.orchestration.base import BaseAsyncClient, BaseClient
|
8
|
+
from prefect.exceptions import ObjectNotFound
|
9
|
+
|
10
|
+
if TYPE_CHECKING:
|
11
|
+
from uuid import UUID
|
12
|
+
|
13
|
+
from prefect.events.schemas.automations import Automation, AutomationCore
|
14
|
+
|
15
|
+
|
16
|
+
class AutomationClient(BaseClient):
|
17
|
+
def create_automation(self, automation: "AutomationCore") -> "UUID":
|
18
|
+
"""Creates an automation in Prefect Cloud."""
|
19
|
+
response = self.request(
|
20
|
+
"POST",
|
21
|
+
"/automations/",
|
22
|
+
json=automation.model_dump(mode="json"),
|
23
|
+
)
|
24
|
+
from uuid import UUID
|
25
|
+
|
26
|
+
return UUID(response.json()["id"])
|
27
|
+
|
28
|
+
def update_automation(
|
29
|
+
self, automation_id: "UUID", automation: "AutomationCore"
|
30
|
+
) -> None:
|
31
|
+
"""Updates an automation in Prefect Cloud."""
|
32
|
+
response = self.request(
|
33
|
+
"PUT",
|
34
|
+
"/automations/{id}",
|
35
|
+
path_params={"id": automation_id},
|
36
|
+
json=automation.model_dump(mode="json", exclude_unset=True),
|
37
|
+
)
|
38
|
+
response.raise_for_status()
|
39
|
+
|
40
|
+
def read_automations(self) -> list["Automation"]:
|
41
|
+
response = self.request("POST", "/automations/filter")
|
42
|
+
response.raise_for_status()
|
43
|
+
from prefect.events.schemas.automations import Automation
|
44
|
+
|
45
|
+
return Automation.model_validate_list(response.json())
|
46
|
+
|
47
|
+
def find_automation(self, id_or_name: "str | UUID") -> "Automation | None":
|
48
|
+
if isinstance(id_or_name, str):
|
49
|
+
name = id_or_name
|
50
|
+
try:
|
51
|
+
id = UUID(id_or_name)
|
52
|
+
except ValueError:
|
53
|
+
id = None
|
54
|
+
else:
|
55
|
+
id = id_or_name
|
56
|
+
name = str(id)
|
57
|
+
|
58
|
+
if id:
|
59
|
+
try:
|
60
|
+
automation = self.read_automation(id)
|
61
|
+
return automation
|
62
|
+
except HTTPStatusError as e:
|
63
|
+
if e.response.status_code == 404:
|
64
|
+
raise ObjectNotFound(http_exc=e) from e
|
65
|
+
|
66
|
+
automations = self.read_automations()
|
67
|
+
|
68
|
+
# Look for it by an exact name
|
69
|
+
for automation in automations:
|
70
|
+
if automation.name == name:
|
71
|
+
return automation
|
72
|
+
|
73
|
+
# Look for it by a case-insensitive name
|
74
|
+
for automation in automations:
|
75
|
+
if automation.name.lower() == name.lower():
|
76
|
+
return automation
|
77
|
+
|
78
|
+
return None
|
79
|
+
|
80
|
+
def read_automation(self, automation_id: "UUID | str") -> "Automation | None":
|
81
|
+
response = self.request(
|
82
|
+
"GET", "/automations/{id}", path_params={"id": automation_id}
|
83
|
+
)
|
84
|
+
if response.status_code == 404:
|
85
|
+
return None
|
86
|
+
response.raise_for_status()
|
87
|
+
from prefect.events.schemas.automations import Automation
|
88
|
+
|
89
|
+
return Automation.model_validate(response.json())
|
90
|
+
|
91
|
+
def read_automations_by_name(self, name: str) -> list["Automation"]:
|
92
|
+
"""
|
93
|
+
Query the Prefect API for an automation by name. Only automations matching the provided name will be returned.
|
94
|
+
|
95
|
+
Args:
|
96
|
+
name: the name of the automation to query
|
97
|
+
|
98
|
+
Returns:
|
99
|
+
a list of Automation model representations of the automations
|
100
|
+
"""
|
101
|
+
from prefect.client.schemas.sorting import AutomationSort
|
102
|
+
from prefect.events.filters import (
|
103
|
+
AutomationFilter,
|
104
|
+
AutomationFilterName,
|
105
|
+
)
|
106
|
+
|
107
|
+
automation_filter = AutomationFilter(name=AutomationFilterName(any_=[name]))
|
108
|
+
|
109
|
+
response = self.request(
|
110
|
+
"POST",
|
111
|
+
"/automations/filter",
|
112
|
+
json={
|
113
|
+
"sort": AutomationSort.UPDATED_DESC,
|
114
|
+
"automations": automation_filter.model_dump(mode="json")
|
115
|
+
if automation_filter
|
116
|
+
else None,
|
117
|
+
},
|
118
|
+
)
|
119
|
+
|
120
|
+
response.raise_for_status()
|
121
|
+
from prefect.events.schemas.automations import Automation
|
122
|
+
|
123
|
+
return Automation.model_validate_list(response.json())
|
124
|
+
|
125
|
+
def pause_automation(self, automation_id: "UUID") -> None:
|
126
|
+
response = self.request(
|
127
|
+
"PATCH",
|
128
|
+
"/automations/{id}",
|
129
|
+
path_params={"id": automation_id},
|
130
|
+
json={"enabled": False},
|
131
|
+
)
|
132
|
+
response.raise_for_status()
|
133
|
+
|
134
|
+
def resume_automation(self, automation_id: "UUID") -> None:
|
135
|
+
response = self.request(
|
136
|
+
"PATCH",
|
137
|
+
"/automations/{id}",
|
138
|
+
path_params={"id": automation_id},
|
139
|
+
json={"enabled": True},
|
140
|
+
)
|
141
|
+
response.raise_for_status()
|
142
|
+
|
143
|
+
def delete_automation(self, automation_id: "UUID") -> None:
|
144
|
+
response = self.request(
|
145
|
+
"DELETE",
|
146
|
+
"/automations/{id}",
|
147
|
+
path_params={"id": automation_id},
|
148
|
+
)
|
149
|
+
if response.status_code == 404:
|
150
|
+
return
|
151
|
+
|
152
|
+
response.raise_for_status()
|
153
|
+
|
154
|
+
def read_resource_related_automations(self, resource_id: str) -> list["Automation"]:
|
155
|
+
response = self.request(
|
156
|
+
"GET",
|
157
|
+
"/automations/related-to/{resource_id}",
|
158
|
+
path_params={"resource_id": resource_id},
|
159
|
+
)
|
160
|
+
response.raise_for_status()
|
161
|
+
from prefect.events.schemas.automations import Automation
|
162
|
+
|
163
|
+
return Automation.model_validate_list(response.json())
|
164
|
+
|
165
|
+
def delete_resource_owned_automations(self, resource_id: str) -> None:
|
166
|
+
self.request(
|
167
|
+
"DELETE",
|
168
|
+
"/automations/owned-by/{resource_id}",
|
169
|
+
path_params={"resource_id": resource_id},
|
170
|
+
)
|
171
|
+
|
172
|
+
|
173
|
+
class AutomationAsyncClient(BaseAsyncClient):
|
174
|
+
async def create_automation(self, automation: "AutomationCore") -> "UUID":
|
175
|
+
"""Creates an automation in Prefect Cloud."""
|
176
|
+
response = await self.request(
|
177
|
+
"POST",
|
178
|
+
"/automations/",
|
179
|
+
json=automation.model_dump(mode="json"),
|
180
|
+
)
|
181
|
+
from uuid import UUID
|
182
|
+
|
183
|
+
return UUID(response.json()["id"])
|
184
|
+
|
185
|
+
async def update_automation(
|
186
|
+
self, automation_id: "UUID", automation: "AutomationCore"
|
187
|
+
) -> None:
|
188
|
+
"""Updates an automation in Prefect Cloud."""
|
189
|
+
response = await self.request(
|
190
|
+
"PUT",
|
191
|
+
"/automations/{id}",
|
192
|
+
path_params={"id": automation_id},
|
193
|
+
json=automation.model_dump(mode="json", exclude_unset=True),
|
194
|
+
)
|
195
|
+
response.raise_for_status()
|
196
|
+
|
197
|
+
async def read_automations(self) -> list["Automation"]:
|
198
|
+
response = await self.request("POST", "/automations/filter")
|
199
|
+
response.raise_for_status()
|
200
|
+
from prefect.events.schemas.automations import Automation
|
201
|
+
|
202
|
+
return Automation.model_validate_list(response.json())
|
203
|
+
|
204
|
+
async def find_automation(self, id_or_name: "str | UUID") -> "Automation | None":
|
205
|
+
if isinstance(id_or_name, str):
|
206
|
+
name = id_or_name
|
207
|
+
try:
|
208
|
+
id = UUID(id_or_name)
|
209
|
+
except ValueError:
|
210
|
+
id = None
|
211
|
+
else:
|
212
|
+
id = id_or_name
|
213
|
+
name = str(id)
|
214
|
+
|
215
|
+
if id:
|
216
|
+
try:
|
217
|
+
automation = await self.read_automation(id)
|
218
|
+
return automation
|
219
|
+
except HTTPStatusError as e:
|
220
|
+
if e.response.status_code == 404:
|
221
|
+
raise ObjectNotFound(http_exc=e) from e
|
222
|
+
|
223
|
+
automations = await self.read_automations()
|
224
|
+
|
225
|
+
# Look for it by an exact name
|
226
|
+
for automation in automations:
|
227
|
+
if automation.name == name:
|
228
|
+
return automation
|
229
|
+
|
230
|
+
# Look for it by a case-insensitive name
|
231
|
+
for automation in automations:
|
232
|
+
if automation.name.lower() == name.lower():
|
233
|
+
return automation
|
234
|
+
|
235
|
+
return None
|
236
|
+
|
237
|
+
async def read_automation(self, automation_id: "UUID | str") -> "Automation | None":
|
238
|
+
response = await self.request(
|
239
|
+
"GET", "/automations/{id}", path_params={"id": automation_id}
|
240
|
+
)
|
241
|
+
if response.status_code == 404:
|
242
|
+
return None
|
243
|
+
response.raise_for_status()
|
244
|
+
from prefect.events.schemas.automations import Automation
|
245
|
+
|
246
|
+
return Automation.model_validate(response.json())
|
247
|
+
|
248
|
+
async def read_automations_by_name(self, name: str) -> list["Automation"]:
|
249
|
+
"""
|
250
|
+
Query the Prefect API for an automation by name. Only automations matching the provided name will be returned.
|
251
|
+
|
252
|
+
Args:
|
253
|
+
name: the name of the automation to query
|
254
|
+
|
255
|
+
Returns:
|
256
|
+
a list of Automation model representations of the automations
|
257
|
+
"""
|
258
|
+
from prefect.client.schemas.sorting import AutomationSort
|
259
|
+
from prefect.events.filters import (
|
260
|
+
AutomationFilter,
|
261
|
+
AutomationFilterName,
|
262
|
+
)
|
263
|
+
|
264
|
+
automation_filter = AutomationFilter(name=AutomationFilterName(any_=[name]))
|
265
|
+
|
266
|
+
response = await self.request(
|
267
|
+
"POST",
|
268
|
+
"/automations/filter",
|
269
|
+
json={
|
270
|
+
"sort": AutomationSort.UPDATED_DESC,
|
271
|
+
"automations": automation_filter.model_dump(mode="json")
|
272
|
+
if automation_filter
|
273
|
+
else None,
|
274
|
+
},
|
275
|
+
)
|
276
|
+
|
277
|
+
response.raise_for_status()
|
278
|
+
from prefect.events.schemas.automations import Automation
|
279
|
+
|
280
|
+
return Automation.model_validate_list(response.json())
|
281
|
+
|
282
|
+
async def pause_automation(self, automation_id: "UUID") -> None:
|
283
|
+
response = await self.request(
|
284
|
+
"PATCH",
|
285
|
+
"/automations/{id}",
|
286
|
+
path_params={"id": automation_id},
|
287
|
+
json={"enabled": False},
|
288
|
+
)
|
289
|
+
response.raise_for_status()
|
290
|
+
|
291
|
+
async def resume_automation(self, automation_id: "UUID") -> None:
|
292
|
+
response = await self.request(
|
293
|
+
"PATCH",
|
294
|
+
"/automations/{id}",
|
295
|
+
path_params={"id": automation_id},
|
296
|
+
json={"enabled": True},
|
297
|
+
)
|
298
|
+
response.raise_for_status()
|
299
|
+
|
300
|
+
async def delete_automation(self, automation_id: "UUID") -> None:
|
301
|
+
response = await self.request(
|
302
|
+
"DELETE",
|
303
|
+
"/automations/{id}",
|
304
|
+
path_params={"id": automation_id},
|
305
|
+
)
|
306
|
+
if response.status_code == 404:
|
307
|
+
return
|
308
|
+
|
309
|
+
response.raise_for_status()
|
310
|
+
|
311
|
+
async def read_resource_related_automations(
|
312
|
+
self, resource_id: str
|
313
|
+
) -> list["Automation"]:
|
314
|
+
response = await self.request(
|
315
|
+
"GET",
|
316
|
+
"/automations/related-to/{resource_id}",
|
317
|
+
path_params={"resource_id": resource_id},
|
318
|
+
)
|
319
|
+
response.raise_for_status()
|
320
|
+
from prefect.events.schemas.automations import Automation
|
321
|
+
|
322
|
+
return Automation.model_validate_list(response.json())
|
323
|
+
|
324
|
+
async def delete_resource_owned_automations(self, resource_id: str) -> None:
|
325
|
+
await self.request(
|
326
|
+
"DELETE",
|
327
|
+
"/automations/owned-by/{resource_id}",
|
328
|
+
path_params={"resource_id": resource_id},
|
329
|
+
)
|
File without changes
|