prefect-client 3.1.2__py3-none-any.whl → 3.1.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- prefect/_internal/compatibility/async_dispatch.py +33 -43
- prefect/_version.py +3 -3
- prefect/blocks/notifications.py +1 -0
- prefect/cache_policies.py +13 -2
- prefect/client/schemas/objects.py +8 -0
- prefect/events/filters.py +13 -9
- prefect/exceptions.py +4 -0
- prefect/flow_engine.py +56 -1
- prefect/logging/handlers.py +5 -4
- prefect/settings/models/experiments.py +0 -5
- prefect/telemetry/__init__.py +1 -0
- prefect/telemetry/processors.py +2 -2
- prefect/utilities/filesystem.py +35 -8
- prefect/utilities/hashing.py +28 -7
- prefect/utilities/urls.py +2 -2
- prefect/workers/base.py +30 -20
- {prefect_client-3.1.2.dist-info → prefect_client-3.1.3.dist-info}/METADATA +3 -2
- {prefect_client-3.1.2.dist-info → prefect_client-3.1.3.dist-info}/RECORD +21 -21
- {prefect_client-3.1.2.dist-info → prefect_client-3.1.3.dist-info}/LICENSE +0 -0
- {prefect_client-3.1.2.dist-info → prefect_client-3.1.3.dist-info}/WHEEL +0 -0
- {prefect_client-3.1.2.dist-info → prefect_client-3.1.3.dist-info}/top_level.txt +0 -0
@@ -1,73 +1,63 @@
|
|
1
1
|
import asyncio
|
2
2
|
import inspect
|
3
3
|
from functools import wraps
|
4
|
-
from typing import Any, Callable, Coroutine,
|
4
|
+
from typing import Any, Callable, Coroutine, Optional, TypeVar, Union
|
5
5
|
|
6
6
|
from typing_extensions import ParamSpec
|
7
7
|
|
8
|
+
from prefect.tasks import Task
|
9
|
+
|
8
10
|
R = TypeVar("R")
|
9
11
|
P = ParamSpec("P")
|
10
12
|
|
11
13
|
|
12
|
-
class AsyncDispatchable(Protocol[P, R]):
|
13
|
-
"""Protocol for functions decorated with async_dispatch."""
|
14
|
-
|
15
|
-
def __call__(
|
16
|
-
self, *args: P.args, **kwargs: P.kwargs
|
17
|
-
) -> Union[R, Coroutine[Any, Any, R]]:
|
18
|
-
...
|
19
|
-
|
20
|
-
aio: Callable[P, Coroutine[Any, Any, R]]
|
21
|
-
sync: Callable[P, R]
|
22
|
-
|
23
|
-
|
24
14
|
def is_in_async_context() -> bool:
|
25
|
-
"""
|
15
|
+
"""
|
16
|
+
Returns True if called from within an async context (coroutine or running event loop)
|
17
|
+
"""
|
26
18
|
try:
|
27
|
-
|
28
|
-
|
29
|
-
return True
|
30
|
-
|
31
|
-
# Check if we have a loop and it's running
|
32
|
-
loop = asyncio.get_event_loop()
|
33
|
-
return loop.is_running()
|
19
|
+
asyncio.get_running_loop()
|
20
|
+
return True
|
34
21
|
except RuntimeError:
|
35
22
|
return False
|
36
23
|
|
37
24
|
|
25
|
+
def _is_acceptable_callable(obj: Union[Callable, Task]) -> bool:
|
26
|
+
if inspect.iscoroutinefunction(obj):
|
27
|
+
return True
|
28
|
+
if isinstance(obj, Task) and inspect.iscoroutinefunction(obj.fn):
|
29
|
+
return True
|
30
|
+
return False
|
31
|
+
|
32
|
+
|
38
33
|
def async_dispatch(
|
39
34
|
async_impl: Callable[P, Coroutine[Any, Any, R]],
|
40
|
-
) -> Callable[[Callable[P, R]],
|
35
|
+
) -> Callable[[Callable[P, R]], Callable[P, Union[R, Coroutine[Any, Any, R]]]]:
|
41
36
|
"""
|
42
|
-
Decorator that
|
43
|
-
|
44
|
-
The decorated function will:
|
45
|
-
- Return a coroutine when in an async context (detected via running event loop)
|
46
|
-
- Run synchronously when in a sync context
|
47
|
-
- Provide .aio for explicit async access
|
48
|
-
- Provide .sync for explicit sync access
|
37
|
+
Decorator that dispatches to either sync or async implementation based on context.
|
49
38
|
|
50
39
|
Args:
|
51
|
-
async_impl: The async implementation to dispatch to when async
|
52
|
-
is needed
|
40
|
+
async_impl: The async implementation to dispatch to when in async context
|
53
41
|
"""
|
54
|
-
if not inspect.iscoroutinefunction(async_impl):
|
55
|
-
raise TypeError(
|
56
|
-
"async_impl must be an async function to dispatch in async contexts"
|
57
|
-
)
|
58
42
|
|
59
|
-
def decorator(
|
43
|
+
def decorator(
|
44
|
+
sync_fn: Callable[P, R],
|
45
|
+
) -> Callable[P, Union[R, Coroutine[Any, Any, R]]]:
|
46
|
+
if not _is_acceptable_callable(async_impl):
|
47
|
+
raise TypeError("async_impl must be an async function")
|
48
|
+
|
60
49
|
@wraps(sync_fn)
|
61
50
|
def wrapper(
|
62
|
-
*args: P.args,
|
51
|
+
*args: P.args,
|
52
|
+
_sync: Optional[bool] = None, # type: ignore
|
53
|
+
**kwargs: P.kwargs,
|
63
54
|
) -> Union[R, Coroutine[Any, Any, R]]:
|
64
|
-
if is_in_async_context()
|
65
|
-
|
66
|
-
|
55
|
+
should_run_sync = _sync if _sync is not None else not is_in_async_context()
|
56
|
+
|
57
|
+
if should_run_sync:
|
58
|
+
return sync_fn(*args, **kwargs)
|
59
|
+
return async_impl(*args, **kwargs)
|
67
60
|
|
68
|
-
# Attach both async and sync implementations directly
|
69
|
-
wrapper.aio = async_impl
|
70
|
-
wrapper.sync = sync_fn
|
71
61
|
return wrapper # type: ignore
|
72
62
|
|
73
63
|
return decorator
|
prefect/_version.py
CHANGED
@@ -8,11 +8,11 @@ import json
|
|
8
8
|
|
9
9
|
version_json = '''
|
10
10
|
{
|
11
|
-
"date": "2024-11-
|
11
|
+
"date": "2024-11-19T15:25:34-0600",
|
12
12
|
"dirty": true,
|
13
13
|
"error": null,
|
14
|
-
"full-revisionid": "
|
15
|
-
"version": "3.1.
|
14
|
+
"full-revisionid": "39b6028cea9f2b0437546ba13cc08bb3bf6d94a4",
|
15
|
+
"version": "3.1.3"
|
16
16
|
}
|
17
17
|
''' # END VERSION_JSON
|
18
18
|
|
prefect/blocks/notifications.py
CHANGED
prefect/cache_policies.py
CHANGED
@@ -7,6 +7,7 @@ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Literal, Optional,
|
|
7
7
|
from typing_extensions import Self
|
8
8
|
|
9
9
|
from prefect.context import TaskRunContext
|
10
|
+
from prefect.exceptions import HashError
|
10
11
|
from prefect.utilities.hashing import hash_objects
|
11
12
|
|
12
13
|
if TYPE_CHECKING:
|
@@ -223,7 +224,6 @@ class TaskSource(CachePolicy):
|
|
223
224
|
lines = task_ctx.task.fn.__code__.co_code
|
224
225
|
else:
|
225
226
|
raise
|
226
|
-
|
227
227
|
return hash_objects(lines, raise_on_failure=True)
|
228
228
|
|
229
229
|
|
@@ -293,7 +293,18 @@ class Inputs(CachePolicy):
|
|
293
293
|
if key not in exclude:
|
294
294
|
hashed_inputs[key] = val
|
295
295
|
|
296
|
-
|
296
|
+
try:
|
297
|
+
return hash_objects(hashed_inputs, raise_on_failure=True)
|
298
|
+
except HashError as exc:
|
299
|
+
msg = (
|
300
|
+
f"{exc}\n\n"
|
301
|
+
"This often occurs when task inputs contain objects that cannot be cached "
|
302
|
+
"like locks, file handles, or other system resources.\n\n"
|
303
|
+
"To resolve this, you can:\n"
|
304
|
+
" 1. Exclude these arguments by defining a custom `cache_key_fn`\n"
|
305
|
+
" 2. Disable caching by passing `cache_policy=NONE`\n"
|
306
|
+
)
|
307
|
+
raise ValueError(msg) from exc
|
297
308
|
|
298
309
|
def __sub__(self, other: str) -> "CachePolicy":
|
299
310
|
if not isinstance(other, str):
|
@@ -497,6 +497,9 @@ class FlowRunPolicy(PrefectBaseModel):
|
|
497
497
|
resuming: Optional[bool] = Field(
|
498
498
|
default=False, description="Indicates if this run is resuming from a pause."
|
499
499
|
)
|
500
|
+
retry_type: Optional[Literal["in_process", "reschedule"]] = Field(
|
501
|
+
default=None, description="The type of retry this run is undergoing."
|
502
|
+
)
|
500
503
|
|
501
504
|
@model_validator(mode="before")
|
502
505
|
@classmethod
|
@@ -560,6 +563,11 @@ class FlowRun(ObjectBaseModel):
|
|
560
563
|
description="A list of tags on the flow run",
|
561
564
|
examples=[["tag-1", "tag-2"]],
|
562
565
|
)
|
566
|
+
labels: KeyValueLabels = Field(
|
567
|
+
default_factory=dict,
|
568
|
+
description="Prefect Cloud: A dictionary of key-value labels. Values can be strings, numbers, or booleans.",
|
569
|
+
examples=[{"key": "value1", "key2": 42}],
|
570
|
+
)
|
563
571
|
parent_task_run_id: Optional[UUID] = Field(
|
564
572
|
default=None,
|
565
573
|
description=(
|
prefect/events/filters.py
CHANGED
@@ -83,17 +83,18 @@ class EventOccurredFilter(EventDataFilter):
|
|
83
83
|
|
84
84
|
class EventNameFilter(EventDataFilter):
|
85
85
|
prefix: Optional[List[str]] = Field(
|
86
|
-
None, description="Only include events matching one of these prefixes"
|
86
|
+
default=None, description="Only include events matching one of these prefixes"
|
87
87
|
)
|
88
88
|
exclude_prefix: Optional[List[str]] = Field(
|
89
|
-
None, description="Exclude events matching one of these prefixes"
|
89
|
+
default=None, description="Exclude events matching one of these prefixes"
|
90
90
|
)
|
91
91
|
|
92
92
|
name: Optional[List[str]] = Field(
|
93
|
-
None,
|
93
|
+
default=None,
|
94
|
+
description="Only include events matching one of these names exactly",
|
94
95
|
)
|
95
96
|
exclude_name: Optional[List[str]] = Field(
|
96
|
-
None, description="Exclude events matching one of these names exactly"
|
97
|
+
default=None, description="Exclude events matching one of these names exactly"
|
97
98
|
)
|
98
99
|
|
99
100
|
def includes(self, event: Event) -> bool:
|
@@ -230,17 +231,20 @@ class EventFilter(EventDataFilter):
|
|
230
231
|
description="Filter criteria for when the events occurred",
|
231
232
|
)
|
232
233
|
event: Optional[EventNameFilter] = Field(
|
233
|
-
None,
|
234
|
+
default=None,
|
234
235
|
description="Filter criteria for the event name",
|
235
236
|
)
|
236
237
|
any_resource: Optional[EventAnyResourceFilter] = Field(
|
237
|
-
None,
|
238
|
+
default=None,
|
239
|
+
description="Filter criteria for any resource involved in the event",
|
238
240
|
)
|
239
241
|
resource: Optional[EventResourceFilter] = Field(
|
240
|
-
None,
|
242
|
+
default=None,
|
243
|
+
description="Filter criteria for the resource of the event",
|
241
244
|
)
|
242
245
|
related: Optional[EventRelatedFilter] = Field(
|
243
|
-
None,
|
246
|
+
default=None,
|
247
|
+
description="Filter criteria for the related resources of the event",
|
244
248
|
)
|
245
249
|
id: EventIDFilter = Field(
|
246
250
|
default_factory=lambda: EventIDFilter(id=[]),
|
@@ -248,6 +252,6 @@ class EventFilter(EventDataFilter):
|
|
248
252
|
)
|
249
253
|
|
250
254
|
order: EventOrder = Field(
|
251
|
-
EventOrder.DESC,
|
255
|
+
default=EventOrder.DESC,
|
252
256
|
description="The order to return filtered events",
|
253
257
|
)
|
prefect/exceptions.py
CHANGED
prefect/flow_engine.py
CHANGED
@@ -22,8 +22,11 @@ from typing import (
|
|
22
22
|
)
|
23
23
|
from uuid import UUID
|
24
24
|
|
25
|
+
from opentelemetry import trace
|
26
|
+
from opentelemetry.trace import Tracer, get_tracer
|
25
27
|
from typing_extensions import ParamSpec
|
26
28
|
|
29
|
+
import prefect
|
27
30
|
from prefect import Task
|
28
31
|
from prefect.client.orchestration import SyncPrefectClient, get_client
|
29
32
|
from prefect.client.schemas import FlowRun, TaskRun
|
@@ -124,6 +127,10 @@ class FlowRunEngine(Generic[P, R]):
|
|
124
127
|
_client: Optional[SyncPrefectClient] = None
|
125
128
|
short_circuit: bool = False
|
126
129
|
_flow_run_name_set: bool = False
|
130
|
+
_tracer: Tracer = field(
|
131
|
+
default_factory=lambda: get_tracer("prefect", prefect.__version__)
|
132
|
+
)
|
133
|
+
_span: Optional[trace.Span] = None
|
127
134
|
|
128
135
|
def __post_init__(self):
|
129
136
|
if self.flow is None and self.flow_run_id is None:
|
@@ -233,6 +240,17 @@ class FlowRunEngine(Generic[P, R]):
|
|
233
240
|
self.flow_run.state = state # type: ignore
|
234
241
|
self.flow_run.state_name = state.name # type: ignore
|
235
242
|
self.flow_run.state_type = state.type # type: ignore
|
243
|
+
|
244
|
+
if self._span:
|
245
|
+
self._span.add_event(
|
246
|
+
state.name,
|
247
|
+
{
|
248
|
+
"prefect.state.message": state.message or "",
|
249
|
+
"prefect.state.type": state.type,
|
250
|
+
"prefect.state.name": state.name or state.type,
|
251
|
+
"prefect.state.id": str(state.id),
|
252
|
+
},
|
253
|
+
)
|
236
254
|
return state
|
237
255
|
|
238
256
|
def result(self, raise_on_failure: bool = True) -> "Union[R, State, None]":
|
@@ -281,6 +299,9 @@ class FlowRunEngine(Generic[P, R]):
|
|
281
299
|
)
|
282
300
|
self.set_state(terminal_state)
|
283
301
|
self._return_value = resolved_result
|
302
|
+
|
303
|
+
self._end_span_on_success()
|
304
|
+
|
284
305
|
return result
|
285
306
|
|
286
307
|
def handle_exception(
|
@@ -311,6 +332,9 @@ class FlowRunEngine(Generic[P, R]):
|
|
311
332
|
)
|
312
333
|
state = self.set_state(Running())
|
313
334
|
self._raised = exc
|
335
|
+
|
336
|
+
self._end_span_on_error(exc, state.message)
|
337
|
+
|
314
338
|
return state
|
315
339
|
|
316
340
|
def handle_timeout(self, exc: TimeoutError) -> None:
|
@@ -329,6 +353,8 @@ class FlowRunEngine(Generic[P, R]):
|
|
329
353
|
self.set_state(state)
|
330
354
|
self._raised = exc
|
331
355
|
|
356
|
+
self._end_span_on_error(exc, message)
|
357
|
+
|
332
358
|
def handle_crash(self, exc: BaseException) -> None:
|
333
359
|
state = run_coro_as_sync(exception_to_crashed_state(exc))
|
334
360
|
self.logger.error(f"Crash detected! {state.message}")
|
@@ -336,6 +362,23 @@ class FlowRunEngine(Generic[P, R]):
|
|
336
362
|
self.set_state(state, force=True)
|
337
363
|
self._raised = exc
|
338
364
|
|
365
|
+
self._end_span_on_error(exc, state.message)
|
366
|
+
|
367
|
+
def _end_span_on_success(self):
|
368
|
+
if not self._span:
|
369
|
+
return
|
370
|
+
self._span.set_status(trace.Status(trace.StatusCode.OK))
|
371
|
+
self._span.end(time.time_ns())
|
372
|
+
self._span = None
|
373
|
+
|
374
|
+
def _end_span_on_error(self, exc: BaseException, description: Optional[str]):
|
375
|
+
if not self._span:
|
376
|
+
return
|
377
|
+
self._span.record_exception(exc)
|
378
|
+
self._span.set_status(trace.Status(trace.StatusCode.ERROR, description))
|
379
|
+
self._span.end(time.time_ns())
|
380
|
+
self._span = None
|
381
|
+
|
339
382
|
def load_subflow_run(
|
340
383
|
self,
|
341
384
|
parent_task_run: TaskRun,
|
@@ -578,6 +621,18 @@ class FlowRunEngine(Generic[P, R]):
|
|
578
621
|
flow_version=self.flow.version,
|
579
622
|
empirical_policy=self.flow_run.empirical_policy,
|
580
623
|
)
|
624
|
+
|
625
|
+
self._span = self._tracer.start_span(
|
626
|
+
name=self.flow_run.name,
|
627
|
+
attributes={
|
628
|
+
**self.flow_run.labels,
|
629
|
+
"prefect.run.type": "flow",
|
630
|
+
"prefect.run.id": str(self.flow_run.id),
|
631
|
+
"prefect.tags": self.flow_run.tags,
|
632
|
+
"prefect.flow.name": self.flow.name,
|
633
|
+
},
|
634
|
+
)
|
635
|
+
|
581
636
|
try:
|
582
637
|
yield self
|
583
638
|
|
@@ -632,7 +687,7 @@ class FlowRunEngine(Generic[P, R]):
|
|
632
687
|
|
633
688
|
@contextmanager
|
634
689
|
def start(self) -> Generator[None, None, None]:
|
635
|
-
with self.initialize_run():
|
690
|
+
with self.initialize_run(), trace.use_span(self._span):
|
636
691
|
self.begin_run()
|
637
692
|
|
638
693
|
if self.state.is_running():
|
prefect/logging/handlers.py
CHANGED
@@ -32,7 +32,6 @@ from prefect.settings import (
|
|
32
32
|
PREFECT_LOGGING_TO_API_BATCH_SIZE,
|
33
33
|
PREFECT_LOGGING_TO_API_MAX_LOG_SIZE,
|
34
34
|
PREFECT_LOGGING_TO_API_WHEN_MISSING_FLOW,
|
35
|
-
get_current_settings,
|
36
35
|
)
|
37
36
|
|
38
37
|
|
@@ -241,10 +240,12 @@ class APILogHandler(logging.Handler):
|
|
241
240
|
|
242
241
|
class WorkerAPILogHandler(APILogHandler):
|
243
242
|
def emit(self, record: logging.LogRecord):
|
244
|
-
|
245
|
-
|
246
|
-
|
243
|
+
# Open-source API servers do not currently support worker logs, and
|
244
|
+
# worker logs only have an associated worker ID when connected to Cloud,
|
245
|
+
# so we won't send worker logs to the API unless they have a worker ID.
|
246
|
+
if not getattr(record, "worker_id", None):
|
247
247
|
return
|
248
|
+
super().emit(record)
|
248
249
|
|
249
250
|
def prepare(self, record: logging.LogRecord) -> Dict[str, Any]:
|
250
251
|
"""
|
@@ -18,11 +18,6 @@ class ExperimentsSettings(PrefectBaseSettings):
|
|
18
18
|
),
|
19
19
|
)
|
20
20
|
|
21
|
-
worker_logging_to_api_enabled: bool = Field(
|
22
|
-
default=False,
|
23
|
-
description="Enables the logging of worker logs to Prefect Cloud.",
|
24
|
-
)
|
25
|
-
|
26
21
|
telemetry_enabled: bool = Field(
|
27
22
|
default=False,
|
28
23
|
description="Enables sending telemetry to Prefect Cloud.",
|
prefect/telemetry/__init__.py
CHANGED
@@ -0,0 +1 @@
|
|
1
|
+
|
prefect/telemetry/processors.py
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import time
|
2
2
|
from threading import Event, Lock, Thread
|
3
|
-
from typing import Optional
|
3
|
+
from typing import Dict, Optional
|
4
4
|
|
5
5
|
from opentelemetry.context import Context
|
6
6
|
from opentelemetry.sdk.trace import ReadableSpan, Span, SpanProcessor
|
@@ -10,7 +10,7 @@ from opentelemetry.sdk.trace.export import SpanExporter
|
|
10
10
|
class InFlightSpanProcessor(SpanProcessor):
|
11
11
|
def __init__(self, span_exporter: SpanExporter):
|
12
12
|
self.span_exporter = span_exporter
|
13
|
-
self._in_flight = {}
|
13
|
+
self._in_flight: Dict[int, Span] = {}
|
14
14
|
self._lock = Lock()
|
15
15
|
self._stop_event = Event()
|
16
16
|
self._export_thread = Thread(target=self._export_periodically, daemon=True)
|
prefect/utilities/filesystem.py
CHANGED
@@ -7,7 +7,7 @@ import pathlib
|
|
7
7
|
import threading
|
8
8
|
from contextlib import contextmanager
|
9
9
|
from pathlib import Path, PureWindowsPath
|
10
|
-
from typing import Optional, Union
|
10
|
+
from typing import Optional, Union, cast
|
11
11
|
|
12
12
|
import fsspec
|
13
13
|
import pathspec
|
@@ -22,8 +22,8 @@ def create_default_ignore_file(path: str) -> bool:
|
|
22
22
|
Creates default ignore file in the provided path if one does not already exist; returns boolean specifying
|
23
23
|
whether a file was created.
|
24
24
|
"""
|
25
|
-
|
26
|
-
ignore_file =
|
25
|
+
_path = pathlib.Path(path)
|
26
|
+
ignore_file = _path / ".prefectignore"
|
27
27
|
if ignore_file.exists():
|
28
28
|
return False
|
29
29
|
default_file = pathlib.Path(prefect.__module_path__) / ".prefectignore"
|
@@ -54,12 +54,34 @@ def filter_files(
|
|
54
54
|
chdir_lock = threading.Lock()
|
55
55
|
|
56
56
|
|
57
|
+
def _normalize_path(path: Union[str, Path]) -> str:
|
58
|
+
"""
|
59
|
+
Normalize a path, handling UNC paths on Windows specially.
|
60
|
+
"""
|
61
|
+
path = Path(path)
|
62
|
+
|
63
|
+
# Handle UNC paths on Windows differently
|
64
|
+
if os.name == "nt" and str(path).startswith("\\\\"):
|
65
|
+
# For UNC paths, use absolute() instead of resolve()
|
66
|
+
# to avoid the Windows path resolution issues
|
67
|
+
return str(path.absolute())
|
68
|
+
else:
|
69
|
+
try:
|
70
|
+
# For non-UNC paths, try resolve() first
|
71
|
+
return str(path.resolve())
|
72
|
+
except OSError:
|
73
|
+
# Fallback to absolute() if resolve() fails
|
74
|
+
return str(path.absolute())
|
75
|
+
|
76
|
+
|
57
77
|
@contextmanager
|
58
78
|
def tmpchdir(path: str):
|
59
79
|
"""
|
60
|
-
Change current-working directories for the duration of the context
|
80
|
+
Change current-working directories for the duration of the context,
|
81
|
+
with special handling for UNC paths on Windows.
|
61
82
|
"""
|
62
|
-
path =
|
83
|
+
path = _normalize_path(path)
|
84
|
+
|
63
85
|
if os.path.isfile(path) or (not os.path.exists(path) and not path.endswith("/")):
|
64
86
|
path = os.path.dirname(path)
|
65
87
|
|
@@ -67,7 +89,12 @@ def tmpchdir(path: str):
|
|
67
89
|
|
68
90
|
with chdir_lock:
|
69
91
|
try:
|
70
|
-
|
92
|
+
# On Windows with UNC paths, we need to handle the directory change carefully
|
93
|
+
if os.name == "nt" and path.startswith("\\\\"):
|
94
|
+
# Use os.path.abspath to handle UNC paths
|
95
|
+
os.chdir(os.path.abspath(path))
|
96
|
+
else:
|
97
|
+
os.chdir(path)
|
71
98
|
yield path
|
72
99
|
finally:
|
73
100
|
os.chdir(owd)
|
@@ -76,7 +103,7 @@ def tmpchdir(path: str):
|
|
76
103
|
def filename(path: str) -> str:
|
77
104
|
"""Extract the file name from a path with remote file system support"""
|
78
105
|
try:
|
79
|
-
of: OpenFile = fsspec.open(path)
|
106
|
+
of: OpenFile = cast(OpenFile, fsspec.open(path))
|
80
107
|
sep = of.fs.sep
|
81
108
|
except (ImportError, AttributeError):
|
82
109
|
sep = "\\" if "\\" in path else "/"
|
@@ -98,7 +125,7 @@ def is_local_path(path: Union[str, pathlib.Path, OpenFile]):
|
|
98
125
|
else:
|
99
126
|
raise TypeError(f"Invalid path of type {type(path).__name__!r}")
|
100
127
|
|
101
|
-
return
|
128
|
+
return isinstance(of.fs, LocalFileSystem)
|
102
129
|
|
103
130
|
|
104
131
|
def to_display_path(
|
prefect/utilities/hashing.py
CHANGED
@@ -6,6 +6,7 @@ from typing import Optional, Union
|
|
6
6
|
|
7
7
|
import cloudpickle
|
8
8
|
|
9
|
+
from prefect.exceptions import HashError
|
9
10
|
from prefect.serializers import JSONSerializer
|
10
11
|
|
11
12
|
if sys.version_info[:2] >= (3, 9):
|
@@ -53,19 +54,39 @@ def hash_objects(
|
|
53
54
|
) -> Optional[str]:
|
54
55
|
"""
|
55
56
|
Attempt to hash objects by dumping to JSON or serializing with cloudpickle.
|
56
|
-
|
57
|
-
|
57
|
+
|
58
|
+
Args:
|
59
|
+
*args: Positional arguments to hash
|
60
|
+
hash_algo: Hash algorithm to use
|
61
|
+
raise_on_failure: If True, raise exceptions instead of returning None
|
62
|
+
**kwargs: Keyword arguments to hash
|
63
|
+
|
64
|
+
Returns:
|
65
|
+
A hash string or None if hashing failed
|
66
|
+
|
67
|
+
Raises:
|
68
|
+
HashError: If objects cannot be hashed and raise_on_failure is True
|
58
69
|
"""
|
70
|
+
json_error = None
|
71
|
+
pickle_error = None
|
72
|
+
|
59
73
|
try:
|
60
74
|
serializer = JSONSerializer(dumps_kwargs={"sort_keys": True})
|
61
75
|
return stable_hash(serializer.dumps((args, kwargs)), hash_algo=hash_algo)
|
62
|
-
except Exception:
|
63
|
-
|
76
|
+
except Exception as e:
|
77
|
+
json_error = str(e)
|
64
78
|
|
65
79
|
try:
|
66
80
|
return stable_hash(cloudpickle.dumps((args, kwargs)), hash_algo=hash_algo)
|
67
|
-
except Exception:
|
68
|
-
|
69
|
-
|
81
|
+
except Exception as e:
|
82
|
+
pickle_error = str(e)
|
83
|
+
|
84
|
+
if raise_on_failure:
|
85
|
+
msg = (
|
86
|
+
"Unable to create hash - objects could not be serialized.\n"
|
87
|
+
f" JSON error: {json_error}\n"
|
88
|
+
f" Pickle error: {pickle_error}"
|
89
|
+
)
|
90
|
+
raise HashError(msg)
|
70
91
|
|
71
92
|
return None
|
prefect/utilities/urls.py
CHANGED
@@ -3,7 +3,7 @@ import ipaddress
|
|
3
3
|
import socket
|
4
4
|
import urllib.parse
|
5
5
|
from string import Formatter
|
6
|
-
from typing import TYPE_CHECKING, Any,
|
6
|
+
from typing import TYPE_CHECKING, Any, Literal, Optional, Union
|
7
7
|
from urllib.parse import urlparse
|
8
8
|
from uuid import UUID
|
9
9
|
|
@@ -135,7 +135,7 @@ def url_for(
|
|
135
135
|
obj_id: Optional[Union[str, UUID]] = None,
|
136
136
|
url_type: URLType = "ui",
|
137
137
|
default_base_url: Optional[str] = None,
|
138
|
-
**additional_format_kwargs:
|
138
|
+
**additional_format_kwargs: Any,
|
139
139
|
) -> Optional[str]:
|
140
140
|
"""
|
141
141
|
Returns the URL for a Prefect object.
|
prefect/workers/base.py
CHANGED
@@ -146,26 +146,26 @@ class BaseJobConfiguration(BaseModel):
|
|
146
146
|
Important: this method expects that the base_job_template was already
|
147
147
|
validated server-side.
|
148
148
|
"""
|
149
|
-
|
149
|
+
base_config: Dict[str, Any] = base_job_template["job_configuration"]
|
150
150
|
variables_schema = base_job_template["variables"]
|
151
151
|
variables = cls._get_base_config_defaults(
|
152
152
|
variables_schema.get("properties", {})
|
153
153
|
)
|
154
154
|
|
155
|
-
# copy variable defaults for `env` to
|
155
|
+
# copy variable defaults for `env` to base config before they're replaced by
|
156
156
|
# deployment overrides
|
157
157
|
if variables.get("env"):
|
158
|
-
|
158
|
+
base_config["env"] = variables.get("env")
|
159
159
|
|
160
160
|
variables.update(values)
|
161
161
|
|
162
162
|
# deep merge `env`
|
163
|
-
if isinstance(
|
164
|
-
|
163
|
+
if isinstance(base_config.get("env"), dict) and (
|
164
|
+
deployment_env := variables.get("env")
|
165
165
|
):
|
166
|
-
|
166
|
+
base_config["env"] = base_config.get("env") | deployment_env
|
167
167
|
|
168
|
-
populated_configuration = apply_values(template=
|
168
|
+
populated_configuration = apply_values(template=base_config, values=variables)
|
169
169
|
populated_configuration = await resolve_block_document_references(
|
170
170
|
template=populated_configuration, client=client
|
171
171
|
)
|
@@ -649,9 +649,14 @@ class BaseWorker(abc.ABC):
|
|
649
649
|
for scope in self._scheduled_task_scopes:
|
650
650
|
scope.cancel()
|
651
651
|
|
652
|
-
|
652
|
+
# Emit stopped event before closing client
|
653
653
|
if self._started_event:
|
654
|
-
|
654
|
+
try:
|
655
|
+
await self._emit_worker_stopped_event(self._started_event)
|
656
|
+
except Exception:
|
657
|
+
self._logger.exception("Failed to emit worker stopped event")
|
658
|
+
|
659
|
+
await self._exit_stack.__aexit__(*exc_info)
|
655
660
|
self._runs_task_group = None
|
656
661
|
self._client = None
|
657
662
|
|
@@ -816,14 +821,14 @@ class BaseWorker(abc.ABC):
|
|
816
821
|
self._logger = get_worker_logger(self)
|
817
822
|
|
818
823
|
self._logger.debug(
|
819
|
-
|
824
|
+
"Worker synchronized with the Prefect API server. "
|
825
|
+
+ (f"Remote ID: {self.backend_id}" if self.backend_id else "")
|
820
826
|
)
|
821
827
|
|
822
828
|
def _should_get_worker_id(self):
|
823
829
|
"""Determines if the worker should request an ID from the API server."""
|
824
830
|
return (
|
825
|
-
|
826
|
-
and self._client
|
831
|
+
self._client
|
827
832
|
and self._client.server_type == ServerType.CLOUD
|
828
833
|
and self.backend_id is None
|
829
834
|
)
|
@@ -881,10 +886,7 @@ class BaseWorker(abc.ABC):
|
|
881
886
|
run_logger.info(
|
882
887
|
f"Worker '{self.name}' submitting flow run '{flow_run.id}'"
|
883
888
|
)
|
884
|
-
if
|
885
|
-
get_current_settings().experiments.worker_logging_to_api_enabled
|
886
|
-
and self.backend_id
|
887
|
-
):
|
889
|
+
if self.backend_id:
|
888
890
|
try:
|
889
891
|
worker_url = url_for(
|
890
892
|
"worker",
|
@@ -971,10 +973,11 @@ class BaseWorker(abc.ABC):
|
|
971
973
|
|
972
974
|
else:
|
973
975
|
# If the run is not ready to submit, release the concurrency slot
|
974
|
-
|
975
|
-
self._limiter.release_on_behalf_of(flow_run.id)
|
976
|
+
self._release_limit_slot(flow_run.id)
|
976
977
|
|
977
978
|
self._submitting_flow_run_ids.remove(flow_run.id)
|
979
|
+
else:
|
980
|
+
self._release_limit_slot(flow_run.id)
|
978
981
|
|
979
982
|
async def _submit_run_and_capture_errors(
|
980
983
|
self, flow_run: "FlowRun", task_status: Optional[anyio.abc.TaskStatus] = None
|
@@ -1009,8 +1012,7 @@ class BaseWorker(abc.ABC):
|
|
1009
1012
|
)
|
1010
1013
|
return exc
|
1011
1014
|
finally:
|
1012
|
-
|
1013
|
-
self._limiter.release_on_behalf_of(flow_run.id)
|
1015
|
+
self._release_limit_slot(flow_run.id)
|
1014
1016
|
|
1015
1017
|
if not task_status._future.done():
|
1016
1018
|
run_logger.error(
|
@@ -1035,6 +1037,14 @@ class BaseWorker(abc.ABC):
|
|
1035
1037
|
|
1036
1038
|
return result
|
1037
1039
|
|
1040
|
+
def _release_limit_slot(self, flow_run_id: str) -> None:
|
1041
|
+
"""
|
1042
|
+
Frees up a slot taken by the given flow run id.
|
1043
|
+
"""
|
1044
|
+
if self._limiter:
|
1045
|
+
self._limiter.release_on_behalf_of(flow_run_id)
|
1046
|
+
self._logger.debug("Limit slot released for flow run '%s'", flow_run_id)
|
1047
|
+
|
1038
1048
|
def get_status(self):
|
1039
1049
|
"""
|
1040
1050
|
Retrieves the status of the current worker including its name, current worker
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: prefect-client
|
3
|
-
Version: 3.1.
|
3
|
+
Version: 3.1.3
|
4
4
|
Summary: Workflow orchestration and management.
|
5
5
|
Home-page: https://www.prefect.io
|
6
6
|
Author: Prefect Technologies, Inc.
|
@@ -29,7 +29,7 @@ Requires-Dist: asgi-lifespan<3.0,>=1.0
|
|
29
29
|
Requires-Dist: cachetools<6.0,>=5.3
|
30
30
|
Requires-Dist: cloudpickle<4.0,>=2.0
|
31
31
|
Requires-Dist: coolname<3.0.0,>=1.0.4
|
32
|
-
Requires-Dist: croniter<
|
32
|
+
Requires-Dist: croniter<6.0.0,>=1.0.12
|
33
33
|
Requires-Dist: exceptiongroup>=1.0.0
|
34
34
|
Requires-Dist: fastapi<1.0.0,>=0.111.0
|
35
35
|
Requires-Dist: fsspec>=2022.5.0
|
@@ -39,6 +39,7 @@ Requires-Dist: httpcore<2.0.0,>=1.0.5
|
|
39
39
|
Requires-Dist: httpx[http2]!=0.23.2,>=0.23
|
40
40
|
Requires-Dist: jsonpatch<2.0,>=1.32
|
41
41
|
Requires-Dist: jsonschema<5.0.0,>=4.0.0
|
42
|
+
Requires-Dist: opentelemetry-api<2.0.0,>=1.27.0
|
42
43
|
Requires-Dist: orjson<4.0,>=3.7
|
43
44
|
Requires-Dist: packaging<24.3,>=21.3
|
44
45
|
Requires-Dist: pathspec>=0.8.0
|
@@ -1,15 +1,15 @@
|
|
1
1
|
prefect/.prefectignore,sha256=awSprvKT0vI8a64mEOLrMxhxqcO-b0ERQeYpA2rNKVQ,390
|
2
2
|
prefect/__init__.py,sha256=UZPTpdap8ECK1zLoggfeOtZGkKcf6um1-lMb-nn4o5I,3450
|
3
|
-
prefect/_version.py,sha256=
|
3
|
+
prefect/_version.py,sha256=V4oVtbz7s0T9HhJbsnPlJc7W2E-m2PBHC2K7gFbgZOQ,496
|
4
4
|
prefect/agent.py,sha256=BOVVY5z-vUIQ2u8LwMTXDaNys2fjOZSS5YGDwJmTQjI,230
|
5
5
|
prefect/artifacts.py,sha256=dsxFWmdg2r9zbHM3KgKOR5YbJ29_dXUYF9kipJpbxkE,13009
|
6
6
|
prefect/automations.py,sha256=NlQ62GPJzy-gnWQqX7c6CQJKw7p60WLGDAFcy82vtg4,5613
|
7
|
-
prefect/cache_policies.py,sha256=
|
7
|
+
prefect/cache_policies.py,sha256=pG6BtQw0w3f5dxlAZ-fjpILrxcTFkZH35Pa6Z4MfDtU,9762
|
8
8
|
prefect/context.py,sha256=sNZwFecVO4-OmatU_OTNb9HoxG5rtwNIzP_NNGsmbYo,21496
|
9
9
|
prefect/engine.py,sha256=BpmDbe6miZcTl1vRkxfCPYcWSXADLigGPCagFwucMz0,1976
|
10
|
-
prefect/exceptions.py,sha256=
|
10
|
+
prefect/exceptions.py,sha256=KR8Vg7GetiBmwU5rvV5imlpg410Mv6RqSyk_gEojWAI,11884
|
11
11
|
prefect/filesystems.py,sha256=CxwMmKY8LBUed_9IqE2jUqxVCWhXa1r2fjKgLbIC2Vg,17893
|
12
|
-
prefect/flow_engine.py,sha256=
|
12
|
+
prefect/flow_engine.py,sha256=FwmdAJd2Z2RvRhEwpTrR4xky_jzdS4dhOL7Z8MQZJ8c,31873
|
13
13
|
prefect/flow_runs.py,sha256=EaXRIQTOnwnA0fO7_EjwafFRmS57K_CRy0Xsz3JDIhc,16070
|
14
14
|
prefect/flows.py,sha256=PUEPpQx5pjXMVfnrPbIeAvWUdEdeaNPO4DXj7tgxGcA,90185
|
15
15
|
prefect/futures.py,sha256=DlZvdccKtwQKuDUFrZ4zcINeO9C1chLiNOwjE5gTgCk,16356
|
@@ -32,7 +32,7 @@ prefect/_internal/integrations.py,sha256=U4cZMDbnilzZSKaMxvzZcSL27a1tzRMjDoTfr2u
|
|
32
32
|
prefect/_internal/pytz.py,sha256=WWl9x16rKFWequGmcOGs_ljpCDPf2LDHMyZp_4D8e6c,13748
|
33
33
|
prefect/_internal/retries.py,sha256=xtgj6oPSvYQLbyk451LR6swcRQvRVWEzCxY6GMK7qA4,2284
|
34
34
|
prefect/_internal/compatibility/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
35
|
-
prefect/_internal/compatibility/async_dispatch.py,sha256=
|
35
|
+
prefect/_internal/compatibility/async_dispatch.py,sha256=eTFioVEHtfPYnUxgiwJW8vBcuVA0bfOb86Rcul6i9_I,1794
|
36
36
|
prefect/_internal/compatibility/deprecated.py,sha256=PVME2C3Oe4_8tKIGufx1W4EpGkz5IQY8gFohPVOjNcM,7533
|
37
37
|
prefect/_internal/compatibility/migration.py,sha256=oifIj6mKwVUfrUO13ODLKOCwLON4YqaTXzhBFh8AK6E,6797
|
38
38
|
prefect/_internal/concurrency/__init__.py,sha256=YlTwU9ryjPNwbJa45adLJY00t_DGCh1QrdtY9WdVFfw,2140
|
@@ -61,7 +61,7 @@ prefect/blocks/__init__.py,sha256=BUfh6gIwA6HEjRyVCAiv0he3M1zfM-oY-JrlBfeWeY8,18
|
|
61
61
|
prefect/blocks/abstract.py,sha256=YLzCaf3yXv6wFCF5ZqCIHJNwH7fME1rLxC-SijARHzk,16319
|
62
62
|
prefect/blocks/core.py,sha256=l_56oggt9uJOABHus-NCXLQ4akeY4kzyDUO37ZyosX0,52783
|
63
63
|
prefect/blocks/fields.py,sha256=1m507VVmkpOnMF_7N-qboRjtw4_ceIuDneX3jZ3Jm54,63
|
64
|
-
prefect/blocks/notifications.py,sha256=
|
64
|
+
prefect/blocks/notifications.py,sha256=ufGULZCdGENKN1KYTVwVF9ZD21c_U7gE6PGKZjHOyYU,30514
|
65
65
|
prefect/blocks/redis.py,sha256=GUKYyx2QLtyNvgf5FT_dJxbgQcOzWCja3I23J1-AXhM,5629
|
66
66
|
prefect/blocks/system.py,sha256=OacB-LLXaNiLY49bPx7aAjmvdEdBxNoaOdzsCUcDr2c,4563
|
67
67
|
prefect/blocks/webhook.py,sha256=F0u1WSO17Gda8qwr9gYaA84Nfc8Qkic6HhhJMYXRzug,2496
|
@@ -76,7 +76,7 @@ prefect/client/utilities.py,sha256=89fmza0cRMOayxgXRdO51TKb11TczJ0ByOZmcZVrt44,3
|
|
76
76
|
prefect/client/schemas/__init__.py,sha256=KlyqFV-hMulMkNstBn_0ijoHoIwJZaBj6B1r07UmgvE,607
|
77
77
|
prefect/client/schemas/actions.py,sha256=m2HJr9oAoK9vqigCHSwMGwvKPTjGNEtP0xdXgforIT0,28629
|
78
78
|
prefect/client/schemas/filters.py,sha256=ynzD3mdvHHkI51pJ_NWgeDv8Awr7-2QtpUq7fTInEYM,36316
|
79
|
-
prefect/client/schemas/objects.py,sha256=
|
79
|
+
prefect/client/schemas/objects.py,sha256=8RTtKzWOdFq8hROB77DPLCVwuKP5Jyc9gB-fOF6Qwwc,57147
|
80
80
|
prefect/client/schemas/responses.py,sha256=tV06W8npA8oCjV9d0ZNvjro4QcbHxayb8PC4LmanXjo,15467
|
81
81
|
prefect/client/schemas/schedules.py,sha256=8rpqjOYtknu2-1n5_WD4cOplgu93P3mCyX86B22LfL4,13070
|
82
82
|
prefect/client/schemas/sorting.py,sha256=L-2Mx-igZPtsUoRUguTcG3nIEstMEMPD97NwPM2Ox5s,2579
|
@@ -109,7 +109,7 @@ prefect/docker/docker_image.py,sha256=Y84_ooCYA9NGl6FElJul9-FaW3teT-eia2SiNtZ1LG
|
|
109
109
|
prefect/events/__init__.py,sha256=GtKl2bE--pJduTxelH2xy7SadlLJmmis8WR1EYixhuA,2094
|
110
110
|
prefect/events/actions.py,sha256=A7jS8bo4zWGnrt3QfSoQs0uYC1xfKXio3IfU0XtTb5s,9129
|
111
111
|
prefect/events/clients.py,sha256=fCR64VROlbMfVY5WL7Dy_1UroBKYrKNltll2sIiD8Ek,23028
|
112
|
-
prefect/events/filters.py,sha256=
|
112
|
+
prefect/events/filters.py,sha256=IaJ39jGpkTocJOyrrBmnXEJEYeYZyB600Ri2apw6cxI,8294
|
113
113
|
prefect/events/related.py,sha256=TQPYIPJI_vZlZgZgq3YpsGCmFleiZCMDtn_jMrYBJRg,6537
|
114
114
|
prefect/events/utilities.py,sha256=ajIAiNFTN5Bz57IEq-o-i1BJdUi7P2oYH_6GyQjCKs8,2635
|
115
115
|
prefect/events/worker.py,sha256=VEz5xgJ9KuPFNH_H08YJ2_v2lYM5ASE-Nx2Yd9DqfZ8,4126
|
@@ -138,7 +138,7 @@ prefect/logging/__init__.py,sha256=zx9f5_dWrR4DbcTOFBpNGOPoCZ1QcPFudr7zxb2XRpA,1
|
|
138
138
|
prefect/logging/configuration.py,sha256=5kOYdd4Hi6t-wJhxEncYS9bUAMEMTRKy_i22pepjDrw,3343
|
139
139
|
prefect/logging/filters.py,sha256=9keHLN4-cpnsWcii1qU0RITNi9-m7pOhkJ_t0MtCM4k,1117
|
140
140
|
prefect/logging/formatters.py,sha256=3nBWgawvD48slT0zgkKeus1gIyf0OjmDKdLwMEe5mPU,3923
|
141
|
-
prefect/logging/handlers.py,sha256=
|
141
|
+
prefect/logging/handlers.py,sha256=ywaVcQmC8-v_B9l7Cand6kvjeFgPhfDTiqbHpQKt1vE,11943
|
142
142
|
prefect/logging/highlighters.py,sha256=pH6TZmMaMdAkMLJB-U9NPWZIj3GUfczYCSFzCbBCq2s,1776
|
143
143
|
prefect/logging/loggers.py,sha256=BKYjyP8N2aJPdHwpqNU5Od4uu0pKztsDQ7RPRNb4oGo,12146
|
144
144
|
prefect/logging/logging.yml,sha256=-HoWPYLsKMt5bKRgjIqk8S7tQlAaQ93pGkwIkYtMVMo,3172
|
@@ -173,7 +173,7 @@ prefect/settings/models/cli.py,sha256=mHB-BHBVO9qfQcr9uHbBmU6MMDLlLUUDxjyaRz7v1l
|
|
173
173
|
prefect/settings/models/client.py,sha256=Ua18wKXWrNi0Ktb6cd42kdSOQYhFnObwTHTc3QDYg2k,2985
|
174
174
|
prefect/settings/models/cloud.py,sha256=7-WtW0rGPMOuG1O9Lwv_H_keEldXPo9YGHmoGwCXpeg,1767
|
175
175
|
prefect/settings/models/deployments.py,sha256=ui4xqT7N-6B_gMnGnkJ8Ys0hzdfNTOtlcwzAQo2LlQI,1235
|
176
|
-
prefect/settings/models/experiments.py,sha256=
|
176
|
+
prefect/settings/models/experiments.py,sha256=toCpajFA9d2rosqshdlQBayOnyJff9zyrpRCEKAF7Bo,707
|
177
177
|
prefect/settings/models/flows.py,sha256=IrW3cFQJnu-31cXvSihCl6naRhmZc2eFqSgqdnNLUzg,1056
|
178
178
|
prefect/settings/models/internal.py,sha256=mJ7h3d_WHw-0FBVhIbDHPjYI041YtuReD1bZO98G1OU,612
|
179
179
|
prefect/settings/models/logging.py,sha256=YxD8fOcWOROUrq6dH6EIadJwYL7LlLSUGWlHVLn-l3Y,4560
|
@@ -194,11 +194,11 @@ prefect/settings/models/server/root.py,sha256=uhryCvrk6oGAu8S3GGZNc3IaxXyd_dFnsK
|
|
194
194
|
prefect/settings/models/server/services.py,sha256=xDQyRUh18mU_cTgp1Q_BwKpdeZHKLSh2o_YNNXvzsoo,16748
|
195
195
|
prefect/settings/models/server/tasks.py,sha256=YzfRTcmiYnD_INezR_29rvO0M_YbAqT1by7kiK2KP60,2814
|
196
196
|
prefect/settings/models/server/ui.py,sha256=6cTSC2RQsS4c2HpB1Se6qRms4RMEKSsaI40T2CTkobg,1780
|
197
|
-
prefect/telemetry/__init__.py,sha256=
|
197
|
+
prefect/telemetry/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
198
198
|
prefect/telemetry/bootstrap.py,sha256=oOdEjIHDQHANviyP2ZKpz9B4yBq832f9y1PKwAQ5-ro,987
|
199
199
|
prefect/telemetry/instrumentation.py,sha256=S7IRYqKXaixAt-W5oxDO4CqkyXc3dy4ATgBmuindJIM,4241
|
200
200
|
prefect/telemetry/logging.py,sha256=yn5D4D2GGRrAv0y8wlHPN7PZDmQucGjQT_YauK9M9Yo,727
|
201
|
-
prefect/telemetry/processors.py,sha256=
|
201
|
+
prefect/telemetry/processors.py,sha256=IEWBD8c_O3lx54TbIsBOF8kneIMcT27bcwh3O0VY7HI,2029
|
202
202
|
prefect/types/__init__.py,sha256=oabzKSvuT7tKBX6OiBev40wUtN1JstJT2L7ocpEUZ14,3640
|
203
203
|
prefect/types/entrypoint.py,sha256=2FF03-wLPgtnqR_bKJDB2BsXXINPdu8ptY9ZYEZnXg8,328
|
204
204
|
prefect/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -211,8 +211,8 @@ prefect/utilities/context.py,sha256=BThuUW94-IYgFYTeMIM9KMo8ShT3oiI7w5ajZHzU1j0,
|
|
211
211
|
prefect/utilities/dispatch.py,sha256=EthEmyRwv-4W8z2BJclrsOQHJ_pJoZYL0t2cyYPEa-E,6098
|
212
212
|
prefect/utilities/dockerutils.py,sha256=zjqeyE4gK8r0n5l3b2XK2AKviQ2F-pOd1LE2O4qfJt0,20372
|
213
213
|
prefect/utilities/engine.py,sha256=pi-TQEpoJ98u2LNYh3ZpNoiN9VSlGRJV558Hjg2eFxY,32433
|
214
|
-
prefect/utilities/filesystem.py,sha256=
|
215
|
-
prefect/utilities/hashing.py,sha256=
|
214
|
+
prefect/utilities/filesystem.py,sha256=FH5SRDeLei5_nouYmYkr44GdCJy7p9rIV-VyhW71ziE,5420
|
215
|
+
prefect/utilities/hashing.py,sha256=IrcILlSvLz1hFtOFtIelPtkcyZ7qnaARYlrGFv3eVxs,2485
|
216
216
|
prefect/utilities/importtools.py,sha256=aO-xhf2h2KzsLGvSKwRAZLB4ITeW9rsV0Ys-gwq3i7o,19426
|
217
217
|
prefect/utilities/math.py,sha256=wLwcKVidpNeWQi1TUIWWLHGjlz9UgboX9FUGhx_CQzo,2821
|
218
218
|
prefect/utilities/names.py,sha256=x-stHcF7_tebJPvB1dz-5FvdXJXNBTg2kFZXSnIBBmk,1657
|
@@ -224,20 +224,20 @@ prefect/utilities/slugify.py,sha256=57Vb14t13F3zm1P65KAu8nVeAz0iJCd1Qc5eMG-R5y8,
|
|
224
224
|
prefect/utilities/templating.py,sha256=nAiOGMMHGbIDFkGYy-g-dzcbY311WfycdgAhsM3cLpY,13298
|
225
225
|
prefect/utilities/text.py,sha256=JRs6WNUn07i5oRP_jyTUYD6I0hdVwyMI0JmJc8f9gFw,731
|
226
226
|
prefect/utilities/timeout.py,sha256=BRDIOWnqcw3B7X9tIk83Y3n9nQrJzZgduDQ63z-ns8w,1286
|
227
|
-
prefect/utilities/urls.py,sha256=
|
227
|
+
prefect/utilities/urls.py,sha256=NQqtifJRoewrXXjYmxC7YAkaMb1nE00evwjxO40Gmoc,8892
|
228
228
|
prefect/utilities/visualization.py,sha256=Lum4IvLQ0nHsdLt6GGzS3Wwo-828u1rmOKc5mmWu994,6502
|
229
229
|
prefect/utilities/schema_tools/__init__.py,sha256=KsFsTEHQqgp89TkDpjggkgBBywoHQPxbx-m6YQhiNEI,322
|
230
230
|
prefect/utilities/schema_tools/hydration.py,sha256=k12qVCdLLrK-mNo1hPCdhxM5f_N14Nj0vJdtiWYWffk,8858
|
231
231
|
prefect/utilities/schema_tools/validation.py,sha256=2GCjxwApTFwzey40ul9OkcAXrU3r-kWK__9ucMo0qbk,9744
|
232
232
|
prefect/workers/__init__.py,sha256=8dP8SLZbWYyC_l9DRTQSE3dEbDgns5DZDhxkp_NfsbQ,35
|
233
|
-
prefect/workers/base.py,sha256=
|
233
|
+
prefect/workers/base.py,sha256=7Gb19vDG1cFsyrfsvZIR1h-OvX5T3RFrSS0Vj7uO5JU,49209
|
234
234
|
prefect/workers/block.py,sha256=BOVVY5z-vUIQ2u8LwMTXDaNys2fjOZSS5YGDwJmTQjI,230
|
235
235
|
prefect/workers/cloud.py,sha256=BOVVY5z-vUIQ2u8LwMTXDaNys2fjOZSS5YGDwJmTQjI,230
|
236
236
|
prefect/workers/process.py,sha256=tcJ3fbiraLCfpVGpv8dOHwMSfVzeD_kyguUOvPuIz6I,19796
|
237
237
|
prefect/workers/server.py,sha256=lgh2FfSuaNU7b6HPxSFm8JtKvAvHsZGkiOo4y4tW1Cw,2022
|
238
238
|
prefect/workers/utilities.py,sha256=VfPfAlGtTuDj0-Kb8WlMgAuOfgXCdrGAnKMapPSBrwc,2483
|
239
|
-
prefect_client-3.1.
|
240
|
-
prefect_client-3.1.
|
241
|
-
prefect_client-3.1.
|
242
|
-
prefect_client-3.1.
|
243
|
-
prefect_client-3.1.
|
239
|
+
prefect_client-3.1.3.dist-info/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
|
240
|
+
prefect_client-3.1.3.dist-info/METADATA,sha256=PdG3F-fwco9gK2XcOTh-Os4oyp_5HzQSR5tx_BMPXiM,7386
|
241
|
+
prefect_client-3.1.3.dist-info/WHEEL,sha256=bFJAMchF8aTQGUgMZzHJyDDMPTO3ToJ7x23SLJa1SVo,92
|
242
|
+
prefect_client-3.1.3.dist-info/top_level.txt,sha256=MJZYJgFdbRc2woQCeB4vM6T33tr01TmkEhRcns6H_H4,8
|
243
|
+
prefect_client-3.1.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|