prefect-client 2.18.0__py3-none-any.whl → 2.18.2__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 (49) hide show
  1. prefect/_internal/schemas/fields.py +31 -12
  2. prefect/automations.py +162 -0
  3. prefect/blocks/core.py +1 -1
  4. prefect/blocks/notifications.py +2 -2
  5. prefect/blocks/system.py +2 -3
  6. prefect/client/orchestration.py +309 -30
  7. prefect/client/schemas/objects.py +11 -8
  8. prefect/client/schemas/sorting.py +9 -0
  9. prefect/client/utilities.py +25 -3
  10. prefect/concurrency/asyncio.py +11 -5
  11. prefect/concurrency/events.py +3 -3
  12. prefect/concurrency/services.py +1 -1
  13. prefect/concurrency/sync.py +9 -5
  14. prefect/deployments/deployments.py +27 -18
  15. prefect/deployments/runner.py +34 -26
  16. prefect/engine.py +3 -1
  17. prefect/events/actions.py +2 -1
  18. prefect/events/cli/automations.py +207 -46
  19. prefect/events/clients.py +53 -20
  20. prefect/events/filters.py +31 -4
  21. prefect/events/instrument.py +40 -40
  22. prefect/events/related.py +2 -1
  23. prefect/events/schemas/automations.py +52 -7
  24. prefect/events/schemas/deployment_triggers.py +16 -228
  25. prefect/events/schemas/events.py +18 -11
  26. prefect/events/schemas/labelling.py +1 -1
  27. prefect/events/utilities.py +1 -1
  28. prefect/events/worker.py +10 -7
  29. prefect/flows.py +42 -24
  30. prefect/input/actions.py +9 -9
  31. prefect/input/run_input.py +51 -37
  32. prefect/new_flow_engine.py +444 -0
  33. prefect/new_task_engine.py +488 -0
  34. prefect/results.py +3 -2
  35. prefect/runner/runner.py +3 -2
  36. prefect/server/api/collections_data/views/aggregate-worker-metadata.json +45 -4
  37. prefect/settings.py +47 -0
  38. prefect/states.py +25 -19
  39. prefect/tasks.py +146 -19
  40. prefect/utilities/asyncutils.py +41 -0
  41. prefect/utilities/engine.py +6 -4
  42. prefect/utilities/schema_tools/validation.py +1 -1
  43. prefect/workers/process.py +2 -1
  44. {prefect_client-2.18.0.dist-info → prefect_client-2.18.2.dist-info}/METADATA +1 -1
  45. {prefect_client-2.18.0.dist-info → prefect_client-2.18.2.dist-info}/RECORD +48 -46
  46. prefect/concurrency/common.py +0 -0
  47. {prefect_client-2.18.0.dist-info → prefect_client-2.18.2.dist-info}/LICENSE +0 -0
  48. {prefect_client-2.18.0.dist-info → prefect_client-2.18.2.dist-info}/WHEEL +0 -0
  49. {prefect_client-2.18.0.dist-info → prefect_client-2.18.2.dist-info}/top_level.txt +0 -0
