prefect-client 2.16.1__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/flows.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """
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
  # This file requires type-checking with pyright because mypy does not yet support PEP612
5
6
  # See https://github.com/python/mypy/issues/8645
6
7
 
@@ -40,7 +41,7 @@ from prefect._internal.compatibility.deprecated import deprecated_parameter
40
41
  from prefect._internal.concurrency.api import create_call, from_async
41
42
  from prefect._internal.pydantic import HAS_PYDANTIC_V2
42
43
  from prefect.client.orchestration import get_client
43
- from prefect.deployments.runner import DeploymentImage, deploy
44
+ from prefect.deployments.runner import DeploymentImage, EntrypointType, deploy
44
45
  from prefect.filesystems import ReadableDeploymentStorage
45
46
  from prefect.runner.storage import (
46
47
  BlockStorageAdapter,
@@ -182,6 +183,7 @@ class Flow(Generic[P, R]):
182
183
  on_completion: An optional list of callables to run when the flow enters a completed state.
183
184
  on_cancellation: An optional list of callables to run when the flow enters a cancelling state.
184
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.
185
187
  """
186
188
 
187
189
  # NOTE: These parameters (types, defaults, and docstrings) should be duplicated
@@ -211,6 +213,7 @@ class Flow(Generic[P, R]):
211
213
  List[Callable[[FlowSchema, FlowRun, State], None]]
212
214
  ] = None,
213
215
  on_crashed: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
216
+ on_running: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
214
217
  ):
215
218
  if name is not None and not isinstance(name, str):
216
219
  raise TypeError(
@@ -226,8 +229,20 @@ class Flow(Generic[P, R]):
226
229
  )
227
230
 
228
231
  # Validate if hook passed is list and contains callables
229
- hook_categories = [on_completion, on_failure, on_cancellation, on_crashed]
230
- 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
+ ]
231
246
  for hooks, hook_name in zip(hook_categories, hook_names):
232
247
  if hooks is not None:
233
248
  if not hooks:
@@ -349,6 +364,7 @@ class Flow(Generic[P, R]):
349
364
  self.on_failure = on_failure
350
365
  self.on_cancellation = on_cancellation
351
366
  self.on_crashed = on_crashed
367
+ self.on_running = on_running
352
368
 
353
369
  # Used for flows loaded from remote storage
354
370
  self._storage: Optional[RunnerStorage] = None
@@ -386,6 +402,7 @@ class Flow(Generic[P, R]):
386
402
  List[Callable[[FlowSchema, FlowRun, State], None]]
387
403
  ] = None,
388
404
  on_crashed: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
405
+ on_running: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
389
406
  ) -> Self:
390
407
  """
391
408
  Create a new flow from the current object, updating provided options.
@@ -414,6 +431,7 @@ class Flow(Generic[P, R]):
414
431
  on_completion: A new list of callables to run when the flow enters a completed state.
415
432
  on_cancellation: A new list of callables to run when the flow enters a cancelling state.
416
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.
417
435
 
418
436
  Returns:
419
437
  A new `Flow` instance.
@@ -449,9 +467,11 @@ class Flow(Generic[P, R]):
449
467
  version=version or self.version,
450
468
  task_runner=task_runner or self.task_runner,
451
469
  retries=retries if retries is not None else self.retries,
452
- retry_delay_seconds=retry_delay_seconds
453
- if retry_delay_seconds is not None
454
- else self.retry_delay_seconds,
470
+ retry_delay_seconds=(
471
+ retry_delay_seconds
472
+ if retry_delay_seconds is not None
473
+ else self.retry_delay_seconds
474
+ ),
455
475
  timeout_seconds=(
456
476
  timeout_seconds if timeout_seconds is not None else self.timeout_seconds
457
477
  ),
@@ -481,6 +501,7 @@ class Flow(Generic[P, R]):
481
501
  on_failure=on_failure or self.on_failure,
482
502
  on_cancellation=on_cancellation or self.on_cancellation,
483
503
  on_crashed=on_crashed or self.on_crashed,
504
+ on_running=on_running or self.on_running,
484
505
  )
485
506
  new_flow._storage = self._storage
486
507
  new_flow._entrypoint = self._entrypoint
@@ -605,6 +626,7 @@ class Flow(Generic[P, R]):
605
626
  work_pool_name: Optional[str] = None,
606
627
  work_queue_name: Optional[str] = None,
607
628
  job_variables: Optional[Dict[str, Any]] = None,
629
+ entrypoint_type: EntrypointType = EntrypointType.FILE_PATH,
608
630
  ) -> "RunnerDeployment":
609
631
  """
