prefect-client 3.1.11__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.
Files changed (56) hide show
  1. prefect/_experimental/sla/__init__.py +0 -0
  2. prefect/_experimental/sla/client.py +66 -0
  3. prefect/_experimental/sla/objects.py +53 -0
  4. prefect/_version.py +3 -3
  5. prefect/automations.py +236 -30
  6. prefect/blocks/__init__.py +3 -3
  7. prefect/blocks/abstract.py +53 -30
  8. prefect/blocks/core.py +181 -82
  9. prefect/blocks/notifications.py +133 -73
  10. prefect/blocks/redis.py +13 -9
  11. prefect/blocks/system.py +24 -11
  12. prefect/blocks/webhook.py +7 -5
  13. prefect/cache_policies.py +3 -2
  14. prefect/client/orchestration/__init__.py +103 -2006
  15. prefect/client/orchestration/_automations/__init__.py +0 -0
  16. prefect/client/orchestration/_automations/client.py +329 -0
  17. prefect/client/orchestration/_blocks_documents/__init__.py +0 -0
  18. prefect/client/orchestration/_blocks_documents/client.py +334 -0
  19. prefect/client/orchestration/_blocks_schemas/__init__.py +0 -0
  20. prefect/client/orchestration/_blocks_schemas/client.py +200 -0
  21. prefect/client/orchestration/_blocks_types/__init__.py +0 -0
  22. prefect/client/orchestration/_blocks_types/client.py +380 -0
  23. prefect/client/orchestration/_deployments/__init__.py +0 -0
  24. prefect/client/orchestration/_deployments/client.py +1128 -0
  25. prefect/client/orchestration/_flow_runs/__init__.py +0 -0
  26. prefect/client/orchestration/_flow_runs/client.py +903 -0
  27. prefect/client/orchestration/_flows/__init__.py +0 -0
  28. prefect/client/orchestration/_flows/client.py +343 -0
  29. prefect/client/orchestration/_logs/client.py +16 -14
  30. prefect/client/schemas/__init__.py +68 -28
  31. prefect/client/schemas/objects.py +5 -5
  32. prefect/context.py +15 -1
  33. prefect/deployments/base.py +6 -0
  34. prefect/deployments/runner.py +42 -1
  35. prefect/engine.py +17 -4
  36. prefect/filesystems.py +6 -2
  37. prefect/flow_engine.py +47 -38
  38. prefect/flows.py +10 -1
  39. prefect/logging/logging.yml +1 -1
  40. prefect/runner/runner.py +4 -2
  41. prefect/settings/models/cloud.py +5 -0
  42. prefect/settings/models/experiments.py +0 -5
  43. prefect/states.py +57 -38
  44. prefect/task_runners.py +56 -55
  45. prefect/task_worker.py +2 -2
  46. prefect/tasks.py +6 -4
  47. prefect/telemetry/bootstrap.py +10 -9
  48. prefect/telemetry/services.py +4 -0
  49. prefect/utilities/templating.py +25 -1
  50. prefect/workers/base.py +6 -3
  51. prefect/workers/process.py +1 -1
  52. {prefect_client-3.1.11.dist-info → prefect_client-3.1.12.dist-info}/METADATA +2 -2
  53. {prefect_client-3.1.11.dist-info → prefect_client-3.1.12.dist-info}/RECORD +56 -39
  54. {prefect_client-3.1.11.dist-info → prefect_client-3.1.12.dist-info}/LICENSE +0 -0
  55. {prefect_client-3.1.11.dist-info → prefect_client-3.1.12.dist-info}/WHEEL +0 -0
  56. {prefect_client-3.1.11.dist-info → prefect_client-3.1.12.dist-info}/top_level.txt +0 -0
@@ -36,6 +36,7 @@ from pathlib import Path
36
36
  from typing import TYPE_CHECKING, Any, ClassVar, Iterable, List, Optional, Union
37
37
  from uuid import UUID
38
38
 
