prefect-client 3.2.8__py3-none-any.whl → 3.2.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/_build_info.py CHANGED
@@ -1,5 +1,5 @@
1
1
  # Generated by versioningit
2
- __version__ = "3.2.8"
3
- __build_date__ = "2025-02-28 00:11:08.300212+00:00"
4
- __git_commit__ = "2c0860d5dcd6156fc3fae75d53f7f48f4bd1a522"
2
+ __version__ = "3.2.10"
3
+ __build_date__ = "2025-03-05 18:07:05.465362+00:00"
4
+ __git_commit__ = "3a61a72641ef7ba00d874f725351b1017927a247"
5
5
  __dirty__ = False
@@ -11,7 +11,6 @@ import sys
11
11
  from typing import Any, TypedDict
12
12
 
13
13
  import cloudpickle
14
- import uv
15
14
 
16
15
  from prefect.client.schemas.objects import FlowRun
17
16
  from prefect.context import SettingsContext, get_settings_context, serialize_context
@@ -22,6 +21,13 @@ from prefect.settings.context import get_current_settings
22
21
  from prefect.settings.models.root import Settings
23
22
  from prefect.utilities.slugify import slugify
24
23
 
24
+ try:
25
+ import uv
26
+
27
+ uv_path = uv.find_uv_bin()
28
+ except (ImportError, ModuleNotFoundError):
29
+ uv_path = "uv"
30
+
25
31
 
26
32
  class SerializedBundle(TypedDict):
