prefect-client 2.16.2__py3-none-any.whl → 2.16.3__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/events/schemas.py CHANGED
@@ -1,8 +1,22 @@
1
+ import abc
1
2
  from datetime import timedelta
2
- from typing import Any, Dict, Iterable, List, Optional, Set, Tuple, Union, cast
3
+ from enum import Enum
4
+ from typing import (
5
+ Any,
6
+ Dict,
7
+ Iterable,
8
+ List,
9
+ Literal,
10
+ Optional,
11
+ Set,
12
+ Tuple,
13
+ Union,
14
+ cast,
15
+ )
3
16
  from uuid import UUID, uuid4
4
17
 
5
18
  import pendulum
19
+ from typing_extensions import TypeAlias
6
20
 
7
21
  from prefect._internal.pydantic import HAS_PYDANTIC_V2
8
22
 
@@ -15,7 +29,6 @@ else:
15
29
 
16
30
  from prefect._internal.schemas.bases import PrefectBaseModel
17
31
  from prefect._internal.schemas.fields import DateTimeTZ
18
- from prefect._internal.schemas.transformations import FieldFrom, copy_model_fields
19
32
  from prefect.events.actions import ActionTypes, RunDeployment
20
33
  from prefect.utilities.collections import AutoEnum
21
34
 
@@ -27,6 +40,7 @@ MAXIMUM_RELATED_RESOURCES = 500
27
40
  class Posture(AutoEnum):
28
41
  Reactive = "Reactive"
29
42
  Proactive = "Proactive"
43
+ Metric = "Metric"
30
44
 
31
45
 
32
46
  class ResourceSpecification(PrefectBaseModel):
@@ -164,32 +178,56 @@ class Event(PrefectBaseModel):
164
178
  return value
165
179
 
166
180
 
167
- class Trigger(PrefectBaseModel):
168
- """Defines the criteria for the events and conditions under which an Automation
169
- will trigger an action"""
181
+ class Trigger(PrefectBaseModel, abc.ABC):
182
+ """
183
+ Base class describing a set of criteria that must be satisfied in order to trigger
184
+ an automation.
185
+ """
186
+
187
+ class Config:
188
+ extra = Extra.ignore
189
+
190
+ type: str
191
+
192
+
193
+ class ResourceTrigger(Trigger, abc.ABC):
194
+ """
195
+ Base class for triggers that may filter by the labels of resources.
196
+ """
197
+
198
+ type: str
170
199
 
171
200
  match: ResourceSpecification = Field(
172
201
  default_factory=lambda: ResourceSpecification(__root__={}),
173
- description="Labels for resources which this Automation will match.",
202
+ description="Labels for resources which this trigger will match.",
174
203
  )
175
204
  match_related: ResourceSpecification = Field(
176
205
  default_factory=lambda: ResourceSpecification(__root__={}),
177
- description="Labels for related resources which this Automation will match.",
206
+ description="Labels for related resources which this trigger will match.",
178
207
  )
179
208
 
209
+
210
+ class EventTrigger(ResourceTrigger):
211
+ """
212
+ A trigger that fires based on the presence or absence of events within a given
213
+ period of time.
214
+ """
215
+
216
+ type: Literal["event"] = "event"
217
+
180
218
  after: Set[str] = Field(
181
219
  default_factory=set,
182
220
  description=(
183
- "The event(s) which must first been seen to start this automation. If "
184
- "empty, then start this Automation immediately. Events may include "
221
+ "The event(s) which must first been seen to fire this trigger. If "
222
+ "empty, then fire this trigger immediately. Events may include "
185
223
  "trailing wildcards, like `prefect.flow-run.*`"
186
224
  ),
187
225
  )
188
226
  expect: Set[str] = Field(
189
227
  default_factory=set,
190
228
  description=(
191
- "The event(s) this automation is expecting to see. If empty, this "
192
- "automation will match any event. Events may include trailing wildcards, "
229
+ "The event(s) this trigger is expecting to see. If empty, this "
230
+ "trigger will match any event. Events may include trailing wildcards, "
193
231
  "like `prefect.flow-run.*`"
194
232
  ),
195
233
  )