610
632
  Creates a runner deployment object for this flow.
@@ -617,7 +639,7 @@ class Flow(Generic[P, R]):
617
639
  rrule: An rrule schedule of when to execute runs of this deployment.
618
640
  paused: Whether or not to set this deployment as paused.
619
641
  schedules: A list of schedule objects defining when to execute runs of this deployment.
620
- Used to define multiple schedules or additional scheduling options like `timezone`.
642
+ Used to define multiple schedules or additional scheduling options such as `timezone`.
621
643
  schedule: A schedule object defining when to execute runs of this deployment.
622
644
  is_schedule_active: Whether or not to set the schedule for this deployment as active. If
623
645
  not provided when creating a deployment, the schedule will be set as active. If not
@@ -636,6 +658,8 @@ class Flow(Generic[P, R]):
636
658
  If not provided the default work queue for the work pool will be used.
637
659
  job_variables: Settings used to override the values specified default base job template
638
660
  of the chosen work pool. Refer to the base job template of the chosen work pool for
661
+ entrypoint_type: Type of entrypoint to use for the deployment. When using a module path
662
+ entrypoint, ensure that the module will be importable in the execution environment.
639
663
 
640
664
  Examples:
641
665
  Prepare two deployments and serve them:
@@ -703,6 +727,7 @@ class Flow(Generic[P, R]):
703
727
  work_pool_name=work_pool_name,
704
728
  work_queue_name=work_queue_name,
705
729
  job_variables=job_variables,
730
+ entrypoint_type=entrypoint_type,
706
731
  )
707
732
 
708
733
  @sync_compatible
@@ -733,22 +758,27 @@ class Flow(Generic[P, R]):
733
758
  print_starting_message: bool = True,
734
759
  limit: Optional[int] = None,
735
760
  webserver: bool = False,
761
+ entrypoint_type: EntrypointType = EntrypointType.FILE_PATH,
736
762
  ):
737
763
  """
738
764
  Creates a deployment for this flow and starts a runner to monitor for scheduled work.
739
765
 
740
766
  Args:
741
767
  name: The name to give the created deployment.
742
- interval: An interval on which to execute the new deployment. Accepts either a number
743
- or a timedelta object. If a number is given, it will be interpreted as seconds.
744
- cron: A cron schedule of when to execute runs of this deployment.
745
- rrule: An rrule schedule of when to execute runs of this deployment.
768
+ interval: An interval on which to execute the deployment. Accepts a number or a
769
+ timedelta object to create a single schedule. If a number is given, it will be
770
+ interpreted as seconds. Also accepts an iterable of numbers or timedelta to create
771
+ multiple schedules.
772
+ cron: A cron schedule string of when to execute runs of this deployment.
773
+ Also accepts an iterable of cron schedule strings to create multiple schedules.
774
+ rrule: An rrule schedule string of when to execute runs of this deployment.
775
+ Also accepts an iterable of rrule schedule strings to create multiple schedules.
746
776
  triggers: A list of triggers that will kick off runs of this deployment.
747
777
  paused: Whether or not to set this deployment as paused.
748
778
  schedules: A list of schedule objects defining when to execute runs of this deployment.
749
779
  Used to define multiple schedules or additional scheduling options like `timezone`.
750
780
  schedule: A schedule object defining when to execute runs of this deployment. Used to
751
- define additional scheduling options like `timezone`.
781
+ define additional scheduling options such as `timezone`.
752
782
  is_schedule_active: Whether or not to set the schedule for this deployment as active. If
753
783
  not provided when creating a deployment, the schedule will be set as active. If not
754
784
  provided when updating a deployment, the schedule's activation will not be changed.
@@ -765,6 +795,8 @@ class Flow(Generic[P, R]):
765
795
  print_starting_message: Whether or not to print the starting message when flow is served.
766
796
  limit: The maximum number of runs that can be executed concurrently.
767
797
  webserver: Whether or not to start a monitoring webserver for this flow.
798
+ entrypoint_type: Type of entrypoint to use for the deployment. When using a module path
799
+ entrypoint, ensure that the module will be importable in the execution environment.
768
800
 
769
801
  Examples:
770
802
  Serve a flow:
@@ -817,6 +849,7 @@ class Flow(Generic[P, R]):
817
849
  tags=tags,
818
850
  version=version,
819
851
  enforce_parameter_schema=enforce_parameter_schema,
852
+ entrypoint_type=entrypoint_type,
820
853
  )
821
854
  if print_starting_message:
822
855
  help_message = (
@@ -935,6 +968,7 @@ class Flow(Generic[P, R]):
935
968
  tags: Optional[List[str]] = None,
936
969
  version: Optional[str] = None,
937
970
  enforce_parameter_schema: bool = False,
971
+ entrypoint_type: EntrypointType = EntrypointType.FILE_PATH,
938
972
  print_next_steps: bool = True,
939
973
  ) -> UUID:
940
974
  """
