prefect-client 3.1.11__py3-none-any.whl → 3.1.13__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/sla/__init__.py +0 -0
- prefect/_experimental/sla/client.py +92 -0
- prefect/_experimental/sla/objects.py +61 -0
- prefect/_internal/concurrency/services.py +2 -2
- prefect/_internal/concurrency/threads.py +6 -0
- prefect/_internal/retries.py +6 -3
- prefect/_internal/schemas/validators.py +6 -4
- prefect/_version.py +3 -3
- prefect/artifacts.py +4 -1
- prefect/automations.py +236 -30
- prefect/blocks/__init__.py +3 -3
- prefect/blocks/abstract.py +57 -31
- prefect/blocks/core.py +181 -82
- prefect/blocks/notifications.py +134 -73
- prefect/blocks/redis.py +13 -9
- prefect/blocks/system.py +24 -11
- prefect/blocks/webhook.py +7 -5
- prefect/cache_policies.py +23 -22
- prefect/client/orchestration/__init__.py +103 -2006
- 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/_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/client.py +16 -14
- prefect/client/schemas/__init__.py +68 -28
- prefect/client/schemas/objects.py +5 -5
- prefect/client/utilities.py +3 -3
- prefect/context.py +15 -1
- prefect/deployments/base.py +13 -4
- prefect/deployments/flow_runs.py +5 -1
- prefect/deployments/runner.py +37 -1
- prefect/deployments/steps/core.py +1 -1
- prefect/deployments/steps/pull.py +8 -3
- prefect/deployments/steps/utility.py +2 -2
- prefect/docker/docker_image.py +13 -9
- prefect/engine.py +33 -11
- prefect/events/cli/automations.py +4 -4
- prefect/events/clients.py +17 -14
- prefect/events/schemas/automations.py +12 -8
- prefect/events/schemas/events.py +5 -1
- prefect/events/worker.py +1 -1
- prefect/filesystems.py +7 -3
- prefect/flow_engine.py +64 -47
- prefect/flows.py +128 -74
- prefect/futures.py +14 -7
- prefect/infrastructure/provisioners/__init__.py +2 -0
- prefect/infrastructure/provisioners/cloud_run.py +4 -4
- prefect/infrastructure/provisioners/coiled.py +249 -0
- prefect/infrastructure/provisioners/container_instance.py +4 -3
- prefect/infrastructure/provisioners/ecs.py +55 -43
- prefect/infrastructure/provisioners/modal.py +5 -4
- prefect/input/actions.py +5 -1
- prefect/input/run_input.py +157 -43
- prefect/logging/configuration.py +3 -3
- prefect/logging/filters.py +2 -2
- prefect/logging/formatters.py +15 -11
- prefect/logging/handlers.py +24 -14
- prefect/logging/highlighters.py +5 -5
- prefect/logging/loggers.py +28 -18
- prefect/logging/logging.yml +1 -1
- prefect/main.py +3 -1
- prefect/results.py +166 -86
- prefect/runner/runner.py +38 -29
- prefect/runner/server.py +3 -1
- prefect/runner/storage.py +18 -18
- prefect/runner/submit.py +19 -12
- prefect/runtime/deployment.py +15 -8
- prefect/runtime/flow_run.py +19 -6
- prefect/runtime/task_run.py +7 -3
- prefect/settings/base.py +17 -7
- prefect/settings/legacy.py +4 -4
- prefect/settings/models/api.py +4 -3
- prefect/settings/models/cli.py +4 -3
- prefect/settings/models/client.py +7 -4
- prefect/settings/models/cloud.py +9 -3
- prefect/settings/models/deployments.py +4 -3
- prefect/settings/models/experiments.py +4 -8
- prefect/settings/models/flows.py +4 -3
- prefect/settings/models/internal.py +4 -3
- prefect/settings/models/logging.py +8 -6
- prefect/settings/models/results.py +4 -3
- prefect/settings/models/root.py +11 -16
- prefect/settings/models/runner.py +8 -5
- prefect/settings/models/server/api.py +6 -3
- prefect/settings/models/server/database.py +120 -25
- prefect/settings/models/server/deployments.py +4 -3
- prefect/settings/models/server/ephemeral.py +7 -4
- prefect/settings/models/server/events.py +6 -3
- prefect/settings/models/server/flow_run_graph.py +4 -3
- prefect/settings/models/server/root.py +4 -3
- prefect/settings/models/server/services.py +15 -12
- prefect/settings/models/server/tasks.py +7 -4
- prefect/settings/models/server/ui.py +4 -3
- prefect/settings/models/tasks.py +10 -5
- prefect/settings/models/testing.py +4 -3
- prefect/settings/models/worker.py +7 -4
- prefect/settings/profiles.py +13 -12
- prefect/settings/sources.py +20 -19
- prefect/states.py +74 -51
- prefect/task_engine.py +43 -33
- prefect/task_runners.py +85 -72
- prefect/task_runs.py +20 -11
- prefect/task_worker.py +14 -9
- prefect/tasks.py +36 -28
- prefect/telemetry/bootstrap.py +13 -9
- prefect/telemetry/run_telemetry.py +15 -13
- prefect/telemetry/services.py +4 -0
- prefect/transactions.py +3 -3
- prefect/types/__init__.py +3 -1
- prefect/utilities/_deprecated.py +38 -0
- prefect/utilities/engine.py +11 -4
- prefect/utilities/filesystem.py +2 -2
- prefect/utilities/generics.py +1 -1
- prefect/utilities/pydantic.py +21 -36
- prefect/utilities/templating.py +25 -1
- prefect/workers/base.py +58 -33
- prefect/workers/process.py +20 -15
- prefect/workers/server.py +4 -5
- {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/METADATA +3 -3
- {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/RECORD +133 -114
- {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/LICENSE +0 -0
- {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/WHEEL +0 -0
- {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,7 @@ from collections.abc import Iterable
|
|
7
7
|
from contextlib import AsyncExitStack
|
8
8
|
from logging import Logger
|
9
9
|
from typing import TYPE_CHECKING, Any, Literal, NoReturn, Optional, Union, overload
|
10
|
-
from uuid import UUID
|
10
|
+
from uuid import UUID
|
11
11
|
|
12
12
|
import certifi
|
13
13
|
import httpcore
|
@@ -40,31 +40,49 @@ from prefect.client.orchestration._variables.client import (
|
|
40
40
|
VariableAsyncClient,
|
41
41
|
)
|
42
42
|
|
43
|
+
from prefect.client.orchestration._deployments.client import (
|
44
|
+
DeploymentClient,
|
45
|
+
DeploymentAsyncClient,
|
46
|
+
)
|
47
|
+
from prefect.client.orchestration._automations.client import (
|
48
|
+
AutomationClient,
|
49
|
+
AutomationAsyncClient,
|
50
|
+
)
|
51
|
+
from prefect._experimental.sla.client import SlaClient, SlaAsyncClient
|
52
|
+
|
53
|
+
from prefect.client.orchestration._flows.client import (
|
54
|
+
FlowClient,
|
55
|
+
FlowAsyncClient,
|
56
|
+
)
|
57
|
+
from prefect.client.orchestration._flow_runs.client import (
|
58
|
+
FlowRunClient,
|
59
|
+
FlowRunAsyncClient,
|
60
|
+
)
|
61
|
+
|
62
|
+
from prefect.client.orchestration._blocks_documents.client import (
|
63
|
+
BlocksDocumentClient,
|
64
|
+
BlocksDocumentAsyncClient,
|
65
|
+
)
|
66
|
+
|
67
|
+
from prefect.client.orchestration._blocks_schemas.client import (
|
68
|
+
BlocksSchemaClient,
|
69
|
+
BlocksSchemaAsyncClient,
|
70
|
+
)
|
71
|
+
|
72
|
+
from prefect.client.orchestration._blocks_types.client import (
|
73
|
+
BlocksTypeClient,
|
74
|
+
BlocksTypeAsyncClient,
|
75
|
+
)
|
76
|
+
|
43
77
|
import prefect
|
44
78
|
import prefect.exceptions
|
45
79
|
import prefect.settings
|
46
80
|
import prefect.states
|
47
81
|
from prefect.client.constants import SERVER_API_VERSION
|
48
|
-
from prefect.client.schemas import FlowRun, OrchestrationResult, TaskRun
|
82
|
+
from prefect.client.schemas import FlowRun, OrchestrationResult, TaskRun
|
49
83
|
from prefect.client.schemas.actions import (
|
50
|
-
BlockDocumentCreate,
|
51
|
-
BlockDocumentUpdate,
|
52
|
-
BlockSchemaCreate,
|
53
|
-
BlockTypeCreate,
|
54
|
-
BlockTypeUpdate,
|
55
|
-
DeploymentCreate,
|
56
|
-
DeploymentFlowRunCreate,
|
57
|
-
DeploymentScheduleCreate,
|
58
|
-
DeploymentScheduleUpdate,
|
59
|
-
DeploymentUpdate,
|
60
|
-
FlowCreate,
|
61
|
-
FlowRunCreate,
|
62
84
|
FlowRunNotificationPolicyCreate,
|
63
85
|
FlowRunNotificationPolicyUpdate,
|
64
|
-
FlowRunUpdate,
|
65
|
-
LogCreate,
|
66
|
-
GlobalConcurrencyLimitCreate,
|
67
|
-
GlobalConcurrencyLimitUpdate,
|
68
86
|
TaskRunCreate,
|
69
87
|
TaskRunUpdate,
|
70
88
|
WorkPoolCreate,
|
@@ -84,16 +102,8 @@ from prefect.client.schemas.filters import (
|
|
84
102
|
WorkQueueFilterName,
|
85
103
|
)
|
86
104
|
from prefect.client.schemas.objects import (
|
87
|
-
BlockDocument,
|
88
|
-
BlockSchema,
|
89
|
-
BlockType,
|
90
|
-
ConcurrencyOptions,
|
91
105
|
Constant,
|
92
|
-
DeploymentSchedule,
|
93
|
-
Flow,
|
94
|
-
FlowRunInput,
|
95
106
|
FlowRunNotificationPolicy,
|
96
|
-
FlowRunPolicy,
|
97
107
|
Parameter,
|
98
108
|
TaskRunPolicy,
|
99
109
|
TaskRunResult,
|
@@ -104,19 +114,11 @@ from prefect.client.schemas.objects import (
|
|
104
114
|
WorkQueueStatusDetail,
|
105
115
|
)
|
106
116
|
from prefect.client.schemas.responses import (
|
107
|
-
DeploymentResponse,
|
108
|
-
FlowRunResponse,
|
109
117
|
WorkerFlowRunResponse,
|
110
118
|
)
|
111
|
-
from prefect.client.schemas.schedules import SCHEDULE_TYPES
|
112
119
|
from prefect.client.schemas.sorting import (
|
113
|
-
DeploymentSort,
|
114
|
-
FlowRunSort,
|
115
|
-
FlowSort,
|
116
120
|
TaskRunSort,
|
117
121
|
)
|
118
|
-
from prefect.events import filters
|
119
|
-
from prefect.events.schemas.automations import Automation, AutomationCore
|
120
122
|
from prefect.logging import get_logger
|
121
123
|
from prefect.settings import (
|
122
124
|
PREFECT_API_AUTH_STRING,
|
@@ -133,10 +135,8 @@ from prefect.settings import (
|
|
133
135
|
PREFECT_TESTING_UNIT_TEST_MODE,
|
134
136
|
get_current_settings,
|
135
137
|
)
|
136
|
-
from prefect.types import KeyValueLabelsField
|
137
138
|
|
138
139
|
if TYPE_CHECKING:
|
139
|
-
from prefect.flows import Flow as FlowObject
|
140
140
|
from prefect.tasks import Task as TaskObject
|
141
141
|
|
142
142
|
from prefect.client.base import (
|
@@ -255,6 +255,14 @@ class PrefectClient(
|
|
255
255
|
LogAsyncClient,
|
256
256
|
VariableAsyncClient,
|
257
257
|
ConcurrencyLimitAsyncClient,
|
258
|
+
DeploymentAsyncClient,
|
259
|
+
AutomationAsyncClient,
|
260
|
+
SlaAsyncClient,
|
261
|
+
FlowRunAsyncClient,
|
262
|
+
FlowAsyncClient,
|
263
|
+
BlocksDocumentAsyncClient,
|
264
|
+
BlocksSchemaAsyncClient,
|
265
|
+
BlocksTypeAsyncClient,
|
258
266
|
):
|
259
267
|
"""
|
260
268
|
An asynchronous client for interacting with the [Prefect REST API](/api-ref/rest-api/).
|
@@ -467,361 +475,6 @@ class PrefectClient(
|
|
467
475
|
"""
|
468
476
|
return await self._client.get("/hello")
|
469
477
|
|
470
|
-
async def create_flow(self, flow: "FlowObject[Any, Any]") -> UUID:
|
471
|
-
"""
|
472
|
-
Create a flow in the Prefect API.
|
473
|
-
|
474
|
-
Args:
|
475
|
-
flow: a [Flow][prefect.flows.Flow] object
|
476
|
-
|
477
|
-
Raises:
|
478
|
-
httpx.RequestError: if a flow was not created for any reason
|
479
|
-
|
480
|
-
Returns:
|
481
|
-
the ID of the flow in the backend
|
482
|
-
"""
|
483
|
-
return await self.create_flow_from_name(flow.name)
|
484
|
-
|
485
|
-
async def create_flow_from_name(self, flow_name: str) -> UUID:
|
486
|
-
"""
|
487
|
-
Create a flow in the Prefect API.
|
488
|
-
|
489
|
-
Args:
|
490
|
-
flow_name: the name of the new flow
|
491
|
-
|
492
|
-
Raises:
|
493
|
-
httpx.RequestError: if a flow was not created for any reason
|
494
|
-
|
495
|
-
Returns:
|
496
|
-
the ID of the flow in the backend
|
497
|
-
"""
|
498
|
-
flow_data = FlowCreate(name=flow_name)
|
499
|
-
response = await self._client.post(
|
500
|
-
"/flows/", json=flow_data.model_dump(mode="json")
|
501
|
-
)
|
502
|
-
|
503
|
-
flow_id = response.json().get("id")
|
504
|
-
if not flow_id:
|
505
|
-
raise httpx.RequestError(f"Malformed response: {response}")
|
506
|
-
|
507
|
-
# Return the id of the created flow
|
508
|
-
return UUID(flow_id)
|
509
|
-
|
510
|
-
async def read_flow(self, flow_id: UUID) -> Flow:
|
511
|
-
"""
|
512
|
-
Query the Prefect API for a flow by id.
|
513
|
-
|
514
|
-
Args:
|
515
|
-
flow_id: the flow ID of interest
|
516
|
-
|
517
|
-
Returns:
|
518
|
-
a [Flow model][prefect.client.schemas.objects.Flow] representation of the flow
|
519
|
-
"""
|
520
|
-
response = await self._client.get(f"/flows/{flow_id}")
|
521
|
-
return Flow.model_validate(response.json())
|
522
|
-
|
523
|
-
async def delete_flow(self, flow_id: UUID) -> None:
|
524
|
-
"""
|
525
|
-
Delete a flow by UUID.
|
526
|
-
|
527
|
-
Args:
|
528
|
-
flow_id: ID of the flow to be deleted
|
529
|
-
Raises:
|
530
|
-
prefect.exceptions.ObjectNotFound: If request returns 404
|
531
|
-
httpx.RequestError: If requests fail
|
532
|
-
"""
|
533
|
-
try:
|
534
|
-
await self._client.delete(f"/flows/{flow_id}")
|
535
|
-
except httpx.HTTPStatusError as e:
|
536
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
537
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
538
|
-
else:
|
539
|
-
raise
|
540
|
-
|
541
|
-
async def read_flows(
|
542
|
-
self,
|
543
|
-
*,
|
544
|
-
flow_filter: Optional[FlowFilter] = None,
|
545
|
-
flow_run_filter: Optional[FlowRunFilter] = None,
|
546
|
-
task_run_filter: Optional[TaskRunFilter] = None,
|
547
|
-
deployment_filter: Optional[DeploymentFilter] = None,
|
548
|
-
work_pool_filter: Optional[WorkPoolFilter] = None,
|
549
|
-
work_queue_filter: Optional[WorkQueueFilter] = None,
|
550
|
-
sort: Optional[FlowSort] = None,
|
551
|
-
limit: Optional[int] = None,
|
552
|
-
offset: int = 0,
|
553
|
-
) -> list[Flow]:
|
554
|
-
"""
|
555
|
-
Query the Prefect API for flows. Only flows matching all criteria will
|
556
|
-
be returned.
|
557
|
-
|
558
|
-
Args:
|
559
|
-
flow_filter: filter criteria for flows
|
560
|
-
flow_run_filter: filter criteria for flow runs
|
561
|
-
task_run_filter: filter criteria for task runs
|
562
|
-
deployment_filter: filter criteria for deployments
|
563
|
-
work_pool_filter: filter criteria for work pools
|
564
|
-
work_queue_filter: filter criteria for work pool queues
|
565
|
-
sort: sort criteria for the flows
|
566
|
-
limit: limit for the flow query
|
567
|
-
offset: offset for the flow query
|
568
|
-
|
569
|
-
Returns:
|
570
|
-
a list of Flow model representations of the flows
|
571
|
-
"""
|
572
|
-
body: dict[str, Any] = {
|
573
|
-
"flows": flow_filter.model_dump(mode="json") if flow_filter else None,
|
574
|
-
"flow_runs": (
|
575
|
-
flow_run_filter.model_dump(mode="json", exclude_unset=True)
|
576
|
-
if flow_run_filter
|
577
|
-
else None
|
578
|
-
),
|
579
|
-
"task_runs": (
|
580
|
-
task_run_filter.model_dump(mode="json") if task_run_filter else None
|
581
|
-
),
|
582
|
-
"deployments": (
|
583
|
-
deployment_filter.model_dump(mode="json") if deployment_filter else None
|
584
|
-
),
|
585
|
-
"work_pools": (
|
586
|
-
work_pool_filter.model_dump(mode="json") if work_pool_filter else None
|
587
|
-
),
|
588
|
-
"work_queues": (
|
589
|
-
work_queue_filter.model_dump(mode="json") if work_queue_filter else None
|
590
|
-
),
|
591
|
-
"sort": sort,
|
592
|
-
"limit": limit,
|
593
|
-
"offset": offset,
|
594
|
-
}
|
595
|
-
|
596
|
-
response = await self._client.post("/flows/filter", json=body)
|
597
|
-
return pydantic.TypeAdapter(list[Flow]).validate_python(response.json())
|
598
|
-
|
599
|
-
async def read_flow_by_name(
|
600
|
-
self,
|
601
|
-
flow_name: str,
|
602
|
-
) -> Flow:
|
603
|
-
"""
|
604
|
-
Query the Prefect API for a flow by name.
|
605
|
-
|
606
|
-
Args:
|
607
|
-
flow_name: the name of a flow
|
608
|
-
|
609
|
-
Returns:
|
610
|
-
a fully hydrated Flow model
|
611
|
-
"""
|
612
|
-
response = await self._client.get(f"/flows/name/{flow_name}")
|
613
|
-
return Flow.model_validate(response.json())
|
614
|
-
|
615
|
-
async def create_flow_run_from_deployment(
|
616
|
-
self,
|
617
|
-
deployment_id: UUID,
|
618
|
-
*,
|
619
|
-
parameters: Optional[dict[str, Any]] = None,
|
620
|
-
context: Optional[dict[str, Any]] = None,
|
621
|
-
state: Optional[prefect.states.State[Any]] = None,
|
622
|
-
name: Optional[str] = None,
|
623
|
-
tags: Optional[Iterable[str]] = None,
|
624
|
-
idempotency_key: Optional[str] = None,
|
625
|
-
parent_task_run_id: Optional[UUID] = None,
|
626
|
-
work_queue_name: Optional[str] = None,
|
627
|
-
job_variables: Optional[dict[str, Any]] = None,
|
628
|
-
labels: Optional[KeyValueLabelsField] = None,
|
629
|
-
) -> FlowRun:
|
630
|
-
"""
|
631
|
-
Create a flow run for a deployment.
|
632
|
-
|
633
|
-
Args:
|
634
|
-
deployment_id: The deployment ID to create the flow run from
|
635
|
-
parameters: Parameter overrides for this flow run. Merged with the
|
636
|
-
deployment defaults
|
637
|
-
context: Optional run context data
|
638
|
-
state: The initial state for the run. If not provided, defaults to
|
639
|
-
`Scheduled` for now. Should always be a `Scheduled` type.
|
640
|
-
name: An optional name for the flow run. If not provided, the server will
|
641
|
-
generate a name.
|
642
|
-
tags: An optional iterable of tags to apply to the flow run; these tags
|
643
|
-
are merged with the deployment's tags.
|
644
|
-
idempotency_key: Optional idempotency key for creation of the flow run.
|
645
|
-
If the key matches the key of an existing flow run, the existing run will
|
646
|
-
be returned instead of creating a new one.
|
647
|
-
parent_task_run_id: if a subflow run is being created, the placeholder task
|
648
|
-
run identifier in the parent flow
|
649
|
-
work_queue_name: An optional work queue name to add this run to. If not provided,
|
650
|
-
will default to the deployment's set work queue. If one is provided that does not
|
651
|
-
exist, a new work queue will be created within the deployment's work pool.
|
652
|
-
job_variables: Optional variables that will be supplied to the flow run job.
|
653
|
-
|
654
|
-
Raises:
|
655
|
-
httpx.RequestError: if the Prefect API does not successfully create a run for any reason
|
656
|
-
|
657
|
-
Returns:
|
658
|
-
The flow run model
|
659
|
-
"""
|
660
|
-
parameters = parameters or {}
|
661
|
-
context = context or {}
|
662
|
-
state = state or prefect.states.Scheduled()
|
663
|
-
tags = tags or []
|
664
|
-
|
665
|
-
flow_run_create = DeploymentFlowRunCreate(
|
666
|
-
parameters=parameters,
|
667
|
-
context=context,
|
668
|
-
state=state.to_state_create(),
|
669
|
-
tags=list(tags),
|
670
|
-
name=name,
|
671
|
-
idempotency_key=idempotency_key,
|
672
|
-
parent_task_run_id=parent_task_run_id,
|
673
|
-
job_variables=job_variables,
|
674
|
-
labels=labels,
|
675
|
-
)
|
676
|
-
|
677
|
-
# done separately to avoid including this field in payloads sent to older API versions
|
678
|
-
if work_queue_name:
|
679
|
-
flow_run_create.work_queue_name = work_queue_name
|
680
|
-
|
681
|
-
response = await self._client.post(
|
682
|
-
f"/deployments/{deployment_id}/create_flow_run",
|
683
|
-
json=flow_run_create.model_dump(mode="json", exclude_unset=True),
|
684
|
-
)
|
685
|
-
return FlowRun.model_validate(response.json())
|
686
|
-
|
687
|
-
async def create_flow_run(
|
688
|
-
self,
|
689
|
-
flow: "FlowObject[Any, R]",
|
690
|
-
name: Optional[str] = None,
|
691
|
-
parameters: Optional[dict[str, Any]] = None,
|
692
|
-
context: Optional[dict[str, Any]] = None,
|
693
|
-
tags: Optional[Iterable[str]] = None,
|
694
|
-
parent_task_run_id: Optional[UUID] = None,
|
695
|
-
state: Optional["prefect.states.State[R]"] = None,
|
696
|
-
) -> FlowRun:
|
697
|
-
"""
|
698
|
-
Create a flow run for a flow.
|
699
|
-
|
700
|
-
Args:
|
701
|
-
flow: The flow model to create the flow run for
|
702
|
-
name: An optional name for the flow run
|
703
|
-
parameters: Parameter overrides for this flow run.
|
704
|
-
context: Optional run context data
|
705
|
-
tags: a list of tags to apply to this flow run
|
706
|
-
parent_task_run_id: if a subflow run is being created, the placeholder task
|
707
|
-
run identifier in the parent flow
|
708
|
-
state: The initial state for the run. If not provided, defaults to
|
709
|
-
`Scheduled` for now. Should always be a `Scheduled` type.
|
710
|
-
|
711
|
-
Raises:
|
712
|
-
httpx.RequestError: if the Prefect API does not successfully create a run for any reason
|
713
|
-
|
714
|
-
Returns:
|
715
|
-
The flow run model
|
716
|
-
"""
|
717
|
-
parameters = parameters or {}
|
718
|
-
context = context or {}
|
719
|
-
|
720
|
-
if state is None:
|
721
|
-
state = prefect.states.Pending()
|
722
|
-
|
723
|
-
# Retrieve the flow id
|
724
|
-
flow_id = await self.create_flow(flow)
|
725
|
-
|
726
|
-
flow_run_create = FlowRunCreate(
|
727
|
-
flow_id=flow_id,
|
728
|
-
flow_version=flow.version,
|
729
|
-
name=name,
|
730
|
-
parameters=parameters,
|
731
|
-
context=context,
|
732
|
-
tags=list(tags or []),
|
733
|
-
parent_task_run_id=parent_task_run_id,
|
734
|
-
state=state.to_state_create(),
|
735
|
-
empirical_policy=FlowRunPolicy(
|
736
|
-
retries=flow.retries,
|
737
|
-
retry_delay=int(flow.retry_delay_seconds or 0),
|
738
|
-
),
|
739
|
-
)
|
740
|
-
|
741
|
-
flow_run_create_json = flow_run_create.model_dump(mode="json")
|
742
|
-
response = await self._client.post("/flow_runs/", json=flow_run_create_json)
|
743
|
-
flow_run = FlowRun.model_validate(response.json())
|
744
|
-
|
745
|
-
# Restore the parameters to the local objects to retain expectations about
|
746
|
-
# Python objects
|
747
|
-
flow_run.parameters = parameters
|
748
|
-
|
749
|
-
return flow_run
|
750
|
-
|
751
|
-
async def update_flow_run(
|
752
|
-
self,
|
753
|
-
flow_run_id: UUID,
|
754
|
-
flow_version: Optional[str] = None,
|
755
|
-
parameters: Optional[dict[str, Any]] = None,
|
756
|
-
name: Optional[str] = None,
|
757
|
-
tags: Optional[Iterable[str]] = None,
|
758
|
-
empirical_policy: Optional[FlowRunPolicy] = None,
|
759
|
-
infrastructure_pid: Optional[str] = None,
|
760
|
-
job_variables: Optional[dict[str, Any]] = None,
|
761
|
-
) -> httpx.Response:
|
762
|
-
"""
|
763
|
-
Update a flow run's details.
|
764
|
-
|
765
|
-
Args:
|
766
|
-
flow_run_id: The identifier for the flow run to update.
|
767
|
-
flow_version: A new version string for the flow run.
|
768
|
-
parameters: A dictionary of parameter values for the flow run. This will not
|
769
|
-
be merged with any existing parameters.
|
770
|
-
name: A new name for the flow run.
|
771
|
-
empirical_policy: A new flow run orchestration policy. This will not be
|
772
|
-
merged with any existing policy.
|
773
|
-
tags: An iterable of new tags for the flow run. These will not be merged with
|
774
|
-
any existing tags.
|
775
|
-
infrastructure_pid: The id of flow run as returned by an
|
776
|
-
infrastructure block.
|
777
|
-
|
778
|
-
Returns:
|
779
|
-
an `httpx.Response` object from the PATCH request
|
780
|
-
"""
|
781
|
-
params: dict[str, Any] = {}
|
782
|
-
if flow_version is not None:
|
783
|
-
params["flow_version"] = flow_version
|
784
|
-
if parameters is not None:
|
785
|
-
params["parameters"] = parameters
|
786
|
-
if name is not None:
|
787
|
-
params["name"] = name
|
788
|
-
if tags is not None:
|
789
|
-
params["tags"] = tags
|
790
|
-
if empirical_policy is not None:
|
791
|
-
params["empirical_policy"] = empirical_policy
|
792
|
-
if infrastructure_pid:
|
793
|
-
params["infrastructure_pid"] = infrastructure_pid
|
794
|
-
if job_variables is not None:
|
795
|
-
params["job_variables"] = job_variables
|
796
|
-
|
797
|
-
flow_run_data = FlowRunUpdate(**params)
|
798
|
-
|
799
|
-
return await self._client.patch(
|
800
|
-
f"/flow_runs/{flow_run_id}",
|
801
|
-
json=flow_run_data.model_dump(mode="json", exclude_unset=True),
|
802
|
-
)
|
803
|
-
|
804
|
-
async def delete_flow_run(
|
805
|
-
self,
|
806
|
-
flow_run_id: UUID,
|
807
|
-
) -> None:
|
808
|
-
"""
|
809
|
-
Delete a flow run by UUID.
|
810
|
-
|
811
|
-
Args:
|
812
|
-
flow_run_id: The flow run UUID of interest.
|
813
|
-
Raises:
|
814
|
-
prefect.exceptions.ObjectNotFound: If request returns 404
|
815
|
-
httpx.RequestError: If requests fails
|
816
|
-
"""
|
817
|
-
try:
|
818
|
-
await self._client.delete(f"/flow_runs/{flow_run_id}")
|
819
|
-
except httpx.HTTPStatusError as e:
|
820
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
821
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
822
|
-
else:
|
823
|
-
raise
|
824
|
-
|
825
478
|
async def create_work_queue(
|
826
479
|
self,
|
827
480
|
name: str,
|
@@ -1089,1003 +742,37 @@ class PrefectClient(
|
|
1089
742
|
else:
|
1090
743
|
raise
|
1091
744
|
|
1092
|
-
async def
|
1093
|
-
|
1094
|
-
|
1095
|
-
|
1096
|
-
|
1097
|
-
|
1098
|
-
"/block_types/",
|
1099
|
-
json=block_type.model_dump(
|
1100
|
-
mode="json", exclude_unset=True, exclude={"id"}
|
1101
|
-
),
|
1102
|
-
)
|
1103
|
-
except httpx.HTTPStatusError as e:
|
1104
|
-
if e.response.status_code == status.HTTP_409_CONFLICT:
|
1105
|
-
raise prefect.exceptions.ObjectAlreadyExists(http_exc=e) from e
|
1106
|
-
else:
|
1107
|
-
raise
|
1108
|
-
return BlockType.model_validate(response.json())
|
1109
|
-
|
1110
|
-
async def create_block_schema(self, block_schema: BlockSchemaCreate) -> BlockSchema:
|
1111
|
-
"""
|
1112
|
-
Create a block schema in the Prefect API.
|
1113
|
-
"""
|
1114
|
-
try:
|
1115
|
-
response = await self._client.post(
|
1116
|
-
"/block_schemas/",
|
1117
|
-
json=block_schema.model_dump(
|
1118
|
-
mode="json",
|
1119
|
-
exclude_unset=True,
|
1120
|
-
exclude={"id", "block_type", "checksum"},
|
1121
|
-
),
|
1122
|
-
)
|
1123
|
-
except httpx.HTTPStatusError as e:
|
1124
|
-
if e.response.status_code == status.HTTP_409_CONFLICT:
|
1125
|
-
raise prefect.exceptions.ObjectAlreadyExists(http_exc=e) from e
|
1126
|
-
else:
|
1127
|
-
raise
|
1128
|
-
return BlockSchema.model_validate(response.json())
|
745
|
+
async def set_task_run_name(self, task_run_id: UUID, name: str) -> httpx.Response:
|
746
|
+
task_run_data = TaskRunUpdate(name=name)
|
747
|
+
return await self._client.patch(
|
748
|
+
f"/task_runs/{task_run_id}",
|
749
|
+
json=task_run_data.model_dump(mode="json", exclude_unset=True),
|
750
|
+
)
|
1129
751
|
|
1130
|
-
async def
|
752
|
+
async def create_task_run(
|
1131
753
|
self,
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
754
|
+
task: "TaskObject[P, R]",
|
755
|
+
flow_run_id: Optional[UUID],
|
756
|
+
dynamic_key: str,
|
757
|
+
id: Optional[UUID] = None,
|
758
|
+
name: Optional[str] = None,
|
759
|
+
extra_tags: Optional[Iterable[str]] = None,
|
760
|
+
state: Optional[prefect.states.State[R]] = None,
|
761
|
+
task_inputs: Optional[
|
762
|
+
dict[
|
763
|
+
str,
|
764
|
+
list[
|
765
|
+
Union[
|
766
|
+
TaskRunResult,
|
767
|
+
Parameter,
|
768
|
+
Constant,
|
769
|
+
]
|
770
|
+
],
|
771
|
+
]
|
772
|
+
] = None,
|
773
|
+
) -> TaskRun:
|
1135
774
|
"""
|
1136
|
-
Create a
|
1137
|
-
corresponding Block.
|
1138
|
-
|
1139
|
-
Args:
|
1140
|
-
include_secrets (bool): whether to include secret values
|
1141
|
-
on the stored Block, corresponding to Pydantic's `SecretStr` and
|
1142
|
-
`SecretBytes` fields. Note Blocks may not work as expected if
|
1143
|
-
this is set to `False`.
|
1144
|
-
"""
|
1145
|
-
block_document_data = block_document.model_dump(
|
1146
|
-
mode="json",
|
1147
|
-
exclude_unset=True,
|
1148
|
-
exclude={"id", "block_schema", "block_type"},
|
1149
|
-
context={"include_secrets": include_secrets},
|
1150
|
-
serialize_as_any=True,
|
1151
|
-
)
|
1152
|
-
try:
|
1153
|
-
response = await self._client.post(
|
1154
|
-
"/block_documents/",
|
1155
|
-
json=block_document_data,
|
1156
|
-
)
|
1157
|
-
except httpx.HTTPStatusError as e:
|
1158
|
-
if e.response.status_code == status.HTTP_409_CONFLICT:
|
1159
|
-
raise prefect.exceptions.ObjectAlreadyExists(http_exc=e) from e
|
1160
|
-
else:
|
1161
|
-
raise
|
1162
|
-
return BlockDocument.model_validate(response.json())
|
1163
|
-
|
1164
|
-
async def update_block_document(
|
1165
|
-
self,
|
1166
|
-
block_document_id: UUID,
|
1167
|
-
block_document: BlockDocumentUpdate,
|
1168
|
-
) -> None:
|
1169
|
-
"""
|
1170
|
-
Update a block document in the Prefect API.
|
1171
|
-
"""
|
1172
|
-
try:
|
1173
|
-
await self._client.patch(
|
1174
|
-
f"/block_documents/{block_document_id}",
|
1175
|
-
json=block_document.model_dump(
|
1176
|
-
mode="json",
|
1177
|
-
exclude_unset=True,
|
1178
|
-
include={"data", "merge_existing_data", "block_schema_id"},
|
1179
|
-
),
|
1180
|
-
)
|
1181
|
-
except httpx.HTTPStatusError as e:
|
1182
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
1183
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
1184
|
-
else:
|
1185
|
-
raise
|
1186
|
-
|
1187
|
-
async def delete_block_document(self, block_document_id: UUID) -> None:
|
1188
|
-
"""
|
1189
|
-
Delete a block document.
|
1190
|
-
"""
|
1191
|
-
try:
|
1192
|
-
await self._client.delete(f"/block_documents/{block_document_id}")
|
1193
|
-
except httpx.HTTPStatusError as e:
|
1194
|
-
if e.response.status_code == 404:
|
1195
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
1196
|
-
else:
|
1197
|
-
raise
|
1198
|
-
|
1199
|
-
async def read_block_type_by_slug(self, slug: str) -> BlockType:
|
1200
|
-
"""
|
1201
|
-
Read a block type by its slug.
|
1202
|
-
"""
|
1203
|
-
try:
|
1204
|
-
response = await self._client.get(f"/block_types/slug/{slug}")
|
1205
|
-
except httpx.HTTPStatusError as e:
|
1206
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
1207
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
1208
|
-
else:
|
1209
|
-
raise
|
1210
|
-
return BlockType.model_validate(response.json())
|
1211
|
-
|
1212
|
-
async def read_block_schema_by_checksum(
|
1213
|
-
self, checksum: str, version: Optional[str] = None
|
1214
|
-
) -> BlockSchema:
|
1215
|
-
"""
|
1216
|
-
Look up a block schema checksum
|
1217
|
-
"""
|
1218
|
-
try:
|
1219
|
-
url = f"/block_schemas/checksum/{checksum}"
|
1220
|
-
if version is not None:
|
1221
|
-
url = f"{url}?version={version}"
|
1222
|
-
response = await self._client.get(url)
|
1223
|
-
except httpx.HTTPStatusError as e:
|
1224
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
1225
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
1226
|
-
else:
|
1227
|
-
raise
|
1228
|
-
return BlockSchema.model_validate(response.json())
|
1229
|
-
|
1230
|
-
async def update_block_type(
|
1231
|
-
self, block_type_id: UUID, block_type: BlockTypeUpdate
|
1232
|
-
) -> None:
|
1233
|
-
"""
|
1234
|
-
Update a block document in the Prefect API.
|
1235
|
-
"""
|
1236
|
-
try:
|
1237
|
-
await self._client.patch(
|
1238
|
-
f"/block_types/{block_type_id}",
|
1239
|
-
json=block_type.model_dump(
|
1240
|
-
mode="json",
|
1241
|
-
exclude_unset=True,
|
1242
|
-
include=BlockTypeUpdate.updatable_fields(),
|
1243
|
-
),
|
1244
|
-
)
|
1245
|
-
except httpx.HTTPStatusError as e:
|
1246
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
1247
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
1248
|
-
else:
|
1249
|
-
raise
|
1250
|
-
|
1251
|
-
async def delete_block_type(self, block_type_id: UUID) -> None:
|
1252
|
-
"""
|
1253
|
-
Delete a block type.
|
1254
|
-
"""
|
1255
|
-
try:
|
1256
|
-
await self._client.delete(f"/block_types/{block_type_id}")
|
1257
|
-
except httpx.HTTPStatusError as e:
|
1258
|
-
if e.response.status_code == 404:
|
1259
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
1260
|
-
elif (
|
1261
|
-
e.response.status_code == status.HTTP_403_FORBIDDEN
|
1262
|
-
and e.response.json()["detail"]
|
1263
|
-
== "protected block types cannot be deleted."
|
1264
|
-
):
|
1265
|
-
raise prefect.exceptions.ProtectedBlockError(
|
1266
|
-
"Protected block types cannot be deleted."
|
1267
|
-
) from e
|
1268
|
-
else:
|
1269
|
-
raise
|
1270
|
-
|
1271
|
-
async def read_block_types(self) -> list[BlockType]:
|
1272
|
-
"""
|
1273
|
-
Read all block types
|
1274
|
-
Raises:
|
1275
|
-
httpx.RequestError: if the block types were not found
|
1276
|
-
|
1277
|
-
Returns:
|
1278
|
-
List of BlockTypes.
|
1279
|
-
"""
|
1280
|
-
response = await self._client.post("/block_types/filter", json={})
|
1281
|
-
return pydantic.TypeAdapter(list[BlockType]).validate_python(response.json())
|
1282
|
-
|
1283
|
-
async def read_block_schemas(self) -> list[BlockSchema]:
|
1284
|
-
"""
|
1285
|
-
Read all block schemas
|
1286
|
-
Raises:
|
1287
|
-
httpx.RequestError: if a valid block schema was not found
|
1288
|
-
|
1289
|
-
Returns:
|
1290
|
-
A BlockSchema.
|
1291
|
-
"""
|
1292
|
-
response = await self._client.post("/block_schemas/filter", json={})
|
1293
|
-
return pydantic.TypeAdapter(list[BlockSchema]).validate_python(response.json())
|
1294
|
-
|
1295
|
-
async def get_most_recent_block_schema_for_block_type(
|
1296
|
-
self,
|
1297
|
-
block_type_id: UUID,
|
1298
|
-
) -> Optional[BlockSchema]:
|
1299
|
-
"""
|
1300
|
-
Fetches the most recent block schema for a specified block type ID.
|
1301
|
-
|
1302
|
-
Args:
|
1303
|
-
block_type_id: The ID of the block type.
|
1304
|
-
|
1305
|
-
Raises:
|
1306
|
-
httpx.RequestError: If the request fails for any reason.
|
1307
|
-
|
1308
|
-
Returns:
|
1309
|
-
The most recent block schema or None.
|
1310
|
-
"""
|
1311
|
-
try:
|
1312
|
-
response = await self._client.post(
|
1313
|
-
"/block_schemas/filter",
|
1314
|
-
json={
|
1315
|
-
"block_schemas": {"block_type_id": {"any_": [str(block_type_id)]}},
|
1316
|
-
"limit": 1,
|
1317
|
-
},
|
1318
|
-
)
|
1319
|
-
except httpx.HTTPStatusError:
|
1320
|
-
raise
|
1321
|
-
return (
|
1322
|
-
BlockSchema.model_validate(response.json()[0]) if response.json() else None
|
1323
|
-
)
|
1324
|
-
|
1325
|
-
async def read_block_document(
|
1326
|
-
self,
|
1327
|
-
block_document_id: UUID,
|
1328
|
-
include_secrets: bool = True,
|
1329
|
-
) -> BlockDocument:
|
1330
|
-
"""
|
1331
|
-
Read the block document with the specified ID.
|
1332
|
-
|
1333
|
-
Args:
|
1334
|
-
block_document_id: the block document id
|
1335
|
-
include_secrets (bool): whether to include secret values
|
1336
|
-
on the Block, corresponding to Pydantic's `SecretStr` and
|
1337
|
-
`SecretBytes` fields. These fields are automatically obfuscated
|
1338
|
-
by Pydantic, but users can additionally choose not to receive
|
1339
|
-
their values from the API. Note that any business logic on the
|
1340
|
-
Block may not work if this is `False`.
|
1341
|
-
|
1342
|
-
Raises:
|
1343
|
-
httpx.RequestError: if the block document was not found for any reason
|
1344
|
-
|
1345
|
-
Returns:
|
1346
|
-
A block document or None.
|
1347
|
-
"""
|
1348
|
-
assert (
|
1349
|
-
block_document_id is not None
|
1350
|
-
), "Unexpected ID on block document. Was it persisted?"
|
1351
|
-
try:
|
1352
|
-
response = await self._client.get(
|
1353
|
-
f"/block_documents/{block_document_id}",
|
1354
|
-
params=dict(include_secrets=include_secrets),
|
1355
|
-
)
|
1356
|
-
except httpx.HTTPStatusError as e:
|
1357
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
1358
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
1359
|
-
else:
|
1360
|
-
raise
|
1361
|
-
return BlockDocument.model_validate(response.json())
|
1362
|
-
|
1363
|
-
async def read_block_document_by_name(
|
1364
|
-
self,
|
1365
|
-
name: str,
|
1366
|
-
block_type_slug: str,
|
1367
|
-
include_secrets: bool = True,
|
1368
|
-
) -> BlockDocument:
|
1369
|
-
"""
|
1370
|
-
Read the block document with the specified name that corresponds to a
|
1371
|
-
specific block type name.
|
1372
|
-
|
1373
|
-
Args:
|
1374
|
-
name: The block document name.
|
1375
|
-
block_type_slug: The block type slug.
|
1376
|
-
include_secrets (bool): whether to include secret values
|
1377
|
-
on the Block, corresponding to Pydantic's `SecretStr` and
|
1378
|
-
`SecretBytes` fields. These fields are automatically obfuscated
|
1379
|
-
by Pydantic, but users can additionally choose not to receive
|
1380
|
-
their values from the API. Note that any business logic on the
|
1381
|
-
Block may not work if this is `False`.
|
1382
|
-
|
1383
|
-
Raises:
|
1384
|
-
httpx.RequestError: if the block document was not found for any reason
|
1385
|
-
|
1386
|
-
Returns:
|
1387
|
-
A block document or None.
|
1388
|
-
"""
|
1389
|
-
try:
|
1390
|
-
response = await self._client.get(
|
1391
|
-
f"/block_types/slug/{block_type_slug}/block_documents/name/{name}",
|
1392
|
-
params=dict(include_secrets=include_secrets),
|
1393
|
-
)
|
1394
|
-
except httpx.HTTPStatusError as e:
|
1395
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
1396
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
1397
|
-
else:
|
1398
|
-
raise
|
1399
|
-
return BlockDocument.model_validate(response.json())
|
1400
|
-
|
1401
|
-
async def read_block_documents(
|
1402
|
-
self,
|
1403
|
-
block_schema_type: Optional[str] = None,
|
1404
|
-
offset: Optional[int] = None,
|
1405
|
-
limit: Optional[int] = None,
|
1406
|
-
include_secrets: bool = True,
|
1407
|
-
) -> list[BlockDocument]:
|
1408
|
-
"""
|
1409
|
-
Read block documents
|
1410
|
-
|
1411
|
-
Args:
|
1412
|
-
block_schema_type: an optional block schema type
|
1413
|
-
offset: an offset
|
1414
|
-
limit: the number of blocks to return
|
1415
|
-
include_secrets (bool): whether to include secret values
|
1416
|
-
on the Block, corresponding to Pydantic's `SecretStr` and
|
1417
|
-
`SecretBytes` fields. These fields are automatically obfuscated
|
1418
|
-
by Pydantic, but users can additionally choose not to receive
|
1419
|
-
their values from the API. Note that any business logic on the
|
1420
|
-
Block may not work if this is `False`.
|
1421
|
-
|
1422
|
-
Returns:
|
1423
|
-
A list of block documents
|
1424
|
-
"""
|
1425
|
-
response = await self._client.post(
|
1426
|
-
"/block_documents/filter",
|
1427
|
-
json=dict(
|
1428
|
-
block_schema_type=block_schema_type,
|
1429
|
-
offset=offset,
|
1430
|
-
limit=limit,
|
1431
|
-
include_secrets=include_secrets,
|
1432
|
-
),
|
1433
|
-
)
|
1434
|
-
return pydantic.TypeAdapter(list[BlockDocument]).validate_python(
|
1435
|
-
response.json()
|
1436
|
-
)
|
1437
|
-
|
1438
|
-
async def read_block_documents_by_type(
|
1439
|
-
self,
|
1440
|
-
block_type_slug: str,
|
1441
|
-
offset: Optional[int] = None,
|
1442
|
-
limit: Optional[int] = None,
|
1443
|
-
include_secrets: bool = True,
|
1444
|
-
) -> list[BlockDocument]:
|
1445
|
-
"""Retrieve block documents by block type slug.
|
1446
|
-
|
1447
|
-
Args:
|
1448
|
-
block_type_slug: The block type slug.
|
1449
|
-
offset: an offset
|
1450
|
-
limit: the number of blocks to return
|
1451
|
-
include_secrets: whether to include secret values
|
1452
|
-
|
1453
|
-
Returns:
|
1454
|
-
A list of block documents
|
1455
|
-
"""
|
1456
|
-
response = await self._client.get(
|
1457
|
-
f"/block_types/slug/{block_type_slug}/block_documents",
|
1458
|
-
params=dict(
|
1459
|
-
offset=offset,
|
1460
|
-
limit=limit,
|
1461
|
-
include_secrets=include_secrets,
|
1462
|
-
),
|
1463
|
-
)
|
1464
|
-
|
1465
|
-
return pydantic.TypeAdapter(list[BlockDocument]).validate_python(
|
1466
|
-
response.json()
|
1467
|
-
)
|
1468
|
-
|
1469
|
-
async def create_deployment(
|
1470
|
-
self,
|
1471
|
-
flow_id: UUID,
|
1472
|
-
name: str,
|
1473
|
-
version: Optional[str] = None,
|
1474
|
-
schedules: Optional[list[DeploymentScheduleCreate]] = None,
|
1475
|
-
concurrency_limit: Optional[int] = None,
|
1476
|
-
concurrency_options: Optional[ConcurrencyOptions] = None,
|
1477
|
-
parameters: Optional[dict[str, Any]] = None,
|
1478
|
-
description: Optional[str] = None,
|
1479
|
-
work_queue_name: Optional[str] = None,
|
1480
|
-
work_pool_name: Optional[str] = None,
|
1481
|
-
tags: Optional[list[str]] = None,
|
1482
|
-
storage_document_id: Optional[UUID] = None,
|
1483
|
-
path: Optional[str] = None,
|
1484
|
-
entrypoint: Optional[str] = None,
|
1485
|
-
infrastructure_document_id: Optional[UUID] = None,
|
1486
|
-
parameter_openapi_schema: Optional[dict[str, Any]] = None,
|
1487
|
-
paused: Optional[bool] = None,
|
1488
|
-
pull_steps: Optional[list[dict[str, Any]]] = None,
|
1489
|
-
enforce_parameter_schema: Optional[bool] = None,
|
1490
|
-
job_variables: Optional[dict[str, Any]] = None,
|
1491
|
-
) -> UUID:
|
1492
|
-
"""
|
1493
|
-
Create a deployment.
|
1494
|
-
|
1495
|
-
Args:
|
1496
|
-
flow_id: the flow ID to create a deployment for
|
1497
|
-
name: the name of the deployment
|
1498
|
-
version: an optional version string for the deployment
|
1499
|
-
tags: an optional list of tags to apply to the deployment
|
1500
|
-
storage_document_id: an reference to the storage block document
|
1501
|
-
used for the deployed flow
|
1502
|
-
infrastructure_document_id: an reference to the infrastructure block document
|
1503
|
-
to use for this deployment
|
1504
|
-
job_variables: A dictionary of dot delimited infrastructure overrides that
|
1505
|
-
will be applied at runtime; for example `env.CONFIG_KEY=config_value` or
|
1506
|
-
`namespace='prefect'`. This argument was previously named `infra_overrides`.
|
1507
|
-
Both arguments are supported for backwards compatibility.
|
1508
|
-
|
1509
|
-
Raises:
|
1510
|
-
httpx.RequestError: if the deployment was not created for any reason
|
1511
|
-
|
1512
|
-
Returns:
|
1513
|
-
the ID of the deployment in the backend
|
1514
|
-
"""
|
1515
|
-
|
1516
|
-
if parameter_openapi_schema is None:
|
1517
|
-
parameter_openapi_schema = {}
|
1518
|
-
deployment_create = DeploymentCreate(
|
1519
|
-
flow_id=flow_id,
|
1520
|
-
name=name,
|
1521
|
-
version=version,
|
1522
|
-
parameters=dict(parameters or {}),
|
1523
|
-
tags=list(tags or []),
|
1524
|
-
work_queue_name=work_queue_name,
|
1525
|
-
description=description,
|
1526
|
-
storage_document_id=storage_document_id,
|
1527
|
-
path=path,
|
1528
|
-
entrypoint=entrypoint,
|
1529
|
-
infrastructure_document_id=infrastructure_document_id,
|
1530
|
-
job_variables=dict(job_variables or {}),
|
1531
|
-
parameter_openapi_schema=parameter_openapi_schema,
|
1532
|
-
paused=paused,
|
1533
|
-
schedules=schedules or [],
|
1534
|
-
concurrency_limit=concurrency_limit,
|
1535
|
-
concurrency_options=concurrency_options,
|
1536
|
-
pull_steps=pull_steps,
|
1537
|
-
enforce_parameter_schema=enforce_parameter_schema,
|
1538
|
-
)
|
1539
|
-
|
1540
|
-
if work_pool_name is not None:
|
1541
|
-
deployment_create.work_pool_name = work_pool_name
|
1542
|
-
|
1543
|
-
# Exclude newer fields that are not set to avoid compatibility issues
|
1544
|
-
exclude = {
|
1545
|
-
field
|
1546
|
-
for field in ["work_pool_name", "work_queue_name"]
|
1547
|
-
if field not in deployment_create.model_fields_set
|
1548
|
-
}
|
1549
|
-
|
1550
|
-
if deployment_create.paused is None:
|
1551
|
-
exclude.add("paused")
|
1552
|
-
|
1553
|
-
if deployment_create.pull_steps is None:
|
1554
|
-
exclude.add("pull_steps")
|
1555
|
-
|
1556
|
-
if deployment_create.enforce_parameter_schema is None:
|
1557
|
-
exclude.add("enforce_parameter_schema")
|
1558
|
-
|
1559
|
-
json = deployment_create.model_dump(mode="json", exclude=exclude)
|
1560
|
-
response = await self._client.post(
|
1561
|
-
"/deployments/",
|
1562
|
-
json=json,
|
1563
|
-
)
|
1564
|
-
deployment_id = response.json().get("id")
|
1565
|
-
if not deployment_id:
|
1566
|
-
raise httpx.RequestError(f"Malformed response: {response}")
|
1567
|
-
|
1568
|
-
return UUID(deployment_id)
|
1569
|
-
|
1570
|
-
async def set_deployment_paused_state(
|
1571
|
-
self, deployment_id: UUID, paused: bool
|
1572
|
-
) -> None:
|
1573
|
-
await self._client.patch(
|
1574
|
-
f"/deployments/{deployment_id}", json={"paused": paused}
|
1575
|
-
)
|
1576
|
-
|
1577
|
-
async def update_deployment(
|
1578
|
-
self,
|
1579
|
-
deployment_id: UUID,
|
1580
|
-
deployment: DeploymentUpdate,
|
1581
|
-
) -> None:
|
1582
|
-
await self._client.patch(
|
1583
|
-
f"/deployments/{deployment_id}",
|
1584
|
-
json=deployment.model_dump(mode="json", exclude_unset=True),
|
1585
|
-
)
|
1586
|
-
|
1587
|
-
async def _create_deployment_from_schema(self, schema: DeploymentCreate) -> UUID:
|
1588
|
-
"""
|
1589
|
-
Create a deployment from a prepared `DeploymentCreate` schema.
|
1590
|
-
"""
|
1591
|
-
# TODO: We are likely to remove this method once we have considered the
|
1592
|
-
# packaging interface for deployments further.
|
1593
|
-
response = await self._client.post(
|
1594
|
-
"/deployments/", json=schema.model_dump(mode="json")
|
1595
|
-
)
|
1596
|
-
deployment_id = response.json().get("id")
|
1597
|
-
if not deployment_id:
|
1598
|
-
raise httpx.RequestError(f"Malformed response: {response}")
|
1599
|
-
|
1600
|
-
return UUID(deployment_id)
|
1601
|
-
|
1602
|
-
async def read_deployment(
|
1603
|
-
self,
|
1604
|
-
deployment_id: Union[UUID, str],
|
1605
|
-
) -> DeploymentResponse:
|
1606
|
-
"""
|
1607
|
-
Query the Prefect API for a deployment by id.
|
1608
|
-
|
1609
|
-
Args:
|
1610
|
-
deployment_id: the deployment ID of interest
|
1611
|
-
|
1612
|
-
Returns:
|
1613
|
-
a [Deployment model][prefect.client.schemas.objects.Deployment] representation of the deployment
|
1614
|
-
"""
|
1615
|
-
if not isinstance(deployment_id, UUID):
|
1616
|
-
try:
|
1617
|
-
deployment_id = UUID(deployment_id)
|
1618
|
-
except ValueError:
|
1619
|
-
raise ValueError(f"Invalid deployment ID: {deployment_id}")
|
1620
|
-
|
1621
|
-
try:
|
1622
|
-
response = await self._client.get(f"/deployments/{deployment_id}")
|
1623
|
-
except httpx.HTTPStatusError as e:
|
1624
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
1625
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
1626
|
-
else:
|
1627
|
-
raise
|
1628
|
-
return DeploymentResponse.model_validate(response.json())
|
1629
|
-
|
1630
|
-
async def read_deployment_by_name(
|
1631
|
-
self,
|
1632
|
-
name: str,
|
1633
|
-
) -> DeploymentResponse:
|
1634
|
-
"""
|
1635
|
-
Query the Prefect API for a deployment by name.
|
1636
|
-
|
1637
|
-
Args:
|
1638
|
-
name: A deployed flow's name: <FLOW_NAME>/<DEPLOYMENT_NAME>
|
1639
|
-
|
1640
|
-
Raises:
|
1641
|
-
prefect.exceptions.ObjectNotFound: If request returns 404
|
1642
|
-
httpx.RequestError: If request fails
|
1643
|
-
|
1644
|
-
Returns:
|
1645
|
-
a Deployment model representation of the deployment
|
1646
|
-
"""
|
1647
|
-
try:
|
1648
|
-
response = await self._client.get(f"/deployments/name/{name}")
|
1649
|
-
except httpx.HTTPStatusError as e:
|
1650
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
1651
|
-
from prefect.utilities.text import fuzzy_match_string
|
1652
|
-
|
1653
|
-
deployments = await self.read_deployments()
|
1654
|
-
flow_name_map = {
|
1655
|
-
flow.id: flow.name
|
1656
|
-
for flow in await asyncio.gather(
|
1657
|
-
*[
|
1658
|
-
self.read_flow(flow_id)
|
1659
|
-
for flow_id in {d.flow_id for d in deployments}
|
1660
|
-
]
|
1661
|
-
)
|
1662
|
-
}
|
1663
|
-
|
1664
|
-
raise prefect.exceptions.ObjectNotFound(
|
1665
|
-
http_exc=e,
|
1666
|
-
help_message=(
|
1667
|
-
f"Deployment {name!r} not found; did you mean {fuzzy_match!r}?"
|
1668
|
-
if (
|
1669
|
-
fuzzy_match := fuzzy_match_string(
|
1670
|
-
name,
|
1671
|
-
[
|
1672
|
-
f"{flow_name_map[d.flow_id]}/{d.name}"
|
1673
|
-
for d in deployments
|
1674
|
-
],
|
1675
|
-
)
|
1676
|
-
)
|
1677
|
-
else f"Deployment {name!r} not found. Try `prefect deployment ls` to find available deployments."
|
1678
|
-
),
|
1679
|
-
) from e
|
1680
|
-
else:
|
1681
|
-
raise
|
1682
|
-
|
1683
|
-
return DeploymentResponse.model_validate(response.json())
|
1684
|
-
|
1685
|
-
async def read_deployments(
|
1686
|
-
self,
|
1687
|
-
*,
|
1688
|
-
flow_filter: Optional[FlowFilter] = None,
|
1689
|
-
flow_run_filter: Optional[FlowRunFilter] = None,
|
1690
|
-
task_run_filter: Optional[TaskRunFilter] = None,
|
1691
|
-
deployment_filter: Optional[DeploymentFilter] = None,
|
1692
|
-
work_pool_filter: Optional[WorkPoolFilter] = None,
|
1693
|
-
work_queue_filter: Optional[WorkQueueFilter] = None,
|
1694
|
-
limit: Optional[int] = None,
|
1695
|
-
sort: Optional[DeploymentSort] = None,
|
1696
|
-
offset: int = 0,
|
1697
|
-
) -> list[DeploymentResponse]:
|
1698
|
-
"""
|
1699
|
-
Query the Prefect API for deployments. Only deployments matching all
|
1700
|
-
the provided criteria will be returned.
|
1701
|
-
|
1702
|
-
Args:
|
1703
|
-
flow_filter: filter criteria for flows
|
1704
|
-
flow_run_filter: filter criteria for flow runs
|
1705
|
-
task_run_filter: filter criteria for task runs
|
1706
|
-
deployment_filter: filter criteria for deployments
|
1707
|
-
work_pool_filter: filter criteria for work pools
|
1708
|
-
work_queue_filter: filter criteria for work pool queues
|
1709
|
-
limit: a limit for the deployment query
|
1710
|
-
offset: an offset for the deployment query
|
1711
|
-
|
1712
|
-
Returns:
|
1713
|
-
a list of Deployment model representations
|
1714
|
-
of the deployments
|
1715
|
-
"""
|
1716
|
-
body: dict[str, Any] = {
|
1717
|
-
"flows": flow_filter.model_dump(mode="json") if flow_filter else None,
|
1718
|
-
"flow_runs": (
|
1719
|
-
flow_run_filter.model_dump(mode="json", exclude_unset=True)
|
1720
|
-
if flow_run_filter
|
1721
|
-
else None
|
1722
|
-
),
|
1723
|
-
"task_runs": (
|
1724
|
-
task_run_filter.model_dump(mode="json") if task_run_filter else None
|
1725
|
-
),
|
1726
|
-
"deployments": (
|
1727
|
-
deployment_filter.model_dump(mode="json") if deployment_filter else None
|
1728
|
-
),
|
1729
|
-
"work_pools": (
|
1730
|
-
work_pool_filter.model_dump(mode="json") if work_pool_filter else None
|
1731
|
-
),
|
1732
|
-
"work_pool_queues": (
|
1733
|
-
work_queue_filter.model_dump(mode="json") if work_queue_filter else None
|
1734
|
-
),
|
1735
|
-
"limit": limit,
|
1736
|
-
"offset": offset,
|
1737
|
-
"sort": sort,
|
1738
|
-
}
|
1739
|
-
|
1740
|
-
response = await self._client.post("/deployments/filter", json=body)
|
1741
|
-
return pydantic.TypeAdapter(list[DeploymentResponse]).validate_python(
|
1742
|
-
response.json()
|
1743
|
-
)
|
1744
|
-
|
1745
|
-
async def delete_deployment(
|
1746
|
-
self,
|
1747
|
-
deployment_id: UUID,
|
1748
|
-
) -> None:
|
1749
|
-
"""
|
1750
|
-
Delete deployment by id.
|
1751
|
-
|
1752
|
-
Args:
|
1753
|
-
deployment_id: The deployment id of interest.
|
1754
|
-
Raises:
|
1755
|
-
prefect.exceptions.ObjectNotFound: If request returns 404
|
1756
|
-
httpx.RequestError: If requests fails
|
1757
|
-
"""
|
1758
|
-
try:
|
1759
|
-
await self._client.delete(f"/deployments/{deployment_id}")
|
1760
|
-
except httpx.HTTPStatusError as e:
|
1761
|
-
if e.response.status_code == 404:
|
1762
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
1763
|
-
else:
|
1764
|
-
raise
|
1765
|
-
|
1766
|
-
async def create_deployment_schedules(
|
1767
|
-
self,
|
1768
|
-
deployment_id: UUID,
|
1769
|
-
schedules: list[tuple[SCHEDULE_TYPES, bool]],
|
1770
|
-
) -> list[DeploymentSchedule]:
|
1771
|
-
"""
|
1772
|
-
Create deployment schedules.
|
1773
|
-
|
1774
|
-
Args:
|
1775
|
-
deployment_id: the deployment ID
|
1776
|
-
schedules: a list of tuples containing the schedule to create
|
1777
|
-
and whether or not it should be active.
|
1778
|
-
|
1779
|
-
Raises:
|
1780
|
-
httpx.RequestError: if the schedules were not created for any reason
|
1781
|
-
|
1782
|
-
Returns:
|
1783
|
-
the list of schedules created in the backend
|
1784
|
-
"""
|
1785
|
-
deployment_schedule_create = [
|
1786
|
-
DeploymentScheduleCreate(schedule=schedule[0], active=schedule[1])
|
1787
|
-
for schedule in schedules
|
1788
|
-
]
|
1789
|
-
|
1790
|
-
json = [
|
1791
|
-
deployment_schedule_create.model_dump(mode="json")
|
1792
|
-
for deployment_schedule_create in deployment_schedule_create
|
1793
|
-
]
|
1794
|
-
response = await self._client.post(
|
1795
|
-
f"/deployments/{deployment_id}/schedules", json=json
|
1796
|
-
)
|
1797
|
-
return pydantic.TypeAdapter(list[DeploymentSchedule]).validate_python(
|
1798
|
-
response.json()
|
1799
|
-
)
|
1800
|
-
|
1801
|
-
async def read_deployment_schedules(
|
1802
|
-
self,
|
1803
|
-
deployment_id: UUID,
|
1804
|
-
) -> list[DeploymentSchedule]:
|
1805
|
-
"""
|
1806
|
-
Query the Prefect API for a deployment's schedules.
|
1807
|
-
|
1808
|
-
Args:
|
1809
|
-
deployment_id: the deployment ID
|
1810
|
-
|
1811
|
-
Returns:
|
1812
|
-
a list of DeploymentSchedule model representations of the deployment schedules
|
1813
|
-
"""
|
1814
|
-
try:
|
1815
|
-
response = await self._client.get(f"/deployments/{deployment_id}/schedules")
|
1816
|
-
except httpx.HTTPStatusError as e:
|
1817
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
1818
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
1819
|
-
else:
|
1820
|
-
raise
|
1821
|
-
return pydantic.TypeAdapter(list[DeploymentSchedule]).validate_python(
|
1822
|
-
response.json()
|
1823
|
-
)
|
1824
|
-
|
1825
|
-
async def update_deployment_schedule(
|
1826
|
-
self,
|
1827
|
-
deployment_id: UUID,
|
1828
|
-
schedule_id: UUID,
|
1829
|
-
active: Optional[bool] = None,
|
1830
|
-
schedule: Optional[SCHEDULE_TYPES] = None,
|
1831
|
-
) -> None:
|
1832
|
-
"""
|
1833
|
-
Update a deployment schedule by ID.
|
1834
|
-
|
1835
|
-
Args:
|
1836
|
-
deployment_id: the deployment ID
|
1837
|
-
schedule_id: the deployment schedule ID of interest
|
1838
|
-
active: whether or not the schedule should be active
|
1839
|
-
schedule: the cron, rrule, or interval schedule this deployment schedule should use
|
1840
|
-
"""
|
1841
|
-
kwargs: dict[str, Any] = {}
|
1842
|
-
if active is not None:
|
1843
|
-
kwargs["active"] = active
|
1844
|
-
if schedule is not None:
|
1845
|
-
kwargs["schedule"] = schedule
|
1846
|
-
|
1847
|
-
deployment_schedule_update = DeploymentScheduleUpdate(**kwargs)
|
1848
|
-
json = deployment_schedule_update.model_dump(mode="json", exclude_unset=True)
|
1849
|
-
|
1850
|
-
try:
|
1851
|
-
await self._client.patch(
|
1852
|
-
f"/deployments/{deployment_id}/schedules/{schedule_id}", json=json
|
1853
|
-
)
|
1854
|
-
except httpx.HTTPStatusError as e:
|
1855
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
1856
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
1857
|
-
else:
|
1858
|
-
raise
|
1859
|
-
|
1860
|
-
async def delete_deployment_schedule(
|
1861
|
-
self,
|
1862
|
-
deployment_id: UUID,
|
1863
|
-
schedule_id: UUID,
|
1864
|
-
) -> None:
|
1865
|
-
"""
|
1866
|
-
Delete a deployment schedule.
|
1867
|
-
|
1868
|
-
Args:
|
1869
|
-
deployment_id: the deployment ID
|
1870
|
-
schedule_id: the ID of the deployment schedule to delete.
|
1871
|
-
|
1872
|
-
Raises:
|
1873
|
-
httpx.RequestError: if the schedules were not deleted for any reason
|
1874
|
-
"""
|
1875
|
-
try:
|
1876
|
-
await self._client.delete(
|
1877
|
-
f"/deployments/{deployment_id}/schedules/{schedule_id}"
|
1878
|
-
)
|
1879
|
-
except httpx.HTTPStatusError as e:
|
1880
|
-
if e.response.status_code == 404:
|
1881
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
1882
|
-
else:
|
1883
|
-
raise
|
1884
|
-
|
1885
|
-
async def read_flow_run(self, flow_run_id: UUID) -> FlowRun:
|
1886
|
-
"""
|
1887
|
-
Query the Prefect API for a flow run by id.
|
1888
|
-
|
1889
|
-
Args:
|
1890
|
-
flow_run_id: the flow run ID of interest
|
1891
|
-
|
1892
|
-
Returns:
|
1893
|
-
a Flow Run model representation of the flow run
|
1894
|
-
"""
|
1895
|
-
try:
|
1896
|
-
response = await self._client.get(f"/flow_runs/{flow_run_id}")
|
1897
|
-
except httpx.HTTPStatusError as e:
|
1898
|
-
if e.response.status_code == 404:
|
1899
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
1900
|
-
else:
|
1901
|
-
raise
|
1902
|
-
return FlowRun.model_validate(response.json())
|
1903
|
-
|
1904
|
-
async def resume_flow_run(
|
1905
|
-
self, flow_run_id: UUID, run_input: Optional[dict[str, Any]] = None
|
1906
|
-
) -> OrchestrationResult[Any]:
|
1907
|
-
"""
|
1908
|
-
Resumes a paused flow run.
|
1909
|
-
|
1910
|
-
Args:
|
1911
|
-
flow_run_id: the flow run ID of interest
|
1912
|
-
run_input: the input to resume the flow run with
|
1913
|
-
|
1914
|
-
Returns:
|
1915
|
-
an OrchestrationResult model representation of state orchestration output
|
1916
|
-
"""
|
1917
|
-
try:
|
1918
|
-
response = await self._client.post(
|
1919
|
-
f"/flow_runs/{flow_run_id}/resume", json={"run_input": run_input}
|
1920
|
-
)
|
1921
|
-
except httpx.HTTPStatusError:
|
1922
|
-
raise
|
1923
|
-
|
1924
|
-
result: OrchestrationResult[Any] = OrchestrationResult.model_validate(
|
1925
|
-
response.json()
|
1926
|
-
)
|
1927
|
-
return result
|
1928
|
-
|
1929
|
-
async def read_flow_runs(
|
1930
|
-
self,
|
1931
|
-
*,
|
1932
|
-
flow_filter: Optional[FlowFilter] = None,
|
1933
|
-
flow_run_filter: Optional[FlowRunFilter] = None,
|
1934
|
-
task_run_filter: Optional[TaskRunFilter] = None,
|
1935
|
-
deployment_filter: Optional[DeploymentFilter] = None,
|
1936
|
-
work_pool_filter: Optional[WorkPoolFilter] = None,
|
1937
|
-
work_queue_filter: Optional[WorkQueueFilter] = None,
|
1938
|
-
sort: Optional[FlowRunSort] = None,
|
1939
|
-
limit: Optional[int] = None,
|
1940
|
-
offset: int = 0,
|
1941
|
-
) -> list[FlowRun]:
|
1942
|
-
"""
|
1943
|
-
Query the Prefect API for flow runs. Only flow runs matching all criteria will
|
1944
|
-
be returned.
|
1945
|
-
|
1946
|
-
Args:
|
1947
|
-
flow_filter: filter criteria for flows
|
1948
|
-
flow_run_filter: filter criteria for flow runs
|
1949
|
-
task_run_filter: filter criteria for task runs
|
1950
|
-
deployment_filter: filter criteria for deployments
|
1951
|
-
work_pool_filter: filter criteria for work pools
|
1952
|
-
work_queue_filter: filter criteria for work pool queues
|
1953
|
-
sort: sort criteria for the flow runs
|
1954
|
-
limit: limit for the flow run query
|
1955
|
-
offset: offset for the flow run query
|
1956
|
-
|
1957
|
-
Returns:
|
1958
|
-
a list of Flow Run model representations
|
1959
|
-
of the flow runs
|
1960
|
-
"""
|
1961
|
-
body: dict[str, Any] = {
|
1962
|
-
"flows": flow_filter.model_dump(mode="json") if flow_filter else None,
|
1963
|
-
"flow_runs": (
|
1964
|
-
flow_run_filter.model_dump(mode="json", exclude_unset=True)
|
1965
|
-
if flow_run_filter
|
1966
|
-
else None
|
1967
|
-
),
|
1968
|
-
"task_runs": (
|
1969
|
-
task_run_filter.model_dump(mode="json") if task_run_filter else None
|
1970
|
-
),
|
1971
|
-
"deployments": (
|
1972
|
-
deployment_filter.model_dump(mode="json") if deployment_filter else None
|
1973
|
-
),
|
1974
|
-
"work_pools": (
|
1975
|
-
work_pool_filter.model_dump(mode="json") if work_pool_filter else None
|
1976
|
-
),
|
1977
|
-
"work_pool_queues": (
|
1978
|
-
work_queue_filter.model_dump(mode="json") if work_queue_filter else None
|
1979
|
-
),
|
1980
|
-
"sort": sort,
|
1981
|
-
"limit": limit,
|
1982
|
-
"offset": offset,
|
1983
|
-
}
|
1984
|
-
|
1985
|
-
response = await self._client.post("/flow_runs/filter", json=body)
|
1986
|
-
return pydantic.TypeAdapter(list[FlowRun]).validate_python(response.json())
|
1987
|
-
|
1988
|
-
async def set_flow_run_state(
|
1989
|
-
self,
|
1990
|
-
flow_run_id: Union[UUID, str],
|
1991
|
-
state: "prefect.states.State[T]",
|
1992
|
-
force: bool = False,
|
1993
|
-
) -> OrchestrationResult[T]:
|
1994
|
-
"""
|
1995
|
-
Set the state of a flow run.
|
1996
|
-
|
1997
|
-
Args:
|
1998
|
-
flow_run_id: the id of the flow run
|
1999
|
-
state: the state to set
|
2000
|
-
force: if True, disregard orchestration logic when setting the state,
|
2001
|
-
forcing the Prefect API to accept the state
|
2002
|
-
|
2003
|
-
Returns:
|
2004
|
-
an OrchestrationResult model representation of state orchestration output
|
2005
|
-
"""
|
2006
|
-
flow_run_id = (
|
2007
|
-
flow_run_id if isinstance(flow_run_id, UUID) else UUID(flow_run_id)
|
2008
|
-
)
|
2009
|
-
state_create = state.to_state_create()
|
2010
|
-
state_create.state_details.flow_run_id = flow_run_id
|
2011
|
-
state_create.state_details.transition_id = uuid4()
|
2012
|
-
try:
|
2013
|
-
response = await self._client.post(
|
2014
|
-
f"/flow_runs/{flow_run_id}/set_state",
|
2015
|
-
json=dict(
|
2016
|
-
state=state_create.model_dump(mode="json", serialize_as_any=True),
|
2017
|
-
force=force,
|
2018
|
-
),
|
2019
|
-
)
|
2020
|
-
except httpx.HTTPStatusError as e:
|
2021
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
2022
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
2023
|
-
else:
|
2024
|
-
raise
|
2025
|
-
|
2026
|
-
result: OrchestrationResult[T] = OrchestrationResult.model_validate(
|
2027
|
-
response.json()
|
2028
|
-
)
|
2029
|
-
return result
|
2030
|
-
|
2031
|
-
async def read_flow_run_states(
|
2032
|
-
self, flow_run_id: UUID
|
2033
|
-
) -> list[prefect.states.State]:
|
2034
|
-
"""
|
2035
|
-
Query for the states of a flow run
|
2036
|
-
|
2037
|
-
Args:
|
2038
|
-
flow_run_id: the id of the flow run
|
2039
|
-
|
2040
|
-
Returns:
|
2041
|
-
a list of State model representations
|
2042
|
-
of the flow run states
|
2043
|
-
"""
|
2044
|
-
response = await self._client.get(
|
2045
|
-
"/flow_run_states/", params=dict(flow_run_id=str(flow_run_id))
|
2046
|
-
)
|
2047
|
-
return pydantic.TypeAdapter(list[prefect.states.State]).validate_python(
|
2048
|
-
response.json()
|
2049
|
-
)
|
2050
|
-
|
2051
|
-
async def set_flow_run_name(self, flow_run_id: UUID, name: str) -> httpx.Response:
|
2052
|
-
flow_run_data = FlowRunUpdate(name=name)
|
2053
|
-
return await self._client.patch(
|
2054
|
-
f"/flow_runs/{flow_run_id}",
|
2055
|
-
json=flow_run_data.model_dump(mode="json", exclude_unset=True),
|
2056
|
-
)
|
2057
|
-
|
2058
|
-
async def set_task_run_name(self, task_run_id: UUID, name: str) -> httpx.Response:
|
2059
|
-
task_run_data = TaskRunUpdate(name=name)
|
2060
|
-
return await self._client.patch(
|
2061
|
-
f"/task_runs/{task_run_id}",
|
2062
|
-
json=task_run_data.model_dump(mode="json", exclude_unset=True),
|
2063
|
-
)
|
2064
|
-
|
2065
|
-
async def create_task_run(
|
2066
|
-
self,
|
2067
|
-
task: "TaskObject[P, R]",
|
2068
|
-
flow_run_id: Optional[UUID],
|
2069
|
-
dynamic_key: str,
|
2070
|
-
id: Optional[UUID] = None,
|
2071
|
-
name: Optional[str] = None,
|
2072
|
-
extra_tags: Optional[Iterable[str]] = None,
|
2073
|
-
state: Optional[prefect.states.State[R]] = None,
|
2074
|
-
task_inputs: Optional[
|
2075
|
-
dict[
|
2076
|
-
str,
|
2077
|
-
list[
|
2078
|
-
Union[
|
2079
|
-
TaskRunResult,
|
2080
|
-
Parameter,
|
2081
|
-
Constant,
|
2082
|
-
]
|
2083
|
-
],
|
2084
|
-
]
|
2085
|
-
] = None,
|
2086
|
-
) -> TaskRun:
|
2087
|
-
"""
|
2088
|
-
Create a task run
|
775
|
+
Create a task run
|
2089
776
|
|
2090
777
|
Args:
|
2091
778
|
task: The Task to run
|
@@ -2666,251 +1353,46 @@ class PrefectClient(
|
|
2666
1353
|
|
2667
1354
|
return pydantic.TypeAdapter(list[WorkQueue]).validate_python(response.json())
|
2668
1355
|
|
2669
|
-
async def get_scheduled_flow_runs_for_deployments(
|
2670
|
-
self,
|
2671
|
-
deployment_ids: list[UUID],
|
2672
|
-
scheduled_before: Optional[datetime.datetime] = None,
|
2673
|
-
limit: Optional[int] = None,
|
2674
|
-
) -> list[FlowRunResponse]:
|
2675
|
-
body: dict[str, Any] = dict(deployment_ids=[str(id) for id in deployment_ids])
|
2676
|
-
if scheduled_before:
|
2677
|
-
body["scheduled_before"] = str(scheduled_before)
|
2678
|
-
if limit:
|
2679
|
-
body["limit"] = limit
|
2680
|
-
|
2681
|
-
response = await self._client.post(
|
2682
|
-
"/deployments/get_scheduled_flow_runs",
|
2683
|
-
json=body,
|
2684
|
-
)
|
2685
|
-
|
2686
|
-
return pydantic.TypeAdapter(list[FlowRunResponse]).validate_python(
|
2687
|
-
response.json()
|
2688
|
-
)
|
2689
|
-
|
2690
1356
|
async def get_scheduled_flow_runs_for_work_pool(
|
2691
1357
|
self,
|
2692
1358
|
work_pool_name: str,
|
2693
1359
|
work_queue_names: Optional[list[str]] = None,
|
2694
1360
|
scheduled_before: Optional[datetime.datetime] = None,
|
2695
|
-
) -> list[WorkerFlowRunResponse]:
|
2696
|
-
"""
|
2697
|
-
Retrieves scheduled flow runs for the provided set of work pool queues.
|
2698
|
-
|
2699
|
-
Args:
|
2700
|
-
work_pool_name: The name of the work pool that the work pool
|
2701
|
-
queues are associated with.
|
2702
|
-
work_queue_names: The names of the work pool queues from which
|
2703
|
-
to get scheduled flow runs.
|
2704
|
-
scheduled_before: Datetime used to filter returned flow runs. Flow runs
|
2705
|
-
scheduled for after the given datetime string will not be returned.
|
2706
|
-
|
2707
|
-
Returns:
|
2708
|
-
A list of worker flow run responses containing information about the
|
2709
|
-
retrieved flow runs.
|
2710
|
-
"""
|
2711
|
-
body: dict[str, Any] = {}
|
2712
|
-
if work_queue_names is not None:
|
2713
|
-
body["work_queue_names"] = list(work_queue_names)
|
2714
|
-
if scheduled_before:
|
2715
|
-
body["scheduled_before"] = str(scheduled_before)
|
2716
|
-
|
2717
|
-
response = await self._client.post(
|
2718
|
-
f"/work_pools/{work_pool_name}/get_scheduled_flow_runs",
|
2719
|
-
json=body,
|
2720
|
-
)
|
2721
|
-
return pydantic.TypeAdapter(list[WorkerFlowRunResponse]).validate_python(
|
2722
|
-
response.json()
|
2723
|
-
)
|
2724
|
-
|
2725
|
-
async def read_worker_metadata(self) -> dict[str, Any]:
|
2726
|
-
"""Reads worker metadata stored in Prefect collection registry."""
|
2727
|
-
response = await self._client.get("collections/views/aggregate-worker-metadata")
|
2728
|
-
response.raise_for_status()
|
2729
|
-
return response.json()
|
2730
|
-
|
2731
|
-
async def create_flow_run_input(
|
2732
|
-
self, flow_run_id: UUID, key: str, value: str, sender: Optional[str] = None
|
2733
|
-
) -> None:
|
2734
|
-
"""
|
2735
|
-
Creates a flow run input.
|
2736
|
-
|
2737
|
-
Args:
|
2738
|
-
flow_run_id: The flow run id.
|
2739
|
-
key: The input key.
|
2740
|
-
value: The input value.
|
2741
|
-
sender: The sender of the input.
|
2742
|
-
"""
|
2743
|
-
|
2744
|
-
# Initialize the input to ensure that the key is valid.
|
2745
|
-
FlowRunInput(flow_run_id=flow_run_id, key=key, value=value)
|
2746
|
-
|
2747
|
-
response = await self._client.post(
|
2748
|
-
f"/flow_runs/{flow_run_id}/input",
|
2749
|
-
json={"key": key, "value": value, "sender": sender},
|
2750
|
-
)
|
2751
|
-
response.raise_for_status()
|
2752
|
-
|
2753
|
-
async def filter_flow_run_input(
|
2754
|
-
self, flow_run_id: UUID, key_prefix: str, limit: int, exclude_keys: set[str]
|
2755
|
-
) -> list[FlowRunInput]:
|
2756
|
-
response = await self._client.post(
|
2757
|
-
f"/flow_runs/{flow_run_id}/input/filter",
|
2758
|
-
json={
|
2759
|
-
"prefix": key_prefix,
|
2760
|
-
"limit": limit,
|
2761
|
-
"exclude_keys": list(exclude_keys),
|
2762
|
-
},
|
2763
|
-
)
|
2764
|
-
response.raise_for_status()
|
2765
|
-
return pydantic.TypeAdapter(list[FlowRunInput]).validate_python(response.json())
|
2766
|
-
|
2767
|
-
async def read_flow_run_input(self, flow_run_id: UUID, key: str) -> str:
|
2768
|
-
"""
|
2769
|
-
Reads a flow run input.
|
2770
|
-
|
2771
|
-
Args:
|
2772
|
-
flow_run_id: The flow run id.
|
2773
|
-
key: The input key.
|
2774
|
-
"""
|
2775
|
-
response = await self._client.get(f"/flow_runs/{flow_run_id}/input/{key}")
|
2776
|
-
response.raise_for_status()
|
2777
|
-
return response.content.decode()
|
2778
|
-
|
2779
|
-
async def delete_flow_run_input(self, flow_run_id: UUID, key: str) -> None:
|
2780
|
-
"""
|
2781
|
-
Deletes a flow run input.
|
2782
|
-
|
2783
|
-
Args:
|
2784
|
-
flow_run_id: The flow run id.
|
2785
|
-
key: The input key.
|
2786
|
-
"""
|
2787
|
-
response = await self._client.delete(f"/flow_runs/{flow_run_id}/input/{key}")
|
2788
|
-
response.raise_for_status()
|
2789
|
-
|
2790
|
-
async def create_automation(self, automation: AutomationCore) -> UUID:
|
2791
|
-
"""Creates an automation in Prefect Cloud."""
|
2792
|
-
response = await self._client.post(
|
2793
|
-
"/automations/",
|
2794
|
-
json=automation.model_dump(mode="json"),
|
2795
|
-
)
|
2796
|
-
|
2797
|
-
return UUID(response.json()["id"])
|
2798
|
-
|
2799
|
-
async def update_automation(
|
2800
|
-
self, automation_id: UUID, automation: AutomationCore
|
2801
|
-
) -> None:
|
2802
|
-
"""Updates an automation in Prefect Cloud."""
|
2803
|
-
response = await self._client.put(
|
2804
|
-
f"/automations/{automation_id}",
|
2805
|
-
json=automation.model_dump(mode="json", exclude_unset=True),
|
2806
|
-
)
|
2807
|
-
response.raise_for_status
|
2808
|
-
|
2809
|
-
async def read_automations(self) -> list[Automation]:
|
2810
|
-
response = await self._client.post("/automations/filter")
|
2811
|
-
response.raise_for_status()
|
2812
|
-
return pydantic.TypeAdapter(list[Automation]).validate_python(response.json())
|
2813
|
-
|
2814
|
-
async def find_automation(
|
2815
|
-
self, id_or_name: Union[str, UUID]
|
2816
|
-
) -> Optional[Automation]:
|
2817
|
-
if isinstance(id_or_name, str):
|
2818
|
-
name = id_or_name
|
2819
|
-
try:
|
2820
|
-
id = UUID(id_or_name)
|
2821
|
-
except ValueError:
|
2822
|
-
id = None
|
2823
|
-
else:
|
2824
|
-
id = id_or_name
|
2825
|
-
name = str(id)
|
2826
|
-
|
2827
|
-
if id:
|
2828
|
-
try:
|
2829
|
-
automation = await self.read_automation(id)
|
2830
|
-
return automation
|
2831
|
-
except prefect.exceptions.HTTPStatusError as e:
|
2832
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
2833
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
2834
|
-
|
2835
|
-
automations = await self.read_automations()
|
2836
|
-
|
2837
|
-
# Look for it by an exact name
|
2838
|
-
for automation in automations:
|
2839
|
-
if automation.name == name:
|
2840
|
-
return automation
|
2841
|
-
|
2842
|
-
# Look for it by a case-insensitive name
|
2843
|
-
for automation in automations:
|
2844
|
-
if automation.name.lower() == name.lower():
|
2845
|
-
return automation
|
2846
|
-
|
2847
|
-
return None
|
2848
|
-
|
2849
|
-
async def read_automation(
|
2850
|
-
self, automation_id: Union[UUID, str]
|
2851
|
-
) -> Optional[Automation]:
|
2852
|
-
response = await self._client.get(f"/automations/{automation_id}")
|
2853
|
-
if response.status_code == 404:
|
2854
|
-
return None
|
2855
|
-
response.raise_for_status()
|
2856
|
-
return Automation.model_validate(response.json())
|
2857
|
-
|
2858
|
-
async def read_automations_by_name(self, name: str) -> list[Automation]:
|
1361
|
+
) -> list[WorkerFlowRunResponse]:
|
2859
1362
|
"""
|
2860
|
-
|
1363
|
+
Retrieves scheduled flow runs for the provided set of work pool queues.
|
2861
1364
|
|
2862
1365
|
Args:
|
2863
|
-
|
1366
|
+
work_pool_name: The name of the work pool that the work pool
|
1367
|
+
queues are associated with.
|
1368
|
+
work_queue_names: The names of the work pool queues from which
|
1369
|
+
to get scheduled flow runs.
|
1370
|
+
scheduled_before: Datetime used to filter returned flow runs. Flow runs
|
1371
|
+
scheduled for after the given datetime string will not be returned.
|
2864
1372
|
|
2865
1373
|
Returns:
|
2866
|
-
|
1374
|
+
A list of worker flow run responses containing information about the
|
1375
|
+
retrieved flow runs.
|
2867
1376
|
"""
|
2868
|
-
|
2869
|
-
|
2870
|
-
|
1377
|
+
body: dict[str, Any] = {}
|
1378
|
+
if work_queue_names is not None:
|
1379
|
+
body["work_queue_names"] = list(work_queue_names)
|
1380
|
+
if scheduled_before:
|
1381
|
+
body["scheduled_before"] = str(scheduled_before)
|
2871
1382
|
|
2872
1383
|
response = await self._client.post(
|
2873
|
-
"/
|
2874
|
-
json=
|
2875
|
-
"sort": sorting.AutomationSort.UPDATED_DESC,
|
2876
|
-
"automations": automation_filter.model_dump(mode="json")
|
2877
|
-
if automation_filter
|
2878
|
-
else None,
|
2879
|
-
},
|
2880
|
-
)
|
2881
|
-
|
2882
|
-
response.raise_for_status()
|
2883
|
-
|
2884
|
-
return pydantic.TypeAdapter(list[Automation]).validate_python(response.json())
|
2885
|
-
|
2886
|
-
async def pause_automation(self, automation_id: UUID) -> None:
|
2887
|
-
response = await self._client.patch(
|
2888
|
-
f"/automations/{automation_id}", json={"enabled": False}
|
1384
|
+
f"/work_pools/{work_pool_name}/get_scheduled_flow_runs",
|
1385
|
+
json=body,
|
2889
1386
|
)
|
2890
|
-
|
2891
|
-
|
2892
|
-
async def resume_automation(self, automation_id: UUID) -> None:
|
2893
|
-
response = await self._client.patch(
|
2894
|
-
f"/automations/{automation_id}", json={"enabled": True}
|
1387
|
+
return pydantic.TypeAdapter(list[WorkerFlowRunResponse]).validate_python(
|
1388
|
+
response.json()
|
2895
1389
|
)
|
2896
|
-
response.raise_for_status()
|
2897
|
-
|
2898
|
-
async def delete_automation(self, automation_id: UUID) -> None:
|
2899
|
-
response = await self._client.delete(f"/automations/{automation_id}")
|
2900
|
-
if response.status_code == 404:
|
2901
|
-
return
|
2902
1390
|
|
1391
|
+
async def read_worker_metadata(self) -> dict[str, Any]:
|
1392
|
+
"""Reads worker metadata stored in Prefect collection registry."""
|
1393
|
+
response = await self._client.get("collections/views/aggregate-worker-metadata")
|
2903
1394
|
response.raise_for_status()
|
2904
|
-
|
2905
|
-
async def read_resource_related_automations(
|
2906
|
-
self, resource_id: str
|
2907
|
-
) -> list[Automation]:
|
2908
|
-
response = await self._client.get(f"/automations/related-to/{resource_id}")
|
2909
|
-
response.raise_for_status()
|
2910
|
-
return pydantic.TypeAdapter(list[Automation]).validate_python(response.json())
|
2911
|
-
|
2912
|
-
async def delete_resource_owned_automations(self, resource_id: str) -> None:
|
2913
|
-
await self._client.delete(f"/automations/owned-by/{resource_id}")
|
1395
|
+
return response.json()
|
2914
1396
|
|
2915
1397
|
async def api_version(self) -> str:
|
2916
1398
|
res = await self._client.get("/admin/version")
|
@@ -2940,18 +1422,6 @@ class PrefectClient(
|
|
2940
1422
|
f"Major versions must match."
|
2941
1423
|
)
|
2942
1424
|
|
2943
|
-
async def update_flow_run_labels(
|
2944
|
-
self, flow_run_id: UUID, labels: KeyValueLabelsField
|
2945
|
-
) -> None:
|
2946
|
-
"""
|
2947
|
-
Updates the labels of a flow run.
|
2948
|
-
"""
|
2949
|
-
|
2950
|
-
response = await self._client.patch(
|
2951
|
-
f"/flow_runs/{flow_run_id}/labels", json=labels
|
2952
|
-
)
|
2953
|
-
response.raise_for_status()
|
2954
|
-
|
2955
1425
|
async def __aenter__(self) -> Self:
|
2956
1426
|
"""
|
2957
1427
|
Start the client.
|
@@ -3026,6 +1496,14 @@ class SyncPrefectClient(
|
|
3026
1496
|
LogClient,
|
3027
1497
|
VariableClient,
|
3028
1498
|
ConcurrencyLimitClient,
|
1499
|
+
DeploymentClient,
|
1500
|
+
AutomationClient,
|
1501
|
+
SlaClient,
|
1502
|
+
FlowRunClient,
|
1503
|
+
FlowClient,
|
1504
|
+
BlocksDocumentClient,
|
1505
|
+
BlocksSchemaClient,
|
1506
|
+
BlocksTypeClient,
|
3029
1507
|
):
|
3030
1508
|
"""
|
3031
1509
|
A synchronous client for interacting with the [Prefect REST API](/api-ref/rest-api/).
|
@@ -3284,288 +1762,6 @@ class SyncPrefectClient(
|
|
3284
1762
|
f"Major versions must match."
|
3285
1763
|
)
|
3286
1764
|
|
3287
|
-
def create_flow(self, flow: "FlowObject[Any, Any]") -> UUID:
|
3288
|
-
"""
|
3289
|
-
Create a flow in the Prefect API.
|
3290
|
-
|
3291
|
-
Args:
|
3292
|
-
flow: a [Flow][prefect.flows.Flow] object
|
3293
|
-
|
3294
|
-
Raises:
|
3295
|
-
httpx.RequestError: if a flow was not created for any reason
|
3296
|
-
|
3297
|
-
Returns:
|
3298
|
-
the ID of the flow in the backend
|
3299
|
-
"""
|
3300
|
-
return self.create_flow_from_name(flow.name)
|
3301
|
-
|
3302
|
-
def create_flow_from_name(self, flow_name: str) -> UUID:
|
3303
|
-
"""
|
3304
|
-
Create a flow in the Prefect API.
|
3305
|
-
|
3306
|
-
Args:
|
3307
|
-
flow_name: the name of the new flow
|
3308
|
-
|
3309
|
-
Raises:
|
3310
|
-
httpx.RequestError: if a flow was not created for any reason
|
3311
|
-
|
3312
|
-
Returns:
|
3313
|
-
the ID of the flow in the backend
|
3314
|
-
"""
|
3315
|
-
flow_data = FlowCreate(name=flow_name)
|
3316
|
-
response = self._client.post("/flows/", json=flow_data.model_dump(mode="json"))
|
3317
|
-
|
3318
|
-
flow_id = response.json().get("id")
|
3319
|
-
if not flow_id:
|
3320
|
-
raise httpx.RequestError(f"Malformed response: {response}")
|
3321
|
-
|
3322
|
-
# Return the id of the created flow
|
3323
|
-
return UUID(flow_id)
|
3324
|
-
|
3325
|
-
def create_flow_run(
|
3326
|
-
self,
|
3327
|
-
flow: "FlowObject[Any, R]",
|
3328
|
-
name: Optional[str] = None,
|
3329
|
-
parameters: Optional[dict[str, Any]] = None,
|
3330
|
-
context: Optional[dict[str, Any]] = None,
|
3331
|
-
tags: Optional[Iterable[str]] = None,
|
3332
|
-
parent_task_run_id: Optional[UUID] = None,
|
3333
|
-
state: Optional["prefect.states.State[R]"] = None,
|
3334
|
-
) -> FlowRun:
|
3335
|
-
"""
|
3336
|
-
Create a flow run for a flow.
|
3337
|
-
|
3338
|
-
Args:
|
3339
|
-
flow: The flow model to create the flow run for
|
3340
|
-
name: An optional name for the flow run
|
3341
|
-
parameters: Parameter overrides for this flow run.
|
3342
|
-
context: Optional run context data
|
3343
|
-
tags: a list of tags to apply to this flow run
|
3344
|
-
parent_task_run_id: if a subflow run is being created, the placeholder task
|
3345
|
-
run identifier in the parent flow
|
3346
|
-
state: The initial state for the run. If not provided, defaults to
|
3347
|
-
`Scheduled` for now. Should always be a `Scheduled` type.
|
3348
|
-
|
3349
|
-
Raises:
|
3350
|
-
httpx.RequestError: if the Prefect API does not successfully create a run for any reason
|
3351
|
-
|
3352
|
-
Returns:
|
3353
|
-
The flow run model
|
3354
|
-
"""
|
3355
|
-
parameters = parameters or {}
|
3356
|
-
context = context or {}
|
3357
|
-
|
3358
|
-
if state is None:
|
3359
|
-
state = prefect.states.Pending()
|
3360
|
-
|
3361
|
-
# Retrieve the flow id
|
3362
|
-
flow_id = self.create_flow(flow)
|
3363
|
-
|
3364
|
-
flow_run_create = FlowRunCreate(
|
3365
|
-
flow_id=flow_id,
|
3366
|
-
flow_version=flow.version,
|
3367
|
-
name=name,
|
3368
|
-
parameters=parameters,
|
3369
|
-
context=context,
|
3370
|
-
tags=list(tags or []),
|
3371
|
-
parent_task_run_id=parent_task_run_id,
|
3372
|
-
state=state.to_state_create(),
|
3373
|
-
empirical_policy=FlowRunPolicy(
|
3374
|
-
retries=flow.retries,
|
3375
|
-
retry_delay=int(flow.retry_delay_seconds or 0),
|
3376
|
-
),
|
3377
|
-
)
|
3378
|
-
|
3379
|
-
flow_run_create_json = flow_run_create.model_dump(mode="json")
|
3380
|
-
response = self._client.post("/flow_runs/", json=flow_run_create_json)
|
3381
|
-
flow_run = FlowRun.model_validate(response.json())
|
3382
|
-
|
3383
|
-
# Restore the parameters to the local objects to retain expectations about
|
3384
|
-
# Python objects
|
3385
|
-
flow_run.parameters = parameters
|
3386
|
-
|
3387
|
-
return flow_run
|
3388
|
-
|
3389
|
-
def update_flow_run(
|
3390
|
-
self,
|
3391
|
-
flow_run_id: UUID,
|
3392
|
-
flow_version: Optional[str] = None,
|
3393
|
-
parameters: Optional[dict[str, Any]] = None,
|
3394
|
-
name: Optional[str] = None,
|
3395
|
-
tags: Optional[Iterable[str]] = None,
|
3396
|
-
empirical_policy: Optional[FlowRunPolicy] = None,
|
3397
|
-
infrastructure_pid: Optional[str] = None,
|
3398
|
-
job_variables: Optional[dict[str, Any]] = None,
|
3399
|
-
) -> httpx.Response:
|
3400
|
-
"""
|
3401
|
-
Update a flow run's details.
|
3402
|
-
|
3403
|
-
Args:
|
3404
|
-
flow_run_id: The identifier for the flow run to update.
|
3405
|
-
flow_version: A new version string for the flow run.
|
3406
|
-
parameters: A dictionary of parameter values for the flow run. This will not
|
3407
|
-
be merged with any existing parameters.
|
3408
|
-
name: A new name for the flow run.
|
3409
|
-
empirical_policy: A new flow run orchestration policy. This will not be
|
3410
|
-
merged with any existing policy.
|
3411
|
-
tags: An iterable of new tags for the flow run. These will not be merged with
|
3412
|
-
any existing tags.
|
3413
|
-
infrastructure_pid: The id of flow run as returned by an
|
3414
|
-
infrastructure block.
|
3415
|
-
|
3416
|
-
Returns:
|
3417
|
-
an `httpx.Response` object from the PATCH request
|
3418
|
-
"""
|
3419
|
-
params: dict[str, Any] = {}
|
3420
|
-
if flow_version is not None:
|
3421
|
-
params["flow_version"] = flow_version
|
3422
|
-
if parameters is not None:
|
3423
|
-
params["parameters"] = parameters
|
3424
|
-
if name is not None:
|
3425
|
-
params["name"] = name
|
3426
|
-
if tags is not None:
|
3427
|
-
params["tags"] = tags
|
3428
|
-
if empirical_policy is not None:
|
3429
|
-
params["empirical_policy"] = empirical_policy.model_dump(
|
3430
|
-
mode="json", exclude_unset=True
|
3431
|
-
)
|
3432
|
-
if infrastructure_pid:
|
3433
|
-
params["infrastructure_pid"] = infrastructure_pid
|
3434
|
-
if job_variables is not None:
|
3435
|
-
params["job_variables"] = job_variables
|
3436
|
-
|
3437
|
-
flow_run_data = FlowRunUpdate(**params)
|
3438
|
-
|
3439
|
-
return self._client.patch(
|
3440
|
-
f"/flow_runs/{flow_run_id}",
|
3441
|
-
json=flow_run_data.model_dump(mode="json", exclude_unset=True),
|
3442
|
-
)
|
3443
|
-
|
3444
|
-
def read_flow_run(self, flow_run_id: UUID) -> FlowRun:
|
3445
|
-
"""
|
3446
|
-
Query the Prefect API for a flow run by id.
|
3447
|
-
|
3448
|
-
Args:
|
3449
|
-
flow_run_id: the flow run ID of interest
|
3450
|
-
|
3451
|
-
Returns:
|
3452
|
-
a Flow Run model representation of the flow run
|
3453
|
-
"""
|
3454
|
-
try:
|
3455
|
-
response = self._client.get(f"/flow_runs/{flow_run_id}")
|
3456
|
-
except httpx.HTTPStatusError as e:
|
3457
|
-
if e.response.status_code == 404:
|
3458
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
3459
|
-
else:
|
3460
|
-
raise
|
3461
|
-
return FlowRun.model_validate(response.json())
|
3462
|
-
|
3463
|
-
def read_flow_runs(
|
3464
|
-
self,
|
3465
|
-
*,
|
3466
|
-
flow_filter: Optional[FlowFilter] = None,
|
3467
|
-
flow_run_filter: Optional[FlowRunFilter] = None,
|
3468
|
-
task_run_filter: Optional[TaskRunFilter] = None,
|
3469
|
-
deployment_filter: Optional[DeploymentFilter] = None,
|
3470
|
-
work_pool_filter: Optional[WorkPoolFilter] = None,
|
3471
|
-
work_queue_filter: Optional[WorkQueueFilter] = None,
|
3472
|
-
sort: Optional[FlowRunSort] = None,
|
3473
|
-
limit: Optional[int] = None,
|
3474
|
-
offset: int = 0,
|
3475
|
-
) -> list[FlowRun]:
|
3476
|
-
"""
|
3477
|
-
Query the Prefect API for flow runs. Only flow runs matching all criteria will
|
3478
|
-
be returned.
|
3479
|
-
|
3480
|
-
Args:
|
3481
|
-
flow_filter: filter criteria for flows
|
3482
|
-
flow_run_filter: filter criteria for flow runs
|
3483
|
-
task_run_filter: filter criteria for task runs
|
3484
|
-
deployment_filter: filter criteria for deployments
|
3485
|
-
work_pool_filter: filter criteria for work pools
|
3486
|
-
work_queue_filter: filter criteria for work pool queues
|
3487
|
-
sort: sort criteria for the flow runs
|
3488
|
-
limit: limit for the flow run query
|
3489
|
-
offset: offset for the flow run query
|
3490
|
-
|
3491
|
-
Returns:
|
3492
|
-
a list of Flow Run model representations
|
3493
|
-
of the flow runs
|
3494
|
-
"""
|
3495
|
-
body: dict[str, Any] = {
|
3496
|
-
"flows": flow_filter.model_dump(mode="json") if flow_filter else None,
|
3497
|
-
"flow_runs": (
|
3498
|
-
flow_run_filter.model_dump(mode="json", exclude_unset=True)
|
3499
|
-
if flow_run_filter
|
3500
|
-
else None
|
3501
|
-
),
|
3502
|
-
"task_runs": (
|
3503
|
-
task_run_filter.model_dump(mode="json") if task_run_filter else None
|
3504
|
-
),
|
3505
|
-
"deployments": (
|
3506
|
-
deployment_filter.model_dump(mode="json") if deployment_filter else None
|
3507
|
-
),
|
3508
|
-
"work_pools": (
|
3509
|
-
work_pool_filter.model_dump(mode="json") if work_pool_filter else None
|
3510
|
-
),
|
3511
|
-
"work_pool_queues": (
|
3512
|
-
work_queue_filter.model_dump(mode="json") if work_queue_filter else None
|
3513
|
-
),
|
3514
|
-
"sort": sort,
|
3515
|
-
"limit": limit,
|
3516
|
-
"offset": offset,
|
3517
|
-
}
|
3518
|
-
|
3519
|
-
response = self._client.post("/flow_runs/filter", json=body)
|
3520
|
-
return pydantic.TypeAdapter(list[FlowRun]).validate_python(response.json())
|
3521
|
-
|
3522
|
-
def set_flow_run_state(
|
3523
|
-
self,
|
3524
|
-
flow_run_id: UUID,
|
3525
|
-
state: "prefect.states.State[T]",
|
3526
|
-
force: bool = False,
|
3527
|
-
) -> OrchestrationResult[T]:
|
3528
|
-
"""
|
3529
|
-
Set the state of a flow run.
|
3530
|
-
|
3531
|
-
Args:
|
3532
|
-
flow_run_id: the id of the flow run
|
3533
|
-
state: the state to set
|
3534
|
-
force: if True, disregard orchestration logic when setting the state,
|
3535
|
-
forcing the Prefect API to accept the state
|
3536
|
-
|
3537
|
-
Returns:
|
3538
|
-
an OrchestrationResult model representation of state orchestration output
|
3539
|
-
"""
|
3540
|
-
state_create = state.to_state_create()
|
3541
|
-
state_create.state_details.flow_run_id = flow_run_id
|
3542
|
-
state_create.state_details.transition_id = uuid4()
|
3543
|
-
try:
|
3544
|
-
response = self._client.post(
|
3545
|
-
f"/flow_runs/{flow_run_id}/set_state",
|
3546
|
-
json=dict(
|
3547
|
-
state=state_create.model_dump(mode="json", serialize_as_any=True),
|
3548
|
-
force=force,
|
3549
|
-
),
|
3550
|
-
)
|
3551
|
-
except httpx.HTTPStatusError as e:
|
3552
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
3553
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
3554
|
-
else:
|
3555
|
-
raise
|
3556
|
-
|
3557
|
-
result: OrchestrationResult[T] = OrchestrationResult.model_validate(
|
3558
|
-
response.json()
|
3559
|
-
)
|
3560
|
-
return result
|
3561
|
-
|
3562
|
-
def set_flow_run_name(self, flow_run_id: UUID, name: str) -> httpx.Response:
|
3563
|
-
flow_run_data = FlowRunUpdate(name=name)
|
3564
|
-
return self._client.patch(
|
3565
|
-
f"/flow_runs/{flow_run_id}",
|
3566
|
-
json=flow_run_data.model_dump(mode="json", exclude_unset=True),
|
3567
|
-
)
|
3568
|
-
|
3569
1765
|
def set_task_run_name(self, task_run_id: UUID, name: str) -> httpx.Response:
|
3570
1766
|
task_run_data = TaskRunUpdate(name=name)
|
3571
1767
|
return self._client.patch(
|
@@ -3759,102 +1955,3 @@ class SyncPrefectClient(
|
|
3759
1955
|
return pydantic.TypeAdapter(list[prefect.states.State]).validate_python(
|
3760
1956
|
response.json()
|
3761
1957
|
)
|
3762
|
-
|
3763
|
-
def read_deployment(
|
3764
|
-
self,
|
3765
|
-
deployment_id: UUID,
|
3766
|
-
) -> DeploymentResponse:
|
3767
|
-
"""
|
3768
|
-
Query the Prefect API for a deployment by id.
|
3769
|
-
|
3770
|
-
Args:
|
3771
|
-
deployment_id: the deployment ID of interest
|
3772
|
-
|
3773
|
-
Returns:
|
3774
|
-
a [Deployment model][prefect.client.schemas.objects.Deployment] representation of the deployment
|
3775
|
-
"""
|
3776
|
-
try:
|
3777
|
-
response = self._client.get(f"/deployments/{deployment_id}")
|
3778
|
-
except httpx.HTTPStatusError as e:
|
3779
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
3780
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
3781
|
-
else:
|
3782
|
-
raise
|
3783
|
-
return DeploymentResponse.model_validate(response.json())
|
3784
|
-
|
3785
|
-
def read_deployment_by_name(
|
3786
|
-
self,
|
3787
|
-
name: str,
|
3788
|
-
) -> DeploymentResponse:
|
3789
|
-
"""
|
3790
|
-
Query the Prefect API for a deployment by name.
|
3791
|
-
|
3792
|
-
Args:
|
3793
|
-
name: A deployed flow's name: <FLOW_NAME>/<DEPLOYMENT_NAME>
|
3794
|
-
|
3795
|
-
Raises:
|
3796
|
-
prefect.exceptions.ObjectNotFound: If request returns 404
|
3797
|
-
httpx.RequestError: If request fails
|
3798
|
-
|
3799
|
-
Returns:
|
3800
|
-
a Deployment model representation of the deployment
|
3801
|
-
"""
|
3802
|
-
try:
|
3803
|
-
response = self._client.get(f"/deployments/name/{name}")
|
3804
|
-
except httpx.HTTPStatusError as e:
|
3805
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
3806
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
3807
|
-
else:
|
3808
|
-
raise
|
3809
|
-
|
3810
|
-
return DeploymentResponse.model_validate(response.json())
|
3811
|
-
|
3812
|
-
def update_flow_run_labels(
|
3813
|
-
self, flow_run_id: UUID, labels: KeyValueLabelsField
|
3814
|
-
) -> None:
|
3815
|
-
"""
|
3816
|
-
Updates the labels of a flow run.
|
3817
|
-
"""
|
3818
|
-
response = self._client.patch(
|
3819
|
-
f"/flow_runs/{flow_run_id}/labels",
|
3820
|
-
json=labels,
|
3821
|
-
)
|
3822
|
-
response.raise_for_status()
|
3823
|
-
|
3824
|
-
def read_block_document_by_name(
|
3825
|
-
self,
|
3826
|
-
name: str,
|
3827
|
-
block_type_slug: str,
|
3828
|
-
include_secrets: bool = True,
|
3829
|
-
) -> BlockDocument:
|
3830
|
-
"""
|
3831
|
-
Read the block document with the specified name that corresponds to a
|
3832
|
-
specific block type name.
|
3833
|
-
|
3834
|
-
Args:
|
3835
|
-
name: The block document name.
|
3836
|
-
block_type_slug: The block type slug.
|
3837
|
-
include_secrets (bool): whether to include secret values
|
3838
|
-
on the Block, corresponding to Pydantic's `SecretStr` and
|
3839
|
-
`SecretBytes` fields. These fields are automatically obfuscated
|
3840
|
-
by Pydantic, but users can additionally choose not to receive
|
3841
|
-
their values from the API. Note that any business logic on the
|
3842
|
-
Block may not work if this is `False`.
|
3843
|
-
|
3844
|
-
Raises:
|
3845
|
-
httpx.RequestError: if the block document was not found for any reason
|
3846
|
-
|
3847
|
-
Returns:
|
3848
|
-
A block document or None.
|
3849
|
-
"""
|
3850
|
-
try:
|
3851
|
-
response = self._client.get(
|
3852
|
-
f"/block_types/slug/{block_type_slug}/block_documents/name/{name}",
|
3853
|
-
params=dict(include_secrets=include_secrets),
|
3854
|
-
)
|
3855
|
-
except httpx.HTTPStatusError as e:
|
3856
|
-
if e.response.status_code == status.HTTP_404_NOT_FOUND:
|
3857
|
-
raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
|
3858
|
-
else:
|
3859
|
-
raise
|
3860
|
-
return BlockDocument.model_validate(response.json())
|