39
+ from exceptiongroup import ExceptionGroup # novermin
39
40
  from pydantic import (
40
41
  BaseModel,
41
42
  ConfigDict,
@@ -48,12 +49,14 @@ from rich.console import Console
48
49
  from rich.progress import Progress, SpinnerColumn, TextColumn, track
49
50
  from rich.table import Table
50
51
 
52
+ from prefect._experimental.sla.objects import SlaTypes
51
53
  from prefect._internal.concurrency.api import create_call, from_async
52
54
  from prefect._internal.schemas.validators import (
53
55
  reconcile_paused_deployment,
54
56
  reconcile_schedules_runner,
55
57
  )
56
- from prefect.client.orchestration import get_client
58
+ from prefect.client.base import ServerType
59
+ from prefect.client.orchestration import PrefectClient, get_client
57
60
  from prefect.client.schemas.actions import DeploymentScheduleCreate
58
61
  from prefect.client.schemas.filters import WorkerFilter, WorkerFilterStatus
59
62
  from prefect.client.schemas.objects import (
@@ -128,6 +131,7 @@ class RunnerDeployment(BaseModel):
128
131
  job_variables: Settings used to override the values specified default base job template
129
132
  of the chosen work pool. Refer to the base job template of the chosen work pool for
130
133
  available settings.
134
+ _sla: (Experimental) SLA configuration for the deployment. May be removed or modified at any time. Currently only supported on Prefect Cloud.
131
135
  """
132
136
 
133
137
  model_config: ClassVar[ConfigDict] = ConfigDict(arbitrary_types_allowed=True)
@@ -207,6 +211,10 @@ class RunnerDeployment(BaseModel):
207
211
  " a built runner."
208
212
  ),
209
213
  )
214
+ # (Experimental) SLA configuration for the deployment. May be removed or modified at any time. Currently only supported on Prefect Cloud.
215
+ _sla: Optional[Union[SlaTypes, list[SlaTypes]]] = PrivateAttr(
216
+ default=None,
217
+ )
210
218
  _entrypoint_type: EntrypointType = PrivateAttr(
211
219
  default=EntrypointType.FILE_PATH,
212
220
  )
@@ -351,8 +359,32 @@ class RunnerDeployment(BaseModel):
351
359
  trigger.set_deployment_id(deployment_id)
352
360
  await client.create_automation(trigger.as_automation())
353
361
 
362
+ # We plan to support SLA configuration on the Prefect Server in the future.
363
+ # For now, we only support it on Prefect Cloud.
364
+ if self._sla:
365
+ await self._create_slas(deployment_id, client)
366
+
354
367
  return deployment_id
355
368
 
369
+ async def _create_slas(self, deployment_id: UUID, client: PrefectClient):
370
+ if not isinstance(self._sla, list):
371
+ self._sla = [self._sla]
372
+
373
+ if client.server_type == ServerType.CLOUD:
374
+ exceptions = []
375
+ for sla in self._sla:
376
+ try:
377
+ sla.set_deployment_id(deployment_id)
378
+ await client.create_sla(sla)
379
+ except Exception as e:
380
+ exceptions.append(e)
381
+ if exceptions:
382
+ raise ExceptionGroup("Failed to create SLAs", exceptions) # novermin
383
+ else:
384
+ raise ValueError(
385
+ "SLA configuration is currently only supported on Prefect Cloud."
386
+ )
387
+
356
388
  @staticmethod
357
389
  def _construct_deployment_schedules(
358
390
  interval: Optional[
@@ -467,6 +499,7 @@ class RunnerDeployment(BaseModel):
467
499
  work_queue_name: Optional[str] = None,
468
500
  job_variables: Optional[dict[str, Any]] = None,
469
501
  entrypoint_type: EntrypointType = EntrypointType.FILE_PATH,
502
+ _sla: Optional[Union[SlaTypes, list[SlaTypes]]] = None, # experimental
470
503
  ) -> "RunnerDeployment":
471
504
  """
472
505
  Configure a deployment for a given flow.
@@ -497,6 +530,7 @@ class RunnerDeployment(BaseModel):
497
530
  job_variables: Settings used to override the values specified default base job template
498
531
  of the chosen work pool. Refer to the base job template of the chosen work pool for
499
532
  available settings.
533
+ _sla: (Experimental) SLA configuration for the deployment. May be removed or modified at any time. Currently only supported on Prefect Cloud.
500
534
  """
501
535
  constructed_schedules = cls._construct_deployment_schedules(
502
536
  interval=interval,
@@ -532,6 +566,7 @@ class RunnerDeployment(BaseModel):
532
566
  work_queue_name=work_queue_name,
533
567
  job_variables=job_variables,
534
568
  )
569
+ deployment._sla = _sla
535
570
 
536
571
  if not deployment.entrypoint:
537
572
  no_file_location_error = (
@@ -607,6 +642,7 @@ class RunnerDeployment(BaseModel):
607
642
  work_pool_name: Optional[str] = None,
608
643
  work_queue_name: Optional[str] = None,
609
644
  job_variables: Optional[dict[str, Any]] = None,
645
+ _sla: Optional[Union[SlaTypes, list[SlaTypes]]] = None, # experimental
610
646
  ) -> "RunnerDeployment":
611
647
  """
612
648
  Configure a deployment for a given flow located at a given entrypoint.
@@ -638,6 +674,7 @@ class RunnerDeployment(BaseModel):
638
674
  job_variables: Settings used to override the values specified default base job template
639
675
  of the chosen work pool. Refer to the base job template of the chosen work pool for
640
676
  available settings.
677
+ _sla: (Experimental) SLA configuration for the deployment. May be removed or modified at any time. Currently only supported on Prefect Cloud.
641
678
  """
642
679
  from prefect.flows import load_flow_from_entrypoint
643
680
 
@@ -677,6 +714,7 @@ class RunnerDeployment(BaseModel):
677
714
  work_queue_name=work_queue_name,
678
715
  job_variables=job_variables,
679
716
  )
717
+ deployment._sla = _sla
680
718
  deployment._path = str(Path.cwd())
681
719
 
682
720
  cls._set_defaults_from_flow(deployment, flow)
@@ -708,6 +746,7 @@ class RunnerDeployment(BaseModel):
708
746
  work_pool_name: Optional[str] = None,
709
747
  work_queue_name: Optional[str] = None,
710
748
  job_variables: Optional[dict[str, Any]] = None,
749
+ _sla: Optional[Union[SlaTypes, list[SlaTypes]]] = None, # experimental
711
750
  ):
712
751
  """
713
752
  Create a RunnerDeployment from a flow located at a given entrypoint and stored in a
@@ -739,6 +778,7 @@ class RunnerDeployment(BaseModel):
739
778
  job_variables: Settings used to override the values specified default base job template
740
779
  of the chosen work pool. Refer to the base job template of the chosen work pool for
741
780
  available settings.
781
+ _sla: (Experimental) SLA configuration for the deployment. May be removed or modified at any time. Currently only supported on Prefect Cloud.
742
782
  """
743
783
  from prefect.flows import load_flow_from_entrypoint
744
784
 
@@ -787,6 +827,7 @@ class RunnerDeployment(BaseModel):
787
827
  work_queue_name=work_queue_name,
788
828
  job_variables=job_variables,
789
829
  )
830
+ deployment._sla = _sla
790
831
  deployment._path = str(storage.destination).replace(
791
832
  tmpdir, "$STORAGE_BASE_PATH"
792
833
  )
prefect/engine.py CHANGED
@@ -31,16 +31,29 @@ if __name__ == "__main__":
31
31
 
32
32
  try:
33
33
  from prefect.flow_engine import (
34
- load_flow_and_flow_run,
34
+ flow_run_logger,
35
+ load_flow,
36
+ load_flow_run,
35
37
  run_flow,
36
38
  )
37
39
 
38
- flow_run, flow = load_flow_and_flow_run(flow_run_id=flow_run_id)
40
+ flow_run = load_flow_run(flow_run_id=flow_run_id)
41
+ run_logger = flow_run_logger(flow_run=flow_run)
42
+
43
+ try:
44
+ flow = load_flow(flow_run)
45
+ except Exception:
46
+ run_logger.error(
47
+ "Unexpected exception encountered when trying to load flow",
48
+ exc_info=True,
49
+ )
50
+ raise
51
+
39
52
  # run the flow
40
53
  if flow.isasync:
41
- run_coro_as_sync(run_flow(flow, flow_run=flow_run))
54
+ run_coro_as_sync(run_flow(flow, flow_run=flow_run, error_logger=run_logger))
42
55
  else:
43
- run_flow(flow, flow_run=flow_run)
56
+ run_flow(flow, flow_run=flow_run, error_logger=run_logger)
44
57
 
45
58
  except Abort as exc:
46
59
  engine_logger.info(
prefect/filesystems.py CHANGED
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import abc
2
4
  import urllib.parse
3
5
  from pathlib import Path
@@ -92,7 +94,9 @@ class LocalFileSystem(WritableFileSystem, WritableDeploymentStorage):
92
94
  )
93
95
 
94
96
  @field_validator("basepath", mode="before")
95
- def cast_pathlib(cls, value):
97
+ def cast_pathlib(cls, value: str | Path | None) -> str | None:
98
+ if value is None:
99
+ return value
96
100
  return stringify_path(value)
97
101
 
98
102
  def _resolve_path(self, path: str, validate: bool = False) -> Path:
@@ -132,7 +136,7 @@ class LocalFileSystem(WritableFileSystem, WritableDeploymentStorage):
132
136
  Defaults to copying the entire contents of the block's basepath to the current working directory.
133
137
  """
134
138
  if not from_path:
135
- from_path = Path(self.basepath).expanduser().resolve()
139
+ from_path = Path(self.basepath or ".").expanduser().resolve()
136
140
  else:
137
141
  from_path = self._resolve_path(from_path)
138
142
 
prefect/flow_engine.py CHANGED
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  import asyncio
2
4
  import logging
3
5
  import os
@@ -14,7 +16,6 @@ from typing import (
14
16
  Iterable,
15
17
  Literal,
16
18
  Optional,
17
- Tuple,
18
19
  Type,
19
20
  TypeVar,
20
21
  Union,
@@ -103,13 +104,15 @@ class FlowRunTimeoutError(TimeoutError):
103
104
  """Raised when a flow run exceeds its defined timeout."""
104
105
 
105
106
 
106
- def load_flow_and_flow_run(flow_run_id: UUID) -> Tuple[FlowRun, Flow]:
107
- ## TODO: add error handling to update state and log tracebacks
108
- entrypoint = os.environ.get("PREFECT__FLOW_ENTRYPOINT")
107
+ def load_flow_run(flow_run_id: UUID) -> FlowRun:
108
+ client = get_client(sync_client=True)
109
+ flow_run = client.read_flow_run(flow_run_id)
110
+ return flow_run
109
111
 
110
- client = cast(SyncPrefectClient, get_client(sync_client=True))
111
112
 
112
- flow_run = client.read_flow_run(flow_run_id)
113
+ def load_flow(flow_run: FlowRun) -> Flow[..., Any]:
114
+ entrypoint = os.environ.get("PREFECT__FLOW_ENTRYPOINT")
115
+
113
116
  if entrypoint:
114
117
  # we should not accept a placeholder flow at runtime
115
118
  flow = load_flow_from_entrypoint(entrypoint, use_placeholder_flow=False)
@@ -117,7 +120,12 @@ def load_flow_and_flow_run(flow_run_id: UUID) -> Tuple[FlowRun, Flow]:
117
120
  flow = run_coro_as_sync(
118
121
  load_flow_from_flow_run(flow_run, use_placeholder_flow=False)
119
122
  )
123
+ return flow
124
+
120
125
 
126
+ def load_flow_and_flow_run(flow_run_id: UUID) -> tuple[FlowRun, Flow[..., Any]]:
127
+ flow_run = load_flow_run(flow_run_id)
128
+ flow = load_flow(flow_run)
121
129
  return flow_run, flow
122
130
 
123
131
 
@@ -128,7 +136,7 @@ class BaseFlowRunEngine(Generic[P, R]):
128
136
  flow_run: Optional[FlowRun] = None
129
137
  flow_run_id: Optional[UUID] = None
130
138
  logger: logging.Logger = field(default_factory=lambda: get_logger("engine"))
131
- wait_for: Optional[Iterable[PrefectFuture]] = None
139
+ wait_for: Optional[Iterable[PrefectFuture[Any]]] = None
132
140
  # holds the return value from the user code
133
141
  _return_value: Union[R, Type[NotSet]] = NotSet
134
142
  # holds the exception raised by the user code, if any
@@ -209,7 +217,7 @@ class FlowRunEngine(BaseFlowRunEngine[P, R]):
209
217
 
210
218
  def _resolve_parameters(self):
211
219
  if not self.parameters:
212
- return {}
220
+ return
213
221
 
214
222
  resolved_parameters = {}
215
223
  for parameter, value in self.parameters.items():
@@ -277,7 +285,6 @@ class FlowRunEngine(BaseFlowRunEngine[P, R]):
277
285
  ),
278
286
  )
279
287
  self.short_circuit = True
280
- self.call_hooks()
281
288
 
282
289
  new_state = Running()
283
290
  state = self.set_state(new_state)
@@ -300,6 +307,7 @@ class FlowRunEngine(BaseFlowRunEngine[P, R]):
300
307
  self.flow_run.state_type = state.type # type: ignore
301
308
 
302
309
  self._telemetry.update_state(state)
310
+ self.call_hooks(state)
303
311
  return state
304
312
 
305
313
  def result(self, raise_on_failure: bool = True) -> "Union[R, State, None]":
@@ -711,8 +719,6 @@ class FlowRunEngine(BaseFlowRunEngine[P, R]):
711
719
  ):