@@ -961,10 +995,14 @@ class Flow(Generic[P, R]):
961
995
  job_variables: Settings used to override the values specified default base job template
962
996
  of the chosen work pool. Refer to the base job template of the chosen work pool for
963
997
  available settings.
964
- interval: An interval on which to execute the new deployment. Accepts either a number
965
- or a timedelta object. If a number is given, it will be interpreted as seconds.
966
- cron: A cron schedule of when to execute runs of this deployment.
967
- rrule: An rrule schedule of when to execute runs of this deployment.
998
+ interval: An interval on which to execute the deployment. Accepts a number or a
999
+ timedelta object to create a single schedule. If a number is given, it will be
1000
+ interpreted as seconds. Also accepts an iterable of numbers or timedelta to create
1001
+ multiple schedules.
1002
+ cron: A cron schedule string of when to execute runs of this deployment.
1003
+ Also accepts an iterable of cron schedule strings to create multiple schedules.
1004
+ rrule: An rrule schedule string of when to execute runs of this deployment.
1005
+ Also accepts an iterable of rrule schedule strings to create multiple schedules.
968
1006
  triggers: A list of triggers that will kick off runs of this deployment.
969
1007
  paused: Whether or not to set this deployment as paused.
970
1008
  schedules: A list of schedule objects defining when to execute runs of this deployment.
@@ -982,8 +1020,10 @@ class Flow(Generic[P, R]):
982
1020
  version: A version for the created deployment. Defaults to the flow's version.
983
1021
  enforce_parameter_schema: Whether or not the Prefect API should enforce the
984
1022
  parameter schema for the created deployment.
1023
+ entrypoint_type: Type of entrypoint to use for the deployment. When using a module path
1024
+ entrypoint, ensure that the module will be importable in the execution environment.
985
1025
  print_next_steps_message: Whether or not to print a message with next steps
986
- after deploying the deployments.
1026
+ after deploying the deployments.
987
1027
 
988
1028
  Returns:
989
1029
  The ID of the created/updated deployment.
@@ -1050,6 +1090,7 @@ class Flow(Generic[P, R]):
1050
1090
  enforce_parameter_schema=enforce_parameter_schema,
1051
1091
  work_queue_name=work_queue_name,
1052
1092
  job_variables=job_variables,
1093
+ entrypoint_type=entrypoint_type,
1053
1094
  )
1054
1095
 
1055
1096
  deployment_ids = await deploy(
@@ -1310,6 +1351,7 @@ def flow(
1310
1351
  List[Callable[[FlowSchema, FlowRun, State], None]]
1311
1352
  ] = None,
1312
1353
  on_crashed: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
1354
+ on_running: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
1313
1355
  ) -> Callable[[Callable[P, R]], Flow[P, R]]:
1314
1356
  ...
1315
1357
 
@@ -1337,6 +1379,7 @@ def flow(
1337
1379
  List[Callable[[FlowSchema, FlowRun, State], None]]
1338
1380
  ] = None,
1339
1381
  on_crashed: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
1382
+ on_running: Optional[List[Callable[[FlowSchema, FlowRun, State], None]]] = None,
1340
1383
  ):
