prefect-client 2.19.3__py3-none-any.whl → 3.0.0rc1__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/__init__.py +8 -56
- prefect/_internal/compatibility/deprecated.py +6 -115
- prefect/_internal/compatibility/experimental.py +4 -79
- prefect/_internal/concurrency/api.py +0 -34
- prefect/_internal/concurrency/calls.py +0 -6
- prefect/_internal/concurrency/cancellation.py +0 -3
- prefect/_internal/concurrency/event_loop.py +0 -20
- prefect/_internal/concurrency/inspection.py +3 -3
- prefect/_internal/concurrency/threads.py +35 -0
- prefect/_internal/concurrency/waiters.py +0 -28
- prefect/_internal/pydantic/__init__.py +0 -45
- prefect/_internal/pydantic/v1_schema.py +21 -22
- prefect/_internal/pydantic/v2_schema.py +0 -2
- prefect/_internal/pydantic/v2_validated_func.py +18 -23
- prefect/_internal/schemas/bases.py +44 -177
- prefect/_internal/schemas/fields.py +1 -43
- prefect/_internal/schemas/validators.py +60 -158
- prefect/artifacts.py +161 -14
- prefect/automations.py +39 -4
- prefect/blocks/abstract.py +1 -1
- prefect/blocks/core.py +268 -148
- prefect/blocks/fields.py +2 -57
- prefect/blocks/kubernetes.py +8 -12
- prefect/blocks/notifications.py +40 -20
- prefect/blocks/system.py +22 -11
- prefect/blocks/webhook.py +2 -9
- prefect/client/base.py +4 -4
- prefect/client/cloud.py +8 -13
- prefect/client/orchestration.py +347 -341
- prefect/client/schemas/actions.py +92 -86
- prefect/client/schemas/filters.py +20 -40
- prefect/client/schemas/objects.py +147 -145
- prefect/client/schemas/responses.py +16 -24
- prefect/client/schemas/schedules.py +47 -35
- prefect/client/subscriptions.py +2 -2
- prefect/client/utilities.py +5 -2
- prefect/concurrency/asyncio.py +3 -1
- prefect/concurrency/events.py +1 -1
- prefect/concurrency/services.py +6 -3
- prefect/context.py +195 -27
- prefect/deployments/__init__.py +5 -6
- prefect/deployments/base.py +7 -5
- prefect/deployments/flow_runs.py +185 -0
- prefect/deployments/runner.py +50 -45
- prefect/deployments/schedules.py +28 -23
- prefect/deployments/steps/__init__.py +0 -1
- prefect/deployments/steps/core.py +1 -0
- prefect/deployments/steps/pull.py +7 -21
- prefect/engine.py +12 -2422
- prefect/events/actions.py +17 -23
- prefect/events/cli/automations.py +19 -6
- prefect/events/clients.py +14 -37
- prefect/events/filters.py +14 -18
- prefect/events/related.py +2 -2
- prefect/events/schemas/__init__.py +0 -5
- prefect/events/schemas/automations.py +55 -46
- prefect/events/schemas/deployment_triggers.py +7 -197
- prefect/events/schemas/events.py +34 -65
- prefect/events/schemas/labelling.py +10 -14
- prefect/events/utilities.py +2 -3
- prefect/events/worker.py +2 -3
- prefect/filesystems.py +6 -517
- prefect/{new_flow_engine.py → flow_engine.py} +313 -72
- prefect/flow_runs.py +377 -5
- prefect/flows.py +248 -165
- prefect/futures.py +186 -345
- prefect/infrastructure/__init__.py +0 -27
- prefect/infrastructure/provisioners/__init__.py +5 -3
- prefect/infrastructure/provisioners/cloud_run.py +11 -6
- prefect/infrastructure/provisioners/container_instance.py +11 -7
- prefect/infrastructure/provisioners/ecs.py +6 -4
- prefect/infrastructure/provisioners/modal.py +8 -5
- prefect/input/actions.py +2 -4
- prefect/input/run_input.py +5 -7
- prefect/logging/formatters.py +0 -2
- prefect/logging/handlers.py +3 -11
- prefect/logging/loggers.py +2 -2
- prefect/manifests.py +2 -1
- prefect/records/__init__.py +1 -0
- prefect/records/result_store.py +42 -0
- prefect/records/store.py +9 -0
- prefect/results.py +43 -39
- prefect/runner/runner.py +9 -9
- prefect/runner/server.py +6 -10
- prefect/runner/storage.py +3 -8
- prefect/runner/submit.py +2 -2
- prefect/runner/utils.py +2 -2
- prefect/serializers.py +24 -35
- prefect/server/api/collections_data/views/aggregate-worker-metadata.json +5 -14
- prefect/settings.py +70 -133
- prefect/states.py +17 -47
- prefect/task_engine.py +697 -58
- prefect/task_runners.py +269 -301
- prefect/task_server.py +53 -34
- prefect/tasks.py +327 -337
- prefect/transactions.py +220 -0
- prefect/types/__init__.py +61 -82
- prefect/utilities/asyncutils.py +195 -136
- prefect/utilities/callables.py +121 -41
- prefect/utilities/collections.py +23 -38
- prefect/utilities/dispatch.py +11 -3
- prefect/utilities/dockerutils.py +4 -0
- prefect/utilities/engine.py +140 -20
- prefect/utilities/importtools.py +26 -27
- prefect/utilities/pydantic.py +128 -38
- prefect/utilities/schema_tools/hydration.py +5 -1
- prefect/utilities/templating.py +12 -2
- prefect/variables.py +78 -61
- prefect/workers/__init__.py +0 -1
- prefect/workers/base.py +15 -17
- prefect/workers/process.py +3 -8
- prefect/workers/server.py +2 -2
- {prefect_client-2.19.3.dist-info → prefect_client-3.0.0rc1.dist-info}/METADATA +22 -21
- prefect_client-3.0.0rc1.dist-info/RECORD +176 -0
- prefect/_internal/pydantic/_base_model.py +0 -51
- prefect/_internal/pydantic/_compat.py +0 -82
- prefect/_internal/pydantic/_flags.py +0 -20
- prefect/_internal/pydantic/_types.py +0 -8
- prefect/_internal/pydantic/utilities/__init__.py +0 -0
- prefect/_internal/pydantic/utilities/config_dict.py +0 -72
- prefect/_internal/pydantic/utilities/field_validator.py +0 -150
- prefect/_internal/pydantic/utilities/model_construct.py +0 -56
- prefect/_internal/pydantic/utilities/model_copy.py +0 -55
- prefect/_internal/pydantic/utilities/model_dump.py +0 -136
- prefect/_internal/pydantic/utilities/model_dump_json.py +0 -112
- prefect/_internal/pydantic/utilities/model_fields.py +0 -50
- prefect/_internal/pydantic/utilities/model_fields_set.py +0 -29
- prefect/_internal/pydantic/utilities/model_json_schema.py +0 -82
- prefect/_internal/pydantic/utilities/model_rebuild.py +0 -80
- prefect/_internal/pydantic/utilities/model_validate.py +0 -75
- prefect/_internal/pydantic/utilities/model_validate_json.py +0 -68
- prefect/_internal/pydantic/utilities/model_validator.py +0 -87
- prefect/_internal/pydantic/utilities/type_adapter.py +0 -71
- prefect/_vendor/__init__.py +0 -0
- prefect/_vendor/fastapi/__init__.py +0 -25
- prefect/_vendor/fastapi/applications.py +0 -946
- prefect/_vendor/fastapi/background.py +0 -3
- prefect/_vendor/fastapi/concurrency.py +0 -44
- prefect/_vendor/fastapi/datastructures.py +0 -58
- prefect/_vendor/fastapi/dependencies/__init__.py +0 -0
- prefect/_vendor/fastapi/dependencies/models.py +0 -64
- prefect/_vendor/fastapi/dependencies/utils.py +0 -877
- prefect/_vendor/fastapi/encoders.py +0 -177
- prefect/_vendor/fastapi/exception_handlers.py +0 -40
- prefect/_vendor/fastapi/exceptions.py +0 -46
- prefect/_vendor/fastapi/logger.py +0 -3
- prefect/_vendor/fastapi/middleware/__init__.py +0 -1
- prefect/_vendor/fastapi/middleware/asyncexitstack.py +0 -25
- prefect/_vendor/fastapi/middleware/cors.py +0 -3
- prefect/_vendor/fastapi/middleware/gzip.py +0 -3
- prefect/_vendor/fastapi/middleware/httpsredirect.py +0 -3
- prefect/_vendor/fastapi/middleware/trustedhost.py +0 -3
- prefect/_vendor/fastapi/middleware/wsgi.py +0 -3
- prefect/_vendor/fastapi/openapi/__init__.py +0 -0
- prefect/_vendor/fastapi/openapi/constants.py +0 -2
- prefect/_vendor/fastapi/openapi/docs.py +0 -203
- prefect/_vendor/fastapi/openapi/models.py +0 -480
- prefect/_vendor/fastapi/openapi/utils.py +0 -485
- prefect/_vendor/fastapi/param_functions.py +0 -340
- prefect/_vendor/fastapi/params.py +0 -453
- prefect/_vendor/fastapi/requests.py +0 -4
- prefect/_vendor/fastapi/responses.py +0 -40
- prefect/_vendor/fastapi/routing.py +0 -1331
- prefect/_vendor/fastapi/security/__init__.py +0 -15
- prefect/_vendor/fastapi/security/api_key.py +0 -98
- prefect/_vendor/fastapi/security/base.py +0 -6
- prefect/_vendor/fastapi/security/http.py +0 -172
- prefect/_vendor/fastapi/security/oauth2.py +0 -227
- prefect/_vendor/fastapi/security/open_id_connect_url.py +0 -34
- prefect/_vendor/fastapi/security/utils.py +0 -10
- prefect/_vendor/fastapi/staticfiles.py +0 -1
- prefect/_vendor/fastapi/templating.py +0 -3
- prefect/_vendor/fastapi/testclient.py +0 -1
- prefect/_vendor/fastapi/types.py +0 -3
- prefect/_vendor/fastapi/utils.py +0 -235
- prefect/_vendor/fastapi/websockets.py +0 -7
- prefect/_vendor/starlette/__init__.py +0 -1
- prefect/_vendor/starlette/_compat.py +0 -28
- prefect/_vendor/starlette/_exception_handler.py +0 -80
- prefect/_vendor/starlette/_utils.py +0 -88
- prefect/_vendor/starlette/applications.py +0 -261
- prefect/_vendor/starlette/authentication.py +0 -159
- prefect/_vendor/starlette/background.py +0 -43
- prefect/_vendor/starlette/concurrency.py +0 -59
- prefect/_vendor/starlette/config.py +0 -151
- prefect/_vendor/starlette/convertors.py +0 -87
- prefect/_vendor/starlette/datastructures.py +0 -707
- prefect/_vendor/starlette/endpoints.py +0 -130
- prefect/_vendor/starlette/exceptions.py +0 -60
- prefect/_vendor/starlette/formparsers.py +0 -276
- prefect/_vendor/starlette/middleware/__init__.py +0 -17
- prefect/_vendor/starlette/middleware/authentication.py +0 -52
- prefect/_vendor/starlette/middleware/base.py +0 -220
- prefect/_vendor/starlette/middleware/cors.py +0 -176
- prefect/_vendor/starlette/middleware/errors.py +0 -265
- prefect/_vendor/starlette/middleware/exceptions.py +0 -74
- prefect/_vendor/starlette/middleware/gzip.py +0 -113
- prefect/_vendor/starlette/middleware/httpsredirect.py +0 -19
- prefect/_vendor/starlette/middleware/sessions.py +0 -82
- prefect/_vendor/starlette/middleware/trustedhost.py +0 -64
- prefect/_vendor/starlette/middleware/wsgi.py +0 -147
- prefect/_vendor/starlette/requests.py +0 -328
- prefect/_vendor/starlette/responses.py +0 -347
- prefect/_vendor/starlette/routing.py +0 -933
- prefect/_vendor/starlette/schemas.py +0 -154
- prefect/_vendor/starlette/staticfiles.py +0 -248
- prefect/_vendor/starlette/status.py +0 -199
- prefect/_vendor/starlette/templating.py +0 -231
- prefect/_vendor/starlette/testclient.py +0 -804
- prefect/_vendor/starlette/types.py +0 -30
- prefect/_vendor/starlette/websockets.py +0 -193
- prefect/agent.py +0 -698
- prefect/deployments/deployments.py +0 -1042
- prefect/deprecated/__init__.py +0 -0
- prefect/deprecated/data_documents.py +0 -350
- prefect/deprecated/packaging/__init__.py +0 -12
- prefect/deprecated/packaging/base.py +0 -96
- prefect/deprecated/packaging/docker.py +0 -146
- prefect/deprecated/packaging/file.py +0 -92
- prefect/deprecated/packaging/orion.py +0 -80
- prefect/deprecated/packaging/serializers.py +0 -171
- prefect/events/instrument.py +0 -135
- prefect/infrastructure/base.py +0 -323
- prefect/infrastructure/container.py +0 -818
- prefect/infrastructure/kubernetes.py +0 -920
- prefect/infrastructure/process.py +0 -289
- prefect/new_task_engine.py +0 -423
- prefect/pydantic/__init__.py +0 -76
- prefect/pydantic/main.py +0 -39
- prefect/software/__init__.py +0 -2
- prefect/software/base.py +0 -50
- prefect/software/conda.py +0 -199
- prefect/software/pip.py +0 -122
- prefect/software/python.py +0 -52
- prefect/workers/block.py +0 -218
- prefect_client-2.19.3.dist-info/RECORD +0 -292
- {prefect_client-2.19.3.dist-info → prefect_client-3.0.0rc1.dist-info}/LICENSE +0 -0
- {prefect_client-2.19.3.dist-info → prefect_client-3.0.0rc1.dist-info}/WHEEL +0 -0
- {prefect_client-2.19.3.dist-info → prefect_client-3.0.0rc1.dist-info}/top_level.txt +0 -0
prefect/task_server.py
CHANGED
@@ -4,33 +4,30 @@ import os
|
|
4
4
|
import signal
|
5
5
|
import socket
|
6
6
|
import sys
|
7
|
+
from concurrent.futures import ThreadPoolExecutor
|
7
8
|
from contextlib import AsyncExitStack
|
8
|
-
from
|
9
|
-
from typing import List, Optional
|
9
|
+
from contextvars import copy_context
|
10
|
+
from typing import List, Optional
|
10
11
|
|
11
12
|
import anyio
|
13
|
+
import anyio.abc
|
12
14
|
from websockets.exceptions import InvalidStatusCode
|
13
15
|
|
14
16
|
from prefect import Task, get_client
|
15
17
|
from prefect._internal.concurrency.api import create_call, from_sync
|
16
18
|
from prefect.client.schemas.objects import TaskRun
|
17
19
|
from prefect.client.subscriptions import Subscription
|
18
|
-
from prefect.engine import emit_task_run_state_change_event, propose_state
|
19
20
|
from prefect.exceptions import Abort, PrefectHTTPStatusError
|
20
21
|
from prefect.logging.loggers import get_logger
|
21
22
|
from prefect.results import ResultFactory
|
22
23
|
from prefect.settings import (
|
23
24
|
PREFECT_API_URL,
|
24
|
-
PREFECT_EXPERIMENTAL_ENABLE_TASK_SCHEDULING,
|
25
25
|
PREFECT_TASK_SCHEDULING_DELETE_FAILED_SUBMISSIONS,
|
26
26
|
)
|
27
27
|
from prefect.states import Pending
|
28
|
-
from prefect.task_engine import
|
29
|
-
from prefect.task_runners import (
|
30
|
-
BaseTaskRunner,
|
31
|
-
ConcurrentTaskRunner,
|
32
|
-
)
|
28
|
+
from prefect.task_engine import run_task_async, run_task_sync
|
33
29
|
from prefect.utilities.asyncutils import asyncnullcontext, sync_compatible
|
30
|
+
from prefect.utilities.engine import emit_task_run_state_change_event, propose_state
|
34
31
|
from prefect.utilities.processutils import _register_signal
|
35
32
|
|
36
33
|
logger = get_logger("task_server")
|
@@ -64,18 +61,17 @@ class TaskServer:
|
|
64
61
|
Args:
|
65
62
|
- tasks: A list of tasks to serve. These tasks will be submitted to the engine
|
66
63
|
when a scheduled task run is found.
|
67
|
-
-
|
68
|
-
`
|
64
|
+
- limit: The maximum number of tasks that can be run concurrently. Defaults to 10.
|
65
|
+
Pass `None` to remove the limit.
|
69
66
|
"""
|
70
67
|
|
71
68
|
def __init__(
|
72
69
|
self,
|
73
70
|
*tasks: Task,
|
74
|
-
|
71
|
+
limit: Optional[int] = 10,
|
75
72
|
):
|
76
73
|
self.tasks: List[Task] = tasks
|
77
74
|
|
78
|
-
self.task_runner: BaseTaskRunner = task_runner or ConcurrentTaskRunner()
|
79
75
|
self.started: bool = False
|
80
76
|
self.stopping: bool = False
|
81
77
|
|
@@ -88,6 +84,8 @@ class TaskServer:
|
|
88
84
|
)
|
89
85
|
|
90
86
|
self._runs_task_group: anyio.abc.TaskGroup = anyio.create_task_group()
|
87
|
+
self._executor = ThreadPoolExecutor()
|
88
|
+
self._limiter = anyio.CapacityLimiter(limit) if limit else None
|
91
89
|
|
92
90
|
@property
|
93
91
|
def _client_id(self) -> str:
|
@@ -148,8 +146,10 @@ class TaskServer:
|
|
148
146
|
keys=[task.task_key for task in self.tasks],
|
149
147
|
client_id=self._client_id,
|
150
148
|
):
|
149
|
+
if self._limiter:
|
150
|
+
await self._limiter.acquire_on_behalf_of(task_run.id)
|
151
151
|
logger.info(f"Received task run: {task_run.id} - {task_run.name}")
|
152
|
-
|
152
|
+
self._runs_task_group.start_soon(self._submit_scheduled_task_run, task_run)
|
153
153
|
|
154
154
|
async def _submit_scheduled_task_run(self, task_run: TaskRun):
|
155
155
|
logger.debug(
|
@@ -171,12 +171,17 @@ class TaskServer:
|
|
171
171
|
# state_details. If there is no parameters_id, then the task was created
|
172
172
|
# without parameters.
|
173
173
|
parameters = {}
|
174
|
+
wait_for = []
|
175
|
+
run_context = None
|
174
176
|
if should_try_to_read_parameters(task, task_run):
|
175
177
|
parameters_id = task_run.state.state_details.task_parameters_id
|
176
178
|
task.persist_result = True
|
177
179
|
factory = await ResultFactory.from_autonomous_task(task)
|
178
180
|
try:
|
179
|
-
|
181
|
+
run_data = await factory.read_parameters(parameters_id)
|
182
|
+
parameters = run_data.get("parameters", {})
|
183
|
+
wait_for = run_data.get("wait_for", [])
|
184
|
+
run_context = run_data.get("context", None)
|
180
185
|
except Exception as exc:
|
181
186
|
logger.exception(
|
182
187
|
f"Failed to read parameters for task run {task_run.id!r}",
|
@@ -194,9 +199,11 @@ class TaskServer:
|
|
194
199
|
)
|
195
200
|
|
196
201
|
try:
|
202
|
+
new_state = Pending()
|
203
|
+
new_state.state_details.deferred = True
|
197
204
|
state = await propose_state(
|
198
205
|
client=get_client(), # TODO prove that we cannot use self._client here
|
199
|
-
state=
|
206
|
+
state=new_state,
|
200
207
|
task_run_id=task_run.id,
|
201
208
|
)
|
202
209
|
except Abort as exc:
|
@@ -225,20 +232,38 @@ class TaskServer:
|
|
225
232
|
validated_state=state,
|
226
233
|
)
|
227
234
|
|
228
|
-
|
229
|
-
|
230
|
-
submit_autonomous_task_run_to_engine,
|
235
|
+
if task.isasync:
|
236
|
+
await run_task_async(
|
231
237
|
task=task,
|
238
|
+
task_run_id=task_run.id,
|
232
239
|
task_run=task_run,
|
233
240
|
parameters=parameters,
|
234
|
-
|
235
|
-
|
241
|
+
wait_for=wait_for,
|
242
|
+
return_type="state",
|
243
|
+
context=run_context,
|
236
244
|
)
|
237
|
-
|
245
|
+
else:
|
246
|
+
context = copy_context()
|
247
|
+
future = self._executor.submit(
|
248
|
+
context.run,
|
249
|
+
run_task_sync,
|
250
|
+
task=task,
|
251
|
+
task_run_id=task_run.id,
|
252
|
+
task_run=task_run,
|
253
|
+
parameters=parameters,
|
254
|
+
wait_for=wait_for,
|
255
|
+
return_type="state",
|
256
|
+
context=run_context,
|
257
|
+
)
|
258
|
+
await asyncio.wrap_future(future)
|
259
|
+
if self._limiter:
|
260
|
+
self._limiter.release_on_behalf_of(task_run.id)
|
238
261
|
|
239
262
|
async def execute_task_run(self, task_run: TaskRun):
|
240
263
|
"""Execute a task run in the task server."""
|
241
264
|
async with self if not self.started else asyncnullcontext():
|
265
|
+
if self._limiter:
|
266
|
+
await self._limiter.acquire_on_behalf_of(task_run.id)
|
242
267
|
await self._submit_scheduled_task_run(task_run)
|
243
268
|
|
244
269
|
async def __aenter__(self):
|
@@ -248,8 +273,8 @@ class TaskServer:
|
|
248
273
|
self._client = get_client()
|
249
274
|
|
250
275
|
await self._exit_stack.enter_async_context(self._client)
|
251
|
-
await self._exit_stack.enter_async_context(self.
|
252
|
-
|
276
|
+
await self._exit_stack.enter_async_context(self._runs_task_group)
|
277
|
+
self._exit_stack.enter_context(self._executor)
|
253
278
|
|
254
279
|
self.started = True
|
255
280
|
return self
|
@@ -257,12 +282,11 @@ class TaskServer:
|
|
257
282
|
async def __aexit__(self, *exc_info):
|
258
283
|
logger.debug("Stopping task server...")
|
259
284
|
self.started = False
|
260
|
-
await self._runs_task_group.__aexit__(*exc_info)
|
261
285
|
await self._exit_stack.__aexit__(*exc_info)
|
262
286
|
|
263
287
|
|
264
288
|
@sync_compatible
|
265
|
-
async def serve(*tasks: Task,
|
289
|
+
async def serve(*tasks: Task, limit: Optional[int] = 10):
|
266
290
|
"""Serve the provided tasks so that their runs may be submitted to and executed.
|
267
291
|
in the engine. Tasks do not need to be within a flow run context to be submitted.
|
268
292
|
You must `.submit` the same task object that you pass to `serve`.
|
@@ -270,8 +294,8 @@ async def serve(*tasks: Task, task_runner: Optional[Type[BaseTaskRunner]] = None
|
|
270
294
|
Args:
|
271
295
|
- tasks: A list of tasks to serve. When a scheduled task run is found for a
|
272
296
|
given task, the task run will be submitted to the engine for execution.
|
273
|
-
-
|
274
|
-
`
|
297
|
+
- limit: The maximum number of tasks that can be run concurrently. Defaults to 10.
|
298
|
+
Pass `None` to remove the limit.
|
275
299
|
|
276
300
|
Example:
|
277
301
|
```python
|
@@ -291,13 +315,8 @@ async def serve(*tasks: Task, task_runner: Optional[Type[BaseTaskRunner]] = None
|
|
291
315
|
serve(say, yell)
|
292
316
|
```
|
293
317
|
"""
|
294
|
-
|
295
|
-
raise RuntimeError(
|
296
|
-
"To enable task scheduling, set PREFECT_EXPERIMENTAL_ENABLE_TASK_SCHEDULING"
|
297
|
-
" to True."
|
298
|
-
)
|
318
|
+
task_server = TaskServer(*tasks, limit=limit)
|
299
319
|
|
300
|
-
task_server = TaskServer(*tasks, task_runner=task_runner)
|
301
320
|
try:
|
302
321
|
await task_server.start()
|
303
322
|
|