712
720
  self.begin_run()
713
721
 
714
- if self.state.is_running():
715
- self.call_hooks()
716
722
  yield
717
723
 
718
724
  @contextmanager
@@ -734,9 +740,6 @@ class FlowRunEngine(BaseFlowRunEngine[P, R]):
734
740
  except Exception as exc:
735
741
  self.logger.exception("Encountered exception during execution: %r", exc)
736
742
  self.handle_exception(exc)
737
- finally:
738
- if self.state.is_final() or self.state.is_cancelling():
739
- self.call_hooks()
740
743
 
741
744
  def call_flow_fn(self) -> Union[R, Coroutine[Any, Any, R]]:
742
745
  """
@@ -774,7 +777,7 @@ class AsyncFlowRunEngine(BaseFlowRunEngine[P, R]):
774
777
 
775
778
  def _resolve_parameters(self):
776
779
  if not self.parameters:
777
- return {}
780
+ return
778
781
 
779
782
  resolved_parameters = {}
780
783
  for parameter, value in self.parameters.items():
@@ -842,7 +845,6 @@ class AsyncFlowRunEngine(BaseFlowRunEngine[P, R]):
842
845
  ),
843
846
  )
844
847
  self.short_circuit = True
845
- await self.call_hooks()
846
848
 
847
849
  new_state = Running()
848
850
  state = await self.set_state(new_state)
@@ -865,6 +867,7 @@ class AsyncFlowRunEngine(BaseFlowRunEngine[P, R]):
865
867
  self.flow_run.state_type = state.type # type: ignore
866
868
 
867
869
  self._telemetry.update_state(state)
870
+ await self.call_hooks(state)
868
871
  return state
869
872
 
870
873
  async def result(self, raise_on_failure: bool = True) -> "Union[R, State, None]":
@@ -1279,8 +1282,6 @@ class AsyncFlowRunEngine(BaseFlowRunEngine[P, R]):
1279
1282
  ):
1280
1283
  await self.begin_run()
1281
1284
 
1282
- if self.state.is_running():
1283
- await self.call_hooks()
1284
1285
  yield
1285
1286
 
1286
1287
  @asynccontextmanager
@@ -1302,9 +1303,6 @@ class AsyncFlowRunEngine(BaseFlowRunEngine[P, R]):
1302
1303
  except Exception as exc:
1303
1304
  self.logger.exception("Encountered exception during execution: %r", exc)
1304
1305
  await self.handle_exception(exc)
1305
- finally:
1306
- if self.state.is_final() or self.state.is_cancelling():
1307
- await self.call_hooks()
1308
1306
 
1309
1307
  async def call_flow_fn(self) -> Coroutine[Any, Any, R]:
1310
1308
  """
