prefect-client 3.1.14__py3-none-any.whl → 3.2.0__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/__main__.py +4 -0
- prefect/_experimental/lineage.py +40 -22
- prefect/_experimental/sla/objects.py +29 -1
- prefect/_internal/compatibility/deprecated.py +4 -4
- prefect/_internal/compatibility/migration.py +1 -1
- prefect/_internal/concurrency/calls.py +1 -2
- prefect/_internal/concurrency/cancellation.py +2 -4
- prefect/_internal/concurrency/services.py +1 -1
- prefect/_internal/concurrency/threads.py +3 -3
- prefect/_internal/schemas/bases.py +3 -11
- prefect/_internal/schemas/validators.py +36 -60
- prefect/_result_records.py +235 -0
- prefect/_version.py +3 -3
- prefect/agent.py +1 -0
- prefect/artifacts.py +408 -105
- prefect/automations.py +4 -8
- prefect/blocks/core.py +1 -1
- prefect/blocks/notifications.py +13 -8
- prefect/cache_policies.py +2 -0
- prefect/client/base.py +7 -8
- prefect/client/collections.py +3 -6
- prefect/client/orchestration/__init__.py +15 -263
- prefect/client/orchestration/_deployments/client.py +14 -6
- prefect/client/orchestration/_flow_runs/client.py +10 -6
- prefect/client/orchestration/_work_pools/__init__.py +0 -0
- prefect/client/orchestration/_work_pools/client.py +598 -0
- prefect/client/orchestration/base.py +9 -2
- prefect/client/schemas/actions.py +77 -3
- prefect/client/schemas/objects.py +22 -50
- prefect/client/schemas/schedules.py +11 -22
- prefect/client/types/flexible_schedule_list.py +2 -1
- prefect/context.py +2 -3
- prefect/deployments/base.py +13 -16
- prefect/deployments/flow_runs.py +1 -1
- prefect/deployments/runner.py +236 -47
- prefect/deployments/schedules.py +7 -1
- prefect/engine.py +4 -9
- prefect/events/clients.py +39 -0
- prefect/events/schemas/automations.py +4 -2
- prefect/events/utilities.py +15 -13
- prefect/exceptions.py +1 -1
- prefect/flow_engine.py +119 -0
- prefect/flow_runs.py +4 -8
- prefect/flows.py +282 -31
- prefect/infrastructure/__init__.py +1 -0
- prefect/infrastructure/base.py +1 -0
- prefect/infrastructure/provisioners/__init__.py +3 -6
- prefect/infrastructure/provisioners/coiled.py +3 -3
- prefect/infrastructure/provisioners/container_instance.py +1 -0
- prefect/infrastructure/provisioners/ecs.py +6 -6
- prefect/infrastructure/provisioners/modal.py +3 -3
- prefect/input/run_input.py +5 -7
- prefect/locking/filesystem.py +4 -3
- prefect/main.py +1 -1
- prefect/results.py +42 -249
- prefect/runner/runner.py +9 -4
- prefect/runner/server.py +5 -5
- prefect/runner/storage.py +12 -10
- prefect/runner/submit.py +2 -4
- prefect/runtime/task_run.py +37 -9
- prefect/schedules.py +231 -0
- prefect/serializers.py +5 -5
- prefect/settings/__init__.py +2 -1
- prefect/settings/base.py +3 -3
- prefect/settings/models/root.py +4 -0
- prefect/settings/models/server/services.py +50 -9
- prefect/settings/sources.py +4 -4
- prefect/states.py +42 -11
- prefect/task_engine.py +10 -10
- prefect/task_runners.py +11 -22
- prefect/task_worker.py +9 -9
- prefect/tasks.py +28 -45
- prefect/telemetry/bootstrap.py +4 -6
- prefect/telemetry/services.py +2 -4
- prefect/types/__init__.py +2 -1
- prefect/types/_datetime.py +28 -1
- prefect/utilities/_engine.py +0 -1
- prefect/utilities/asyncutils.py +4 -8
- prefect/utilities/collections.py +13 -22
- prefect/utilities/dispatch.py +2 -4
- prefect/utilities/dockerutils.py +6 -6
- prefect/utilities/importtools.py +1 -68
- prefect/utilities/names.py +1 -1
- prefect/utilities/processutils.py +3 -6
- prefect/utilities/pydantic.py +4 -6
- prefect/utilities/render_swagger.py +1 -1
- prefect/utilities/schema_tools/hydration.py +6 -5
- prefect/utilities/templating.py +21 -8
- prefect/utilities/visualization.py +2 -4
- prefect/workers/base.py +3 -3
- prefect/workers/block.py +1 -0
- prefect/workers/cloud.py +1 -0
- prefect/workers/process.py +1 -0
- {prefect_client-3.1.14.dist-info → prefect_client-3.2.0.dist-info}/METADATA +1 -1
- {prefect_client-3.1.14.dist-info → prefect_client-3.2.0.dist-info}/RECORD +98 -93
- {prefect_client-3.1.14.dist-info → prefect_client-3.2.0.dist-info}/LICENSE +0 -0
- {prefect_client-3.1.14.dist-info → prefect_client-3.2.0.dist-info}/WHEEL +0 -0
- {prefect_client-3.1.14.dist-info → prefect_client-3.2.0.dist-info}/top_level.txt +0 -0
@@ -1,5 +1,5 @@
|
|
1
1
|
from copy import deepcopy
|
2
|
-
from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union
|
2
|
+
from typing import TYPE_CHECKING, Any, Callable, Optional, TypeVar, Union
|
3
3
|
from uuid import UUID, uuid4
|
4
4
|
|
5
5
|
import jsonschema
|
@@ -22,7 +22,14 @@ from prefect.client.schemas.objects import (
|
|
22
22
|
StateDetails,
|
23
23
|
StateType,
|
24
24
|
)
|
25
|
-
from prefect.client.schemas.schedules import
|
25
|
+
from prefect.client.schemas.schedules import (
|
26
|
+
SCHEDULE_TYPES,
|
27
|
+
CronSchedule,
|
28
|
+
IntervalSchedule,
|
29
|
+
NoSchedule,
|
30
|
+
RRuleSchedule,
|
31
|
+
)
|
32
|
+
from prefect.schedules import Schedule
|
26
33
|
from prefect.settings import PREFECT_DEPLOYMENT_SCHEDULE_MAX_SCHEDULED_RUNS
|
27
34
|
from prefect.types import (
|
28
35
|
MAX_VARIABLE_NAME_LENGTH,
|
@@ -39,7 +46,7 @@ from prefect.utilities.collections import listrepr
|
|
39
46
|
from prefect.utilities.pydantic import get_class_fields_only
|
40
47
|
|
41
48
|
if TYPE_CHECKING:
|
42
|
-
from prefect.
|
49
|
+
from prefect._result_records import ResultRecordMetadata
|
43
50
|
|
44
51
|
R = TypeVar("R")
|
45
52
|
|
@@ -92,6 +99,24 @@ class DeploymentScheduleCreate(ActionBaseModel):
|
|
92
99
|
default=None,
|
93
100
|
description="The maximum number of scheduled runs for the schedule.",
|
94
101
|
)
|
102
|
+
parameters: dict[str, Any] = Field(
|
103
|
+
default_factory=dict,
|
104
|
+
description="Parameter overrides for the schedule.",
|
105
|
+
)
|
106
|
+
slug: Optional[str] = Field(
|
107
|
+
default=None,
|
108
|
+
description="A unique identifier for the schedule.",
|
109
|
+
)
|
110
|
+
|
111
|
+
@field_validator("active", mode="wrap")
|
112
|
+
@classmethod
|
113
|
+
def validate_active(cls, v: Any, handler: Callable[[Any], Any]) -> bool:
|
114
|
+
try:
|
115
|
+
return handler(v)
|
116
|
+
except Exception:
|
117
|
+
raise ValueError(
|
118
|
+
f"active must be able to be parsed as a boolean, got {v!r} of type {type(v)}"
|
119
|
+
)
|
95
120
|
|
96
121
|
@field_validator("max_scheduled_runs")
|
97
122
|
@classmethod
|
@@ -100,6 +125,45 @@ class DeploymentScheduleCreate(ActionBaseModel):
|
|
100
125
|
v, PREFECT_DEPLOYMENT_SCHEDULE_MAX_SCHEDULED_RUNS.value()
|
101
126
|
)
|
102
127
|
|
128
|
+
@classmethod
|
129
|
+
def from_schedule(cls, schedule: Schedule) -> "DeploymentScheduleCreate":
|
130
|
+
if schedule.interval is not None:
|
131
|
+
return cls(
|
132
|
+
schedule=IntervalSchedule(
|
133
|
+
interval=schedule.interval,
|
134
|
+
timezone=schedule.timezone,
|
135
|
+
anchor_date=schedule.anchor_date,
|
136
|
+
),
|
137
|
+
parameters=schedule.parameters,
|
138
|
+
active=schedule.active,
|
139
|
+
slug=schedule.slug,
|
140
|
+
)
|
141
|
+
elif schedule.cron is not None:
|
142
|
+
return cls(
|
143
|
+
schedule=CronSchedule(
|
144
|
+
cron=schedule.cron,
|
145
|
+
timezone=schedule.timezone,
|
146
|
+
day_or=schedule.day_or,
|
147
|
+
),
|
148
|
+
parameters=schedule.parameters,
|
149
|
+
active=schedule.active,
|
150
|
+
slug=schedule.slug,
|
151
|
+
)
|
152
|
+
elif schedule.rrule is not None:
|
153
|
+
return cls(
|
154
|
+
schedule=RRuleSchedule(
|
155
|
+
rrule=schedule.rrule,
|
156
|
+
timezone=schedule.timezone,
|
157
|
+
),
|
158
|
+
parameters=schedule.parameters,
|
159
|
+
active=schedule.active,
|
160
|
+
slug=schedule.slug,
|
161
|
+
)
|
162
|
+
else:
|
163
|
+
return cls(
|
164
|
+
schedule=NoSchedule(),
|
165
|
+
)
|
166
|
+
|
103
167
|
|
104
168
|
class DeploymentScheduleUpdate(ActionBaseModel):
|
105
169
|
schedule: Optional[SCHEDULE_TYPES] = Field(
|
@@ -113,6 +177,14 @@ class DeploymentScheduleUpdate(ActionBaseModel):
|
|
113
177
|
default=None,
|
114
178
|
description="The maximum number of scheduled runs for the schedule.",
|
115
179
|
)
|
180
|
+
parameters: Optional[dict[str, Any]] = Field(
|
181
|
+
default=None,
|
182
|
+
description="Parameter overrides for the schedule.",
|
183
|
+
)
|
184
|
+
slug: Optional[str] = Field(
|
185
|
+
default=None,
|
186
|
+
description="A unique identifier for the schedule.",
|
187
|
+
)
|
116
188
|
|
117
189
|
@field_validator("max_scheduled_runs")
|
118
190
|
@classmethod
|
@@ -254,6 +326,8 @@ class DeploymentUpdate(ActionBaseModel):
|
|
254
326
|
"Whether or not the deployment should enforce the parameter schema."
|
255
327
|
),
|
256
328
|
)
|
329
|
+
parameter_openapi_schema: Optional[dict[str, Any]] = Field(default_factory=dict)
|
330
|
+
pull_steps: Optional[list[dict[str, Any]]] = Field(default=None)
|
257
331
|
|
258
332
|
def check_valid_configuration(self, base_job_template: dict[str, Any]) -> None:
|
259
333
|
"""Check that the combination of base_job_template defaults
|
@@ -1,3 +1,5 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
1
3
|
import datetime
|
2
4
|
import warnings
|
3
5
|
from collections.abc import Callable, Mapping
|
@@ -15,7 +17,6 @@ from typing import (
|
|
15
17
|
from uuid import UUID, uuid4
|
16
18
|
|
17
19
|
import orjson
|
18
|
-
import pendulum
|
19
20
|
from pydantic import (
|
20
21
|
ConfigDict,
|
21
22
|
Discriminator,
|
@@ -48,6 +49,7 @@ from prefect._internal.schemas.validators import (
|
|
48
49
|
validate_not_negative,
|
49
50
|
validate_parent_and_ref_diff,
|
50
51
|
)
|
52
|
+
from prefect._result_records import ResultRecordMetadata
|
51
53
|
from prefect.client.schemas.schedules import SCHEDULE_TYPES
|
52
54
|
from prefect.settings import PREFECT_CLOUD_API_URL, PREFECT_CLOUD_UI_URL
|
53
55
|
from prefect.types import (
|
@@ -58,25 +60,17 @@ from prefect.types import (
|
|
58
60
|
PositiveInteger,
|
59
61
|
StrictVariableValue,
|
60
62
|
)
|
63
|
+
from prefect.types._datetime import DateTime
|
61
64
|
from prefect.utilities.collections import AutoEnum, listrepr, visit_collection
|
62
65
|
from prefect.utilities.names import generate_slug
|
63
66
|
from prefect.utilities.pydantic import handle_secret_render
|
64
67
|
|
65
|
-
if TYPE_CHECKING:
|
66
|
-
from prefect.client.schemas.actions import StateCreate
|
67
|
-
from prefect.results import ResultRecordMetadata
|
68
|
-
|
69
|
-
DateTime = pendulum.DateTime
|
70
|
-
else:
|
71
|
-
from prefect.types import DateTime
|
72
|
-
|
73
|
-
|
74
68
|
R = TypeVar("R", default=Any)
|
75
69
|
|
76
70
|
|
77
|
-
DEFAULT_BLOCK_SCHEMA_VERSION = "non-versioned"
|
78
|
-
DEFAULT_AGENT_WORK_POOL_NAME = "default-agent-pool"
|
79
|
-
FLOW_RUN_NOTIFICATION_TEMPLATE_KWARGS = [
|
71
|
+
DEFAULT_BLOCK_SCHEMA_VERSION: Literal["non-versioned"] = "non-versioned"
|
72
|
+
DEFAULT_AGENT_WORK_POOL_NAME: Literal["default-agent-pool"] = "default-agent-pool"
|
73
|
+
FLOW_RUN_NOTIFICATION_TEMPLATE_KWARGS: list[str] = [
|
80
74
|
"flow_run_notification_policy_id",
|
81
75
|
"flow_id",
|
82
76
|
"flow_name",
|
@@ -105,7 +99,7 @@ class StateType(AutoEnum):
|
|
105
99
|
CANCELLING = AutoEnum.auto()
|
106
100
|
|
107
101
|
|
108
|
-
TERMINAL_STATES = {
|
102
|
+
TERMINAL_STATES: set[StateType] = {
|
109
103
|
StateType.COMPLETED,
|
110
104
|
StateType.CANCELLED,
|
111
105
|
StateType.FAILED,
|
@@ -223,8 +217,7 @@ class State(ObjectBaseModel, Generic[R]):
|
|
223
217
|
raise_on_failure: Literal[True] = ...,
|
224
218
|
fetch: bool = ...,
|
225
219
|
retry_result_failure: bool = ...,
|
226
|
-
) -> R:
|
227
|
-
...
|
220
|
+
) -> R: ...
|
228
221
|
|
229
222
|
@overload
|
230
223
|
def result(
|
@@ -232,8 +225,7 @@ class State(ObjectBaseModel, Generic[R]):
|
|
232
225
|
raise_on_failure: Literal[False] = False,
|
233
226
|
fetch: bool = ...,
|
234
227
|
retry_result_failure: bool = ...,
|
235
|
-
) -> Union[R, Exception]:
|
236
|
-
...
|
228
|
+
) -> Union[R, Exception]: ...
|
237
229
|
|
238
230
|
@overload
|
239
231
|
def result(
|
@@ -241,8 +233,7 @@ class State(ObjectBaseModel, Generic[R]):
|
|
241
233
|
raise_on_failure: bool = ...,
|
242
234
|
fetch: bool = ...,
|
243
235
|
retry_result_failure: bool = ...,
|
244
|
-
) -> Union[R, Exception]:
|
245
|
-
...
|
236
|
+
) -> Union[R, Exception]: ...
|
246
237
|
|
247
238
|
@deprecated.deprecated_parameter(
|
248
239
|
"fetch",
|
@@ -333,33 +324,6 @@ class State(ObjectBaseModel, Generic[R]):
|
|
333
324
|
retry_result_failure=retry_result_failure,
|
334
325
|
)
|
335
326
|
|
336
|
-
def to_state_create(self) -> "StateCreate":
|
337
|
-
"""
|
338
|
-
Convert this state to a `StateCreate` type which can be used to set the state of
|
339
|
-
a run in the API.
|
340
|
-
|
341
|
-
This method will drop this state's `data` if it is not a result type. Only
|
342
|
-
results should be sent to the API. Other data is only available locally.
|
343
|
-
"""
|
344
|
-
from prefect.client.schemas.actions import StateCreate
|
345
|
-
from prefect.results import (
|
346
|
-
ResultRecord,
|
347
|
-
should_persist_result,
|
348
|
-
)
|
349
|
-
|
350
|
-
if isinstance(self.data, ResultRecord) and should_persist_result():
|
351
|
-
data = self.data.metadata # pyright: ignore[reportUnknownMemberType] unable to narrow ResultRecord type
|
352
|
-
else:
|
353
|
-
data = None
|
354
|
-
|
355
|
-
return StateCreate(
|
356
|
-
type=self.type,
|
357
|
-
name=self.name,
|
358
|
-
message=self.message,
|
359
|
-
data=data,
|
360
|
-
state_details=self.state_details,
|
361
|
-
)
|
362
|
-
|
363
327
|
@model_validator(mode="after")
|
364
328
|
def default_name_from_type(self) -> Self:
|
365
329
|
"""If a name is not provided, use the type"""
|
@@ -374,7 +338,7 @@ class State(ObjectBaseModel, Generic[R]):
|
|
374
338
|
def default_scheduled_start_time(self) -> Self:
|
375
339
|
if self.type == StateType.SCHEDULED:
|
376
340
|
if not self.state_details.scheduled_time:
|
377
|
-
self.state_details.scheduled_time =
|
341
|
+
self.state_details.scheduled_time = DateTime.now("utc")
|
378
342
|
return self
|
379
343
|
|
380
344
|
@model_validator(mode="after")
|
@@ -1099,6 +1063,14 @@ class DeploymentSchedule(ObjectBaseModel):
|
|
1099
1063
|
default=None,
|
1100
1064
|
description="The maximum number of scheduled runs for the schedule.",
|
1101
1065
|
)
|
1066
|
+
parameters: dict[str, Any] = Field(
|
1067
|
+
default_factory=dict,
|
1068
|
+
description="Parameter overrides for the schedule.",
|
1069
|
+
)
|
1070
|
+
slug: Optional[str] = Field(
|
1071
|
+
default=None,
|
1072
|
+
description="A unique identifier for the schedule.",
|
1073
|
+
)
|
1102
1074
|
|
1103
1075
|
|
1104
1076
|
class Deployment(ObjectBaseModel):
|
@@ -1374,7 +1346,7 @@ class WorkQueueHealthPolicy(PrefectBaseModel):
|
|
1374
1346
|
)
|
1375
1347
|
|
1376
1348
|
def evaluate_health_status(
|
1377
|
-
self, late_runs_count: int, last_polled:
|
1349
|
+
self, late_runs_count: int, last_polled: DateTime | None = None
|
1378
1350
|
) -> bool:
|
1379
1351
|
"""
|
1380
1352
|
Given empirical information about the state of the work queue, evaluate its health status.
|
@@ -1396,7 +1368,7 @@ class WorkQueueHealthPolicy(PrefectBaseModel):
|
|
1396
1368
|
if self.maximum_seconds_since_last_polled is not None:
|
1397
1369
|
if (
|
1398
1370
|
last_polled is None
|
1399
|
-
or
|
1371
|
+
or DateTime.now("UTC").diff(last_polled).in_seconds()
|
1400
1372
|
> self.maximum_seconds_since_last_polled
|
1401
1373
|
):
|
1402
1374
|
healthy = False
|
@@ -8,7 +8,6 @@ from typing import TYPE_CHECKING, Annotated, Any, ClassVar, Optional, Union
|
|
8
8
|
import dateutil
|
9
9
|
import dateutil.rrule
|
10
10
|
import dateutil.tz
|
11
|
-
import pendulum
|
12
11
|
from pydantic import AfterValidator, ConfigDict, Field, field_validator, model_validator
|
13
12
|
from typing_extensions import TypeAlias, TypeGuard
|
14
13
|
|
@@ -19,14 +18,7 @@ from prefect._internal.schemas.validators import (
|
|
19
18
|
validate_cron_string,
|
20
19
|
validate_rrule_string,
|
21
20
|
)
|
22
|
-
|
23
|
-
if TYPE_CHECKING:
|
24
|
-
# type checkers have difficulty accepting that
|
25
|
-
# pydantic_extra_types.pendulum_dt and pendulum.DateTime can be used
|
26
|
-
# together.
|
27
|
-
DateTime = pendulum.DateTime
|
28
|
-
else:
|
29
|
-
from prefect.types import DateTime
|
21
|
+
from prefect.types._datetime import Date, DateTime
|
30
22
|
|
31
23
|
MAX_ITERATIONS = 1000
|
32
24
|
# approx. 1 years worth of RDATEs + buffer
|
@@ -83,7 +75,7 @@ class IntervalSchedule(PrefectBaseModel):
|
|
83
75
|
|
84
76
|
interval: datetime.timedelta = Field(gt=datetime.timedelta(0))
|
85
77
|
anchor_date: Annotated[DateTime, AfterValidator(default_anchor_date)] = Field(
|
86
|
-
default_factory=lambda:
|
78
|
+
default_factory=lambda: DateTime.now("UTC"),
|
87
79
|
examples=["2020-01-01T00:00:00Z"],
|
88
80
|
)
|
89
81
|
timezone: Optional[str] = Field(default=None, examples=["America/New_York"])
|
@@ -99,12 +91,9 @@ class IntervalSchedule(PrefectBaseModel):
|
|
99
91
|
self,
|
100
92
|
/,
|
101
93
|
interval: datetime.timedelta,
|
102
|
-
anchor_date: Optional[
|
103
|
-
Union[pendulum.DateTime, datetime.datetime, str]
|
104
|
-
] = None,
|
94
|
+
anchor_date: Optional[Union[DateTime, datetime.datetime, str]] = None,
|
105
95
|
timezone: Optional[str] = None,
|
106
|
-
) -> None:
|
107
|
-
...
|
96
|
+
) -> None: ...
|
108
97
|
|
109
98
|
|
110
99
|
class CronSchedule(PrefectBaseModel):
|
@@ -145,7 +134,7 @@ class CronSchedule(PrefectBaseModel):
|
|
145
134
|
|
146
135
|
@field_validator("timezone")
|
147
136
|
@classmethod
|
148
|
-
def valid_timezone(cls, v: Optional[str]) -> str:
|
137
|
+
def valid_timezone(cls, v: Optional[str]) -> Optional[str]:
|
149
138
|
return default_timezone(v)
|
150
139
|
|
151
140
|
@field_validator("cron")
|
@@ -154,7 +143,7 @@ class CronSchedule(PrefectBaseModel):
|
|
154
143
|
return validate_cron_string(v)
|
155
144
|
|
156
145
|
|
157
|
-
DEFAULT_ANCHOR_DATE =
|
146
|
+
DEFAULT_ANCHOR_DATE = Date(2020, 1, 1)
|
158
147
|
|
159
148
|
|
160
149
|
def _rrule_dt(
|
@@ -220,7 +209,7 @@ class RRuleSchedule(PrefectBaseModel):
|
|
220
209
|
return RRuleSchedule(rrule=str(rrule), timezone=timezone)
|
221
210
|
rrules = _rrule(rrule)
|
222
211
|
dtstarts = [dts for rr in rrules if (dts := _rrule_dt(rr)) is not None]
|
223
|
-
unique_dstarts = set(
|
212
|
+
unique_dstarts = set(DateTime.instance(d).in_tz("UTC") for d in dtstarts)
|
224
213
|
unique_timezones = set(d.tzinfo for d in dtstarts if d.tzinfo is not None)
|
225
214
|
|
226
215
|
if len(unique_timezones) > 1:
|
@@ -276,7 +265,7 @@ class RRuleSchedule(PrefectBaseModel):
|
|
276
265
|
kwargs.update(
|
277
266
|
until=until.replace(tzinfo=timezone),
|
278
267
|
)
|
279
|
-
return rrule.replace(**kwargs)
|
268
|
+
return rrule.replace(**kwargs) # pyright: ignore[reportUnknownVariableType, reportUnknownMemberType] missing type hints
|
280
269
|
|
281
270
|
# update rrules
|
282
271
|
localized_rrules: list[dateutil.rrule.rrule] = []
|
@@ -286,7 +275,7 @@ class RRuleSchedule(PrefectBaseModel):
|
|
286
275
|
kwargs: dict[str, Any] = dict(dtstart=dtstart.replace(tzinfo=timezone))
|
287
276
|
if until := _rrule_dt(rr, "_until"):
|
288
277
|
kwargs.update(until=until.replace(tzinfo=timezone))
|
289
|
-
localized_rrules.append(rr.replace(**kwargs))
|
278
|
+
localized_rrules.append(rr.replace(**kwargs)) # pyright: ignore[reportUnknownArgumentType, reportUnknownMemberType] missing type hints
|
290
279
|
setattr(rrule, "_rrule", localized_rrules)
|
291
280
|
|
292
281
|
# update exrules
|
@@ -297,7 +286,7 @@ class RRuleSchedule(PrefectBaseModel):
|
|
297
286
|
kwargs = dict(dtstart=dtstart.replace(tzinfo=timezone))
|
298
287
|
if until := _rrule_dt(exr, "_until"):
|
299
288
|
kwargs.update(until=until.replace(tzinfo=timezone))
|
300
|
-
localized_exrules.append(exr.replace(**kwargs))
|
289
|
+
localized_exrules.append(exr.replace(**kwargs)) # pyright: ignore[reportUnknownArgumentType, reportUnknownMemberType] missing type hints
|
301
290
|
setattr(rrule, "_exrule", localized_exrules)
|
302
291
|
|
303
292
|
# update rdates
|
@@ -381,7 +370,7 @@ def construct_schedule(
|
|
381
370
|
if isinstance(interval, (int, float)):
|
382
371
|
interval = datetime.timedelta(seconds=interval)
|
383
372
|
if not anchor_date:
|
384
|
-
anchor_date =
|
373
|
+
anchor_date = DateTime.now()
|
385
374
|
schedule = IntervalSchedule(
|
386
375
|
interval=interval, anchor_date=anchor_date, timezone=timezone
|
387
376
|
)
|
@@ -5,7 +5,8 @@ from typing_extensions import TypeAlias
|
|
5
5
|
if TYPE_CHECKING:
|
6
6
|
from prefect.client.schemas.actions import DeploymentScheduleCreate
|
7
7
|
from prefect.client.schemas.schedules import SCHEDULE_TYPES
|
8
|
+
from prefect.schedules import Schedule
|
8
9
|
|
9
10
|
FlexibleScheduleList: TypeAlias = Sequence[
|
10
|
-
Union["DeploymentScheduleCreate", dict[str, Any], "SCHEDULE_TYPES"]
|
11
|
+
Union["DeploymentScheduleCreate", dict[str, Any], "SCHEDULE_TYPES", "Schedule"]
|
11
12
|
]
|
prefect/context.py
CHANGED
@@ -73,8 +73,8 @@ def hydrated_context(
|
|
73
73
|
# We need to rebuild the models because we might be hydrating in a remote
|
74
74
|
# environment where the models are not available.
|
75
75
|
# TODO: Remove this once we have fixed our circular imports and we don't need to rebuild models any more.
|
76
|
+
from prefect._result_records import ResultRecordMetadata
|
76
77
|
from prefect.flows import Flow
|
77
|
-
from prefect.results import ResultRecordMetadata
|
78
78
|
from prefect.tasks import Task
|
79
79
|
|
80
80
|
_types: dict[str, Any] = dict(
|
@@ -123,8 +123,7 @@ class ContextModel(BaseModel):
|
|
123
123
|
|
124
124
|
if TYPE_CHECKING:
|
125
125
|
# subclasses can pass through keyword arguments to the pydantic base model
|
126
|
-
def __init__(self, **kwargs: Any) -> None:
|
127
|
-
...
|
126
|
+
def __init__(self, **kwargs: Any) -> None: ...
|
128
127
|
|
129
128
|
# The context variable for storing data must be defined by the child class
|
130
129
|
__var__: ClassVar[ContextVar[Self]]
|
prefect/deployments/base.py
CHANGED
@@ -10,12 +10,11 @@ from __future__ import annotations
|
|
10
10
|
import os
|
11
11
|
from copy import deepcopy
|
12
12
|
from pathlib import Path
|
13
|
-
from typing import Any, Dict, List, Optional
|
13
|
+
from typing import Any, Dict, List, Optional
|
14
14
|
|
15
15
|
import yaml
|
16
16
|
from ruamel.yaml import YAML
|
17
17
|
|
18
|
-
from prefect.client.schemas.actions import DeploymentScheduleCreate
|
19
18
|
from prefect.client.schemas.objects import ConcurrencyLimitStrategy
|
20
19
|
from prefect.client.schemas.schedules import IntervalSchedule
|
21
20
|
from prefect.utilities._git import get_git_branch, get_git_remote_origin_url
|
@@ -207,8 +206,8 @@ def initialize_project(
|
|
207
206
|
|
208
207
|
|
209
208
|
def _format_deployment_for_saving_to_prefect_file(
|
210
|
-
deployment:
|
211
|
-
) ->
|
209
|
+
deployment: dict[str, Any],
|
210
|
+
) -> dict[str, Any]:
|
212
211
|
"""
|
213
212
|
Formats a deployment into a templated deploy config for saving to prefect.yaml.
|
214
213
|
|
@@ -227,10 +226,8 @@ def _format_deployment_for_saving_to_prefect_file(
|
|
227
226
|
deployment.pop("flow_name", None)
|
228
227
|
|
229
228
|
if deployment.get("schedules"):
|
230
|
-
schedules = []
|
231
|
-
for deployment_schedule in
|
232
|
-
List[DeploymentScheduleCreate], deployment["schedules"]
|
233
|
-
):
|
229
|
+
schedules: list[dict[str, Any]] = []
|
230
|
+
for deployment_schedule in deployment["schedules"]:
|
234
231
|
if isinstance(deployment_schedule.schedule, IntervalSchedule):
|
235
232
|
schedule_config = _interval_schedule_to_dict(
|
236
233
|
deployment_schedule.schedule
|
@@ -257,7 +254,7 @@ def _format_deployment_for_saving_to_prefect_file(
|
|
257
254
|
return deployment
|
258
255
|
|
259
256
|
|
260
|
-
def _interval_schedule_to_dict(schedule: IntervalSchedule) ->
|
257
|
+
def _interval_schedule_to_dict(schedule: IntervalSchedule) -> dict[str, Any]:
|
261
258
|
"""
|
262
259
|
Converts an IntervalSchedule to a dictionary.
|
263
260
|
|
@@ -265,7 +262,7 @@ def _interval_schedule_to_dict(schedule: IntervalSchedule) -> Dict:
|
|
265
262
|
- schedule (IntervalSchedule): the schedule to convert
|
266
263
|
|
267
264
|
Returns:
|
268
|
-
-
|
265
|
+
- dict[str, Any]: the schedule as a dictionary
|
269
266
|
"""
|
270
267
|
schedule_config = schedule.model_dump()
|
271
268
|
schedule_config["interval"] = schedule_config["interval"].total_seconds()
|
@@ -275,12 +272,12 @@ def _interval_schedule_to_dict(schedule: IntervalSchedule) -> Dict:
|
|
275
272
|
|
276
273
|
|
277
274
|
def _save_deployment_to_prefect_file(
|
278
|
-
deployment:
|
279
|
-
build_steps:
|
280
|
-
push_steps:
|
281
|
-
pull_steps:
|
282
|
-
triggers:
|
283
|
-
sla:
|
275
|
+
deployment: dict[str, Any],
|
276
|
+
build_steps: list[dict[str, Any]] | None = None,
|
277
|
+
push_steps: list[dict[str, Any]] | None = None,
|
278
|
+
pull_steps: list[dict[str, Any]] | None = None,
|
279
|
+
triggers: list[dict[str, Any]] | None = None,
|
280
|
+
sla: list[dict[str, Any]] | None = None,
|
284
281
|
prefect_file: Path = Path("prefect.yaml"),
|
285
282
|
):
|
286
283
|
"""
|
prefect/deployments/flow_runs.py
CHANGED
@@ -6,11 +6,11 @@ import anyio
|
|
6
6
|
import pendulum
|
7
7
|
|
8
8
|
import prefect
|
9
|
+
from prefect._result_records import ResultRecordMetadata
|
9
10
|
from prefect.client.schemas import FlowRun
|
10
11
|
from prefect.client.utilities import inject_client
|
11
12
|
from prefect.context import FlowRunContext, TaskRunContext
|
12
13
|
from prefect.logging import get_logger
|
13
|
-
from prefect.results import ResultRecordMetadata
|
14
14
|
from prefect.states import Pending, Scheduled
|
15
15
|
from prefect.tasks import Task
|
16
16
|
from prefect.telemetry.run_telemetry import (
|