prefect-client 3.1.9__py3-none-any.whl → 3.1.10__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/_version.py +3 -3
- prefect/artifacts.py +61 -74
- prefect/automations.py +27 -7
- prefect/context.py +16 -27
- prefect/flows.py +2 -1
- prefect/futures.py +42 -27
- prefect/locking/filesystem.py +8 -7
- prefect/locking/memory.py +5 -3
- prefect/locking/protocol.py +1 -1
- prefect/plugins.py +12 -10
- prefect/results.py +1 -1
- prefect/telemetry/processors.py +6 -6
- prefect/telemetry/services.py +32 -31
- prefect/workers/__init__.py +2 -0
- {prefect_client-3.1.9.dist-info → prefect_client-3.1.10.dist-info}/METADATA +1 -1
- {prefect_client-3.1.9.dist-info → prefect_client-3.1.10.dist-info}/RECORD +19 -19
- {prefect_client-3.1.9.dist-info → prefect_client-3.1.10.dist-info}/LICENSE +0 -0
- {prefect_client-3.1.9.dist-info → prefect_client-3.1.10.dist-info}/WHEEL +0 -0
- {prefect_client-3.1.9.dist-info → prefect_client-3.1.10.dist-info}/top_level.txt +0 -0
prefect/_version.py
CHANGED
@@ -8,11 +8,11 @@ import json
|
|
8
8
|
|
9
9
|
version_json = '''
|
10
10
|
{
|
11
|
-
"date": "2024-12-
|
11
|
+
"date": "2024-12-24T22:58:40-0800",
|
12
12
|
"dirty": true,
|
13
13
|
"error": null,
|
14
|
-
"full-revisionid": "
|
15
|
-
"version": "3.1.
|
14
|
+
"full-revisionid": "b11b56fc6143df2bd4c7018f7a974dc656fe9aa3",
|
15
|
+
"version": "3.1.10"
|
16
16
|
}
|
17
17
|
''' # END VERSION_JSON
|
18
18
|
|
prefect/artifacts.py
CHANGED
@@ -2,19 +2,20 @@
|
|
2
2
|
Interface for creating and reading artifacts.
|
3
3
|
"""
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
import asyncio
|
7
6
|
import json # noqa: I001
|
8
7
|
import math
|
9
8
|
import warnings
|
10
|
-
from typing import TYPE_CHECKING, Any,
|
9
|
+
from typing import TYPE_CHECKING, Any, Optional, Union
|
11
10
|
from uuid import UUID
|
12
11
|
|
12
|
+
from typing_extensions import Self
|
13
|
+
|
13
14
|
from prefect.client.schemas.actions import ArtifactCreate as ArtifactRequest
|
14
15
|
from prefect.client.schemas.actions import ArtifactUpdate
|
15
16
|
from prefect.client.schemas.filters import ArtifactFilter, ArtifactFilterKey
|
16
17
|
from prefect.client.schemas.sorting import ArtifactSort
|
17
|
-
from prefect.client.utilities import get_or_create_client
|
18
|
+
from prefect.client.utilities import get_or_create_client
|
18
19
|
from prefect.logging.loggers import get_logger
|
19
20
|
from prefect.utilities.asyncutils import sync_compatible
|
20
21
|
from prefect.utilities.context import get_task_and_flow_run_ids
|
@@ -22,8 +23,6 @@ from prefect.utilities.context import get_task_and_flow_run_ids
|
|
22
23
|
logger = get_logger("artifacts")
|
23
24
|
|
24
25
|
if TYPE_CHECKING:
|
25
|
-
from typing_extensions import Self
|
26
|
-
|
27
26
|
from prefect.client.orchestration import PrefectClient
|
28
27
|
from prefect.client.schemas.objects import Artifact as ArtifactResponse
|
29
28
|
|
@@ -43,7 +42,7 @@ class Artifact(ArtifactRequest):
|
|
43
42
|
|
44
43
|
@sync_compatible
|
45
44
|
async def create(
|
46
|
-
self:
|
45
|
+
self: Self,
|
47
46
|
client: Optional["PrefectClient"] = None,
|
48
47
|
) -> "ArtifactResponse":
|
49
48
|
"""
|
@@ -95,16 +94,15 @@ class Artifact(ArtifactRequest):
|
|
95
94
|
(ArtifactResponse, optional): The artifact (if found).
|
96
95
|
"""
|
97
96
|
client, _ = get_or_create_client(client)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
)
|
97
|
+
filter_key_value = None if key is None else [key]
|
98
|
+
artifacts = await client.read_artifacts(
|
99
|
+
limit=1,
|
100
|
+
sort=ArtifactSort.UPDATED_DESC,
|
101
|
+
artifact_filter=ArtifactFilter(
|
102
|
+
key=ArtifactFilterKey(any_=filter_key_value)
|
105
103
|
),
|
106
|
-
None,
|
107
104
|
)
|
105
|
+
return None if not artifacts else artifacts[0]
|
108
106
|
|
109
107
|
@classmethod
|
110
108
|
@sync_compatible
|
@@ -112,10 +110,10 @@ class Artifact(ArtifactRequest):
|
|
112
110
|
cls,
|
113
111
|
key: Optional[str] = None,
|
114
112
|
description: Optional[str] = None,
|
115
|
-
data: Optional[Union[
|
113
|
+
data: Optional[Union[dict[str, Any], Any]] = None,
|
116
114
|
client: Optional["PrefectClient"] = None,
|
117
115
|
**kwargs: Any,
|
118
|
-
) ->
|
116
|
+
) -> tuple["ArtifactResponse", bool]:
|
119
117
|
"""
|
120
118
|
A method to get or create an artifact.
|
121
119
|
|
@@ -128,18 +126,20 @@ class Artifact(ArtifactRequest):
|
|
128
126
|
Returns:
|
129
127
|
(ArtifactResponse): The artifact, either retrieved or created.
|
130
128
|
"""
|
131
|
-
|
129
|
+
artifact_coro = cls.get(key, client)
|
130
|
+
if TYPE_CHECKING:
|
131
|
+
assert asyncio.iscoroutine(artifact_coro)
|
132
|
+
artifact = await artifact_coro
|
132
133
|
if artifact:
|
133
134
|
return artifact, False
|
134
|
-
else:
|
135
|
-
return (
|
136
|
-
await cls(key=key, description=description, data=data, **kwargs).create(
|
137
|
-
client
|
138
|
-
),
|
139
|
-
True,
|
140
|
-
)
|
141
135
|
|
142
|
-
|
136
|
+
new_artifact = cls(key=key, description=description, data=data, **kwargs)
|
137
|
+
create_coro = new_artifact.create(client)
|
138
|
+
if TYPE_CHECKING:
|
139
|
+
assert asyncio.iscoroutine(create_coro)
|
140
|
+
return await create_coro, True
|
141
|
+
|
142
|
+
async def format(self) -> Optional[Union[dict[str, Any], Any]]:
|
143
143
|
return json.dumps(self.data)
|
144
144
|
|
145
145
|
|
@@ -165,13 +165,13 @@ class MarkdownArtifact(Artifact):
|
|
165
165
|
|
166
166
|
|
167
167
|
class TableArtifact(Artifact):
|
168
|
-
table: Union[
|
168
|
+
table: Union[dict[str, list[Any]], list[dict[str, Any]], list[list[Any]]]
|
169
169
|
type: Optional[str] = "table"
|
170
170
|
|
171
171
|
@classmethod
|
172
172
|
def _sanitize(
|
173
|
-
cls, item: Union[
|
174
|
-
) -> Union[
|
173
|
+
cls, item: Union[dict[str, Any], list[Any], float]
|
174
|
+
) -> Union[dict[str, Any], list[Any], int, float, None]:
|
175
175
|
"""
|
176
176
|
Sanitize NaN values in a given item.
|
177
177
|
The item can be a dict, list or float.
|
@@ -230,39 +230,6 @@ class ImageArtifact(Artifact):
|
|
230
230
|
return self.image_url
|
231
231
|
|
232
232
|
|
233
|
-
@inject_client
|
234
|
-
async def _create_artifact(
|
235
|
-
type: str,
|
236
|
-
key: Optional[str] = None,
|
237
|
-
description: Optional[str] = None,
|
238
|
-
data: Optional[Union[Dict[str, Any], Any]] = None,
|
239
|
-
client: Optional["PrefectClient"] = None,
|
240
|
-
) -> UUID:
|
241
|
-
"""
|
242
|
-
Helper function to create an artifact.
|
243
|
-
|
244
|
-
Arguments:
|
245
|
-
type: A string identifying the type of artifact.
|
246
|
-
key: A user-provided string identifier.
|
247
|
-
The key must only contain lowercase letters, numbers, and dashes.
|
248
|
-
description: A user-specified description of the artifact.
|
249
|
-
data: A JSON payload that allows for a result to be retrieved.
|
250
|
-
client: The PrefectClient
|
251
|
-
|
252
|
-
Returns:
|
253
|
-
- The table artifact ID.
|
254
|
-
"""
|
255
|
-
|
256
|
-
artifact = await Artifact(
|
257
|
-
type=type,
|
258
|
-
key=key,
|
259
|
-
description=description,
|
260
|
-
data=data,
|
261
|
-
).create(client)
|
262
|
-
|
263
|
-
return artifact.id
|
264
|
-
|
265
|
-
|
266
233
|
@sync_compatible
|
267
234
|
async def create_link_artifact(
|
268
235
|
link: str,
|
@@ -286,12 +253,16 @@ async def create_link_artifact(
|
|
286
253
|
Returns:
|
287
254
|
The table artifact ID.
|
288
255
|
"""
|
289
|
-
|
256
|
+
new_artifact = LinkArtifact(
|
290
257
|
key=key,
|
291
258
|
description=description,
|
292
259
|
link=link,
|
293
260
|
link_text=link_text,
|
294
|
-
)
|
261
|
+
)
|
262
|
+
create_coro = new_artifact.create(client)
|
263
|
+
if TYPE_CHECKING:
|
264
|
+
assert asyncio.iscoroutine(create_coro)
|
265
|
+
artifact = await create_coro
|
295
266
|
|
296
267
|
return artifact.id
|
297
268
|
|
@@ -315,18 +286,22 @@ async def create_markdown_artifact(
|
|
315
286
|
Returns:
|
316
287
|
The table artifact ID.
|
317
288
|
"""
|
318
|
-
|
289
|
+
new_artifact = MarkdownArtifact(
|
319
290
|
key=key,
|
320
291
|
description=description,
|
321
292
|
markdown=markdown,
|
322
|
-
)
|
293
|
+
)
|
294
|
+
create_coro = new_artifact.create()
|
295
|
+
if TYPE_CHECKING:
|
296
|
+
assert asyncio.iscoroutine(create_coro)
|
297
|
+
artifact = await create_coro
|
323
298
|
|
324
299
|
return artifact.id
|
325
300
|
|
326
301
|
|
327
302
|
@sync_compatible
|
328
303
|
async def create_table_artifact(
|
329
|
-
table: Union[
|
304
|
+
table: Union[dict[str, list[Any]], list[dict[str, Any]], list[list[Any]]],
|
330
305
|
key: Optional[str] = None,
|
331
306
|
description: Optional[str] = None,
|
332
307
|
) -> UUID:
|
@@ -344,11 +319,15 @@ async def create_table_artifact(
|
|
344
319
|
The table artifact ID.
|
345
320
|
"""
|
346
321
|
|
347
|
-
|
322
|
+
new_artifact = TableArtifact(
|
348
323
|
key=key,
|
349
324
|
description=description,
|
350
325
|
table=table,
|
351
|
-
)
|
326
|
+
)
|
327
|
+
create_coro = new_artifact.create()
|
328
|
+
if TYPE_CHECKING:
|
329
|
+
assert asyncio.iscoroutine(create_coro)
|
330
|
+
artifact = await create_coro
|
352
331
|
|
353
332
|
return artifact.id
|
354
333
|
|
@@ -373,11 +352,15 @@ async def create_progress_artifact(
|
|
373
352
|
The progress artifact ID.
|
374
353
|
"""
|
375
354
|
|
376
|
-
|
355
|
+
new_artifact = ProgressArtifact(
|
377
356
|
key=key,
|
378
357
|
description=description,
|
379
358
|
progress=progress,
|
380
|
-
)
|
359
|
+
)
|
360
|
+
create_coro = new_artifact.create()
|
361
|
+
if TYPE_CHECKING:
|
362
|
+
assert asyncio.iscoroutine(create_coro)
|
363
|
+
artifact = await create_coro
|
381
364
|
|
382
365
|
return artifact.id
|
383
366
|
|
@@ -387,7 +370,7 @@ async def update_progress_artifact(
|
|
387
370
|
artifact_id: UUID,
|
388
371
|
progress: float,
|
389
372
|
description: Optional[str] = None,
|
390
|
-
client: Optional[PrefectClient] = None,
|
373
|
+
client: Optional["PrefectClient"] = None,
|
391
374
|
) -> UUID:
|
392
375
|
"""
|
393
376
|
Update a progress artifact.
|
@@ -444,10 +427,14 @@ async def create_image_artifact(
|
|
444
427
|
The image artifact ID.
|
445
428
|
"""
|
446
429
|
|
447
|
-
|
430
|
+
new_artifact = ImageArtifact(
|
448
431
|
key=key,
|
449
432
|
description=description,
|
450
433
|
image_url=image_url,
|
451
|
-
)
|
434
|
+
)
|
435
|
+
create_coro = new_artifact.create()
|
436
|
+
if TYPE_CHECKING:
|
437
|
+
assert asyncio.iscoroutine(create_coro)
|
438
|
+
artifact = await create_coro
|
452
439
|
|
453
440
|
return artifact.id
|
prefect/automations.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from typing import Optional,
|
1
|
+
from typing import TYPE_CHECKING, Optional, overload
|
2
2
|
from uuid import UUID
|
3
3
|
|
4
4
|
from pydantic import Field
|
@@ -112,17 +112,28 @@ class Automation(AutomationCore):
|
|
112
112
|
auto.name = "new name"
|
113
113
|
auto.update()
|
114
114
|
"""
|
115
|
+
assert self.id is not None
|
115
116
|
async with get_client() as client:
|
116
117
|
automation = AutomationCore(
|
117
118
|
**self.model_dump(exclude={"id", "owner_resource"})
|
118
119
|
)
|
119
120
|
await client.update_automation(automation_id=self.id, automation=automation)
|
120
121
|
|
122
|
+
@overload
|
123
|
+
@classmethod
|
124
|
+
async def read(cls, id: UUID, name: Optional[str] = ...) -> Self:
|
125
|
+
...
|
126
|
+
|
127
|
+
@overload
|
128
|
+
@classmethod
|
129
|
+
async def read(cls, id: None = None, name: str = ...) -> Optional[Self]:
|
130
|
+
...
|
131
|
+
|
121
132
|
@classmethod
|
122
133
|
@sync_compatible
|
123
134
|
async def read(
|
124
|
-
cls
|
125
|
-
) -> Self:
|
135
|
+
cls, id: Optional[UUID] = None, name: Optional[str] = None
|
136
|
+
) -> Optional[Self]:
|
126
137
|
"""
|
127
138
|
Read an automation by ID or name.
|
128
139
|
automation = Automation.read(name="woodchonk")
|
@@ -145,13 +156,13 @@ class Automation(AutomationCore):
|
|
145
156
|
raise
|
146
157
|
if automation is None:
|
147
158
|
raise ValueError(f"Automation with ID {id!r} not found")
|
148
|
-
return
|
159
|
+
return cls(**automation.model_dump())
|
149
160
|
else:
|
161
|
+
if TYPE_CHECKING:
|
162
|
+
assert name is not None
|
150
163
|
automation = await client.read_automations_by_name(name=name)
|
151
164
|
if len(automation) > 0:
|
152
|
-
return (
|
153
|
-
Automation(**automation[0].model_dump()) if automation else None
|
154
|
-
)
|
165
|
+
return cls(**automation[0].model_dump()) if automation else None
|
155
166
|
else:
|
156
167
|
raise ValueError(f"Automation with name {name!r} not found")
|
157
168
|
|
@@ -161,6 +172,9 @@ class Automation(AutomationCore):
|
|
161
172
|
auto = Automation.read(id = 123)
|
162
173
|
auto.delete()
|
163
174
|
"""
|
175
|
+
if self.id is None:
|
176
|
+
raise ValueError("Can't delete an automation without an id")
|
177
|
+
|
164
178
|
async with get_client() as client:
|
165
179
|
try:
|
166
180
|
await client.delete_automation(self.id)
|
@@ -177,6 +191,9 @@ class Automation(AutomationCore):
|
|
177
191
|
auto = Automation.read(id = 123)
|
178
192
|
auto.disable()
|
179
193
|
"""
|
194
|
+
if self.id is None:
|
195
|
+
raise ValueError("Can't disable an automation without an id")
|
196
|
+
|
180
197
|
async with get_client() as client:
|
181
198
|
try:
|
182
199
|
await client.pause_automation(self.id)
|
@@ -193,6 +210,9 @@ class Automation(AutomationCore):
|
|
193
210
|
auto = Automation.read(id = 123)
|
194
211
|
auto.enable()
|
195
212
|
"""
|
213
|
+
if self.id is None:
|
214
|
+
raise ValueError("Can't enable an automation without an id")
|
215
|
+
|
196
216
|
async with get_client() as client:
|
197
217
|
try:
|
198
218
|
await client.resume_automation(self.id)
|
prefect/context.py
CHANGED
@@ -9,21 +9,10 @@ For more user-accessible information about the current run, see [`prefect.runtim
|
|
9
9
|
import os
|
10
10
|
import sys
|
11
11
|
import warnings
|
12
|
+
from collections.abc import AsyncGenerator, Generator, Mapping
|
12
13
|
from contextlib import ExitStack, asynccontextmanager, contextmanager
|
13
14
|
from contextvars import ContextVar, Token
|
14
|
-
from typing import
|
15
|
-
TYPE_CHECKING,
|
16
|
-
Any,
|
17
|
-
AsyncGenerator,
|
18
|
-
Dict,
|
19
|
-
Generator,
|
20
|
-
Mapping,
|
21
|
-
Optional,
|
22
|
-
Set,
|
23
|
-
Type,
|
24
|
-
TypeVar,
|
25
|
-
Union,
|
26
|
-
)
|
15
|
+
from typing import TYPE_CHECKING, Any, Optional, TypeVar, Union
|
27
16
|
|
28
17
|
from pydantic import BaseModel, ConfigDict, Field, PrivateAttr
|
29
18
|
from typing_extensions import Self
|
@@ -64,7 +53,7 @@ if TYPE_CHECKING:
|
|
64
53
|
GLOBAL_SETTINGS_CONTEXT = None # type: ignore
|
65
54
|
|
66
55
|
|
67
|
-
def serialize_context() ->
|
56
|
+
def serialize_context() -> dict[str, Any]:
|
68
57
|
"""
|
69
58
|
Serialize the current context for use in a remote execution environment.
|
70
59
|
"""
|
@@ -84,7 +73,7 @@ def serialize_context() -> Dict[str, Any]:
|
|
84
73
|
|
85
74
|
@contextmanager
|
86
75
|
def hydrated_context(
|
87
|
-
serialized_context: Optional[
|
76
|
+
serialized_context: Optional[dict[str, Any]] = None,
|
88
77
|
client: Union[PrefectClient, SyncPrefectClient, None] = None,
|
89
78
|
):
|
90
79
|
with ExitStack() as stack:
|
@@ -148,7 +137,7 @@ class ContextModel(BaseModel):
|
|
148
137
|
self._token = None
|
149
138
|
|
150
139
|
@classmethod
|
151
|
-
def get(cls:
|
140
|
+
def get(cls: type[Self]) -> Optional[Self]:
|
152
141
|
"""Get the current context instance"""
|
153
142
|
return cls.__var__.get(None)
|
154
143
|
|
@@ -173,7 +162,7 @@ class ContextModel(BaseModel):
|
|
173
162
|
new._token = None
|
174
163
|
return new
|
175
164
|
|
176
|
-
def serialize(self, include_secrets: bool = True) ->
|
165
|
+
def serialize(self, include_secrets: bool = True) -> dict[str, Any]:
|
177
166
|
"""
|
178
167
|
Serialize the context model to a dictionary that can be pickled with cloudpickle.
|
179
168
|
"""
|
@@ -314,10 +303,10 @@ class RunContext(ContextModel):
|
|
314
303
|
start_client_metrics_server()
|
315
304
|
|
316
305
|
start_time: DateTime = Field(default_factory=lambda: DateTime.now("UTC"))
|
317
|
-
input_keyset: Optional[
|
306
|
+
input_keyset: Optional[dict[str, dict[str, str]]] = None
|
318
307
|
client: Union[PrefectClient, SyncPrefectClient]
|
319
308
|
|
320
|
-
def serialize(self: Self, include_secrets: bool = True) ->
|
309
|
+
def serialize(self: Self, include_secrets: bool = True) -> dict[str, Any]:
|
321
310
|
return self.model_dump(
|
322
311
|
include={"start_time", "input_keyset"},
|
323
312
|
exclude_unset=True,
|
@@ -344,7 +333,7 @@ class EngineContext(RunContext):
|
|
344
333
|
flow_run: Optional[FlowRun] = None
|
345
334
|
task_runner: TaskRunner[Any]
|
346
335
|
log_prints: bool = False
|
347
|
-
parameters: Optional[
|
336
|
+
parameters: Optional[dict[str, Any]] = None
|
348
337
|
|
349
338
|
# Flag signaling if the flow run context has been serialized and sent
|
350
339
|
# to remote infrastructure.
|
@@ -355,10 +344,10 @@ class EngineContext(RunContext):
|
|
355
344
|
persist_result: bool = Field(default_factory=get_default_persist_setting)
|
356
345
|
|
357
346
|
# Counter for task calls allowing unique
|
358
|
-
task_run_dynamic_keys:
|
347
|
+
task_run_dynamic_keys: dict[str, Union[str, int]] = Field(default_factory=dict)
|
359
348
|
|
360
349
|
# Counter for flow pauses
|
361
|
-
observed_flow_pauses:
|
350
|
+
observed_flow_pauses: dict[str, int] = Field(default_factory=dict)
|
362
351
|
|
363
352
|
# Tracking for result from task runs in this flow run for dependency tracking
|
364
353
|
# Holds the ID of the object returned by the task run and task run state
|
@@ -369,7 +358,7 @@ class EngineContext(RunContext):
|
|
369
358
|
|
370
359
|
__var__: ContextVar[Self] = ContextVar("flow_run")
|
371
360
|
|
372
|
-
def serialize(self: Self, include_secrets: bool = True) ->
|
361
|
+
def serialize(self: Self, include_secrets: bool = True) -> dict[str, Any]:
|
373
362
|
return self.model_dump(
|
374
363
|
include={
|
375
364
|
"flow_run",
|
@@ -403,7 +392,7 @@ class TaskRunContext(RunContext):
|
|
403
392
|
task: "Task[Any, Any]"
|
404
393
|
task_run: TaskRun
|
405
394
|
log_prints: bool = False
|
406
|
-
parameters:
|
395
|
+
parameters: dict[str, Any]
|
407
396
|
|
408
397
|
# Result handling
|
409
398
|
result_store: ResultStore
|
@@ -411,7 +400,7 @@ class TaskRunContext(RunContext):
|
|
411
400
|
|
412
401
|
__var__ = ContextVar("task_run")
|
413
402
|
|
414
|
-
def serialize(self: Self, include_secrets: bool = True) ->
|
403
|
+
def serialize(self: Self, include_secrets: bool = True) -> dict[str, Any]:
|
415
404
|
return self.model_dump(
|
416
405
|
include={
|
417
406
|
"task_run",
|
@@ -437,7 +426,7 @@ class TagsContext(ContextModel):
|
|
437
426
|
current_tags: A set of current tags in the context
|
438
427
|
"""
|
439
428
|
|
440
|
-
current_tags:
|
429
|
+
current_tags: set[str] = Field(default_factory=set)
|
441
430
|
|
442
431
|
@classmethod
|
443
432
|
def get(cls) -> "TagsContext":
|
@@ -512,7 +501,7 @@ def get_settings_context() -> SettingsContext:
|
|
512
501
|
|
513
502
|
|
514
503
|
@contextmanager
|
515
|
-
def tags(*new_tags: str) -> Generator[
|
504
|
+
def tags(*new_tags: str) -> Generator[set[str], None, None]:
|
516
505
|
"""
|
517
506
|
Context manager to add tags to flow and task run calls.
|
518
507
|
|
prefect/flows.py
CHANGED
@@ -37,7 +37,6 @@ from typing import (
|
|
37
37
|
from uuid import UUID
|
38
38
|
|
39
39
|
import pydantic
|
40
|
-
from fastapi.encoders import jsonable_encoder
|
41
40
|
from pydantic.v1 import BaseModel as V1BaseModel
|
42
41
|
from pydantic.v1.decorator import ValidatedFunction as V1ValidatedFunction
|
43
42
|
from pydantic.v1.errors import ConfigError # TODO
|
@@ -613,6 +612,8 @@ class Flow(Generic[P, R]):
|
|
613
612
|
serialized_parameters[key] = f"<{type(value).__name__}>"
|
614
613
|
continue
|
615
614
|
try:
|
615
|
+
from fastapi.encoders import jsonable_encoder
|
616
|
+
|
616
617
|
serialized_parameters[key] = jsonable_encoder(value)
|
617
618
|
except (TypeError, ValueError):
|
618
619
|
logger.debug(
|
prefect/futures.py
CHANGED
@@ -1,17 +1,15 @@
|
|
1
1
|
import abc
|
2
2
|
import asyncio
|
3
|
-
import collections
|
4
3
|
import concurrent.futures
|
5
4
|
import threading
|
6
5
|
import uuid
|
7
6
|
from collections.abc import Generator, Iterator
|
8
7
|
from functools import partial
|
9
|
-
from typing import Any, Callable, Generic,
|
8
|
+
from typing import Any, Callable, Generic, Optional, Union
|
10
9
|
|
11
|
-
from typing_extensions import TypeVar
|
10
|
+
from typing_extensions import NamedTuple, Self, TypeVar
|
12
11
|
|
13
12
|
from prefect.client.orchestration import get_client
|
14
|
-
from prefect.client.schemas.objects import TaskRun
|
15
13
|
from prefect.exceptions import ObjectNotFound
|
16
14
|
from prefect.logging.loggers import get_logger, get_run_logger
|
17
15
|
from prefect.states import Pending, State
|
@@ -50,7 +48,7 @@ class PrefectFuture(abc.ABC, Generic[R]):
|
|
50
48
|
return self._final_state
|
51
49
|
client = get_client(sync_client=True)
|
52
50
|
try:
|
53
|
-
task_run =
|
51
|
+
task_run = client.read_task_run(task_run_id=self.task_run_id)
|
54
52
|
except ObjectNotFound:
|
55
53
|
# We'll be optimistic and assume this task will eventually start
|
56
54
|
# TODO: Consider using task run events to wait for the task to start
|
@@ -92,7 +90,7 @@ class PrefectFuture(abc.ABC, Generic[R]):
|
|
92
90
|
"""
|
93
91
|
|
94
92
|
@abc.abstractmethod
|
95
|
-
def add_done_callback(self, fn):
|
93
|
+
def add_done_callback(self, fn: Callable[["PrefectFuture[R]"], None]):
|
96
94
|
"""
|
97
95
|
Add a callback to be run when the future completes or is cancelled.
|
98
96
|
|
@@ -102,13 +100,17 @@ class PrefectFuture(abc.ABC, Generic[R]):
|
|
102
100
|
...
|
103
101
|
|
104
102
|
|
105
|
-
class PrefectWrappedFuture(PrefectFuture, abc.ABC, Generic[R, F]):
|
103
|
+
class PrefectWrappedFuture(PrefectFuture[R], abc.ABC, Generic[R, F]):
|
106
104
|
"""
|
107
105
|
A Prefect future that wraps another future object.
|
106
|
+
|
107
|
+
Type Parameters:
|
108
|
+
R: The return type of the future
|
109
|
+
F: The type of the wrapped future
|
108
110
|
"""
|
109
111
|
|
110
112
|
def __init__(self, task_run_id: uuid.UUID, wrapped_future: F):
|
111
|
-
self._wrapped_future = wrapped_future
|
113
|
+
self._wrapped_future: F = wrapped_future
|
112
114
|
super().__init__(task_run_id)
|
113
115
|
|
114
116
|
@property
|
@@ -116,10 +118,11 @@ class PrefectWrappedFuture(PrefectFuture, abc.ABC, Generic[R, F]):
|
|
116
118
|
"""The underlying future object wrapped by this Prefect future"""
|
117
119
|
return self._wrapped_future
|
118
120
|
|
119
|
-
def add_done_callback(self, fn: Callable[[PrefectFuture[R]], None]):
|
121
|
+
def add_done_callback(self, fn: Callable[[PrefectFuture[R]], None]) -> None:
|
122
|
+
"""Add a callback to be executed when the future completes."""
|
120
123
|
if not self._final_state:
|
121
124
|
|
122
|
-
def call_with_self(future):
|
125
|
+
def call_with_self(future: F):
|
123
126
|
"""Call the callback with self as the argument, this is necessary to ensure we remove the future from the pending set"""
|
124
127
|
fn(self)
|
125
128
|
|
@@ -128,7 +131,7 @@ class PrefectWrappedFuture(PrefectFuture, abc.ABC, Generic[R, F]):
|
|
128
131
|
fn(self)
|
129
132
|
|
130
133
|
|
131
|
-
class PrefectConcurrentFuture(PrefectWrappedFuture[R, concurrent.futures.Future]):
|
134
|
+
class PrefectConcurrentFuture(PrefectWrappedFuture[R, concurrent.futures.Future[R]]):
|
132
135
|
"""
|
133
136
|
A Prefect future that wraps a concurrent.futures.Future. This future is used
|
134
137
|
when the task run is submitted to a ThreadPoolExecutor.
|
@@ -193,7 +196,7 @@ class PrefectDistributedFuture(PrefectFuture[R]):
|
|
193
196
|
any task run scheduled in Prefect's API.
|
194
197
|
"""
|
195
198
|
|
196
|
-
done_callbacks:
|
199
|
+
done_callbacks: list[Callable[[PrefectFuture[R]], None]] = []
|
197
200
|
waiter = None
|
198
201
|
|
199
202
|
def wait(self, timeout: Optional[float] = None) -> None:
|
@@ -270,7 +273,7 @@ class PrefectDistributedFuture(PrefectFuture[R]):
|
|
270
273
|
return
|
271
274
|
TaskRunWaiter.add_done_callback(self._task_run_id, partial(fn, self))
|
272
275
|
|
273
|
-
def __eq__(self, other):
|
276
|
+
def __eq__(self, other: Any) -> bool:
|
274
277
|
if not isinstance(other, PrefectDistributedFuture):
|
275
278
|
return False
|
276
279
|
return self.task_run_id == other.task_run_id
|
@@ -279,7 +282,7 @@ class PrefectDistributedFuture(PrefectFuture[R]):
|
|
279
282
|
return hash(self.task_run_id)
|
280
283
|
|
281
284
|
|
282
|
-
class PrefectFutureList(list, Iterator
|
285
|
+
class PrefectFutureList(list[PrefectFuture[R]], Iterator[PrefectFuture[R]]):
|
283
286
|
"""
|
284
287
|
A list of Prefect futures.
|
285
288
|
|
@@ -298,10 +301,10 @@ class PrefectFutureList(list, Iterator, Generic[F]):
|
|
298
301
|
wait(self, timeout=timeout)
|
299
302
|
|
300
303
|
def result(
|
301
|
-
self:
|
304
|
+
self: Self,
|
302
305
|
timeout: Optional[float] = None,
|
303
306
|
raise_on_failure: bool = True,
|
304
|
-
) ->
|
307
|
+
) -> list[R]:
|
305
308
|
"""
|
306
309
|
Get the results of all task runs associated with the futures in the list.
|
307
310
|
|
@@ -331,21 +334,22 @@ class PrefectFutureList(list, Iterator, Generic[F]):
|
|
331
334
|
|
332
335
|
|
333
336
|
def as_completed(
|
334
|
-
futures:
|
337
|
+
futures: list[PrefectFuture[R]], timeout: Optional[float] = None
|
335
338
|
) -> Generator[PrefectFuture[R], None]:
|
336
|
-
unique_futures:
|
339
|
+
unique_futures: set[PrefectFuture[R]] = set(futures)
|
337
340
|
total_futures = len(unique_futures)
|
341
|
+
pending = unique_futures
|
338
342
|
try:
|
339
343
|
with timeout_context(timeout):
|
340
|
-
done = {f for f in unique_futures if f._final_state}
|
344
|
+
done = {f for f in unique_futures if f._final_state} # type: ignore[privateUsage]
|
341
345
|
pending = unique_futures - done
|
342
346
|
yield from done
|
343
347
|
|
344
348
|
finished_event = threading.Event()
|
345
349
|
finished_lock = threading.Lock()
|
346
|
-
finished_futures = []
|
350
|
+
finished_futures: list[PrefectFuture[R]] = []
|
347
351
|
|
348
|
-
def add_to_done(future):
|
352
|
+
def add_to_done(future: PrefectFuture[R]):
|
349
353
|
with finished_lock:
|
350
354
|
finished_futures.append(future)
|
351
355
|
finished_event.set()
|
@@ -370,10 +374,19 @@ def as_completed(
|
|
370
374
|
)
|
371
375
|
|
372
376
|
|
373
|
-
DoneAndNotDoneFutures
|
377
|
+
class DoneAndNotDoneFutures(NamedTuple, Generic[R]):
|
378
|
+
"""A named 2-tuple of sets.
|
379
|
+
|
380
|
+
multiple inheritance supported in 3.11+, use typing_extensions.NamedTuple
|
381
|
+
"""
|
382
|
+
|
383
|
+
done: set[PrefectFuture[R]]
|
384
|
+
not_done: set[PrefectFuture[R]]
|
374
385
|
|
375
386
|
|
376
|
-
def wait(
|
387
|
+
def wait(
|
388
|
+
futures: list[PrefectFuture[R]], timeout: Optional[float] = None
|
389
|
+
) -> DoneAndNotDoneFutures[R]:
|
377
390
|
"""
|
378
391
|
Wait for the futures in the given sequence to complete.
|
379
392
|
|
@@ -431,9 +444,11 @@ def resolve_futures_to_states(
|
|
431
444
|
|
432
445
|
Unsupported object types will be returned without modification.
|
433
446
|
"""
|
434
|
-
futures:
|
447
|
+
futures: set[PrefectFuture[R]] = set()
|
435
448
|
|
436
|
-
def _collect_futures(
|
449
|
+
def _collect_futures(
|
450
|
+
futures: set[PrefectFuture[R]], expr: Any, context: Any
|
451
|
+
) -> Union[PrefectFuture[R], Any]:
|
437
452
|
# Expressions inside quotes should not be traversed
|
438
453
|
if isinstance(context.get("annotation"), quote):
|
439
454
|
raise StopVisiting()
|
@@ -455,14 +470,14 @@ def resolve_futures_to_states(
|
|
455
470
|
return expr
|
456
471
|
|
457
472
|
# Get final states for each future
|
458
|
-
states = []
|
473
|
+
states: list[State] = []
|
459
474
|
for future in futures:
|
460
475
|
future.wait()
|
461
476
|
states.append(future.state)
|
462
477
|
|
463
478
|
states_by_future = dict(zip(futures, states))
|
464
479
|
|
465
|
-
def replace_futures_with_states(expr, context):
|
480
|
+
def replace_futures_with_states(expr: Any, context: Any) -> Any:
|
466
481
|
# Expressions inside quotes should not be modified
|
467
482
|
if isinstance(context.get("annotation"), quote):
|
468
483
|
raise StopVisiting()
|
prefect/locking/filesystem.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import time
|
2
|
+
from logging import Logger
|
2
3
|
from pathlib import Path
|
3
|
-
from typing import
|
4
|
+
from typing import Optional
|
4
5
|
|
5
6
|
import anyio
|
6
7
|
import pendulum
|
@@ -11,7 +12,7 @@ from prefect.logging.loggers import get_logger
|
|
11
12
|
|
12
13
|
from .protocol import LockManager
|
13
14
|
|
14
|
-
logger = get_logger(__name__)
|
15
|
+
logger: Logger = get_logger(__name__)
|
15
16
|
|
16
17
|
|
17
18
|
class _LockInfo(TypedDict):
|
@@ -37,11 +38,11 @@ class FileSystemLockManager(LockManager):
|
|
37
38
|
lock_files_directory: the directory where lock files are stored
|
38
39
|
"""
|
39
40
|
|
40
|
-
def __init__(self, lock_files_directory: Path):
|
41
|
-
self.lock_files_directory = lock_files_directory.expanduser().resolve()
|
42
|
-
self._locks:
|
41
|
+
def __init__(self, lock_files_directory: Path) -> None:
|
42
|
+
self.lock_files_directory: Path = lock_files_directory.expanduser().resolve()
|
43
|
+
self._locks: dict[str, _LockInfo] = {}
|
43
44
|
|
44
|
-
def _ensure_lock_files_directory_exists(self):
|
45
|
+
def _ensure_lock_files_directory_exists(self) -> None:
|
45
46
|
self.lock_files_directory.mkdir(parents=True, exist_ok=True)
|
46
47
|
|
47
48
|
def _lock_path_for_key(self, key: str) -> Path:
|
@@ -49,7 +50,7 @@ class FileSystemLockManager(LockManager):
|
|
49
50
|
return lock_info["path"]
|
50
51
|
return self.lock_files_directory.joinpath(key).with_suffix(".lock")
|
51
52
|
|
52
|
-
def _get_lock_info(self, key: str, use_cache=True) -> Optional[_LockInfo]:
|
53
|
+
def _get_lock_info(self, key: str, use_cache: bool = True) -> Optional[_LockInfo]:
|
53
54
|
if use_cache:
|
54
55
|
if (lock_info := self._locks.get(key)) is not None:
|
55
56
|
return lock_info
|
prefect/locking/memory.py
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
import asyncio
|
2
2
|
import threading
|
3
|
-
from typing import
|
3
|
+
from typing import Any, Optional, TypedDict
|
4
|
+
|
5
|
+
from typing_extensions import Self
|
4
6
|
|
5
7
|
from .protocol import LockManager
|
6
8
|
|
@@ -30,14 +32,14 @@ class MemoryLockManager(LockManager):
|
|
30
32
|
|
31
33
|
_instance = None
|
32
34
|
|
33
|
-
def __new__(cls, *args, **kwargs):
|
35
|
+
def __new__(cls, *args: Any, **kwargs: Any) -> Self:
|
34
36
|
if cls._instance is None:
|
35
37
|
cls._instance = super().__new__(cls)
|
36
38
|
return cls._instance
|
37
39
|
|
38
40
|
def __init__(self):
|
39
41
|
self._locks_dict_lock = threading.Lock()
|
40
|
-
self._locks:
|
42
|
+
self._locks: dict[str, _LockInfo] = {}
|
41
43
|
|
42
44
|
def _expire_lock(self, key: str):
|
43
45
|
"""
|
prefect/locking/protocol.py
CHANGED
prefect/plugins.py
CHANGED
@@ -9,15 +9,15 @@ Currently supported entrypoints:
|
|
9
9
|
"""
|
10
10
|
|
11
11
|
from types import ModuleType
|
12
|
-
from typing import Any,
|
12
|
+
from typing import Any, Union
|
13
13
|
|
14
14
|
import prefect.settings
|
15
15
|
from prefect.utilities.compat import EntryPoints, entry_points
|
16
16
|
|
17
|
-
|
17
|
+
_collections: Union[None, dict[str, Union[ModuleType, Exception]]] = None
|
18
18
|
|
19
19
|
|
20
|
-
def safe_load_entrypoints(entrypoints: EntryPoints) ->
|
20
|
+
def safe_load_entrypoints(entrypoints: EntryPoints) -> dict[str, Union[Exception, Any]]:
|
21
21
|
"""
|
22
22
|
Load entry points for a group capturing any exceptions that occur.
|
23
23
|
"""
|
@@ -26,7 +26,7 @@ def safe_load_entrypoints(entrypoints: EntryPoints) -> Dict[str, Union[Exception
|
|
26
26
|
# also want to validate the type for the group for entrypoints that have
|
27
27
|
# a specific type we expect.
|
28
28
|
|
29
|
-
results = {}
|
29
|
+
results: dict[str, Union[Exception, Any]] = {}
|
30
30
|
|
31
31
|
for entrypoint in entrypoints:
|
32
32
|
result = None
|
@@ -40,18 +40,20 @@ def safe_load_entrypoints(entrypoints: EntryPoints) -> Dict[str, Union[Exception
|
|
40
40
|
return results
|
41
41
|
|
42
42
|
|
43
|
-
def load_prefect_collections() ->
|
43
|
+
def load_prefect_collections() -> dict[str, Union[ModuleType, Exception]]:
|
44
44
|
"""
|
45
45
|
Load all Prefect collections that define an entrypoint in the group
|
46
46
|
`prefect.collections`.
|
47
47
|
"""
|
48
|
-
global
|
48
|
+
global _collections
|
49
49
|
|
50
|
-
if
|
51
|
-
return
|
50
|
+
if _collections is not None:
|
51
|
+
return _collections
|
52
52
|
|
53
53
|
collection_entrypoints: EntryPoints = entry_points(group="prefect.collections")
|
54
|
-
collections = safe_load_entrypoints(
|
54
|
+
collections: dict[str, Union[Exception, Any]] = safe_load_entrypoints(
|
55
|
+
collection_entrypoints
|
56
|
+
)
|
55
57
|
|
56
58
|
# TODO: Consider the utility of this once we've established this pattern.
|
57
59
|
# We cannot use a logger here because logging is not yet initialized.
|
@@ -68,5 +70,5 @@ def load_prefect_collections() -> Dict[str, Union[ModuleType, Exception]]:
|
|
68
70
|
if prefect.settings.PREFECT_DEBUG_MODE:
|
69
71
|
print(f"Loaded collection {name!r}.")
|
70
72
|
|
71
|
-
|
73
|
+
_collections = collections
|
72
74
|
return collections
|
prefect/results.py
CHANGED
@@ -245,7 +245,7 @@ async def _call_explicitly_async_block_method(
|
|
245
245
|
see https://github.com/PrefectHQ/prefect/issues/15008
|
246
246
|
"""
|
247
247
|
if hasattr(block, f"a{method}"): # explicit async method
|
248
|
-
return await getattr(block
|
248
|
+
return await getattr(block, f"a{method}")(*args, **kwargs)
|
249
249
|
elif hasattr(getattr(block, method, None), "aio"): # sync_compatible
|
250
250
|
return await getattr(block, method).aio(block, *args, **kwargs)
|
251
251
|
else: # should not happen in prefect, but users can override impls
|
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 TYPE_CHECKING,
|
3
|
+
from typing import TYPE_CHECKING, Optional
|
4
4
|
|
5
5
|
from opentelemetry.context import Context
|
6
6
|
from opentelemetry.sdk.trace import Span, SpanProcessor
|
@@ -13,7 +13,7 @@ if TYPE_CHECKING:
|
|
13
13
|
class InFlightSpanProcessor(SpanProcessor):
|
14
14
|
def __init__(self, span_exporter: "SpanExporter"):
|
15
15
|
self.span_exporter = span_exporter
|
16
|
-
self._in_flight:
|
16
|
+
self._in_flight: dict[int, Span] = {}
|
17
17
|
self._lock = Lock()
|
18
18
|
self._stop_event = Event()
|
19
19
|
self._export_thread = Thread(target=self._export_periodically, daemon=True)
|
@@ -30,10 +30,10 @@ class InFlightSpanProcessor(SpanProcessor):
|
|
30
30
|
self.span_exporter.export(to_export)
|
31
31
|
|
32
32
|
def _readable_span(self, span: "Span") -> "ReadableSpan":
|
33
|
-
readable = span._readable_span()
|
34
|
-
readable._end_time = time.time_ns()
|
35
|
-
readable._attributes = {
|
36
|
-
**(readable._attributes or {}),
|
33
|
+
readable = span._readable_span() # pyright: ignore[reportPrivateUsage]
|
34
|
+
readable._end_time = time.time_ns() # pyright: ignore[reportPrivateUsage]
|
35
|
+
readable._attributes = { # pyright: ignore[reportPrivateUsage]
|
36
|
+
**(readable._attributes or {}), # pyright: ignore[reportPrivateUsage]
|
37
37
|
"prefect.in-flight": True,
|
38
38
|
}
|
39
39
|
return readable
|
prefect/telemetry/services.py
CHANGED
@@ -1,32 +1,38 @@
|
|
1
|
-
from abc import
|
2
|
-
from typing import
|
1
|
+
from collections.abc import Sequence
|
2
|
+
from typing import Any, Protocol, TypeVar
|
3
3
|
|
4
4
|
from opentelemetry.exporter.otlp.proto.http._log_exporter import OTLPLogExporter
|
5
5
|
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
|
6
6
|
from opentelemetry.sdk._logs import LogData
|
7
7
|
from opentelemetry.sdk._logs.export import LogExporter
|
8
8
|
from opentelemetry.sdk.trace import ReadableSpan
|
9
|
-
from opentelemetry.sdk.trace.export import SpanExporter
|
9
|
+
from opentelemetry.sdk.trace.export import SpanExporter, SpanExportResult
|
10
10
|
|
11
11
|
from prefect._internal.concurrency.services import BatchedQueueService
|
12
12
|
|
13
|
+
BatchItem = TypeVar("BatchItem", ReadableSpan, LogData)
|
14
|
+
T_contra = TypeVar("T_contra", contravariant=True)
|
13
15
|
|
14
|
-
|
16
|
+
|
17
|
+
class OTLPExporter(Protocol[T_contra]):
|
18
|
+
def export(self, __items: Sequence[T_contra]) -> Any:
|
19
|
+
...
|
20
|
+
|
21
|
+
def shutdown(self) -> Any:
|
22
|
+
...
|
23
|
+
|
24
|
+
|
25
|
+
class BaseQueueingExporter(BatchedQueueService[BatchItem]):
|
15
26
|
_max_batch_size = 512
|
16
27
|
_min_interval = 2.0
|
17
|
-
_otlp_exporter: Union[SpanExporter, LogExporter]
|
18
|
-
|
19
|
-
def export(self, batch: list[Union[ReadableSpan, LogData]]) -> None:
|
20
|
-
for item in batch:
|
21
|
-
self.send(item)
|
22
28
|
|
23
|
-
|
24
|
-
|
25
|
-
|
29
|
+
def __init__(self, otlp_exporter: OTLPExporter[BatchItem]) -> None:
|
30
|
+
super().__init__()
|
31
|
+
self._otlp_exporter = otlp_exporter
|
26
32
|
|
27
|
-
async def _handle_batch(self, items: list[
|
33
|
+
async def _handle_batch(self, items: list[BatchItem]) -> None:
|
28
34
|
try:
|
29
|
-
self.
|
35
|
+
self._otlp_exporter.export(items)
|
30
36
|
except Exception as e:
|
31
37
|
self._logger.exception(f"Failed to export batch: {e}")
|
32
38
|
raise
|
@@ -39,29 +45,24 @@ class BaseQueueingExporter(BatchedQueueService):
|
|
39
45
|
self._otlp_exporter.shutdown()
|
40
46
|
|
41
47
|
|
42
|
-
class QueueingSpanExporter(BaseQueueingExporter, SpanExporter):
|
48
|
+
class QueueingSpanExporter(BaseQueueingExporter[ReadableSpan], SpanExporter):
|
43
49
|
_otlp_exporter: OTLPSpanExporter
|
44
50
|
|
45
51
|
def __init__(self, endpoint: str, headers: tuple[tuple[str, str]]):
|
46
|
-
super().__init__()
|
47
|
-
self._otlp_exporter = OTLPSpanExporter(
|
48
|
-
endpoint=endpoint,
|
49
|
-
headers=dict(headers),
|
50
|
-
)
|
52
|
+
super().__init__(OTLPSpanExporter(endpoint=endpoint, headers=dict(headers)))
|
51
53
|
|
52
|
-
def
|
53
|
-
|
54
|
+
def export(self, spans: Sequence[ReadableSpan]) -> SpanExportResult:
|
55
|
+
for item in spans:
|
56
|
+
self.send(item)
|
57
|
+
return SpanExportResult.SUCCESS
|
54
58
|
|
55
59
|
|
56
|
-
class QueueingLogExporter(BaseQueueingExporter, LogExporter):
|
60
|
+
class QueueingLogExporter(BaseQueueingExporter[LogData], LogExporter):
|
57
61
|
_otlp_exporter: OTLPLogExporter
|
58
62
|
|
59
|
-
def __init__(self, endpoint: str, headers: tuple[tuple[str, str]]):
|
60
|
-
super().__init__()
|
61
|
-
self._otlp_exporter = OTLPLogExporter(
|
62
|
-
endpoint=endpoint,
|
63
|
-
headers=dict(headers),
|
64
|
-
)
|
63
|
+
def __init__(self, endpoint: str, headers: tuple[tuple[str, str]]) -> None:
|
64
|
+
super().__init__(OTLPLogExporter(endpoint=endpoint, headers=dict(headers)))
|
65
65
|
|
66
|
-
def
|
67
|
-
|
66
|
+
def export(self, batch: Sequence[LogData]) -> None:
|
67
|
+
for item in batch:
|
68
|
+
self.send(item)
|
prefect/workers/__init__.py
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
prefect/.prefectignore,sha256=awSprvKT0vI8a64mEOLrMxhxqcO-b0ERQeYpA2rNKVQ,390
|
2
2
|
prefect/__init__.py,sha256=FmdMSNpGH8Mrkn5X0mNZup8_SHdeB_aqEmS5taeOHAQ,3530
|
3
|
-
prefect/_version.py,sha256=
|
3
|
+
prefect/_version.py,sha256=bUcLcvgSrFk7uLI6vWR4M14nKrDGJAXv4mOuUqQtH0U,497
|
4
4
|
prefect/agent.py,sha256=qyyUMdiv5ndUIk-O8uwamESJGXXDQ_BmhKiLlm31ue0,286
|
5
|
-
prefect/artifacts.py,sha256=
|
6
|
-
prefect/automations.py,sha256=
|
5
|
+
prefect/artifacts.py,sha256=c_hMYTQoKFij8_tahtBeHzjYl7ztXAU90QP_6SuMw9A,12934
|
6
|
+
prefect/automations.py,sha256=QHS3Xh6wUKRvzxXt8cfWri6wXjX8EfEDDQN8a7cRw3c,6594
|
7
7
|
prefect/cache_policies.py,sha256=dlhYHMxhb2N5KdDMIAuw4q-PIsI8WH5k0LDDLqsRYMU,9903
|
8
|
-
prefect/context.py,sha256=
|
8
|
+
prefect/context.py,sha256=OAEhyJz7kheIh6UEwPp3oLklYdM_UHibrdqeM3aCLqk,22325
|
9
9
|
prefect/engine.py,sha256=qkT6hQWfxQPmjAEECQx3wluiDiFMHf3h9DRG1ShwK7w,2031
|
10
10
|
prefect/exceptions.py,sha256=sbphPKQ4yOBUa9w0MsSFoDj_uC8Tlv9WHTjzO3cQKq8,11593
|
11
11
|
prefect/filesystems.py,sha256=cLBGbnW2NQqH4N70Y1i1QuCL3R7p-_r_d5CGaEAd4wg,17897
|
12
12
|
prefect/flow_engine.py,sha256=eb2N5lRdsZBWNIsaAs1pqdDhL5Vevq8ETxyn5LM4Mks,53812
|
13
13
|
prefect/flow_runs.py,sha256=-5udBBYdgdCBCjAMYvELbA1vmrjZ6oREXl-BZdZr6hc,16129
|
14
|
-
prefect/flows.py,sha256=
|
15
|
-
prefect/futures.py,sha256=
|
14
|
+
prefect/flows.py,sha256=Z1BdpmJotXJoqoDqcUtxiiPsGWvDfSBvk1XEEo6ykw4,94127
|
15
|
+
prefect/futures.py,sha256=ZtQiRJddO5-LNabUZiX_2wEJnRf6w7qZ8KRC5VUNOa0,16915
|
16
16
|
prefect/main.py,sha256=lFYvXkW32sMj4aVH97foApD3Ut3rZIwtO91xUQHo_6I,2355
|
17
|
-
prefect/plugins.py,sha256=
|
17
|
+
prefect/plugins.py,sha256=FPRLR2mWVBMuOnlzeiTD9krlHONZH2rtYLD753JQDNQ,2516
|
18
18
|
prefect/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
19
|
-
prefect/results.py,sha256=
|
19
|
+
prefect/results.py,sha256=okLkMlQcYUZHIl0XXMqVnWVLdcIYXe4b1wWX1T7Qa_8,50562
|
20
20
|
prefect/serializers.py,sha256=DiKLYdIA5VjCSrLyu0BSWcLLVRujqjvj8XoQ3HOuvoY,8968
|
21
21
|
prefect/states.py,sha256=ZhJHLx8ax7dQNdaBl2eDT6VYGAU-68R1loht68qHGpc,25396
|
22
22
|
prefect/task_engine.py,sha256=1xM64s9OpDREnKPnU9HpwHgtbAE50uwdp2ZucmPUhCg,61226
|
@@ -133,9 +133,9 @@ prefect/input/__init__.py,sha256=Ue2h-YhYP71nEtsVJaslqMwO6C0ckjhjTYwwEgp-E3g,701
|
|
133
133
|
prefect/input/actions.py,sha256=IGdWjVcesnRjLmPCzB4ZM7FkRWXDKCku6yhE-7p0vKk,3777
|
134
134
|
prefect/input/run_input.py,sha256=2wG-0L3N0spwh61Z3xI0PM8AAjHEIQZcDN703Er_gLo,18728
|
135
135
|
prefect/locking/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
136
|
-
prefect/locking/filesystem.py,sha256=
|
137
|
-
prefect/locking/memory.py,sha256=
|
138
|
-
prefect/locking/protocol.py,sha256=
|
136
|
+
prefect/locking/filesystem.py,sha256=zhNwdKroi2kLR6Cut6CMT-rWmFwtTtzuGKSwGH_Iw0s,8084
|
137
|
+
prefect/locking/memory.py,sha256=mFUgV750ywEL7aVQuxFjg9gxbjVU4esBQn7bGQYzeMY,7548
|
138
|
+
prefect/locking/protocol.py,sha256=RsfvlaHTTEJ0YvYWSqFGoZuT2w4FPPxyQlHqjoyNGuE,4240
|
139
139
|
prefect/logging/__init__.py,sha256=zx9f5_dWrR4DbcTOFBpNGOPoCZ1QcPFudr7zxb2XRpA,148
|
140
140
|
prefect/logging/configuration.py,sha256=t7EJrk7Jr4QMxopH3TP6gRN8kMg_LFBsIoiwXCihrso,3353
|
141
141
|
prefect/logging/filters.py,sha256=9keHLN4-cpnsWcii1qU0RITNi9-m7pOhkJ_t0MtCM4k,1117
|
@@ -200,9 +200,9 @@ prefect/telemetry/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs
|
|
200
200
|
prefect/telemetry/bootstrap.py,sha256=b64UpBBo0Yo7Z8b_V9NQLAlFrpIuJoTs5opYTuB-R20,1550
|
201
201
|
prefect/telemetry/instrumentation.py,sha256=G8kDiN2N4l7A8on-BHbYnh8uqH71zuGr3t2JntxRv0Q,4183
|
202
202
|
prefect/telemetry/logging.py,sha256=yn5D4D2GGRrAv0y8wlHPN7PZDmQucGjQT_YauK9M9Yo,727
|
203
|
-
prefect/telemetry/processors.py,sha256=
|
203
|
+
prefect/telemetry/processors.py,sha256=jw6j6LviOVxw3IBJe7cSjsxFk0zzY43jUmy6C9pcfCE,2272
|
204
204
|
prefect/telemetry/run_telemetry.py,sha256=FfvcUJK6Sqcagp6rJ3vx4twCAkyYJYBhtNUUzjM0D7A,8135
|
205
|
-
prefect/telemetry/services.py,sha256=
|
205
|
+
prefect/telemetry/services.py,sha256=ek5KMSgCjUeIoNl9INPCfKkwlUwyFYp_dUiZd_rD0_8,2270
|
206
206
|
prefect/types/__init__.py,sha256=s-l0r8UiDs7GCEstOPMzbb9PvvF_0F4G8OcVy3_50Yk,4700
|
207
207
|
prefect/types/entrypoint.py,sha256=2FF03-wLPgtnqR_bKJDB2BsXXINPdu8ptY9ZYEZnXg8,328
|
208
208
|
prefect/utilities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -234,15 +234,15 @@ prefect/utilities/visualization.py,sha256=4MyQKLb00A1QZCvSrbPEbyqUNByQ_EkJ6wXKFC
|
|
234
234
|
prefect/utilities/schema_tools/__init__.py,sha256=At3rMHd2g_Em2P3_dFQlFgqR_EpBwrYtU2N2OJd0pDE,345
|
235
235
|
prefect/utilities/schema_tools/hydration.py,sha256=4yQMynZSloPFp0tlA7g8udWqE2TjZgfm19Y4R4F0s04,9415
|
236
236
|
prefect/utilities/schema_tools/validation.py,sha256=Wix26IVR-ZJ32-6MX2pHhrwm3reB-Q4iB6_phn85OKE,10743
|
237
|
-
prefect/workers/__init__.py,sha256=
|
237
|
+
prefect/workers/__init__.py,sha256=EaM1F0RZ-XIJaGeTKLsXDnfOPHzVWk5bk0_c4BVS44M,64
|
238
238
|
prefect/workers/base.py,sha256=nBv4pc51J1JRoSkgxvBDfQb4wIEN67D7cBVwT-jYHdI,49198
|
239
239
|
prefect/workers/block.py,sha256=qyyUMdiv5ndUIk-O8uwamESJGXXDQ_BmhKiLlm31ue0,286
|
240
240
|
prefect/workers/cloud.py,sha256=qyyUMdiv5ndUIk-O8uwamESJGXXDQ_BmhKiLlm31ue0,286
|
241
241
|
prefect/workers/process.py,sha256=tcJ3fbiraLCfpVGpv8dOHwMSfVzeD_kyguUOvPuIz6I,19796
|
242
242
|
prefect/workers/server.py,sha256=lgh2FfSuaNU7b6HPxSFm8JtKvAvHsZGkiOo4y4tW1Cw,2022
|
243
243
|
prefect/workers/utilities.py,sha256=VfPfAlGtTuDj0-Kb8WlMgAuOfgXCdrGAnKMapPSBrwc,2483
|
244
|
-
prefect_client-3.1.
|
245
|
-
prefect_client-3.1.
|
246
|
-
prefect_client-3.1.
|
247
|
-
prefect_client-3.1.
|
248
|
-
prefect_client-3.1.
|
244
|
+
prefect_client-3.1.10.dist-info/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
|
245
|
+
prefect_client-3.1.10.dist-info/METADATA,sha256=BbPdwx1OPrG1CxVh7OJNeBzquSMMMfOCBk4e-zilqhs,7287
|
246
|
+
prefect_client-3.1.10.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
|
247
|
+
prefect_client-3.1.10.dist-info/top_level.txt,sha256=MJZYJgFdbRc2woQCeB4vM6T33tr01TmkEhRcns6H_H4,8
|
248
|
+
prefect_client-3.1.10.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|