prefect-client 3.1.10__py3-none-any.whl → 3.1.12__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/_experimental/lineage.py +7 -8
- prefect/_experimental/sla/__init__.py +0 -0
- prefect/_experimental/sla/client.py +66 -0
- prefect/_experimental/sla/objects.py +53 -0
- prefect/_internal/_logging.py +15 -3
- prefect/_internal/compatibility/async_dispatch.py +22 -16
- prefect/_internal/compatibility/deprecated.py +42 -18
- prefect/_internal/compatibility/migration.py +2 -2
- prefect/_internal/concurrency/inspection.py +12 -14
- prefect/_internal/concurrency/primitives.py +2 -2
- prefect/_internal/concurrency/services.py +154 -80
- prefect/_internal/concurrency/waiters.py +13 -9
- prefect/_internal/pydantic/annotations/pendulum.py +7 -7
- prefect/_internal/pytz.py +4 -3
- prefect/_internal/retries.py +10 -5
- prefect/_internal/schemas/bases.py +19 -10
- prefect/_internal/schemas/validators.py +227 -388
- prefect/_version.py +3 -3
- prefect/automations.py +236 -30
- prefect/blocks/__init__.py +3 -3
- prefect/blocks/abstract.py +53 -30
- prefect/blocks/core.py +183 -84
- prefect/blocks/notifications.py +133 -73
- prefect/blocks/redis.py +13 -9
- prefect/blocks/system.py +24 -11
- prefect/blocks/webhook.py +7 -5
- prefect/cache_policies.py +3 -2
- prefect/client/orchestration/__init__.py +1957 -0
- prefect/client/orchestration/_artifacts/__init__.py +0 -0
- prefect/client/orchestration/_artifacts/client.py +239 -0
- prefect/client/orchestration/_automations/__init__.py +0 -0
- prefect/client/orchestration/_automations/client.py +329 -0
- prefect/client/orchestration/_blocks_documents/__init__.py +0 -0
- prefect/client/orchestration/_blocks_documents/client.py +334 -0
- prefect/client/orchestration/_blocks_schemas/__init__.py +0 -0
- prefect/client/orchestration/_blocks_schemas/client.py +200 -0
- prefect/client/orchestration/_blocks_types/__init__.py +0 -0
- prefect/client/orchestration/_blocks_types/client.py +380 -0
- prefect/client/orchestration/_concurrency_limits/__init__.py +0 -0
- prefect/client/orchestration/_concurrency_limits/client.py +762 -0
- prefect/client/orchestration/_deployments/__init__.py +0 -0
- prefect/client/orchestration/_deployments/client.py +1128 -0
- prefect/client/orchestration/_flow_runs/__init__.py +0 -0
- prefect/client/orchestration/_flow_runs/client.py +903 -0
- prefect/client/orchestration/_flows/__init__.py +0 -0
- prefect/client/orchestration/_flows/client.py +343 -0
- prefect/client/orchestration/_logs/__init__.py +0 -0
- prefect/client/orchestration/_logs/client.py +97 -0
- prefect/client/orchestration/_variables/__init__.py +0 -0
- prefect/client/orchestration/_variables/client.py +157 -0
- prefect/client/orchestration/base.py +46 -0
- prefect/client/orchestration/routes.py +145 -0
- prefect/client/schemas/__init__.py +68 -28
- prefect/client/schemas/actions.py +2 -2
- prefect/client/schemas/filters.py +5 -0
- prefect/client/schemas/objects.py +8 -15
- prefect/client/schemas/schedules.py +22 -10
- prefect/concurrency/_asyncio.py +87 -0
- prefect/concurrency/{events.py → _events.py} +10 -10
- prefect/concurrency/asyncio.py +20 -104
- prefect/concurrency/context.py +6 -4
- prefect/concurrency/services.py +26 -74
- prefect/concurrency/sync.py +23 -44
- prefect/concurrency/v1/_asyncio.py +63 -0
- prefect/concurrency/v1/{events.py → _events.py} +13 -15
- prefect/concurrency/v1/asyncio.py +27 -80
- prefect/concurrency/v1/context.py +6 -4
- prefect/concurrency/v1/services.py +33 -79
- prefect/concurrency/v1/sync.py +18 -37
- prefect/context.py +66 -45
- prefect/deployments/base.py +10 -144
- prefect/deployments/flow_runs.py +12 -2
- prefect/deployments/runner.py +53 -4
- prefect/deployments/steps/pull.py +13 -0
- prefect/engine.py +17 -4
- prefect/events/clients.py +7 -1
- prefect/events/schemas/events.py +3 -2
- prefect/filesystems.py +6 -2
- prefect/flow_engine.py +101 -85
- prefect/flows.py +10 -1
- prefect/input/run_input.py +2 -1
- prefect/logging/logging.yml +1 -1
- prefect/main.py +1 -3
- prefect/results.py +2 -307
- prefect/runner/runner.py +4 -2
- prefect/runner/storage.py +87 -21
- prefect/serializers.py +32 -25
- prefect/settings/legacy.py +4 -4
- prefect/settings/models/api.py +3 -3
- prefect/settings/models/cli.py +3 -3
- prefect/settings/models/client.py +5 -3
- prefect/settings/models/cloud.py +8 -3
- prefect/settings/models/deployments.py +3 -3
- prefect/settings/models/experiments.py +4 -7
- prefect/settings/models/flows.py +3 -3
- prefect/settings/models/internal.py +4 -2
- prefect/settings/models/logging.py +4 -3
- prefect/settings/models/results.py +3 -3
- prefect/settings/models/root.py +3 -2
- prefect/settings/models/runner.py +4 -4
- prefect/settings/models/server/api.py +3 -3
- prefect/settings/models/server/database.py +11 -4
- prefect/settings/models/server/deployments.py +6 -2
- prefect/settings/models/server/ephemeral.py +4 -2
- prefect/settings/models/server/events.py +3 -2
- prefect/settings/models/server/flow_run_graph.py +6 -2
- prefect/settings/models/server/root.py +3 -3
- prefect/settings/models/server/services.py +26 -11
- prefect/settings/models/server/tasks.py +6 -3
- prefect/settings/models/server/ui.py +3 -3
- prefect/settings/models/tasks.py +5 -5
- prefect/settings/models/testing.py +3 -3
- prefect/settings/models/worker.py +5 -3
- prefect/settings/profiles.py +15 -2
- prefect/states.py +61 -45
- prefect/task_engine.py +54 -75
- prefect/task_runners.py +56 -55
- prefect/task_worker.py +2 -2
- prefect/tasks.py +90 -36
- prefect/telemetry/bootstrap.py +10 -9
- prefect/telemetry/run_telemetry.py +13 -8
- prefect/telemetry/services.py +4 -0
- prefect/transactions.py +4 -15
- prefect/utilities/_git.py +34 -0
- prefect/utilities/asyncutils.py +1 -1
- prefect/utilities/engine.py +3 -19
- prefect/utilities/generics.py +18 -0
- prefect/utilities/templating.py +25 -1
- prefect/workers/base.py +6 -3
- prefect/workers/process.py +1 -1
- {prefect_client-3.1.10.dist-info → prefect_client-3.1.12.dist-info}/METADATA +2 -2
- {prefect_client-3.1.10.dist-info → prefect_client-3.1.12.dist-info}/RECORD +135 -109
- prefect/client/orchestration.py +0 -4523
- prefect/records/__init__.py +0 -1
- prefect/records/base.py +0 -235
- prefect/records/filesystem.py +0 -213
- prefect/records/memory.py +0 -184
- prefect/records/result_store.py +0 -70
- {prefect_client-3.1.10.dist-info → prefect_client-3.1.12.dist-info}/LICENSE +0 -0
- {prefect_client-3.1.10.dist-info → prefect_client-3.1.12.dist-info}/WHEEL +0 -0
- {prefect_client-3.1.10.dist-info → prefect_client-3.1.12.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": "
|
11
|
+
"date": "2025-01-09T10:09:15-0800",
|
12
12
|
"dirty": true,
|
13
13
|
"error": null,
|
14
|
-
"full-revisionid": "
|
15
|
-
"version": "3.1.
|
14
|
+
"full-revisionid": "e299e5a781867735d62685e7c190b5d100a28b62",
|
15
|
+
"version": "3.1.12"
|
16
16
|
}
|
17
17
|
''' # END VERSION_JSON
|
18
18
|
|
prefect/automations.py
CHANGED
@@ -4,6 +4,7 @@ from uuid import UUID
|
|
4
4
|
from pydantic import Field
|
5
5
|
from typing_extensions import Self
|
6
6
|
|
7
|
+
from prefect._internal.compatibility.async_dispatch import async_dispatch
|
7
8
|
from prefect.client.orchestration import get_client
|
8
9
|
from prefect.events.actions import (
|
9
10
|
CallWebhook,
|
@@ -39,7 +40,6 @@ from prefect.events.schemas.automations import (
|
|
39
40
|
Trigger,
|
40
41
|
)
|
41
42
|
from prefect.exceptions import PrefectHTTPStatusError
|
42
|
-
from prefect.utilities.asyncutils import sync_compatible
|
43
43
|
|
44
44
|
__all__ = [
|
45
45
|
"AutomationCore",
|
@@ -78,11 +78,13 @@ __all__ = [
|
|
78
78
|
class Automation(AutomationCore):
|
79
79
|
id: Optional[UUID] = Field(default=None, description="The ID of this automation")
|
80
80
|
|
81
|
-
|
82
|
-
async def create(self: Self) -> Self:
|
81
|
+
async def acreate(self: Self) -> Self:
|
83
82
|
"""
|
84
|
-
|
83
|
+
Asynchronously create a new automation.
|
84
|
+
|
85
|
+
Examples:
|
85
86
|
|
87
|
+
```python
|
86
88
|
auto_to_create = Automation(
|
87
89
|
name="woodchonk",
|
88
90
|
trigger=EventTrigger(
|
@@ -97,20 +99,55 @@ class Automation(AutomationCore):
|
|
97
99
|
),
|
98
100
|
actions=[CancelFlowRun()]
|
99
101
|
)
|
100
|
-
created_automation = auto_to_create.
|
102
|
+
created_automation = await auto_to_create.acreate()
|
103
|
+
```
|
101
104
|
"""
|
102
105
|
async with get_client() as client:
|
103
106
|
automation = AutomationCore(**self.model_dump(exclude={"id"}))
|
104
107
|
self.id = await client.create_automation(automation=automation)
|
105
108
|
return self
|
106
109
|
|
107
|
-
@
|
108
|
-
|
110
|
+
@async_dispatch(acreate)
|
111
|
+
def create(self: Self) -> Self:
|
112
|
+
"""
|
113
|
+
Create a new automation.
|
114
|
+
|
115
|
+
Examples:
|
116
|
+
|
117
|
+
```python
|
118
|
+
auto_to_create = Automation(
|
119
|
+
name="woodchonk",
|
120
|
+
trigger=EventTrigger(
|
121
|
+
expect={"animal.walked"},
|
122
|
+
match={
|
123
|
+
"genus": "Marmota",
|
124
|
+
"species": "monax",
|
125
|
+
},
|
126
|
+
posture="Reactive",
|
127
|
+
threshold=3,
|
128
|
+
within=timedelta(seconds=10),
|
129
|
+
),
|
130
|
+
actions=[CancelFlowRun()]
|
131
|
+
)
|
132
|
+
created_automation = auto_to_create.create()
|
133
|
+
```
|
134
|
+
"""
|
135
|
+
with get_client(sync_client=True) as client:
|
136
|
+
automation = AutomationCore(**self.model_dump(exclude={"id"}))
|
137
|
+
self.id = client.create_automation(automation=automation)
|
138
|
+
return self
|
139
|
+
|
140
|
+
async def aupdate(self: Self):
|
109
141
|
"""
|
110
142
|
Updates an existing automation.
|
143
|
+
|
144
|
+
Examples:
|
145
|
+
|
146
|
+
```python
|
111
147
|
auto = Automation.read(id=123)
|
112
148
|
auto.name = "new name"
|
113
149
|
auto.update()
|
150
|
+
```
|
114
151
|
"""
|
115
152
|
assert self.id is not None
|
116
153
|
async with get_client() as client:
|
@@ -119,28 +156,51 @@ class Automation(AutomationCore):
|
|
119
156
|
)
|
120
157
|
await client.update_automation(automation_id=self.id, automation=automation)
|
121
158
|
|
159
|
+
@async_dispatch(aupdate)
|
160
|
+
def update(self: Self):
|
161
|
+
"""
|
162
|
+
Updates an existing automation.
|
163
|
+
|
164
|
+
Examples:
|
165
|
+
|
166
|
+
|
167
|
+
```python
|
168
|
+
auto = Automation.read(id=123)
|
169
|
+
auto.name = "new name"
|
170
|
+
auto.update()
|
171
|
+
```
|
172
|
+
"""
|
173
|
+
assert self.id is not None
|
174
|
+
with get_client(sync_client=True) as client:
|
175
|
+
automation = AutomationCore(
|
176
|
+
**self.model_dump(exclude={"id", "owner_resource"})
|
177
|
+
)
|
178
|
+
client.update_automation(automation_id=self.id, automation=automation)
|
179
|
+
|
122
180
|
@overload
|
123
181
|
@classmethod
|
124
|
-
async def
|
182
|
+
async def aread(cls, id: UUID, name: Optional[str] = ...) -> Self:
|
125
183
|
...
|
126
184
|
|
127
185
|
@overload
|
128
186
|
@classmethod
|
129
|
-
async def
|
187
|
+
async def aread(cls, id: None = None, name: str = ...) -> Self:
|
130
188
|
...
|
131
189
|
|
132
190
|
@classmethod
|
133
|
-
|
134
|
-
async def read(
|
135
|
-
cls, id: Optional[UUID] = None, name: Optional[str] = None
|
136
|
-
) -> Optional[Self]:
|
191
|
+
async def aread(cls, id: Optional[UUID] = None, name: Optional[str] = None) -> Self:
|
137
192
|
"""
|
138
|
-
|
139
|
-
automation = Automation.read(name="woodchonk")
|
193
|
+
Asynchronously read an automation by ID or name.
|
140
194
|
|
141
|
-
|
195
|
+
Examples:
|
142
196
|
|
143
|
-
|
197
|
+
```python
|
198
|
+
automation = await Automation.aread(name="woodchonk")
|
199
|
+
```
|
200
|
+
|
201
|
+
```python
|
202
|
+
automation = await Automation.aread(id=UUID("b3514963-02b1-47a5-93d1-6eeb131041cb"))
|
203
|
+
```
|
144
204
|
"""
|
145
205
|
if id and name:
|
146
206
|
raise ValueError("Only one of id or name can be provided")
|
@@ -162,15 +222,68 @@ class Automation(AutomationCore):
|
|
162
222
|
assert name is not None
|
163
223
|
automation = await client.read_automations_by_name(name=name)
|
164
224
|
if len(automation) > 0:
|
165
|
-
return cls(**automation[0].model_dump())
|
166
|
-
|
167
|
-
raise ValueError(f"Automation with name {name!r} not found")
|
225
|
+
return cls(**automation[0].model_dump())
|
226
|
+
raise ValueError(f"Automation with name {name!r} not found")
|
168
227
|
|
169
|
-
@
|
170
|
-
|
228
|
+
@overload
|
229
|
+
@classmethod
|
230
|
+
async def read(cls, id: UUID, name: Optional[str] = ...) -> Self:
|
231
|
+
...
|
232
|
+
|
233
|
+
@overload
|
234
|
+
@classmethod
|
235
|
+
async def read(cls, id: None = None, name: str = ...) -> Self:
|
236
|
+
...
|
237
|
+
|
238
|
+
@classmethod
|
239
|
+
@async_dispatch(aread)
|
240
|
+
def read(cls, id: Optional[UUID] = None, name: Optional[str] = None) -> Self:
|
171
241
|
"""
|
242
|
+
Read an automation by ID or name.
|
243
|
+
|
244
|
+
Examples:
|
245
|
+
|
246
|
+
```python
|
247
|
+
automation = Automation.read(name="woodchonk")
|
248
|
+
```
|
249
|
+
|
250
|
+
```python
|
251
|
+
automation = Automation.read(id=UUID("b3514963-02b1-47a5-93d1-6eeb131041cb"))
|
252
|
+
```
|
253
|
+
"""
|
254
|
+
if id and name:
|
255
|
+
raise ValueError("Only one of id or name can be provided")
|
256
|
+
if not id and not name:
|
257
|
+
raise ValueError("One of id or name must be provided")
|
258
|
+
with get_client(sync_client=True) as client:
|
259
|
+
if id:
|
260
|
+
try:
|
261
|
+
automation = client.read_automation(automation_id=id)
|
262
|
+
except PrefectHTTPStatusError as exc:
|
263
|
+
if exc.response.status_code == 404:
|
264
|
+
raise ValueError(f"Automation with ID {id!r} not found")
|
265
|
+
raise
|
266
|
+
if automation is None:
|
267
|
+
raise ValueError(f"Automation with ID {id!r} not found")
|
268
|
+
return cls(**automation.model_dump())
|
269
|
+
else:
|
270
|
+
if TYPE_CHECKING:
|
271
|
+
assert name is not None
|
272
|
+
automation = client.read_automations_by_name(name=name)
|
273
|
+
if len(automation) > 0:
|
274
|
+
return cls(**automation[0].model_dump())
|
275
|
+
raise ValueError(f"Automation with name {name!r} not found")
|
276
|
+
|
277
|
+
async def adelete(self: Self) -> bool:
|
278
|
+
"""
|
279
|
+
Asynchronously delete an automation.
|
280
|
+
|
281
|
+
Examples:
|
282
|
+
|
283
|
+
```python
|
172
284
|
auto = Automation.read(id = 123)
|
173
|
-
auto.
|
285
|
+
await auto.adelete()
|
286
|
+
```
|
174
287
|
"""
|
175
288
|
if self.id is None:
|
176
289
|
raise ValueError("Can't delete an automation without an id")
|
@@ -184,38 +297,131 @@ class Automation(AutomationCore):
|
|
184
297
|
return False
|
185
298
|
raise
|
186
299
|
|
187
|
-
@
|
188
|
-
|
300
|
+
@async_dispatch(adelete)
|
301
|
+
def delete(self: Self) -> bool:
|
302
|
+
"""
|
303
|
+
Delete an automation.
|
304
|
+
|
305
|
+
Examples:
|
306
|
+
|
307
|
+
```python
|
308
|
+
auto = Automation.read(id = 123)
|
309
|
+
auto.delete()
|
310
|
+
```
|
311
|
+
"""
|
312
|
+
if self.id is None:
|
313
|
+
raise ValueError("Can't delete an automation without an id")
|
314
|
+
|
315
|
+
with get_client(sync_client=True) as client:
|
316
|
+
try:
|
317
|
+
client.delete_automation(self.id)
|
318
|
+
return True
|
319
|
+
except PrefectHTTPStatusError as exc:
|
320
|
+
if exc.response.status_code == 404:
|
321
|
+
return False
|
322
|
+
raise
|
323
|
+
|
324
|
+
async def adisable(self: Self) -> bool:
|
325
|
+
"""
|
326
|
+
Asynchronously disable an automation.
|
327
|
+
|
328
|
+
Raises:
|
329
|
+
ValueError: If the automation does not have an id
|
330
|
+
PrefectHTTPStatusError: If the automation cannot be disabled
|
331
|
+
|
332
|
+
Example:
|
333
|
+
```python
|
334
|
+
auto = await Automation.aread(id = 123)
|
335
|
+
await auto.adisable()
|
336
|
+
```
|
337
|
+
"""
|
338
|
+
if self.id is None:
|
339
|
+
raise ValueError("Can't disable an automation without an id")
|
340
|
+
|
341
|
+
async with get_client() as client:
|
342
|
+
try:
|
343
|
+
await client.pause_automation(self.id)
|
344
|
+
return True
|
345
|
+
except PrefectHTTPStatusError as exc:
|
346
|
+
if exc.response.status_code == 404:
|
347
|
+
return False
|
348
|
+
raise
|
349
|
+
|
350
|
+
@async_dispatch(adisable)
|
351
|
+
def disable(self: Self) -> bool:
|
189
352
|
"""
|
190
353
|
Disable an automation.
|
354
|
+
|
355
|
+
|
356
|
+
Raises:
|
357
|
+
ValueError: If the automation does not have an id
|
358
|
+
PrefectHTTPStatusError: If the automation cannot be disabled
|
359
|
+
|
360
|
+
Example:
|
361
|
+
```python
|
191
362
|
auto = Automation.read(id = 123)
|
192
363
|
auto.disable()
|
364
|
+
```
|
193
365
|
"""
|
194
366
|
if self.id is None:
|
195
367
|
raise ValueError("Can't disable an automation without an id")
|
196
368
|
|
369
|
+
with get_client(sync_client=True) as client:
|
370
|
+
try:
|
371
|
+
client.pause_automation(self.id)
|
372
|
+
return True
|
373
|
+
except PrefectHTTPStatusError as exc:
|
374
|
+
if exc.response.status_code == 404:
|
375
|
+
return False
|
376
|
+
raise
|
377
|
+
|
378
|
+
async def aenable(self: Self) -> bool:
|
379
|
+
"""
|
380
|
+
Asynchronously enable an automation.
|
381
|
+
|
382
|
+
Raises:
|
383
|
+
ValueError: If the automation does not have an id
|
384
|
+
PrefectHTTPStatusError: If the automation cannot be enabled
|
385
|
+
|
386
|
+
Example:
|
387
|
+
```python
|
388
|
+
auto = await Automation.aread(id = 123)
|
389
|
+
await auto.aenable()
|
390
|
+
```
|
391
|
+
"""
|
392
|
+
if self.id is None:
|
393
|
+
raise ValueError("Can't enable an automation without an id")
|
394
|
+
|
197
395
|
async with get_client() as client:
|
198
396
|
try:
|
199
|
-
await client.
|
397
|
+
await client.resume_automation(self.id)
|
200
398
|
return True
|
201
399
|
except PrefectHTTPStatusError as exc:
|
202
400
|
if exc.response.status_code == 404:
|
203
401
|
return False
|
204
402
|
raise
|
205
403
|
|
206
|
-
@
|
207
|
-
|
404
|
+
@async_dispatch(aenable)
|
405
|
+
def enable(self: Self) -> bool:
|
208
406
|
"""
|
209
407
|
Enable an automation.
|
408
|
+
|
409
|
+
Raises:
|
410
|
+
ValueError: If the automation does not have an id
|
411
|
+
PrefectHTTPStatusError: If the automation cannot be enabled
|
412
|
+
|
413
|
+
Example:
|
414
|
+
```python
|
210
415
|
auto = Automation.read(id = 123)
|
211
416
|
auto.enable()
|
417
|
+
```
|
212
418
|
"""
|
213
419
|
if self.id is None:
|
214
420
|
raise ValueError("Can't enable an automation without an id")
|
215
421
|
|
216
|
-
|
422
|
+
with get_client(sync_client=True) as client:
|
217
423
|
try:
|
218
|
-
|
424
|
+
client.resume_automation(self.id)
|
219
425
|
return True
|
220
426
|
except PrefectHTTPStatusError as exc:
|
221
427
|
if exc.response.status_code == 404:
|
prefect/blocks/__init__.py
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# ensure core blocks are registered
|
2
2
|
|
3
|
-
import prefect.blocks.notifications
|
4
|
-
import prefect.blocks.system
|
5
|
-
import prefect.blocks.webhook
|
3
|
+
import prefect.blocks.notifications as notifications
|
4
|
+
import prefect.blocks.system as system
|
5
|
+
import prefect.blocks.webhook as webhook
|
6
6
|
|
7
7
|
__all__ = ["notifications", "system", "webhook"]
|
prefect/blocks/abstract.py
CHANGED
@@ -1,16 +1,16 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
import logging
|
4
|
+
import sys
|
1
5
|
from abc import ABC, abstractmethod
|
2
6
|
from contextlib import contextmanager
|
3
|
-
from logging import Logger
|
7
|
+
from logging import Logger
|
4
8
|
from pathlib import Path
|
5
9
|
from typing import (
|
6
10
|
Any,
|
7
11
|
BinaryIO,
|
8
|
-
Dict,
|
9
12
|
Generator,
|
10
13
|
Generic,
|
11
|
-
List,
|
12
|
-
Optional,
|
13
|
-
Tuple,
|
14
14
|
TypeVar,
|
15
15
|
Union,
|
16
16
|
)
|
@@ -23,7 +23,12 @@ from prefect.logging.loggers import get_logger, get_run_logger
|
|
23
23
|
|
24
24
|
T = TypeVar("T")
|
25
25
|
|
26
|
-
|
26
|
+
if sys.version_info >= (3, 12):
|
27
|
+
LoggingAdapter = logging.LoggerAdapter[logging.Logger]
|
28
|
+
else:
|
29
|
+
LoggingAdapter = logging.LoggerAdapter
|
30
|
+
|
31
|
+
LoggerOrAdapter: TypeAlias = Union[Logger, LoggingAdapter]
|
27
32
|
|
28
33
|
|
29
34
|
class CredentialsBlock(Block, ABC):
|
@@ -52,7 +57,7 @@ class CredentialsBlock(Block, ABC):
|
|
52
57
|
return get_logger(self.__class__.__name__)
|
53
58
|
|
54
59
|
@abstractmethod
|
55
|
-
def get_client(self, *args, **kwargs):
|
60
|
+
def get_client(self, *args: Any, **kwargs: Any) -> Any:
|
56
61
|
"""
|
57
62
|
Returns a client for interacting with the external system.
|
58
63
|
|
@@ -94,7 +99,7 @@ class NotificationBlock(Block, ABC):
|
|
94
99
|
return get_logger(self.__class__.__name__)
|
95
100
|
|
96
101
|
@abstractmethod
|
97
|
-
async def notify(self, body: str, subject:
|
102
|
+
async def notify(self, body: str, subject: str | None = None) -> None:
|
98
103
|
"""
|
99
104
|
Send a notification.
|
100
105
|
|
@@ -153,7 +158,7 @@ class JobRun(ABC, Generic[T]): # not a block
|
|
153
158
|
"""
|
154
159
|
|
155
160
|
|
156
|
-
class JobBlock(Block, ABC):
|
161
|
+
class JobBlock(Block, ABC, Generic[T]):
|
157
162
|
"""
|
158
163
|
Block that represents an entity in an external service
|
159
164
|
that can trigger a long running execution.
|
@@ -176,7 +181,7 @@ class JobBlock(Block, ABC):
|
|
176
181
|
return get_logger(self.__class__.__name__)
|
177
182
|
|
178
183
|
@abstractmethod
|
179
|
-
async def trigger(self) -> JobRun:
|
184
|
+
async def trigger(self) -> JobRun[T]:
|
180
185
|
"""
|
181
186
|
Triggers a job run in an external service and returns a JobRun object
|
182
187
|
to track the execution of the run.
|
@@ -221,8 +226,11 @@ class DatabaseBlock(Block, ABC):
|
|
221
226
|
|
222
227
|
@abstractmethod
|
223
228
|
async def fetch_one(
|
224
|
-
self,
|
225
|
-
|
229
|
+
self,
|
230
|
+
operation: str,
|
231
|
+
parameters: dict[str, Any] | None = None,
|
232
|
+
**execution_kwargs: Any,
|
233
|
+
) -> tuple[Any, ...]:
|
226
234
|
"""
|
227
235
|
Fetch a single result from the database.
|
228
236
|
|
@@ -238,8 +246,12 @@ class DatabaseBlock(Block, ABC):
|
|
238
246
|
|
239
247
|
@abstractmethod
|
240
248
|
async def fetch_many(
|
241
|
-
self,
|
242
|
-
|
249
|
+
self,
|
250
|
+
operation: str,
|
251
|
+
parameters: dict[str, Any] | None = None,
|
252
|
+
size: int | None = None,
|
253
|
+
**execution_kwargs: Any,
|
254
|
+
) -> list[tuple[Any, ...]]:
|
243
255
|
"""
|
244
256
|
Fetch a limited number of results from the database.
|
245
257
|
|
@@ -256,8 +268,11 @@ class DatabaseBlock(Block, ABC):
|
|
256
268
|
|
257
269
|
@abstractmethod
|
258
270
|
async def fetch_all(
|
259
|
-
self,
|
260
|
-
|
271
|
+
self,
|
272
|
+
operation: str,
|
273
|
+
parameters: dict[str, Any] | None = None,
|
274
|
+
**execution_kwargs: Any,
|
275
|
+
) -> list[tuple[Any, ...]]:
|
261
276
|
"""
|
262
277
|
Fetch all results from the database.
|
263
278
|
|
@@ -272,7 +287,12 @@ class DatabaseBlock(Block, ABC):
|
|
272
287
|
"""
|
273
288
|
|
274
289
|
@abstractmethod
|
275
|
-
async def execute(
|
290
|
+
async def execute(
|
291
|
+
self,
|
292
|
+
operation: str,
|
293
|
+
parameters: dict[str, Any] | None = None,
|
294
|
+
**execution_kwargs: Any,
|
295
|
+
) -> None:
|
276
296
|
"""
|
277
297
|
Executes an operation on the database. This method is intended to be used
|
278
298
|
for operations that do not return data, such as INSERT, UPDATE, or DELETE.
|
@@ -285,7 +305,10 @@ class DatabaseBlock(Block, ABC):
|
|
285
305
|
|
286
306
|
@abstractmethod
|
287
307
|
async def execute_many(
|
288
|
-
self,
|
308
|
+
self,
|
309
|
+
operation: str,
|
310
|
+
seq_of_parameters: list[dict[str, Any]],
|
311
|
+
**execution_kwargs: Any,
|
289
312
|
) -> None:
|
290
313
|
"""
|
291
314
|
Executes multiple operations on the database. This method is intended to be used
|
@@ -307,7 +330,7 @@ class DatabaseBlock(Block, ABC):
|
|
307
330
|
f"{self.__class__.__name__} does not support async context management."
|
308
331
|
)
|
309
332
|
|
310
|
-
async def __aexit__(self, *args) -> None:
|
333
|
+
async def __aexit__(self, *args: Any) -> None:
|
311
334
|
"""
|
312
335
|
Context management method for async databases.
|
313
336
|
"""
|
@@ -323,7 +346,7 @@ class DatabaseBlock(Block, ABC):
|
|
323
346
|
f"{self.__class__.__name__} does not support context management."
|
324
347
|
)
|
325
348
|
|
326
|
-
def __exit__(self, *args) -> None:
|
349
|
+
def __exit__(self, *args: Any) -> None:
|
327
350
|
"""
|
328
351
|
Context management method for databases.
|
329
352
|
"""
|
@@ -358,8 +381,8 @@ class ObjectStorageBlock(Block, ABC):
|
|
358
381
|
async def download_object_to_path(
|
359
382
|
self,
|
360
383
|
from_path: str,
|
361
|
-
to_path:
|
362
|
-
**download_kwargs:
|
384
|
+
to_path: str | Path,
|
385
|
+
**download_kwargs: Any,
|
363
386
|
) -> Path:
|
364
387
|
"""
|
365
388
|
Downloads an object from the object storage service to a path.
|
@@ -378,7 +401,7 @@ class ObjectStorageBlock(Block, ABC):
|
|
378
401
|
self,
|
379
402
|
from_path: str,
|
380
403
|
to_file_object: BinaryIO,
|
381
|
-
**download_kwargs:
|
404
|
+
**download_kwargs: Any,
|
382
405
|
) -> BinaryIO:
|
383
406
|
"""
|
384
407
|
Downloads an object from the object storage service to a file-like object,
|
@@ -397,8 +420,8 @@ class ObjectStorageBlock(Block, ABC):
|
|
397
420
|
async def download_folder_to_path(
|
398
421
|
self,
|
399
422
|
from_folder: str,
|
400
|
-
to_folder:
|
401
|
-
**download_kwargs:
|
423
|
+
to_folder: str | Path,
|
424
|
+
**download_kwargs: Any,
|
402
425
|
) -> Path:
|
403
426
|
"""
|
404
427
|
Downloads a folder from the object storage service to a path.
|
@@ -414,7 +437,7 @@ class ObjectStorageBlock(Block, ABC):
|
|
414
437
|
|
415
438
|
@abstractmethod
|
416
439
|
async def upload_from_path(
|
417
|
-
self, from_path:
|
440
|
+
self, from_path: str | Path, to_path: str, **upload_kwargs: Any
|
418
441
|
) -> str:
|
419
442
|
"""
|
420
443
|
Uploads an object from a path to the object storage service.
|
@@ -430,7 +453,7 @@ class ObjectStorageBlock(Block, ABC):
|
|
430
453
|
|
431
454
|
@abstractmethod
|
432
455
|
async def upload_from_file_object(
|
433
|
-
self, from_file_object: BinaryIO, to_path: str, **upload_kwargs:
|
456
|
+
self, from_file_object: BinaryIO, to_path: str, **upload_kwargs: Any
|
434
457
|
) -> str:
|
435
458
|
"""
|
436
459
|
Uploads an object to the object storage service from a file-like object,
|
@@ -448,9 +471,9 @@ class ObjectStorageBlock(Block, ABC):
|
|
448
471
|
@abstractmethod
|
449
472
|
async def upload_from_folder(
|
450
473
|
self,
|
451
|
-
from_folder:
|
474
|
+
from_folder: str | Path,
|
452
475
|
to_folder: str,
|
453
|
-
**upload_kwargs:
|
476
|
+
**upload_kwargs: Any,
|
454
477
|
) -> str:
|
455
478
|
"""
|
456
479
|
Uploads a folder to the object storage service from a path.
|
@@ -496,7 +519,7 @@ class SecretBlock(Block, ABC):
|
|
496
519
|
"""
|
497
520
|
|
498
521
|
@abstractmethod
|
499
|
-
async def write_secret(self, secret_data) -> str:
|
522
|
+
async def write_secret(self, secret_data: bytes) -> str:
|
500
523
|
"""
|
501
524
|
Writes secret data to the configured secret in the secret storage service.
|
502
525
|
|