1341
1384
  """
1342
1385
  Decorator to designate a function as a Prefect workflow.
@@ -1400,6 +1443,8 @@ def flow(
1400
1443
  on_crashed: An optional list of functions to call when the flow run crashes. Each
1401
1444
  function should accept three arguments: the flow, the flow run, and the
1402
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
1403
1448
 
1404
1449
  Returns:
1405
1450
  A callable `Flow` object which, when called, will run the flow and return its
@@ -1462,6 +1507,7 @@ def flow(
1462
1507
  on_failure=on_failure,
1463
1508
  on_cancellation=on_cancellation,
1464
1509
  on_crashed=on_crashed,
1510
+ on_running=on_running,
1465
1511
  ),
1466
1512
  )
1467
1513
  else:
@@ -1487,6 +1533,7 @@ def flow(
1487
1533
  on_failure=on_failure,
1488
1534
  on_cancellation=on_cancellation,
1489
1535
  on_crashed=on_crashed,
1536
+ on_running=on_running,
1490
1537
  ),
1491
1538
  )
1492
1539
 
@@ -1585,7 +1632,8 @@ def load_flow_from_entrypoint(entrypoint: str) -> Flow:
1585
1632
  Extract a flow object from a script at an entrypoint by running all of the code in the file.
1586
1633
 
1587
1634
  Args:
1588
- entrypoint: a string in the format `<path_to_script>:<flow_func_name>`
1635
+ entrypoint: a string in the format `<path_to_script>:<flow_func_name>` or a module path
1636
+ to a flow function
1589
1637
 
1590
1638
  Returns:
1591
1639
  The flow object from the script
@@ -1598,8 +1646,11 @@ def load_flow_from_entrypoint(entrypoint: str) -> Flow:
1598
1646
  block_code_execution=True,
1599
1647
  capture_failures=True,
1600
1648
  ):
1601
- # split by the last colon once to handle Windows paths with drive letters i.e C:\path\to\file.py:do_stuff
1602
- path, func_name = entrypoint.rsplit(":", maxsplit=1)
1649
+ if ":" in entrypoint:
1650
+ # split by the last colon once to handle Windows paths with drive letters i.e C:\path\to\file.py:do_stuff
1651
+ path, func_name = entrypoint.rsplit(":", maxsplit=1)
1652
+ else:
1653
+ path, func_name = entrypoint.rsplit(".", maxsplit=1)
1603
1654
  try:
1604
1655
  flow = import_object(entrypoint)
1605
1656
  except AttributeError as exc:
@@ -1,8 +1,31 @@
1
1
  import logging
2
+ from typing import Any
2
3
 
4
+ from prefect.utilities.collections import visit_collection
3
5
  from prefect.utilities.names import obfuscate
4
6
 
5
7
 
8
+ def redact_substr(obj: Any, substr: str):
9
+ """
10
+ Redact a string from a potentially nested object.
11
+
12
+ Args:
13
+ obj: The object to redact the string from
14
+ substr: The string to redact.
15
+
16
+ Returns:
17
+ Any: The object with the API key redacted.
18
+ """
19
+
20
+ def redact_item(item):
21
+ if isinstance(item, str):
22
+ return item.replace(substr, obfuscate(substr))
23
+ return item
24
+
25
+ redacted_obj = visit_collection(obj, visit_fn=redact_item, return_data=True)
26
+ return redacted_obj
27
+
28
+
6
29
  class ObfuscateApiKeyFilter(logging.Filter):
7
30
  """
8
31
  A logging filter that obfuscates any string that matches the obfuscate_string function.
@@ -13,7 +36,6 @@ class ObfuscateApiKeyFilter(logging.Filter):
13
36
  from prefect.settings import PREFECT_API_KEY
14
37
 
15
38
  if PREFECT_API_KEY:
16
- record.msg = record.msg.replace(
17
- PREFECT_API_KEY.value(), obfuscate(PREFECT_API_KEY.value())
18
- )
39
+ record.msg = redact_substr(record.msg, PREFECT_API_KEY.value())
40
+
19
41
  return True