@@ -16,7 +16,6 @@ from typing import (
16
16
  Any,
17
17
  Dict,
18
18
  List,
19
- Literal,
20
19
  Optional,
21
20
  Set,
22
21
  Union,
@@ -25,19 +24,16 @@ from uuid import UUID
25
24
 
26
25
  from typing_extensions import TypeAlias
27
26
 
28
- from prefect._internal.compatibility.deprecated import deprecated_class
29
27
  from prefect._internal.pydantic import HAS_PYDANTIC_V2
30
- from prefect._internal.schemas.validators import validate_trigger_within
31
28
 
32
29
  if HAS_PYDANTIC_V2:
33
- from pydantic.v1 import Field, PrivateAttr, root_validator, validator
34
- from pydantic.v1.fields import ModelField
30
+ from pydantic.v1 import Field, PrivateAttr
35
31
  else:
36
- from pydantic import Field, PrivateAttr, root_validator, validator
37
- from pydantic.fields import ModelField
32
+ from pydantic import Field, PrivateAttr # type: ignore
38
33
 
34
+ from prefect._internal.compatibility.deprecated import deprecated_class
39
35
  from prefect._internal.schemas.bases import PrefectBaseModel
40
- from prefect.events.actions import RunDeployment
36
+ from prefect.events.actions import ActionTypes, RunDeployment
41
37
 
42
38
  from .automations import (
43
39
  AutomationCore,
@@ -47,13 +43,12 @@ from .automations import (
47
43
  MetricTriggerQuery,
48
44
  Posture,
49
45
  SequenceTrigger,
50
- Trigger,
51
46
  TriggerTypes,
52
47
  )
53
48
  from .events import ResourceSpecification
54
49
 
55
50
 
56
- class BaseDeploymentTrigger(PrefectBaseModel, abc.ABC, extra="ignore"):
51
+ class BaseDeploymentTrigger(PrefectBaseModel, abc.ABC, extra="ignore"): # type: ignore[call-arg]
57
52
  """
58
53
  Base class describing a set of criteria that must be satisfied in order to trigger
59
54
  an automation.
@@ -67,11 +62,7 @@ class BaseDeploymentTrigger(PrefectBaseModel, abc.ABC, extra="ignore"):
67
62
  description: str = Field("", description="A longer description of this automation")
68
63
  enabled: bool = Field(True, description="Whether this automation will be evaluated")
69
64
 
70
- # Fields from Trigger
71
-
72
- type: str
73
-
74
- # Fields from Deployment
65
+ # Fields from the RunDeployment action
75
66
 
76
67
  parameters: Optional[Dict[str, Any]] = Field(
77
68
  None,
@@ -87,60 +78,9 @@ class BaseDeploymentTrigger(PrefectBaseModel, abc.ABC, extra="ignore"):
87
78
  "deployment's default job variables"
88
79
  ),
89
80
  )
90
- _deployment_id: Optional[UUID] = PrivateAttr(default=None)
91
-
92
- def set_deployment_id(self, deployment_id: UUID):
93
- self._deployment_id = deployment_id
94
-
95
- def owner_resource(self) -> Optional[str]:
96
- return f"prefect.deployment.{self._deployment_id}"
97
-
98
- def actions(self) -> List[RunDeployment]:
99
- assert self._deployment_id
100
- return [
101
- RunDeployment(
102
- parameters=self.parameters,
103
- deployment_id=self._deployment_id,
104
- job_variables=self.job_variables,
105
- )
106
- ]
107
-
108
- def as_automation(self) -> AutomationCore:
109
- if not self.name:
110
- raise ValueError("name is required")
111
-
112
- return AutomationCore(
113
- name=self.name,
114
- description=self.description,
115
- enabled=self.enabled,
116
- trigger=self.as_trigger(),
117
- actions=self.actions(),
118
- owner_resource=self.owner_resource(),
119
- )
120
-
121
- @abc.abstractmethod
122
- def as_trigger(self) -> Trigger:
123
- ...
124
81
 
125
82
 
126
- class DeploymentResourceTrigger(BaseDeploymentTrigger, abc.ABC):
127
- """
128
- Base class for triggers that may filter by the labels of resources.
129
- """
130
-
131
- type: str
132
-
133
- match: ResourceSpecification = Field(
134
- default_factory=lambda: ResourceSpecification.parse_obj({}),
135
- description="Labels for resources which this trigger will match.",
136
- )
137
- match_related: ResourceSpecification = Field(
138
- default_factory=lambda: ResourceSpecification.parse_obj({}),
139
- description="Labels for related resources which this trigger will match.",
140
- )
141
-
142
-
143
- class DeploymentEventTrigger(DeploymentResourceTrigger):
83
+ class DeploymentEventTrigger(BaseDeploymentTrigger, EventTrigger):
144
84
  """
145
85
  A trigger that fires based on the presence or absence of events within a given
146
86
  period of time.
@@ -148,184 +88,28 @@ class DeploymentEventTrigger(DeploymentResourceTrigger):
148
88
 
149
89
  trigger_type = EventTrigger
150
90
 
151
- type: Literal["event"] = "event"
152
91
 
153
- after: Set[str] = Field(
154
- default_factory=set,
155
- description=(
156
- "The event(s) which must first been seen to fire this trigger. If "
157
- "empty, then fire this trigger immediately. Events may include "
158
- "trailing wildcards, like `prefect.flow-run.*`"
159
- ),
160
- )
161
- expect: Set[str] = Field(
162
- default_factory=set,
163
- description=(
164
- "The event(s) this trigger is expecting to see. If empty, this "
165
- "trigger will match any event. Events may include trailing wildcards, "
166
- "like `prefect.flow-run.*`"
167
- ),
168
- )
169
-
170
- for_each: Set[str] = Field(
171
- default_factory=set,
172
- description=(
173
- "Evaluate the trigger separately for each distinct value of these labels "
174
- "on the resource. By default, labels refer to the primary resource of the "
175
- "triggering event. You may also refer to labels from related "
176
- "resources by specifying `related:<role>:<label>`. This will use the "
177
- "value of that label for the first related resource in that role. For "
178
- 'example, `"for_each": ["related:flow:prefect.resource.id"]` would '
179
- "evaluate the trigger for each flow."
180
- ),
181
- )
182
- posture: Literal[Posture.Reactive, Posture.Proactive] = Field( # type: ignore[valid-type]
183
- Posture.Reactive,
184
- description=(
185
- "The posture of this trigger, either Reactive or Proactive. Reactive "
186
- "triggers respond to the _presence_ of the expected events, while "
187
- "Proactive triggers respond to the _absence_ of those expected events."
188
- ),
189
- )
190
- threshold: int = Field(
191
- 1,
192
- description=(
193
- "The number of events required for this trigger to fire (for "
194
- "Reactive triggers), or the number of events expected (for Proactive "
195
- "triggers)"
196
- ),
197
- )
198
- within: timedelta = Field(
199
- timedelta(0),
200
- minimum=0.0,
201
- exclusiveMinimum=False,
202
- description=(
203
- "The time period over which the events must occur. For Reactive triggers, "
204
- "this may be as low as 0 seconds, but must be at least 10 seconds for "
205
- "Proactive triggers"
206
- ),
207
- )
208
-
209
- @validator("within")
210
- def enforce_minimum_within(
211
- cls, value: timedelta, values, config, field: ModelField
212
- ):
213
- return validate_trigger_within(value, field)
214
-
215
- @root_validator(skip_on_failure=True)
216
- def enforce_minimum_within_for_proactive_triggers(cls, values: Dict[str, Any]):
217
- posture: Optional[Posture] = values.get("posture")
218
- within: Optional[timedelta] = values.get("within")
219
-
220
- if posture == Posture.Proactive:
221
- if not within or within == timedelta(0):
222
- values["within"] = timedelta(seconds=10.0)
223
- elif within < timedelta(seconds=10.0):
224
- raise ValueError(
225
- "The minimum within for Proactive triggers is 10 seconds"
226
- )
227
-
228
- return values
229
-
230
- def as_trigger(self) -> Trigger:
231
- return self.trigger_type(
232
- match=self.match,
233
- match_related=self.match_related,
234
- after=self.after,
235
- expect=self.expect,
236
- for_each=self.for_each,
237
- posture=self.posture,
238
- threshold=self.threshold,
239
- within=self.within,
240
- )
241
-
242
-
243
- class DeploymentMetricTrigger(DeploymentResourceTrigger):
92
+ class DeploymentMetricTrigger(BaseDeploymentTrigger, MetricTrigger):
244
93
  """
245
94
  A trigger that fires based on the results of a metric query.
246
95
  """
247
96
 
248
97
  trigger_type = MetricTrigger
249
98
 
250
- type: Literal["metric"] = "metric"
251
-
252
- posture: Literal[Posture.Metric] = Field( # type: ignore[valid-type]
253
- Posture.Metric,
254
- description="Periodically evaluate the configured metric query.",
255
- )
256
-
257
- metric: MetricTriggerQuery = Field(
258
- ...,
259
- description="The metric query to evaluate for this trigger. ",
260
- )
261
-
262
- def as_trigger(self) -> Trigger:
263
- return self.trigger_type(
264
- match=self.match,
265
- match_related=self.match_related,
266
- posture=self.posture,
267
- metric=self.metric,
268
- job_variables=self.job_variables,
269
- )
270
-
271
-
272
- class DeploymentCompositeTrigger(BaseDeploymentTrigger, abc.ABC):
273
- """
274
- Requires some number of triggers to have fired within the given time period.
275
- """
276
-
277
- type: Literal["compound", "sequence"]
278
- triggers: List["TriggerTypes"]
279
- within: Optional[timedelta]
280
99
 
281
-
282
- class DeploymentCompoundTrigger(DeploymentCompositeTrigger):
100
+ class DeploymentCompoundTrigger(BaseDeploymentTrigger, CompoundTrigger):
283
101
  """A composite trigger that requires some number of triggers to have
284
102
  fired within the given time period"""
285
103
 
286
104
  trigger_type = CompoundTrigger
287
105
 
288
- type: Literal["compound"] = "compound"
289
- require: Union[int, Literal["any", "all"]]
290
-
291
- @root_validator
292
- def validate_require(cls, values: Dict[str, Any]) -> Dict[str, Any]:
293
- require = values.get("require")
294
-
295
- if isinstance(require, int):
296
- if require < 1:
297
- raise ValueError("required must be at least 1")
298
- if require > len(values["triggers"]):
299
- raise ValueError(
300
- "required must be less than or equal to the number of triggers"
301
- )
302
-
303
- return values
304
-
305
- def as_trigger(self) -> Trigger:
306
- return self.trigger_type(
307
- require=self.require,
308
- triggers=self.triggers,
309
- within=self.within,
310
- job_variables=self.job_variables,
311
- )
312
106
 
313
-
314
- class DeploymentSequenceTrigger(DeploymentCompositeTrigger):
107
+ class DeploymentSequenceTrigger(BaseDeploymentTrigger, SequenceTrigger):
315
108
  """A composite trigger that requires some number of triggers to have fired
316
109
  within the given time period in a specific order"""
317
110
 
318
111
  trigger_type = SequenceTrigger
319
112
 
320
- type: Literal["sequence"] = "sequence"
321
-
322
- def as_trigger(self) -> Trigger:
323
- return self.trigger_type(
324
- triggers=self.triggers,
325
- within=self.within,
326
- job_variables=self.job_variables,
327
- )
328
-
329
113
 
330
114
  # Concrete deployment trigger types
331
115
  DeploymentTriggerTypes: TypeAlias = Union[
@@ -461,7 +245,10 @@ class DeploymentTrigger(PrefectBaseModel):
461
245
  def as_automation(self) -> AutomationCore:
462
246
  assert self.name
463
247
 
248
+ trigger: TriggerTypes
249
+
464
250
  if self.posture == Posture.Metric:
251
+ assert self.metric
465
252
  trigger = MetricTrigger(
466
253
  type="metric",
467
254
  match=self.match,
@@ -496,12 +283,13 @@ class DeploymentTrigger(PrefectBaseModel):
496
283
  def owner_resource(self) -> Optional[str]:
497
284
  return f"prefect.deployment.{self._deployment_id}"
498
285
 
499
- def actions(self) -> List[RunDeployment]:
286
+ def actions(self) -> List[ActionTypes]:
500
287
  assert self._deployment_id
501
288
  return [
502
289
  RunDeployment(
503
- parameters=self.parameters,
290
+ source="selected",
504
291
  deployment_id=self._deployment_id,
292
+ parameters=self.parameters,
505
293
  job_variables=self.job_variables,
506
294
  )
507
295
  ]
@@ -15,9 +15,14 @@ from typing import (
15
15
  from uuid import UUID, uuid4
16
16
 
17
17
  import pendulum
18
- from pydantic import Field, root_validator, validator
19
18
 
20
19
  from prefect._internal.pydantic import HAS_PYDANTIC_V2
20
+
21
+ if HAS_PYDANTIC_V2:
22
+ from pydantic.v1 import Field, root_validator, validator
23
+ else:
24
+ from pydantic import Field, root_validator, validator # type: ignore
25
+
21
26
  from prefect._internal.schemas.bases import PrefectBaseModel
22
27
  from prefect._internal.schemas.fields import DateTimeTZ
23
28
  from prefect.logging import get_logger
@@ -26,11 +31,6 @@ from prefect.settings import (
26
31
  PREFECT_EVENTS_MAXIMUM_RELATED_RESOURCES,
27
32
  )
28
33
 
29
- if HAS_PYDANTIC_V2:
30
- from pydantic.v1 import Field, root_validator, validator
31
- else:
32
- from pydantic import Field, root_validator, validator
33
-
34
34
  from .labelling import Labelled
35
35
 
36
36
  logger = get_logger(__name__)
@@ -128,7 +128,7 @@ class Event(PrefectBaseModel):
128
128
  description="The client-provided identifier of this event",
129
129
  )
130
130
  follows: Optional[UUID] = Field(
131
- None,
131
+ default=None,
132
132
  description=(
133
133
  "The ID of an event that is known to have occurred prior to this one. "
134
134
  "If set, this may be used to establish a more precise ordering of causally-"
@@ -192,15 +192,22 @@ class ReceivedEvent(Event):
192
192
 
193
193
  def matches(expected: str, value: Optional[str]) -> bool:
194
194
  """Returns true if the given value matches the expected string, which may
195
- include wildcards"""
195
+ include a a negation prefix ("!this-value") or a wildcard suffix
196
+ ("any-value-starting-with*")"""
196
197
  if value is None:
197
198
  return False
198
199
 
199
- # TODO: handle wildcards/globs better than this
200
+ positive = True
201
+ if expected.startswith("!"):
202
+ expected = expected[1:]
203
+ positive = False
204
+
200
205
  if expected.endswith("*"):
201
- return value.startswith(expected[:-1])
206
+ match = value.startswith(expected[:-1])
207
+ else:
208
+ match = value == expected
202
209
 
203
- return value == expected
210
+ return match if positive else not match
204
211
 
205
212
 
206
213
  class ResourceSpecification(PrefectBaseModel):
@@ -71,7 +71,7 @@ class LabelDiver:
71
71
  raise AttributeError
72
72
 
73
73
 
74
- class Labelled(PrefectBaseModel, extra="ignore"):
74
+ class Labelled(PrefectBaseModel, extra="ignore"): # type: ignore[call-arg]
75
75
  """An object defined by string labels and values"""
76
76
 
77
77
  __root__: Dict[str, str]
@@ -61,7 +61,7 @@ def emit_event(
61
61
  if worker_instance.client_type not in operational_clients:
62
62
  return None
63
63
 
64
- event_kwargs = {
64
+ event_kwargs: Dict[str, Any] = {
65
65
  "event": event,
66
66
  "resource": resource,
67
67
  }
prefect/events/worker.py CHANGED
@@ -1,6 +1,7 @@
1
1
  from contextlib import asynccontextmanager
2
2
  from contextvars import Context, copy_context
3
- from typing import Any, Optional, Tuple, Type
3
+ from typing import Any, Dict, Optional, Tuple, Type
4
+ from uuid import UUID
4
5
 
5
6
  from typing_extensions import Self
6
7
 
@@ -41,11 +42,11 @@ def emit_events_to_cloud() -> bool:
41
42
 
42
43
  def should_emit_events_to_running_server() -> bool:
43
44
  api_url = PREFECT_API_URL.value()
44
- return isinstance(api_url, str) and PREFECT_EXPERIMENTAL_EVENTS
45
+ return isinstance(api_url, str) and PREFECT_EXPERIMENTAL_EVENTS.value()
45
46
 
46
47
 
47
48
  def should_emit_events_to_ephemeral_server() -> bool:
48
- return PREFECT_API_KEY.value() is None and PREFECT_EXPERIMENTAL_EVENTS
49
+ return PREFECT_API_KEY.value() is None and PREFECT_EXPERIMENTAL_EVENTS.value()
49
50
 
50
51
 
51
52
  class EventsWorker(QueueService[Event]):
@@ -56,6 +57,7 @@ class EventsWorker(QueueService[Event]):
56
57
  self.client_type = client_type
57
58
  self.client_options = client_options
58
59
  self._client: EventsClient
60
+ self._context_cache: Dict[UUID, Context] = {}
59
61
 
60
62
  @asynccontextmanager
61
63
  async def _lifespan(self):
@@ -64,11 +66,12 @@ class EventsWorker(QueueService[Event]):
64
66
  async with self._client:
65
67
  yield
66
68
 
67
- def _prepare_item(self, event: Event) -> Tuple[Event, Context]:
68
- return (event, copy_context())
69
+ def _prepare_item(self, event: Event) -> Event:
70
+ self._context_cache[event.id] = copy_context()
71
+ return event
69
72
 
70
- async def _handle(self, event_and_context: Tuple[Event, Context]):
71
- event, context = event_and_context
73
+ async def _handle(self, event: Event):
74
+ context = self._context_cache.pop(event.id)
72
75
  with temporary_context(context=context):
73
76
  await self.attach_related_resources_from_context(event)
74
77
 
prefect/flows.py CHANGED
@@ -34,20 +34,10 @@ from typing import (
34
34
  )
35
35
  from uuid import UUID
36
36
 
37
- from prefect._vendor.fastapi.encoders import jsonable_encoder
38
- from typing_extensions import Self
37
+ from rich.console import Console
38
+ from typing_extensions import Literal, ParamSpec, Self
39
39
 
40
- from prefect._internal.compatibility.deprecated import deprecated_parameter
41
- from prefect._internal.concurrency.api import create_call, from_async
42
40
  from prefect._internal.pydantic import HAS_PYDANTIC_V2
43
- from prefect.client.orchestration import get_client
44
- from prefect.deployments.runner import DeploymentImage, EntrypointType, deploy
45
- from prefect.filesystems import ReadableDeploymentStorage
46
- from prefect.runner.storage import (
47
- BlockStorageAdapter,
48
- RunnerStorage,
49
- create_storage_from_url,
50
- )
51
41
 
52
42
  if HAS_PYDANTIC_V2:
53
43
  import pydantic.v1 as pydantic
@@ -67,26 +57,36 @@ else:
67
57
 
68
58
  V2ValidationError = None
69
59
 
70
- from rich.console import Console
71
- from typing_extensions import Literal, ParamSpec
60
+ from prefect._vendor.fastapi.encoders import jsonable_encoder
72
61
 
62
+ from prefect._internal.compatibility.deprecated import deprecated_parameter
63
+ from prefect._internal.concurrency.api import create_call, from_async
73
64
  from prefect._internal.schemas.validators import raise_on_name_with_banned_characters
65
+ from prefect.client.orchestration import get_client
74
66
  from prefect.client.schemas.objects import Flow as FlowSchema
75
67
  from prefect.client.schemas.objects import FlowRun, MinimalDeploymentSchedule
76
68
  from prefect.client.schemas.schedules import SCHEDULE_TYPES
77
69
  from prefect.context import PrefectObjectRegistry, registry_from_script
78
- from prefect.events import DeploymentTriggerTypes
70
+ from prefect.deployments.runner import DeploymentImage, EntrypointType, deploy
71
+ from prefect.events import DeploymentTriggerTypes, TriggerTypes
79
72
  from prefect.exceptions import (
80
73
  MissingFlowError,
81
74
  ObjectNotFound,
82
75
  ParameterTypeError,
83
76
  UnspecifiedFlowError,
84
77
  )
78
+ from prefect.filesystems import ReadableDeploymentStorage
85
79
  from prefect.futures import PrefectFuture
86
80
  from prefect.logging import get_logger
87
81
  from prefect.results import ResultSerializer, ResultStorage
82
+ from prefect.runner.storage import (
83
+ BlockStorageAdapter,
84
+ RunnerStorage,
85
+ create_storage_from_url,
86
+ )
88
87
  from prefect.settings import (
89
88
  PREFECT_DEFAULT_WORK_POOL_NAME,
89
+ PREFECT_EXPERIMENTAL_ENABLE_NEW_ENGINE,
90
90
  PREFECT_FLOW_DEFAULT_RETRIES,
91
91
  PREFECT_FLOW_DEFAULT_RETRY_DELAY_SECONDS,
92
92
  PREFECT_UI_URL,
@@ -618,7 +618,7 @@ class Flow(Generic[P, R]):
618
618
  schedule: Optional[SCHEDULE_TYPES] = None,
619
619
  is_schedule_active: Optional[bool] = None,
620
620
  parameters: Optional[dict] = None,
621
- triggers: Optional[List[DeploymentTriggerTypes]] = None,
621
+ triggers: Optional[List[Union[DeploymentTriggerTypes, TriggerTypes]]] = None,
622
622
  description: Optional[str] = None,
623
623
  tags: Optional[List[str]] = None,
624
624
  version: Optional[str] = None,
@@ -733,7 +733,7 @@ class Flow(Generic[P, R]):
733
733
  @sync_compatible
734
734
  async def serve(
735
735
  self,
736
- name: str,
736
+ name: Optional[str] = None,
737
737
  interval: Optional[
738
738
  Union[
739
739
  Iterable[Union[int, float, datetime.timedelta]],
@@ -748,7 +748,7 @@ class Flow(Generic[P, R]):
748
748
  schedules: Optional[List["FlexibleScheduleList"]] = None,
749
749
  schedule: Optional[SCHEDULE_TYPES] = None,
750
750
  is_schedule_active: Optional[bool] = None,
751
- triggers: Optional[List[DeploymentTriggerTypes]] = None,
751
+ triggers: Optional[List[Union[DeploymentTriggerTypes, TriggerTypes]]] = None,
752
752
  parameters: Optional[dict] = None,
753
753
  description: Optional[str] = None,
754
754
  tags: Optional[List[str]] = None,
@@ -764,7 +764,7 @@ class Flow(Generic[P, R]):
764
764
  Creates a deployment for this flow and starts a runner to monitor for scheduled work.
765
765
 
766
766
  Args:
767
- name: The name to give the created deployment.
767
+ name: The name to give the created deployment. Defaults to the name of the flow.
768
768
  interval: An interval on which to execute the deployment. Accepts a number or a
769
769
  timedelta object to create a single schedule. If a number is given, it will be
770
770
  interpreted as seconds. Also accepts an iterable of numbers or timedelta to create
@@ -827,10 +827,13 @@ class Flow(Generic[P, R]):
827
827
  """
828
828
  from prefect.runner import Runner
829
829
 
830
- # Handling for my_flow.serve(__file__)
831
- # Will set name to name of file where my_flow.serve() without the extension
832
- # Non filepath strings will pass through unchanged
833
- name = Path(name).stem
830
+ if not name:
831
+ name = self.name
832
+ else:
833
+ # Handling for my_flow.serve(__file__)
834
+ # Will set name to name of file where my_flow.serve() without the extension
835
+ # Non filepath strings will pass through unchanged
836
+ name = Path(name).stem
834
837
 
835
838
  runner = Runner(name=name, pause_on_shutdown=pause_on_shutdown, limit=limit)
836
839
  deployment_id = await runner.add_flow(
@@ -962,7 +965,7 @@ class Flow(Generic[P, R]):
962
965
  schedules: Optional[List[MinimalDeploymentSchedule]] = None,
963
966
  schedule: Optional[SCHEDULE_TYPES] = None,
964
967
  is_schedule_active: Optional[bool] = None,
965
- triggers: Optional[List[DeploymentTriggerTypes]] = None,
968
+ triggers: Optional[List[Union[DeploymentTriggerTypes, TriggerTypes]]] = None,
966
969
  parameters: Optional[dict] = None,
967
970
  description: Optional[str] = None,
968
971
  tags: Optional[List[str]] = None,
@@ -1225,6 +1228,21 @@ class Flow(Generic[P, R]):
1225
1228
  # we can add support for exploring subflows for tasks in the future.
1226
1229
  return track_viz_task(self.isasync, self.name, parameters)
1227
1230
 
1231
+ if PREFECT_EXPERIMENTAL_ENABLE_NEW_ENGINE.value():
1232
+ from prefect.new_flow_engine import run_flow, run_flow_sync
1233
+
1234
+ run_kwargs = dict(
1235
+ flow=self,
1236
+ parameters=parameters,
1237
+ wait_for=wait_for,
1238
+ return_type=return_type,
1239
+ )
1240
+ if self.isasync:
1241
+ # this returns an awaitable coroutine
1242
+ return run_flow(**run_kwargs)
1243
+ else:
1244
+ return run_flow_sync(**run_kwargs)
1245
+
1228
1246
  return enter_flow_run_engine_from_flow_call(
1229
1247
  self,
1230
1248
  parameters,
prefect/input/actions.py CHANGED
@@ -5,7 +5,7 @@ import orjson
5
5
  import pydantic
6
6
 
7
7
  from prefect._internal.pydantic import HAS_PYDANTIC_V2
8
- from prefect.client.utilities import inject_client
8
+ from prefect.client.utilities import client_injector
9
9
  from prefect.context import FlowRunContext
10
10
  from prefect.exceptions import PrefectHTTPStatusError
11
11
  from prefect.utilities.asyncutils import sync_compatible
@@ -52,13 +52,13 @@ async def create_flow_run_input_from_model(
52
52
 
53
53
 
54
54
  @sync_compatible
55
- @inject_client
55
+ @client_injector
56
56
  async def create_flow_run_input(
57
+ client: "PrefectClient",
57
58
  key: str,
58
59
  value: Any,
59
60
  flow_run_id: Optional[UUID] = None,
60
61
  sender: Optional[str] = None,
61
- client: "PrefectClient" = None,
62
62
  ):
63
63
  """
64
64
  Create a new flow run input. The given `value` will be serialized to JSON
@@ -81,13 +81,13 @@ async def create_flow_run_input(
81
81
 
82
82
 
83
83
  @sync_compatible
84
- @inject_client
84
+ @client_injector
85
85
  async def filter_flow_run_input(
86
+ client: "PrefectClient",
86
87
  key_prefix: str,
87
88
  limit: int = 1,
88
89
  exclude_keys: Optional[Set[str]] = None,
89
90
  flow_run_id: Optional[UUID] = None,
90
- client: "PrefectClient" = None,
91
91
  ):
92
92
  if exclude_keys is None:
93
93
  exclude_keys = set()
@@ -103,9 +103,9 @@ async def filter_flow_run_input(
103
103
 
104
104
 
105
105
  @sync_compatible
106
- @inject_client
106
+ @client_injector
107
107
  async def read_flow_run_input(
108
- key: str, flow_run_id: Optional[UUID] = None, client: "PrefectClient" = None
108
+ client: "PrefectClient", key: str, flow_run_id: Optional[UUID] = None
109
109
  ) -> Any:
110
110
  """Read a flow run input.
111
111
 
@@ -126,9 +126,9 @@ async def read_flow_run_input(
126
126
 
127
127
 
128
128
  @sync_compatible
129
- @inject_client
129
+ @client_injector
130
130
  async def delete_flow_run_input(
131
- key: str, flow_run_id: Optional[UUID] = None, client: "PrefectClient" = None
131
+ client: "PrefectClient", key: str, flow_run_id: Optional[UUID] = None
132
132
  ):
133
133
  """Delete a flow run input.
134
134