27
33
  """
@@ -73,7 +79,7 @@ def create_bundle_for_flow_run(
73
79
  "flow_run": flow_run.model_dump(mode="json"),
74
80
  "dependencies": subprocess.check_output(
75
81
  [
76
- uv.find_uv_bin(),
82
+ uv_path,
77
83
  "pip",
78
84
  "freeze",
79
85
  # Exclude editable installs because we won't be able to install them in the execution environment
@@ -148,7 +154,7 @@ def execute_bundle_in_subprocess(
148
154
  # Install dependencies if necessary
149
155
  if dependencies := bundle.get("dependencies"):
150
156
  subprocess.check_call(
151
- [uv.find_uv_bin(), "pip", "install", *dependencies.split("\n")],
157
+ [uv_path, "pip", "install", *dependencies.split("\n")],
152
158
  # Copy the current environment to ensure we install into the correct venv
153
159
  env=os.environ,
154
160
  )
@@ -3,6 +3,8 @@ from typing import TYPE_CHECKING, Any, Iterable, Optional, Union
3
3
  from uuid import UUID
4
4
 
5
5
  import anyio
6
+ from opentelemetry import trace
7
+ from opentelemetry.instrumentation.utils import is_instrumentation_enabled
6
8
 
7
9
  import prefect
8
10
  from prefect._result_records import ResultRecordMetadata
@@ -12,9 +14,7 @@ from prefect.context import FlowRunContext, TaskRunContext
12
14
  from prefect.logging import get_logger
13
15
  from prefect.states import Pending, Scheduled
14
16
  from prefect.tasks import Task
15
- from prefect.telemetry.run_telemetry import (
16
- LABELS_TRACEPARENT_KEY,
17
- )
17
+ from prefect.telemetry.run_telemetry import LABELS_TRACEPARENT_KEY, RunTelemetry
18
18
  from prefect.types._datetime import now
19
19
  from prefect.utilities.asyncutils import sync_compatible
20
20
  from prefect.utilities.slugify import slugify
@@ -164,6 +164,8 @@ async def run_deployment(
164
164
 
165
165
  if flow_run_ctx and flow_run_ctx.flow_run:
166
166
  traceparent = flow_run_ctx.flow_run.labels.get(LABELS_TRACEPARENT_KEY)
167
+ elif is_instrumentation_enabled():
168
+ traceparent = RunTelemetry.traceparent_from_span(span=trace.get_current_span())
167
169
  else:
168
170
  traceparent = None
169
171
 
prefect/events/clients.py CHANGED
@@ -21,6 +21,7 @@ from urllib.parse import urlparse
21
21
  from urllib.request import proxy_bypass
22
22
  from uuid import UUID
23
23
 
24
+ import certifi
24
25
  import orjson
25
26
  from cachetools import TTLCache
26
27
  from prometheus_client import Counter
@@ -38,6 +39,7 @@ from prefect.events import Event
38
39
  from prefect.logging import get_logger
39
40
  from prefect.settings import (
40
41
  PREFECT_API_KEY,
42
+ PREFECT_API_SSL_CERT_FILE,
41
43
  PREFECT_API_TLS_INSECURE_SKIP_VERIFY,
42
44
  PREFECT_API_URL,
43
45
  PREFECT_CLOUD_API_URL,
@@ -123,12 +125,19 @@ class WebsocketProxyConnect(connect):
123
125
  self._host = host
124
126
  self._port = port
125
127
 
126
- if PREFECT_API_TLS_INSECURE_SKIP_VERIFY:
128
+ if PREFECT_API_TLS_INSECURE_SKIP_VERIFY and u.scheme == "wss":
127
129
  # Create an unverified context for insecure connections
128
130
  ctx = ssl.create_default_context()
129
131
  ctx.check_hostname = False
130
132
  ctx.verify_mode = ssl.CERT_NONE
131
133
  self._kwargs.setdefault("ssl", ctx)
134
+ elif u.scheme == "wss":
135
+ cert_file = PREFECT_API_SSL_CERT_FILE.value()
136
+ if not cert_file:
137
+ cert_file = certifi.where()
138
+ # Create a verified context with the certificate file
139
+ ctx = ssl.create_default_context(cafile=cert_file)
140
+ self._kwargs.setdefault("ssl", ctx)
132
141
 
133
142
  async def _proxy_connect(self: Self) -> ClientConnection:
134
143
  if self._proxy:
prefect/flows.py CHANGED
@@ -2162,6 +2162,14 @@ def serve(
2162
2162
 
2163
2163
  runner = Runner(pause_on_shutdown=pause_on_shutdown, limit=limit, **kwargs)
2164
2164
  for deployment in args:
2165
+ if deployment.work_pool_name:
2166
+ warnings.warn(
2167
+ "Work pools are not necessary for served deployments - "
2168
+ "the `work_pool_name` argument will be ignored. Omit the "
2169
+ f"`work_pool_name` argument from `to_deployment` for {deployment.name!r}.",
2170
+ UserWarning,
2171
+ )
2172
+ deployment.work_pool_name = None
2165
2173
  runner.add_deployment(deployment)
2166
2174
 
2167
2175
  if print_starting_message:
prefect/runner/runner.py CHANGED
@@ -108,18 +108,20 @@ from prefect.settings import (
108
108
  get_current_settings,
109
109
  )
110
110
  from prefect.states import (
111
+ AwaitingRetry,
111
112
  Crashed,
112
113
  Pending,
113
114
  exception_to_failed_state,
114
115
  )
115
116
  from prefect.types._datetime import DateTime
116
117
  from prefect.types.entrypoint import EntrypointType
118
+ from prefect.utilities.annotations import NotSet
117
119
  from prefect.utilities.asyncutils import (
118
120
  asyncnullcontext,
119
121
  is_async_fn,
120
122
  sync_compatible,
121
123
  )
122
- from prefect.utilities.engine import propose_state
124
+ from prefect.utilities.engine import propose_state, propose_state_sync
123
125
  from prefect.utilities.processutils import (
124
126
  get_sys_executable,
125
127
  run_process,
@@ -153,7 +155,7 @@ class Runner:
153
155
  query_seconds: Optional[float] = None,
154
156
  prefetch_seconds: float = 10,
155
157
  heartbeat_seconds: Optional[float] = None,
156
- limit: Optional[int] = None,
158
+ limit: int | type[NotSet] | None = NotSet,
157
159
  pause_on_shutdown: bool = True,
158
160
  webserver: bool = False,
159
161
  ):
@@ -169,7 +171,8 @@ class Runner:
169
171
  heartbeat_seconds: The number of seconds to wait between emitting
170
172
  flow run heartbeats. The runner will not emit heartbeats if the value is None.
171
173
  Defaults to `PREFECT_RUNNER_HEARTBEAT_FREQUENCY`.
172
- limit: The maximum number of flow runs this runner should be running at
174
+ limit: The maximum number of flow runs this runner should be running at. Provide `None` for no limit.
175
+ If not provided, the runner will use the value of `PREFECT_RUNNER_PROCESS_LIMIT`.
173
176
  pause_on_shutdown: A boolean for whether or not to automatically pause
174
177
  deployment schedules on shutdown; defaults to `True`
175
178
  webserver: a boolean flag for whether to start a webserver for this runner
@@ -210,7 +213,11 @@ class Runner:
210
213
  self.started: bool = False
211
214
  self.stopping: bool = False
212
215
  self.pause_on_shutdown: bool = pause_on_shutdown
213
- self.limit: int | None = limit or settings.runner.process_limit
216
+ self.limit: int | None = (
217
+ settings.runner.process_limit
218
+ if limit is NotSet or isinstance(limit, type)
219
+ else limit
220
+ )
214
221
  self.webserver: bool = webserver
215
222
 
216
223
  self.query_seconds: float = query_seconds or settings.runner.poll_frequency
@@ -220,6 +227,7 @@ class Runner:
220
227
  )
221
228
  if self.heartbeat_seconds is not None and self.heartbeat_seconds < 30:
222
229
  raise ValueError("Heartbeat must be 30 seconds or greater.")
230
+ self._heartbeat_task: asyncio.Task[None] | None = None
223
231
 
224
232
  self._limiter: anyio.CapacityLimiter | None = None
225
233
  self._client: PrefectClient = get_client()
@@ -230,6 +238,8 @@ class Runner:
230
238
  self._flow_run_process_map: dict[UUID, ProcessMapEntry] = dict()
231
239
  self.__flow_run_process_map_lock: asyncio.Lock | None = None
232
240
  self._flow_run_bundle_map: dict[UUID, SerializedBundle] = dict()
241
+ # Flip to True when we are rescheduling flow runs to avoid marking flow runs as crashed
242
+ self._rescheduling: bool = False
233
243
 
234
244
  self._tmp_dir: Path = (
235
245
  Path(tempfile.gettempdir()) / "runner_storage" / str(uuid4())
@@ -500,16 +510,6 @@ class Runner:
500
510
  jitter_range=0.3,
501
511
  )
502
512
  )
503
- if self.heartbeat_seconds is not None:
504
- loops_task_group.start_soon(
505
- partial(
506
- critical_service_loop,
507
- workload=runner._emit_flow_run_heartbeats,
508
- interval=self.heartbeat_seconds,
509
- run_once=run_once,
510
- jitter_range=0.3,
511
- )
512
- )
513
513
 
514
514
  def execute_in_background(
515
515
  self, func: Callable[..., Any], *args: Any, **kwargs: Any
@@ -562,9 +562,9 @@ class Runner:
562
562
  flow_run_id: UUID,
563
563
  entrypoint: str | None = None,
564
564
  command: str | None = None,
565
- cwd: Path | None = None,
565
+ cwd: Path | str | None = None,
566
566
  env: dict[str, str | None] | None = None,
567
- task_status: anyio.abc.TaskStatus[int] | None = None,
567
+ task_status: anyio.abc.TaskStatus[int] = anyio.TASK_STATUS_IGNORED,
568
568
  stream_output: bool = True,
569
569
  ) -> anyio.abc.Process | None:
570
570
  """
@@ -588,7 +588,9 @@ class Runner:
588
588
  self._submitting_flow_run_ids.add(flow_run_id)
589
589
  flow_run = await self._client.read_flow_run(flow_run_id)
590
590
 
591
- process: anyio.abc.Process = await self._runs_task_group.start(
591
+ process: (
592
+ anyio.abc.Process | Exception
593
+ ) = await self._runs_task_group.start(
592
594
  partial(
593
595
  self._submit_run_and_capture_errors,
594
596
  flow_run=flow_run,
@@ -599,8 +601,13 @@ class Runner:
599
601
  stream_output=stream_output,
600
602
  ),
601
603
  )
602
- if task_status:
603
- task_status.started(process.pid)
604
+ if isinstance(process, Exception):
605
+ return
606
+
607
+ task_status.started(process.pid)
608
+
609
+ if self.heartbeat_seconds is not None:
610
+ await self._emit_flow_run_heartbeat(flow_run)
604
611
 
605
612
  async with self._flow_run_process_map_lock:
606
613
  # Only add the process to the map if it is still running
@@ -626,15 +633,6 @@ class Runner:
626
633
  jitter_range=0.3,
627
634
  )
628
635
  )
629
- if self.heartbeat_seconds is not None:
630
- tg.start_soon(
631
- partial(
632
- critical_service_loop,
633
- workload=self._emit_flow_run_heartbeats,
634
- interval=self.heartbeat_seconds,
635
- jitter_range=0.3,
636
- )
637
- )
638
636
 
