prefect-client 3.4.0__py3-none-any.whl → 3.4.1.dev2__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.4.0"
3
- __build_date__ = "2025-05-02 20:01:04.986143+00:00"
4
- __git_commit__ = "c80e444246c8805f1dfb684267e0d88dbfcc8d38"
2
+ __version__ = "3.4.1.dev2"
3
+ __build_date__ = "2025-05-05 08:08:58.760597+00:00"
4
+ __git_commit__ = "c158d3eb6aae366fd814ba55c9151ca73ca1666a"
5
5
  __dirty__ = False
@@ -322,12 +322,16 @@ class PrefectClient(
322
322
  if api_version is None:
323
323
  api_version = SERVER_API_VERSION
324
324
  httpx_settings["headers"].setdefault("X-PREFECT-API-VERSION", api_version)
325
- if api_key:
326
- httpx_settings["headers"].setdefault("Authorization", f"Bearer {api_key}")
327
-
325
+ # Prioritize auth_string if provided, otherwise use api_key
328
326
  if auth_string:
329
327
  token = base64.b64encode(auth_string.encode("utf-8")).decode("utf-8")
330
- httpx_settings["headers"].setdefault("Authorization", f"Basic {token}")
328
+ httpx_settings["headers"]["Authorization"] = (
329
+ f"Basic {token}" # Overwrite if exists
330
+ )
331
+ elif api_key:
332
+ httpx_settings["headers"]["Authorization"] = (
333
+ f"Bearer {api_key}" # Set if auth_string is not present
334
+ )
331
335
 
332
336
  # Context management
333
337
  self._context_stack: int = 0
@@ -1189,12 +1193,16 @@ class SyncPrefectClient(
1189
1193
  if api_version is None:
1190
1194
  api_version = SERVER_API_VERSION
1191
1195
  httpx_settings["headers"].setdefault("X-PREFECT-API-VERSION", api_version)
1192
- if api_key:
1193
- httpx_settings["headers"].setdefault("Authorization", f"Bearer {api_key}")
1194
-
1196
+ # Prioritize auth_string if provided, otherwise use api_key
1195
1197
  if auth_string:
1196
1198
  token = base64.b64encode(auth_string.encode("utf-8")).decode("utf-8")
1197
- httpx_settings["headers"].setdefault("Authorization", f"Basic {token}")
1199
+ httpx_settings["headers"]["Authorization"] = (
1200
+ f"Basic {token}" # Overwrite if exists
1201
+ )
1202
+ elif api_key:
1203
+ httpx_settings["headers"]["Authorization"] = (
1204
+ f"Bearer {api_key}" # Set if auth_string is not present
1205
+ )
1198
1206
 
1199
1207
  # Context management
1200
1208
  self._context_stack: int = 0
@@ -13,7 +13,7 @@ from typing_extensions import Self
13
13
  from prefect._internal.schemas.bases import IDBaseModel
14
14
  from prefect.events.clients import websocket_connect
15
15
  from prefect.logging import get_logger
16
- from prefect.settings import PREFECT_API_KEY
16
+ from prefect.settings import get_current_settings
17
17
 
18
18
  logger: Logger = get_logger(__name__)
19
19
 
@@ -76,10 +76,17 @@ class Subscription(Generic[S]):
76
76
  websocket = await self._connect.__aenter__()
77
77
 
78
78
  try:
79
+ settings = get_current_settings()
80
+ auth_token = (
81
+ settings.api.auth_string.get_secret_value()
82
+ if settings.api.auth_string
83
+ else None
84
+ )
85
+ api_key = settings.api.key.get_secret_value() if settings.api.key else None
86
+ token = auth_token or api_key # Prioritize auth_token
87
+
79
88
  await websocket.send(
80
- orjson.dumps(
81
- {"type": "auth", "token": PREFECT_API_KEY.value()}
82
- ).decode()
89
+ orjson.dumps({"type": "auth", "token": token}).decode()
83
90
  )
84
91
 
85
92
  auth: dict[str, Any] = orjson.loads(await websocket.recv())
@@ -107,11 +114,13 @@ class Subscription(Generic[S]):
107
114
  reason = None
108
115
 
109
116
  if reason:
110
- raise Exception(
111
- "Unable to authenticate to the subscription. Please "
112
- "ensure the provided `PREFECT_API_KEY` you are using is "
113
- f"valid for this environment. Reason: {reason}"
114
- ) from e
117
+ error_message = (
118
+ "Unable to authenticate to the subscription. Please ensure the provided "
119
+ "`PREFECT_API_AUTH_STRING` (for self-hosted with auth string) or "
120
+ "`PREFECT_API_KEY` (for Cloud or self-hosted with API key) "
121
+ f"you are using is valid for this environment. Reason: {reason}"
122
+ )
123
+ raise Exception(error_message) from e
115
124
  raise
116
125
  else:
117
126
  self._websocket = websocket
prefect/events/clients.py CHANGED
@@ -684,8 +684,8 @@ class PrefectEventSubscriber:
684
684
 
685
685
  async def __aexit__(
686
686
  self,
687
- exc_type: Optional[Type[Exception]],
688
- exc_val: Optional[Exception],
687
+ exc_type: Optional[Type[BaseException]],
688
+ exc_val: Optional[BaseException],
689
689
  exc_tb: Optional[TracebackType],
690
690
  ) -> None:
691
691
  self._websocket = None
@@ -0,0 +1,60 @@
1
+ import asyncio
2
+ import uuid
3
+ from contextlib import AsyncExitStack
4
+ from typing import Any, Protocol
5
+
6
+ from prefect.events.clients import PrefectEventSubscriber, get_events_subscriber
7
+ from prefect.events.filters import EventFilter, EventNameFilter
8
+ from prefect.logging.loggers import get_logger
9
+
10
+
11
+ class OnCancellingCallback(Protocol):
12
+ def __call__(self, flow_run_id: uuid.UUID) -> None: ...
13
+
14
+
15
+ class FlowRunCancellingObserver:
16
+ def __init__(self, on_cancelling: OnCancellingCallback):
17
+ self.logger = get_logger("FlowRunCancellingObserver")
18
+ self.on_cancelling = on_cancelling
19
+ self._events_subscriber: PrefectEventSubscriber | None
20
+ self._exit_stack = AsyncExitStack()
21
+
22
+ async def _consume_events(self):
23
+ if self._events_subscriber is None:
24
+ raise RuntimeError(
25
+ "Events subscriber not initialized. Please use `async with` to initialize the observer."
26
+ )
27
+ async for event in self._events_subscriber:
28
+ try:
29
+ flow_run_id = uuid.UUID(
30
+ event.resource["prefect.resource.id"].replace(
31
+ "prefect.flow-run.", ""
32
+ )
33
+ )
34
+ self.on_cancelling(flow_run_id)
35
+ except ValueError:
36
+ self.logger.debug(
37
+ "Received event with invalid flow run ID: %s",
38
+ event.resource["prefect.resource.id"],
39
+ )
40
+
41
+ async def __aenter__(self):
42
+ self._events_subscriber = await self._exit_stack.enter_async_context(
43
+ get_events_subscriber(
44
+ filter=EventFilter(
45
+ event=EventNameFilter(name=["prefect.flow-run.Cancelling"])
46
+ )
47
+ )
48
+ )
49
+ self._consumer_task = asyncio.create_task(self._consume_events())
50
+ return self
51
+
52
+ async def __aexit__(self, *exc_info: Any):
53
+ await self._exit_stack.__aexit__(*exc_info)
54
+ self._consumer_task.cancel()
55
+ try:
56
+ await self._consumer_task
57
+ except asyncio.CancelledError:
58
+ pass
59
+ except Exception:
60
+ self.logger.exception("Error consuming events")
prefect/runner/runner.py CHANGED
@@ -46,6 +46,8 @@ import subprocess
46
46
  import sys
47
47
  import tempfile
48
48
  import threading
49
+ import uuid
50
+ from contextlib import AsyncExitStack
49
51
  from copy import deepcopy
50
52
  from functools import partial
51
53
  from pathlib import Path
@@ -80,13 +82,6 @@ from prefect._internal.concurrency.api import (
80
82
  from_sync,
81
83
  )
82
84
  from prefect.client.orchestration import PrefectClient, get_client
83
- from prefect.client.schemas.filters import (
84
- FlowRunFilter,
85
- FlowRunFilterId,
86
- FlowRunFilterState,
87
- FlowRunFilterStateName,
88
- FlowRunFilterStateType,
89
- )
90
85
  from prefect.client.schemas.objects import (
91
86
  ConcurrencyLimitConfig,
92
87
  State,
@@ -100,6 +95,7 @@ from prefect.events.utilities import emit_event
100
95
  from prefect.exceptions import Abort, ObjectNotFound
101
96
  from prefect.flows import Flow, FlowStateHook, load_flow_from_flow_run
102
97
  from prefect.logging.loggers import PrefectLogAdapter, flow_run_logger, get_logger
98
+ from prefect.runner._observers import FlowRunCancellingObserver
103
99
  from prefect.runner.storage import RunnerStorage
104
100
  from prefect.schedules import Schedule
105
101
  from prefect.settings import (
@@ -229,6 +225,7 @@ class Runner:
229
225
  raise ValueError("Heartbeat must be 30 seconds or greater.")
230
226
  self._heartbeat_task: asyncio.Task[None] | None = None
231
227
 
228
+ self._exit_stack = AsyncExitStack()
232
229
  self._limiter: anyio.CapacityLimiter | None = None
233
230
  self._client: PrefectClient = get_client()
234
231
  self._submitting_flow_run_ids: set[UUID] = set()
@@ -501,15 +498,6 @@ class Runner:
501
498
  jitter_range=0.3,
502
499
  )
503
500
  )
504
- loops_task_group.start_soon(
505
- partial(
506
- critical_service_loop,
507
- workload=runner._check_for_cancelled_flow_runs,
508
- interval=self.query_seconds * 2,
509
- run_once=run_once,
510
- jitter_range=0.3,
511
- )
512
- )
513
501
 
514
502
  def execute_in_background(
515
503
  self, func: Callable[..., Any], *args: Any, **kwargs: Any
@@ -583,58 +571,42 @@ class Runner:
583
571
  if not self._acquire_limit_slot(flow_run_id):
584
572
  return
585
573
 
586
- async with anyio.create_task_group() as tg:
587
- with anyio.CancelScope():
588
- self._submitting_flow_run_ids.add(flow_run_id)
589
- flow_run = await self._client.read_flow_run(flow_run_id)
590
-
591
- process: (
592
- anyio.abc.Process | Exception
593
- ) = await self._runs_task_group.start(
594
- partial(
595
- self._submit_run_and_capture_errors,
596
- flow_run=flow_run,
597
- entrypoint=entrypoint,
598
- command=command,
599
- cwd=cwd,
600
- env=env,
601
- stream_output=stream_output,
602
- ),
603
- )
604
- if isinstance(process, Exception):
605
- return
574
+ self._submitting_flow_run_ids.add(flow_run_id)
575
+ flow_run = await self._client.read_flow_run(flow_run_id)
606
576
 
607
- task_status.started(process.pid)
577
+ process: anyio.abc.Process | Exception = await self._runs_task_group.start(
578
+ partial(
579
+ self._submit_run_and_capture_errors,
580
+ flow_run=flow_run,
581
+ entrypoint=entrypoint,
582
+ command=command,
583
+ cwd=cwd,
584
+ env=env,
585
+ stream_output=stream_output,
586
+ ),
587
+ )
588
+ if isinstance(process, Exception):
589
+ return
608
590
 
609
- if self.heartbeat_seconds is not None:
610
- await self._emit_flow_run_heartbeat(flow_run)
591
+ task_status.started(process.pid)
611
592
 
612
- async with self._flow_run_process_map_lock:
613
- # Only add the process to the map if it is still running
614
- if process.returncode is None:
615
- self._flow_run_process_map[flow_run.id] = ProcessMapEntry(
616
- pid=process.pid, flow_run=flow_run
617
- )
593
+ if self.heartbeat_seconds is not None:
594
+ await self._emit_flow_run_heartbeat(flow_run)
618
595
 
619
- # We want this loop to stop when the flow run process exits
620
- # so we'll check if the flow run process is still alive on
621
- # each iteration and cancel the task group if it is not.
622
- workload = partial(
623
- self._check_for_cancelled_flow_runs,
624
- should_stop=lambda: not self._flow_run_process_map,
625
- on_stop=tg.cancel_scope.cancel,
596
+ async with self._flow_run_process_map_lock:
597
+ # Only add the process to the map if it is still running
598
+ if process.returncode is None:
599
+ self._flow_run_process_map[flow_run.id] = ProcessMapEntry(
600
+ pid=process.pid, flow_run=flow_run
626
601
  )
627
602
 
628
- tg.start_soon(
629
- partial(
630
- critical_service_loop,
631
- workload=workload,
632
- interval=self.query_seconds,
633
- jitter_range=0.3,
634
- )
635
- )
603
+ while True:
604
+ # Wait until flow run execution is complete and the process has been removed from the map
605
+ await anyio.sleep(0.1)
606
+ if self._flow_run_process_map.get(flow_run.id) is None:
607
+ break
636
608
 
637
- return process
609
+ return process
638
610
 
639
611
  async def execute_bundle(
640
612
  self,
@@ -673,24 +645,8 @@ class Runner:
673
645
  )
674
646
  self._flow_run_bundle_map[flow_run.id] = bundle
675
647
 
676
- tasks: list[asyncio.Task[None]] = []
677
- tasks.append(
678
- asyncio.create_task(
679
- critical_service_loop(
680
- workload=self._check_for_cancelled_flow_runs,
681
- interval=self.query_seconds,
682
- jitter_range=0.3,
683
- )
684
- )
685
- )
686
-
687
648
  await anyio.to_thread.run_sync(process.join)
688
649
 
689
- for task in tasks:
690
- task.cancel()
691
-
692
- await asyncio.gather(*tasks, return_exceptions=True)
693
-
694
650
  self._flow_run_process_map.pop(flow_run.id)
695
651
 
696
652
  flow_run_logger = self._get_flow_run_logger(flow_run)
@@ -1000,83 +956,11 @@ class Runner:
1000
956
  self.last_polled: datetime.datetime = now("UTC")
1001
957
  return await self._submit_scheduled_flow_runs(flow_run_response=runs_response)
1002
958
 
1003
- async def _check_for_cancelled_flow_runs(
1004
- self,
1005
- should_stop: Callable[[], bool] = lambda: False,
1006
- on_stop: Callable[[], None] = lambda: None,
959
+ async def _cancel_run(
960
+ self, flow_run: "FlowRun | uuid.UUID", state_msg: Optional[str] = None
1007
961
  ):
1008
- """
1009
- Checks for flow runs with CANCELLING a cancelling state and attempts to
1010
- cancel them.
1011
-
1012
- Args:
1013
- should_stop: A callable that returns a boolean indicating whether or not
1014
- the runner should stop checking for cancelled flow runs.
1015
- on_stop: A callable that is called when the runner should stop checking
1016
- for cancelled flow runs.
1017
- """
1018
- if self.stopping:
1019
- return
1020
- if not self.started:
1021
- raise RuntimeError(
1022
- "Runner is not set up. Please make sure you are running this runner "
1023
- "as an async context manager."
1024
- )
1025
-
1026
- if should_stop():
1027
- self._logger.debug(
1028
- "Runner has no active flow runs or deployments. Sending message to loop"
1029
- " service that no further cancellation checks are needed."
1030
- )
1031
- on_stop()
1032
-
1033
- self._logger.debug("Checking for cancelled flow runs...")
1034
-
1035
- named_cancelling_flow_runs = await self._client.read_flow_runs(
1036
- flow_run_filter=FlowRunFilter(
1037
- state=FlowRunFilterState(
1038
- type=FlowRunFilterStateType(any_=[StateType.CANCELLED]),
1039
- name=FlowRunFilterStateName(any_=["Cancelling"]),
1040
- ),
1041
- # Avoid duplicate cancellation calls
1042
- id=FlowRunFilterId(
1043
- any_=list(
1044
- self._flow_run_process_map.keys()
1045
- - self._cancelling_flow_run_ids
1046
- )
1047
- ),
1048
- ),
1049
- )
1050
-
1051
- typed_cancelling_flow_runs = await self._client.read_flow_runs(
1052
- flow_run_filter=FlowRunFilter(
1053
- state=FlowRunFilterState(
1054
- type=FlowRunFilterStateType(any_=[StateType.CANCELLING]),
1055
- ),
1056
- # Avoid duplicate cancellation calls
1057
- id=FlowRunFilterId(
1058
- any_=list(
1059
- self._flow_run_process_map.keys()
1060
- - self._cancelling_flow_run_ids
1061
- )
1062
- ),
1063
- ),
1064
- )
1065
-
1066
- cancelling_flow_runs = named_cancelling_flow_runs + typed_cancelling_flow_runs
1067
-
1068
- if cancelling_flow_runs:
1069
- self._logger.info(
1070
- f"Found {len(cancelling_flow_runs)} flow runs awaiting cancellation."
1071
- )
1072
-
1073
- for flow_run in cancelling_flow_runs:
1074
- self._cancelling_flow_run_ids.add(flow_run.id)
1075
- self._runs_task_group.start_soon(self._cancel_run, flow_run)
1076
-
1077
- return cancelling_flow_runs
1078
-
1079
- async def _cancel_run(self, flow_run: "FlowRun", state_msg: Optional[str] = None):
962
+ if isinstance(flow_run, uuid.UUID):
963
+ flow_run = await self._client.read_flow_run(flow_run)
1080
964
  run_logger = self._get_flow_run_logger(flow_run)
1081
965
 
1082
966
  process_map_entry = self._flow_run_process_map.get(flow_run.id)
@@ -1543,43 +1427,6 @@ class Runner:
1543
1427
 
1544
1428
  await self._client.set_flow_run_state(flow_run.id, state, force=True)
1545
1429
 
1546
- # Do not remove the flow run from the cancelling set immediately because
1547
- # the API caches responses for the `read_flow_runs` and we do not want to
1548
- # duplicate cancellations.
1549
- await self._schedule_task(
1550
- 60 * 10, self._cancelling_flow_run_ids.remove, flow_run.id
1551
- )
1552
-
1553
- async def _schedule_task(
1554
- self, __in_seconds: int, fn: Callable[..., Any], *args: Any, **kwargs: Any
1555
- ) -> None:
1556
- """
1557
- Schedule a background task to start after some time.
1558
-
1559
- These tasks will be run immediately when the runner exits instead of waiting.
1560
-
1561
- The function may be async or sync. Async functions will be awaited.
1562
- """
1563
-
1564
- async def wrapper(task_status: anyio.abc.TaskStatus[None]) -> None:
1565
- # If we are shutting down, do not sleep; otherwise sleep until the scheduled
1566
- # time or shutdown
1567
- if self.started:
1568
- with anyio.CancelScope() as scope:
1569
- self._scheduled_task_scopes.add(scope)
1570
- task_status.started()
1571
- await anyio.sleep(__in_seconds)
1572
-
1573
- self._scheduled_task_scopes.remove(scope)
1574
- else:
1575
- task_status.started()
1576
-
1577
- result = fn(*args, **kwargs)
1578
- if asyncio.iscoroutine(result):
1579
- await result
1580
-
1581
- await self._runs_task_group.start(wrapper)
1582
-
1583
1430
  async def _run_on_cancellation_hooks(
1584
1431
  self,
1585
1432
  flow_run: "FlowRun",
@@ -1647,11 +1494,18 @@ class Runner:
1647
1494
  if not hasattr(self, "_loop") or not self._loop:
1648
1495
  self._loop = asyncio.get_event_loop()
1649
1496
 
1650
- await self._client.__aenter__()
1497
+ await self._exit_stack.enter_async_context(
1498
+ FlowRunCancellingObserver(
1499
+ on_cancelling=lambda flow_run_id: self._runs_task_group.start_soon(
1500
+ self._cancel_run, flow_run_id
1501
+ )
1502
+ )
1503
+ )
1504
+ await self._exit_stack.enter_async_context(self._client)
1651
1505
 
1652
1506
  if not hasattr(self, "_runs_task_group") or not self._runs_task_group:
1653
1507
  self._runs_task_group: anyio.abc.TaskGroup = anyio.create_task_group()
1654
- await self._runs_task_group.__aenter__()
1508
+ await self._exit_stack.enter_async_context(self._runs_task_group)
1655
1509
 
1656
1510
  if not hasattr(self, "_loops_task_group") or not self._loops_task_group:
1657
1511
  self._loops_task_group: anyio.abc.TaskGroup = anyio.create_task_group()
@@ -1677,11 +1531,7 @@ class Runner:
1677
1531
  for scope in self._scheduled_task_scopes:
1678
1532
  scope.cancel()
1679
1533
 
1680
- if self._runs_task_group:
1681
- await self._runs_task_group.__aexit__(*exc_info)
1682
-
1683
- if self._client:
1684
- await self._client.__aexit__(*exc_info)
1534
+ await self._exit_stack.__aexit__(*exc_info)
1685
1535
 
1686
1536
  shutil.rmtree(str(self._tmp_dir))
1687
1537
  del self._runs_task_group, self._loops_task_group
prefect/tasks.py CHANGED
@@ -1551,7 +1551,7 @@ class Task(Generic[P, R]):
1551
1551
  validated_state=task_run.state,
1552
1552
  )
1553
1553
 
1554
- if task_run_url := url_for(task_run):
1554
+ if get_current_settings().ui_url and (task_run_url := url_for(task_run)):
1555
1555
  logger.info(
1556
1556
  f"Created task run {task_run.name!r}. View it in the UI at {task_run_url!r}"
1557
1557
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prefect-client
3
- Version: 3.4.0
3
+ Version: 3.4.1.dev2
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=he53eMvLm7NsraWSPtkBQjfJ16fUU8YPCI6caWK9kN0,180
4
+ prefect/_build_info.py,sha256=qHCpV6KpRqnsAiZVjqF9RvA2dX5er6gG6lSsXYjxJw4,185
5
5
  prefect/_result_records.py,sha256=S6QmsODkehGVSzbMm6ig022PYbI6gNKz671p_8kBYx4,7789
6
6
  prefect/_versioning.py,sha256=YqR5cxXrY4P6LM1Pmhd8iMo7v_G2KJpGNdsf4EvDFQ0,14132
7
7
  prefect/_waiters.py,sha256=Ia2ITaXdHzevtyWIgJoOg95lrEXQqNEOquHvw3T33UQ,9026
@@ -28,7 +28,7 @@ prefect/task_engine.py,sha256=j0rr8IyBinJmKPD-486RYWKZakhifkEE9ppPCJ9Es-U,62463
28
28
  prefect/task_runners.py,sha256=vzJ1kiW1z90Fkkg21QNhPwjfLoDy6rVsUAToXqb6FUE,16206
29
29
  prefect/task_runs.py,sha256=7LIzfo3fondCyEUpU05sYFN5IfpZigBDXrhG5yc-8t0,9039
30
30
  prefect/task_worker.py,sha256=gMj_rl4EjTrnJ5YSOXinC6y-7KSK7fRQt_UYbZbrrV8,17879
31
- prefect/tasks.py,sha256=EpMw5O1B9pAFVraC0KzytMOKi8iy7ZYnKWRs7WtvogU,74742
31
+ prefect/tasks.py,sha256=DODF_1xPDQVvj_paJDWm43RS46Jdx9_7b2huqT_QyiM,74778
32
32
  prefect/transactions.py,sha256=uIoPNudzJzH6NrMJhrgr5lyh6JxOJQqT1GvrXt69yNw,26068
33
33
  prefect/variables.py,sha256=dCK3vX7TbkqXZhnNT_v7rcGh3ISRqoR6pJVLpoll3Js,8342
34
34
  prefect/_experimental/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -82,9 +82,9 @@ prefect/client/base.py,sha256=7VAMyoy8KtmtI-H8KYsI16_uw9TlrXSrcxChFuMp65Q,26269
82
82
  prefect/client/cloud.py,sha256=jnFgg0osMVDGbLjdWkDX3rQg_0pI_zvfSlU480XCWGQ,6523
83
83
  prefect/client/collections.py,sha256=t9XkVU_onQMZ871L21F1oZnAiPSQeeVfd_MuDEBS3iM,1050
84
84
  prefect/client/constants.py,sha256=Z_GG8KF70vbbXxpJuqW5pLnwzujTVeHbcYYRikNmGH0,29
85
- prefect/client/subscriptions.py,sha256=b2gjoWjrTjshnv_s6zlPN3t0JIe2EKAdMqEzj3-kc6w,3879
85
+ prefect/client/subscriptions.py,sha256=PTYi1Pp7rX-aGdcxZkxRBZkZnpzBt1P17APsm05EDR8,4376
86
86
  prefect/client/utilities.py,sha256=UEJD6nwYg2mD8-GSmru-E2ofXaBlmSFZ2-8T_5rIK6c,3472
87
- prefect/client/orchestration/__init__.py,sha256=O6tItUwU1NBycVPf0PoYVT8bF8gfrVoe9eaSmTQTNFU,55485
87
+ prefect/client/orchestration/__init__.py,sha256=DPbazZvQDgoSZipuNk4z_AILgJbM6zBld-1OsVH55ME,55831
88
88
  prefect/client/orchestration/base.py,sha256=HM6ryHBZSzuHoCFQM9u5qR5k1dN9Bbr_ah6z1UPNbZQ,1542
89
89
  prefect/client/orchestration/routes.py,sha256=_-HC-EmgMhsYdmGwZTxIXlINaVzYuX7RZAvzjHbVp-4,4266
90
90
  prefect/client/orchestration/_artifacts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -148,7 +148,7 @@ prefect/docker/__init__.py,sha256=z6wdc6UFfiBG2jb9Jk64uCWVM04JKVWeVyDWwuuon8M,52
148
148
  prefect/docker/docker_image.py,sha256=bR_pEq5-FDxlwTj8CP_7nwZ_MiGK6KxIi8v7DRjy1Kg,3138
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=c5ZTt-ZVslvDr6-OrbsWb_7XUocWptGyAuVAVtAzokY,27589
151
+ prefect/events/clients.py,sha256=gp3orepQav99303OC-zK6uz3dpyLlLpQ9ZWJEDol0cs,27597
152
152
  prefect/events/filters.py,sha256=2hVfzc3Rdgy0mBHDutWxT__LJY0zpVM8greWX3y6kjM,8233
153
153
  prefect/events/related.py,sha256=CTeexYUmmA93V4gsR33GIFmw-SS-X_ouOpRg-oeq-BU,6672
154
154
  prefect/events/utilities.py,sha256=ww34bTMENCNwcp6RhhgzG0KgXOvKGe0MKmBdSJ8NpZY,3043
@@ -184,7 +184,8 @@ prefect/logging/highlighters.py,sha256=BCf_LNhFInIfGPqwuu8YVrGa4wVxNc4YXo2pYgftp
184
184
  prefect/logging/loggers.py,sha256=rwFJv0i3dhdKr25XX-xUkQy4Vv4dy18bTy366jrC0OQ,12741
185
185
  prefect/logging/logging.yml,sha256=tT7gTyC4NmngFSqFkCdHaw7R0GPNPDDsTCGZQByiJAQ,3169
186
186
  prefect/runner/__init__.py,sha256=pQBd9wVrUVUDUFJlgiweKSnbahoBZwqnd2O2jkhrULY,158
187
- prefect/runner/runner.py,sha256=hk-y9Y29rpB7p08u9hlt4V8KmXUGMvkF9DE8uBxuXdI,65118
187
+ prefect/runner/_observers.py,sha256=PpyXQL5bjp86AnDFEzcFPS5ayL6ExqcYgyuBMMQCO9Q,2183
188
+ prefect/runner/runner.py,sha256=DFgZQTkKwmCDMmfA640xY1oTOCURzTOo7HOtwQxRVwA,59443
188
189
  prefect/runner/server.py,sha256=YRYFNoYddA9XfiTIYtudxrnD1vCX-PaOLhvyGUOb9AQ,11966
189
190
  prefect/runner/storage.py,sha256=n-65YoEf7KNVInnmMPeP5TVFJOa2zOS8w9en9MHi6uo,31328
190
191
  prefect/runner/submit.py,sha256=qOEj-NChQ6RYFV35hHEVMTklrNmKwaGs2mR78ku9H0o,9474
@@ -318,7 +319,7 @@ prefect/workers/cloud.py,sha256=dPvG1jDGD5HSH7aM2utwtk6RaJ9qg13XjkA0lAIgQmY,287
318
319
  prefect/workers/process.py,sha256=Yi5D0U5AQ51wHT86GdwtImXSefe0gJf3LGq4r4z9zwM,11090
319
320
  prefect/workers/server.py,sha256=2pmVeJZiVbEK02SO6BEZaBIvHMsn6G8LzjW8BXyiTtk,1952
320
321
  prefect/workers/utilities.py,sha256=VfPfAlGtTuDj0-Kb8WlMgAuOfgXCdrGAnKMapPSBrwc,2483
321
- prefect_client-3.4.0.dist-info/METADATA,sha256=UbF7RUupdDJ_R4xFe6ybCcDpsKc9d-BwIdHOF4VTVXM,7466
322
- prefect_client-3.4.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
323
- prefect_client-3.4.0.dist-info/licenses/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
324
- prefect_client-3.4.0.dist-info/RECORD,,
322
+ prefect_client-3.4.1.dev2.dist-info/METADATA,sha256=SrQm0IQPihKCyz3wiIcpgc7slcilDL4wdt9-gV9G2xk,7471
323
+ prefect_client-3.4.1.dev2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
324
+ prefect_client-3.4.1.dev2.dist-info/licenses/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
325
+ prefect_client-3.4.1.dev2.dist-info/RECORD,,