prefect/results.py CHANGED
@@ -4,6 +4,7 @@ from functools import partial
4
4
  from typing import (
5
5
  TYPE_CHECKING,
6
6
  Any,
7
+ Awaitable,
7
8
  Callable,
8
9
  Dict,
9
10
  Generic,
@@ -41,6 +42,7 @@ from prefect.settings import (
41
42
  PREFECT_LOCAL_STORAGE_PATH,
42
43
  PREFECT_RESULTS_DEFAULT_SERIALIZER,
43
44
  PREFECT_RESULTS_PERSIST_BY_DEFAULT,
45
+ PREFECT_TASK_SCHEDULING_DEFAULT_STORAGE_BLOCK,
44
46
  )
45
47
  from prefect.utilities.annotations import NotSet
46
48
  from prefect.utilities.asyncutils import sync_compatible
@@ -69,7 +71,6 @@ async def get_default_result_storage() -> ResultStorage:
69
71
  """
70
72
  Generate a default file system for result storage.
71
73
  """
72
-
73
74
  return (
74
75
  await Block.load(PREFECT_DEFAULT_RESULT_STORAGE_BLOCK.value())
75
76
  if PREFECT_DEFAULT_RESULT_STORAGE_BLOCK.value() is not None
@@ -77,6 +78,52 @@ async def get_default_result_storage() -> ResultStorage:
77
78
  )
78
79
 
79
80
 
81
+ _default_task_scheduling_storages: Dict[Tuple[str, str], WritableFileSystem] = {}
82
+
83
+
84
+ async def get_or_create_default_task_scheduling_storage() -> ResultStorage:
85
+ """
86
+ Generate a default file system for autonomous task parameter/result storage.
87
+ """
88
+ default_storage_name, storage_path = cache_key = (
89
+ PREFECT_TASK_SCHEDULING_DEFAULT_STORAGE_BLOCK.value(),
90
+ PREFECT_LOCAL_STORAGE_PATH.value(),
91
+ )
92
+
93
+ async def get_storage():
94
+ try:
95
+ return await Block.load(default_storage_name)
96
+ except ValueError as e:
97
+ if "Unable to find" not in str(e):
98
+ raise e
99
+
100
+ block_type_slug, name = default_storage_name.split("/")
101
+ if block_type_slug == "local-file-system":
102
+ block = LocalFileSystem(basepath=storage_path)
103
+ else:
104
+ raise Exception(
105
+ "The default task storage block does not exist, but it is of type "
106
+ f"'{block_type_slug}' which cannot be created implicitly. Please create "
107
+ "the block manually."
108
+ )
109
+
110
+ try:
111
+ await block.save(name, overwrite=False)
112
+ return block
113
+ except ValueError as e:
114
+ if "already in use" not in str(e):
115
+ raise e
116
+
117
+ return await Block.load(default_storage_name)
118
+
119
+ try:
120
+ return _default_task_scheduling_storages[cache_key]
121
+ except KeyError:
122
+ storage = await get_storage()
123
+ _default_task_scheduling_storages[cache_key] = storage
124
+ return storage
125
+
126
+
80
127
  def get_default_result_serializer() -> ResultSerializer:
81
128
  """
82
129
  Generate a default file system for result storage.
@@ -231,10 +278,39 @@ class ResultFactory(pydantic.BaseModel):
231
278
 
232
279
  ctx = FlowRunContext.get()
233
280
 
281
+ if ctx and ctx.autonomous_task_run:
282
+ return await cls.from_autonomous_task(task, client=client)
283
+
284
+ return await cls._from_task(task, get_default_result_storage, client=client)
285
+
286
+ @classmethod
287
+ @inject_client
288
+ async def from_autonomous_task(
289
+ cls: Type[Self], task: "Task", client: "PrefectClient" = None
290
+ ) -> Self:
291
+ """
292
+ Create a new result factory for an autonomous task.
293
+ """
294
+ return await cls._from_task(
295
+ task, get_or_create_default_task_scheduling_storage, client=client
296
+ )
297
+
298
+ @classmethod
299
+ @inject_client
300
+ async def _from_task(
301
+ cls: Type[Self],
302
+ task: "Task",
303
+ default_storage_getter: Callable[[], Awaitable[ResultStorage]],
304
+ client: "PrefectClient" = None,
305
+ ) -> Self:
306
+ from prefect.context import FlowRunContext
307
+
308
+ ctx = FlowRunContext.get()
309
+
234
310
  result_storage = task.result_storage or (
235
311
  ctx.result_factory.storage_block
236
312
  if ctx and ctx.result_factory
237
- else await get_default_result_storage()
313
+ else await default_storage_getter()
238
314
  )
239
315
  result_serializer = task.result_serializer or (
240
316
  ctx.result_factory.serializer
prefect/runner/runner.py CHANGED
@@ -74,7 +74,11 @@ from prefect.client.schemas.objects import (
74
74
  )
75
75
  from prefect.client.schemas.schedules import SCHEDULE_TYPES
76
76
  from prefect.deployments.deployments import load_flow_from_flow_run
77
- from prefect.deployments.runner import FlexibleScheduleList, RunnerDeployment
77
+ from prefect.deployments.runner import (
78
+ EntrypointType,
79
+ RunnerDeployment,
80
+ )
81
+ from prefect.deployments.schedules import FlexibleScheduleList
78
82
  from prefect.engine import propose_state
79
83
  from prefect.events.schemas import DeploymentTrigger
80
84
  from prefect.exceptions import (
@@ -224,7 +228,7 @@ class Runner:
224
228
  cron: Optional[Union[Iterable[str], str]] = None,
225
229
  rrule: Optional[Union[Iterable[str], str]] = None,
226
230
  paused: Optional[bool] = None,
227
- schedules: Optional[List[FlexibleScheduleList]] = None,
231
+ schedules: Optional[FlexibleScheduleList] = None,
228
232
  schedule: Optional[SCHEDULE_TYPES] = None,
229
233
  is_schedule_active: Optional[bool] = None,
230
234
  parameters: Optional[dict] = None,
@@ -233,6 +237,7 @@ class Runner:
233
237
  tags: Optional[List[str]] = None,
234
238
  version: Optional[str] = None,
235
239
  enforce_parameter_schema: bool = False,
240
+ entrypoint_type: EntrypointType = EntrypointType.FILE_PATH,
236
241
  ) -> UUID:
237
242
  """
238
243
  Provides a flow to the runner to be run based on the provided configuration.
@@ -260,6 +265,8 @@ class Runner:
260
265
  tags: A list of tags to associate with the created deployment for organizational
261
266
  purposes.
262
267
  version: A version for the created deployment. Defaults to the flow's version.
268
+ entrypoint_type: Type of entrypoint to use for the deployment. When using a module path
269
+ entrypoint, ensure that the module will be importable in the execution environment.
263
270
  """
264
271
  api = PREFECT_API_URL.value()
265
272
  if any([interval, cron, rrule]) and not api:
@@ -284,6 +291,7 @@ class Runner:
284
291
  tags=tags,
285
292
  version=version,
286
293
  enforce_parameter_schema=enforce_parameter_schema,
294
+ entrypoint_type=entrypoint_type,
287
295
  )
288
296
  return await self.add_deployment(deployment)
289
297
 
@@ -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
  """
@@ -600,6 +602,15 @@ If provided, the URL of a hosted Prefect API. Defaults to `None`.
600
602
  When using Prefect Cloud, this will include an account and workspace.
601
603
  """
602
604
 
605
+ PREFECT_SILENCE_API_URL_MISCONFIGURATION = Setting(
606
+ bool,
607
+ default=False,
608
+ )
609
+ """If `True`, disable the warning when a user accidentally misconfigure its `PREFECT_API_URL`
610
+ Sometimes when a user manually set `PREFECT_API_URL` to a custom url,reverse-proxy for example,
611
+ we would like to silence this warning so we will set it to `FALSE`.
612
+ """
613
+
603
614
  PREFECT_API_KEY = Setting(
604
615
  str,
605
616
  default=None,
@@ -1286,6 +1297,11 @@ PREFECT_EXPERIMENTAL_ENABLE_ARTIFACTS_ON_FLOW_RUN_GRAPH = Setting(bool, default=
1286
1297
  Whether or not to enable artifacts on the flow run graph.
1287
1298
  """
1288
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
+
1289
1305
  PREFECT_EXPERIMENTAL_ENABLE_EVENTS_CLIENT = Setting(bool, default=True)
1290
1306
  """
1291
1307
  Whether or not to enable experimental Prefect work pools.
@@ -1326,6 +1342,11 @@ PREFECT_EXPERIMENTAL_ENABLE_ENHANCED_CANCELLATION = Setting(bool, default=True)
1326
1342
  Whether or not to enable experimental enhanced flow run cancellation.
1327
1343
  """
1328
1344
 
1345
+ PREFECT_EXPERIMENTAL_ENABLE_ENHANCED_DEPLOYMENT_PARAMETERS = Setting(bool, default=True)
1346
+ """
1347
+ Whether or not to enable enhanced deployment parameters.
1348
+ """
1349
+
1329
1350
  PREFECT_EXPERIMENTAL_WARN_ENHANCED_CANCELLATION = Setting(bool, default=False)
1330
1351
  """
1331
1352
  Whether or not to warn when experimental enhanced flow run cancellation is used.
@@ -1417,6 +1438,14 @@ PREFECT_WORKER_WEBSERVER_PORT = Setting(
1417
1438
  """
1418
1439
  The port the worker's webserver should bind to.
1419
1440
  """
1441
+
1442
+ PREFECT_TASK_SCHEDULING_DEFAULT_STORAGE_BLOCK = Setting(
1443
+ str,
1444
+ default="local-file-system/prefect-task-scheduling",
1445
+ )
1446
+ """The `block-type/block-document` slug of a block to use as the default storage
1447
+ for autonomous tasks."""
1448
+
1420
1449
  PREFECT_TASK_SCHEDULING_DELETE_FAILED_SUBMISSIONS = Setting(
1421
1450
  bool,
1422
1451
  default=True,
@@ -1441,6 +1470,16 @@ PREFECT_TASK_SCHEDULING_MAX_RETRY_QUEUE_SIZE = Setting(
1441
1470
  The maximum number of retries to queue for submission.
1442
1471
  """
1443
1472
 
1473
+ PREFECT_TASK_SCHEDULING_PENDING_TASK_TIMEOUT = Setting(
1474
+ timedelta,
1475
+ default=timedelta(seconds=30),
1476
+ )
1477
+ """
1478
+ How long before a PENDING task are made available to another task server. In practice,
1479
+ a task server should move a task from PENDING to RUNNING very quickly, so runs stuck in
1480
+ PENDING for a while is a sign that the task server may have crashed.
1481
+ """
1482
+
1444
1483
  PREFECT_EXPERIMENTAL_ENABLE_FLOW_RUN_INFRA_OVERRIDES = Setting(bool, default=False)
1445
1484
  """
1446
1485
  Whether or not to enable infrastructure overrides made on flow runs.
@@ -1486,11 +1525,6 @@ PREFECT_EXPERIMENTAL_ENABLE_WORK_QUEUE_STATUS = Setting(bool, default=True)
1486
1525
  Whether or not to enable experimental work queue status in-place of work queue health.
1487
1526
  """
1488
1527
 
1489
- PREFECT_EXPERIMENTAL_ENABLE_ENHANCED_SCHEDULING_UI = Setting(bool, default=True)
1490
- """
1491
- Whether or not to enable the enhanced scheduling UI.
1492
- """
1493
-
1494
1528
 
1495
1529
  # Defaults -----------------------------------------------------------------------------
1496
1530
 
@@ -1614,7 +1648,8 @@ class Settings(SettingsFieldsMixin):
1614
1648
  # in the future.
1615
1649
  values = max_log_size_smaller_than_batch_size(values)
1616
1650
  values = warn_on_database_password_value_without_usage(values)
1617
- values = warn_on_misconfigured_api_url(values)
1651
+ if not values["PREFECT_SILENCE_API_URL_MISCONFIGURATION"]:
1652
+ values = warn_on_misconfigured_api_url(values)
1618
1653
  return values
1619
1654
 
1620
1655
  def copy_with_update(
@@ -2043,6 +2078,24 @@ class ProfilesCollection:
2043
2078
  )
2044
2079
 
2045
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
+
2046
2099
  def _read_profiles_from(path: Path) -> ProfilesCollection:
2047
2100
  """
2048
2101
  Read profiles from a path into a new `ProfilesCollection`.
@@ -2059,10 +2112,10 @@ def _read_profiles_from(path: Path) -> ProfilesCollection:
2059
2112
  active_profile = contents.get("active")
2060
2113
  raw_profiles = contents.get("profiles", {})
2061
2114
 
2062
- profiles = [
2063
- Profile(name=name, settings=settings, source=path)
2064
- for name, settings in raw_profiles.items()
2065
- ]
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))
2066
2119
 
2067
2120
  return ProfilesCollection(profiles, active=active_profile)
2068
2121