639
637
  return process
640
638
 
@@ -662,6 +660,9 @@ class Runner:
662
660
  await self._propose_crashed_state(flow_run, msg)
663
661
  raise RuntimeError(msg)
664
662
 
663
+ if self.heartbeat_seconds is not None:
664
+ await self._emit_flow_run_heartbeat(flow_run)
665
+
665
666
  self._flow_run_process_map[flow_run.id] = ProcessMapEntry(
666
667
  pid=process.pid, flow_run=flow_run
667
668
  )
@@ -677,16 +678,6 @@ class Runner:
677
678
  )
678
679
  )
679
680
  )
680
- if self.heartbeat_seconds is not None:
681
- tasks.append(
682
- asyncio.create_task(
683
- critical_service_loop(
684
- workload=self._emit_flow_run_heartbeats,
685
- interval=self.heartbeat_seconds,
686
- jitter_range=0.1,
687
- )
688
- )
689
- )
690
681
 
691
682
  await anyio.to_thread.run_sync(process.join)
692
683
 
@@ -762,10 +753,12 @@ class Runner:
762
753
  async def _run_process(
763
754
  self,
764
755
  flow_run: "FlowRun",
765
- task_status: anyio.abc.TaskStatus[anyio.abc.Process] | None = None,
756
+ task_status: anyio.abc.TaskStatus[
757
+ anyio.abc.Process
758
+ ] = anyio.TASK_STATUS_IGNORED,
766
759
  entrypoint: str | None = None,
767
760
  command: str | None = None,
768
- cwd: Path | None = None,
761
+ cwd: Path | str | None = None,
769
762
  env: dict[str, str | None] | None = None,
770
763
  stream_output: bool = True,
771
764
  ) -> anyio.abc.Process:
@@ -945,6 +938,45 @@ class Runner:
945
938
  # process ended right after the check above.
946
939
  return
947
940
 
941
+ def reschedule_current_flow_runs(
942
+ self,
943
+ ) -> None:
944
+ """
945
+ Reschedules all flow runs that are currently running.
946
+
947
+ This should only be called when the runner is shutting down because it kill all
948
+ child processes and short-circuit the crash detection logic.
949
+ """
950
+ self._rescheduling = True
951
+ # Create a new sync client because this will often run in a separate thread
952
+ # as part of a signal handler.
953
+ with get_client(sync_client=True) as client:
954
+ self._logger.info("Rescheduling flow runs...")
955
+ for process_info in self._flow_run_process_map.values():
956
+ flow_run = process_info["flow_run"]
957
+ run_logger = self._get_flow_run_logger(flow_run)
958
+ run_logger.info(
959
+ "Rescheduling flow run for resubmission in response to SIGTERM"
960
+ )
961
+ try:
962
+ propose_state_sync(client, AwaitingRetry(), flow_run_id=flow_run.id)
963
+ os.kill(process_info["pid"], signal.SIGTERM)
964
+ run_logger.info("Rescheduled flow run for resubmission")
965
+ except ProcessLookupError:
966
+ # Process may have already exited
967
+ pass
968
+ except Abort as exc:
969
+ run_logger.info(
970
+ (
971
+ "Aborted submission of flow run. "
972
+ f"Server sent an abort signal: {exc}"
973
+ ),
974
+ )
975
+ except Exception:
976
+ run_logger.exception(
977
+ "Failed to reschedule flow run",
978
+ )
979
+
948
980
  async def _pause_schedules(self):
