prefect-client 3.1.9__py3-none-any.whl → 3.1.11__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/_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/artifacts.py +61 -74
- prefect/automations.py +27 -7
- prefect/blocks/core.py +3 -3
- prefect/client/{orchestration.py → orchestration/__init__.py} +38 -701
- prefect/client/orchestration/_artifacts/__init__.py +0 -0
- prefect/client/orchestration/_artifacts/client.py +239 -0
- prefect/client/orchestration/_concurrency_limits/__init__.py +0 -0
- prefect/client/orchestration/_concurrency_limits/client.py +762 -0
- prefect/client/orchestration/_logs/__init__.py +0 -0
- prefect/client/orchestration/_logs/client.py +95 -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/actions.py +2 -2
- prefect/client/schemas/filters.py +5 -0
- prefect/client/schemas/objects.py +3 -10
- 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 -70
- prefect/deployments/base.py +4 -144
- prefect/deployments/flow_runs.py +12 -2
- prefect/deployments/runner.py +11 -3
- prefect/deployments/steps/pull.py +13 -0
- prefect/events/clients.py +7 -1
- prefect/events/schemas/events.py +3 -2
- prefect/flow_engine.py +54 -47
- prefect/flows.py +2 -1
- prefect/futures.py +42 -27
- prefect/input/run_input.py +2 -1
- prefect/locking/filesystem.py +8 -7
- prefect/locking/memory.py +5 -3
- prefect/locking/protocol.py +1 -1
- prefect/main.py +1 -3
- prefect/plugins.py +12 -10
- prefect/results.py +3 -308
- 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 +3 -3
- prefect/settings/models/deployments.py +3 -3
- prefect/settings/models/experiments.py +4 -2
- 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 +4 -7
- prefect/task_engine.py +54 -75
- prefect/tasks.py +84 -32
- prefect/telemetry/processors.py +6 -6
- prefect/telemetry/run_telemetry.py +13 -8
- prefect/telemetry/services.py +32 -31
- 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/workers/__init__.py +2 -0
- {prefect_client-3.1.9.dist-info → prefect_client-3.1.11.dist-info}/METADATA +1 -1
- {prefect_client-3.1.9.dist-info → prefect_client-3.1.11.dist-info}/RECORD +108 -99
- 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.9.dist-info → prefect_client-3.1.11.dist-info}/LICENSE +0 -0
- {prefect_client-3.1.9.dist-info → prefect_client-3.1.11.dist-info}/WHEEL +0 -0
- {prefect_client-3.1.9.dist-info → prefect_client-3.1.11.dist-info}/top_level.txt +0 -0
@@ -19,6 +19,27 @@ from packaging import version
|
|
19
19
|
from starlette import status
|
20
20
|
from typing_extensions import ParamSpec, Self, TypeVar
|
21
21
|
|
22
|
+
from prefect.client.orchestration._artifacts.client import (
|
23
|
+
ArtifactClient,
|
24
|
+
ArtifactAsyncClient,
|
25
|
+
ArtifactCollectionClient,
|
26
|
+
ArtifactCollectionAsyncClient,
|
27
|
+
)
|
28
|
+
|
29
|
+
from prefect.client.orchestration._concurrency_limits.client import (
|
30
|
+
ConcurrencyLimitAsyncClient,
|
31
|
+
ConcurrencyLimitClient,
|
32
|
+
)
|
33
|
+
|
34
|
+
from prefect.client.orchestration._logs.client import (
|
35
|
+
LogClient,
|
36
|
+
LogAsyncClient,
|
37
|
+
)
|
38
|
+
from prefect.client.orchestration._variables.client import (
|
39
|
+
VariableClient,
|
40
|
+
VariableAsyncClient,
|
41
|
+
)
|
42
|
+
|
22
43
|
import prefect
|
23
44
|
import prefect.exceptions
|
24
45
|
import prefect.settings
|
@@ -26,14 +47,11 @@ import prefect.states
|
|
26
47
|
from prefect.client.constants import SERVER_API_VERSION
|
27
48
|
from prefect.client.schemas import FlowRun, OrchestrationResult, TaskRun, sorting
|
28
49
|
from prefect.client.schemas.actions import (
|
29
|
-
ArtifactCreate,
|
30
|
-
ArtifactUpdate,
|
31
50
|
BlockDocumentCreate,
|
32
51
|
BlockDocumentUpdate,
|
33
52
|
BlockSchemaCreate,
|
34
53
|
BlockTypeCreate,
|
35
54
|
BlockTypeUpdate,
|
36
|
-
ConcurrencyLimitCreate,
|
37
55
|
DeploymentCreate,
|
38
56
|
DeploymentFlowRunCreate,
|
39
57
|
DeploymentScheduleCreate,
|
@@ -44,26 +62,21 @@ from prefect.client.schemas.actions import (
|
|
44
62
|
FlowRunNotificationPolicyCreate,
|
45
63
|
FlowRunNotificationPolicyUpdate,
|
46
64
|
FlowRunUpdate,
|
65
|
+
LogCreate,
|
47
66
|
GlobalConcurrencyLimitCreate,
|
48
67
|
GlobalConcurrencyLimitUpdate,
|
49
|
-
LogCreate,
|
50
68
|
TaskRunCreate,
|
51
69
|
TaskRunUpdate,
|
52
|
-
VariableCreate,
|
53
|
-
VariableUpdate,
|
54
70
|
WorkPoolCreate,
|
55
71
|
WorkPoolUpdate,
|
56
72
|
WorkQueueCreate,
|
57
73
|
WorkQueueUpdate,
|
58
74
|
)
|
59
75
|
from prefect.client.schemas.filters import (
|
60
|
-
ArtifactCollectionFilter,
|
61
|
-
ArtifactFilter,
|
62
76
|
DeploymentFilter,
|
63
77
|
FlowFilter,
|
64
78
|
FlowRunFilter,
|
65
79
|
FlowRunNotificationPolicyFilter,
|
66
|
-
LogFilter,
|
67
80
|
TaskRunFilter,
|
68
81
|
WorkerFilter,
|
69
82
|
WorkPoolFilter,
|
@@ -71,12 +84,9 @@ from prefect.client.schemas.filters import (
|
|
71
84
|
WorkQueueFilterName,
|
72
85
|
)
|
73
86
|
from prefect.client.schemas.objects import (
|
74
|
-
Artifact,
|
75
|
-
ArtifactCollection,
|
76
87
|
BlockDocument,
|
77
88
|
BlockSchema,
|
78
89
|
BlockType,
|
79
|
-
ConcurrencyLimit,
|
80
90
|
ConcurrencyOptions,
|
81
91
|
Constant,
|
82
92
|
DeploymentSchedule,
|
@@ -84,11 +94,9 @@ from prefect.client.schemas.objects import (
|
|
84
94
|
FlowRunInput,
|
85
95
|
FlowRunNotificationPolicy,
|
86
96
|
FlowRunPolicy,
|
87
|
-
Log,
|
88
97
|
Parameter,
|
89
98
|
TaskRunPolicy,
|
90
99
|
TaskRunResult,
|
91
|
-
Variable,
|
92
100
|
Worker,
|
93
101
|
WorkerMetadata,
|
94
102
|
WorkPool,
|
@@ -98,17 +106,13 @@ from prefect.client.schemas.objects import (
|
|
98
106
|
from prefect.client.schemas.responses import (
|
99
107
|
DeploymentResponse,
|
100
108
|
FlowRunResponse,
|
101
|
-
GlobalConcurrencyLimitResponse,
|
102
109
|
WorkerFlowRunResponse,
|
103
110
|
)
|
104
111
|
from prefect.client.schemas.schedules import SCHEDULE_TYPES
|
105
112
|
from prefect.client.schemas.sorting import (
|
106
|
-
ArtifactCollectionSort,
|
107
|
-
ArtifactSort,
|
108
113
|
DeploymentSort,
|
109
114
|
FlowRunSort,
|
110
115
|
FlowSort,
|
111
|
-
LogSort,
|
112
116
|
TaskRunSort,
|
113
117
|
)
|
114
118
|
from prefect.events import filters
|
@@ -245,7 +249,13 @@ def get_client(
|
|
245
249
|
)
|
246
250
|
|
247
251
|
|
248
|
-
class PrefectClient
|
252
|
+
class PrefectClient(
|
253
|
+
ArtifactAsyncClient,
|
254
|
+
ArtifactCollectionAsyncClient,
|
255
|
+
LogAsyncClient,
|
256
|
+
VariableAsyncClient,
|
257
|
+
ConcurrencyLimitAsyncClient,
|
258
|
+
):
|
249
259
|
"""
|
250
260
|
An asynchronous client for interacting with the [Prefect REST API](/api-ref/rest-api/).
|
251
261
|
|
@@ -615,6 +625,7 @@ class PrefectClient:
|
|
615
625
|
parent_task_run_id: Optional[UUID] = None,
|
616
626
|
work_queue_name: Optional[str] = None,
|
617
627
|
job_variables: Optional[dict[str, Any]] = None,
|
628
|
+
labels: Optional[KeyValueLabelsField] = None,
|
618
629
|
) -> FlowRun:
|
619
630
|
"""
|
620
631
|
Create a flow run for a deployment.
|
@@ -660,6 +671,7 @@ class PrefectClient:
|
|
660
671
|
idempotency_key=idempotency_key,
|
661
672
|
parent_task_run_id=parent_task_run_id,
|
662
673
|
job_variables=job_variables,
|
674
|
+
labels=labels,
|
663
675
|
)
|
664
676
|
|
665
677
|
# done separately to avoid including this field in payloads sent to older API versions
|
@@ -810,213 +822,6 @@ class PrefectClient:
|
|
810
822
|
else:
|
811
823
|
raise
|
812
824
|
|
813
|
-
async def create_concurrency_limit(
|
814
|
-
self,
|
815
|
-
tag: str,
|
816
|
-
concurrency_limit: int,
|
817
|
-
) -> UUID:
|
818
|
-
"""
|
819
|
-
Create a tag concurrency limit in the Prefect API. These limits govern concurrently
|
820
|
-
running tasks.
|
821
|
-
|
822
|
-
Args:
|
823
|
-
tag: a tag the concurrency limit is applied to
|
824
|
-
concurrency_limit: the maximum number of concurrent task runs for a given tag
|
825
|
-
|
826
|
-
Raises:
|
827
|
-
httpx.RequestError: if the concurrency limit was not created for any reason
|
828
|
-
|
829
|
-
Returns:
|
830
|
-
the ID of the concurrency limit in the backend
|
831
|
-
"""
|
832
|
-
|
833
|
-
concurrency_limit_create = ConcurrencyLimitCreate(
|
834
|
-
tag=tag,
|
835
|
-
concurrency_limit=concurrency_limit,
|
836
|
-
)
|
837
|
-
response = await self._client.post(
|
838
|
-
"/concurrency_limits/",
|
839
|
-
json=concurrency_limit_create.model_dump(mode="json"),
|
840
|
-
)
|
841
|
-
|
842
|
-
concurrency_limit_id = response.json().get("id")
|
843
|
-
|
844
|
-
if not concurrency_limit_id:
|
845
|
-
raise httpx.RequestError(f"Malformed response: {response}")
|
846
|
-
|
847
|
-
return UUID(concurrency_limit_id)
|
848
|
-
|
849
|
-
async def read_concurrency_limit_by_tag(
|
850
|
-
self,
|
851
|
-
tag: str,
|
852
|
-
) -> ConcurrencyLimit:
|
853
|
-
"""
|
854
|
-
Read the concurrency limit set on a specific tag.
|
855
|
-
|
856
|
-
Args:
|
857
|
-
tag: a tag the concurrency limit is applied to
|
858
|
-
|
859
|
-
Raises:
|
860
|
-
prefect.exceptions.ObjectNotFound: If request returns 404
|
861
|
-
httpx.RequestError: if the concurrency limit was not created for any reason
|
862
|
-
|
863
|
-
Returns:
|
864
|
-
the concurrency limit set on a specific tag
|
865
|
-
"""
|
866
|
-
try:
|
867
|
-
response = await self._client.get(
|
868
|
-
f"/concurrency_limits/tag/{tag}",
|
869
|
-
)
|
870
|
-
except httpx.HTTPStatusError as e:
|
871
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
872
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
873
|
-
else:
|
874
|
-
raise
|
875
|
-
|
876
|
-
concurrency_limit_id = response.json().get("id")
|
877
|
-
|
878
|
-
if not concurrency_limit_id:
|
879
|
-
raise httpx.RequestError(f"Malformed response: {response}")
|
880
|
-
|
881
|
-
concurrency_limit = ConcurrencyLimit.model_validate(response.json())
|
882
|
-
return concurrency_limit
|
883
|
-
|
884
|
-
async def read_concurrency_limits(
|
885
|
-
self,
|
886
|
-
limit: int,
|
887
|
-
offset: int,
|
888
|
-
) -> list[ConcurrencyLimit]:
|
889
|
-
"""
|
890
|
-
Lists concurrency limits set on task run tags.
|
891
|
-
|
892
|
-
Args:
|
893
|
-
limit: the maximum number of concurrency limits returned
|
894
|
-
offset: the concurrency limit query offset
|
895
|
-
|
896
|
-
Returns:
|
897
|
-
a list of concurrency limits
|
898
|
-
"""
|
899
|
-
|
900
|
-
body = {
|
901
|
-
"limit": limit,
|
902
|
-
"offset": offset,
|
903
|
-
}
|
904
|
-
|
905
|
-
response = await self._client.post("/concurrency_limits/filter", json=body)
|
906
|
-
return pydantic.TypeAdapter(list[ConcurrencyLimit]).validate_python(
|
907
|
-
response.json()
|
908
|
-
)
|
909
|
-
|
910
|
-
async def reset_concurrency_limit_by_tag(
|
911
|
-
self,
|
912
|
-
tag: str,
|
913
|
-
slot_override: Optional[list[Union[UUID, str]]] = None,
|
914
|
-
) -> None:
|
915
|
-
"""
|
916
|
-
Resets the concurrency limit slots set on a specific tag.
|
917
|
-
|
918
|
-
Args:
|
919
|
-
tag: a tag the concurrency limit is applied to
|
920
|
-
slot_override: a list of task run IDs that are currently using a
|
921
|
-
concurrency slot, please check that any task run IDs included in
|
922
|
-
`slot_override` are currently running, otherwise those concurrency
|
923
|
-
slots will never be released.
|
924
|
-
|
925
|
-
Raises:
|
926
|
-
prefect.exceptions.ObjectNotFound: If request returns 404
|
927
|
-
httpx.RequestError: If request fails
|
928
|
-
|
929
|
-
"""
|
930
|
-
if slot_override is not None:
|
931
|
-
slot_override = [str(slot) for slot in slot_override]
|
932
|
-
|
933
|
-
try:
|
934
|
-
await self._client.post(
|
935
|
-
f"/concurrency_limits/tag/{tag}/reset",
|
936
|
-
json=dict(slot_override=slot_override),
|
937
|
-
)
|
938
|
-
except httpx.HTTPStatusError as e:
|
939
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
940
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
941
|
-
else:
|
942
|
-
raise
|
943
|
-
|
944
|
-
async def delete_concurrency_limit_by_tag(
|
945
|
-
self,
|
946
|
-
tag: str,
|
947
|
-
) -> None:
|
948
|
-
"""
|
949
|
-
Delete the concurrency limit set on a specific tag.
|
950
|
-
|
951
|
-
Args:
|
952
|
-
tag: a tag the concurrency limit is applied to
|
953
|
-
|
954
|
-
Raises:
|
955
|
-
prefect.exceptions.ObjectNotFound: If request returns 404
|
956
|
-
httpx.RequestError: If request fails
|
957
|
-
|
958
|
-
"""
|
959
|
-
try:
|
960
|
-
await self._client.delete(
|
961
|
-
f"/concurrency_limits/tag/{tag}",
|
962
|
-
)
|
963
|
-
except httpx.HTTPStatusError as e:
|
964
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
965
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
966
|
-
else:
|
967
|
-
raise
|
968
|
-
|
969
|
-
async def increment_v1_concurrency_slots(
|
970
|
-
self,
|
971
|
-
names: list[str],
|
972
|
-
task_run_id: UUID,
|
973
|
-
) -> httpx.Response:
|
974
|
-
"""
|
975
|
-
Increment concurrency limit slots for the specified limits.
|
976
|
-
|
977
|
-
Args:
|
978
|
-
names (List[str]): A list of limit names for which to increment limits.
|
979
|
-
task_run_id (UUID): The task run ID incrementing the limits.
|
980
|
-
"""
|
981
|
-
data: dict[str, Any] = {
|
982
|
-
"names": names,
|
983
|
-
"task_run_id": str(task_run_id),
|
984
|
-
}
|
985
|
-
|
986
|
-
return await self._client.post(
|
987
|
-
"/concurrency_limits/increment",
|
988
|
-
json=data,
|
989
|
-
)
|
990
|
-
|
991
|
-
async def decrement_v1_concurrency_slots(
|
992
|
-
self,
|
993
|
-
names: list[str],
|
994
|
-
task_run_id: UUID,
|
995
|
-
occupancy_seconds: float,
|
996
|
-
) -> httpx.Response:
|
997
|
-
"""
|
998
|
-
Decrement concurrency limit slots for the specified limits.
|
999
|
-
|
1000
|
-
Args:
|
1001
|
-
names (List[str]): A list of limit names to decrement.
|
1002
|
-
task_run_id (UUID): The task run ID that incremented the limits.
|
1003
|
-
occupancy_seconds (float): The duration in seconds that the limits
|
1004
|
-
were held.
|
1005
|
-
|
1006
|
-
Returns:
|
1007
|
-
httpx.Response: The HTTP response from the server.
|
1008
|
-
"""
|
1009
|
-
data: dict[str, Any] = {
|
1010
|
-
"names": names,
|
1011
|
-
"task_run_id": str(task_run_id),
|
1012
|
-
"occupancy_seconds": occupancy_seconds,
|
1013
|
-
}
|
1014
|
-
|
1015
|
-
return await self._client.post(
|
1016
|
-
"/concurrency_limits/decrement",
|
1017
|
-
json=data,
|
1018
|
-
)
|
1019
|
-
|
1020
825
|
async def create_work_queue(
|
1021
826
|
self,
|
1022
827
|
name: str,
|
@@ -2463,21 +2268,6 @@ class PrefectClient:
|
|
2463
2268
|
response.json()
|
2464
2269
|
)
|
2465
2270
|
|
2466
|
-
async def create_logs(
|
2467
|
-
self, logs: Iterable[Union[LogCreate, dict[str, Any]]]
|
2468
|
-
) -> None:
|
2469
|
-
"""
|
2470
|
-
Create logs for a flow or task run
|
2471
|
-
|
2472
|
-
Args:
|
2473
|
-
logs: An iterable of `LogCreate` objects or already json-compatible dicts
|
2474
|
-
"""
|
2475
|
-
serialized_logs = [
|
2476
|
-
log.model_dump(mode="json") if isinstance(log, LogCreate) else log
|
2477
|
-
for log in logs
|
2478
|
-
]
|
2479
|
-
await self._client.post("/logs/", json=serialized_logs)
|
2480
|
-
|
2481
2271
|
async def create_flow_run_notification_policy(
|
2482
2272
|
self,
|
2483
2273
|
block_document_id: UUID,
|
@@ -2623,26 +2413,6 @@ class PrefectClient:
|
|
2623
2413
|
response.json()
|
2624
2414
|
)
|
2625
2415
|
|
2626
|
-
async def read_logs(
|
2627
|
-
self,
|
2628
|
-
log_filter: Optional[LogFilter] = None,
|
2629
|
-
limit: Optional[int] = None,
|
2630
|
-
offset: Optional[int] = None,
|
2631
|
-
sort: LogSort = LogSort.TIMESTAMP_ASC,
|
2632
|
-
) -> list[Log]:
|
2633
|
-
"""
|
2634
|
-
Read flow and task run logs.
|
2635
|
-
"""
|
2636
|
-
body: dict[str, Any] = {
|
2637
|
-
"logs": log_filter.model_dump(mode="json") if log_filter else None,
|
2638
|
-
"limit": limit,
|
2639
|
-
"offset": offset,
|
2640
|
-
"sort": sort,
|
2641
|
-
}
|
2642
|
-
|
2643
|
-
response = await self._client.post("/logs/filter", json=body)
|
2644
|
-
return pydantic.TypeAdapter(list[Log]).validate_python(response.json())
|
2645
|
-
|
2646
2416
|
async def send_worker_heartbeat(
|
2647
2417
|
self,
|
2648
2418
|
work_pool_name: str,
|
@@ -2952,333 +2722,12 @@ class PrefectClient:
|
|
2952
2722
|
response.json()
|
2953
2723
|
)
|
2954
2724
|
|
2955
|
-
async def create_artifact(
|
2956
|
-
self,
|
2957
|
-
artifact: ArtifactCreate,
|
2958
|
-
) -> Artifact:
|
2959
|
-
"""
|
2960
|
-
Creates an artifact with the provided configuration.
|
2961
|
-
|
2962
|
-
Args:
|
2963
|
-
artifact: Desired configuration for the new artifact.
|
2964
|
-
Returns:
|
2965
|
-
Information about the newly created artifact.
|
2966
|
-
"""
|
2967
|
-
|
2968
|
-
response = await self._client.post(
|
2969
|
-
"/artifacts/",
|
2970
|
-
json=artifact.model_dump(mode="json", exclude_unset=True),
|
2971
|
-
)
|
2972
|
-
|
2973
|
-
return Artifact.model_validate(response.json())
|
2974
|
-
|
2975
|
-
async def update_artifact(
|
2976
|
-
self,
|
2977
|
-
artifact_id: UUID,
|
2978
|
-
artifact: ArtifactUpdate,
|
2979
|
-
) -> None:
|
2980
|
-
"""
|
2981
|
-
Updates an artifact
|
2982
|
-
|
2983
|
-
Args:
|
2984
|
-
artifact: Desired values for the updated artifact.
|
2985
|
-
Returns:
|
2986
|
-
Information about the updated artifact.
|
2987
|
-
"""
|
2988
|
-
|
2989
|
-
await self._client.patch(
|
2990
|
-
f"/artifacts/{artifact_id}",
|
2991
|
-
json=artifact.model_dump(mode="json", exclude_unset=True),
|
2992
|
-
)
|
2993
|
-
|
2994
|
-
async def read_artifacts(
|
2995
|
-
self,
|
2996
|
-
*,
|
2997
|
-
artifact_filter: Optional[ArtifactFilter] = None,
|
2998
|
-
flow_run_filter: Optional[FlowRunFilter] = None,
|
2999
|
-
task_run_filter: Optional[TaskRunFilter] = None,
|
3000
|
-
sort: Optional[ArtifactSort] = None,
|
3001
|
-
limit: Optional[int] = None,
|
3002
|
-
offset: int = 0,
|
3003
|
-
) -> list[Artifact]:
|
3004
|
-
"""
|
3005
|
-
Query the Prefect API for artifacts. Only artifacts matching all criteria will
|
3006
|
-
be returned.
|
3007
|
-
Args:
|
3008
|
-
artifact_filter: filter criteria for artifacts
|
3009
|
-
flow_run_filter: filter criteria for flow runs
|
3010
|
-
task_run_filter: filter criteria for task runs
|
3011
|
-
sort: sort criteria for the artifacts
|
3012
|
-
limit: limit for the artifact query
|
3013
|
-
offset: offset for the artifact query
|
3014
|
-
Returns:
|
3015
|
-
a list of Artifact model representations of the artifacts
|
3016
|
-
"""
|
3017
|
-
body: dict[str, Any] = {
|
3018
|
-
"artifacts": (
|
3019
|
-
artifact_filter.model_dump(mode="json") if artifact_filter else None
|
3020
|
-
),
|
3021
|
-
"flow_runs": (
|
3022
|
-
flow_run_filter.model_dump(mode="json") if flow_run_filter else None
|
3023
|
-
),
|
3024
|
-
"task_runs": (
|
3025
|
-
task_run_filter.model_dump(mode="json") if task_run_filter else None
|
3026
|
-
),
|
3027
|
-
"sort": sort,
|
3028
|
-
"limit": limit,
|
3029
|
-
"offset": offset,
|
3030
|
-
}
|
3031
|
-
response = await self._client.post("/artifacts/filter", json=body)
|
3032
|
-
return pydantic.TypeAdapter(list[Artifact]).validate_python(response.json())
|
3033
|
-
|
3034
|
-
async def read_latest_artifacts(
|
3035
|
-
self,
|
3036
|
-
*,
|
3037
|
-
artifact_filter: Optional[ArtifactCollectionFilter] = None,
|
3038
|
-
flow_run_filter: Optional[FlowRunFilter] = None,
|
3039
|
-
task_run_filter: Optional[TaskRunFilter] = None,
|
3040
|
-
sort: Optional[ArtifactCollectionSort] = None,
|
3041
|
-
limit: Optional[int] = None,
|
3042
|
-
offset: int = 0,
|
3043
|
-
) -> list[ArtifactCollection]:
|
3044
|
-
"""
|
3045
|
-
Query the Prefect API for artifacts. Only artifacts matching all criteria will
|
3046
|
-
be returned.
|
3047
|
-
Args:
|
3048
|
-
artifact_filter: filter criteria for artifacts
|
3049
|
-
flow_run_filter: filter criteria for flow runs
|
3050
|
-
task_run_filter: filter criteria for task runs
|
3051
|
-
sort: sort criteria for the artifacts
|
3052
|
-
limit: limit for the artifact query
|
3053
|
-
offset: offset for the artifact query
|
3054
|
-
Returns:
|
3055
|
-
a list of Artifact model representations of the artifacts
|
3056
|
-
"""
|
3057
|
-
body: dict[str, Any] = {
|
3058
|
-
"artifacts": (
|
3059
|
-
artifact_filter.model_dump(mode="json") if artifact_filter else None
|
3060
|
-
),
|
3061
|
-
"flow_runs": (
|
3062
|
-
flow_run_filter.model_dump(mode="json") if flow_run_filter else None
|
3063
|
-
),
|
3064
|
-
"task_runs": (
|
3065
|
-
task_run_filter.model_dump(mode="json") if task_run_filter else None
|
3066
|
-
),
|
3067
|
-
"sort": sort,
|
3068
|
-
"limit": limit,
|
3069
|
-
"offset": offset,
|
3070
|
-
}
|
3071
|
-
response = await self._client.post("/artifacts/latest/filter", json=body)
|
3072
|
-
return pydantic.TypeAdapter(list[ArtifactCollection]).validate_python(
|
3073
|
-
response.json()
|
3074
|
-
)
|
3075
|
-
|
3076
|
-
async def delete_artifact(self, artifact_id: UUID) -> None:
|
3077
|
-
"""
|
3078
|
-
Deletes an artifact with the provided id.
|
3079
|
-
|
3080
|
-
Args:
|
3081
|
-
artifact_id: The id of the artifact to delete.
|
3082
|
-
"""
|
3083
|
-
try:
|
3084
|
-
await self._client.delete(f"/artifacts/{artifact_id}")
|
3085
|
-
except httpx.HTTPStatusError as e:
|
3086
|
-
if e.response.status_code == 404:
|
3087
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
3088
|
-
else:
|
3089
|
-
raise
|
3090
|
-
|
3091
|
-
async def create_variable(self, variable: VariableCreate) -> Variable:
|
3092
|
-
"""
|
3093
|
-
Creates an variable with the provided configuration.
|
3094
|
-
|
3095
|
-
Args:
|
3096
|
-
variable: Desired configuration for the new variable.
|
3097
|
-
Returns:
|
3098
|
-
Information about the newly created variable.
|
3099
|
-
"""
|
3100
|
-
response = await self._client.post(
|
3101
|
-
"/variables/",
|
3102
|
-
json=variable.model_dump(mode="json", exclude_unset=True),
|
3103
|
-
)
|
3104
|
-
return Variable(**response.json())
|
3105
|
-
|
3106
|
-
async def update_variable(self, variable: VariableUpdate) -> None:
|
3107
|
-
"""
|
3108
|
-
Updates a variable with the provided configuration.
|
3109
|
-
|
3110
|
-
Args:
|
3111
|
-
variable: Desired configuration for the updated variable.
|
3112
|
-
Returns:
|
3113
|
-
Information about the updated variable.
|
3114
|
-
"""
|
3115
|
-
await self._client.patch(
|
3116
|
-
f"/variables/name/{variable.name}",
|
3117
|
-
json=variable.model_dump(mode="json", exclude_unset=True),
|
3118
|
-
)
|
3119
|
-
|
3120
|
-
async def read_variable_by_name(self, name: str) -> Optional[Variable]:
|
3121
|
-
"""Reads a variable by name. Returns None if no variable is found."""
|
3122
|
-
try:
|
3123
|
-
response = await self._client.get(f"/variables/name/{name}")
|
3124
|
-
return Variable(**response.json())
|
3125
|
-
except httpx.HTTPStatusError as e:
|
3126
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
3127
|
-
return None
|
3128
|
-
else:
|
3129
|
-
raise
|
3130
|
-
|
3131
|
-
async def delete_variable_by_name(self, name: str) -> None:
|
3132
|
-
"""Deletes a variable by name."""
|
3133
|
-
try:
|
3134
|
-
await self._client.delete(f"/variables/name/{name}")
|
3135
|
-
except httpx.HTTPStatusError as e:
|
3136
|
-
if e.response.status_code == 404:
|
3137
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
3138
|
-
else:
|
3139
|
-
raise
|
3140
|
-
|
3141
|
-
async def read_variables(self, limit: Optional[int] = None) -> list[Variable]:
|
3142
|
-
"""Reads all variables."""
|
3143
|
-
response = await self._client.post("/variables/filter", json={"limit": limit})
|
3144
|
-
return pydantic.TypeAdapter(list[Variable]).validate_python(response.json())
|
3145
|
-
|
3146
2725
|
async def read_worker_metadata(self) -> dict[str, Any]:
|
3147
2726
|
"""Reads worker metadata stored in Prefect collection registry."""
|
3148
2727
|
response = await self._client.get("collections/views/aggregate-worker-metadata")
|
3149
2728
|
response.raise_for_status()
|
3150
2729
|
return response.json()
|
3151
2730
|
|
3152
|
-
async def increment_concurrency_slots(
|
3153
|
-
self,
|
3154
|
-
names: list[str],
|
3155
|
-
slots: int,
|
3156
|
-
mode: str,
|
3157
|
-
create_if_missing: Optional[bool] = None,
|
3158
|
-
) -> httpx.Response:
|
3159
|
-
return await self._client.post(
|
3160
|
-
"/v2/concurrency_limits/increment",
|
3161
|
-
json={
|
3162
|
-
"names": names,
|
3163
|
-
"slots": slots,
|
3164
|
-
"mode": mode,
|
3165
|
-
"create_if_missing": create_if_missing if create_if_missing else False,
|
3166
|
-
},
|
3167
|
-
)
|
3168
|
-
|
3169
|
-
async def release_concurrency_slots(
|
3170
|
-
self, names: list[str], slots: int, occupancy_seconds: float
|
3171
|
-
) -> httpx.Response:
|
3172
|
-
"""
|
3173
|
-
Release concurrency slots for the specified limits.
|
3174
|
-
|
3175
|
-
Args:
|
3176
|
-
names (List[str]): A list of limit names for which to release slots.
|
3177
|
-
slots (int): The number of concurrency slots to release.
|
3178
|
-
occupancy_seconds (float): The duration in seconds that the slots
|
3179
|
-
were occupied.
|
3180
|
-
|
3181
|
-
Returns:
|
3182
|
-
httpx.Response: The HTTP response from the server.
|
3183
|
-
"""
|
3184
|
-
|
3185
|
-
return await self._client.post(
|
3186
|
-
"/v2/concurrency_limits/decrement",
|
3187
|
-
json={
|
3188
|
-
"names": names,
|
3189
|
-
"slots": slots,
|
3190
|
-
"occupancy_seconds": occupancy_seconds,
|
3191
|
-
},
|
3192
|
-
)
|
3193
|
-
|
3194
|
-
async def create_global_concurrency_limit(
|
3195
|
-
self, concurrency_limit: GlobalConcurrencyLimitCreate
|
3196
|
-
) -> UUID:
|
3197
|
-
response = await self._client.post(
|
3198
|
-
"/v2/concurrency_limits/",
|
3199
|
-
json=concurrency_limit.model_dump(mode="json", exclude_unset=True),
|
3200
|
-
)
|
3201
|
-
return UUID(response.json()["id"])
|
3202
|
-
|
3203
|
-
async def update_global_concurrency_limit(
|
3204
|
-
self, name: str, concurrency_limit: GlobalConcurrencyLimitUpdate
|
3205
|
-
) -> httpx.Response:
|
3206
|
-
try:
|
3207
|
-
response = await self._client.patch(
|
3208
|
-
f"/v2/concurrency_limits/{name}",
|
3209
|
-
json=concurrency_limit.model_dump(mode="json", exclude_unset=True),
|
3210
|
-
)
|
3211
|
-
return response
|
3212
|
-
except httpx.HTTPStatusError as e:
|
3213
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
3214
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
3215
|
-
else:
|
3216
|
-
raise
|
3217
|
-
|
3218
|
-
async def delete_global_concurrency_limit_by_name(
|
3219
|
-
self, name: str
|
3220
|
-
) -> httpx.Response:
|
3221
|
-
try:
|
3222
|
-
response = await self._client.delete(f"/v2/concurrency_limits/{name}")
|
3223
|
-
return response
|
3224
|
-
except httpx.HTTPStatusError as e:
|
3225
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
3226
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
3227
|
-
else:
|
3228
|
-
raise
|
3229
|
-
|
3230
|
-
async def read_global_concurrency_limit_by_name(
|
3231
|
-
self, name: str
|
3232
|
-
) -> GlobalConcurrencyLimitResponse:
|
3233
|
-
try:
|
3234
|
-
response = await self._client.get(f"/v2/concurrency_limits/{name}")
|
3235
|
-
return GlobalConcurrencyLimitResponse.model_validate(response.json())
|
3236
|
-
except httpx.HTTPStatusError as e:
|
3237
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
3238
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
3239
|
-
else:
|
3240
|
-
raise
|
3241
|
-
|
3242
|
-
async def upsert_global_concurrency_limit_by_name(
|
3243
|
-
self, name: str, limit: int
|
3244
|
-
) -> None:
|
3245
|
-
"""Creates a global concurrency limit with the given name and limit if one does not already exist.
|
3246
|
-
|
3247
|
-
If one does already exist matching the name then update it's limit if it is different.
|
3248
|
-
|
3249
|
-
Note: This is not done atomically.
|
3250
|
-
"""
|
3251
|
-
try:
|
3252
|
-
existing_limit = await self.read_global_concurrency_limit_by_name(name)
|
3253
|
-
except prefect.exceptions.ObjectNotFound:
|
3254
|
-
existing_limit = None
|
3255
|
-
|
3256
|
-
if not existing_limit:
|
3257
|
-
await self.create_global_concurrency_limit(
|
3258
|
-
GlobalConcurrencyLimitCreate(
|
3259
|
-
name=name,
|
3260
|
-
limit=limit,
|
3261
|
-
)
|
3262
|
-
)
|
3263
|
-
elif existing_limit.limit != limit:
|
3264
|
-
await self.update_global_concurrency_limit(
|
3265
|
-
name, GlobalConcurrencyLimitUpdate(limit=limit)
|
3266
|
-
)
|
3267
|
-
|
3268
|
-
async def read_global_concurrency_limits(
|
3269
|
-
self, limit: int = 10, offset: int = 0
|
3270
|
-
) -> list[GlobalConcurrencyLimitResponse]:
|
3271
|
-
response = await self._client.post(
|
3272
|
-
"/v2/concurrency_limits/filter",
|
3273
|
-
json={
|
3274
|
-
"limit": limit,
|
3275
|
-
"offset": offset,
|
3276
|
-
},
|
3277
|
-
)
|
3278
|
-
return pydantic.TypeAdapter(
|
3279
|
-
list[GlobalConcurrencyLimitResponse]
|
3280
|
-
).validate_python(response.json())
|
3281
|
-
|
3282
2731
|
async def create_flow_run_input(
|
3283
2732
|
self, flow_run_id: UUID, key: str, value: str, sender: Optional[str] = None
|
3284
2733
|
) -> None:
|
@@ -3571,7 +3020,13 @@ class PrefectClient:
|
|
3571
3020
|
assert False, "This should never be called but must be defined for __enter__"
|
3572
3021
|
|
3573
3022
|
|
3574
|
-
class SyncPrefectClient
|
3023
|
+
class SyncPrefectClient(
|
3024
|
+
ArtifactClient,
|
3025
|
+
ArtifactCollectionClient,
|
3026
|
+
LogClient,
|
3027
|
+
VariableClient,
|
3028
|
+
ConcurrencyLimitClient,
|
3029
|
+
):
|
3575
3030
|
"""
|
3576
3031
|
A synchronous client for interacting with the [Prefect REST API](/api-ref/rest-api/).
|
3577
3032
|
|
@@ -4354,74 +3809,6 @@ class SyncPrefectClient:
|
|
4354
3809
|
|
4355
3810
|
return DeploymentResponse.model_validate(response.json())
|
4356
3811
|
|
4357
|
-
def create_artifact(
|
4358
|
-
self,
|
4359
|
-
artifact: ArtifactCreate,
|
4360
|
-
) -> Artifact:
|
4361
|
-
"""
|
4362
|
-
Creates an artifact with the provided configuration.
|
4363
|
-
|
4364
|
-
Args:
|
4365
|
-
artifact: Desired configuration for the new artifact.
|
4366
|
-
Returns:
|
4367
|
-
Information about the newly created artifact.
|
4368
|
-
"""
|
4369
|
-
|
4370
|
-
response = self._client.post(
|
4371
|
-
"/artifacts/",
|
4372
|
-
json=artifact.model_dump(mode="json", exclude_unset=True),
|
4373
|
-
)
|
4374
|
-
|
4375
|
-
return Artifact.model_validate(response.json())
|
4376
|
-
|
4377
|
-
def release_concurrency_slots(
|
4378
|
-
self, names: list[str], slots: int, occupancy_seconds: float
|
4379
|
-
) -> httpx.Response:
|
4380
|
-
"""
|
4381
|
-
Release concurrency slots for the specified limits.
|
4382
|
-
|
4383
|
-
Args:
|
4384
|
-
names (List[str]): A list of limit names for which to release slots.
|
4385
|
-
slots (int): The number of concurrency slots to release.
|
4386
|
-
occupancy_seconds (float): The duration in seconds that the slots
|
4387
|
-
were occupied.
|
4388
|
-
|
4389
|
-
Returns:
|
4390
|
-
httpx.Response: The HTTP response from the server.
|
4391
|
-
"""
|
4392
|
-
return self._client.post(
|
4393
|
-
"/v2/concurrency_limits/decrement",
|
4394
|
-
json={
|
4395
|
-
"names": names,
|
4396
|
-
"slots": slots,
|
4397
|
-
"occupancy_seconds": occupancy_seconds,
|
4398
|
-
},
|
4399
|
-
)
|
4400
|
-
|
4401
|
-
def decrement_v1_concurrency_slots(
|
4402
|
-
self, names: list[str], occupancy_seconds: float, task_run_id: UUID
|
4403
|
-
) -> httpx.Response:
|
4404
|
-
"""
|
4405
|
-
Release the specified concurrency limits.
|
4406
|
-
|
4407
|
-
Args:
|
4408
|
-
names (List[str]): A list of limit names to decrement.
|
4409
|
-
occupancy_seconds (float): The duration in seconds that the slots
|
4410
|
-
were held.
|
4411
|
-
task_run_id (UUID): The task run ID that incremented the limits.
|
4412
|
-
|
4413
|
-
Returns:
|
4414
|
-
httpx.Response: The HTTP response from the server.
|
4415
|
-
"""
|
4416
|
-
return self._client.post(
|
4417
|
-
"/concurrency_limits/decrement",
|
4418
|
-
json={
|
4419
|
-
"names": names,
|
4420
|
-
"occupancy_seconds": occupancy_seconds,
|
4421
|
-
"task_run_id": str(task_run_id),
|
4422
|
-
},
|
4423
|
-
)
|
4424
|
-
|
4425
3812
|
def update_flow_run_labels(
|
4426
3813
|
self, flow_run_id: UUID, labels: KeyValueLabelsField
|
4427
3814
|
) -> None:
|
@@ -4471,53 +3858,3 @@ class SyncPrefectClient:
|
|
4471
3858
|
else:
|
4472
3859
|
raise
|
4473
3860
|
return BlockDocument.model_validate(response.json())
|
4474
|
-
|
4475
|
-
def create_variable(self, variable: VariableCreate) -> Variable:
|
4476
|
-
"""
|
4477
|
-
Creates an variable with the provided configuration.
|
4478
|
-
|
4479
|
-
Args:
|
4480
|
-
variable: Desired configuration for the new variable.
|
4481
|
-
Returns:
|
4482
|
-
Information about the newly created variable.
|
4483
|
-
"""
|
4484
|
-
response = self._client.post(
|
4485
|
-
"/variables/",
|
4486
|
-
json=variable.model_dump(mode="json", exclude_unset=True),
|
4487
|
-
)
|
4488
|
-
return Variable(**response.json())
|
4489
|
-
|
4490
|
-
def update_variable(self, variable: VariableUpdate) -> None:
|
4491
|
-
"""
|
4492
|
-
Updates a variable with the provided configuration.
|
4493
|
-
|
4494
|
-
Args:
|
4495
|
-
variable: Desired configuration for the updated variable.
|
4496
|
-
Returns:
|
4497
|
-
Information about the updated variable.
|
4498
|
-
"""
|
4499
|
-
self._client.patch(
|
4500
|
-
f"/variables/name/{variable.name}",
|
4501
|
-
json=variable.model_dump(mode="json", exclude_unset=True),
|
4502
|
-
)
|
4503
|
-
|
4504
|
-
def read_variable_by_name(self, name: str) -> Optional[Variable]:
|
4505
|
-
"""Reads a variable by name. Returns None if no variable is found."""
|
4506
|
-
try:
|
4507
|
-
response = self._client.get(f"/variables/name/{name}")
|
4508
|
-
return Variable(**response.json())
|
4509
|
-
except httpx.HTTPStatusError as e:
|
4510
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
4511
|
-
return None
|
4512
|
-
else:
|
4513
|
-
raise
|
4514
|
-
|
4515
|
-
def delete_variable_by_name(self, name: str) -> None:
|
4516
|
-
"""Deletes a variable by name."""
|
4517
|
-
try:
|
4518
|
-
self._client.delete(f"/variables/name/{name}")
|
4519
|
-
except httpx.HTTPStatusError as e:
|
4520
|
-
if e.response.status_code == 404:
|
4521
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
4522
|
-
else:
|
4523
|
-
raise
|