prefect-client 3.3.0__py3-none-any.whl → 3.3.2__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/_build_info.py +3 -3
- prefect/_internal/compatibility/deprecated.py +30 -19
- prefect/_internal/concurrency/calls.py +5 -2
- prefect/_internal/pydantic/v2_schema.py +1 -0
- prefect/_internal/schemas/bases.py +4 -2
- prefect/blocks/core.py +10 -13
- prefect/client/base.py +16 -2
- prefect/client/orchestration/__init__.py +5 -0
- prefect/client/orchestration/_deployments/client.py +51 -16
- prefect/client/schemas/actions.py +20 -1
- prefect/client/schemas/objects.py +12 -1
- prefect/client/schemas/responses.py +26 -1
- prefect/context.py +2 -1
- prefect/events/filters.py +1 -1
- prefect/events/related.py +5 -3
- prefect/flows.py +18 -17
- prefect/runner/runner.py +2 -18
- prefect/schedules.py +2 -2
- prefect/server/api/flow_runs.py +15 -14
- prefect/server/api/run_history.py +1 -1
- prefect/server/api/ui/task_runs.py +21 -1
- prefect/settings/base.py +4 -4
- prefect/settings/models/root.py +10 -5
- prefect/tasks.py +8 -9
- prefect/types/_datetime.py +2 -2
- prefect/utilities/callables.py +1 -1
- {prefect_client-3.3.0.dist-info → prefect_client-3.3.2.dist-info}/METADATA +2 -1
- {prefect_client-3.3.0.dist-info → prefect_client-3.3.2.dist-info}/RECORD +30 -30
- {prefect_client-3.3.0.dist-info → prefect_client-3.3.2.dist-info}/WHEEL +0 -0
- {prefect_client-3.3.0.dist-info → prefect_client-3.3.2.dist-info}/licenses/LICENSE +0 -0
prefect/_build_info.py
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Generated by versioningit
|
2
|
-
__version__ = "3.3.
|
3
|
-
__build_date__ = "2025-03
|
4
|
-
__git_commit__ = "
|
2
|
+
__version__ = "3.3.2"
|
3
|
+
__build_date__ = "2025-04-03 21:24:32.871912+00:00"
|
4
|
+
__git_commit__ = "e49e31850463a0c0db93b4798856247a6d1669a6"
|
5
5
|
__dirty__ = False
|
@@ -10,12 +10,15 @@ will be calculated 6 months later. Start and end dates are always in the format
|
|
10
10
|
e.g. Jan 2023.
|
11
11
|
"""
|
12
12
|
|
13
|
+
from __future__ import annotations
|
14
|
+
|
13
15
|
import datetime
|
14
16
|
import functools
|
15
17
|
import sys
|
16
18
|
import warnings
|
17
19
|
from typing import TYPE_CHECKING, Any, Callable, Optional, Union
|
18
20
|
|
21
|
+
import dateparser
|
19
22
|
from pydantic import BaseModel
|
20
23
|
from typing_extensions import ParamSpec, TypeAlias, TypeVar
|
21
24
|
|
@@ -32,6 +35,9 @@ R = TypeVar("R", infer_variance=True)
|
|
32
35
|
M = TypeVar("M", bound=BaseModel)
|
33
36
|
T = TypeVar("T")
|
34
37
|
|
38
|
+
# Note: A datetime is strongly preferred over a string, but a string is acceptable for
|
39
|
+
# backwards compatibility until support is dropped from dateparser in Python 3.15.
|
40
|
+
_AcceptableDate: TypeAlias = Optional[Union[datetime.datetime, str]]
|
35
41
|
|
36
42
|
DEPRECATED_WARNING = (
|
37
43
|
"{name} has been deprecated{when}. It will not be available in new releases after {end_date}."
|
@@ -51,18 +57,25 @@ class PrefectDeprecationWarning(DeprecationWarning):
|
|
51
57
|
"""
|
52
58
|
|
53
59
|
|
60
|
+
def _coerce_datetime(
|
61
|
+
dt: Optional[_AcceptableDate],
|
62
|
+
) -> Optional[datetime.datetime]:
|
63
|
+
if dt is None or isinstance(dt, datetime.datetime):
|
64
|
+
return dt
|
65
|
+
with warnings.catch_warnings():
|
66
|
+
warnings.filterwarnings("ignore", category=DeprecationWarning)
|
67
|
+
return dateparser.parse(dt)
|
68
|
+
|
69
|
+
|
54
70
|
def generate_deprecation_message(
|
55
71
|
name: str,
|
56
|
-
start_date: Optional[
|
57
|
-
end_date: Optional[
|
72
|
+
start_date: Optional[_AcceptableDate] = None,
|
73
|
+
end_date: Optional[_AcceptableDate] = None,
|
58
74
|
help: str = "",
|
59
75
|
when: str = "",
|
60
76
|
) -> str:
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
if end_date is not None and not isinstance(end_date, datetime.datetime):
|
65
|
-
raise ValueError("Must provide end_date as a datetime")
|
77
|
+
start_date = _coerce_datetime(start_date)
|
78
|
+
end_date = _coerce_datetime(end_date)
|
66
79
|
|
67
80
|
if start_date is None and end_date is None:
|
68
81
|
raise ValueError(
|
@@ -87,8 +100,8 @@ def generate_deprecation_message(
|
|
87
100
|
|
88
101
|
def deprecated_callable(
|
89
102
|
*,
|
90
|
-
start_date: Optional[
|
91
|
-
end_date: Optional[
|
103
|
+
start_date: Optional[_AcceptableDate] = None,
|
104
|
+
end_date: Optional[_AcceptableDate] = None,
|
92
105
|
stacklevel: int = 2,
|
93
106
|
help: str = "",
|
94
107
|
) -> Callable[[Callable[P, R]], Callable[P, R]]:
|
@@ -112,8 +125,8 @@ def deprecated_callable(
|
|
112
125
|
|
113
126
|
def deprecated_class(
|
114
127
|
*,
|
115
|
-
start_date: Optional[
|
116
|
-
end_date: Optional[
|
128
|
+
start_date: Optional[_AcceptableDate] = None,
|
129
|
+
end_date: Optional[_AcceptableDate] = None,
|
117
130
|
stacklevel: int = 2,
|
118
131
|
help: str = "",
|
119
132
|
) -> Callable[[type[T]], type[T]]:
|
@@ -141,8 +154,8 @@ def deprecated_class(
|
|
141
154
|
def deprecated_parameter(
|
142
155
|
name: str,
|
143
156
|
*,
|
144
|
-
start_date: Optional[
|
145
|
-
end_date: Optional[
|
157
|
+
start_date: Optional[_AcceptableDate] = None,
|
158
|
+
end_date: Optional[_AcceptableDate] = None,
|
146
159
|
stacklevel: int = 2,
|
147
160
|
help: str = "",
|
148
161
|
when: Optional[Callable[[Any], bool]] = None,
|
@@ -197,8 +210,8 @@ JsonDict: TypeAlias = dict[str, JsonValue]
|
|
197
210
|
def deprecated_field(
|
198
211
|
name: str,
|
199
212
|
*,
|
200
|
-
start_date: Optional[
|
201
|
-
end_date: Optional[
|
213
|
+
start_date: Optional[_AcceptableDate] = None,
|
214
|
+
end_date: Optional[_AcceptableDate] = None,
|
202
215
|
when_message: str = "",
|
203
216
|
help: str = "",
|
204
217
|
when: Optional[Callable[[Any], bool]] = None,
|
@@ -242,7 +255,7 @@ def deprecated_field(
|
|
242
255
|
|
243
256
|
cls_init(__pydantic_self__, **data)
|
244
257
|
|
245
|
-
field = __pydantic_self__.model_fields.get(name)
|
258
|
+
field = __pydantic_self__.__class__.model_fields.get(name)
|
246
259
|
if field is not None:
|
247
260
|
json_schema_extra = field.json_schema_extra or {}
|
248
261
|
|
@@ -279,9 +292,7 @@ def inject_renamed_module_alias_finder():
|
|
279
292
|
sys.meta_path.insert(0, AliasedModuleFinder(DEPRECATED_MODULE_ALIASES))
|
280
293
|
|
281
294
|
|
282
|
-
def register_renamed_module(
|
283
|
-
old_name: str, new_name: str, start_date: datetime.datetime
|
284
|
-
):
|
295
|
+
def register_renamed_module(old_name: str, new_name: str, start_date: _AcceptableDate):
|
285
296
|
"""
|
286
297
|
Register a renamed module.
|
287
298
|
|
@@ -374,8 +374,11 @@ class Call(Generic[T]):
|
|
374
374
|
|
375
375
|
except CancelledError:
|
376
376
|
# Report cancellation
|
377
|
-
|
378
|
-
|
377
|
+
# in rare cases, enforce_sync_deadline raises CancelledError
|
378
|
+
# prior to yielding
|
379
|
+
if cancel_scope is None:
|
380
|
+
self.future.cancel()
|
381
|
+
return None
|
379
382
|
if cancel_scope.timedout():
|
380
383
|
setattr(self.future, "_timed_out", True)
|
381
384
|
self.future.cancel()
|
@@ -64,7 +64,7 @@ class PrefectBaseModel(BaseModel):
|
|
64
64
|
|
65
65
|
def __rich_repr__(self) -> RichReprResult:
|
66
66
|
# Display all of the fields in the model if they differ from the default value
|
67
|
-
for name, field in self.model_fields.items():
|
67
|
+
for name, field in type(self).model_fields.items():
|
68
68
|
value = getattr(self, name)
|
69
69
|
|
70
70
|
# Simplify the display of some common fields
|
@@ -90,7 +90,9 @@ class PrefectBaseModel(BaseModel):
|
|
90
90
|
"""
|
91
91
|
return self.model_copy(
|
92
92
|
update={
|
93
|
-
field: self
|
93
|
+
field: type(self)
|
94
|
+
.model_fields[field]
|
95
|
+
.get_default(call_default_factory=True)
|
94
96
|
for field in self._reset_fields
|
95
97
|
}
|
96
98
|
)
|
prefect/blocks/core.py
CHANGED
@@ -18,6 +18,7 @@ from typing import (
|
|
18
18
|
Optional,
|
19
19
|
TypeVar,
|
20
20
|
Union,
|
21
|
+
cast,
|
21
22
|
get_origin,
|
22
23
|
)
|
23
24
|
from uuid import UUID, uuid4
|
@@ -169,14 +170,13 @@ def _collect_secret_fields(
|
|
169
170
|
return
|
170
171
|
|
171
172
|
if type_ in (SecretStr, SecretBytes) or (
|
172
|
-
isinstance(type_, type)
|
173
|
+
isinstance(type_, type) # type: ignore[unnecessaryIsInstance]
|
173
174
|
and getattr(type_, "__module__", None) == "pydantic.types"
|
174
175
|
and getattr(type_, "__name__", None) == "Secret"
|
175
176
|
):
|
176
177
|
secrets.append(name)
|
177
178
|
elif type_ == SecretDict:
|
178
|
-
# Append .* to field name to signify that all values under
|
179
|
-
# field are secret and should be obfuscated.
|
179
|
+
# Append .* to field name to signify that all values under a given key are secret and should be obfuscated.
|
180
180
|
secrets.append(f"{name}.*")
|
181
181
|
elif Block.is_block_class(type_):
|
182
182
|
secrets.extend(
|
@@ -371,7 +371,7 @@ class Block(BaseModel, ABC):
|
|
371
371
|
visit_fn=partial(handle_secret_render, context=ctx),
|
372
372
|
return_data=True,
|
373
373
|
)
|
374
|
-
for field_name in self.model_fields
|
374
|
+
for field_name in type(self).model_fields
|
375
375
|
}
|
376
376
|
)
|
377
377
|
if extra_fields := {
|
@@ -1501,14 +1501,7 @@ class Block(BaseModel, ABC):
|
|
1501
1501
|
if "$defs" in schema:
|
1502
1502
|
schema["definitions"] = schema.pop("$defs")
|
1503
1503
|
|
1504
|
-
|
1505
|
-
if "additionalProperties" in schema:
|
1506
|
-
schema.pop("additionalProperties")
|
1507
|
-
|
1508
|
-
for _, definition in schema.get("definitions", {}).items():
|
1509
|
-
if "additionalProperties" in definition:
|
1510
|
-
definition.pop("additionalProperties")
|
1511
|
-
|
1504
|
+
schema = remove_nested_keys(["additionalProperties"], schema)
|
1512
1505
|
return schema
|
1513
1506
|
|
1514
1507
|
@classmethod
|
@@ -1521,6 +1514,7 @@ class Block(BaseModel, ABC):
|
|
1521
1514
|
context: dict[str, Any] | None = None,
|
1522
1515
|
) -> Self:
|
1523
1516
|
if isinstance(obj, dict):
|
1517
|
+
obj = cast(dict[str, Any], obj)
|
1524
1518
|
extra_serializer_fields = {
|
1525
1519
|
"_block_document_id",
|
1526
1520
|
"_block_document_name",
|
@@ -1530,7 +1524,10 @@ class Block(BaseModel, ABC):
|
|
1530
1524
|
obj.pop(field, None)
|
1531
1525
|
|
1532
1526
|
return super().model_validate(
|
1533
|
-
obj,
|
1527
|
+
obj,
|
1528
|
+
strict=strict,
|
1529
|
+
from_attributes=from_attributes,
|
1530
|
+
context=context,
|
1534
1531
|
)
|
1535
1532
|
|
1536
1533
|
def model_dump(
|
prefect/client/base.py
CHANGED
@@ -222,6 +222,10 @@ class PrefectHttpxAsyncClient(httpx.AsyncClient):
|
|
222
222
|
if the request either raises an exception listed in `retry_exceptions` or
|
223
223
|
receives a response with a status code listed in `retry_codes`.
|
224
224
|
|
225
|
+
Retries are not counted against the limit if the response headers contains
|
226
|
+
a reserved value, indicating that the server is undergoing maintenance. These
|
227
|
+
requests will retry indefinitely until the header is no longer returned.
|
228
|
+
|
225
229
|
Retries will be delayed based on either the retry header (preferred) or
|
226
230
|
exponential backoff if a retry header is not provided.
|
227
231
|
"""
|
@@ -239,18 +243,21 @@ class PrefectHttpxAsyncClient(httpx.AsyncClient):
|
|
239
243
|
await self._add_csrf_headers(request=request)
|
240
244
|
|
241
245
|
while try_count <= PREFECT_CLIENT_MAX_RETRIES.value():
|
242
|
-
try_count += 1
|
243
246
|
retry_seconds = None
|
244
247
|
exc_info = None
|
245
248
|
|
246
249
|
try:
|
247
250
|
response = await send(request, *send_args, **send_kwargs)
|
248
251
|
except retry_exceptions: # type: ignore
|
252
|
+
try_count += 1
|
249
253
|
if try_count > PREFECT_CLIENT_MAX_RETRIES.value():
|
250
254
|
raise
|
251
255
|
# Otherwise, we will ignore this error but capture the info for logging
|
252
256
|
exc_info = sys.exc_info()
|
253
257
|
else:
|
258
|
+
if response.headers.get("Prefect-Maintenance") != "true":
|
259
|
+
try_count += 1
|
260
|
+
|
254
261
|
# We got a response; check if it's a CSRF error, otherwise
|
255
262
|
# return immediately if it is not retryable
|
256
263
|
if (
|
@@ -441,6 +448,10 @@ class PrefectHttpxSyncClient(httpx.Client):
|
|
441
448
|
if the request either raises an exception listed in `retry_exceptions` or
|
442
449
|
receives a response with a status code listed in `retry_codes`.
|
443
450
|
|
451
|
+
Retries are not counted against the limit if the response headers contains
|
452
|
+
a reserved value, indicating that the server is undergoing maintenance. These
|
453
|
+
requests will retry indefinitely until the header is no longer returned.
|
454
|
+
|
444
455
|
Retries will be delayed based on either the retry header (preferred) or
|
445
456
|
exponential backoff if a retry header is not provided.
|
446
457
|
"""
|
@@ -458,18 +469,21 @@ class PrefectHttpxSyncClient(httpx.Client):
|
|
458
469
|
self._add_csrf_headers(request=request)
|
459
470
|
|
460
471
|
while try_count <= PREFECT_CLIENT_MAX_RETRIES.value():
|
461
|
-
try_count += 1
|
462
472
|
retry_seconds = None
|
463
473
|
exc_info = None
|
464
474
|
|
465
475
|
try:
|
466
476
|
response = send(request, *send_args, **send_kwargs)
|
467
477
|
except retry_exceptions: # type: ignore
|
478
|
+
try_count += 1
|
468
479
|
if try_count > PREFECT_CLIENT_MAX_RETRIES.value():
|
469
480
|
raise
|
470
481
|
# Otherwise, we will ignore this error but capture the info for logging
|
471
482
|
exc_info = sys.exc_info()
|
472
483
|
else:
|
484
|
+
if response.headers.get("Prefect-Maintenance") != "true":
|
485
|
+
try_count += 1
|
486
|
+
|
473
487
|
# We got a response; check if it's a CSRF error, otherwise
|
474
488
|
# return immediately if it is not retryable
|
475
489
|
if (
|
@@ -1,3 +1,4 @@
|
|
1
|
+
from __future__ import annotations
|
1
2
|
import asyncio
|
2
3
|
import base64
|
3
4
|
import datetime
|
@@ -1164,6 +1165,10 @@ class PrefectClient(
|
|
1164
1165
|
def client_version(self) -> str:
|
1165
1166
|
return prefect.__version__
|
1166
1167
|
|
1168
|
+
@property
|
1169
|
+
def loop(self) -> asyncio.AbstractEventLoop | None:
|
1170
|
+
return self._loop
|
1171
|
+
|
1167
1172
|
async def raise_for_api_version_mismatch(self) -> None:
|
1168
1173
|
# Cloud is always compatible as a server
|
1169
1174
|
if self.server_type == ServerType.CLOUD:
|
@@ -29,6 +29,7 @@ if TYPE_CHECKING:
|
|
29
29
|
from prefect.client.schemas.objects import (
|
30
30
|
ConcurrencyOptions,
|
31
31
|
DeploymentSchedule,
|
32
|
+
VersionInfo,
|
32
33
|
)
|
33
34
|
from prefect.client.schemas.responses import (
|
34
35
|
DeploymentResponse,
|
@@ -48,6 +49,7 @@ class DeploymentClient(BaseClient):
|
|
48
49
|
flow_id: "UUID",
|
49
50
|
name: str,
|
50
51
|
version: str | None = None,
|
52
|
+
version_info: "VersionInfo | None" = None,
|
51
53
|
schedules: list["DeploymentScheduleCreate"] | None = None,
|
52
54
|
concurrency_limit: int | None = None,
|
53
55
|
concurrency_options: "ConcurrencyOptions | None" = None,
|
@@ -65,6 +67,9 @@ class DeploymentClient(BaseClient):
|
|
65
67
|
pull_steps: list[dict[str, Any]] | None = None,
|
66
68
|
enforce_parameter_schema: bool | None = None,
|
67
69
|
job_variables: dict[str, Any] | None = None,
|
70
|
+
branch: str | None = None,
|
71
|
+
base: UUID | None = None,
|
72
|
+
root: UUID | None = None,
|
68
73
|
) -> "UUID":
|
69
74
|
"""
|
70
75
|
Create a deployment.
|
@@ -99,6 +104,7 @@ class DeploymentClient(BaseClient):
|
|
99
104
|
flow_id=flow_id,
|
100
105
|
name=name,
|
101
106
|
version=version,
|
107
|
+
version_info=version_info,
|
102
108
|
parameters=dict(parameters or {}),
|
103
109
|
tags=list(tags or []),
|
104
110
|
work_queue_name=work_queue_name,
|
@@ -115,6 +121,9 @@ class DeploymentClient(BaseClient):
|
|
115
121
|
concurrency_options=concurrency_options,
|
116
122
|
pull_steps=pull_steps,
|
117
123
|
enforce_parameter_schema=enforce_parameter_schema,
|
124
|
+
branch=branch,
|
125
|
+
base=base,
|
126
|
+
root=root,
|
118
127
|
)
|
119
128
|
|
120
129
|
if work_pool_name is not None:
|
@@ -123,20 +132,29 @@ class DeploymentClient(BaseClient):
|
|
123
132
|
# Exclude newer fields that are not set to avoid compatibility issues
|
124
133
|
exclude = {
|
125
134
|
field
|
126
|
-
for field in [
|
135
|
+
for field in [
|
136
|
+
"work_pool_name",
|
137
|
+
"work_queue_name",
|
138
|
+
]
|
127
139
|
if field not in deployment_create.model_fields_set
|
128
140
|
}
|
129
141
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
142
|
+
exclude_if_none = [
|
143
|
+
"paused",
|
144
|
+
"pull_steps",
|
145
|
+
"enforce_parameter_schema",
|
146
|
+
"version_info",
|
147
|
+
"branch",
|
148
|
+
"base",
|
149
|
+
"root",
|
150
|
+
]
|
135
151
|
|
136
|
-
|
137
|
-
|
152
|
+
for field in exclude_if_none:
|
153
|
+
if getattr(deployment_create, field) is None:
|
154
|
+
exclude.add(field)
|
138
155
|
|
139
156
|
json = deployment_create.model_dump(mode="json", exclude=exclude)
|
157
|
+
|
140
158
|
response = self.request(
|
141
159
|
"POST",
|
142
160
|
"/deployments/",
|
@@ -593,6 +611,7 @@ class DeploymentAsyncClient(BaseAsyncClient):
|
|
593
611
|
flow_id: "UUID",
|
594
612
|
name: str,
|
595
613
|
version: str | None = None,
|
614
|
+
version_info: "VersionInfo | None" = None,
|
596
615
|
schedules: list["DeploymentScheduleCreate"] | None = None,
|
597
616
|
concurrency_limit: int | None = None,
|
598
617
|
concurrency_options: "ConcurrencyOptions | None" = None,
|
@@ -610,6 +629,9 @@ class DeploymentAsyncClient(BaseAsyncClient):
|
|
610
629
|
pull_steps: list[dict[str, Any]] | None = None,
|
611
630
|
enforce_parameter_schema: bool | None = None,
|
612
631
|
job_variables: dict[str, Any] | None = None,
|
632
|
+
branch: str | None = None,
|
633
|
+
base: UUID | None = None,
|
634
|
+
root: UUID | None = None,
|
613
635
|
) -> "UUID":
|
614
636
|
"""
|
615
637
|
Create a deployment.
|
@@ -644,6 +666,7 @@ class DeploymentAsyncClient(BaseAsyncClient):
|
|
644
666
|
flow_id=flow_id,
|
645
667
|
name=name,
|
646
668
|
version=version,
|
669
|
+
version_info=version_info,
|
647
670
|
parameters=dict(parameters or {}),
|
648
671
|
tags=list(tags or []),
|
649
672
|
work_queue_name=work_queue_name,
|
@@ -660,6 +683,9 @@ class DeploymentAsyncClient(BaseAsyncClient):
|
|
660
683
|
concurrency_options=concurrency_options,
|
661
684
|
pull_steps=pull_steps,
|
662
685
|
enforce_parameter_schema=enforce_parameter_schema,
|
686
|
+
branch=branch,
|
687
|
+
base=base,
|
688
|
+
root=root,
|
663
689
|
)
|
664
690
|
|
665
691
|
if work_pool_name is not None:
|
@@ -668,20 +694,29 @@ class DeploymentAsyncClient(BaseAsyncClient):
|
|
668
694
|
# Exclude newer fields that are not set to avoid compatibility issues
|
669
695
|
exclude = {
|
670
696
|
field
|
671
|
-
for field in [
|
697
|
+
for field in [
|
698
|
+
"work_pool_name",
|
699
|
+
"work_queue_name",
|
700
|
+
]
|
672
701
|
if field not in deployment_create.model_fields_set
|
673
702
|
}
|
674
703
|
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
704
|
+
exclude_if_none = [
|
705
|
+
"paused",
|
706
|
+
"pull_steps",
|
707
|
+
"enforce_parameter_schema",
|
708
|
+
"version_info",
|
709
|
+
"branch",
|
710
|
+
"base",
|
711
|
+
"root",
|
712
|
+
]
|
680
713
|
|
681
|
-
|
682
|
-
|
714
|
+
for field in exclude_if_none:
|
715
|
+
if getattr(deployment_create, field) is None:
|
716
|
+
exclude.add(field)
|
683
717
|
|
684
718
|
json = deployment_create.model_dump(mode="json", exclude=exclude)
|
719
|
+
|
685
720
|
response = await self.request(
|
686
721
|
"POST",
|
687
722
|
"/deployments/",
|
@@ -253,13 +253,29 @@ class DeploymentCreate(ActionBaseModel):
|
|
253
253
|
infrastructure_document_id: Optional[UUID] = Field(default=None)
|
254
254
|
description: Optional[str] = Field(default=None)
|
255
255
|
path: Optional[str] = Field(default=None)
|
256
|
-
version: Optional[str] = Field(default=None)
|
257
256
|
entrypoint: Optional[str] = Field(default=None)
|
258
257
|
job_variables: dict[str, Any] = Field(
|
259
258
|
default_factory=dict,
|
260
259
|
description="Overrides to apply to flow run infrastructure at runtime.",
|
261
260
|
)
|
262
261
|
|
262
|
+
# Versionining
|
263
|
+
version: Optional[str] = Field(default=None)
|
264
|
+
version_info: Optional[objects.VersionInfo] = Field(
|
265
|
+
default=None, description="Version information for the deployment."
|
266
|
+
)
|
267
|
+
|
268
|
+
# Branching
|
269
|
+
branch: Optional[str] = Field(
|
270
|
+
default=None, description="The branch of the deployment."
|
271
|
+
)
|
272
|
+
base: Optional[UUID] = Field(
|
273
|
+
default=None, description="The base deployment of the deployment."
|
274
|
+
)
|
275
|
+
root: Optional[UUID] = Field(
|
276
|
+
default=None, description="The root deployment of the deployment."
|
277
|
+
)
|
278
|
+
|
263
279
|
def check_valid_configuration(self, base_job_template: dict[str, Any]) -> None:
|
264
280
|
"""Check that the combination of base_job_template defaults
|
265
281
|
and job_variables conforms to the specified schema.
|
@@ -289,6 +305,9 @@ class DeploymentUpdate(ActionBaseModel):
|
|
289
305
|
return remove_old_deployment_fields(values)
|
290
306
|
|
291
307
|
version: Optional[str] = Field(default=None)
|
308
|
+
version_info: Optional[objects.VersionInfo] = Field(
|
309
|
+
default=None, description="Version information for the deployment."
|
310
|
+
)
|
292
311
|
description: Optional[str] = Field(default=None)
|
293
312
|
parameters: Optional[dict[str, Any]] = Field(
|
294
313
|
default=None,
|
@@ -414,7 +414,7 @@ class State(ObjectBaseModel, Generic[R]):
|
|
414
414
|
database again. The 'timestamp' is reset using the default factory.
|
415
415
|
"""
|
416
416
|
update = {
|
417
|
-
"timestamp": self.model_fields["timestamp"].get_default(),
|
417
|
+
"timestamp": type(self).model_fields["timestamp"].get_default(),
|
418
418
|
**(update or {}),
|
419
419
|
}
|
420
420
|
return super().model_copy(update=update, deep=deep)
|
@@ -1102,6 +1102,11 @@ class DeploymentSchedule(ObjectBaseModel):
|
|
1102
1102
|
)
|
1103
1103
|
|
1104
1104
|
|
1105
|
+
class VersionInfo(PrefectBaseModel, extra="allow"):
|
1106
|
+
type: str = Field(default=..., description="The type of version info.")
|
1107
|
+
version: str = Field(default=..., description="The version of the deployment.")
|
1108
|
+
|
1109
|
+
|
1105
1110
|
class Deployment(ObjectBaseModel):
|
1106
1111
|
"""An ORM representation of deployment data."""
|
1107
1112
|
|
@@ -1109,6 +1114,12 @@ class Deployment(ObjectBaseModel):
|
|
1109
1114
|
version: Optional[str] = Field(
|
1110
1115
|
default=None, description="An optional version for the deployment."
|
1111
1116
|
)
|
1117
|
+
version_id: Optional[UUID] = Field(
|
1118
|
+
default=None, description="The ID of the current version of the deployment."
|
1119
|
+
)
|
1120
|
+
version_info: Optional[VersionInfo] = Field(
|
1121
|
+
default=None, description="A description of this version of the deployment."
|
1122
|
+
)
|
1112
1123
|
description: Optional[str] = Field(
|
1113
1124
|
default=None, description="A description for the deployment."
|
1114
1125
|
)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import datetime
|
2
|
-
from typing import Any, ClassVar, Generic, Optional, TypeVar, Union
|
2
|
+
from typing import TYPE_CHECKING, Any, ClassVar, Generic, Optional, TypeVar, Union
|
3
3
|
from uuid import UUID
|
4
4
|
|
5
5
|
from pydantic import ConfigDict, Field
|
@@ -12,6 +12,9 @@ from prefect.types import DateTime, KeyValueLabelsField
|
|
12
12
|
from prefect.utilities.collections import AutoEnum
|
13
13
|
from prefect.utilities.names import generate_slug
|
14
14
|
|
15
|
+
if TYPE_CHECKING:
|
16
|
+
from prefect.events.schemas.events import RelatedResource
|
17
|
+
|
15
18
|
T = TypeVar("T")
|
16
19
|
|
17
20
|
|
@@ -308,6 +311,12 @@ class DeploymentResponse(ObjectBaseModel):
|
|
308
311
|
version: Optional[str] = Field(
|
309
312
|
default=None, description="An optional version for the deployment."
|
310
313
|
)
|
314
|
+
version_id: Optional[UUID] = Field(
|
315
|
+
default=None, description="The ID of the current version of the deployment."
|
316
|
+
)
|
317
|
+
version_info: Optional[objects.VersionInfo] = Field(
|
318
|
+
default=None, description="A description of this version of the deployment."
|
319
|
+
)
|
311
320
|
description: Optional[str] = Field(
|
312
321
|
default=None, description="A description for the deployment."
|
313
322
|
)
|
@@ -420,6 +429,22 @@ class DeploymentResponse(ObjectBaseModel):
|
|
420
429
|
description="Current status of the deployment.",
|
421
430
|
)
|
422
431
|
|
432
|
+
def as_related_resource(self, role: str = "deployment") -> "RelatedResource":
|
433
|
+
from prefect.events.schemas.events import RelatedResource
|
434
|
+
|
435
|
+
labels = {
|
436
|
+
"prefect.resource.id": f"prefect.deployment.{self.id}",
|
437
|
+
"prefect.resource.role": role,
|
438
|
+
"prefect.resource.name": self.name,
|
439
|
+
}
|
440
|
+
|
441
|
+
if self.version_id and self.version_info:
|
442
|
+
labels["prefect.deployment.version-id"] = str(self.version_id)
|
443
|
+
labels["prefect.deployment.version-type"] = self.version_info.type
|
444
|
+
labels["prefect.deployment.version"] = self.version_info.version
|
445
|
+
|
446
|
+
return RelatedResource(labels)
|
447
|
+
|
423
448
|
|
424
449
|
class MinimalConcurrencyLimitResponse(PrefectBaseModel):
|
425
450
|
model_config: ClassVar[ConfigDict] = ConfigDict(extra="ignore")
|
prefect/context.py
CHANGED
@@ -6,6 +6,7 @@ These contexts should never be directly mutated by the user.
|
|
6
6
|
For more user-accessible information about the current run, see [`prefect.runtime`](../runtime/flow_run).
|
7
7
|
"""
|
8
8
|
|
9
|
+
import asyncio
|
9
10
|
import os
|
10
11
|
import sys
|
11
12
|
import warnings
|
@@ -294,7 +295,7 @@ class AsyncClientContext(ContextModel):
|
|
294
295
|
@asynccontextmanager
|
295
296
|
async def get_or_create(cls) -> AsyncGenerator[Self, None]:
|
296
297
|
ctx = cls.get()
|
297
|
-
if ctx:
|
298
|
+
if ctx and asyncio.get_running_loop() is ctx.client.loop:
|
298
299
|
yield ctx
|
299
300
|
else:
|
300
301
|
async with cls() as ctx:
|
prefect/events/filters.py
CHANGED
@@ -45,7 +45,7 @@ class EventDataFilter(PrefectBaseModel, extra="forbid"): # type: ignore[call-ar
|
|
45
45
|
def get_filters(self) -> list["EventDataFilter"]:
|
46
46
|
filters: list["EventDataFilter"] = [
|
47
47
|
filter
|
48
|
-
for filter in [getattr(self, name) for name in self.model_fields]
|
48
|
+
for filter in [getattr(self, name) for name in type(self).model_fields]
|
49
49
|
if isinstance(filter, EventDataFilter)
|
50
50
|
]
|
51
51
|
return filters
|
prefect/events/related.py
CHANGED
@@ -33,7 +33,7 @@ RESOURCE_CACHE: RelatedResourceCache = {}
|
|
33
33
|
|
34
34
|
def tags_as_related_resources(tags: Iterable[str]) -> List[RelatedResource]:
|
35
35
|
return [
|
36
|
-
RelatedResource
|
36
|
+
RelatedResource(
|
37
37
|
{
|
38
38
|
"prefect.resource.id": f"prefect.tag.{tag}",
|
39
39
|
"prefect.resource.role": "tag",
|
@@ -44,9 +44,11 @@ def tags_as_related_resources(tags: Iterable[str]) -> List[RelatedResource]:
|
|
44
44
|
|
45
45
|
|
46
46
|
def object_as_related_resource(kind: str, role: str, object: Any) -> RelatedResource:
|
47
|
-
|
47
|
+
if as_related_resource := getattr(object, "as_related_resource", None):
|
48
|
+
return as_related_resource(role=role)
|
48
49
|
|
49
|
-
|
50
|
+
resource_id = f"prefect.{kind}.{object.id}"
|
51
|
+
return RelatedResource(
|
50
52
|
{
|
51
53
|
"prefect.resource.id": resource_id,
|
52
54
|
"prefect.resource.role": role,
|
prefect/flows.py
CHANGED
@@ -272,10 +272,11 @@ class Flow(Generic[P, R]):
|
|
272
272
|
|
273
273
|
if isinstance(fn, classmethod):
|
274
274
|
fn = cast(Callable[P, R], fn.__func__)
|
275
|
+
self._isclassmethod = True
|
275
276
|
|
276
277
|
if isinstance(fn, staticmethod):
|
277
278
|
fn = cast(Callable[P, R], fn.__func__)
|
278
|
-
|
279
|
+
self._isstaticmethod = True
|
279
280
|
|
280
281
|
if not callable(fn):
|
281
282
|
raise TypeError("'fn' must be callable")
|
@@ -405,11 +406,11 @@ class Flow(Generic[P, R]):
|
|
405
406
|
|
406
407
|
@property
|
407
408
|
def isclassmethod(self) -> bool:
|
408
|
-
return
|
409
|
+
return getattr(self, "_isclassmethod", False)
|
409
410
|
|
410
411
|
@property
|
411
412
|
def isstaticmethod(self) -> bool:
|
412
|
-
return getattr(self
|
413
|
+
return getattr(self, "_isstaticmethod", False)
|
413
414
|
|
414
415
|
def __get__(self, instance: Any, owner: Any) -> "Flow[P, R]":
|
415
416
|
"""
|
@@ -417,21 +418,20 @@ class Flow(Generic[P, R]):
|
|
417
418
|
When an instance method is loaded, this method is called with the "self" instance as
|
418
419
|
an argument. We return a copy of the flow with that instance bound to the flow's function.
|
419
420
|
"""
|
420
|
-
if self.isstaticmethod:
|
421
|
-
return self
|
422
|
-
|
423
421
|
# wrapped function is a classmethod
|
424
|
-
if
|
425
|
-
|
426
|
-
setattr(
|
427
|
-
return
|
422
|
+
if self.isclassmethod:
|
423
|
+
bound_task = copy(self)
|
424
|
+
setattr(bound_task.fn, "__prefect_cls__", owner)
|
425
|
+
return bound_task
|
428
426
|
|
429
|
-
# if the
|
430
|
-
# of the
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
return
|
427
|
+
# if the task is being accessed on an instance, bind the instance to the __prefect_self__ attribute
|
428
|
+
# of the task's function. This will allow it to be automatically added to the task's parameters
|
429
|
+
if instance:
|
430
|
+
bound_task = copy(self)
|
431
|
+
bound_task.fn.__prefect_self__ = instance # type: ignore[attr-defined]
|
432
|
+
return bound_task
|
433
|
+
|
434
|
+
return self
|
435
435
|
|
436
436
|
def with_options(
|
437
437
|
self,
|
@@ -636,7 +636,8 @@ class Flow(Generic[P, R]):
|
|
636
636
|
cast_parameters = {
|
637
637
|
k: v
|
638
638
|
for k, v in dict(iter(model)).items()
|
639
|
-
if k in model.model_fields_set
|
639
|
+
if k in model.model_fields_set
|
640
|
+
or type(model).model_fields[k].default_factory
|
640
641
|
}
|
641
642
|
return cast_parameters
|
642
643
|
|
prefect/runner/runner.py
CHANGED
@@ -1158,15 +1158,7 @@ class Runner:
|
|
1158
1158
|
|
1159
1159
|
flow, deployment = await self._get_flow_and_deployment(flow_run)
|
1160
1160
|
if deployment:
|
1161
|
-
related.append(
|
1162
|
-
RelatedResource(
|
1163
|
-
{
|
1164
|
-
"prefect.resource.id": f"prefect.deployment.{deployment.id}",
|
1165
|
-
"prefect.resource.role": "deployment",
|
1166
|
-
"prefect.resource.name": deployment.name,
|
1167
|
-
}
|
1168
|
-
)
|
1169
|
-
)
|
1161
|
+
related.append(deployment.as_related_resource())
|
1170
1162
|
tags.extend(deployment.tags)
|
1171
1163
|
if flow:
|
1172
1164
|
related.append(
|
@@ -1211,15 +1203,7 @@ class Runner:
|
|
1211
1203
|
related: list[RelatedResource] = []
|
1212
1204
|
tags: list[str] = []
|
1213
1205
|
if deployment:
|
1214
|
-
related.append(
|
1215
|
-
RelatedResource(
|
1216
|
-
{
|
1217
|
-
"prefect.resource.id": f"prefect.deployment.{deployment.id}",
|
1218
|
-
"prefect.resource.role": "deployment",
|
1219
|
-
"prefect.resource.name": deployment.name,
|
1220
|
-
}
|
1221
|
-
)
|
1222
|
-
)
|
1206
|
+
related.append(deployment.as_related_resource())
|
1223
1207
|
tags.extend(deployment.tags)
|
1224
1208
|
if flow:
|
1225
1209
|
related.append(
|
prefect/schedules.py
CHANGED
@@ -47,7 +47,7 @@ class Schedule:
|
|
47
47
|
anchor_date: datetime.datetime = dataclasses.field(
|
48
48
|
default_factory=partial(datetime.datetime.now, tz=datetime.timezone.utc)
|
49
49
|
)
|
50
|
-
day_or: bool =
|
50
|
+
day_or: bool = True
|
51
51
|
active: bool = True
|
52
52
|
parameters: dict[str, Any] = dataclasses.field(default_factory=dict)
|
53
53
|
slug: str | None = None
|
@@ -73,7 +73,7 @@ def Cron(
|
|
73
73
|
cron: str,
|
74
74
|
/,
|
75
75
|
timezone: str | None = None,
|
76
|
-
day_or: bool =
|
76
|
+
day_or: bool = True,
|
77
77
|
active: bool = True,
|
78
78
|
parameters: dict[str, Any] | None = None,
|
79
79
|
slug: str | None = None,
|
prefect/server/api/flow_runs.py
CHANGED
@@ -181,12 +181,12 @@ async def update_flow_run(
|
|
181
181
|
|
182
182
|
@router.post("/count")
|
183
183
|
async def count_flow_runs(
|
184
|
-
flows: schemas.filters.FlowFilter = None,
|
185
|
-
flow_runs: schemas.filters.FlowRunFilter = None,
|
186
|
-
task_runs: schemas.filters.TaskRunFilter = None,
|
187
|
-
deployments: schemas.filters.DeploymentFilter = None,
|
188
|
-
work_pools: schemas.filters.WorkPoolFilter = None,
|
189
|
-
work_pool_queues: schemas.filters.WorkQueueFilter = None,
|
184
|
+
flows: Optional[schemas.filters.FlowFilter] = None,
|
185
|
+
flow_runs: Optional[schemas.filters.FlowRunFilter] = None,
|
186
|
+
task_runs: Optional[schemas.filters.TaskRunFilter] = None,
|
187
|
+
deployments: Optional[schemas.filters.DeploymentFilter] = None,
|
188
|
+
work_pools: Optional[schemas.filters.WorkPoolFilter] = None,
|
189
|
+
work_pool_queues: Optional[schemas.filters.WorkQueueFilter] = None,
|
190
190
|
db: PrefectDBInterface = Depends(provide_database_interface),
|
191
191
|
) -> int:
|
192
192
|
"""
|
@@ -279,12 +279,12 @@ async def flow_run_history(
|
|
279
279
|
json_schema_extra={"format": "time-delta"},
|
280
280
|
alias="history_interval_seconds",
|
281
281
|
),
|
282
|
-
flows: schemas.filters.FlowFilter = None,
|
283
|
-
flow_runs: schemas.filters.FlowRunFilter = None,
|
284
|
-
task_runs: schemas.filters.TaskRunFilter = None,
|
285
|
-
deployments: schemas.filters.DeploymentFilter = None,
|
286
|
-
work_pools: schemas.filters.WorkPoolFilter = None,
|
287
|
-
work_queues: schemas.filters.WorkQueueFilter = None,
|
282
|
+
flows: Optional[schemas.filters.FlowFilter] = None,
|
283
|
+
flow_runs: Optional[schemas.filters.FlowRunFilter] = None,
|
284
|
+
task_runs: Optional[schemas.filters.TaskRunFilter] = None,
|
285
|
+
deployments: Optional[schemas.filters.DeploymentFilter] = None,
|
286
|
+
work_pools: Optional[schemas.filters.WorkPoolFilter] = None,
|
287
|
+
work_queues: Optional[schemas.filters.WorkQueueFilter] = None,
|
288
288
|
db: PrefectDBInterface = Depends(provide_database_interface),
|
289
289
|
) -> List[schemas.responses.HistoryResponse]:
|
290
290
|
"""
|
@@ -293,6 +293,7 @@ async def flow_run_history(
|
|
293
293
|
if isinstance(history_interval, float):
|
294
294
|
history_interval = datetime.timedelta(seconds=history_interval)
|
295
295
|
|
296
|
+
assert isinstance(history_interval, datetime.timedelta)
|
296
297
|
if history_interval < datetime.timedelta(seconds=1):
|
297
298
|
raise HTTPException(
|
298
299
|
status.HTTP_422_UNPROCESSABLE_ENTITY,
|
@@ -351,8 +352,8 @@ async def read_flow_run_graph_v1(
|
|
351
352
|
@router.get("/{id:uuid}/graph-v2", tags=["Flow Run Graph"])
|
352
353
|
async def read_flow_run_graph_v2(
|
353
354
|
flow_run_id: UUID = Path(..., description="The flow run id", alias="id"),
|
354
|
-
since:
|
355
|
-
default=jsonable_encoder(
|
355
|
+
since: datetime.datetime = Query(
|
356
|
+
default=jsonable_encoder(datetime.datetime.min),
|
356
357
|
description="Only include runs that start or end after this time.",
|
357
358
|
),
|
358
359
|
db: PrefectDBInterface = Depends(provide_database_interface),
|
@@ -36,7 +36,7 @@ async def run_history(
|
|
36
36
|
deployments: Optional[schemas.filters.DeploymentFilter] = None,
|
37
37
|
work_pools: Optional[schemas.filters.WorkPoolFilter] = None,
|
38
38
|
work_queues: Optional[schemas.filters.WorkQueueFilter] = None,
|
39
|
-
) ->
|
39
|
+
) -> list[schemas.responses.HistoryResponse]:
|
40
40
|
"""
|
41
41
|
Produce a history of runs aggregated by interval and state
|
42
42
|
"""
|
@@ -1,8 +1,9 @@
|
|
1
1
|
from datetime import datetime
|
2
2
|
from typing import TYPE_CHECKING, List, Optional
|
3
|
+
from uuid import UUID
|
3
4
|
|
4
5
|
import sqlalchemy as sa
|
5
|
-
from fastapi import Depends, HTTPException, status
|
6
|
+
from fastapi import Depends, HTTPException, Path, status
|
6
7
|
from pydantic import Field, model_serializer
|
7
8
|
|
8
9
|
import prefect.server.schemas as schemas
|
@@ -173,3 +174,22 @@ async def read_task_run_counts_by_state(
|
|
173
174
|
task_run_filter=task_runs,
|
174
175
|
deployment_filter=deployments,
|
175
176
|
)
|
177
|
+
|
178
|
+
|
179
|
+
@router.get("/{id}")
|
180
|
+
async def read_task_run_with_flow_run_name(
|
181
|
+
task_run_id: UUID = Path(..., description="The task run id", alias="id"),
|
182
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
183
|
+
) -> schemas.ui.UITaskRun:
|
184
|
+
"""
|
185
|
+
Get a task run by id.
|
186
|
+
"""
|
187
|
+
async with db.session_context() as session:
|
188
|
+
task_run = await models.task_runs.read_task_run_with_flow_run_name(
|
189
|
+
session=session, task_run_id=task_run_id
|
190
|
+
)
|
191
|
+
|
192
|
+
if not task_run:
|
193
|
+
raise HTTPException(status.HTTP_404_NOT_FOUND, detail="Task not found")
|
194
|
+
|
195
|
+
return schemas.ui.UITaskRun.model_validate(task_run)
|
prefect/settings/base.py
CHANGED
@@ -101,7 +101,7 @@ class PrefectBaseSettings(BaseSettings):
|
|
101
101
|
context={"include_secrets": include_secrets},
|
102
102
|
)
|
103
103
|
env_variables: dict[str, str] = {}
|
104
|
-
for key in self.model_fields.keys():
|
104
|
+
for key in type(self).model_fields.keys():
|
105
105
|
if isinstance(child_settings := getattr(self, key), PrefectBaseSettings):
|
106
106
|
child_env = child_settings.to_environment_variables(
|
107
107
|
exclude_unset=exclude_unset,
|
@@ -110,7 +110,7 @@ class PrefectBaseSettings(BaseSettings):
|
|
110
110
|
)
|
111
111
|
env_variables.update(child_env)
|
112
112
|
elif (value := env.get(key)) is not None:
|
113
|
-
validation_alias = self.model_fields[key].validation_alias
|
113
|
+
validation_alias = type(self).model_fields[key].validation_alias
|
114
114
|
if include_aliases and validation_alias is not None:
|
115
115
|
if isinstance(validation_alias, AliasChoices):
|
116
116
|
for alias in validation_alias.choices:
|
@@ -134,9 +134,9 @@ class PrefectBaseSettings(BaseSettings):
|
|
134
134
|
def ser_model(
|
135
135
|
self, handler: SerializerFunctionWrapHandler, info: SerializationInfo
|
136
136
|
) -> Any:
|
137
|
-
jsonable_self = handler(self)
|
137
|
+
jsonable_self: dict[str, Any] = handler(self)
|
138
138
|
# iterate over fields to ensure child models that have been updated are also included
|
139
|
-
for key in self.model_fields.keys():
|
139
|
+
for key in type(self).model_fields.keys():
|
140
140
|
if info.exclude and key in info.exclude:
|
141
141
|
continue
|
142
142
|
if info.include and key not in info.include:
|
prefect/settings/models/root.py
CHANGED
@@ -276,12 +276,17 @@ class Settings(PrefectBaseSettings):
|
|
276
276
|
for r in restore_defaults or []:
|
277
277
|
path = r.accessor.split(".")
|
278
278
|
model = self
|
279
|
+
model_cls = model.__class__
|
280
|
+
model_fields = model_cls.model_fields
|
279
281
|
for key in path[:-1]:
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
282
|
+
model_field = model_fields[key]
|
283
|
+
model_cls = model_field.annotation
|
284
|
+
if model_cls is None:
|
285
|
+
raise ValueError(f"Invalid setting path: {r.accessor}")
|
286
|
+
model_fields = model_cls.model_fields
|
287
|
+
|
288
|
+
model_field = model_fields[path[-1]]
|
289
|
+
assert model_field is not None, f"Invalid setting path: {r.accessor}"
|
285
290
|
if hasattr(model_field, "default"):
|
286
291
|
default = model_field.default
|
287
292
|
elif (
|
prefect/tasks.py
CHANGED
@@ -382,10 +382,11 @@ class Task(Generic[P, R]):
|
|
382
382
|
|
383
383
|
if isinstance(fn, classmethod):
|
384
384
|
fn = cast(Callable[P, R], fn.__func__)
|
385
|
+
self._isclassmethod = True
|
385
386
|
|
386
387
|
if isinstance(fn, staticmethod):
|
387
388
|
fn = cast(Callable[P, R], fn.__func__)
|
388
|
-
|
389
|
+
self._isstaticmethod = True
|
389
390
|
|
390
391
|
if not callable(fn):
|
391
392
|
raise TypeError("'fn' must be callable")
|
@@ -547,11 +548,11 @@ class Task(Generic[P, R]):
|
|
547
548
|
|
548
549
|
@property
|
549
550
|
def isclassmethod(self) -> bool:
|
550
|
-
return
|
551
|
+
return getattr(self, "_isclassmethod", False)
|
551
552
|
|
552
553
|
@property
|
553
554
|
def isstaticmethod(self) -> bool:
|
554
|
-
return getattr(self
|
555
|
+
return getattr(self, "_isstaticmethod", False)
|
555
556
|
|
556
557
|
def __get__(self, instance: Any, owner: Any) -> "Task[P, R]":
|
557
558
|
"""
|
@@ -559,23 +560,21 @@ class Task(Generic[P, R]):
|
|
559
560
|
When an instance method is loaded, this method is called with the "self" instance as
|
560
561
|
an argument. We return a copy of the task with that instance bound to the task's function.
|
561
562
|
"""
|
562
|
-
|
563
|
-
if self.isstaticmethod:
|
564
|
-
return self
|
565
|
-
|
566
563
|
# wrapped function is a classmethod
|
567
|
-
if
|
564
|
+
if self.isclassmethod:
|
568
565
|
bound_task = copy(self)
|
569
566
|
setattr(bound_task.fn, "__prefect_cls__", owner)
|
570
567
|
return bound_task
|
571
568
|
|
572
569
|
# if the task is being accessed on an instance, bind the instance to the __prefect_self__ attribute
|
573
570
|
# of the task's function. This will allow it to be automatically added to the task's parameters
|
574
|
-
|
571
|
+
if instance:
|
575
572
|
bound_task = copy(self)
|
576
573
|
bound_task.fn.__prefect_self__ = instance # type: ignore[attr-defined]
|
577
574
|
return bound_task
|
578
575
|
|
576
|
+
return self
|
577
|
+
|
579
578
|
def with_options(
|
580
579
|
self,
|
581
580
|
*,
|
prefect/types/_datetime.py
CHANGED
@@ -130,7 +130,7 @@ def end_of_period(dt: datetime.datetime, period: str) -> datetime.datetime:
|
|
130
130
|
ValueError: If an invalid unit is specified.
|
131
131
|
"""
|
132
132
|
if sys.version_info >= (3, 13):
|
133
|
-
from whenever import Weekday, ZonedDateTime
|
133
|
+
from whenever import Weekday, ZonedDateTime, days
|
134
134
|
|
135
135
|
if not isinstance(dt.tzinfo, ZoneInfo):
|
136
136
|
zdt = ZonedDateTime.from_py_datetime(
|
@@ -150,8 +150,8 @@ def end_of_period(dt: datetime.datetime, period: str) -> datetime.datetime:
|
|
150
150
|
days_till_end_of_week: int = (
|
151
151
|
Weekday.SUNDAY.value - zdt.date().day_of_week().value
|
152
152
|
)
|
153
|
+
zdt = zdt + days(days_till_end_of_week)
|
153
154
|
zdt = zdt.replace(
|
154
|
-
day=zdt.day + days_till_end_of_week,
|
155
155
|
hour=23,
|
156
156
|
minute=59,
|
157
157
|
second=59,
|
prefect/utilities/callables.py
CHANGED
@@ -63,7 +63,7 @@ def get_call_parameters(
|
|
63
63
|
"""
|
64
64
|
if hasattr(fn, "__prefect_self__"):
|
65
65
|
call_args = (getattr(fn, "__prefect_self__"), *call_args)
|
66
|
-
|
66
|
+
elif hasattr(fn, "__prefect_cls__"):
|
67
67
|
call_args = (getattr(fn, "__prefect_cls__"), *call_args)
|
68
68
|
|
69
69
|
try:
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: prefect-client
|
3
|
-
Version: 3.3.
|
3
|
+
Version: 3.3.2
|
4
4
|
Summary: Workflow orchestration and management.
|
5
5
|
Project-URL: Changelog, https://github.com/PrefectHQ/prefect/releases
|
6
6
|
Project-URL: Documentation, https://docs.prefect.io
|
@@ -26,6 +26,7 @@ Requires-Dist: asgi-lifespan<3.0,>=1.0
|
|
26
26
|
Requires-Dist: cachetools<6.0,>=5.3
|
27
27
|
Requires-Dist: cloudpickle<4.0,>=2.0
|
28
28
|
Requires-Dist: coolname<3.0.0,>=1.0.4
|
29
|
+
Requires-Dist: dateparser<2.0.0,>=1.1.1
|
29
30
|
Requires-Dist: exceptiongroup>=1.0.0
|
30
31
|
Requires-Dist: fastapi<1.0.0,>=0.111.0
|
31
32
|
Requires-Dist: fsspec>=2022.5.0
|
@@ -1,33 +1,33 @@
|
|
1
1
|
prefect/.prefectignore,sha256=awSprvKT0vI8a64mEOLrMxhxqcO-b0ERQeYpA2rNKVQ,390
|
2
2
|
prefect/__init__.py,sha256=iCdcC5ZmeewikCdnPEP6YBAjPNV5dvfxpYCTpw30Hkw,3685
|
3
3
|
prefect/__main__.py,sha256=WFjw3kaYJY6pOTA7WDOgqjsz8zUEUZHCcj3P5wyVa-g,66
|
4
|
-
prefect/_build_info.py,sha256=
|
4
|
+
prefect/_build_info.py,sha256=473OUpqqyTyKvJsXN8EGGpANJ_OK3HinkV88WnKjNJ4,180
|
5
5
|
prefect/_result_records.py,sha256=S6QmsODkehGVSzbMm6ig022PYbI6gNKz671p_8kBYx4,7789
|
6
6
|
prefect/_waiters.py,sha256=Ia2ITaXdHzevtyWIgJoOg95lrEXQqNEOquHvw3T33UQ,9026
|
7
7
|
prefect/agent.py,sha256=dPvG1jDGD5HSH7aM2utwtk6RaJ9qg13XjkA0lAIgQmY,287
|
8
8
|
prefect/artifacts.py,sha256=dMBUOAWnUamzjb5HSqwB5-GR2Qb-Gxee26XG5NDCUuw,22720
|
9
9
|
prefect/automations.py,sha256=ZzPxn2tINdlXTQo805V4rIlbXuNWxd7cdb3gTJxZIeY,12567
|
10
10
|
prefect/cache_policies.py,sha256=Kwdei4JjitNfx42OepKpDNxwPtEwRgUUAn_soxsnNzI,12699
|
11
|
-
prefect/context.py,sha256=
|
11
|
+
prefect/context.py,sha256=LYEOlz7ZkuSDj7TmrE4mByy3N3TquFkIE2hEy0WHW1Y,23798
|
12
12
|
prefect/engine.py,sha256=uB5JN4l045i5JTlRQNT1x7MwlSiGQ5Bop2Q6jHHOgxY,3699
|
13
13
|
prefect/exceptions.py,sha256=wZLQQMRB_DyiYkeEdIC5OKwbba5A94Dlnics-lrWI7A,11581
|
14
14
|
prefect/filesystems.py,sha256=v5YqGB4uXf9Ew2VuB9VCSkawvYMMVvEtZf7w1VmAmr8,18036
|
15
15
|
prefect/flow_engine.py,sha256=hZpTYEtwTPMtwVoTCrfD93igN7rlKeG_0kyCvdU4aYE,58876
|
16
16
|
prefect/flow_runs.py,sha256=dbHcXsOq1UsNM7vyJV9gboCTylmdUwQ_-W4NQt4R4ds,17267
|
17
|
-
prefect/flows.py,sha256=
|
17
|
+
prefect/flows.py,sha256=0Es8TYUUEItxAz6G50eUmlIAXDaUTh4U0dQvgUyW2rk,109529
|
18
18
|
prefect/futures.py,sha256=ZD5rdgUHA4sfxwHaPToumOUKlyn4d989JHR7eI97-Hs,23271
|
19
19
|
prefect/main.py,sha256=8V-qLB4GjEVCkGRgGXeaIk-JIXY8Z9FozcNluj4Sm9E,2589
|
20
20
|
prefect/plugins.py,sha256=FPRLR2mWVBMuOnlzeiTD9krlHONZH2rtYLD753JQDNQ,2516
|
21
21
|
prefect/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
22
|
prefect/results.py,sha256=9mMOOZsj8ueqEch3oqxCaZPhF6D76Sn3P5TkqgVpbg8,36679
|
23
|
-
prefect/schedules.py,sha256=
|
23
|
+
prefect/schedules.py,sha256=dhq4OhImRvcmtxF7UH1m8RbwYdHT5RQsp_FrxVXfODE,7289
|
24
24
|
prefect/serializers.py,sha256=QI0oEal_BO4HQaWSjr6ReSwT55Hn4sbSOXxGgQI1-y0,9249
|
25
25
|
prefect/states.py,sha256=IOfdOJCbgz2G94VCMknX2dheP1bJ6w9rYm62SF2dGQ8,26021
|
26
26
|
prefect/task_engine.py,sha256=IIvDRl2bnnO3aKXTmtWsz0pnV8kL7xjOaUyJTlL6LaM,61491
|
27
27
|
prefect/task_runners.py,sha256=Ce_ngocfq_X-NA5zhPj13IdVmzZ5h6gXlmfxYWs2AXA,15828
|
28
28
|
prefect/task_runs.py,sha256=7LIzfo3fondCyEUpU05sYFN5IfpZigBDXrhG5yc-8t0,9039
|
29
29
|
prefect/task_worker.py,sha256=gMj_rl4EjTrnJ5YSOXinC6y-7KSK7fRQt_UYbZbrrV8,17879
|
30
|
-
prefect/tasks.py,sha256=
|
30
|
+
prefect/tasks.py,sha256=X83KIVowu-c-EDFbmh4ZurEVtEKTyUSkQ8Elo0nWy4k,74946
|
31
31
|
prefect/transactions.py,sha256=BYvxr4ZSFmYDCODPhH8DO1_51inH35oJ75ZZOd_GI_w,16341
|
32
32
|
prefect/variables.py,sha256=dCK3vX7TbkqXZhnNT_v7rcGh3ISRqoR6pJVLpoll3Js,8342
|
33
33
|
prefect/_experimental/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -43,11 +43,11 @@ prefect/_internal/pytz.py,sha256=Sy_cD-Hkmo_Yrhx2Jucy7DgTRhvO8ZD0whW1ywbSg_U,137
|
|
43
43
|
prefect/_internal/retries.py,sha256=pMHofrTQPDSxbVWclDwXbfhFKaDC6sxe1DkUOWugV6k,3040
|
44
44
|
prefect/_internal/compatibility/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
45
45
|
prefect/_internal/compatibility/async_dispatch.py,sha256=cUXOqSeseMUaje9oYUzasVPtNttyiHvrqfJl0zK66XI,2949
|
46
|
-
prefect/_internal/compatibility/deprecated.py,sha256=
|
46
|
+
prefect/_internal/compatibility/deprecated.py,sha256=YUK1IGOgZrDh6dYRez-9IYTB1eqNC19QiSKbBDl88Qs,9305
|
47
47
|
prefect/_internal/compatibility/migration.py,sha256=Z_r28B90ZQkSngXjr4I_9zA6P74_u48mtp2jYWB9zGg,6797
|
48
48
|
prefect/_internal/concurrency/__init__.py,sha256=YlTwU9ryjPNwbJa45adLJY00t_DGCh1QrdtY9WdVFfw,2140
|
49
49
|
prefect/_internal/concurrency/api.py,sha256=9MuQ0icQVTxwxChujn9mnv0WXRqwToysQy9GWC3sJRg,7352
|
50
|
-
prefect/_internal/concurrency/calls.py,sha256=
|
50
|
+
prefect/_internal/concurrency/calls.py,sha256=DkXNOpOrEM8IhFNE7E_ondwg1gcBeceLgoWPH3F2ExM,16596
|
51
51
|
prefect/_internal/concurrency/cancellation.py,sha256=stCN22-S0f_kZPk50hCEEYzH35fBel3Nthq86FrW0MU,18675
|
52
52
|
prefect/_internal/concurrency/event_loop.py,sha256=N6SyBV0vaSF5HD4_JM8zL7oBGd2nMuEKkeSPnBZdHw4,2136
|
53
53
|
prefect/_internal/concurrency/inspection.py,sha256=wUWVbHi4G-BxuuYFWhTNmo5yc1C651lQrp5OMiHPU1E,3545
|
@@ -58,10 +58,10 @@ prefect/_internal/concurrency/waiters.py,sha256=mhXpQk8swcUAxBk7f7kGn1fqy44XcFyn
|
|
58
58
|
prefect/_internal/pydantic/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
59
59
|
prefect/_internal/pydantic/schemas.py,sha256=tsRKq5yEIgiRbWMl3BPnbfNaKyDN6pq8WSs0M8SQMm4,452
|
60
60
|
prefect/_internal/pydantic/v1_schema.py,sha256=wSyQr3LUbIh0R9LsZ6ItmLnQeAS8dxVMNpIb-4aPvjM,1175
|
61
|
-
prefect/_internal/pydantic/v2_schema.py,sha256=
|
61
|
+
prefect/_internal/pydantic/v2_schema.py,sha256=n56GUlGSUeNZLpMphHliN5ksryVdE9OQHoVir2hGXoA,3224
|
62
62
|
prefect/_internal/pydantic/v2_validated_func.py,sha256=Ld8OtPFF7Ci-gHHmKhSMizBxzuIBOQ6kuIFNRh0vRVY,3731
|
63
63
|
prefect/_internal/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
64
|
-
prefect/_internal/schemas/bases.py,sha256=
|
64
|
+
prefect/_internal/schemas/bases.py,sha256=JqcZazL5Cp2hZ8Hssu8R2SVXRxHfbdRbTqmvwDYSzyk,4291
|
65
65
|
prefect/_internal/schemas/fields.py,sha256=m4LrFNz8rA9uBhMk9VyQT6FIXmV_EVAW92hdXeSvHbY,837
|
66
66
|
prefect/_internal/schemas/serializers.py,sha256=G_RGHfObjisUiRvd29p-zc6W4bwt5rE1OdR6TXNrRhQ,825
|
67
67
|
prefect/_internal/schemas/validators.py,sha256=ty9hpmfiNEWpENgeBGrgs94j192L8SpLJ0bhFHeXV_8,19733
|
@@ -69,20 +69,20 @@ prefect/_vendor/croniter/__init__.py,sha256=NUFzdbyPcTQhIOFtzmFM0nbClAvBbKh2mlnT
|
|
69
69
|
prefect/_vendor/croniter/croniter.py,sha256=eJ2HzStNAYV-vNiLOgDXl4sYWWHOsSA0dgwbkQoguhY,53009
|
70
70
|
prefect/blocks/__init__.py,sha256=D0hB72qMfgqnBB2EMZRxUxlX9yLfkab5zDChOwJZmkY,220
|
71
71
|
prefect/blocks/abstract.py,sha256=mpOAWopSR_RrzdxeurBTXVSKisP8ne-k8LYos-tp7go,17021
|
72
|
-
prefect/blocks/core.py,sha256=
|
72
|
+
prefect/blocks/core.py,sha256=Z-vC0wP-c1mQUDc-0qgBloLba5OKfJ3hJtDinJyZOH0,62045
|
73
73
|
prefect/blocks/fields.py,sha256=1m507VVmkpOnMF_7N-qboRjtw4_ceIuDneX3jZ3Jm54,63
|
74
74
|
prefect/blocks/notifications.py,sha256=UpNNxc4Bwx0nSlDj-vZQOv2XyUCUB2PaO4uBPO1Y6XM,34162
|
75
75
|
prefect/blocks/redis.py,sha256=lt_f1SIcS5OVvthCY6KRWiy5DyUZNRlHqkKhKF25P8c,5770
|
76
76
|
prefect/blocks/system.py,sha256=4KiUIy5zizMqfGJrxvi9GLRLcMj4BjAXARxCUEmgbKI,5041
|
77
77
|
prefect/blocks/webhook.py,sha256=hRpMGamOpS2HSM0iPU2ylVGnDWtWUPo6sIU3O24lIa0,2558
|
78
78
|
prefect/client/__init__.py,sha256=bDeOC_I8_la5dwCAfxKzYSTSAr2tlq5HpxJgVoCCdAs,675
|
79
|
-
prefect/client/base.py,sha256=
|
79
|
+
prefect/client/base.py,sha256=7VAMyoy8KtmtI-H8KYsI16_uw9TlrXSrcxChFuMp65Q,26269
|
80
80
|
prefect/client/cloud.py,sha256=jnFgg0osMVDGbLjdWkDX3rQg_0pI_zvfSlU480XCWGQ,6523
|
81
81
|
prefect/client/collections.py,sha256=t9XkVU_onQMZ871L21F1oZnAiPSQeeVfd_MuDEBS3iM,1050
|
82
82
|
prefect/client/constants.py,sha256=Z_GG8KF70vbbXxpJuqW5pLnwzujTVeHbcYYRikNmGH0,29
|
83
83
|
prefect/client/subscriptions.py,sha256=b2gjoWjrTjshnv_s6zlPN3t0JIe2EKAdMqEzj3-kc6w,3879
|
84
84
|
prefect/client/utilities.py,sha256=UEJD6nwYg2mD8-GSmru-E2ofXaBlmSFZ2-8T_5rIK6c,3472
|
85
|
-
prefect/client/orchestration/__init__.py,sha256=
|
85
|
+
prefect/client/orchestration/__init__.py,sha256=1GHRA9-JWPBX6oSVNytQ1qL6epFeslRT2oBgZdFDJ68,60807
|
86
86
|
prefect/client/orchestration/base.py,sha256=HM6ryHBZSzuHoCFQM9u5qR5k1dN9Bbr_ah6z1UPNbZQ,1542
|
87
87
|
prefect/client/orchestration/routes.py,sha256=JFG1OWUBfrxPKW8Q7XWItlhOrSZ67IOySSoFZ6mxzm0,4364
|
88
88
|
prefect/client/orchestration/_artifacts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -98,7 +98,7 @@ prefect/client/orchestration/_blocks_types/client.py,sha256=alA4xD-yp3mycAbzMyRu
|
|
98
98
|
prefect/client/orchestration/_concurrency_limits/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
99
99
|
prefect/client/orchestration/_concurrency_limits/client.py,sha256=r_oyY7hQbgyG1rntwe7WWcsraQHBKhk6MOPFUAHWiVc,23678
|
100
100
|
prefect/client/orchestration/_deployments/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
101
|
-
prefect/client/orchestration/_deployments/client.py,sha256=
|
101
|
+
prefect/client/orchestration/_deployments/client.py,sha256=GmKUbUB0gdFoPzp7zZVf1kQilErzhW09ivZPZ05-Zew,41548
|
102
102
|
prefect/client/orchestration/_flow_runs/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
103
103
|
prefect/client/orchestration/_flow_runs/client.py,sha256=fjh5J-LG8tsny7BGYEvynbuGuHDAudYHpx-PamL0GYQ,32220
|
104
104
|
prefect/client/orchestration/_flows/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -110,10 +110,10 @@ prefect/client/orchestration/_variables/client.py,sha256=wKBbZBLGgs5feDCil-xxKt3
|
|
110
110
|
prefect/client/orchestration/_work_pools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
111
111
|
prefect/client/orchestration/_work_pools/client.py,sha256=s1DfUQQBgB2sLiVVPhLNTlkueUDE6uFsh4mAzcSA1OE,19881
|
112
112
|
prefect/client/schemas/__init__.py,sha256=InZcDzdeWA2oaV0TlyvoMcyLcbi_aaqU1U9D6Gx-eoU,2747
|
113
|
-
prefect/client/schemas/actions.py,sha256=
|
113
|
+
prefect/client/schemas/actions.py,sha256=n8f-qNQs-mSca_zYdpZSR4A4OwnT6pylkjVc2VwFZBc,33684
|
114
114
|
prefect/client/schemas/filters.py,sha256=zaiDkalrIpKjd38V4aP1GHlqD24KTPCZiKtPyX69ZWE,36607
|
115
|
-
prefect/client/schemas/objects.py,sha256=
|
116
|
-
prefect/client/schemas/responses.py,sha256=
|
115
|
+
prefect/client/schemas/objects.py,sha256=qEV2lIdK6JGGhNsAiUDsvtPbjdIZZABqdjnA8cMsnak,58999
|
116
|
+
prefect/client/schemas/responses.py,sha256=9x8gP2O52xEf40EbnSKaKwxS1vIg347t8CqgHGMYCNg,16664
|
117
117
|
prefect/client/schemas/schedules.py,sha256=sxLFk0SmFY7X1Y9R9HyGDqOS3U5NINBWTciUU7vTTic,14836
|
118
118
|
prefect/client/schemas/sorting.py,sha256=L-2Mx-igZPtsUoRUguTcG3nIEstMEMPD97NwPM2Ox5s,2579
|
119
119
|
prefect/client/types/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -147,8 +147,8 @@ prefect/docker/docker_image.py,sha256=bR_pEq5-FDxlwTj8CP_7nwZ_MiGK6KxIi8v7DRjy1K
|
|
147
147
|
prefect/events/__init__.py,sha256=GtKl2bE--pJduTxelH2xy7SadlLJmmis8WR1EYixhuA,2094
|
148
148
|
prefect/events/actions.py,sha256=A7jS8bo4zWGnrt3QfSoQs0uYC1xfKXio3IfU0XtTb5s,9129
|
149
149
|
prefect/events/clients.py,sha256=XA33NpeRdgVglt7J47uFdpASa1bCvcKWyxsxQt3vEPQ,27290
|
150
|
-
prefect/events/filters.py,sha256=
|
151
|
-
prefect/events/related.py,sha256=
|
150
|
+
prefect/events/filters.py,sha256=2hVfzc3Rdgy0mBHDutWxT__LJY0zpVM8greWX3y6kjM,8233
|
151
|
+
prefect/events/related.py,sha256=CTeexYUmmA93V4gsR33GIFmw-SS-X_ouOpRg-oeq-BU,6672
|
152
152
|
prefect/events/utilities.py,sha256=ww34bTMENCNwcp6RhhgzG0KgXOvKGe0MKmBdSJ8NpZY,3043
|
153
153
|
prefect/events/worker.py,sha256=HjbibR0_J1W1nnNMZDFTXAbB0cl_cFGaFI87DvNGcnI,4557
|
154
154
|
prefect/events/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -182,7 +182,7 @@ prefect/logging/highlighters.py,sha256=BCf_LNhFInIfGPqwuu8YVrGa4wVxNc4YXo2pYgftp
|
|
182
182
|
prefect/logging/loggers.py,sha256=rwFJv0i3dhdKr25XX-xUkQy4Vv4dy18bTy366jrC0OQ,12741
|
183
183
|
prefect/logging/logging.yml,sha256=tT7gTyC4NmngFSqFkCdHaw7R0GPNPDDsTCGZQByiJAQ,3169
|
184
184
|
prefect/runner/__init__.py,sha256=pQBd9wVrUVUDUFJlgiweKSnbahoBZwqnd2O2jkhrULY,158
|
185
|
-
prefect/runner/runner.py,sha256=
|
185
|
+
prefect/runner/runner.py,sha256=eT0TtLjkxzTTCrJBwpPg7m_QFkCU9VaJY75BFBZKjLY,64895
|
186
186
|
prefect/runner/server.py,sha256=vyqMlUVVq6_Te1feny0G9qE8zJCYREZaF9ZstDuGvJQ,11327
|
187
187
|
prefect/runner/storage.py,sha256=L7aSjie5L6qbXYCDqYDX3ouQ_NsNMlmfjPeaWOC-ncs,28043
|
188
188
|
prefect/runner/submit.py,sha256=MtUrEKi4XznXXkDasILYYhY2w_DC2RcAL2hPJUgkgNo,8815
|
@@ -209,12 +209,12 @@ prefect/server/api/deployments.py,sha256=d-GAbVP3T0RVkkz6VN5nsQN7XU7fTjQg-vzYxuo
|
|
209
209
|
prefect/server/api/events.py,sha256=3-Qdt6ORxFv3nLoogQqvd72zEulJSoAmcqZto2OULuk,9907
|
210
210
|
prefect/server/api/flow_run_notification_policies.py,sha256=F8xNm6bgZTC3nFe9xCUJS4NlU9tLXZ8fShtJqmhT2m4,4828
|
211
211
|
prefect/server/api/flow_run_states.py,sha256=lIdxVE9CqLgtDCuH9bTaKkzHNL81FPrr11liPzvONrw,1661
|
212
|
-
prefect/server/api/flow_runs.py,sha256=
|
212
|
+
prefect/server/api/flow_runs.py,sha256=W_9S7MGrTnUnY5NJdjn13LKdRWeUcyzj8lKx0i1BfH0,33709
|
213
213
|
prefect/server/api/flows.py,sha256=Bz0ISh-9oY0W1X3mqA631_8678pQ6tuRGMpSgWAfxOc,7018
|
214
214
|
prefect/server/api/logs.py,sha256=0z78tM2B5sRgJWYRWJn5lHhRoLtZB_OU3C-uALV8tOs,1571
|
215
215
|
prefect/server/api/middleware.py,sha256=WkyuyeJIfo9Q0GAIVU5gO6yIGNVwoHwuBah5AB5oUyw,2733
|
216
216
|
prefect/server/api/root.py,sha256=CeumFYIM_BDvPicJH9ry5PO_02PZTLeMqbLMGGTh90o,942
|
217
|
-
prefect/server/api/run_history.py,sha256=
|
217
|
+
prefect/server/api/run_history.py,sha256=EW-GTPxZAQ5zXiAqHzmS-iAN_Bn6ZSgVQksDT-ZTsyc,5995
|
218
218
|
prefect/server/api/saved_searches.py,sha256=UjoqLLe245QVIs6q5Vk4vdODCOoYzciEEjhi7B8sYCE,3233
|
219
219
|
prefect/server/api/server.py,sha256=CIpLoiRUCuW345trzwr_Z8v53Kw_2RBqe3ppGvkjSx0,32940
|
220
220
|
prefect/server/api/task_run_states.py,sha256=e63OPpxPudv_CIB5oKr8Z8rfQ-Osjm9Zq0iHe8obnMo,1647
|
@@ -231,9 +231,9 @@ prefect/server/api/ui/__init__.py,sha256=TCXO4ZUZCqCbm2QoNvWNTErkzWiX2nSACuO-0Ti
|
|
231
231
|
prefect/server/api/ui/flow_runs.py,sha256=ALmUFY4WrJggN1ha0z-tqXeddG2GptswbPnB7iYixUM,4172
|
232
232
|
prefect/server/api/ui/flows.py,sha256=W4kwqOCJ_2vROmMCmemH2Mq3uWbWZyu5q5uTZPBdYwk,5902
|
233
233
|
prefect/server/api/ui/schemas.py,sha256=NVWA1RFnHW-MMU1s6WbNmp_S5mhbrN-_P41I4O2XtMg,2085
|
234
|
-
prefect/server/api/ui/task_runs.py,sha256=
|
234
|
+
prefect/server/api/ui/task_runs.py,sha256=6CMrHmY-ybJGHXz7YlVVP2ZTmvq7w-XA9GUHqCcw_7o,7319
|
235
235
|
prefect/settings/__init__.py,sha256=3jDLzExmq9HsRWo1kTSE16BO_3B3JlVsk5pR0s4PWEQ,2136
|
236
|
-
prefect/settings/base.py,sha256=
|
236
|
+
prefect/settings/base.py,sha256=HGukXOXOokfqmrVirgejNskKtf1x2QheZ-ldRakxPJA,9701
|
237
237
|
prefect/settings/constants.py,sha256=5NjVLG1Km9J9I-a6wrq-qmi_dTkPdwEk3IrY9bSxWvw,281
|
238
238
|
prefect/settings/context.py,sha256=yKxnaDJHX8e2jmAVtw1RF9o7X4V3AOcz61sVeQyPX2c,2195
|
239
239
|
prefect/settings/legacy.py,sha256=KG00GwaURl1zbwfCKAjwNRdJjB2UdTyo80gYF7U60jk,5693
|
@@ -251,7 +251,7 @@ prefect/settings/models/flows.py,sha256=kQ_sCA7TUqaEs9wWuGHkGQOuAIEZ5elD4UzeKRe0
|
|
251
251
|
prefect/settings/models/internal.py,sha256=KUb16dg3lH5gwlnUnVJub6JHFXHRyZf1voINBvC_Ysc,718
|
252
252
|
prefect/settings/models/logging.py,sha256=Sj9GDNr5QMFaP6CN0WJyfpwhpOk4p1yhv45dyQMRzHM,4729
|
253
253
|
prefect/settings/models/results.py,sha256=VWFplQSSJyc0LXnziw1H5b3N_PDS32QBe_q2MWwYni0,1484
|
254
|
-
prefect/settings/models/root.py,sha256=
|
254
|
+
prefect/settings/models/root.py,sha256=HpXt_I6T_kJw6QAxez4pCZl8p058etihzJbBNRylN3c,16767
|
255
255
|
prefect/settings/models/runner.py,sha256=rD8OmNLwILmqnGe9YkM1dWKsulx3clYm4LI5N9vD5yM,1991
|
256
256
|
prefect/settings/models/tasks.py,sha256=XA83-EmWv1FKvODSzvI1cvS3tGEbNs2qtdh0AbUdblQ,3640
|
257
257
|
prefect/settings/models/testing.py,sha256=j9YH_WkB14iEzOjUtTmvY978qRSbgCypFSEi_cOs8no,1820
|
@@ -275,7 +275,7 @@ prefect/telemetry/processors.py,sha256=jw6j6LviOVxw3IBJe7cSjsxFk0zzY43jUmy6C9pcf
|
|
275
275
|
prefect/telemetry/run_telemetry.py,sha256=_FbjiPqPemu4xvZuI2YBPwXeRJ2BcKRJ6qgO4UMzKKE,8571
|
276
276
|
prefect/telemetry/services.py,sha256=DxgNNDTeWNtHBtioX8cjua4IrCbTiJJdYecx-gugg-w,2358
|
277
277
|
prefect/types/__init__.py,sha256=yBjKxiQmSC7jXoo0UNmM3KZil1NBFS-BWGPfwSEaoJo,4621
|
278
|
-
prefect/types/_datetime.py,sha256=
|
278
|
+
prefect/types/_datetime.py,sha256=Cy6z7MxPDV_-jH2vxqC3PNA2G74IdUDIB07Jaakdj5w,7294
|
279
279
|
prefect/types/entrypoint.py,sha256=2FF03-wLPgtnqR_bKJDB2BsXXINPdu8ptY9ZYEZnXg8,328
|
280
280
|
prefect/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
281
281
|
prefect/utilities/_deprecated.py,sha256=b3pqRSoFANdVJAc8TJkygBcP-VjZtLJUxVIWC7kwspI,1303
|
@@ -283,7 +283,7 @@ prefect/utilities/_engine.py,sha256=9GW4X1lyAbmPwCuXXIubVJ7Z0DMT3dykkEUtp9tm5hI,
|
|
283
283
|
prefect/utilities/_git.py,sha256=bPYWQdr9xvH0BqxR1ll1RkaSb3x0vhwylhYD5EilkKU,863
|
284
284
|
prefect/utilities/annotations.py,sha256=0Elqgq6LR7pQqezNqT5wb6U_0e2pDO_zx6VseVL6kL8,4396
|
285
285
|
prefect/utilities/asyncutils.py,sha256=xcfeNym2j3WH4gKXznON2hI1PpUTcwr_BGc16IQS3C4,19789
|
286
|
-
prefect/utilities/callables.py,sha256=
|
286
|
+
prefect/utilities/callables.py,sha256=xK1zWWcNPkFM4a0Yq8MaMyx9p_4F74DnDYoQ8zEkzZI,25835
|
287
287
|
prefect/utilities/collections.py,sha256=c3nPLPWqIZQQdNuHs_nrbQJwuhQSX4ivUl-h9LtzXto,23243
|
288
288
|
prefect/utilities/compat.py,sha256=nnPA3lf2f4Y-l645tYFFNmj5NDPaYvjqa9pbGKZ3WKE,582
|
289
289
|
prefect/utilities/context.py,sha256=23SDMgdt07SjmB1qShiykHfGgiv55NBzdbMXM3fE9CI,1447
|
@@ -316,7 +316,7 @@ prefect/workers/cloud.py,sha256=dPvG1jDGD5HSH7aM2utwtk6RaJ9qg13XjkA0lAIgQmY,287
|
|
316
316
|
prefect/workers/process.py,sha256=uxOwcqA2Ps-V-W6WeSdKCQMINrCxBEVx1K1Un8pb7vs,8973
|
317
317
|
prefect/workers/server.py,sha256=2pmVeJZiVbEK02SO6BEZaBIvHMsn6G8LzjW8BXyiTtk,1952
|
318
318
|
prefect/workers/utilities.py,sha256=VfPfAlGtTuDj0-Kb8WlMgAuOfgXCdrGAnKMapPSBrwc,2483
|
319
|
-
prefect_client-3.3.
|
320
|
-
prefect_client-3.3.
|
321
|
-
prefect_client-3.3.
|
322
|
-
prefect_client-3.3.
|
319
|
+
prefect_client-3.3.2.dist-info/METADATA,sha256=PVg2Snt8oK_bXqIqzmErcZ6jQQs9hmsoEfBG9YbSXXs,7451
|
320
|
+
prefect_client-3.3.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
321
|
+
prefect_client-3.3.2.dist-info/licenses/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
|
322
|
+
prefect_client-3.3.2.dist-info/RECORD,,
|
File without changes
|
File without changes
|