949
981
  """
950
982
  Pauses all deployment schedules.
@@ -1280,8 +1312,8 @@ class Runner:
1280
1312
  assert self._limiter is not None
1281
1313
  self._logger.info(
1282
1314
  f"Flow run limit reached; {self._limiter.borrowed_tokens} flow runs"
1283
- " in progress. You can control this limit by passing a `limit` value"
1284
- " to `serve` or adjusting the PREFECT_RUNNER_PROCESS_LIMIT setting."
1315
+ " in progress. You can control this limit by adjusting the "
1316
+ "PREFECT_RUNNER_PROCESS_LIMIT setting."
1285
1317
  )
1286
1318
  return False
1287
1319
 
@@ -1375,7 +1407,7 @@ class Runner:
1375
1407
  task_status: anyio.abc.TaskStatus[anyio.abc.Process | Exception],
1376
1408
  entrypoint: str | None = None,
1377
1409
  command: str | None = None,
1378
- cwd: Path | None = None,
1410
+ cwd: Path | str | None = None,
1379
1411
  env: dict[str, str | None] | None = None,
1380
1412
  stream_output: bool = True,
1381
1413
  ) -> Union[Optional[int], Exception]:
@@ -1393,12 +1425,12 @@ class Runner:
1393
1425
  )
1394
1426
  status_code = process.returncode
1395
1427
  except Exception as exc:
1396
- if task_status:
1428
+ if not task_status._future.done():
1397
1429
  # This flow run was being submitted and did not start successfully
1398
1430
  run_logger.exception(
1399
1431
  f"Failed to start process for flow run '{flow_run.id}'."
1400
1432
  )
1401
- # Mark the task as started to prevent agent crash
1433
+ # Mark the task as started to prevent runner crash
1402
1434
  task_status.started(exc)
1403
1435
  message = f"Flow run process could not be started:\n{exc!r}"
1404
1436
  await self._propose_crashed_state(flow_run, message)
@@ -1415,7 +1447,7 @@ class Runner:
1415
1447
  async with self._flow_run_process_map_lock:
1416
1448
  self._flow_run_process_map.pop(flow_run.id, None)
1417
1449
 
1418
- if status_code != 0:
1450
+ if status_code != 0 and not self._rescheduling:
1419
1451
  await self._propose_crashed_state(
1420
1452
  flow_run,
1421
1453
  f"Flow run process exited with non-zero status code {status_code}.",
@@ -1631,6 +1663,15 @@ class Runner:
1631
1663
  if not hasattr(self, "_loops_task_group") or not self._loops_task_group:
1632
1664
  self._loops_task_group: anyio.abc.TaskGroup = anyio.create_task_group()
1633
1665
 
1666
+ if self.heartbeat_seconds is not None:
1667
+ self._heartbeat_task = asyncio.create_task(
1668
+ critical_service_loop(
1669
+ workload=self._emit_flow_run_heartbeats,
1670
+ interval=self.heartbeat_seconds,
1671
+ jitter_range=0.3,
1672
+ )
1673
+ )
1674
+
1634
1675
  self.started = True
1635
1676
  return self
1636
1677
 
@@ -1652,6 +1693,13 @@ class Runner:
1652
1693
  shutil.rmtree(str(self._tmp_dir))
1653
1694
  del self._runs_task_group, self._loops_task_group
1654
1695
 
1696
+ if self._heartbeat_task:
1697
+ self._heartbeat_task.cancel()
1698
+ try:
1699
+ await self._heartbeat_task
1700
+ except asyncio.CancelledError:
1701
+ pass
1702
+
1655
1703
  def __repr__(self) -> str:
1656
1704
  return f"Runner(name={self.name!r})"
1657
1705
 
prefect/runner/storage.py CHANGED
@@ -141,7 +141,8 @@ class GitRepository:
141
141
  self._credentials = credentials
142
142
  self._include_submodules = include_submodules
143
143
  repo_name = urlparse(url).path.split("/")[-1].replace(".git", "")
144
- default_name = f"{repo_name}-{branch}" if branch else repo_name
144
+ safe_branch = branch.replace("/", "-") if branch else None
145
+ default_name = f"{repo_name}-{safe_branch}" if safe_branch else repo_name
145
146
  self._name = name or default_name
146
147
  self._logger = get_logger(f"runner.storage.git-repository.{self._name}")
147
148
  self._storage_base_path = Path.cwd()
@@ -376,12 +376,12 @@ async def read_deployment(
376
376
  async def read_deployments(
377
377
  limit: int = dependencies.LimitBody(),
378
378
  offset: int = Body(0, ge=0),
379
- flows: schemas.filters.FlowFilter = None,
380
- flow_runs: schemas.filters.FlowRunFilter = None,
381
- task_runs: schemas.filters.TaskRunFilter = None,
382
- deployments: schemas.filters.DeploymentFilter = None,
383
- work_pools: schemas.filters.WorkPoolFilter = None,
384
- work_pool_queues: schemas.filters.WorkQueueFilter = None,
379
+ flows: Optional[schemas.filters.FlowFilter] = None,
380
+ flow_runs: Optional[schemas.filters.FlowRunFilter] = None,
381
+ task_runs: Optional[schemas.filters.TaskRunFilter] = None,
382
+ deployments: Optional[schemas.filters.DeploymentFilter] = None,
383
+ work_pools: Optional[schemas.filters.WorkPoolFilter] = None,
384
+ work_pool_queues: Optional[schemas.filters.WorkQueueFilter] = None,
385
385
  sort: schemas.sorting.DeploymentSort = Body(
386
386
  schemas.sorting.DeploymentSort.NAME_ASC
387
387
  ),
@@ -415,12 +415,12 @@ async def read_deployments(
415
415
  async def paginate_deployments(
416
416
  limit: int = dependencies.LimitBody(),
417
417
  page: int = Body(1, ge=1),
418
- flows: schemas.filters.FlowFilter = None,
419
- flow_runs: schemas.filters.FlowRunFilter = None,
420
- task_runs: schemas.filters.TaskRunFilter = None,
421
- deployments: schemas.filters.DeploymentFilter = None,
422
- work_pools: schemas.filters.WorkPoolFilter = None,
423
- work_pool_queues: schemas.filters.WorkQueueFilter = None,
418
+ flows: Optional[schemas.filters.FlowFilter] = None,
419
+ flow_runs: Optional[schemas.filters.FlowRunFilter] = None,
420
+ task_runs: Optional[schemas.filters.TaskRunFilter] = None,
421
+ deployments: Optional[schemas.filters.DeploymentFilter] = None,
422
+ work_pools: Optional[schemas.filters.WorkPoolFilter] = None,
423
+ work_pool_queues: Optional[schemas.filters.WorkQueueFilter] = None,
424
424
  sort: schemas.sorting.DeploymentSort = Body(
425
425
  schemas.sorting.DeploymentSort.NAME_ASC
426
426
  ),
@@ -474,7 +474,7 @@ async def paginate_deployments(
474
474
  @router.post("/get_scheduled_flow_runs")
475
475
  async def get_scheduled_flow_runs_for_deployments(
476
476
  background_tasks: BackgroundTasks,
477
- deployment_ids: List[UUID] = Body(
477
+ deployment_ids: list[UUID] = Body(
478
478
  default=..., description="The deployment IDs to get scheduled runs for"
479
479
  ),
480
480
  scheduled_before: DateTime = Body(
@@ -482,7 +482,7 @@ async def get_scheduled_flow_runs_for_deployments(
482
482
  ),
483
483
  limit: int = dependencies.LimitBody(),
484
484
  db: PrefectDBInterface = Depends(provide_database_interface),
485
- ) -> List[schemas.responses.FlowRunResponse]:
485
+ ) -> list[schemas.responses.FlowRunResponse]:
486
486
  """
487
487
  Get scheduled runs for a set of deployments. Used by a runner to poll for work.
488
488
  """
@@ -515,6 +515,7 @@ async def get_scheduled_flow_runs_for_deployments(
515
515
 
516
516
  background_tasks.add_task(
517
517
  mark_deployments_ready,
518
+ db=db,
518
519
  deployment_ids=deployment_ids,
519
520
  )
520
521
 
@@ -523,12 +524,12 @@ async def get_scheduled_flow_runs_for_deployments(
523
524
 
524
525
  @router.post("/count")
525
526
  async def count_deployments(
526
- flows: schemas.filters.FlowFilter = None,
527
- flow_runs: schemas.filters.FlowRunFilter = None,
528
- task_runs: schemas.filters.TaskRunFilter = None,
529
- deployments: schemas.filters.DeploymentFilter = None,
530
- work_pools: schemas.filters.WorkPoolFilter = None,
531
- work_pool_queues: schemas.filters.WorkQueueFilter = None,
527
+ flows: Optional[schemas.filters.FlowFilter] = None,
528
+ flow_runs: Optional[schemas.filters.FlowRunFilter] = None,
529
+ task_runs: Optional[schemas.filters.TaskRunFilter] = None,
530
+ deployments: Optional[schemas.filters.DeploymentFilter] = None,
531
+ work_pools: Optional[schemas.filters.WorkPoolFilter] = None,
532
+ work_pool_queues: Optional[schemas.filters.WorkQueueFilter] = None,
532
533
  db: PrefectDBInterface = Depends(provide_database_interface),
533
534
  ) -> int:
534
535
  """