@@ -1439,25 +1437,36 @@ def run_flow(
1439
1437
  parameters: Optional[Dict[str, Any]] = None,
1440
1438
  wait_for: Optional[Iterable[PrefectFuture[R]]] = None,
1441
1439
  return_type: Literal["state", "result"] = "result",
1440
+ error_logger: Optional[logging.Logger] = None,
1442
1441
  ) -> Union[R, State, None]:
1443
- kwargs = dict(
1444
- flow=flow,
1445
- flow_run=flow_run,
1446
- parameters=_flow_parameters(
1447
- flow=flow, flow_run=flow_run, parameters=parameters
1448
- ),
1449
- wait_for=wait_for,
1450
- return_type=return_type,
1451
- )
1442
+ ret_val: Union[R, State, None] = None
1443
+
1444
+ try:
1445
+ kwargs: dict[str, Any] = dict(
1446
+ flow=flow,
1447
+ flow_run=flow_run,
1448
+ parameters=_flow_parameters(
1449
+ flow=flow, flow_run=flow_run, parameters=parameters
1450
+ ),
1451
+ wait_for=wait_for,
1452
+ return_type=return_type,
1453
+ )
1452
1454
 
1453
- if flow.isasync and flow.isgenerator:
1454
- return run_generator_flow_async(**kwargs)
1455
- elif flow.isgenerator:
1456
- return run_generator_flow_sync(**kwargs)
1457
- elif flow.isasync:
1458
- return run_flow_async(**kwargs)
1459
- else:
1460
- return run_flow_sync(**kwargs)
1455
+ if flow.isasync and flow.isgenerator:
1456
+ ret_val = run_generator_flow_async(**kwargs)
1457
+ elif flow.isgenerator:
1458
+ ret_val = run_generator_flow_sync(**kwargs)
1459
+ elif flow.isasync:
1460
+ ret_val = run_flow_async(**kwargs)
1461
+ else:
1462
+ ret_val = run_flow_sync(**kwargs)
1463
+ except:
1464
+ if error_logger:
1465
+ error_logger.error(
1466
+ "Engine execution exited with unexpected exception", exc_info=True
1467
+ )
1468
+ raise
1469
+ return ret_val
1461
1470
 
