prefect-client 3.0.0rc15__py3-none-any.whl → 3.0.0rc16__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/_internal/schemas/validators.py +3 -91
- prefect/client/orchestration.py +4 -47
- prefect/client/schemas/actions.py +7 -10
- prefect/client/schemas/filters.py +0 -12
- prefect/client/schemas/objects.py +0 -6
- prefect/client/schemas/responses.py +0 -7
- prefect/deployments/base.py +0 -9
- prefect/deployments/runner.py +1 -36
- prefect/flows.py +0 -44
- prefect/runner/runner.py +0 -10
- prefect/runtime/flow_run.py +19 -1
- prefect/settings.py +5 -1
- prefect/task_engine.py +6 -46
- prefect/transactions.py +30 -3
- {prefect_client-3.0.0rc15.dist-info → prefect_client-3.0.0rc16.dist-info}/METADATA +1 -1
- {prefect_client-3.0.0rc15.dist-info → prefect_client-3.0.0rc16.dist-info}/RECORD +19 -19
- {prefect_client-3.0.0rc15.dist-info → prefect_client-3.0.0rc16.dist-info}/LICENSE +0 -0
- {prefect_client-3.0.0rc15.dist-info → prefect_client-3.0.0rc16.dist-info}/WHEEL +0 -0
- {prefect_client-3.0.0rc15.dist-info → prefect_client-3.0.0rc16.dist-info}/top_level.txt +0 -0
@@ -7,7 +7,6 @@ This will be subject to consolidation and refactoring over the next few months.
|
|
7
7
|
"""
|
8
8
|
|
9
9
|
import json
|
10
|
-
import logging
|
11
10
|
import re
|
12
11
|
import urllib.parse
|
13
12
|
import warnings
|
@@ -21,7 +20,6 @@ import yaml
|
|
21
20
|
from pydantic_extra_types.pendulum_dt import DateTime
|
22
21
|
|
23
22
|
from prefect.exceptions import InvalidRepositoryURLError
|
24
|
-
from prefect.utilities.annotations import NotSet
|
25
23
|
from prefect.utilities.collections import isiterable
|
26
24
|
from prefect.utilities.dockerutils import get_prefect_image_name
|
27
25
|
from prefect.utilities.filesystem import relative_path_to_current_platform
|
@@ -219,96 +217,18 @@ def convert_to_strings(value: Union[Any, List[Any]]) -> Union[str, List[str]]:
|
|
219
217
|
### SCHEDULE SCHEMA VALIDATORS ###
|
220
218
|
|
221
219
|
|
222
|
-
def validate_deprecated_schedule_fields(values: dict, logger: logging.Logger) -> dict:
|
223
|
-
"""
|
224
|
-
Validate and log deprecation warnings for deprecated schedule fields.
|
225
|
-
"""
|
226
|
-
if values.get("schedule") and not values.get("schedules"):
|
227
|
-
logger.warning(
|
228
|
-
"The field 'schedule' in 'Deployment' has been deprecated. It will not be "
|
229
|
-
"available after Sep 2024. Define schedules in the `schedules` list instead."
|
230
|
-
)
|
231
|
-
elif values.get("is_schedule_active") and not values.get("schedules"):
|
232
|
-
logger.warning(
|
233
|
-
"The field 'is_schedule_active' in 'Deployment' has been deprecated. It will "
|
234
|
-
"not be available after Sep 2024. Use the `active` flag within a schedule in "
|
235
|
-
"the `schedules` list instead and the `pause` flag in 'Deployment' to pause "
|
236
|
-
"all schedules."
|
237
|
-
)
|
238
|
-
return values
|
239
|
-
|
240
|
-
|
241
|
-
def reconcile_schedules(cls, values: dict) -> dict:
|
242
|
-
"""
|
243
|
-
Reconcile the `schedule` and `schedules` fields in a deployment.
|
244
|
-
"""
|
245
|
-
|
246
|
-
from prefect.deployments.schedules import (
|
247
|
-
create_deployment_schedule_create,
|
248
|
-
normalize_to_deployment_schedule_create,
|
249
|
-
)
|
250
|
-
|
251
|
-
schedule = values.get("schedule", NotSet)
|
252
|
-
schedules = values.get("schedules", NotSet)
|
253
|
-
|
254
|
-
if schedules is not NotSet:
|
255
|
-
values["schedules"] = normalize_to_deployment_schedule_create(schedules)
|
256
|
-
elif schedule is not NotSet:
|
257
|
-
values["schedule"] = None
|
258
|
-
|
259
|
-
if schedule is None:
|
260
|
-
values["schedules"] = []
|
261
|
-
else:
|
262
|
-
values["schedules"] = [
|
263
|
-
create_deployment_schedule_create(
|
264
|
-
schedule=schedule, active=values.get("is_schedule_active")
|
265
|
-
)
|
266
|
-
]
|
267
|
-
|
268
|
-
for schedule in values.get("schedules", []):
|
269
|
-
cls._validate_schedule(schedule.schedule)
|
270
|
-
|
271
|
-
return values
|
272
|
-
|
273
|
-
|
274
|
-
# TODO: consolidate with above if possible
|
275
220
|
def reconcile_schedules_runner(values: dict) -> dict:
|
276
|
-
"""
|
277
|
-
Similar to above, we reconcile the `schedule` and `schedules` fields in a deployment.
|
278
|
-
"""
|
279
221
|
from prefect.deployments.schedules import (
|
280
|
-
create_deployment_schedule_create,
|
281
222
|
normalize_to_deployment_schedule_create,
|
282
223
|
)
|
283
224
|
|
284
|
-
schedule = values.get("schedule")
|
285
225
|
schedules = values.get("schedules")
|
286
|
-
|
287
|
-
if schedules is None and schedule is not None:
|
288
|
-
values["schedules"] = [create_deployment_schedule_create(schedule)]
|
289
|
-
elif schedules is not None and len(schedules) > 0:
|
226
|
+
if schedules is not None and len(schedules) > 0:
|
290
227
|
values["schedules"] = normalize_to_deployment_schedule_create(schedules)
|
291
228
|
|
292
229
|
return values
|
293
230
|
|
294
231
|
|
295
|
-
def set_deployment_schedules(values: dict) -> dict:
|
296
|
-
from prefect.server.schemas.actions import DeploymentScheduleCreate
|
297
|
-
|
298
|
-
if not values.get("schedules") and values.get("schedule"):
|
299
|
-
kwargs = {
|
300
|
-
key: values[key]
|
301
|
-
for key in ["schedule", "is_schedule_active"]
|
302
|
-
if key in values
|
303
|
-
}
|
304
|
-
if "is_schedule_active" in kwargs:
|
305
|
-
kwargs["active"] = kwargs.pop("is_schedule_active")
|
306
|
-
|
307
|
-
values["schedules"] = [DeploymentScheduleCreate(**kwargs)]
|
308
|
-
|
309
|
-
return values
|
310
|
-
|
311
|
-
|
312
232
|
def validate_schedule_max_scheduled_runs(v: Optional[int], limit: int) -> Optional[int]:
|
313
233
|
if v is not None and v > limit:
|
314
234
|
raise ValueError(f"`max_scheduled_runs` must be less than or equal to {limit}.")
|
@@ -350,17 +270,9 @@ def remove_old_deployment_fields(values: dict) -> dict:
|
|
350
270
|
|
351
271
|
def reconcile_paused_deployment(values):
|
352
272
|
paused = values.get("paused")
|
353
|
-
|
354
|
-
|
355
|
-
if paused is not None:
|
356
|
-
values["paused"] = paused
|
357
|
-
values["is_schedule_active"] = not paused
|
358
|
-
elif is_schedule_active is not None:
|
359
|
-
values["paused"] = not is_schedule_active
|
360
|
-
values["is_schedule_active"] = is_schedule_active
|
361
|
-
else:
|
273
|
+
|
274
|
+
if paused is None:
|
362
275
|
values["paused"] = False
|
363
|
-
values["is_schedule_active"] = True
|
364
276
|
|
365
277
|
return values
|
366
278
|
|
prefect/client/orchestration.py
CHANGED
@@ -86,7 +86,6 @@ from prefect.client.schemas.objects import (
|
|
86
86
|
BlockType,
|
87
87
|
ConcurrencyLimit,
|
88
88
|
Constant,
|
89
|
-
Deployment,
|
90
89
|
DeploymentSchedule,
|
91
90
|
Flow,
|
92
91
|
FlowRunInput,
|
@@ -1599,7 +1598,6 @@ class PrefectClient:
|
|
1599
1598
|
flow_id: UUID,
|
1600
1599
|
name: str,
|
1601
1600
|
version: Optional[str] = None,
|
1602
|
-
schedule: Optional[SCHEDULE_TYPES] = None,
|
1603
1601
|
schedules: Optional[List[DeploymentScheduleCreate]] = None,
|
1604
1602
|
parameters: Optional[Dict[str, Any]] = None,
|
1605
1603
|
description: Optional[str] = None,
|
@@ -1611,7 +1609,6 @@ class PrefectClient:
|
|
1611
1609
|
entrypoint: Optional[str] = None,
|
1612
1610
|
infrastructure_document_id: Optional[UUID] = None,
|
1613
1611
|
parameter_openapi_schema: Optional[Dict[str, Any]] = None,
|
1614
|
-
is_schedule_active: Optional[bool] = None,
|
1615
1612
|
paused: Optional[bool] = None,
|
1616
1613
|
pull_steps: Optional[List[dict]] = None,
|
1617
1614
|
enforce_parameter_schema: Optional[bool] = None,
|
@@ -1624,7 +1621,6 @@ class PrefectClient:
|
|
1624
1621
|
flow_id: the flow ID to create a deployment for
|
1625
1622
|
name: the name of the deployment
|
1626
1623
|
version: an optional version string for the deployment
|
1627
|
-
schedule: an optional schedule to apply to the deployment
|
1628
1624
|
tags: an optional list of tags to apply to the deployment
|
1629
1625
|
storage_document_id: an reference to the storage block document
|
1630
1626
|
used for the deployed flow
|
@@ -1658,9 +1654,7 @@ class PrefectClient:
|
|
1658
1654
|
infrastructure_document_id=infrastructure_document_id,
|
1659
1655
|
job_variables=dict(job_variables or {}),
|
1660
1656
|
parameter_openapi_schema=parameter_openapi_schema,
|
1661
|
-
is_schedule_active=is_schedule_active,
|
1662
1657
|
paused=paused,
|
1663
|
-
schedule=schedule,
|
1664
1658
|
schedules=schedules or [],
|
1665
1659
|
pull_steps=pull_steps,
|
1666
1660
|
enforce_parameter_schema=enforce_parameter_schema,
|
@@ -1676,9 +1670,6 @@ class PrefectClient:
|
|
1676
1670
|
if field not in deployment_create.model_fields_set
|
1677
1671
|
}
|
1678
1672
|
|
1679
|
-
if deployment_create.is_schedule_active is None:
|
1680
|
-
exclude.add("is_schedule_active")
|
1681
|
-
|
1682
1673
|
if deployment_create.paused is None:
|
1683
1674
|
exclude.add("paused")
|
1684
1675
|
|
@@ -1699,12 +1690,6 @@ class PrefectClient:
|
|
1699
1690
|
|
1700
1691
|
return UUID(deployment_id)
|
1701
1692
|
|
1702
|
-
async def update_schedule(self, deployment_id: UUID, active: bool = True):
|
1703
|
-
path = "set_schedule_active" if active else "set_schedule_inactive"
|
1704
|
-
await self._client.post(
|
1705
|
-
f"/deployments/{deployment_id}/{path}",
|
1706
|
-
)
|
1707
|
-
|
1708
1693
|
async def set_deployment_paused_state(self, deployment_id: UUID, paused: bool):
|
1709
1694
|
await self._client.patch(
|
1710
1695
|
f"/deployments/{deployment_id}", json={"paused": paused}
|
@@ -1712,40 +1697,12 @@ class PrefectClient:
|
|
1712
1697
|
|
1713
1698
|
async def update_deployment(
|
1714
1699
|
self,
|
1715
|
-
|
1716
|
-
|
1717
|
-
is_schedule_active: Optional[bool] = None,
|
1700
|
+
deployment_id: UUID,
|
1701
|
+
deployment: DeploymentUpdate,
|
1718
1702
|
):
|
1719
|
-
deployment_update = DeploymentUpdate(
|
1720
|
-
version=deployment.version,
|
1721
|
-
schedule=schedule if schedule is not None else deployment.schedule,
|
1722
|
-
is_schedule_active=(
|
1723
|
-
is_schedule_active
|
1724
|
-
if is_schedule_active is not None
|
1725
|
-
else deployment.is_schedule_active
|
1726
|
-
),
|
1727
|
-
description=deployment.description,
|
1728
|
-
work_queue_name=deployment.work_queue_name,
|
1729
|
-
tags=deployment.tags,
|
1730
|
-
path=deployment.path,
|
1731
|
-
entrypoint=deployment.entrypoint,
|
1732
|
-
parameters=deployment.parameters,
|
1733
|
-
storage_document_id=deployment.storage_document_id,
|
1734
|
-
infrastructure_document_id=deployment.infrastructure_document_id,
|
1735
|
-
job_variables=deployment.job_variables,
|
1736
|
-
enforce_parameter_schema=deployment.enforce_parameter_schema,
|
1737
|
-
)
|
1738
|
-
|
1739
|
-
if getattr(deployment, "work_pool_name", None) is not None:
|
1740
|
-
deployment_update.work_pool_name = deployment.work_pool_name
|
1741
|
-
|
1742
|
-
exclude = set()
|
1743
|
-
if deployment.enforce_parameter_schema is None:
|
1744
|
-
exclude.add("enforce_parameter_schema")
|
1745
|
-
|
1746
1703
|
await self._client.patch(
|
1747
|
-
f"/deployments/{
|
1748
|
-
json=
|
1704
|
+
f"/deployments/{deployment_id}",
|
1705
|
+
json=deployment.model_dump(mode="json", exclude_unset=True),
|
1749
1706
|
)
|
1750
1707
|
|
1751
1708
|
async def _create_deployment_from_schema(self, schema: DeploymentCreate) -> UUID:
|
@@ -11,7 +11,6 @@ from prefect._internal.schemas.bases import ActionBaseModel
|
|
11
11
|
from prefect._internal.schemas.validators import (
|
12
12
|
convert_to_strings,
|
13
13
|
remove_old_deployment_fields,
|
14
|
-
return_none_schedule,
|
15
14
|
validate_artifact_key,
|
16
15
|
validate_block_document_name,
|
17
16
|
validate_block_type_slug,
|
@@ -153,7 +152,6 @@ class DeploymentCreate(ActionBaseModel):
|
|
153
152
|
|
154
153
|
name: str = Field(..., description="The name of the deployment.")
|
155
154
|
flow_id: UUID = Field(..., description="The ID of the flow to deploy.")
|
156
|
-
is_schedule_active: Optional[bool] = Field(None)
|
157
155
|
paused: Optional[bool] = Field(None)
|
158
156
|
schedules: List[DeploymentScheduleCreate] = Field(
|
159
157
|
default_factory=list,
|
@@ -181,7 +179,6 @@ class DeploymentCreate(ActionBaseModel):
|
|
181
179
|
)
|
182
180
|
storage_document_id: Optional[UUID] = Field(None)
|
183
181
|
infrastructure_document_id: Optional[UUID] = Field(None)
|
184
|
-
schedule: Optional[SCHEDULE_TYPES] = Field(None)
|
185
182
|
description: Optional[str] = Field(None)
|
186
183
|
path: Optional[str] = Field(None)
|
187
184
|
version: Optional[str] = Field(None)
|
@@ -219,19 +216,19 @@ class DeploymentUpdate(ActionBaseModel):
|
|
219
216
|
def remove_old_fields(cls, values):
|
220
217
|
return remove_old_deployment_fields(values)
|
221
218
|
|
222
|
-
@field_validator("schedule")
|
223
|
-
@classmethod
|
224
|
-
def validate_none_schedule(cls, v):
|
225
|
-
return return_none_schedule(v)
|
226
|
-
|
227
219
|
version: Optional[str] = Field(None)
|
228
|
-
schedule: Optional[SCHEDULE_TYPES] = Field(None)
|
229
220
|
description: Optional[str] = Field(None)
|
230
|
-
is_schedule_active: bool = Field(None)
|
231
221
|
parameters: Optional[Dict[str, Any]] = Field(
|
232
222
|
default=None,
|
233
223
|
description="Parameters for flow runs scheduled by the deployment.",
|
234
224
|
)
|
225
|
+
paused: Optional[bool] = Field(
|
226
|
+
default=None, description="Whether or not the deployment is paused."
|
227
|
+
)
|
228
|
+
schedules: Optional[List[DeploymentScheduleCreate]] = Field(
|
229
|
+
default=None,
|
230
|
+
description="A list of schedules for the deployment.",
|
231
|
+
)
|
235
232
|
tags: List[str] = Field(default_factory=list)
|
236
233
|
work_queue_name: Optional[str] = Field(None)
|
237
234
|
work_pool_name: Optional[str] = Field(
|
@@ -489,15 +489,6 @@ class DeploymentFilterWorkQueueName(PrefectBaseModel):
|
|
489
489
|
)
|
490
490
|
|
491
491
|
|
492
|
-
class DeploymentFilterIsScheduleActive(PrefectBaseModel):
|
493
|
-
"""Filter by `Deployment.is_schedule_active`."""
|
494
|
-
|
495
|
-
eq_: Optional[bool] = Field(
|
496
|
-
default=None,
|
497
|
-
description="Only returns where deployment schedule is/is not active",
|
498
|
-
)
|
499
|
-
|
500
|
-
|
501
492
|
class DeploymentFilterTags(PrefectBaseModel, OperatorMixin):
|
502
493
|
"""Filter by `Deployment.tags`."""
|
503
494
|
|
@@ -523,9 +514,6 @@ class DeploymentFilter(PrefectBaseModel, OperatorMixin):
|
|
523
514
|
name: Optional[DeploymentFilterName] = Field(
|
524
515
|
default=None, description="Filter criteria for `Deployment.name`"
|
525
516
|
)
|
526
|
-
is_schedule_active: Optional[DeploymentFilterIsScheduleActive] = Field(
|
527
|
-
default=None, description="Filter criteria for `Deployment.is_schedule_active`"
|
528
|
-
)
|
529
517
|
tags: Optional[DeploymentFilterTags] = Field(
|
530
518
|
default=None, description="Filter criteria for `Deployment.tags`"
|
531
519
|
)
|
@@ -993,12 +993,6 @@ class Deployment(ObjectBaseModel):
|
|
993
993
|
flow_id: UUID = Field(
|
994
994
|
default=..., description="The flow id associated with the deployment."
|
995
995
|
)
|
996
|
-
schedule: Optional[SCHEDULE_TYPES] = Field(
|
997
|
-
default=None, description="A schedule for the deployment."
|
998
|
-
)
|
999
|
-
is_schedule_active: bool = Field(
|
1000
|
-
default=True, description="Whether or not the deployment schedule is active."
|
1001
|
-
)
|
1002
996
|
paused: bool = Field(
|
1003
997
|
default=False, description="Whether or not the deployment is paused."
|
1004
998
|
)
|
@@ -9,7 +9,6 @@ from typing_extensions import Literal
|
|
9
9
|
import prefect.client.schemas.objects as objects
|
10
10
|
from prefect._internal.schemas.bases import ObjectBaseModel, PrefectBaseModel
|
11
11
|
from prefect._internal.schemas.fields import CreatedBy, UpdatedBy
|
12
|
-
from prefect.client.schemas.schedules import SCHEDULE_TYPES
|
13
12
|
from prefect.utilities.collections import AutoEnum
|
14
13
|
from prefect.utilities.names import generate_slug
|
15
14
|
|
@@ -314,12 +313,6 @@ class DeploymentResponse(ObjectBaseModel):
|
|
314
313
|
flow_id: UUID = Field(
|
315
314
|
default=..., description="The flow id associated with the deployment."
|
316
315
|
)
|
317
|
-
schedule: Optional[SCHEDULE_TYPES] = Field(
|
318
|
-
default=None, description="A schedule for the deployment."
|
319
|
-
)
|
320
|
-
is_schedule_active: bool = Field(
|
321
|
-
default=True, description="Whether or not the deployment schedule is active."
|
322
|
-
)
|
323
316
|
paused: bool = Field(
|
324
317
|
default=False, description="Whether or not the deployment is paused."
|
325
318
|
)
|
prefect/deployments/base.py
CHANGED
@@ -258,15 +258,6 @@ def _format_deployment_for_saving_to_prefect_file(
|
|
258
258
|
# Only want entrypoint to avoid errors
|
259
259
|
deployment.pop("flow_name", None)
|
260
260
|
|
261
|
-
if deployment.get("schedule"):
|
262
|
-
if isinstance(deployment["schedule"], IntervalSchedule):
|
263
|
-
deployment["schedule"] = _interval_schedule_to_dict(deployment["schedule"])
|
264
|
-
else: # all valid SCHEDULE_TYPES are subclasses of BaseModel
|
265
|
-
deployment["schedule"] = deployment["schedule"].model_dump()
|
266
|
-
|
267
|
-
if "is_schedule_active" in deployment:
|
268
|
-
deployment["schedule"]["active"] = deployment.pop("is_schedule_active")
|
269
|
-
|
270
261
|
if deployment.get("schedules"):
|
271
262
|
schedules = []
|
272
263
|
for deployment_schedule in cast(
|
prefect/deployments/runner.py
CHANGED
@@ -106,7 +106,6 @@ class RunnerDeployment(BaseModel):
|
|
106
106
|
are used only for organizational purposes. For delegating work to agents,
|
107
107
|
see `work_queue_name`.
|
108
108
|
schedule: A schedule to run this deployment on, once registered
|
109
|
-
is_schedule_active: Whether or not the schedule is active
|
110
109
|
parameters: A dictionary of parameter values to pass to runs created from this
|
111
110
|
deployment
|
112
111
|
path: The path to the working directory for the workflow, relative to remote
|
@@ -144,13 +143,9 @@ class RunnerDeployment(BaseModel):
|
|
144
143
|
default=None,
|
145
144
|
description="The schedules that should cause this deployment to run.",
|
146
145
|
)
|
147
|
-
schedule: Optional[SCHEDULE_TYPES] = None
|
148
146
|
paused: Optional[bool] = Field(
|
149
147
|
default=None, description="Whether or not the deployment is paused."
|
150
148
|
)
|
151
|
-
is_schedule_active: Optional[bool] = Field(
|
152
|
-
default=None, description="DEPRECATED: Whether or not the schedule is active."
|
153
|
-
)
|
154
149
|
parameters: Dict[str, Any] = Field(default_factory=dict)
|
155
150
|
entrypoint: Optional[str] = Field(
|
156
151
|
default=None,
|
@@ -383,7 +378,7 @@ class RunnerDeployment(BaseModel):
|
|
383
378
|
)
|
384
379
|
if num_schedules > 1:
|
385
380
|
raise ValueError(
|
386
|
-
"Only one of interval, cron, rrule,
|
381
|
+
"Only one of interval, cron, rrule, or schedules can be provided."
|
387
382
|
)
|
388
383
|
elif num_schedules == 0:
|
389
384
|
return []
|
@@ -437,8 +432,6 @@ class RunnerDeployment(BaseModel):
|
|
437
432
|
rrule: Optional[Union[Iterable[str], str]] = None,
|
438
433
|
paused: Optional[bool] = None,
|
439
434
|
schedules: Optional["FlexibleScheduleList"] = None,
|
440
|
-
schedule: Optional[SCHEDULE_TYPES] = None,
|
441
|
-
is_schedule_active: Optional[bool] = None,
|
442
435
|
parameters: Optional[dict] = None,
|
443
436
|
triggers: Optional[List[Union[DeploymentTriggerTypes, TriggerTypes]]] = None,
|
444
437
|
description: Optional[str] = None,
|
@@ -463,11 +456,6 @@ class RunnerDeployment(BaseModel):
|
|
463
456
|
paused: Whether or not to set this deployment as paused.
|
464
457
|
schedules: A list of schedule objects defining when to execute runs of this deployment.
|
465
458
|
Used to define multiple schedules or additional scheduling options like `timezone`.
|
466
|
-
schedule: A schedule object of when to execute runs of this flow. Used for
|
467
|
-
advanced scheduling options like timezone.
|
468
|
-
is_schedule_active: Whether or not to set the schedule for this deployment as active. If
|
469
|
-
not provided when creating a deployment, the schedule will be set as active. If not
|
470
|
-
provided when updating a deployment, the schedule's activation will not be changed.
|
471
459
|
triggers: A list of triggers that should kick of a run of this flow.
|
472
460
|
parameters: A dictionary of default parameter values to pass to runs of this flow.
|
473
461
|
description: A description for the created deployment. Defaults to the flow's
|
@@ -488,7 +476,6 @@ class RunnerDeployment(BaseModel):
|
|
488
476
|
interval=interval,
|
489
477
|
cron=cron,
|
490
478
|
rrule=rrule,
|
491
|
-
schedule=schedule,
|
492
479
|
schedules=schedules,
|
493
480
|
)
|
494
481
|
|
@@ -497,9 +484,7 @@ class RunnerDeployment(BaseModel):
|
|
497
484
|
deployment = cls(
|
498
485
|
name=Path(name).stem,
|
499
486
|
flow_name=flow.name,
|
500
|
-
schedule=schedule,
|
501
487
|
schedules=constructed_schedules,
|
502
|
-
is_schedule_active=is_schedule_active,
|
503
488
|
paused=paused,
|
504
489
|
tags=tags or [],
|
505
490
|
triggers=triggers or [],
|
@@ -573,8 +558,6 @@ class RunnerDeployment(BaseModel):
|
|
573
558
|
rrule: Optional[Union[Iterable[str], str]] = None,
|
574
559
|
paused: Optional[bool] = None,
|
575
560
|
schedules: Optional["FlexibleScheduleList"] = None,
|
576
|
-
schedule: Optional[SCHEDULE_TYPES] = None,
|
577
|
-
is_schedule_active: Optional[bool] = None,
|
578
561
|
parameters: Optional[dict] = None,
|
579
562
|
triggers: Optional[List[Union[DeploymentTriggerTypes, TriggerTypes]]] = None,
|
580
563
|
description: Optional[str] = None,
|
@@ -599,11 +582,6 @@ class RunnerDeployment(BaseModel):
|
|
599
582
|
paused: Whether or not to set this deployment as paused.
|
600
583
|
schedules: A list of schedule objects defining when to execute runs of this deployment.
|
601
584
|
Used to define multiple schedules or additional scheduling options like `timezone`.
|
602
|
-
schedule: A schedule object of when to execute runs of this flow. Used for
|
603
|
-
advanced scheduling options like timezone.
|
604
|
-
is_schedule_active: Whether or not to set the schedule for this deployment as active. If
|
605
|
-
not provided when creating a deployment, the schedule will be set as active. If not
|
606
|
-
provided when updating a deployment, the schedule's activation will not be changed.
|
607
585
|
triggers: A list of triggers that should kick of a run of this flow.
|
608
586
|
parameters: A dictionary of default parameter values to pass to runs of this flow.
|
609
587
|
description: A description for the created deployment. Defaults to the flow's
|
@@ -629,17 +607,14 @@ class RunnerDeployment(BaseModel):
|
|
629
607
|
interval=interval,
|
630
608
|
cron=cron,
|
631
609
|
rrule=rrule,
|
632
|
-
schedule=schedule,
|
633
610
|
schedules=schedules,
|
634
611
|
)
|
635
612
|
|
636
613
|
deployment = cls(
|
637
614
|
name=Path(name).stem,
|
638
615
|
flow_name=flow.name,
|
639
|
-
schedule=schedule,
|
640
616
|
schedules=constructed_schedules,
|
641
617
|
paused=paused,
|
642
|
-
is_schedule_active=is_schedule_active,
|
643
618
|
tags=tags or [],
|
644
619
|
triggers=triggers or [],
|
645
620
|
parameters=parameters or {},
|
@@ -671,8 +646,6 @@ class RunnerDeployment(BaseModel):
|
|
671
646
|
rrule: Optional[Union[Iterable[str], str]] = None,
|
672
647
|
paused: Optional[bool] = None,
|
673
648
|
schedules: Optional["FlexibleScheduleList"] = None,
|
674
|
-
schedule: Optional[SCHEDULE_TYPES] = None,
|
675
|
-
is_schedule_active: Optional[bool] = None,
|
676
649
|
parameters: Optional[dict] = None,
|
677
650
|
triggers: Optional[List[Union[DeploymentTriggerTypes, TriggerTypes]]] = None,
|
678
651
|
description: Optional[str] = None,
|
@@ -697,11 +670,6 @@ class RunnerDeployment(BaseModel):
|
|
697
670
|
or a timedelta object. If a number is given, it will be interpreted as seconds.
|
698
671
|
cron: A cron schedule of when to execute runs of this flow.
|
699
672
|
rrule: An rrule schedule of when to execute runs of this flow.
|
700
|
-
schedule: A schedule object of when to execute runs of this flow. Used for
|
701
|
-
advanced scheduling options like timezone.
|
702
|
-
is_schedule_active: Whether or not to set the schedule for this deployment as active. If
|
703
|
-
not provided when creating a deployment, the schedule will be set as active. If not
|
704
|
-
provided when updating a deployment, the schedule's activation will not be changed.
|
705
673
|
triggers: A list of triggers that should kick of a run of this flow.
|
706
674
|
parameters: A dictionary of default parameter values to pass to runs of this flow.
|
707
675
|
description: A description for the created deployment. Defaults to the flow's
|
@@ -724,7 +692,6 @@ class RunnerDeployment(BaseModel):
|
|
724
692
|
interval=interval,
|
725
693
|
cron=cron,
|
726
694
|
rrule=rrule,
|
727
|
-
schedule=schedule,
|
728
695
|
schedules=schedules,
|
729
696
|
)
|
730
697
|
|
@@ -742,10 +709,8 @@ class RunnerDeployment(BaseModel):
|
|
742
709
|
deployment = cls(
|
743
710
|
name=Path(name).stem,
|
744
711
|
flow_name=flow.name,
|
745
|
-
schedule=schedule,
|
746
712
|
schedules=constructed_schedules,
|
747
713
|
paused=paused,
|
748
|
-
is_schedule_active=is_schedule_active,
|
749
714
|
tags=tags or [],
|
750
715
|
triggers=triggers or [],
|
751
716
|
parameters=parameters or {},
|
prefect/flows.py
CHANGED
@@ -47,16 +47,12 @@ from pydantic.v1.errors import ConfigError # TODO
|
|
47
47
|
from rich.console import Console
|
48
48
|
from typing_extensions import Literal, ParamSpec, Self
|
49
49
|
|
50
|
-
from prefect._internal.compatibility.deprecated import (
|
51
|
-
deprecated_parameter,
|
52
|
-
)
|
53
50
|
from prefect._internal.concurrency.api import create_call, from_async
|
54
51
|
from prefect.blocks.core import Block
|
55
52
|
from prefect.client.orchestration import get_client
|
56
53
|
from prefect.client.schemas.actions import DeploymentScheduleCreate
|
57
54
|
from prefect.client.schemas.objects import Flow as FlowSchema
|
58
55
|
from prefect.client.schemas.objects import FlowRun
|
59
|
-
from prefect.client.schemas.schedules import SCHEDULE_TYPES
|
60
56
|
from prefect.client.utilities import client_injector
|
61
57
|
from prefect.docker.docker_image import DockerImage
|
62
58
|
from prefect.events import DeploymentTriggerTypes, TriggerTypes
|
@@ -627,18 +623,6 @@ class Flow(Generic[P, R]):
|
|
627
623
|
return serialized_parameters
|
628
624
|
|
629
625
|
@sync_compatible
|
630
|
-
@deprecated_parameter(
|
631
|
-
"schedule",
|
632
|
-
start_date="Mar 2024",
|
633
|
-
when=lambda p: p is not None,
|
634
|
-
help="Use `schedules` instead.",
|
635
|
-
)
|
636
|
-
@deprecated_parameter(
|
637
|
-
"is_schedule_active",
|
638
|
-
start_date="Mar 2024",
|
639
|
-
when=lambda p: p is not None,
|
640
|
-
help="Use `paused` instead.",
|
641
|
-
)
|
642
626
|
async def to_deployment(
|
643
627
|
self,
|
644
628
|
name: str,
|
@@ -654,8 +638,6 @@ class Flow(Generic[P, R]):
|
|
654
638
|
rrule: Optional[Union[Iterable[str], str]] = None,
|
655
639
|
paused: Optional[bool] = None,
|
656
640
|
schedules: Optional[List["FlexibleScheduleList"]] = None,
|
657
|
-
schedule: Optional[SCHEDULE_TYPES] = None,
|
658
|
-
is_schedule_active: Optional[bool] = None,
|
659
641
|
parameters: Optional[dict] = None,
|
660
642
|
triggers: Optional[List[Union[DeploymentTriggerTypes, TriggerTypes]]] = None,
|
661
643
|
description: Optional[str] = None,
|
@@ -679,10 +661,6 @@ class Flow(Generic[P, R]):
|
|
679
661
|
paused: Whether or not to set this deployment as paused.
|
680
662
|
schedules: A list of schedule objects defining when to execute runs of this deployment.
|
681
663
|
Used to define multiple schedules or additional scheduling options such as `timezone`.
|
682
|
-
schedule: A schedule object defining when to execute runs of this deployment.
|
683
|
-
is_schedule_active: Whether or not to set the schedule for this deployment as active. If
|
684
|
-
not provided when creating a deployment, the schedule will be set as active. If not
|
685
|
-
provided when updating a deployment, the schedule's activation will not be changed.
|
686
664
|
parameters: A dictionary of default parameter values to pass to runs of this deployment.
|
687
665
|
triggers: A list of triggers that will kick off runs of this deployment.
|
688
666
|
description: A description for the created deployment. Defaults to the flow's
|
@@ -735,8 +713,6 @@ class Flow(Generic[P, R]):
|
|
735
713
|
rrule=rrule,
|
736
714
|
paused=paused,
|
737
715
|
schedules=schedules,
|
738
|
-
schedule=schedule,
|
739
|
-
is_schedule_active=is_schedule_active,
|
740
716
|
tags=tags,
|
741
717
|
triggers=triggers,
|
742
718
|
parameters=parameters or {},
|
@@ -756,8 +732,6 @@ class Flow(Generic[P, R]):
|
|
756
732
|
rrule=rrule,
|
757
733
|
paused=paused,
|
758
734
|
schedules=schedules,
|
759
|
-
schedule=schedule,
|
760
|
-
is_schedule_active=is_schedule_active,
|
761
735
|
tags=tags,
|
762
736
|
triggers=triggers,
|
763
737
|
parameters=parameters or {},
|
@@ -815,8 +789,6 @@ class Flow(Generic[P, R]):
|
|
815
789
|
rrule: Optional[Union[Iterable[str], str]] = None,
|
816
790
|
paused: Optional[bool] = None,
|
817
791
|
schedules: Optional["FlexibleScheduleList"] = None,
|
818
|
-
schedule: Optional[SCHEDULE_TYPES] = None,
|
819
|
-
is_schedule_active: Optional[bool] = None,
|
820
792
|
triggers: Optional[List[Union[DeploymentTriggerTypes, TriggerTypes]]] = None,
|
821
793
|
parameters: Optional[dict] = None,
|
822
794
|
description: Optional[str] = None,
|
@@ -846,11 +818,6 @@ class Flow(Generic[P, R]):
|
|
846
818
|
paused: Whether or not to set this deployment as paused.
|
847
819
|
schedules: A list of schedule objects defining when to execute runs of this deployment.
|
848
820
|
Used to define multiple schedules or additional scheduling options like `timezone`.
|
849
|
-
schedule: A schedule object defining when to execute runs of this deployment. Used to
|
850
|
-
define additional scheduling options such as `timezone`.
|
851
|
-
is_schedule_active: Whether or not to set the schedule for this deployment as active. If
|
852
|
-
not provided when creating a deployment, the schedule will be set as active. If not
|
853
|
-
provided when updating a deployment, the schedule's activation will not be changed.
|
854
821
|
parameters: A dictionary of default parameter values to pass to runs of this deployment.
|
855
822
|
description: A description for the created deployment. Defaults to the flow's
|
856
823
|
description if not provided.
|
@@ -914,8 +881,6 @@ class Flow(Generic[P, R]):
|
|
914
881
|
rrule=rrule,
|
915
882
|
paused=paused,
|
916
883
|
schedules=schedules,
|
917
|
-
schedule=schedule,
|
918
|
-
is_schedule_active=is_schedule_active,
|
919
884
|
parameters=parameters,
|
920
885
|
description=description,
|
921
886
|
tags=tags,
|
@@ -1085,8 +1050,6 @@ class Flow(Generic[P, R]):
|
|
1085
1050
|
rrule: Optional[str] = None,
|
1086
1051
|
paused: Optional[bool] = None,
|
1087
1052
|
schedules: Optional[List[DeploymentScheduleCreate]] = None,
|
1088
|
-
schedule: Optional[SCHEDULE_TYPES] = None,
|
1089
|
-
is_schedule_active: Optional[bool] = None,
|
1090
1053
|
triggers: Optional[List[Union[DeploymentTriggerTypes, TriggerTypes]]] = None,
|
1091
1054
|
parameters: Optional[dict] = None,
|
1092
1055
|
description: Optional[str] = None,
|
@@ -1133,11 +1096,6 @@ class Flow(Generic[P, R]):
|
|
1133
1096
|
paused: Whether or not to set this deployment as paused.
|
1134
1097
|
schedules: A list of schedule objects defining when to execute runs of this deployment.
|
1135
1098
|
Used to define multiple schedules or additional scheduling options like `timezone`.
|
1136
|
-
schedule: A schedule object defining when to execute runs of this deployment. Used to
|
1137
|
-
define additional scheduling options like `timezone`.
|
1138
|
-
is_schedule_active: Whether or not to set the schedule for this deployment as active. If
|
1139
|
-
not provided when creating a deployment, the schedule will be set as active. If not
|
1140
|
-
provided when updating a deployment, the schedule's activation will not be changed.
|
1141
1099
|
parameters: A dictionary of default parameter values to pass to runs of this deployment.
|
1142
1100
|
description: A description for the created deployment. Defaults to the flow's
|
1143
1101
|
description if not provided.
|
@@ -1213,8 +1171,6 @@ class Flow(Generic[P, R]):
|
|
1213
1171
|
rrule=rrule,
|
1214
1172
|
schedules=schedules,
|
1215
1173
|
paused=paused,
|
1216
|
-
schedule=schedule,
|
1217
|
-
is_schedule_active=is_schedule_active,
|
1218
1174
|
triggers=triggers,
|
1219
1175
|
parameters=parameters,
|
1220
1176
|
description=description,
|
prefect/runner/runner.py
CHANGED
@@ -67,7 +67,6 @@ from prefect.client.schemas.filters import (
|
|
67
67
|
)
|
68
68
|
from prefect.client.schemas.objects import Flow as APIFlow
|
69
69
|
from prefect.client.schemas.objects import FlowRun, State, StateType
|
70
|
-
from prefect.client.schemas.schedules import SCHEDULE_TYPES
|
71
70
|
from prefect.events import DeploymentTriggerTypes, TriggerTypes
|
72
71
|
from prefect.events.related import tags_as_related_resources
|
73
72
|
from prefect.events.schemas.events import RelatedResource
|
@@ -224,8 +223,6 @@ class Runner:
|
|
224
223
|
rrule: Optional[Union[Iterable[str], str]] = None,
|
225
224
|
paused: Optional[bool] = None,
|
226
225
|
schedules: Optional["FlexibleScheduleList"] = None,
|
227
|
-
schedule: Optional[SCHEDULE_TYPES] = None,
|
228
|
-
is_schedule_active: Optional[bool] = None,
|
229
226
|
parameters: Optional[dict] = None,
|
230
227
|
triggers: Optional[List[Union[DeploymentTriggerTypes, TriggerTypes]]] = None,
|
231
228
|
description: Optional[str] = None,
|
@@ -248,11 +245,6 @@ class Runner:
|
|
248
245
|
or a timedelta object. If a number is given, it will be interpreted as seconds.
|
249
246
|
cron: A cron schedule of when to execute runs of this flow.
|
250
247
|
rrule: An rrule schedule of when to execute runs of this flow.
|
251
|
-
schedule: A schedule object of when to execute runs of this flow. Used for
|
252
|
-
advanced scheduling options like timezone.
|
253
|
-
is_schedule_active: Whether or not to set the schedule for this deployment as active. If
|
254
|
-
not provided when creating a deployment, the schedule will be set as active. If not
|
255
|
-
provided when updating a deployment, the schedule's activation will not be changed.
|
256
248
|
triggers: A list of triggers that should kick of a run of this flow.
|
257
249
|
parameters: A dictionary of default parameter values to pass to runs of this flow.
|
258
250
|
description: A description for the created deployment. Defaults to the flow's
|
@@ -277,9 +269,7 @@ class Runner:
|
|
277
269
|
cron=cron,
|
278
270
|
rrule=rrule,
|
279
271
|
schedules=schedules,
|
280
|
-
schedule=schedule,
|
281
272
|
paused=paused,
|
282
|
-
is_schedule_active=is_schedule_active,
|
283
273
|
triggers=triggers,
|
284
274
|
parameters=parameters,
|
285
275
|
description=description,
|
prefect/runtime/flow_run.py
CHANGED
@@ -12,6 +12,7 @@ Available attributes:
|
|
12
12
|
- `scheduled_start_time`: the flow run's expected scheduled start time; defaults to now if not present
|
13
13
|
- `name`: the name of the flow run
|
14
14
|
- `flow_name`: the name of the flow
|
15
|
+
- `flow_version`: the version of the flow
|
15
16
|
- `parameters`: the parameters that were passed to this run; note that these do not necessarily
|
16
17
|
include default values set on the flow function, only the parameter values explicitly passed for the run
|
17
18
|
- `parent_flow_run_id`: the ID of the flow run that triggered this run, if any
|
@@ -35,6 +36,7 @@ __all__ = [
|
|
35
36
|
"scheduled_start_time",
|
36
37
|
"name",
|
37
38
|
"flow_name",
|
39
|
+
"flow_version",
|
38
40
|
"parameters",
|
39
41
|
"parent_flow_run_id",
|
40
42
|
"parent_deployment_id",
|
@@ -119,7 +121,7 @@ async def _get_flow_from_run(flow_run_id):
|
|
119
121
|
return await client.read_flow(flow_run.flow_id)
|
120
122
|
|
121
123
|
|
122
|
-
def get_id() -> str:
|
124
|
+
def get_id() -> Optional[str]:
|
123
125
|
flow_run_ctx = FlowRunContext.get()
|
124
126
|
task_run_ctx = TaskRunContext.get()
|
125
127
|
if flow_run_ctx is not None:
|
@@ -190,6 +192,21 @@ def get_flow_name() -> Optional[str]:
|
|
190
192
|
return flow_run_ctx.flow.name
|
191
193
|
|
192
194
|
|
195
|
+
def get_flow_version() -> Optional[str]:
|
196
|
+
flow_run_ctx = FlowRunContext.get()
|
197
|
+
run_id = get_id()
|
198
|
+
if flow_run_ctx is None and run_id is None:
|
199
|
+
return None
|
200
|
+
elif flow_run_ctx is None:
|
201
|
+
flow = from_sync.call_soon_in_loop_thread(
|
202
|
+
create_call(_get_flow_from_run, run_id)
|
203
|
+
).result()
|
204
|
+
|
205
|
+
return flow.version
|
206
|
+
else:
|
207
|
+
return flow_run_ctx.flow.version
|
208
|
+
|
209
|
+
|
193
210
|
def get_scheduled_start_time() -> pendulum.DateTime:
|
194
211
|
flow_run_ctx = FlowRunContext.get()
|
195
212
|
run_id = get_id()
|
@@ -313,4 +330,5 @@ FIELDS = {
|
|
313
330
|
"run_count": get_run_count,
|
314
331
|
"api_url": get_flow_run_api_url,
|
315
332
|
"ui_url": get_flow_run_ui_url,
|
333
|
+
"flow_version": get_flow_version,
|
316
334
|
}
|
prefect/settings.py
CHANGED
@@ -323,7 +323,11 @@ def template_with_settings(*upstream_settings: Setting) -> Callable[["Settings",
|
|
323
323
|
setting.name: setting.value_from(settings) for setting in upstream_settings
|
324
324
|
}
|
325
325
|
template = string.Template(str(value))
|
326
|
-
|
326
|
+
# Note the use of `safe_substitute` to avoid raising an exception if a
|
327
|
+
# template value is missing. In this case, template values will be left
|
328
|
+
# as-is in the string. Using `safe_substitute` prevents us raising when
|
329
|
+
# the DB password contains a `$` character.
|
330
|
+
return original_type(template.safe_substitute(template_values))
|
327
331
|
|
328
332
|
return templater
|
329
333
|
|
prefect/task_engine.py
CHANGED
@@ -5,7 +5,6 @@ import time
|
|
5
5
|
from asyncio import CancelledError
|
6
6
|
from contextlib import ExitStack, asynccontextmanager, contextmanager
|
7
7
|
from dataclasses import dataclass, field
|
8
|
-
from functools import wraps
|
9
8
|
from textwrap import dedent
|
10
9
|
from typing import (
|
11
10
|
Any,
|
@@ -231,11 +230,11 @@ class BaseTaskRunEngine(Generic[P, R]):
|
|
231
230
|
|
232
231
|
@task
|
233
232
|
def say_hello(name):
|
234
|
-
print
|
233
|
+
print(f"Hello, {name}!")
|
235
234
|
|
236
235
|
@flow
|
237
236
|
def example_flow():
|
238
|
-
future = say_hello.submit(name="Marvin)
|
237
|
+
future = say_hello.submit(name="Marvin")
|
239
238
|
future.wait()
|
240
239
|
|
241
240
|
example_flow()
|
@@ -496,15 +495,8 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
|
|
496
495
|
)
|
497
496
|
transaction.stage(
|
498
497
|
terminal_state.data,
|
499
|
-
on_rollback_hooks=[self.handle_rollback]
|
500
|
-
|
501
|
-
_with_transaction_hook_logging(hook, "rollback", self.logger)
|
502
|
-
for hook in self.task.on_rollback_hooks
|
503
|
-
],
|
504
|
-
on_commit_hooks=[
|
505
|
-
_with_transaction_hook_logging(hook, "commit", self.logger)
|
506
|
-
for hook in self.task.on_commit_hooks
|
507
|
-
],
|
498
|
+
on_rollback_hooks=[self.handle_rollback] + self.task.on_rollback_hooks,
|
499
|
+
on_commit_hooks=self.task.on_commit_hooks,
|
508
500
|
)
|
509
501
|
if transaction.is_committed():
|
510
502
|
terminal_state.name = "Cached"
|
@@ -1068,15 +1060,8 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
|
|
1068
1060
|
)
|
1069
1061
|
transaction.stage(
|
1070
1062
|
terminal_state.data,
|
1071
|
-
on_rollback_hooks=[self.handle_rollback]
|
1072
|
-
|
1073
|
-
_with_transaction_hook_logging(hook, "rollback", self.logger)
|
1074
|
-
for hook in self.task.on_rollback_hooks
|
1075
|
-
],
|
1076
|
-
on_commit_hooks=[
|
1077
|
-
_with_transaction_hook_logging(hook, "commit", self.logger)
|
1078
|
-
for hook in self.task.on_commit_hooks
|
1079
|
-
],
|
1063
|
+
on_rollback_hooks=[self.handle_rollback] + self.task.on_rollback_hooks,
|
1064
|
+
on_commit_hooks=self.task.on_commit_hooks,
|
1080
1065
|
)
|
1081
1066
|
if transaction.is_committed():
|
1082
1067
|
terminal_state.name = "Cached"
|
@@ -1622,28 +1607,3 @@ def run_task(
|
|
1622
1607
|
return run_task_async(**kwargs)
|
1623
1608
|
else:
|
1624
1609
|
return run_task_sync(**kwargs)
|
1625
|
-
|
1626
|
-
|
1627
|
-
def _with_transaction_hook_logging(
|
1628
|
-
hook: Callable[[Transaction], None],
|
1629
|
-
hook_type: Literal["rollback", "commit"],
|
1630
|
-
logger: logging.Logger,
|
1631
|
-
) -> Callable[[Transaction], None]:
|
1632
|
-
@wraps(hook)
|
1633
|
-
def _hook(txn: Transaction) -> None:
|
1634
|
-
hook_name = _get_hook_name(hook)
|
1635
|
-
logger.info(f"Running {hook_type} hook {hook_name!r}")
|
1636
|
-
|
1637
|
-
try:
|
1638
|
-
hook(txn)
|
1639
|
-
except Exception as exc:
|
1640
|
-
logger.error(
|
1641
|
-
f"An error was encountered while running {hook_type} hook {hook_name!r}",
|
1642
|
-
)
|
1643
|
-
raise exc
|
1644
|
-
else:
|
1645
|
-
logger.info(
|
1646
|
-
f"{hook_type.capitalize()} hook {hook_name!r} finished running successfully"
|
1647
|
-
)
|
1648
|
-
|
1649
|
-
return _hook
|
prefect/transactions.py
CHANGED
@@ -4,6 +4,7 @@ from contextvars import ContextVar, Token
|
|
4
4
|
from typing import (
|
5
5
|
Any,
|
6
6
|
Callable,
|
7
|
+
Dict,
|
7
8
|
Generator,
|
8
9
|
List,
|
9
10
|
Optional,
|
@@ -11,7 +12,7 @@ from typing import (
|
|
11
12
|
Union,
|
12
13
|
)
|
13
14
|
|
14
|
-
from pydantic import Field
|
15
|
+
from pydantic import Field, PrivateAttr
|
15
16
|
from typing_extensions import Self
|
16
17
|
|
17
18
|
from prefect.context import ContextModel, FlowRunContext, TaskRunContext
|
@@ -26,6 +27,7 @@ from prefect.results import (
|
|
26
27
|
)
|
27
28
|
from prefect.utilities.asyncutils import run_coro_as_sync
|
28
29
|
from prefect.utilities.collections import AutoEnum
|
30
|
+
from prefect.utilities.engine import _get_hook_name
|
29
31
|
|
30
32
|
|
31
33
|
class IsolationLevel(AutoEnum):
|
@@ -63,9 +65,18 @@ class Transaction(ContextModel):
|
|
63
65
|
)
|
64
66
|
overwrite: bool = False
|
65
67
|
logger: Union[logging.Logger, logging.LoggerAdapter, None] = None
|
68
|
+
_stored_values: Dict[str, Any] = PrivateAttr(default_factory=dict)
|
66
69
|
_staged_value: Any = None
|
67
70
|
__var__: ContextVar = ContextVar("transaction")
|
68
71
|
|
72
|
+
def set(self, name: str, value: Any) -> None:
|
73
|
+
self._stored_values[name] = value
|
74
|
+
|
75
|
+
def get(self, name: str) -> Any:
|
76
|
+
if name not in self._stored_values:
|
77
|
+
raise ValueError(f"Could not retrieve value for unknown key: {name}")
|
78
|
+
return self._stored_values.get(name)
|
79
|
+
|
69
80
|
def is_committed(self) -> bool:
|
70
81
|
return self.state == TransactionState.COMMITTED
|
71
82
|
|
@@ -183,7 +194,7 @@ class Transaction(ContextModel):
|
|
183
194
|
child.commit()
|
184
195
|
|
185
196
|
for hook in self.on_commit_hooks:
|
186
|
-
hook
|
197
|
+
self.run_hook(hook, "commit")
|
187
198
|
|
188
199
|
if self.store and self.key:
|
189
200
|
self.store.write(key=self.key, value=self._staged_value)
|
@@ -198,6 +209,22 @@ class Transaction(ContextModel):
|
|
198
209
|
self.rollback()
|
199
210
|
return False
|
200
211
|
|
212
|
+
def run_hook(self, hook, hook_type: str) -> None:
|
213
|
+
hook_name = _get_hook_name(hook)
|
214
|
+
self.logger.info(f"Running {hook_type} hook {hook_name!r}")
|
215
|
+
|
216
|
+
try:
|
217
|
+
hook(self)
|
218
|
+
except Exception as exc:
|
219
|
+
self.logger.error(
|
220
|
+
f"An error was encountered while running {hook_type} hook {hook_name!r}",
|
221
|
+
)
|
222
|
+
raise exc
|
223
|
+
else:
|
224
|
+
self.logger.info(
|
225
|
+
f"{hook_type.capitalize()} hook {hook_name!r} finished running successfully"
|
226
|
+
)
|
227
|
+
|
201
228
|
def stage(
|
202
229
|
self,
|
203
230
|
value: BaseResult,
|
@@ -222,7 +249,7 @@ class Transaction(ContextModel):
|
|
222
249
|
|
223
250
|
try:
|
224
251
|
for hook in reversed(self.on_rollback_hooks):
|
225
|
-
hook
|
252
|
+
self.run_hook(hook, "rollback")
|
226
253
|
|
227
254
|
self.state = TransactionState.ROLLED_BACK
|
228
255
|
|
@@ -11,7 +11,7 @@ prefect/exceptions.py,sha256=3s69Z_IC3HKF6BKxcHrMPXkKdYwfbEfaTjy4-5LOtQ0,11132
|
|
11
11
|
prefect/filesystems.py,sha256=rbFvlqHXeeo71nK1Y5I0-ucmGOYUcdkbb6N2vpsRcWE,17229
|
12
12
|
prefect/flow_engine.py,sha256=c8mIffc57zLtHFRo4sVtQOXGihVA_y2mZiXYzjJlOHY,29445
|
13
13
|
prefect/flow_runs.py,sha256=EaXRIQTOnwnA0fO7_EjwafFRmS57K_CRy0Xsz3JDIhc,16070
|
14
|
-
prefect/flows.py,sha256=
|
14
|
+
prefect/flows.py,sha256=Sl3m8Q3mXwY1MSgJSeViiXag4jtUBN7stMP1Fs4iepo,88039
|
15
15
|
prefect/futures.py,sha256=Zt5U7PnNpKUQuyfAhWAZZxpG0hQ6HXuA4KVg6E9sQf8,16208
|
16
16
|
prefect/main.py,sha256=bab5nBn37a6gmxdPbTlRS2a9Cf0KY0GaCotDOSbcQ7M,1930
|
17
17
|
prefect/manifests.py,sha256=477XcmfdC_yE81wT6zIAKnEUEJ0lH9ZLfOVSgX2FohE,676
|
@@ -20,14 +20,14 @@ prefect/profiles.toml,sha256=kTvqDNMzjH3fsm5OEI-NKY4dMmipor5EvQXRB6rPEjY,522
|
|
20
20
|
prefect/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
21
|
prefect/results.py,sha256=3mVkVWZn_VSQ9Pik79StNy113rB_SEiP83SdoUsFvTM,24635
|
22
22
|
prefect/serializers.py,sha256=Lo41EM0_qGzcfB_63390Izeo3DdK6cY6VZfxa9hpSGQ,8712
|
23
|
-
prefect/settings.py,sha256=
|
23
|
+
prefect/settings.py,sha256=RpO6XMM2qf6KC_rQMHmQpcjul1t2rZmLOkK89Ta3OcM,72076
|
24
24
|
prefect/states.py,sha256=lw22xucH46cN9stkxiV9ByIvq689mH5iL3gErri-Y18,22207
|
25
|
-
prefect/task_engine.py,sha256=
|
25
|
+
prefect/task_engine.py,sha256=z5raK4OLgCRp6cubrTDL0XZQsx8Z5xTFwKn2QnITGcA,64053
|
26
26
|
prefect/task_runners.py,sha256=W1n0yMwbDIqnvffFVJADo9MGEbLaYkzWk52rqgnkMY4,15019
|
27
27
|
prefect/task_runs.py,sha256=jkaQOkRKOHS8fgHUijteriFpjMSKv4zldn1D8tZHkUI,8777
|
28
28
|
prefect/task_worker.py,sha256=DX4NYERghB8RZeFleZE0xOq3yJVunjUaAKHtiz8wuRo,17992
|
29
29
|
prefect/tasks.py,sha256=tpYQhH4wZcOeVTOOGus0Med4prLlmMM2jSf3TKuFdUQ,68230
|
30
|
-
prefect/transactions.py,sha256=
|
30
|
+
prefect/transactions.py,sha256=YyWuY99mBeEsY8JGR3_eyWbFIUxWIzbHfU2UMBKTaik,11038
|
31
31
|
prefect/variables.py,sha256=-t5LVY0N-K4f0fa6YwruVVQqwnU3fGWBMYXXE32XPkA,4821
|
32
32
|
prefect/_internal/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
33
33
|
prefect/_internal/_logging.py,sha256=HvNHY-8P469o5u4LYEDBTem69XZEt1QUeUaLToijpak,810
|
@@ -59,7 +59,7 @@ prefect/_internal/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
|
|
59
59
|
prefect/_internal/schemas/bases.py,sha256=KYT8v4UOIClOKoXLEHSzDI7jran35BHvRcYWueyMFYU,4098
|
60
60
|
prefect/_internal/schemas/fields.py,sha256=m4LrFNz8rA9uBhMk9VyQT6FIXmV_EVAW92hdXeSvHbY,837
|
61
61
|
prefect/_internal/schemas/serializers.py,sha256=G_RGHfObjisUiRvd29p-zc6W4bwt5rE1OdR6TXNrRhQ,825
|
62
|
-
prefect/_internal/schemas/validators.py,sha256=
|
62
|
+
prefect/_internal/schemas/validators.py,sha256=Y8bHb3EsLJTiHsffg_TPbknj0Nmln8vd6qySLFbfGzY,26546
|
63
63
|
prefect/blocks/__init__.py,sha256=BUfh6gIwA6HEjRyVCAiv0he3M1zfM-oY-JrlBfeWeY8,182
|
64
64
|
prefect/blocks/abstract.py,sha256=YLzCaf3yXv6wFCF5ZqCIHJNwH7fME1rLxC-SijARHzk,16319
|
65
65
|
prefect/blocks/core.py,sha256=EAvmPga9fyUfK9QW_HFLSit0dn6Szh_KbDK3n8HX4q0,52155
|
@@ -73,14 +73,14 @@ prefect/client/base.py,sha256=2K8UiWzorZNNM4c8c-OiGeZ5i5ViUfZ_Q31oPobbOO0,24956
|
|
73
73
|
prefect/client/cloud.py,sha256=7iHff1YDABdzBW5BZFlyzmwgCMWUwbgVv2zTNlqW7lw,4132
|
74
74
|
prefect/client/collections.py,sha256=I9EgbTg4Fn57gn8vwP_WdDmgnATbx9gfkm2jjhCORjw,1037
|
75
75
|
prefect/client/constants.py,sha256=Z_GG8KF70vbbXxpJuqW5pLnwzujTVeHbcYYRikNmGH0,29
|
76
|
-
prefect/client/orchestration.py,sha256=
|
76
|
+
prefect/client/orchestration.py,sha256=G3zkz3HTfy9ZMELKAi8HRqvybOhdlOsia2Vt7ElWEPQ,143316
|
77
77
|
prefect/client/subscriptions.py,sha256=J9uK9NGHO4VX4Y3NGgBJ4pIG_0cf-dJWPhF3f3PGYL4,3388
|
78
78
|
prefect/client/utilities.py,sha256=89fmza0cRMOayxgXRdO51TKb11TczJ0ByOZmcZVrt44,3286
|
79
79
|
prefect/client/schemas/__init__.py,sha256=KlyqFV-hMulMkNstBn_0ijoHoIwJZaBj6B1r07UmgvE,607
|
80
|
-
prefect/client/schemas/actions.py,sha256=
|
81
|
-
prefect/client/schemas/filters.py,sha256=
|
82
|
-
prefect/client/schemas/objects.py,sha256=
|
83
|
-
prefect/client/schemas/responses.py,sha256=
|
80
|
+
prefect/client/schemas/actions.py,sha256=i0izw0JPdlvAeEC2YEbmskr7kU0-tyzEwEtCKXMPi74,28101
|
81
|
+
prefect/client/schemas/filters.py,sha256=_Ibx8VDICS0wkqo-M8zlpOyAbkrRw8sfgqyD9_x2Vvc,34881
|
82
|
+
prefect/client/schemas/objects.py,sha256=PNxOTBwQDQ57703i6ZrV_kxYDSuJSrJ3O_42hDwOliA,53296
|
83
|
+
prefect/client/schemas/responses.py,sha256=3Y-md6uXCF7X8gcZYvvKqcu5CXqvJfkJyfocHFypp9g,14637
|
84
84
|
prefect/client/schemas/schedules.py,sha256=8rpqjOYtknu2-1n5_WD4cOplgu93P3mCyX86B22LfL4,13070
|
85
85
|
prefect/client/schemas/sorting.py,sha256=EIQ6FUjUWMwk6fn6ckVLQLXOP-GI5kce7ftjUkDFWV0,2490
|
86
86
|
prefect/client/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -92,10 +92,10 @@ prefect/concurrency/events.py,sha256=EjZwUbbtP-N-u8rk8nbyMIi-BnkshoLkHRYh913jUWU
|
|
92
92
|
prefect/concurrency/services.py,sha256=wKW9dJzzZkTcS2Wk4IsNPfMOuXle2qSz50Qk0MxrOJc,3438
|
93
93
|
prefect/concurrency/sync.py,sha256=uGomOknZ_ET_wW0LcuOJBzbcYSNcaQZqH0bh1mOkmu8,4261
|
94
94
|
prefect/deployments/__init__.py,sha256=_wb7NxDKhq11z9MjYsPckmT3o6MRhGLRgCV9TmvYtew,1002
|
95
|
-
prefect/deployments/base.py,sha256=
|
95
|
+
prefect/deployments/base.py,sha256=rEMb-AXUuO66a7Qwq0KFUI1L0Xrl_-8z7cgAKaysfwg,16136
|
96
96
|
prefect/deployments/deployments.py,sha256=EvC9qBdvJRc8CHJqRjFTqtzx75SE8bpZOl5C-2eULyA,109
|
97
97
|
prefect/deployments/flow_runs.py,sha256=eatcBD7pg-aaEqs9JxQQcKN_flf614O4gAvedAlRyNo,6803
|
98
|
-
prefect/deployments/runner.py,sha256=
|
98
|
+
prefect/deployments/runner.py,sha256=lNfSyvkElcFglU6pZlsI8ZQTG2KzdsEjrONVNvnbDIs,39514
|
99
99
|
prefect/deployments/schedules.py,sha256=KCYA6dOmLAoElHZuoWqdJn4Yno4TtOZtXfPOpTLb1cE,2046
|
100
100
|
prefect/deployments/steps/__init__.py,sha256=Dlz9VqMRyG1Gal8dj8vfGpPr0LyQhZdvcciozkK8WoY,206
|
101
101
|
prefect/deployments/steps/core.py,sha256=5vFf6BSpu992kkaYsvcPpsz-nZxFmayMIDmY9h0Hb8M,6846
|
@@ -139,14 +139,14 @@ prefect/records/__init__.py,sha256=7q-lwyevfVgb5S7K9frzawmiJmpZ5ET0m5yXIHBYcVA,3
|
|
139
139
|
prefect/records/result_store.py,sha256=6Yh9zqqXMWjn0qWSfcjQBSfXCM7jVg9pve5TVsOodDc,1734
|
140
140
|
prefect/records/store.py,sha256=eQM1p2vZDshXZYg6SkJwL-DP3kUehL_Zgs8xa2-0DZs,224
|
141
141
|
prefect/runner/__init__.py,sha256=7U-vAOXFkzMfRz1q8Uv6Otsvc0OrPYLLP44srwkJ_8s,89
|
142
|
-
prefect/runner/runner.py,sha256=
|
142
|
+
prefect/runner/runner.py,sha256=yrBG5fCO7dCpE-lwPOkx8ToBtfJ3-BKQIUm9eNbjA2g,47388
|
143
143
|
prefect/runner/server.py,sha256=2o5vhrL7Zbn-HBStWhCjqqViex5Ye9GiQ1EW9RSEzdo,10500
|
144
144
|
prefect/runner/storage.py,sha256=OsBa4nWdFxOTiAMNLFpexBdi5K3iuxidQx4YWZwditE,24734
|
145
145
|
prefect/runner/submit.py,sha256=RuyDr-ved9wjYYarXiehY5oJVFf_HE3XKKACNWpxpPc,8131
|
146
146
|
prefect/runner/utils.py,sha256=wVgVa7p5uUL7tfYfDOVuq6QIGf-I8U9dfAjYBmYf6n4,3286
|
147
147
|
prefect/runtime/__init__.py,sha256=JswiTlYRup2zXOYu8AqJ7czKtgcw9Kxo0tTbS6aWCqY,407
|
148
148
|
prefect/runtime/deployment.py,sha256=Kah8Xdh5f94-CEAXjBgnEB4xAQXXYPaEqDJ_gTqltIY,4752
|
149
|
-
prefect/runtime/flow_run.py,sha256=
|
149
|
+
prefect/runtime/flow_run.py,sha256=33XsudriajxIRJtebPpqF8cWCRsUpmvb9V0CSipG4J0,9956
|
150
150
|
prefect/runtime/task_run.py,sha256=B6v_nZiHy9nKZfnKFQF7izZjAjaiZOT0j80m-VcLxmY,3403
|
151
151
|
prefect/server/api/collections_data/views/aggregate-worker-metadata.json,sha256=gqrwGyylzBEzlFSPOJcMuUwdoK_zojpU0SZaBDgK5FE,79748
|
152
152
|
prefect/server/api/static/prefect-logo-mark-gradient.png,sha256=ylRjJkI_JHCw8VbQasNnXQHwZW-sH-IQiUGSD3aWP1E,73430
|
@@ -187,8 +187,8 @@ prefect/workers/cloud.py,sha256=BOVVY5z-vUIQ2u8LwMTXDaNys2fjOZSS5YGDwJmTQjI,230
|
|
187
187
|
prefect/workers/process.py,sha256=t1f1EYRoPL5B25KbLgUX2b5q-lCCAXb2Gpf6T2M9WfY,19822
|
188
188
|
prefect/workers/server.py,sha256=lgh2FfSuaNU7b6HPxSFm8JtKvAvHsZGkiOo4y4tW1Cw,2022
|
189
189
|
prefect/workers/utilities.py,sha256=VfPfAlGtTuDj0-Kb8WlMgAuOfgXCdrGAnKMapPSBrwc,2483
|
190
|
-
prefect_client-3.0.
|
191
|
-
prefect_client-3.0.
|
192
|
-
prefect_client-3.0.
|
193
|
-
prefect_client-3.0.
|
194
|
-
prefect_client-3.0.
|
190
|
+
prefect_client-3.0.0rc16.dist-info/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
|
191
|
+
prefect_client-3.0.0rc16.dist-info/METADATA,sha256=u1Slx4EdzeZnEU0qZ_7V28FsWgCbcfRsjYVCk-1KNcY,7404
|
192
|
+
prefect_client-3.0.0rc16.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
|
193
|
+
prefect_client-3.0.0rc16.dist-info/top_level.txt,sha256=MJZYJgFdbRc2woQCeB4vM6T33tr01TmkEhRcns6H_H4,8
|
194
|
+
prefect_client-3.0.0rc16.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|