@@ -250,8 +250,14 @@ def copy_directory(directory: str, path: str) -> None:
250
250
  if os.path.exists(destination):
251
251
  shutil.rmtree(destination)
252
252
  shutil.copytree(source, destination, symlinks=True)
253
+ # ensure copied files are writeable
254
+ for root, dirs, files in os.walk(destination):
255
+ for f in files:
256
+ os.chmod(os.path.join(root, f), 0o600)
253
257
  else:
254
258
  shutil.copy2(source, destination)
259
+ # Ensure copied file is writeable
260
+ os.chmod(destination, 0o600)
255
261
 
256
262
 
257
263
  async def custom_internal_exception_handler(
@@ -164,6 +164,7 @@ async def read_work_queue_runs(
164
164
 
165
165
  background_tasks.add_task(
166
166
  mark_work_queues_ready,
167
+ db=db,
167
168
  polled_work_queue_ids=[work_queue_id],
168
169
  ready_work_queue_ids=(
169
170
  [work_queue_id] if work_queue.status == WorkQueueStatus.NOT_READY else []
@@ -172,6 +173,7 @@ async def read_work_queue_runs(
172
173
 
173
174
  background_tasks.add_task(
174
175
  mark_deployments_ready,
176
+ db=db,
175
177
  work_queue_ids=[work_queue_id],
176
178
  )
177
179
 
@@ -375,6 +375,7 @@ async def get_scheduled_flow_runs(
375
375
 
376
376
  background_tasks.add_task(
377
377
  mark_work_queues_ready,
378
+ db=db,
378
379
  polled_work_queue_ids=[
379
380
  wq.id for wq in work_queues if wq.status != WorkQueueStatus.NOT_READY
380
381
  ],
@@ -385,6 +386,7 @@ async def get_scheduled_flow_runs(
385
386
 
386
387
  background_tasks.add_task(
387
388
  mark_deployments_ready,
389
+ db=db,
388
390
  work_queue_ids=[wq.id for wq in work_queues],
389
391
  )
390
392
 
@@ -132,7 +132,7 @@ class RunTelemetry:
132
132
  },
133
133
  )
134
134
 
135
- if traceparent := self._traceparent_from_span(self.span):
135
+ if traceparent := RunTelemetry.traceparent_from_span(self.span):
136
136
  run.labels[LABELS_TRACEPARENT_KEY] = traceparent
137
137
 
138
138
  return traceparent, self.span
@@ -150,7 +150,8 @@ class RunTelemetry:
150
150
  carrier = {TRACEPARENT_KEY: traceparent}
151
151
  return propagate.extract(carrier)
152
152
 
153
- def _traceparent_from_span(self, span: Span) -> str | None:
153
+ @staticmethod
154
+ def traceparent_from_span(span: Span) -> str | None:
154
155
  carrier: dict[str, Any] = {}
155
156
  propagate.inject(carrier, context=trace.set_span_in_context(span))
156
157
  return carrier.get(TRACEPARENT_KEY)
prefect/workers/base.py CHANGED
@@ -933,40 +933,32 @@ class BaseWorker(abc.ABC, Generic[C, V, R]):
933
933
  )
934
934
  )
935
935
 
936
- async def _check_flow_run(self, flow_run: "FlowRun") -> None:
936
+ async def _submit_run(self, flow_run: "FlowRun") -> None:
937
937
  """
938
- Performs a check on a submitted flow run to warn the user if the flow run
939
- was created from a deployment with a storage block.
938
+ Submits a given flow run for execution by the worker.
940
939
  """
940
+ run_logger = self.get_flow_run_logger(flow_run)
941
+
941
942
  if flow_run.deployment_id:
942
943
  assert self._client and self._client._started, (
943
944
  "Client must be started to check flow run deployment."
944
945
  )
945
- deployment = await self._client.read_deployment(flow_run.deployment_id)
946
- if deployment.storage_document_id:
947
- raise ValueError(
948
- f"Flow run {flow_run.id!r} was created from deployment"
949
- f" {deployment.name!r} which is configured with a storage block."
950
- " Please use an agent to execute this flow run."
951
- )
952
-
953
- async def _submit_run(self, flow_run: "FlowRun") -> None:
954
- """
955
- Submits a given flow run for execution by the worker.
956
- """
957
- run_logger = self.get_flow_run_logger(flow_run)
958
946
 
959
947
  try:
960
- await self._check_flow_run(flow_run)
961
- except (ValueError, ObjectNotFound):
948
+ await self._client.read_deployment(flow_run.deployment_id)
949
+ except ObjectNotFound:
962
950
  self._logger.exception(
963
- (
964
- "Flow run %s did not pass checks and will not be submitted for"
965
- " execution"
966
- ),
967
- flow_run.id,
951
+ f"Deployment {flow_run.deployment_id} no longer exists. "
952
+ f"Flow run {flow_run.id} will not be submitted for"
953
+ " execution"
968
954
  )
969
955
  self._submitting_flow_run_ids.remove(flow_run.id)
956
+ await self._mark_flow_run_as_cancelled(
957
+ flow_run,
958
+ state_updates=dict(
959
+ message=f"Deployment {flow_run.deployment_id} no longer exists, cancelled run."
960
+ ),
961
+ )
970
962
  return
971
963
 
972
964
  ready_to_submit = await self._propose_pending_state(flow_run)
@@ -16,7 +16,9 @@ checkout out the [Prefect docs](/concepts/work-pools/).
16
16
 
17
17
  from __future__ import annotations
18
18
 
19
+ import contextlib
19
20
  import os
21
+ import tempfile
20
22
  import threading
21
23
  from functools import partial
22
24
  from pathlib import Path
@@ -203,14 +205,23 @@ class ProcessWorker(
203
205
  configuration: ProcessJobConfiguration,
204
206
  task_status: Optional[anyio.abc.TaskStatus[int]] = None,
205
207
  ) -> ProcessWorkerResult:
206
- process = await self._runner.execute_flow_run(
207
- flow_run_id=flow_run.id,
208
- command=configuration.command,
209
- cwd=configuration.working_dir,
210
- env=configuration.env,
211
- stream_output=configuration.stream_output,
212
- task_status=task_status,
208
+ if task_status is None:
209
+ task_status = anyio.TASK_STATUS_IGNORED
210
+
211
+ working_dir_ctx = (
212
+ tempfile.TemporaryDirectory(suffix="prefect")
213
+ if not configuration.working_dir
214
+ else contextlib.nullcontext(configuration.working_dir)
213
215
  )
216
+ with working_dir_ctx as working_dir:
217
+ process = await self._runner.execute_flow_run(
218
+ flow_run_id=flow_run.id,
219
+ command=configuration.command,
220
+ cwd=working_dir,
221
+ env=configuration.env,
222
+ stream_output=configuration.stream_output,
223
+ task_status=task_status,
224
+ )
214
225
 
215
226
  if process is None or process.returncode is None:
216
227
  raise RuntimeError("Failed to start flow run process.")
@@ -222,7 +233,7 @@ class ProcessWorker(
222
233
  async def __aenter__(self) -> ProcessWorker:
223
234
  await super().__aenter__()
224
235
  self._runner = await self._exit_stack.enter_async_context(
225
- Runner(pause_on_shutdown=False)
236
+ Runner(pause_on_shutdown=False, limit=None)
226
237
  )
227
238
  return self
228
239
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prefect-client
3
- Version: 3.2.8
3
+ Version: 3.2.10
4
4
  Summary: Workflow orchestration and management.
5
5
  Project-URL: Changelog, https://github.com/PrefectHQ/prefect/releases
6
6
  Project-URL: Documentation, https://docs.prefect.io
@@ -1,7 +1,7 @@
1
1
  prefect/.prefectignore,sha256=awSprvKT0vI8a64mEOLrMxhxqcO-b0ERQeYpA2rNKVQ,390
2
2
  prefect/__init__.py,sha256=iCdcC5ZmeewikCdnPEP6YBAjPNV5dvfxpYCTpw30Hkw,3685
3
3
  prefect/__main__.py,sha256=WFjw3kaYJY6pOTA7WDOgqjsz8zUEUZHCcj3P5wyVa-g,66
4
- prefect/_build_info.py,sha256=xmDfVj6oyNn39V5dUMzOXraIYaSVi10dtszKjtYfoLY,180
4
+ prefect/_build_info.py,sha256=WbfStAdc-mwmaeLFXnTicNLoAChNnOcmuBnhT1CZ4cU,181
5
5
  prefect/_result_records.py,sha256=S6QmsODkehGVSzbMm6ig022PYbI6gNKz671p_8kBYx4,7789
6
6
  prefect/_waiters.py,sha256=Ia2ITaXdHzevtyWIgJoOg95lrEXQqNEOquHvw3T33UQ,9026
7
7
  prefect/agent.py,sha256=dPvG1jDGD5HSH7aM2utwtk6RaJ9qg13XjkA0lAIgQmY,287
@@ -14,7 +14,7 @@ prefect/exceptions.py,sha256=-nih8qqdxRm6CX-4yrqwePVh8Mcpvla_V6N_KbdJsIU,11593
14
14
  prefect/filesystems.py,sha256=v5YqGB4uXf9Ew2VuB9VCSkawvYMMVvEtZf7w1VmAmr8,18036
15
15
  prefect/flow_engine.py,sha256=gR44YU7aCAbHEqoMDdxL1SDrtS5Xx1Kzg3M7FWjHcvY,58967
16
16
  prefect/flow_runs.py,sha256=ocbV3ioSBIFoLqExpI2YLteyHdWpHB3t0lrbfl-Ni1E,17256
17
- prefect/flows.py,sha256=u21wlvkE3X0NAoN9UlqEC37WHFFM4ziMxAB9XZABDjs,108636
17
+ prefect/flows.py,sha256=g7OVVer6m8nPtrR0MllWpa8_Iezh2G1maxvz8ZeNgbo,109029
18
18
  prefect/futures.py,sha256=ADd8ceFqX7A8Kw8aXaqvbYRG03uU82OEY30xrP5vrwY,23599
19
19
  prefect/main.py,sha256=hFeTTrr01qWKcRwZVEHVipyHEybS0VLTscFV6zG6GtY,2306
20
20
  prefect/plugins.py,sha256=FPRLR2mWVBMuOnlzeiTD9krlHONZH2rtYLD753JQDNQ,2516
@@ -31,7 +31,7 @@ prefect/tasks.py,sha256=g__kIAXvbvdY7NtK7R-KbJg7qUP31xjf5uK80zRS3Ds,74049
31
31
  prefect/transactions.py,sha256=kOXwghBW3jM71gg49MkjJPTnImEzXWeTCUE_zpq2MlI,16068
32
32
  prefect/variables.py,sha256=dCK3vX7TbkqXZhnNT_v7rcGh3ISRqoR6pJVLpoll3Js,8342
33
33
  prefect/_experimental/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
- prefect/_experimental/bundles.py,sha256=qVxA4rkE35wdZeitBOsECa4JBvWFF9oamCRgGchJIdc,6159
34
+ prefect/_experimental/bundles.py,sha256=cxfUFdvBjd42imrimPG2MF3zJoyi1vGeYOVSiyjLC8Y,6245
35
35
  prefect/_experimental/lineage.py,sha256=8LssReoq7eLtQScUCu-7FCtrWoRZstXKRdpO0PxgbKg,9958
36
36
  prefect/_experimental/sla/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
37
  prefect/_experimental/sla/client.py,sha256=XTkYHFZiBy_O7RgUyGEdl9MxaHP-6fEAKBk3ksNQobU,3611
@@ -137,7 +137,7 @@ prefect/concurrency/v1/sync.py,sha256=N_CHNkbV_eNQvDsJoJaehQo8H68MFlX6B1ObDZuYlT
137
137
  prefect/deployments/__init__.py,sha256=_wb7NxDKhq11z9MjYsPckmT3o6MRhGLRgCV9TmvYtew,1002
138
138
  prefect/deployments/base.py,sha256=KEc07W35yyzGJcV6GIZry8bKcNfvQk6JjJ99KKB6XpQ,11729
139
139
  prefect/deployments/deployments.py,sha256=K3Rgnpjxo_T8I8LMwlq24OKqZiZBTE8-YnPg-YGUStM,171
140
- prefect/deployments/flow_runs.py,sha256=VunxRsw4DyqVJHNjooDAPGJaGvSGucLX83SaxHO8ugU,7227
140
+ prefect/deployments/flow_runs.py,sha256=sHHV642rPjncXoMYAxIldW6wz-dipXvZqhrLAEH8vsQ,7466
141
141
  prefect/deployments/runner.py,sha256=FUmBuuF5X8o2wGf8aIdqjijDJy3FWuNYPpwaKhrVaHs,54052
142
142
  prefect/deployments/schedules.py,sha256=2eL1-w8qXtwKVkgfUK7cuamwpKK3X6tN1QYTDa_gWxU,2190
143
143
  prefect/deployments/steps/__init__.py,sha256=Dlz9VqMRyG1Gal8dj8vfGpPr0LyQhZdvcciozkK8WoY,206
@@ -148,7 +148,7 @@ prefect/docker/__init__.py,sha256=z6wdc6UFfiBG2jb9Jk64uCWVM04JKVWeVyDWwuuon8M,52
148
148
  prefect/docker/docker_image.py,sha256=cdvUEokGJXZDugfCekfmrhhpzrxTEW-FvWa2kDs5tVM,3092
149
149
  prefect/events/__init__.py,sha256=GtKl2bE--pJduTxelH2xy7SadlLJmmis8WR1EYixhuA,2094
150
150
  prefect/events/actions.py,sha256=A7jS8bo4zWGnrt3QfSoQs0uYC1xfKXio3IfU0XtTb5s,9129
151
- prefect/events/clients.py,sha256=IZhSLkHPslDwtKtOBCSuePVV2ifHghADmnFxmkahSO0,26845
151
+ prefect/events/clients.py,sha256=PiPWtqX_OSZCWD7ekCuS_toi7DQMVC7FbPmI5q8cf2I,27254
152
152
  prefect/events/filters.py,sha256=h9L6pukS9tD7Y8rGC3dt04KJINu0oJoti-flGLQTQQQ,8086
153
153
  prefect/events/related.py,sha256=Uh6-MoVENvP9dYYhjstb7eHesQUoDp-2PTMSP0nhPDI,6545
154
154
  prefect/events/utilities.py,sha256=4Bz-xiTOzi_EeDyIL9BzI7eMbRbBIIyayNvfO_BFyTw,2632
@@ -184,9 +184,9 @@ prefect/logging/highlighters.py,sha256=BCf_LNhFInIfGPqwuu8YVrGa4wVxNc4YXo2pYgftp
184
184
  prefect/logging/loggers.py,sha256=xkmHXsiuoPZZXcrrEgMA-ZQu0E-gW3tNVd4BIxWjnpM,12704
185
185
  prefect/logging/logging.yml,sha256=tT7gTyC4NmngFSqFkCdHaw7R0GPNPDDsTCGZQByiJAQ,3169
186
186
  prefect/runner/__init__.py,sha256=7U-vAOXFkzMfRz1q8Uv6Otsvc0OrPYLLP44srwkJ_8s,89
187
- prefect/runner/runner.py,sha256=fT2_jXIabxcx0iZmT0q5WmMr46GnN_LZp10hfdB4l3I,63552
187
+ prefect/runner/runner.py,sha256=8JixM-hU4Oo4AMaXhWGEISUdZCg0AZdPGkP4lXxbMu0,65436
188
188
  prefect/runner/server.py,sha256=WDDjCbnd2F_3LZBpVX2Y398xpmHvxjyBLKVHWkh5QxI,11240
189
- prefect/runner/storage.py,sha256=Uxx_7SPm-F0LR1LUq64cT-xHL2ofd37hHqLHtRYjGW0,27527
189
+ prefect/runner/storage.py,sha256=14ABbc6xJfPLLichyBVebmoxTT5qPghrOm8cDEujalc,27604
190
190
  prefect/runner/submit.py,sha256=3Ey6H4XrhYhCII4AobpvzZf21vAunWlMu40zAjMC0gc,8353
191
191
  prefect/runner/utils.py,sha256=MLtoouDD6bh-JAIz0W3fMofKXEt0VfGsg6d8jf45OA0,3280
192
192
  prefect/runtime/__init__.py,sha256=JswiTlYRup2zXOYu8AqJ7czKtgcw9Kxo0tTbS6aWCqY,407
@@ -207,7 +207,7 @@ prefect/server/api/concurrency_limits.py,sha256=E5TB2cJPIZjnxnm1pGxUJnwMDz5CS58g
207
207
  prefect/server/api/concurrency_limits_v2.py,sha256=9JRAqc6E-MqpescewOU8aflPecsXCowCTxPvpYs2Plk,10097
208
208
  prefect/server/api/csrf_token.py,sha256=BwysSjQAhre7O0OY_LF3ZcIiO53FdMQroNT11Q6OcOM,1344
209
209
  prefect/server/api/dependencies.py,sha256=VujfcIGn41TGJxUunFHVabY5hE-6nY6uSHyhNFj8PdI,6634
210
- prefect/server/api/deployments.py,sha256=DWeZ7OIw7XGc8d2ldrI90kLV5LGqfUoMqdqXFYwkvNU,37706
210
+ prefect/server/api/deployments.py,sha256=2C7pCY2renhyPDfi_IuzWoEhH620ERWLmQSTAnxyywM,37901
211
211
  prefect/server/api/events.py,sha256=3-Qdt6ORxFv3nLoogQqvd72zEulJSoAmcqZto2OULuk,9907
212
212
  prefect/server/api/flow_run_notification_policies.py,sha256=F8xNm6bgZTC3nFe9xCUJS4NlU9tLXZ8fShtJqmhT2m4,4828
213
213
  prefect/server/api/flow_run_states.py,sha256=lIdxVE9CqLgtDCuH9bTaKkzHNL81FPrr11liPzvONrw,1661
@@ -218,15 +218,15 @@ prefect/server/api/middleware.py,sha256=WkyuyeJIfo9Q0GAIVU5gO6yIGNVwoHwuBah5AB5o
218
218
  prefect/server/api/root.py,sha256=CeumFYIM_BDvPicJH9ry5PO_02PZTLeMqbLMGGTh90o,942
219
219
  prefect/server/api/run_history.py,sha256=FHepAgo1AYFeuh7rrAVzo_o3hu8Uc8-4DeH5aD5VGgw,5995
220
220
  prefect/server/api/saved_searches.py,sha256=UjoqLLe245QVIs6q5Vk4vdODCOoYzciEEjhi7B8sYCE,3233
221
- prefect/server/api/server.py,sha256=W85DhOyIyq5_Cf5ep-YrNd8vF2IB-JzKzqMppIox9Fs,32082
221
+ prefect/server/api/server.py,sha256=iJX47L_ae4lskDqpOqFvYe3CwKykgw77HkHtqh0UODQ,32367
222
222
  prefect/server/api/task_run_states.py,sha256=e63OPpxPudv_CIB5oKr8Z8rfQ-Osjm9Zq0iHe8obnMo,1647
223
223
  prefect/server/api/task_runs.py,sha256=VY6MrolTi_vmiaE5my3WyRl5r256WKC7sfxxBE4Wnpw,12239
224
224
  prefect/server/api/task_workers.py,sha256=cFP9M8tsApDL_JpySn-x6fOYy9RnOeOgKiqOl_UVVQM,1042
225
225
  prefect/server/api/templates.py,sha256=92bLFfcahZUp5PVNTZPjl8uJSDj4ZYRTVdmTzZXkERg,1027
226
226
  prefect/server/api/validation.py,sha256=HxSNyH8yb_tI-kOfjXESRjJp6WQK6hYWBJsaBxUvY34,14490
227
227
  prefect/server/api/variables.py,sha256=SJaKuqInfQIEdMlJOemptBDN43KLFhlf_u9QwupDu7A,6185
228
- prefect/server/api/work_queues.py,sha256=iOl5CcZWHKPAD66ZK2NZTktSKimtRdHkh1deGH7SG-8,7558
229
- prefect/server/api/workers.py,sha256=VrtEyt-vIx77b_OvsR0CdtD5G0hEUF0XSZtJj1Sotl8,22572
228
+ prefect/server/api/work_queues.py,sha256=wBcbmkZDaQ5Ddi9wc8tNs6kYG_FdNtYwTCR0VkhPj2o,7588
229
+ prefect/server/api/workers.py,sha256=sGQzJED7E3uMP1jMdWAyB3d44xWBRtoHcTGY0oiEbm4,22602
230
230
  prefect/server/api/collections_data/views/aggregate-worker-metadata.json,sha256=gqrwGyylzBEzlFSPOJcMuUwdoK_zojpU0SZaBDgK5FE,79748
231
231
  prefect/server/api/static/prefect-logo-mark-gradient.png,sha256=ylRjJkI_JHCw8VbQasNnXQHwZW-sH-IQiUGSD3aWP1E,73430
232
232
  prefect/server/api/ui/__init__.py,sha256=TCXO4ZUZCqCbm2QoNvWNTErkzWiX2nSACuO-0Tiomvg,93
@@ -274,7 +274,7 @@ prefect/telemetry/bootstrap.py,sha256=tD6CXgMU3skgpKNscrRYZudwCWEEt6wjwMsulYpHeA
274
274
  prefect/telemetry/instrumentation.py,sha256=9JElKwEqKhErohjHNS4oAIXJRYCWVY0rfSnk4DUBna0,4454
275
275
  prefect/telemetry/logging.py,sha256=yn5D4D2GGRrAv0y8wlHPN7PZDmQucGjQT_YauK9M9Yo,727
276
276
  prefect/telemetry/processors.py,sha256=jw6j6LviOVxw3IBJe7cSjsxFk0zzY43jUmy6C9pcfCE,2272
277
- prefect/telemetry/run_telemetry.py,sha256=NcMVqOc_wQVGPlGpE8cfrz-lyCbkG1EOKpcbjsqMnGA,8264
277
+ prefect/telemetry/run_telemetry.py,sha256=xOrZEFf-1cbSdKe3ZlB4spbyJ3sxYbnb2u2yZiUSSqM,8282
278
278
  prefect/telemetry/services.py,sha256=DxgNNDTeWNtHBtioX8cjua4IrCbTiJJdYecx-gugg-w,2358
279
279
  prefect/types/__init__.py,sha256=yBjKxiQmSC7jXoo0UNmM3KZil1NBFS-BWGPfwSEaoJo,4621
280
280
  prefect/types/_datetime.py,sha256=eOsg5gkm4bATLWvK4lmLqHByxQdER6gfTFyafzj-DLk,3343
@@ -312,13 +312,13 @@ prefect/utilities/schema_tools/__init__.py,sha256=At3rMHd2g_Em2P3_dFQlFgqR_EpBwr
312
312
  prefect/utilities/schema_tools/hydration.py,sha256=NkRhWkNfxxFmVGhNDfmxdK_xeKaEhs3a42q83Sg9cT4,9436
313
313
  prefect/utilities/schema_tools/validation.py,sha256=Wix26IVR-ZJ32-6MX2pHhrwm3reB-Q4iB6_phn85OKE,10743
314
314
  prefect/workers/__init__.py,sha256=EaM1F0RZ-XIJaGeTKLsXDnfOPHzVWk5bk0_c4BVS44M,64
315
- prefect/workers/base.py,sha256=1lPZRj2hBDP1-lS2oqdfUXg0iZJ4Y1qw5C6THDG9iB0,49842
315
+ prefect/workers/base.py,sha256=_7_XRi-5v8jGqKelH12Lkf8CBUnXrq04JPlIMc6WhhM,49439
316
316
  prefect/workers/block.py,sha256=dPvG1jDGD5HSH7aM2utwtk6RaJ9qg13XjkA0lAIgQmY,287
317
317
  prefect/workers/cloud.py,sha256=dPvG1jDGD5HSH7aM2utwtk6RaJ9qg13XjkA0lAIgQmY,287
318
- prefect/workers/process.py,sha256=hv1WssMDDznpq3zpTwo6SA3UhzXXKrfIYL4jq1Beark,8490
318
+ prefect/workers/process.py,sha256=ozC-PGp1rjEG7CO1D7wZYM3oO_DeefccXy3rBLJK3kA,8892
319
319
  prefect/workers/server.py,sha256=SEuyScZ5nGm2OotdtbHjpvqJlTRVWCh29ND7FeL_fZA,1974
320
320
  prefect/workers/utilities.py,sha256=VfPfAlGtTuDj0-Kb8WlMgAuOfgXCdrGAnKMapPSBrwc,2483
321
- prefect_client-3.2.8.dist-info/METADATA,sha256=q5Zs-swuflfHYhLYk6sTTD9tSgAPcMBniLAFSCrKeV8,7192
322
- prefect_client-3.2.8.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
323
- prefect_client-3.2.8.dist-info/licenses/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
324
- prefect_client-3.2.8.dist-info/RECORD,,
321
+ prefect_client-3.2.10.dist-info/METADATA,sha256=NSATgsj4dT5OmRVYVVaSTKIcE3qPgwtbxKkrmLVG3dg,7193
322
+ prefect_client-3.2.10.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
323
+ prefect_client-3.2.10.dist-info/licenses/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
324
+ prefect_client-3.2.10.dist-info/RECORD,,