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
prefect/utilities/collections.py
CHANGED
@@ -253,8 +253,7 @@ def visit_collection(
|
|
253
253
|
context: dict[str, VT] = ...,
|
254
254
|
remove_annotations: bool = ...,
|
255
255
|
_seen: Optional[set[int]] = ...,
|
256
|
-
) -> Any:
|
257
|
-
...
|
256
|
+
) -> Any: ...
|
258
257
|
|
259
258
|
|
260
259
|
@overload
|
@@ -267,8 +266,7 @@ def visit_collection(
|
|
267
266
|
context: None = None,
|
268
267
|
remove_annotations: bool = ...,
|
269
268
|
_seen: Optional[set[int]] = ...,
|
270
|
-
) -> Any:
|
271
|
-
...
|
269
|
+
) -> Any: ...
|
272
270
|
|
273
271
|
|
274
272
|
@overload
|
@@ -281,8 +279,7 @@ def visit_collection(
|
|
281
279
|
context: dict[str, VT] = ...,
|
282
280
|
remove_annotations: bool = ...,
|
283
281
|
_seen: Optional[set[int]] = ...,
|
284
|
-
) -> Optional[Any]:
|
285
|
-
...
|
282
|
+
) -> Optional[Any]: ...
|
286
283
|
|
287
284
|
|
288
285
|
@overload
|
@@ -295,8 +292,7 @@ def visit_collection(
|
|
295
292
|
context: None = None,
|
296
293
|
remove_annotations: bool = ...,
|
297
294
|
_seen: Optional[set[int]] = ...,
|
298
|
-
) -> Optional[Any]:
|
299
|
-
...
|
295
|
+
) -> Optional[Any]: ...
|
300
296
|
|
301
297
|
|
302
298
|
@overload
|
@@ -309,8 +305,7 @@ def visit_collection(
|
|
309
305
|
context: dict[str, VT] = ...,
|
310
306
|
remove_annotations: bool = ...,
|
311
307
|
_seen: Optional[set[int]] = ...,
|
312
|
-
) -> None:
|
313
|
-
...
|
308
|
+
) -> None: ...
|
314
309
|
|
315
310
|
|
316
311
|
def visit_collection(
|
@@ -545,13 +540,11 @@ def visit_collection(
|
|
545
540
|
@overload
|
546
541
|
def remove_nested_keys(
|
547
542
|
keys_to_remove: list[HashableT], obj: NestedDict[HashableT, VT]
|
548
|
-
) -> NestedDict[HashableT, VT]:
|
549
|
-
...
|
543
|
+
) -> NestedDict[HashableT, VT]: ...
|
550
544
|
|
551
545
|
|
552
546
|
@overload
|
553
|
-
def remove_nested_keys(keys_to_remove: list[HashableT], obj: Any) -> Any:
|
554
|
-
...
|
547
|
+
def remove_nested_keys(keys_to_remove: list[HashableT], obj: Any) -> Any: ...
|
555
548
|
|
556
549
|
|
557
550
|
def remove_nested_keys(
|
@@ -579,13 +572,13 @@ def remove_nested_keys(
|
|
579
572
|
|
580
573
|
|
581
574
|
@overload
|
582
|
-
def distinct(
|
583
|
-
|
575
|
+
def distinct(
|
576
|
+
iterable: Iterable[HashableT], key: None = None
|
577
|
+
) -> Iterator[HashableT]: ...
|
584
578
|
|
585
579
|
|
586
580
|
@overload
|
587
|
-
def distinct(iterable: Iterable[T], key: Callable[[T], Hashable]) -> Iterator[T]:
|
588
|
-
...
|
581
|
+
def distinct(iterable: Iterable[T], key: Callable[[T], Hashable]) -> Iterator[T]: ...
|
589
582
|
|
590
583
|
|
591
584
|
def distinct(
|
@@ -609,15 +602,13 @@ def distinct(
|
|
609
602
|
@overload
|
610
603
|
def get_from_dict(
|
611
604
|
dct: NestedDict[str, VT], keys: Union[str, list[str]], default: None = None
|
612
|
-
) -> Optional[VT]:
|
613
|
-
...
|
605
|
+
) -> Optional[VT]: ...
|
614
606
|
|
615
607
|
|
616
608
|
@overload
|
617
609
|
def get_from_dict(
|
618
610
|
dct: NestedDict[str, VT], keys: Union[str, list[str]], default: R
|
619
|
-
) -> Union[VT, R]:
|
620
|
-
...
|
611
|
+
) -> Union[VT, R]: ...
|
621
612
|
|
622
613
|
|
623
614
|
def get_from_dict(
|
prefect/utilities/dispatch.py
CHANGED
@@ -45,15 +45,13 @@ def get_registry_for_type(cls: T) -> Optional[dict[str, T]]:
|
|
45
45
|
@overload
|
46
46
|
def get_dispatch_key(
|
47
47
|
cls_or_instance: Any, allow_missing: Literal[False] = False
|
48
|
-
) -> str:
|
49
|
-
...
|
48
|
+
) -> str: ...
|
50
49
|
|
51
50
|
|
52
51
|
@overload
|
53
52
|
def get_dispatch_key(
|
54
53
|
cls_or_instance: Any, allow_missing: Literal[True] = ...
|
55
|
-
) -> Optional[str]:
|
56
|
-
...
|
54
|
+
) -> Optional[str]: ...
|
57
55
|
|
58
56
|
|
59
57
|
def get_dispatch_key(
|
prefect/utilities/dockerutils.py
CHANGED
@@ -331,7 +331,7 @@ class ImageBuilder:
|
|
331
331
|
def assert_has_line(self, line: str) -> None:
|
332
332
|
"""Asserts that the given line is in the Dockerfile"""
|
333
333
|
all_lines = "\n".join(
|
334
|
-
[f" {i+1:>3}: {line}" for i, line in enumerate(self.dockerfile_lines)]
|
334
|
+
[f" {i + 1:>3}: {line}" for i, line in enumerate(self.dockerfile_lines)]
|
335
335
|
)
|
336
336
|
message = (
|
337
337
|
f"Expected {line!r} not found in Dockerfile. Dockerfile:\n{all_lines}"
|
@@ -347,12 +347,12 @@ class ImageBuilder:
|
|
347
347
|
|
348
348
|
surrounding_lines = "\n".join(
|
349
349
|
[
|
350
|
-
f" {i+1:>3}: {line}"
|
350
|
+
f" {i + 1:>3}: {line}"
|
351
351
|
for i, line in enumerate(self.dockerfile_lines[i - 2 : i + 2])
|
352
352
|
]
|
353
353
|
)
|
354
354
|
message = (
|
355
|
-
f"Unexpected {line!r} found in Dockerfile at line {i+1}. "
|
355
|
+
f"Unexpected {line!r} found in Dockerfile at line {i + 1}. "
|
356
356
|
f"Surrounding lines:\n{surrounding_lines}"
|
357
357
|
)
|
358
358
|
|
@@ -368,7 +368,7 @@ class ImageBuilder:
|
|
368
368
|
|
369
369
|
surrounding_lines = "\n".join(
|
370
370
|
[
|
371
|
-
f" {i+1:>3}: {line}"
|
371
|
+
f" {i + 1:>3}: {line}"
|
372
372
|
for i, line in enumerate(
|
373
373
|
self.dockerfile_lines[second_index - 2 : first_index + 2]
|
374
374
|
)
|
@@ -377,8 +377,8 @@ class ImageBuilder:
|
|
377
377
|
|
378
378
|
message = (
|
379
379
|
f"Expected {first!r} to appear before {second!r} in the Dockerfile, but "
|
380
|
-
f"{first!r} was at line {first_index+1} and {second!r} as at line "
|
381
|
-
f"{second_index+1}. Surrounding lines:\n{surrounding_lines}"
|
380
|
+
f"{first!r} was at line {first_index + 1} and {second!r} as at line "
|
381
|
+
f"{second_index + 1}. Surrounding lines:\n{surrounding_lines}"
|
382
382
|
)
|
383
383
|
|
384
384
|
assert first_index < second_index, message
|
prefect/utilities/importtools.py
CHANGED
@@ -2,25 +2,19 @@ import ast
|
|
2
2
|
import importlib
|
3
3
|
import importlib.util
|
4
4
|
import os
|
5
|
-
import runpy
|
6
5
|
import sys
|
7
6
|
import threading
|
8
7
|
import warnings
|
9
8
|
from collections.abc import Iterable, Sequence
|
10
9
|
from importlib.abc import Loader, MetaPathFinder
|
11
10
|
from importlib.machinery import ModuleSpec
|
12
|
-
from io import TextIOWrapper
|
13
11
|
from logging import Logger
|
14
12
|
from pathlib import Path
|
15
|
-
from tempfile import NamedTemporaryFile
|
16
13
|
from types import ModuleType
|
17
|
-
from typing import TYPE_CHECKING, Any, Callable, NamedTuple, Optional
|
18
|
-
|
19
|
-
import fsspec # type: ignore # no typing stubs available
|
14
|
+
from typing import TYPE_CHECKING, Any, Callable, NamedTuple, Optional
|
20
15
|
|
21
16
|
from prefect.exceptions import ScriptError
|
22
17
|
from prefect.logging.loggers import get_logger
|
23
|
-
from prefect.utilities.filesystem import filename, is_local_path, tmpchdir
|
24
18
|
|
25
19
|
logger: Logger = get_logger(__name__)
|
26
20
|
|
@@ -84,67 +78,6 @@ def from_qualified_name(name: str) -> Any:
|
|
84
78
|
return getattr(module, attr_name)
|
85
79
|
|
86
80
|
|
87
|
-
def objects_from_script(
|
88
|
-
path: str, text: Optional[Union[str, bytes]] = None
|
89
|
-
) -> dict[str, Any]:
|
90
|
-
"""
|
91
|
-
Run a python script and return all the global variables
|
92
|
-
|
93
|
-
Supports remote paths by copying to a local temporary file.
|
94
|
-
|
95
|
-
WARNING: The Python documentation does not recommend using runpy for this pattern.
|
96
|
-
|
97
|
-
> Furthermore, any functions and classes defined by the executed code are not
|
98
|
-
> guaranteed to work correctly after a runpy function has returned. If that
|
99
|
-
> limitation is not acceptable for a given use case, importlib is likely to be a
|
100
|
-
> more suitable choice than this module.
|
101
|
-
|
102
|
-
The function `load_script_as_module` uses importlib instead and should be used
|
103
|
-
instead for loading objects from scripts.
|
104
|
-
|
105
|
-
Args:
|
106
|
-
path: The path to the script to run
|
107
|
-
text: Optionally, the text of the script. Skips loading the contents if given.
|
108
|
-
|
109
|
-
Returns:
|
110
|
-
A dictionary mapping variable name to value
|
111
|
-
|
112
|
-
Raises:
|
113
|
-
ScriptError: if the script raises an exception during execution
|
114
|
-
"""
|
115
|
-
|
116
|
-
def run_script(run_path: str) -> dict[str, Any]:
|
117
|
-
# Cast to an absolute path before changing directories to ensure relative paths
|
118
|
-
# are not broken
|
119
|
-
abs_run_path = os.path.abspath(run_path)
|
120
|
-
with tmpchdir(run_path):
|
121
|
-
try:
|
122
|
-
return runpy.run_path(abs_run_path)
|
123
|
-
except Exception as exc:
|
124
|
-
raise ScriptError(user_exc=exc, path=path) from exc
|
125
|
-
|
126
|
-
if text:
|
127
|
-
with NamedTemporaryFile(
|
128
|
-
mode="wt" if isinstance(text, str) else "wb",
|
129
|
-
prefix=f"run-{filename(path)}",
|
130
|
-
suffix=".py",
|
131
|
-
) as tmpfile:
|
132
|
-
tmpfile.write(text)
|
133
|
-
tmpfile.flush()
|
134
|
-
return run_script(tmpfile.name)
|
135
|
-
|
136
|
-
else:
|
137
|
-
if not is_local_path(path):
|
138
|
-
# Remote paths need to be local to run
|
139
|
-
with fsspec.open(path) as f: # type: ignore # no typing stubs available
|
140
|
-
if TYPE_CHECKING:
|
141
|
-
assert isinstance(f, TextIOWrapper)
|
142
|
-
contents = f.read()
|
143
|
-
return objects_from_script(path, contents)
|
144
|
-
else:
|
145
|
-
return run_script(path)
|
146
|
-
|
147
|
-
|
148
81
|
def load_script_as_module(path: str) -> ModuleType:
|
149
82
|
"""Execute a script at the given path.
|
150
83
|
|
prefect/utilities/names.py
CHANGED
@@ -68,5 +68,5 @@ def obfuscate_string(s: str, show_tail: bool = False) -> str:
|
|
68
68
|
# take up to 4 characters, but only after the 10th character
|
69
69
|
suffix = s[10:][-4:]
|
70
70
|
if suffix and show_tail:
|
71
|
-
result = f"{result[
|
71
|
+
result = f"{result[: -len(suffix)]}{suffix}"
|
72
72
|
return result
|
@@ -256,8 +256,7 @@ async def run_process(
|
|
256
256
|
task_status: anyio.abc.TaskStatus[T] = ...,
|
257
257
|
task_status_handler: Callable[[anyio.abc.Process], T] = ...,
|
258
258
|
**kwargs: Any,
|
259
|
-
) -> anyio.abc.Process:
|
260
|
-
...
|
259
|
+
) -> anyio.abc.Process: ...
|
261
260
|
|
262
261
|
|
263
262
|
@overload
|
@@ -270,8 +269,7 @@ async def run_process(
|
|
270
269
|
task_status: Optional[anyio.abc.TaskStatus[int]] = ...,
|
271
270
|
task_status_handler: None = None,
|
272
271
|
**kwargs: Any,
|
273
|
-
) -> anyio.abc.Process:
|
274
|
-
...
|
272
|
+
) -> anyio.abc.Process: ...
|
275
273
|
|
276
274
|
|
277
275
|
@overload
|
@@ -284,8 +282,7 @@ async def run_process(
|
|
284
282
|
task_status: Optional[anyio.abc.TaskStatus[T]] = None,
|
285
283
|
task_status_handler: Optional[Callable[[anyio.abc.Process], T]] = None,
|
286
284
|
**kwargs: Any,
|
287
|
-
) -> anyio.abc.Process:
|
288
|
-
...
|
285
|
+
) -> anyio.abc.Process: ...
|
289
286
|
|
290
287
|
|
291
288
|
async def run_process(
|
prefect/utilities/pydantic.py
CHANGED
@@ -52,15 +52,13 @@ def _unreduce_model(model_name: str, json: str) -> Any:
|
|
52
52
|
|
53
53
|
|
54
54
|
@overload
|
55
|
-
def add_cloudpickle_reduction(__model_cls: type[M]) -> type[M]:
|
56
|
-
...
|
55
|
+
def add_cloudpickle_reduction(__model_cls: type[M]) -> type[M]: ...
|
57
56
|
|
58
57
|
|
59
58
|
@overload
|
60
59
|
def add_cloudpickle_reduction(
|
61
60
|
__model_cls: None = None, **kwargs: Any
|
62
|
-
) -> Callable[[type[M]], type[M]]:
|
63
|
-
...
|
61
|
+
) -> Callable[[type[M]], type[M]]: ...
|
64
62
|
|
65
63
|
|
66
64
|
def add_cloudpickle_reduction(
|
@@ -144,7 +142,7 @@ def add_type_dispatch(model_cls: type[M]) -> type[M]:
|
|
144
142
|
|
145
143
|
elif not defines_dispatch_key and defines_type_field:
|
146
144
|
field_type_annotation = model_cls.model_fields["type"].annotation
|
147
|
-
if field_type_annotation
|
145
|
+
if field_type_annotation is not str and field_type_annotation is not None:
|
148
146
|
raise TypeError(
|
149
147
|
f"Model class {model_cls.__name__!r} defines a 'type' field with "
|
150
148
|
f"type {field_type_annotation.__name__!r} but it must be 'str'."
|
@@ -169,7 +167,7 @@ def add_type_dispatch(model_cls: type[M]) -> type[M]:
|
|
169
167
|
def __init__(__pydantic_self__: M, **data: Any) -> None:
|
170
168
|
type_string = (
|
171
169
|
get_dispatch_key(__pydantic_self__)
|
172
|
-
if type(__pydantic_self__)
|
170
|
+
if type(__pydantic_self__) is not model_cls
|
173
171
|
else "__base__"
|
174
172
|
)
|
175
173
|
data.setdefault("type", type_string)
|
@@ -63,7 +63,7 @@ def swagger_lib(config: MkDocsConfig) -> dict[str, Any]:
|
|
63
63
|
}
|
64
64
|
|
65
65
|
extra_javascript = config.extra_javascript
|
66
|
-
extra_css = cast(list[str], config.extra_css)
|
66
|
+
extra_css = cast(list[str], config.extra_css) # pyright: ignore[reportUnknownMemberType] incomplete type hint
|
67
67
|
for lib in extra_javascript:
|
68
68
|
if (
|
69
69
|
os.path.basename(urllib.parse.urlparse(str(lib)).path)
|
@@ -8,11 +8,6 @@ from pydantic import BaseModel, Field
|
|
8
8
|
from sqlalchemy.ext.asyncio import AsyncSession
|
9
9
|
from typing_extensions import Self, TypeAlias, TypeIs
|
10
10
|
|
11
|
-
from prefect.server.utilities.user_templates import (
|
12
|
-
TemplateSecurityError,
|
13
|
-
render_user_template_sync,
|
14
|
-
validate_user_template,
|
15
|
-
)
|
16
11
|
from prefect.types import StrictVariableValue
|
17
12
|
|
18
13
|
|
@@ -229,6 +224,12 @@ def json_handler(obj: dict[str, Any], ctx: HydrationContext):
|
|
229
224
|
|
230
225
|
@handler("jinja")
|
231
226
|
def jinja_handler(obj: dict[str, Any], ctx: HydrationContext) -> Any:
|
227
|
+
from prefect.server.utilities.user_templates import (
|
228
|
+
TemplateSecurityError,
|
229
|
+
render_user_template_sync,
|
230
|
+
validate_user_template,
|
231
|
+
)
|
232
|
+
|
232
233
|
if "template" in obj:
|
233
234
|
if isinstance(obj["template"], dict):
|
234
235
|
dehydrated_jinja = _hydrate(obj["template"], ctx)
|
prefect/utilities/templating.py
CHANGED
@@ -4,6 +4,7 @@ import re
|
|
4
4
|
from typing import (
|
5
5
|
TYPE_CHECKING,
|
6
6
|
Any,
|
7
|
+
Callable,
|
7
8
|
Literal,
|
8
9
|
NamedTuple,
|
9
10
|
Optional,
|
@@ -92,15 +93,19 @@ def find_placeholders(template: T) -> set[Placeholder]:
|
|
92
93
|
@overload
|
93
94
|
def apply_values(
|
94
95
|
template: T, values: dict[str, Any], remove_notset: Literal[True] = True
|
95
|
-
) -> T:
|
96
|
-
...
|
96
|
+
) -> T: ...
|
97
97
|
|
98
98
|
|
99
99
|
@overload
|
100
100
|
def apply_values(
|
101
101
|
template: T, values: dict[str, Any], remove_notset: Literal[False] = False
|
102
|
-
) -> Union[T, type[NotSet]]:
|
103
|
-
|
102
|
+
) -> Union[T, type[NotSet]]: ...
|
103
|
+
|
104
|
+
|
105
|
+
@overload
|
106
|
+
def apply_values(
|
107
|
+
template: T, values: dict[str, Any], remove_notset: bool = False
|
108
|
+
) -> Union[T, type[NotSet]]: ...
|
104
109
|
|
105
110
|
|
106
111
|
def apply_values(
|
@@ -190,11 +195,13 @@ def apply_values(
|
|
190
195
|
|
191
196
|
@inject_client
|
192
197
|
async def resolve_block_document_references(
|
193
|
-
template: T,
|
198
|
+
template: T,
|
199
|
+
client: Optional["PrefectClient"] = None,
|
200
|
+
value_transformer: Optional[Callable[[str, Any], Any]] = None,
|
194
201
|
) -> Union[T, dict[str, Any]]:
|
195
202
|
"""
|
196
203
|
Resolve block document references in a template by replacing each reference with
|
197
|
-
the
|
204
|
+
its value or the return value of the transformer function if provided.
|
198
205
|
|
199
206
|
Recursively searches for block document references in dictionaries and lists.
|
200
207
|
|
@@ -251,6 +258,7 @@ async def resolve_block_document_references(
|
|
251
258
|
|
252
259
|
Args:
|
253
260
|
template: The template to resolve block documents in
|
261
|
+
value_transformer: A function that takes the block placeholder and the block value and returns replacement text for the template
|
254
262
|
|
255
263
|
Returns:
|
256
264
|
The template with block documents resolved
|
@@ -268,13 +276,15 @@ async def resolve_block_document_references(
|
|
268
276
|
updated_template: dict[str, Any] = {}
|
269
277
|
for key, value in template.items():
|
270
278
|
updated_value = await resolve_block_document_references(
|
271
|
-
value, client=client
|
279
|
+
value, value_transformer=value_transformer, client=client
|
272
280
|
)
|
273
281
|
updated_template[key] = updated_value
|
274
282
|
return updated_template
|
275
283
|
elif isinstance(template, list):
|
276
284
|
return [
|
277
|
-
await resolve_block_document_references(
|
285
|
+
await resolve_block_document_references(
|
286
|
+
item, value_transformer=value_transformer, client=client
|
287
|
+
)
|
278
288
|
for item in template
|
279
289
|
]
|
280
290
|
elif isinstance(template, str):
|
@@ -319,6 +329,9 @@ async def resolve_block_document_references(
|
|
319
329
|
)
|
320
330
|
value = from_dict
|
321
331
|
|
332
|
+
if value_transformer:
|
333
|
+
value = value_transformer(placeholder.full_match, value)
|
334
|
+
|
322
335
|
return value
|
323
336
|
else:
|
324
337
|
raise ValueError(
|
@@ -42,8 +42,7 @@ def track_viz_task(
|
|
42
42
|
task_name: str,
|
43
43
|
parameters: dict[str, Any],
|
44
44
|
viz_return_value: Optional[Any] = None,
|
45
|
-
) -> Coroutine[Any, Any, Any]:
|
46
|
-
...
|
45
|
+
) -> Coroutine[Any, Any, Any]: ...
|
47
46
|
|
48
47
|
|
49
48
|
@overload
|
@@ -52,8 +51,7 @@ def track_viz_task(
|
|
52
51
|
task_name: str,
|
53
52
|
parameters: dict[str, Any],
|
54
53
|
viz_return_value: Optional[Any] = None,
|
55
|
-
) -> Any:
|
56
|
-
...
|
54
|
+
) -> Any: ...
|
57
55
|
|
58
56
|
|
59
57
|
def track_viz_task(
|
prefect/workers/base.py
CHANGED
@@ -939,9 +939,9 @@ class BaseWorker(abc.ABC, Generic[C, V, R]):
|
|
939
939
|
was created from a deployment with a storage block.
|
940
940
|
"""
|
941
941
|
if flow_run.deployment_id:
|
942
|
-
assert (
|
943
|
-
|
944
|
-
)
|
942
|
+
assert self._client and self._client._started, (
|
943
|
+
"Client must be started to check flow run deployment."
|
944
|
+
)
|
945
945
|
deployment = await self._client.read_deployment(flow_run.deployment_id)
|
946
946
|
if deployment.storage_document_id:
|
947
947
|
raise ValueError(
|
prefect/workers/block.py
CHANGED
prefect/workers/cloud.py
CHANGED
prefect/workers/process.py
CHANGED