1462
1471
 
1463
1472
  def _flow_parameters(
prefect/flows.py CHANGED
@@ -2,6 +2,8 @@
2
2
  Module containing the base workflow class and decorator - for most use cases, using the [`@flow` decorator][prefect.flows.flow] is preferred.
3
3
  """
4
4
 
5
+ from __future__ import annotations
6
+
5
7
  # This file requires type-checking with pyright because mypy does not yet support PEP612
6
8
  # See https://github.com/python/mypy/issues/8645
7
9
  import ast
@@ -43,6 +45,7 @@ from pydantic.v1.errors import ConfigError # TODO
43
45
  from rich.console import Console
44
46
  from typing_extensions import Literal, ParamSpec, TypeAlias
45
47
 
48
+ from prefect._experimental.sla.objects import SlaTypes
46
49
  from prefect._internal.concurrency.api import create_call, from_async
47
50
  from prefect.blocks.core import Block
48
51
  from prefect.client.schemas.actions import DeploymentScheduleCreate
@@ -651,6 +654,7 @@ class Flow(Generic[P, R]):
651
654
  work_queue_name: Optional[str] = None,
652
655
  job_variables: Optional[dict[str, Any]] = None,
653
656
  entrypoint_type: EntrypointType = EntrypointType.FILE_PATH,
657
+ _sla: Optional[Union[SlaTypes, list[SlaTypes]]] = None, # experimental
654
658
  ) -> "RunnerDeployment":
655
659
  """
656
660
  Creates a runner deployment object for this flow.
@@ -681,6 +685,7 @@ class Flow(Generic[P, R]):
681
685
  of the chosen work pool. Refer to the base job template of the chosen work pool for
682
686
  entrypoint_type: Type of entrypoint to use for the deployment. When using a module path
683
687
  entrypoint, ensure that the module will be importable in the execution environment.
688
+ _sla: (Experimental) SLA configuration for the deployment. May be removed or modified at any time. Currently only supported on Prefect Cloud.
684
689
 
685
690
  Examples:
686
691
  Prepare two deployments and serve them:
@@ -728,6 +733,7 @@ class Flow(Generic[P, R]):
728
733
  work_pool_name=work_pool_name,
729
734
  work_queue_name=work_queue_name,
730
735
  job_variables=job_variables,
736
+ _sla=_sla,
731
737
  ) # type: ignore # TODO: remove sync_compatible