@@ -197,24 +235,29 @@ class Trigger(PrefectBaseModel):
197
235
  for_each: Set[str] = Field(
198
236
  default_factory=set,
199
237
  description=(
200
- "Evaluate the Automation separately for each distinct value of these labels"
201
- " on the resource"
238
+ "Evaluate the trigger separately for each distinct value of these labels "
239
+ "on the resource. By default, labels refer to the primary resource of the "
240
+ "triggering event. You may also refer to labels from related "
241
+ "resources by specifying `related:<role>:<label>`. This will use the "
242
+ "value of that label for the first related resource in that role. For "
243
+ 'example, `"for_each": ["related:flow:prefect.resource.id"]` would '
244
+ "evaluate the trigger for each flow."
202
245
  ),
203
246
  )
204
- posture: Posture = Field(
205
- Posture.Reactive,
247
+ posture: Literal[Posture.Reactive, Posture.Proactive] = Field( # type: ignore[valid-type]
248
+ ...,
206
249
  description=(
207
- "The posture of this Automation, either Reactive or Proactive. Reactive "
208
- "automations respond to the _presence_ of the expected events, while "
209
- "Proactive automations respond to the _absence_ of those expected events."
250
+ "The posture of this trigger, either Reactive or Proactive. Reactive "
251
+ "triggers respond to the _presence_ of the expected events, while "
252
+ "Proactive triggers respond to the _absence_ of those expected events."
210
253
  ),
211
254
  )
212
255
  threshold: int = Field(
213
256
  1,
214
257
  description=(
215
- "The number of events required for this Automation to trigger (for "
216
- "Reactive automations), or the number of events expected (for Proactive "
217
- "automations)"
258
+ "The number of events required for this trigger to fire (for "
259
+ "Reactive triggers), or the number of events expected (for Proactive "
260
+ "triggers)"
218
261
  ),
219
262
  )
220
263
  within: timedelta = Field(
@@ -253,6 +296,86 @@ class Trigger(PrefectBaseModel):
253
296
  return values
254
297
 
255
298
 
299
+ class MetricTriggerOperator(Enum):
300
+ LT = "<"
301
+ LTE = "<="
302
+ GT = ">"
303
+ GTE = ">="
304
+
305
+
306
+ class PrefectMetric(Enum):
307
+ lateness = "lateness"
308
+ duration = "duration"
309
+ successes = "successes"
310
+
311
+
312
+ class MetricTriggerQuery(PrefectBaseModel):
313
+ """Defines a subset of the Trigger subclass, which is specific
314
+ to Metric automations, that specify the query configurations
315
+ and breaching conditions for the Automation"""
316
+
317
+ name: PrefectMetric = Field(
318
+ ...,
319
+ description="The name of the metric to query.",
320
+ )
321
+ threshold: float = Field(
322
+ ...,
323
+ description=(
324
+ "The threshold value against which we'll compare " "the query result."
325
+ ),
326
+ )
327
+ operator: MetricTriggerOperator = Field(
328
+ ...,
329
+ description=(
330
+ "The comparative operator (LT / LTE / GT / GTE) used to compare "
331
+ "the query result against the threshold value."
332
+ ),
333
+ )
334
+ range: timedelta = Field(
335
+ timedelta(seconds=300), # defaults to 5 minutes
336
+ minimum=300.0,
337
+ exclusiveMinimum=False,
338
+ description=(
339
+ "The lookback duration (seconds) for a metric query. This duration is "
340
+ "used to determine the time range over which the query will be executed. "
341
+ "The minimum value is 300 seconds (5 minutes)."
342
+ ),
343
+ )
344
+ firing_for: timedelta = Field(
345
+ timedelta(seconds=300), # defaults to 5 minutes
346
+ minimum=300.0,
347
+ exclusiveMinimum=False,
348
+ description=(
349
+ "The duration (seconds) for which the metric query must breach "
350
+ "or resolve continuously before the state is updated and the "
351
+ "automation is triggered. "
352
+ "The minimum value is 300 seconds (5 minutes)."
353
+ ),
354
+ )
355
+
356
+
357
+ class MetricTrigger(ResourceTrigger):
358
+ """
359
+ A trigger that fires based on the results of a metric query.
360
+ """
361
+
362
+ type: Literal["metric"] = "metric"
363
+
364
+ posture: Literal[Posture.Metric] = Field( # type: ignore[valid-type]
365
+ Posture.Metric,
366
+ description="Periodically evaluate the configured metric query.",
367
+ )
368
+
369
+ metric: MetricTriggerQuery = Field(
370
+ ...,
371
+ description="The metric query to evaluate for this trigger. ",
372
+ )
373
+
374
+
375
+ TriggerTypes: TypeAlias = Union[EventTrigger, MetricTrigger]
376
+ """The union of all concrete trigger types that a user may actually create"""
377
+
378
+
256
379
  class Automation(PrefectBaseModel):
257
380
  """Defines an action a user wants to take when a certain number of events
258
381
  do or don't happen to the matching resources"""
@@ -265,7 +388,7 @@ class Automation(PrefectBaseModel):
265
388
 
266
389
  enabled: bool = Field(True, description="Whether this automation will be evaluated")
267
390
 
268
- trigger: Trigger = Field(
391
+ trigger: TriggerTypes = Field(
269
392
  ...,
270
393
  description=(
271
394
  "The criteria for which events this Automation covers and how it will "
@@ -286,30 +409,106 @@ class ExistingAutomation(Automation):
286
409
  id: UUID = Field(..., description="The ID of this automation")
287
410
 
288
411
 
289
- @copy_model_fields
290
- class ResourceTrigger(PrefectBaseModel):
412
+ class AutomationCreateFromTrigger(PrefectBaseModel):
291
413
  name: Optional[str] = Field(
292
414
  None, description="The name to give to the automation created for this trigger."
293
415
  )
294
- description: str = FieldFrom(Automation)
295
- enabled: bool = FieldFrom(Automation)
416
+ description: str = Field("", description="A longer description of this automation")
417
+ enabled: bool = Field(True, description="Whether this automation will be evaluated")
418
+
419
+ # from ResourceTrigger
420
+
421
+ match: ResourceSpecification = Field(
422
+ default_factory=lambda: ResourceSpecification(__root__={}),
423
+ description="Labels for resources which this trigger will match.",
424
+ )
425
+ match_related: ResourceSpecification = Field(
426
+ default_factory=lambda: ResourceSpecification(__root__={}),
427
+ description="Labels for related resources which this trigger will match.",
428
+ )
429
+
430
+ # from both EventTrigger and MetricTrigger
431
+
432
+ posture: Posture = Field(
433
+ Posture.Reactive,
434
+ description=(
435
+ "The posture of this trigger, either Reactive, Proactive, or Metric. "
436
+ "Reactive triggers respond to the _presence_ of the expected events, while "
437
+ "Proactive triggers respond to the _absence_ of those expected events. "
438
+ "Metric triggers periodically evaluate the configured metric query."
439
+ ),
440
+ )
296
441
 
297
- match: ResourceSpecification = FieldFrom(Trigger)
298
- match_related: ResourceSpecification = FieldFrom(Trigger)
299
- after: Set[str] = FieldFrom(Trigger)
300
- expect: Set[str] = FieldFrom(Trigger)
301
- for_each: Set[str] = FieldFrom(Trigger)
302
- posture: Posture = FieldFrom(Trigger)
303
- threshold: int = FieldFrom(Trigger)
304
- within: timedelta = FieldFrom(Trigger)
442
+ # from EventTrigger
443
+
444
+ after: Set[str] = Field(
445
+ default_factory=set,
446
+ description=(
447
+ "The event(s) which must first been seen to fire this trigger. If "
448
+ "empty, then fire this trigger immediately. Events may include "
449
+ "trailing wildcards, like `prefect.flow-run.*`"
450
+ ),
451
+ )
452
+ expect: Set[str] = Field(
453
+ default_factory=set,
454
+ description=(
455
+ "The event(s) this trigger is expecting to see. If empty, this "
456
+ "trigger will match any event. Events may include trailing wildcards, "
457
+ "like `prefect.flow-run.*`"
458
+ ),
459
+ )
460
+
461
+ for_each: Set[str] = Field(
462
+ default_factory=set,
463
+ description=(
464
+ "Evaluate the trigger separately for each distinct value of these labels "
465
+ "on the resource. By default, labels refer to the primary resource of the "
466
+ "triggering event. You may also refer to labels from related "
467
+ "resources by specifying `related:<role>:<label>`. This will use the "
468
+ "value of that label for the first related resource in that role. For "
469
+ 'example, `"for_each": ["related:flow:prefect.resource.id"]` would '
470
+ "evaluate the trigger for each flow."
471
+ ),
472
+ )
473
+ threshold: int = Field(
474
+ 1,
475
+ description=(
476
+ "The number of events required for this trigger to fire (for "
477
+ "Reactive triggers), or the number of events expected (for Proactive "
478
+ "triggers)"
479
+ ),
480
+ )
481
+ within: timedelta = Field(
482
+ timedelta(0),
483
+ minimum=0.0,
484
+ exclusiveMinimum=False,
485
+ description=(
486
+ "The time period over which the events must occur. For Reactive triggers, "
487
+ "this may be as low as 0 seconds, but must be at least 10 seconds for "
488
+ "Proactive triggers"
489
+ ),
490
+ )
491
+
492
+ # from MetricTrigger
493
+
494
+ metric: Optional[MetricTriggerQuery] = Field(
495
+ None,
496
+ description="The metric query to evaluate for this trigger. ",
497
+ )
305
498
 
306
499
  def as_automation(self) -> Automation:
307
500
  assert self.name
308
- return Automation(
309
- name=self.name,
310
- description=self.description,
311
- enabled=self.enabled,
312
- trigger=Trigger(
501
+
502
+ if self.posture == Posture.Metric:
503
+ trigger = MetricTrigger(
504
+ type="metric",
505
+ match=self.match,
506
+ match_related=self.match_related,
507
+ posture=self.posture,
508
+ metric=self.metric,
509
+ )
510
+ else:
511
+ trigger = EventTrigger(
313
512
  match=self.match,
314
513
  match_related=self.match_related,
315
514
  after=self.after,
@@ -318,7 +517,13 @@ class ResourceTrigger(PrefectBaseModel):
318
517
  posture=self.posture,
319
518
  threshold=self.threshold,
320
519
  within=self.within,
321
- ),
520
+ )
521
+
522
+ return Automation(
523
+ name=self.name,
524
+ description=self.description,
525
+ enabled=self.enabled,
526
+ trigger=trigger,
322
527
  actions=self.actions(),
323
528
  owner_resource=self.owner_resource(),
324
529
  )
@@ -330,10 +535,15 @@ class ResourceTrigger(PrefectBaseModel):
330
535
  raise NotImplementedError
331
536
 
332
537
 
333
- @copy_model_fields
334
- class DeploymentTrigger(ResourceTrigger):
538
+ class DeploymentTrigger(AutomationCreateFromTrigger):
335
539
  _deployment_id: Optional[UUID] = PrivateAttr(default=None)
336
- parameters: Optional[Dict[str, Any]] = FieldFrom(RunDeployment)
540
+ parameters: Optional[Dict[str, Any]] = Field(
541
+ None,
542
+ description=(
543
+ "The parameters to pass to the deployment, or None to use the "
544
+ "deployment's default parameters"
545
+ ),
546
+ )
337
547
 
338
548
  def set_deployment_id(self, deployment_id: UUID):
339
549
  self._deployment_id = deployment_id
prefect/flows.py CHANGED
@@ -183,6 +183,7 @@ class Flow(Generic[P, R]):
183
183
  on_completion: An optional list of callables to run when the flow enters a completed state.
184
184
  on_cancellation: An optional list of callables to run when the flow enters a cancelling state.
185
185
  on_crashed: An optional list of callables to run when the flow enters a crashed state.
186
+ on_running: An optional list of callables to run when the flow enters a running state.
186
187
  """
187
188
 
188
189
  # NOTE: These parameters (types, defaults, and docstrings) should be duplicated
@@ -212,6 +213,7 @@ class Flow(Generic[P, R]):
212
213
  List[Callable[[FlowSchema, FlowRun, State], None]]
213
214
  ] = None,
214
215
  on_crashed: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
216
+ on_running: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
215
217
  ):
216
218
  if name is not None and not isinstance(name, str):
217
219
  raise TypeError(
@@ -227,8 +229,20 @@ class Flow(Generic[P, R]):
227
229
  )
228
230
 
229
231
  # Validate if hook passed is list and contains callables
230
- hook_categories = [on_completion, on_failure, on_cancellation, on_crashed]
231
- hook_names = ["on_completion", "on_failure", "on_cancellation", "on_crashed"]
232
+ hook_categories = [
233
+ on_completion,
234
+ on_failure,
235
+ on_cancellation,
236
+ on_crashed,
237
+ on_running,
238
+ ]
239
+ hook_names = [
240
+ "on_completion",
241
+ "on_failure",
242
+ "on_cancellation",
243
+ "on_crashed",
244
+ "on_running",
245
+ ]
232
246
  for hooks, hook_name in zip(hook_categories, hook_names):
233
247
  if hooks is not None:
234
248
  if not hooks:
@@ -350,6 +364,7 @@ class Flow(Generic[P, R]):
350
364
  self.on_failure = on_failure
351
365
  self.on_cancellation = on_cancellation
352
366
  self.on_crashed = on_crashed
367
+ self.on_running = on_running
353
368
 
354
369
  # Used for flows loaded from remote storage
355
370
  self._storage: Optional[RunnerStorage] = None
@@ -387,6 +402,7 @@ class Flow(Generic[P, R]):
387
402
  List[Callable[[FlowSchema, FlowRun, State], None]]
388
403
  ] = None,
389
404
  on_crashed: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
405
+ on_running: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
390
406
  ) -> Self:
391
407
  """
392
408
  Create a new flow from the current object, updating provided options.
@@ -415,6 +431,7 @@ class Flow(Generic[P, R]):
415
431
  on_completion: A new list of callables to run when the flow enters a completed state.
416
432
  on_cancellation: A new list of callables to run when the flow enters a cancelling state.
417
433
  on_crashed: A new list of callables to run when the flow enters a crashed state.
434
+ on_running: A new list of callables to run when the flow enters a running state.
418
435
 
419
436
  Returns:
420
437
  A new `Flow` instance.
@@ -484,6 +501,7 @@ class Flow(Generic[P, R]):
484
501
  on_failure=on_failure or self.on_failure,
485
502
  on_cancellation=on_cancellation or self.on_cancellation,
486
503
  on_crashed=on_crashed or self.on_crashed,
504
+ on_running=on_running or self.on_running,
487
505
  )
488
506
  new_flow._storage = self._storage
489
507
  new_flow._entrypoint = self._entrypoint
@@ -1333,6 +1351,7 @@ def flow(
1333
1351
  List[Callable[[FlowSchema, FlowRun, State], None]]
1334
1352
  ] = None,
1335
1353
  on_crashed: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
1354
+ on_running: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
1336
1355
  ) -> Callable[[Callable[P, R]], Flow[P, R]]:
1337
1356
  ...
1338
1357
 
@@ -1360,6 +1379,7 @@ def flow(
1360
1379
  List[Callable[[FlowSchema, FlowRun, State], None]]
1361
1380
  ] = None,
1362
1381
  on_crashed: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
1382
+ on_running: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
1363
1383
  ):
1364
1384
  """
1365
1385
  Decorator to designate a function as a Prefect workflow.
@@ -1423,6 +1443,8 @@ def flow(
1423
1443
  on_crashed: An optional list of functions to call when the flow run crashes. Each
1424
1444
  function should accept three arguments: the flow, the flow run, and the
1425
1445
  final state of the flow run.
1446
+ on_running: An optional list of functions to call when the flow run is started. Each
1447
+ function should accept three arguments: the flow, the flow run, and the current state
1426
1448
 
1427
1449
  Returns:
1428
1450
  A callable `Flow` object which, when called, will run the flow and return its
@@ -1485,6 +1507,7 @@ def flow(
1485
1507
  on_failure=on_failure,
1486
1508
  on_cancellation=on_cancellation,
1487
1509
  on_crashed=on_crashed,
1510
+ on_running=on_running,
1488
1511
  ),
1489
1512
  )
1490
1513
  else:
@@ -1510,6 +1533,7 @@ def flow(
1510
1533
  on_failure=on_failure,
1511
1534
  on_cancellation=on_cancellation,
1512
1535
  on_crashed=on_crashed,
1536
+ on_running=on_running,
1513
1537
  ),
1514
1538
  )
1515
1539
 
prefect/runner/runner.py CHANGED
@@ -76,9 +76,9 @@ from prefect.client.schemas.schedules import SCHEDULE_TYPES
76
76
  from prefect.deployments.deployments import load_flow_from_flow_run
77
77
  from prefect.deployments.runner import (
78
78
  EntrypointType,
79
- FlexibleScheduleList,
80
79
  RunnerDeployment,
81
80
  )
81
+ from prefect.deployments.schedules import FlexibleScheduleList
82
82
  from prefect.engine import propose_state
83
83
  from prefect.events.schemas import DeploymentTrigger
84
84
  from prefect.exceptions import (
@@ -228,7 +228,7 @@ class Runner:
228
228
  cron: Optional[Union[Iterable[str], str]] = None,
229
229
  rrule: Optional[Union[Iterable[str], str]] = None,
230
230
  paused: Optional[bool] = None,
231
- schedules: Optional[List[FlexibleScheduleList]] = None,
231
+ schedules: Optional[FlexibleScheduleList] = None,
232
232
  schedule: Optional[SCHEDULE_TYPES] = None,
233
233
  is_schedule_active: Optional[bool] = None,
234
234
  parameters: Optional[dict] = None,
@@ -122,7 +122,8 @@
122
122
  "auto_deregister_task_definition": "{{ auto_deregister_task_definition }}",
123
123
  "vpc_id": "{{ vpc_id }}",
124
124
  "container_name": "{{ container_name }}",
125
- "cluster": "{{ cluster }}"
125
+ "cluster": "{{ cluster }}",
126
+ "match_latest_revision_in_family": "{{ match_latest_revision_in_family }}"
126
127
  },
127
128
  "variables": {
128
129
  "description": "Variables for templating an ECS job.",
@@ -265,6 +266,12 @@
265
266
  "description": "If enabled, any task definitions that are created by this block will be deregistered. Existing task definitions linked by ARN will never be deregistered. Deregistering a task definition does not remove it from your AWS account, instead it will be marked as INACTIVE.",
266
267
  "default": false,
267
268
  "type": "boolean"
269
+ },
270
+ "match_latest_revision_in_family": {
271
+ "title": "Match Latest Revision In Family",
272
+ "description": "If enabled, the most recent active revision in the task definition family will be compared against the desired ECS task configuration. If they are equal, the existing task definition will be used instead of registering a new one. If no family is specified the default family \"prefect\" will be used.",
273
+ "default": false,
274
+ "type": "boolean"
268
275
  }
269
276
  },
270
277
  "definitions": {
@@ -1628,4 +1635,4 @@
1628
1635
  "type": "kubernetes"
1629
1636
  }
1630
1637
  }
1631
- }
1638
+ }
prefect/settings.py CHANGED
@@ -102,6 +102,8 @@ T = TypeVar("T")
102
102
 
103
103
  DEFAULT_PROFILES_PATH = Path(__file__).parent.joinpath("profiles.toml")
104
104
 
105
+ REMOVED_EXPERIMENTAL_FLAGS = {"PREFECT_EXPERIMENTAL_ENABLE_ENHANCED_SCHEDULING_UI"}
106
+
105
107
 
106
108
  class Setting(Generic[T]):
107
109
  """
@@ -1295,6 +1297,11 @@ PREFECT_EXPERIMENTAL_ENABLE_ARTIFACTS_ON_FLOW_RUN_GRAPH = Setting(bool, default=
1295
1297
  Whether or not to enable artifacts on the flow run graph.
1296
1298
  """
1297
1299
 
1300
+ PREFECT_EXPERIMENTAL_ENABLE_STATES_ON_FLOW_RUN_GRAPH = Setting(bool, default=False)
1301
+ """
1302
+ Whether or not to enable flow run states on the flow run graph.
1303
+ """
1304
+
1298
1305
  PREFECT_EXPERIMENTAL_ENABLE_EVENTS_CLIENT = Setting(bool, default=True)
1299
1306
  """
1300
1307
  Whether or not to enable experimental Prefect work pools.
@@ -1335,6 +1342,11 @@ PREFECT_EXPERIMENTAL_ENABLE_ENHANCED_CANCELLATION = Setting(bool, default=True)
1335
1342
  Whether or not to enable experimental enhanced flow run cancellation.
1336
1343
  """
1337
1344
 
1345
+ PREFECT_EXPERIMENTAL_ENABLE_ENHANCED_DEPLOYMENT_PARAMETERS = Setting(bool, default=True)
1346
+ """
1347
+ Whether or not to enable enhanced deployment parameters.
1348
+ """
1349
+
1338
1350
  PREFECT_EXPERIMENTAL_WARN_ENHANCED_CANCELLATION = Setting(bool, default=False)
1339
1351
  """
1340
1352
  Whether or not to warn when experimental enhanced flow run cancellation is used.
@@ -1513,11 +1525,6 @@ PREFECT_EXPERIMENTAL_ENABLE_WORK_QUEUE_STATUS = Setting(bool, default=True)
1513
1525
  Whether or not to enable experimental work queue status in-place of work queue health.
1514
1526
  """
1515
1527
 
1516
- PREFECT_EXPERIMENTAL_ENABLE_ENHANCED_SCHEDULING_UI = Setting(bool, default=True)
1517
- """
1518
- Whether or not to enable the enhanced scheduling UI.
1519
- """
1520
-
1521
1528
 
1522
1529
  # Defaults -----------------------------------------------------------------------------
1523
1530
 
@@ -2071,6 +2078,24 @@ class ProfilesCollection:
2071
2078
  )
2072
2079
 
2073
2080
 
2081
+ def _handle_removed_flags(profile_name: str, settings: dict) -> dict:
2082
+ to_remove = [name for name in settings if name in REMOVED_EXPERIMENTAL_FLAGS]
2083
+
2084
+ for name in to_remove:
2085
+ warnings.warn(
2086
+ (
2087
+ f"Experimental flag {name!r} has been removed, please "
2088
+ f"update your {profile_name!r} profile."
2089
+ ),
2090
+ UserWarning,
2091
+ stacklevel=3,
2092
+ )
2093
+
2094
+ settings.pop(name)
2095
+
2096
+ return settings
2097
+
2098
+
2074
2099
  def _read_profiles_from(path: Path) -> ProfilesCollection:
2075
2100
  """
2076
2101
  Read profiles from a path into a new `ProfilesCollection`.
@@ -2087,10 +2112,10 @@ def _read_profiles_from(path: Path) -> ProfilesCollection:
2087
2112
  active_profile = contents.get("active")
2088
2113
  raw_profiles = contents.get("profiles", {})
2089
2114
 
2090
- profiles = [
2091
- Profile(name=name, settings=settings, source=path)
2092
- for name, settings in raw_profiles.items()
2093
- ]
2115
+ profiles = []
2116
+ for name, settings in raw_profiles.items():
2117
+ settings = _handle_removed_flags(name, settings)
2118
+ profiles.append(Profile(name=name, settings=settings, source=path))
2094
2119
 
2095
2120
  return ProfilesCollection(profiles, active=active_profile)
2096
2121