732
738
  else:
733
739
  return RunnerDeployment.from_flow(
@@ -749,6 +755,7 @@ class Flow(Generic[P, R]):
749
755
  work_queue_name=work_queue_name,
750
756
  job_variables=job_variables,
751
757
  entrypoint_type=entrypoint_type,
758
+ _sla=_sla,
752
759
  )
753
760
 
754
761
  def on_completion(self, fn: StateHookCallable) -> StateHookCallable:
@@ -1061,6 +1068,7 @@ class Flow(Generic[P, R]):
1061
1068
  entrypoint_type: EntrypointType = EntrypointType.FILE_PATH,
1062
1069
  print_next_steps: bool = True,
1063
1070
  ignore_warnings: bool = False,
1071
+ _sla: Optional[Union[SlaTypes, list[SlaTypes]]] = None,
1064
1072
  ) -> UUID:
1065
1073
  """
1066
1074
  Deploys a flow to run on dynamic infrastructure via a work pool.
@@ -1112,7 +1120,7 @@ class Flow(Generic[P, R]):
1112
1120
  print_next_steps_message: Whether or not to print a message with next steps
1113
1121
  after deploying the deployments.
1114
1122
  ignore_warnings: Whether or not to ignore warnings about the work pool type.
1115
-
1123
+ _sla: (Experimental) SLA configuration for the deployment. May be removed or modified at any time. Currently only supported on Prefect Cloud.
1116
1124
  Returns:
1117
1125
  The ID of the created/updated deployment.
1118
1126
 
@@ -1190,6 +1198,7 @@ class Flow(Generic[P, R]):
1190
1198
  work_queue_name=work_queue_name,
1191
1199
  job_variables=job_variables,
1192
1200
  entrypoint_type=entrypoint_type,
1201
+ _sla=_sla,
1193
1202
  )
1194
1203
 
1195
1204
  from prefect.deployments.runner import deploy
@@ -32,7 +32,7 @@ formatters:
32
32
  # Define any custom filters to drops records containing
33
33
  # sensitive information
34
34
  # my_filter:
35
- # class: your_module.FilterClass
35
+ # (): your_module.FilterClass
36
36
 
37
37
  handlers:
38
38
  # The handlers we define here will output all logs they receive by default
prefect/runner/runner.py CHANGED
@@ -1,6 +1,8 @@
1
1
  """
2
- Runners are responsible for managing the execution of deployments created and managed by
3
- either `flow.serve` or the `serve` utility.
2
+ Runners are responsible for managing the execution of all deployments.
3
+
4
+ When creating a deployment using either `flow.serve` or the `serve` utility,
5
+ they also will poll for scheduled runs.
4
6
 
5
7
  Example:
6
8
  ```python
@@ -39,6 +39,11 @@ class CloudSettings(PrefectBaseSettings):
39
39
  description="API URL for Prefect Cloud. Used for authentication with Prefect Cloud.",
40
40
  )
41
41
 
42
+ enable_orchestration_telemetry: bool = Field(
43
+ default=True,
44
+ description="Whether or not to enable orchestration telemetry.",
45
+ )
46
+
42
47
  ui_url: Optional[str] = Field(
43
48
  default=None,
44
49
  description="The URL of the Prefect Cloud UI. If not set, the client will attempt to infer it.",
@@ -20,11 +20,6 @@ class ExperimentsSettings(PrefectBaseSettings):
20
20
  ),
21
21
  )
22
22
 
23
- telemetry_enabled: bool = Field(
24
- default=False,
25
- description="Enables sending telemetry to Prefect Cloud.",
26
- )
27
-
28
23
  lineage_events_enabled: bool = Field(
29
24
  default=False,
30
25
  description="If `True`, enables emitting lineage events. Set to `False` to disable lineage event emission.",