prefect-client 3.3.8.dev2__py3-none-any.whl → 3.3.8.dev4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
prefect/_build_info.py CHANGED
@@ -1,5 +1,5 @@
1
1
  # Generated by versioningit
2
- __version__ = "3.3.8.dev2"
3
- __build_date__ = "2025-04-30 08:08:18.628483+00:00"
4
- __git_commit__ = "07107c3e1fd50fb76288b0107efaac6df4f57d2d"
2
+ __version__ = "3.3.8.dev4"
3
+ __build_date__ = "2025-05-02 08:08:48.097027+00:00"
4
+ __git_commit__ = "5d6e0c61baba4513aa9744c942297d645fc4db2c"
5
5
  __dirty__ = False
@@ -485,25 +485,6 @@ def validate_not_negative(v: Optional[float]) -> Optional[float]:
485
485
  return v
486
486
 
487
487
 
488
- @overload
489
- def validate_message_template_variables(v: str) -> str: ...
490
-
491
-
492
- @overload
493
- def validate_message_template_variables(v: None) -> None: ...
494
-
495
-
496
- def validate_message_template_variables(v: Optional[str]) -> Optional[str]:
497
- from prefect.client.schemas.objects import FLOW_RUN_NOTIFICATION_TEMPLATE_KWARGS
498
-
499
- if v is not None:
500
- try:
501
- v.format(**{k: "test" for k in FLOW_RUN_NOTIFICATION_TEMPLATE_KWARGS})
502
- except KeyError as exc:
503
- raise ValueError(f"Invalid template variable provided: '{exc.args[0]}'")
504
- return v
505
-
506
-
507
488
  def validate_default_queue_id_not_none(v: Optional[UUID]) -> UUID:
508
489
  if v is None:
509
490
  raise ValueError(
prefect/blocks/core.py CHANGED
@@ -374,15 +374,15 @@ class Block(BaseModel, ABC):
374
374
  for field_name in type(self).model_fields
375
375
  }
376
376
  )
377
- if extra_fields := {
377
+ extra_fields = {
378
378
  "block_type_slug": self.get_block_type_slug(),
379
379
  "_block_document_id": self._block_document_id,
380
380
  "_block_document_name": self._block_document_name,
381
381
  "_is_anonymous": self._is_anonymous,
382
- }:
383
- jsonable_self |= {
384
- key: value for key, value in extra_fields.items() if value is not None
385
- }
382
+ }
383
+ jsonable_self |= {
384
+ key: value for key, value in extra_fields.items() if value is not None
385
+ }
386
386
  return jsonable_self
387
387
 
388
388
  @classmethod
@@ -87,8 +87,6 @@ import prefect.states
87
87
  from prefect.client.constants import SERVER_API_VERSION
88
88
  from prefect.client.schemas import FlowRun, OrchestrationResult, TaskRun
89
89
  from prefect.client.schemas.actions import (
90
- FlowRunNotificationPolicyCreate,
91
- FlowRunNotificationPolicyUpdate,
92
90
  TaskRunCreate,
93
91
  TaskRunUpdate,
94
92
  WorkQueueCreate,
@@ -98,14 +96,12 @@ from prefect.client.schemas.filters import (
98
96
  DeploymentFilter,
99
97
  FlowFilter,
100
98
  FlowRunFilter,
101
- FlowRunNotificationPolicyFilter,
102
99
  TaskRunFilter,
103
100
  WorkQueueFilter,
104
101
  WorkQueueFilterName,
105
102
  )
106
103
  from prefect.client.schemas.objects import (
107
104
  Constant,
108
- FlowRunNotificationPolicy,
109
105
  Parameter,
110
106
  TaskRunPolicy,
111
107
  TaskRunResult,
@@ -962,151 +958,6 @@ class PrefectClient(
962
958
  response.json()
963
959
  )
964
960
 
965
- async def create_flow_run_notification_policy(
966
- self,
967
- block_document_id: UUID,
968
- is_active: bool = True,
969
- tags: Optional[list[str]] = None,
970
- state_names: Optional[list[str]] = None,
971
- message_template: Optional[str] = None,
972
- ) -> UUID:
973
- """
974
- Create a notification policy for flow runs
975
-
976
- Args:
977
- block_document_id: The block document UUID
978
- is_active: Whether the notification policy is active
979
- tags: List of flow tags
980
- state_names: List of state names
981
- message_template: Notification message template
982
- """
983
- if tags is None:
984
- tags = []
985
- if state_names is None:
986
- state_names = []
987
-
988
- policy = FlowRunNotificationPolicyCreate(
989
- block_document_id=block_document_id,
990
- is_active=is_active,
991
- tags=tags,
992
- state_names=state_names,
993
- message_template=message_template,
994
- )
995
- response = await self._client.post(
996
- "/flow_run_notification_policies/",
997
- json=policy.model_dump(mode="json"),
998
- )
999
-
1000
- policy_id = response.json().get("id")
1001
- if not policy_id:
1002
- raise httpx.RequestError(f"Malformed response: {response}")
1003
-
1004
- return UUID(policy_id)
1005
-
1006
- async def delete_flow_run_notification_policy(
1007
- self,
1008
- id: UUID,
1009
- ) -> None:
1010
- """
1011
- Delete a flow run notification policy by id.
1012
-
1013
- Args:
1014
- id: UUID of the flow run notification policy to delete.
1015
- Raises:
1016
- prefect.exceptions.ObjectNotFound: If request returns 404
1017
- httpx.RequestError: If requests fails
1018
- """
1019
- try:
1020
- await self._client.delete(f"/flow_run_notification_policies/{id}")
1021
- except httpx.HTTPStatusError as e:
1022
- if e.response.status_code == status.HTTP_404_NOT_FOUND:
1023
- raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
1024
- else:
1025
- raise
1026
-
1027
- async def update_flow_run_notification_policy(
1028
- self,
1029
- id: UUID,
1030
- block_document_id: Optional[UUID] = None,
1031
- is_active: Optional[bool] = None,
1032
- tags: Optional[list[str]] = None,
1033
- state_names: Optional[list[str]] = None,
1034
- message_template: Optional[str] = None,
1035
- ) -> None:
1036
- """
1037
- Update a notification policy for flow runs
1038
-
1039
- Args:
1040
- id: UUID of the notification policy
1041
- block_document_id: The block document UUID
1042
- is_active: Whether the notification policy is active
1043
- tags: List of flow tags
1044
- state_names: List of state names
1045
- message_template: Notification message template
1046
- Raises:
1047
- prefect.exceptions.ObjectNotFound: If request returns 404
1048
- httpx.RequestError: If requests fails
1049
- """
1050
- params: dict[str, Any] = {}
1051
- if block_document_id is not None:
1052
- params["block_document_id"] = block_document_id
1053
- if is_active is not None:
1054
- params["is_active"] = is_active
1055
- if tags is not None:
1056
- params["tags"] = tags
1057
- if state_names is not None:
1058
- params["state_names"] = state_names
1059
- if message_template is not None:
1060
- params["message_template"] = message_template
1061
-
1062
- policy = FlowRunNotificationPolicyUpdate(**params)
1063
-
1064
- try:
1065
- await self._client.patch(
1066
- f"/flow_run_notification_policies/{id}",
1067
- json=policy.model_dump(mode="json", exclude_unset=True),
1068
- )
1069
- except httpx.HTTPStatusError as e:
1070
- if e.response.status_code == status.HTTP_404_NOT_FOUND:
1071
- raise prefect.exceptions.ObjectNotFound(http_exc=e) from e
1072
- else:
1073
- raise
1074
-
1075
- async def read_flow_run_notification_policies(
1076
- self,
1077
- flow_run_notification_policy_filter: FlowRunNotificationPolicyFilter,
1078
- limit: Optional[int] = None,
1079
- offset: int = 0,
1080
- ) -> list[FlowRunNotificationPolicy]:
1081
- """
1082
- Query the Prefect API for flow run notification policies. Only policies matching all criteria will
1083
- be returned.
1084
-
1085
- Args:
1086
- flow_run_notification_policy_filter: filter criteria for notification policies
1087
- limit: a limit for the notification policies query
1088
- offset: an offset for the notification policies query
1089
-
1090
- Returns:
1091
- a list of FlowRunNotificationPolicy model representations
1092
- of the notification policies
1093
- """
1094
- body: dict[str, Any] = {
1095
- "flow_run_notification_policy_filter": (
1096
- flow_run_notification_policy_filter.model_dump(mode="json")
1097
- if flow_run_notification_policy_filter
1098
- else None
1099
- ),
1100
- "limit": limit,
1101
- "offset": offset,
1102
- }
1103
- response = await self._client.post(
1104
- "/flow_run_notification_policies/filter", json=body
1105
- )
1106
- return pydantic.TypeAdapter(list[FlowRunNotificationPolicy]).validate_python(
1107
- response.json()
1108
- )
1109
-
1110
961
  async def read_work_queues(
1111
962
  self,
1112
963
  work_pool_name: Optional[str] = None,
@@ -63,9 +63,6 @@ ServerRoutes = Literal[
63
63
  "/events/count-by/{countable}",
64
64
  "/events/filter",
65
65
  "/events/filter/next",
66
- "/flow_run_notification_policies/",
67
- "/flow_run_notification_policies/{id}",
68
- "/flow_run_notification_policies/filter",
69
66
  "/flow_run_states/",
70
67
  "/flow_run_states/{id}",
71
68
  "/flow_runs/",
@@ -15,7 +15,6 @@ from prefect._internal.schemas.validators import (
15
15
  validate_artifact_key,
16
16
  validate_block_document_name,
17
17
  validate_block_type_slug,
18
- validate_message_template_variables,
19
18
  validate_name_present_on_nonanonymous_blocks,
20
19
  validate_schedule_max_scheduled_runs,
21
20
  validate_variable_name,
@@ -46,7 +45,7 @@ from prefect.types import (
46
45
  PositiveInteger,
47
46
  StrictVariableValue,
48
47
  )
49
- from prefect.utilities.collections import listrepr, visit_collection
48
+ from prefect.utilities.collections import visit_collection
50
49
  from prefect.utilities.pydantic import get_class_fields_only
51
50
 
52
51
  if TYPE_CHECKING:
@@ -812,51 +811,6 @@ class WorkQueueUpdate(ActionBaseModel):
812
811
  )
813
812
 
814
813
 
815
- class FlowRunNotificationPolicyCreate(ActionBaseModel):
816
- """Data used by the Prefect REST API to create a flow run notification policy."""
817
-
818
- is_active: bool = Field(
819
- default=True, description="Whether the policy is currently active"
820
- )
821
- state_names: list[str] = Field(
822
- default=..., description="The flow run states that trigger notifications"
823
- )
824
- tags: list[str] = Field(
825
- default=...,
826
- description="The flow run tags that trigger notifications (set [] to disable)",
827
- )
828
- block_document_id: UUID = Field(
829
- default=..., description="The block document ID used for sending notifications"
830
- )
831
- message_template: Optional[str] = Field(
832
- default=None,
833
- description=(
834
- "A templatable notification message. Use {braces} to add variables."
835
- " Valid variables include:"
836
- f" {listrepr(sorted(objects.FLOW_RUN_NOTIFICATION_TEMPLATE_KWARGS), sep=', ')}"
837
- ),
838
- examples=[
839
- "Flow run {flow_run_name} with id {flow_run_id} entered state"
840
- " {flow_run_state_name}."
841
- ],
842
- )
843
-
844
- @field_validator("message_template")
845
- @classmethod
846
- def validate_message_template_variables(cls, v: Optional[str]) -> Optional[str]:
847
- return validate_message_template_variables(v)
848
-
849
-
850
- class FlowRunNotificationPolicyUpdate(ActionBaseModel):
851
- """Data used by the Prefect REST API to update a flow run notification policy."""
852
-
853
- is_active: Optional[bool] = Field(default=None)
854
- state_names: Optional[list[str]] = Field(default=None)
855
- tags: Optional[list[str]] = Field(default=None)
856
- block_document_id: Optional[UUID] = Field(default=None)
857
- message_template: Optional[str] = Field(default=None)
858
-
859
-
860
814
  class ArtifactCreate(ActionBaseModel):
861
815
  """Data used by the Prefect REST API to create an artifact."""
862
816
 
@@ -799,26 +799,6 @@ class BlockDocumentFilter(PrefectBaseModel, OperatorMixin):
799
799
  )
800
800
 
801
801
 
802
- class FlowRunNotificationPolicyFilterIsActive(PrefectBaseModel):
803
- """Filter by `FlowRunNotificationPolicy.is_active`."""
804
-
805
- eq_: Optional[bool] = Field(
806
- default=None,
807
- description=(
808
- "Filter notification policies for only those that are or are not active."
809
- ),
810
- )
811
-
812
-
813
- class FlowRunNotificationPolicyFilter(PrefectBaseModel):
814
- """Filter FlowRunNotificationPolicies."""
815
-
816
- is_active: Optional[FlowRunNotificationPolicyFilterIsActive] = Field(
817
- default=FlowRunNotificationPolicyFilterIsActive(eq_=False),
818
- description="Filter criteria for `FlowRunNotificationPolicy.is_active`. ",
819
- )
820
-
821
-
822
802
  class WorkQueueFilterId(PrefectBaseModel):
823
803
  """Filter by `WorkQueue.id`."""
824
804
 
@@ -45,7 +45,6 @@ from prefect._internal.schemas.validators import (
45
45
  validate_block_document_name,
46
46
  validate_default_queue_id_not_none,
47
47
  validate_max_metadata_length,
48
- validate_message_template_variables,
49
48
  validate_name_present_on_nonanonymous_blocks,
50
49
  validate_not_negative,
51
50
  validate_parent_and_ref_diff,
@@ -63,7 +62,7 @@ from prefect.types import (
63
62
  )
64
63
  from prefect.types._datetime import DateTime, now
65
64
  from prefect.utilities.asyncutils import run_coro_as_sync
66
- from prefect.utilities.collections import AutoEnum, listrepr, visit_collection
65
+ from prefect.utilities.collections import AutoEnum, visit_collection
67
66
  from prefect.utilities.names import generate_slug
68
67
  from prefect.utilities.pydantic import handle_secret_render
69
68
 
@@ -72,19 +71,6 @@ R = TypeVar("R", default=Any)
72
71
 
73
72
  DEFAULT_BLOCK_SCHEMA_VERSION: Literal["non-versioned"] = "non-versioned"
74
73
  DEFAULT_AGENT_WORK_POOL_NAME: Literal["default-agent-pool"] = "default-agent-pool"
75
- FLOW_RUN_NOTIFICATION_TEMPLATE_KWARGS: list[str] = [
76
- "flow_run_notification_policy_id",
77
- "flow_id",
78
- "flow_name",
79
- "flow_run_url",
80
- "flow_run_id",
81
- "flow_run_name",
82
- "flow_run_parameters",
83
- "flow_run_state_type",
84
- "flow_run_state_name",
85
- "flow_run_state_timestamp",
86
- "flow_run_state_message",
87
- ]
88
74
 
89
75
 
90
76
  class StateType(AutoEnum):
@@ -1446,41 +1432,6 @@ class WorkQueueStatusDetail(PrefectBaseModel):
1446
1432
  )
1447
1433
 
1448
1434
 
1449
- class FlowRunNotificationPolicy(ObjectBaseModel):
1450
- """An ORM representation of a flow run notification."""
1451
-
1452
- is_active: bool = Field(
1453
- default=True, description="Whether the policy is currently active"
1454
- )
1455
- state_names: list[str] = Field(
1456
- default=..., description="The flow run states that trigger notifications"
1457
- )
1458
- tags: list[str] = Field(
1459
- default=...,
1460
- description="The flow run tags that trigger notifications (set [] to disable)",
1461
- )
1462
- block_document_id: UUID = Field(
1463
- default=..., description="The block document ID used for sending notifications"
1464
- )
1465
- message_template: Optional[str] = Field(
1466
- default=None,
1467
- description=(
1468
- "A templatable notification message. Use {braces} to add variables."
1469
- " Valid variables include:"
1470
- f" {listrepr(sorted(FLOW_RUN_NOTIFICATION_TEMPLATE_KWARGS), sep=', ')}"
1471
- ),
1472
- examples=[
1473
- "Flow run {flow_run_name} with id {flow_run_id} entered state"
1474
- " {flow_run_state_name}."
1475
- ],
1476
- )
1477
-
1478
- @field_validator("message_template")
1479
- @classmethod
1480
- def validate_message_template_variables(cls, v: Optional[str]) -> Optional[str]:
1481
- return validate_message_template_variables(v)
1482
-
1483
-
1484
1435
  class Agent(ObjectBaseModel):
1485
1436
  """An ORM representation of an agent"""
1486
1437
 
@@ -1502,8 +1453,6 @@ class Agent(ObjectBaseModel):
1502
1453
  class WorkPoolStorageConfiguration(PrefectBaseModel):
1503
1454
  """A work pool storage configuration"""
1504
1455
 
1505
- model_config: ClassVar[ConfigDict] = ConfigDict(extra="forbid")
1506
-
1507
1456
  bundle_upload_step: Optional[dict[str, Any]] = Field(
1508
1457
  default=None, description="The bundle upload step for the work pool."
1509
1458
  )
@@ -50,6 +50,7 @@ async def _pull_git_repository_with_retries(repo: GitRepository):
50
50
  async def agit_clone(
51
51
  repository: str,
52
52
  branch: Optional[str] = None,
53
+ commit_sha: Optional[str] = None,
53
54
  include_submodules: bool = False,
54
55
  access_token: Optional[str] = None,
55
56
  credentials: Optional["Block"] = None,
@@ -61,6 +62,7 @@ async def agit_clone(
61
62
  Args:
62
63
  repository: the URL of the repository to clone
63
64
  branch: the branch to clone; if not provided, the default branch will be used
65
+ commit_sha: the commit SHA to clone; if not provided, the default branch will be used
64
66
  include_submodules (bool): whether to include git submodules when cloning the repository
65
67
  access_token: an access token to use for cloning the repository; if not provided
66
68
  the repository will be cloned using the default git credentials
@@ -84,6 +86,7 @@ async def agit_clone(
84
86
  url=repository,
85
87
  credentials=_credentials,
86
88
  branch=branch,
89
+ commit_sha=commit_sha,
87
90
  include_submodules=include_submodules,
88
91
  directories=directories,
89
92
  )
@@ -97,6 +100,7 @@ async def agit_clone(
97
100
  def git_clone(
98
101
  repository: str,
99
102
  branch: Optional[str] = None,
103
+ commit_sha: Optional[str] = None,
100
104
  include_submodules: bool = False,
101
105
  access_token: Optional[str] = None,
102
106
  credentials: Optional["Block"] = None,
@@ -108,6 +112,7 @@ def git_clone(
108
112
  Args:
109
113
  repository: the URL of the repository to clone
110
114
  branch: the branch to clone; if not provided, the default branch will be used
115
+ commit_sha: the commit SHA to clone; if not provided, the default branch will be used
111
116
  include_submodules (bool): whether to include git submodules when cloning the repository
112
117
  access_token: an access token to use for cloning the repository; if not provided
113
118
  the repository will be cloned using the default git credentials
@@ -191,6 +196,7 @@ def git_clone(
191
196
  url=repository,
192
197
  credentials=_credentials,
193
198
  branch=branch,
199
+ commit_sha=commit_sha,
194
200
  include_submodules=include_submodules,
195
201
  directories=directories,
196
202
  )
prefect/futures.py CHANGED
@@ -14,7 +14,7 @@ from typing_extensions import NamedTuple, Self, TypeVar
14
14
  from prefect._waiters import FlowRunWaiter
15
15
  from prefect.client.orchestration import get_client
16
16
  from prefect.exceptions import ObjectNotFound
17
- from prefect.logging.loggers import get_logger, get_run_logger
17
+ from prefect.logging.loggers import get_logger
18
18
  from prefect.states import Pending, State
19
19
  from prefect.task_runs import TaskRunWaiter
20
20
  from prefect.utilities.annotations import quote
@@ -224,19 +224,6 @@ class PrefectConcurrentFuture(PrefectWrappedFuture[R, concurrent.futures.Future[
224
224
  )
225
225
  return _result
226
226
 
227
- def __del__(self) -> None:
228
- if self._final_state or self._wrapped_future.done():
229
- return
230
- try:
231
- local_logger = get_run_logger()
232
- except Exception:
233
- local_logger = logger
234
- local_logger.warning(
235
- "A future was garbage collected before it resolved."
236
- " Please call `.wait()` or `.result()` on futures to ensure they resolve."
237
- "\nSee https://docs.prefect.io/latest/develop/task-runners for more details.",
238
- )
239
-
240
227
 
241
228
  class PrefectDistributedFuture(PrefectTaskRunFuture[R]):
242
229
  """
prefect/runner/storage.py CHANGED
@@ -119,6 +119,7 @@ class GitRepository:
119
119
  credentials: Union[GitCredentials, Block, dict[str, Any], None] = None,
120
120
  name: str | None = None,
121
121
  branch: str | None = None,
122
+ commit_sha: str | None = None,
122
123
  include_submodules: bool = False,
123
124
  pull_interval: int | None = 60,
124
125
  directories: list[str] | None = None,
@@ -135,8 +136,15 @@ class GitRepository:
135
136
  "If a username is provided, an access token or password must also be"
136
137
  " provided."
137
138
  )
139
+
140
+ if branch and commit_sha:
141
+ raise ValueError(
142
+ "Cannot provide both a branch and a commit SHA. Please provide only one."
143
+ )
144
+
138
145
  self._url = url
139
146
  self._branch = branch
147
+ self._commit_sha = commit_sha
140
148
  self._credentials = credentials
141
149
  self._include_submodules = include_submodules
142
150
  repo_name = urlparse(url).path.split("/")[-1].replace(".git", "")
@@ -214,7 +222,6 @@ class GitRepository:
214
222
  """
215
223
  Check if existing repo is sparsely checked out
216
224
  """
217
-
218
225
  try:
219
226
  result = await run_process(
220
227
  ["git", "config", "--get", "core.sparseCheckout"], cwd=self.destination
@@ -223,6 +230,34 @@ class GitRepository:
223
230
  except Exception:
224
231
  return False
225
232
 
233
+ async def is_shallow_clone(self) -> bool:
234
+ """
235
+ Check if the repository is a shallow clone
236
+ """
237
+ try:
238
+ result = await run_process(
239
+ ["git", "rev-parse", "--is-shallow-repository"],
240
+ cwd=self.destination,
241
+ )
242
+ return result.stdout.decode().strip().lower() == "true"
243
+ except Exception:
244
+ return False
245
+
246
+ async def is_current_commit(self) -> bool:
247
+ """
248
+ Check if the current commit is the same as the commit SHA
249
+ """
250
+ if not self._commit_sha:
251
+ raise ValueError("No commit SHA provided")
252
+ try:
253
+ result = await run_process(
254
+ ["git", "rev-parse", self._commit_sha],
255
+ cwd=self.destination,
256
+ )
257
+ return result.stdout.decode().strip() == self._commit_sha
258
+ except Exception:
259
+ return False
260
+
226
261
  async def pull_code(self) -> None:
227
262
  """
228
263
  Pulls the contents of the configured repository to the local filesystem.
@@ -262,22 +297,52 @@ class GitRepository:
262
297
  cmd = ["git"]
263
298
  # Add the git configuration, must be given after `git` and before the command
264
299
  cmd += self._git_config
265
- # Add the pull command and parameters
266
- cmd += ["pull", "origin"]
267
- if self._branch:
268
- cmd += [self._branch]
269
- if self._include_submodules:
270
- cmd += ["--recurse-submodules"]
271
- cmd += ["--depth", "1"]
272
- try:
273
- await run_process(cmd, cwd=self.destination)
274
- self._logger.debug("Successfully pulled latest changes")
275
- except subprocess.CalledProcessError as exc:
276
- self._logger.error(
277
- f"Failed to pull latest changes with exit code {exc}"
300
+
301
+ # If the commit is already checked out, skip the pull
302
+ if self._commit_sha and await self.is_current_commit():
303
+ return
304
+
305
+ # If checking out a specific commit, fetch the latest changes and unshallow the repository if necessary
306
+ elif self._commit_sha:
307
+ if await self.is_shallow_clone():
308
+ cmd += ["fetch", "origin", "--unshallow"]
309
+ else:
310
+ cmd += ["fetch", "origin", self._commit_sha]
311
+ try:
312
+ await run_process(cmd, cwd=self.destination)
313
+ self._logger.debug("Successfully fetched latest changes")
314
+ except subprocess.CalledProcessError as exc:
315
+ self._logger.error(
316
+ f"Failed to fetch latest changes with exit code {exc}"
317
+ )
318
+ shutil.rmtree(self.destination)
319
+ await self._clone_repo()
320
+
321
+ await run_process(
322
+ ["git", "checkout", self._commit_sha],
323
+ cwd=self.destination,
324
+ )
325
+ self._logger.debug(
326
+ f"Successfully checked out commit {self._commit_sha}"
278
327
  )
279
- shutil.rmtree(self.destination)
280
- await self._clone_repo()
328
+
329
+ # Otherwise, pull the latest changes from the branch
330
+ else:
331
+ cmd += ["pull", "origin"]
332
+ if self._branch:
333
+ cmd += [self._branch]
334
+ if self._include_submodules:
335
+ cmd += ["--recurse-submodules"]
336
+ cmd += ["--depth", "1"]
337
+ try:
338
+ await run_process(cmd, cwd=self.destination)
339
+ self._logger.debug("Successfully pulled latest changes")
340
+ except subprocess.CalledProcessError as exc:
341
+ self._logger.error(
342
+ f"Failed to pull latest changes with exit code {exc}"
343
+ )
344
+ shutil.rmtree(self.destination)
345
+ await self._clone_repo()
281
346
 
282
347
  else:
283
348
  await self._clone_repo()
@@ -295,8 +360,6 @@ class GitRepository:
295
360
  # Add the clone command and its parameters
296
361
  cmd += ["clone", repository_url]
297
362
 
298
- if self._branch:
299
- cmd += ["--branch", self._branch]
300
363
  if self._include_submodules:
301
364
  cmd += ["--recurse-submodules"]
302
365
 
@@ -304,8 +367,18 @@ class GitRepository:
304
367
  if self._directories:
305
368
  cmd += ["--sparse"]
306
369
 
307
- # Limit git history and set path to clone to
308
- cmd += ["--depth", "1", str(self.destination)]
370
+ if self._commit_sha:
371
+ cmd += ["--filter=blob:none", "--no-checkout"]
372
+
373
+ else:
374
+ if self._branch:
375
+ cmd += ["--branch", self._branch]
376
+
377
+ # Limit git history
378
+ cmd += ["--depth", "1"]
379
+
380
+ # Set path to clone to
381
+ cmd += [str(self.destination)]
309
382
 
310
383
  try:
311
384
  await run_process(cmd)
@@ -317,6 +390,19 @@ class GitRepository:
317
390
  f" {exc.returncode}."
318
391
  ) from exc_chain
319
392
 
393
+ if self._commit_sha:
394
+ # Fetch the commit
395
+ await run_process(
396
+ ["git", "fetch", "origin", self._commit_sha],
397
+ cwd=self.destination,
398
+ )
399
+ # Checkout the specific commit
400
+ await run_process(
401
+ ["git", "checkout", self._commit_sha],
402
+ cwd=self.destination,
403
+ )
404
+ self._logger.debug(f"Successfully checked out commit {self._commit_sha}")
405
+
320
406
  # Once repository is cloned and the repo is in sparse-checkout mode then grow the working directory
321
407
  if self._directories:
322
408
  self._logger.debug("Will add %s", self._directories)
@@ -351,6 +437,10 @@ class GitRepository:
351
437
  pull_step["prefect.deployments.steps.git_clone"]["include_submodules"] = (
352
438
  self._include_submodules
353
439
  )
440
+ if self._commit_sha:
441
+ pull_step["prefect.deployments.steps.git_clone"]["commit_sha"] = (
442
+ self._commit_sha
443
+ )
354
444
  if isinstance(self._credentials, Block):
355
445
  pull_step["prefect.deployments.steps.git_clone"]["credentials"] = (
356
446
  f"{{{{ {self._credentials.get_block_placeholder()} }}}}"
@@ -13,7 +13,6 @@ from . import (
13
13
  dependencies,
14
14
  deployments,
15
15
  events,
16
- flow_run_notification_policies,
17
16
  flow_run_states,
18
17
  flow_runs,
19
18
  flows,
@@ -89,7 +89,6 @@ API_ROUTERS = (
89
89
  api.task_runs.router,
90
90
  api.flow_run_states.router,
91
91
  api.task_run_states.router,
92
- api.flow_run_notification_policies.router,
93
92
  api.deployments.router,
94
93
  api.saved_searches.router,
95
94
  api.logs.router,
@@ -116,26 +116,6 @@ class ServerServicesEventLoggerSettings(ServicesBaseSetting):
116
116
  )
117
117
 
118
118
 
119
- class ServerServicesFlowRunNotificationsSettings(ServicesBaseSetting):
120
- """
121
- Settings for controlling the flow run notifications service
122
- """
123
-
124
- model_config: ClassVar[SettingsConfigDict] = build_settings_config(
125
- ("server", "services", "flow_run_notifications")
126
- )
127
-
128
- enabled: bool = Field(
129
- default=True,
130
- description="Whether or not to start the flow run notifications service in the server application.",
131
- validation_alias=AliasChoices(
132
- AliasPath("enabled"),
133
- "prefect_server_services_flow_run_notifications_enabled",
134
- "prefect_api_services_flow_run_notifications_enabled",
135
- ),
136
- )
137
-
138
-
139
119
  class ServerServicesForemanSettings(ServicesBaseSetting):
140
120
  """
141
121
  Settings for controlling the foreman service
@@ -490,10 +470,6 @@ class ServerServicesSettings(PrefectBaseSettings):
490
470
  default_factory=ServerServicesEventLoggerSettings,
491
471
  description="Settings for controlling the event logger service",
492
472
  )
493
- flow_run_notifications: ServerServicesFlowRunNotificationsSettings = Field(
494
- default_factory=ServerServicesFlowRunNotificationsSettings,
495
- description="Settings for controlling the flow run notifications service",
496
- )
497
473
  foreman: ServerServicesForemanSettings = Field(
498
474
  default_factory=ServerServicesForemanSettings,
499
475
  description="Settings for controlling the foreman service",
prefect/task_engine.py CHANGED
@@ -384,22 +384,6 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
384
384
  self.logger.info(f"Hook {hook_name!r} finished running successfully")
385
385
 
386
386
  def begin_run(self) -> None:
387
- try:
388
- self._resolve_parameters()
389
- self._set_custom_task_run_name()
390
- self._wait_for_dependencies()
391
- except UpstreamTaskError as upstream_exc:
392
- state = self.set_state(
393
- Pending(
394
- name="NotReady",
395
- message=str(upstream_exc),
396
- ),
397
- # if orchestrating a run already in a pending state, force orchestration to
398
- # update the state name
399
- force=self.state.is_pending(),
400
- )
401
- return
402
-
403
387
  new_state = Running()
404
388
 
405
389
  assert self.task_run is not None, "Task run is not set"
@@ -765,6 +749,24 @@ class SyncTaskRunEngine(BaseTaskRunEngine[P, R]):
765
749
  if self._telemetry.span
766
750
  else nullcontext()
767
751
  ):
752
+ try:
753
+ self._resolve_parameters()
754
+ self._set_custom_task_run_name()
755
+ self._wait_for_dependencies()
756
+ except UpstreamTaskError as upstream_exc:
757
+ self.set_state(
758
+ Pending(
759
+ name="NotReady",
760
+ message=str(upstream_exc),
761
+ ),
762
+ # if orchestrating a run already in a pending state, force orchestration to
763
+ # update the state name
764
+ force=self.state.is_pending(),
765
+ )
766
+ yield
767
+ self.call_hooks()
768
+ return
769
+
768
770
  # Acquire a concurrency slot for each tag, but only if a limit
769
771
  # matching the tag already exists.
770
772
  with concurrency(list(self.task_run.tags), self.task_run.id):
@@ -921,7 +923,6 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
921
923
  try:
922
924
  self._resolve_parameters()
923
925
  self._set_custom_task_run_name()
924
- self._wait_for_dependencies()
925
926
  except UpstreamTaskError as upstream_exc:
926
927
  state = await self.set_state(
927
928
  Pending(
@@ -1298,6 +1299,23 @@ class AsyncTaskRunEngine(BaseTaskRunEngine[P, R]):
1298
1299
  if self._telemetry.span
1299
1300
  else nullcontext()
1300
1301
  ):
1302
+ try:
1303
+ self._resolve_parameters()
1304
+ self._set_custom_task_run_name()
1305
+ self._wait_for_dependencies()
1306
+ except UpstreamTaskError as upstream_exc:
1307
+ await self.set_state(
1308
+ Pending(
1309
+ name="NotReady",
1310
+ message=str(upstream_exc),
1311
+ ),
1312
+ # if orchestrating a run already in a pending state, force orchestration to
1313
+ # update the state name
1314
+ force=self.state.is_pending(),
1315
+ )
1316
+ yield
1317
+ await self.call_hooks()
1318
+ return
1301
1319
  # Acquire a concurrency slot for each tag, but only if a limit
1302
1320
  # matching the tag already exists.
1303
1321
  async with aconcurrency(list(self.task_run.tags), self.task_run.id):
prefect/task_runners.py CHANGED
@@ -281,6 +281,12 @@ class ThreadPoolTaskRunner(TaskRunner[PrefectConcurrentFuture[R]]):
281
281
  if not self._started or self._executor is None:
282
282
  raise RuntimeError("Task runner is not started")
283
283
 
284
+ if wait_for and task.tags and (self._max_workers <= len(task.tags)):
285
+ self.logger.warning(
286
+ f"Task {task.name} has {len(task.tags)} tags but only {self._max_workers} workers available"
287
+ "This may lead to dead-locks. Consider increasing the value of `PREFECT_TASK_RUNNER_THREAD_POOL_MAX_WORKERS` or `max_workers`."
288
+ )
289
+
284
290
  from prefect.context import FlowRunContext
285
291
  from prefect.task_engine import run_task_async, run_task_sync
286
292
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: prefect-client
3
- Version: 3.3.8.dev2
3
+ Version: 3.3.8.dev4
4
4
  Summary: Workflow orchestration and management.
5
5
  Project-URL: Changelog, https://github.com/PrefectHQ/prefect/releases
6
6
  Project-URL: Documentation, https://docs.prefect.io
@@ -1,7 +1,7 @@
1
1
  prefect/.prefectignore,sha256=awSprvKT0vI8a64mEOLrMxhxqcO-b0ERQeYpA2rNKVQ,390
2
2
  prefect/__init__.py,sha256=iCdcC5ZmeewikCdnPEP6YBAjPNV5dvfxpYCTpw30Hkw,3685
3
3
  prefect/__main__.py,sha256=WFjw3kaYJY6pOTA7WDOgqjsz8zUEUZHCcj3P5wyVa-g,66
4
- prefect/_build_info.py,sha256=xIf4RLsQNhfIBLCfQE-Vr-7wv5-VXT7GdtCt6aYYJWg,185
4
+ prefect/_build_info.py,sha256=fPIQpc-QDiKnHO_7x3zhljsGJda7vTLJ-4VzvCenG_U,185
5
5
  prefect/_result_records.py,sha256=S6QmsODkehGVSzbMm6ig022PYbI6gNKz671p_8kBYx4,7789
6
6
  prefect/_versioning.py,sha256=nRawjhBY2XpAzS5dHm4ajj8GlSNCr_YOjg2Zbez69j0,14069
7
7
  prefect/_waiters.py,sha256=Ia2ITaXdHzevtyWIgJoOg95lrEXQqNEOquHvw3T33UQ,9026
@@ -16,7 +16,7 @@ prefect/filesystems.py,sha256=v5YqGB4uXf9Ew2VuB9VCSkawvYMMVvEtZf7w1VmAmr8,18036
16
16
  prefect/flow_engine.py,sha256=hZpTYEtwTPMtwVoTCrfD93igN7rlKeG_0kyCvdU4aYE,58876
17
17
  prefect/flow_runs.py,sha256=d3jfmrIPP3C19IJREvpkuN6fxksX3Lzo-LlHOB-_E2I,17419
18
18
  prefect/flows.py,sha256=UCBwsb99wtPTGPu2PneKCfAMlMBA2GhXJb5rzMBxw1s,118041
19
- prefect/futures.py,sha256=F4eplqRcqw5-aMNKu6-lOFOWdDNr0RGrPso4C4G02bU,24248
19
+ prefect/futures.py,sha256=5wVHLtniwG2au0zuxM-ucqo08x0B5l6e8Z1Swbe8R9s,23720
20
20
  prefect/main.py,sha256=8V-qLB4GjEVCkGRgGXeaIk-JIXY8Z9FozcNluj4Sm9E,2589
21
21
  prefect/plugins.py,sha256=FPRLR2mWVBMuOnlzeiTD9krlHONZH2rtYLD753JQDNQ,2516
22
22
  prefect/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -24,8 +24,8 @@ prefect/results.py,sha256=3zuO8a4EGtti5AP4zLSnoES1YMKP1CugergxJdZa0-8,37140
24
24
  prefect/schedules.py,sha256=dhq4OhImRvcmtxF7UH1m8RbwYdHT5RQsp_FrxVXfODE,7289
25
25
  prefect/serializers.py,sha256=QI0oEal_BO4HQaWSjr6ReSwT55Hn4sbSOXxGgQI1-y0,9249
26
26
  prefect/states.py,sha256=rh7l1bnIYpTXdlXt5nnpz66y9KLjBWAJrN9Eo5RwgQs,26023
27
- prefect/task_engine.py,sha256=wLOj7dPuIBBDZkvsqxWv7wLpUOhGnRb3N5s0ia2y5So,61576
28
- prefect/task_runners.py,sha256=Ce_ngocfq_X-NA5zhPj13IdVmzZ5h6gXlmfxYWs2AXA,15828
27
+ prefect/task_engine.py,sha256=j0rr8IyBinJmKPD-486RYWKZakhifkEE9ppPCJ9Es-U,62463
28
+ prefect/task_runners.py,sha256=vzJ1kiW1z90Fkkg21QNhPwjfLoDy6rVsUAToXqb6FUE,16206
29
29
  prefect/task_runs.py,sha256=7LIzfo3fondCyEUpU05sYFN5IfpZigBDXrhG5yc-8t0,9039
30
30
  prefect/task_worker.py,sha256=gMj_rl4EjTrnJ5YSOXinC6y-7KSK7fRQt_UYbZbrrV8,17879
31
31
  prefect/tasks.py,sha256=EpMw5O1B9pAFVraC0KzytMOKi8iy7ZYnKWRs7WtvogU,74742
@@ -66,12 +66,12 @@ prefect/_internal/schemas/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
66
66
  prefect/_internal/schemas/bases.py,sha256=JqcZazL5Cp2hZ8Hssu8R2SVXRxHfbdRbTqmvwDYSzyk,4291
67
67
  prefect/_internal/schemas/fields.py,sha256=m4LrFNz8rA9uBhMk9VyQT6FIXmV_EVAW92hdXeSvHbY,837
68
68
  prefect/_internal/schemas/serializers.py,sha256=G_RGHfObjisUiRvd29p-zc6W4bwt5rE1OdR6TXNrRhQ,825
69
- prefect/_internal/schemas/validators.py,sha256=ty9hpmfiNEWpENgeBGrgs94j192L8SpLJ0bhFHeXV_8,19733
69
+ prefect/_internal/schemas/validators.py,sha256=-iHt659pMvu6DgPqHTfcRtDUF9tO4yt7HFS391HhRuQ,19175
70
70
  prefect/_vendor/croniter/__init__.py,sha256=NUFzdbyPcTQhIOFtzmFM0nbClAvBbKh2mlnTBa6NfHU,523
71
71
  prefect/_vendor/croniter/croniter.py,sha256=eJ2HzStNAYV-vNiLOgDXl4sYWWHOsSA0dgwbkQoguhY,53009
72
72
  prefect/blocks/__init__.py,sha256=D0hB72qMfgqnBB2EMZRxUxlX9yLfkab5zDChOwJZmkY,220
73
73
  prefect/blocks/abstract.py,sha256=mpOAWopSR_RrzdxeurBTXVSKisP8ne-k8LYos-tp7go,17021
74
- prefect/blocks/core.py,sha256=Z-vC0wP-c1mQUDc-0qgBloLba5OKfJ3hJtDinJyZOH0,62045
74
+ prefect/blocks/core.py,sha256=ZUMmbBiw2O9_k_wOzR1itXJp8rj-E10tr4RPEoSfA4s,62028
75
75
  prefect/blocks/fields.py,sha256=1m507VVmkpOnMF_7N-qboRjtw4_ceIuDneX3jZ3Jm54,63
76
76
  prefect/blocks/notifications.py,sha256=UpNNxc4Bwx0nSlDj-vZQOv2XyUCUB2PaO4uBPO1Y6XM,34162
77
77
  prefect/blocks/redis.py,sha256=lt_f1SIcS5OVvthCY6KRWiy5DyUZNRlHqkKhKF25P8c,5770
@@ -84,9 +84,9 @@ prefect/client/collections.py,sha256=t9XkVU_onQMZ871L21F1oZnAiPSQeeVfd_MuDEBS3iM
84
84
  prefect/client/constants.py,sha256=Z_GG8KF70vbbXxpJuqW5pLnwzujTVeHbcYYRikNmGH0,29
85
85
  prefect/client/subscriptions.py,sha256=b2gjoWjrTjshnv_s6zlPN3t0JIe2EKAdMqEzj3-kc6w,3879
86
86
  prefect/client/utilities.py,sha256=UEJD6nwYg2mD8-GSmru-E2ofXaBlmSFZ2-8T_5rIK6c,3472
87
- prefect/client/orchestration/__init__.py,sha256=1GHRA9-JWPBX6oSVNytQ1qL6epFeslRT2oBgZdFDJ68,60807
87
+ prefect/client/orchestration/__init__.py,sha256=O6tItUwU1NBycVPf0PoYVT8bF8gfrVoe9eaSmTQTNFU,55485
88
88
  prefect/client/orchestration/base.py,sha256=HM6ryHBZSzuHoCFQM9u5qR5k1dN9Bbr_ah6z1UPNbZQ,1542
89
- prefect/client/orchestration/routes.py,sha256=FHG9xyop_eXp6wtg0Fp0G14J6lO8UVsdnhGY5qvnJ9k,4396
89
+ prefect/client/orchestration/routes.py,sha256=_-HC-EmgMhsYdmGwZTxIXlINaVzYuX7RZAvzjHbVp-4,4266
90
90
  prefect/client/orchestration/_artifacts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
91
91
  prefect/client/orchestration/_artifacts/client.py,sha256=0GEM4rJWeedKR2xVgWQcX6DpLyn0zKFJF9nfRCQ4tpM,8855
92
92
  prefect/client/orchestration/_automations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -112,9 +112,9 @@ prefect/client/orchestration/_variables/client.py,sha256=wKBbZBLGgs5feDCil-xxKt3
112
112
  prefect/client/orchestration/_work_pools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
113
113
  prefect/client/orchestration/_work_pools/client.py,sha256=s1DfUQQBgB2sLiVVPhLNTlkueUDE6uFsh4mAzcSA1OE,19881
114
114
  prefect/client/schemas/__init__.py,sha256=InZcDzdeWA2oaV0TlyvoMcyLcbi_aaqU1U9D6Gx-eoU,2747
115
- prefect/client/schemas/actions.py,sha256=s-Ycs5DfiguN_jcc2Yq541TNRgopJjX5r5GujJLWVLg,34939
116
- prefect/client/schemas/filters.py,sha256=zaiDkalrIpKjd38V4aP1GHlqD24KTPCZiKtPyX69ZWE,36607
117
- prefect/client/schemas/objects.py,sha256=nyaodVdbZIl-p5e7BvF5olPoiHZkymXkn7nFkFnXqXA,59402
115
+ prefect/client/schemas/actions.py,sha256=EigGRTOwa_aWBMfqiTvNaUO8e78M1kIxorEzp1bigcI,33148
116
+ prefect/client/schemas/filters.py,sha256=qa--NNZduuSOcL1xw-YMd4FVIKMrDnBwPPY4m5Di0GA,35963
117
+ prefect/client/schemas/objects.py,sha256=uhmwZDw1kZQ8pZNjpoFtyMJIHFc_02s3HI0elgbGEOE,57679
118
118
  prefect/client/schemas/responses.py,sha256=Zdcx7jlIaluEa2uYIOE5mK1HsJvWPErRAcaWM20oY_I,17336
119
119
  prefect/client/schemas/schedules.py,sha256=sxLFk0SmFY7X1Y9R9HyGDqOS3U5NINBWTciUU7vTTic,14836
120
120
  prefect/client/schemas/sorting.py,sha256=L-2Mx-igZPtsUoRUguTcG3nIEstMEMPD97NwPM2Ox5s,2579
@@ -142,7 +142,7 @@ prefect/deployments/runner.py,sha256=_VqbkXvPVvdyFVkRsr5emi26cJmu5-2uhtVUoE0EkNA
142
142
  prefect/deployments/schedules.py,sha256=2eL1-w8qXtwKVkgfUK7cuamwpKK3X6tN1QYTDa_gWxU,2190
143
143
  prefect/deployments/steps/__init__.py,sha256=Dlz9VqMRyG1Gal8dj8vfGpPr0LyQhZdvcciozkK8WoY,206
144
144
  prefect/deployments/steps/core.py,sha256=ulSgBFSx1lhBt1fP-UxebrernkumBDlympR6IPffV1g,6900
145
- prefect/deployments/steps/pull.py,sha256=MDN8nHklgU6MXNMsMRDLDVbIqod87ccPJdt-21dshvU,9767
145
+ prefect/deployments/steps/pull.py,sha256=4ZzJ26xYVsCVF0tQfXHhFXHDAdc5Rk8TP_Qw0aTfT_U,10093
146
146
  prefect/deployments/steps/utility.py,sha256=Ap_p44Rwz9Lxd6pt8hDW8phF3gwI3YjbsSpWHALDyoM,8157
147
147
  prefect/docker/__init__.py,sha256=z6wdc6UFfiBG2jb9Jk64uCWVM04JKVWeVyDWwuuon8M,527
148
148
  prefect/docker/docker_image.py,sha256=bR_pEq5-FDxlwTj8CP_7nwZ_MiGK6KxIi8v7DRjy1Kg,3138
@@ -186,14 +186,14 @@ prefect/logging/logging.yml,sha256=tT7gTyC4NmngFSqFkCdHaw7R0GPNPDDsTCGZQByiJAQ,3
186
186
  prefect/runner/__init__.py,sha256=pQBd9wVrUVUDUFJlgiweKSnbahoBZwqnd2O2jkhrULY,158
187
187
  prefect/runner/runner.py,sha256=jv87XyaJ89uK0VzKpMzL3HfXgKZky8JlRs-gW04no5Y,65117
188
188
  prefect/runner/server.py,sha256=YRYFNoYddA9XfiTIYtudxrnD1vCX-PaOLhvyGUOb9AQ,11966
189
- prefect/runner/storage.py,sha256=L7aSjie5L6qbXYCDqYDX3ouQ_NsNMlmfjPeaWOC-ncs,28043
189
+ prefect/runner/storage.py,sha256=n-65YoEf7KNVInnmMPeP5TVFJOa2zOS8w9en9MHi6uo,31328
190
190
  prefect/runner/submit.py,sha256=qOEj-NChQ6RYFV35hHEVMTklrNmKwaGs2mR78ku9H0o,9474
191
191
  prefect/runner/utils.py,sha256=19DbhyiV6nvSpTXmnWlt7qPNt1jrz1jscznYrRVGurw,3413
192
192
  prefect/runtime/__init__.py,sha256=JswiTlYRup2zXOYu8AqJ7czKtgcw9Kxo0tTbS6aWCqY,407
193
193
  prefect/runtime/deployment.py,sha256=0A_cUVpYiFk3ciJw2ixy95dk9xBJcjisyF69pakSCcQ,5091
194
194
  prefect/runtime/flow_run.py,sha256=V7GkeGff4tiFpDUz1UqN20FoMCxFDBu6eZFrfPlcZ28,10722
195
195
  prefect/runtime/task_run.py,sha256=zYBSs7QrAu7c2IjKomRzPXKyIXrjqclMTMrco-dwyOw,4212
196
- prefect/server/api/__init__.py,sha256=W6s6QR91ogg7pssnFdV0bptpXtP1gbjqjnhySK1hFJM,616
196
+ prefect/server/api/__init__.py,sha256=SpRTXHC6ApqR4_Y3wNHM7TvvH9FZ8N3tH-RZIgmubgM,580
197
197
  prefect/server/api/admin.py,sha256=nINYSrux7XPAV4MMDQUts3X2dddrc3mJtd3iPl5N-jI,2644
198
198
  prefect/server/api/artifacts.py,sha256=aQ80xTf7Nu0-LMQ_UtapyZFDit7_em3s1x4k5ux1l7M,7298
199
199
  prefect/server/api/automations.py,sha256=v2hreB6KYOqsITPyVqpNk7PO6L3OKPflCYD0CD8Jdvw,8220
@@ -209,7 +209,6 @@ prefect/server/api/csrf_token.py,sha256=BwysSjQAhre7O0OY_LF3ZcIiO53FdMQroNT11Q6O
209
209
  prefect/server/api/dependencies.py,sha256=VujfcIGn41TGJxUunFHVabY5hE-6nY6uSHyhNFj8PdI,6634
210
210
  prefect/server/api/deployments.py,sha256=ppYA3b2csnw32-SbOXz5Dm_IsnmPKczNiSbqCzusFKI,39332
211
211
  prefect/server/api/events.py,sha256=3-Qdt6ORxFv3nLoogQqvd72zEulJSoAmcqZto2OULuk,9907
212
- prefect/server/api/flow_run_notification_policies.py,sha256=F8xNm6bgZTC3nFe9xCUJS4NlU9tLXZ8fShtJqmhT2m4,4828
213
212
  prefect/server/api/flow_run_states.py,sha256=lIdxVE9CqLgtDCuH9bTaKkzHNL81FPrr11liPzvONrw,1661
214
213
  prefect/server/api/flow_runs.py,sha256=Lmb165fLbN4DioxjxgDYaAJ5Qxj771iRYaqn-hYq9KM,33744
215
214
  prefect/server/api/flows.py,sha256=Bz0ISh-9oY0W1X3mqA631_8678pQ6tuRGMpSgWAfxOc,7018
@@ -218,7 +217,7 @@ prefect/server/api/middleware.py,sha256=WkyuyeJIfo9Q0GAIVU5gO6yIGNVwoHwuBah5AB5o
218
217
  prefect/server/api/root.py,sha256=CeumFYIM_BDvPicJH9ry5PO_02PZTLeMqbLMGGTh90o,942
219
218
  prefect/server/api/run_history.py,sha256=EW-GTPxZAQ5zXiAqHzmS-iAN_Bn6ZSgVQksDT-ZTsyc,5995
220
219
  prefect/server/api/saved_searches.py,sha256=UjoqLLe245QVIs6q5Vk4vdODCOoYzciEEjhi7B8sYCE,3233
221
- prefect/server/api/server.py,sha256=CIpLoiRUCuW345trzwr_Z8v53Kw_2RBqe3ppGvkjSx0,32940
220
+ prefect/server/api/server.py,sha256=eEZkZJgXcx6N_qpz9PS7wNVYEz-SZgEdVzG8i9ovjSI,32893
222
221
  prefect/server/api/task_run_states.py,sha256=e63OPpxPudv_CIB5oKr8Z8rfQ-Osjm9Zq0iHe8obnMo,1647
223
222
  prefect/server/api/task_runs.py,sha256=86lXKGUJJSElhkVcxX-kbjctrNe98nUe3U0McDCfTMw,13904
224
223
  prefect/server/api/task_workers.py,sha256=cFP9M8tsApDL_JpySn-x6fOYy9RnOeOgKiqOl_UVVQM,1042
@@ -266,7 +265,7 @@ prefect/settings/models/server/ephemeral.py,sha256=rh8Py5Nxh-gq9KgfB7CDnIgT_nuOu
266
265
  prefect/settings/models/server/events.py,sha256=9rdlbLz9SIg_easm1UcFTfX1seS935Xtv5d9y3r39Eo,5578
267
266
  prefect/settings/models/server/flow_run_graph.py,sha256=PuAZqqdu6fzvrbUgXZzyntUH_Ii_bP7qezgcgvW7ULk,1146
268
267
  prefect/settings/models/server/root.py,sha256=Dk_Zx4eGUy1h2cAetDKphnd6TWhDrK6DHOLJxdP7e1Y,5215
269
- prefect/settings/models/server/services.py,sha256=FlU12Mw_J7KG_xsX-4Xp_t1WfTqDUDeniEGseV1WaEI,18866
268
+ prefect/settings/models/server/services.py,sha256=_327K952hukUj4JFnyufly1Ahxbf5wgWl1icMwszp0k,17954
270
269
  prefect/settings/models/server/tasks.py,sha256=_CaOUfh3WDXvUhmHXmR-MkTRaQqocZck4efmX74iOg8,2976
271
270
  prefect/settings/models/server/ui.py,sha256=hShsi4rPBtdJA2WnT1Er0tWqu-e5wUum8NkNgucShkk,1867
272
271
  prefect/telemetry/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
@@ -319,7 +318,7 @@ prefect/workers/cloud.py,sha256=dPvG1jDGD5HSH7aM2utwtk6RaJ9qg13XjkA0lAIgQmY,287
319
318
  prefect/workers/process.py,sha256=Yi5D0U5AQ51wHT86GdwtImXSefe0gJf3LGq4r4z9zwM,11090
320
319
  prefect/workers/server.py,sha256=2pmVeJZiVbEK02SO6BEZaBIvHMsn6G8LzjW8BXyiTtk,1952
321
320
  prefect/workers/utilities.py,sha256=VfPfAlGtTuDj0-Kb8WlMgAuOfgXCdrGAnKMapPSBrwc,2483
322
- prefect_client-3.3.8.dev2.dist-info/METADATA,sha256=JE77CAqyGDR4Dj3Uov__9h-8ItXQIfNE4MOMuoqxzlY,7471
323
- prefect_client-3.3.8.dev2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
324
- prefect_client-3.3.8.dev2.dist-info/licenses/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
325
- prefect_client-3.3.8.dev2.dist-info/RECORD,,
321
+ prefect_client-3.3.8.dev4.dist-info/METADATA,sha256=RnRvdjpOPN4o--OI4fqJHfRiPVRabPGWr4leEn2kHUw,7471
322
+ prefect_client-3.3.8.dev4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
323
+ prefect_client-3.3.8.dev4.dist-info/licenses/LICENSE,sha256=MCxsn8osAkzfxKC4CC_dLcUkU8DZLkyihZ8mGs3Ah3Q,11357
324
+ prefect_client-3.3.8.dev4.dist-info/RECORD,,
@@ -1,122 +0,0 @@
1
- """
2
- Routes for interacting with flow run notification policy objects.
3
- """
4
-
5
- from typing import List
6
- from uuid import UUID
7
-
8
- from fastapi import Body, Depends, HTTPException, Path, status
9
-
10
- import prefect.server.api.dependencies as dependencies
11
- import prefect.server.models as models
12
- import prefect.server.schemas as schemas
13
- from prefect.server.database import PrefectDBInterface, provide_database_interface
14
- from prefect.server.utilities.server import PrefectRouter
15
-
16
- router: PrefectRouter = PrefectRouter(
17
- prefix="/flow_run_notification_policies", tags=["Flow Run Notification Policies"]
18
- )
19
-
20
-
21
- @router.post("/", status_code=status.HTTP_201_CREATED)
22
- async def create_flow_run_notification_policy(
23
- flow_run_notification_policy: schemas.actions.FlowRunNotificationPolicyCreate,
24
- db: PrefectDBInterface = Depends(provide_database_interface),
25
- ) -> schemas.core.FlowRunNotificationPolicy:
26
- """
27
- Creates a new flow run notification policy.
28
-
29
- For more information, see https://docs.prefect.io/v3/automate/events/automations-triggers#sending-notifications-with-automations.
30
- """
31
- async with db.session_context(begin_transaction=True) as session:
32
- return await models.flow_run_notification_policies.create_flow_run_notification_policy(
33
- session=session, flow_run_notification_policy=flow_run_notification_policy
34
- )
35
-
36
-
37
- @router.patch("/{id}", status_code=status.HTTP_204_NO_CONTENT)
38
- async def update_flow_run_notification_policy(
39
- flow_run_notification_policy: schemas.actions.FlowRunNotificationPolicyUpdate,
40
- flow_run_notification_policy_id: UUID = Path(
41
- ..., description="The flow run notification policy id", alias="id"
42
- ),
43
- db: PrefectDBInterface = Depends(provide_database_interface),
44
- ) -> None:
45
- """
46
- Updates an existing flow run notification policy.
47
- """
48
- async with db.session_context(begin_transaction=True) as session:
49
- result = await models.flow_run_notification_policies.update_flow_run_notification_policy(
50
- session=session,
51
- flow_run_notification_policy_id=flow_run_notification_policy_id,
52
- flow_run_notification_policy=flow_run_notification_policy,
53
- )
54
- if not result:
55
- raise HTTPException(
56
- status_code=status.HTTP_404_NOT_FOUND,
57
- detail=f"Flow run notification policy {id} not found",
58
- )
59
-
60
-
61
- @router.get("/{id}")
62
- async def read_flow_run_notification_policy(
63
- flow_run_notification_policy_id: UUID = Path(
64
- ..., description="The flow run notification policy id", alias="id"
65
- ),
66
- db: PrefectDBInterface = Depends(provide_database_interface),
67
- ) -> schemas.core.FlowRunNotificationPolicy:
68
- """
69
- Get a flow run notification policy by id.
70
- """
71
- async with db.session_context() as session:
72
- flow_run_notification_policy = await models.flow_run_notification_policies.read_flow_run_notification_policy(
73
- session=session,
74
- flow_run_notification_policy_id=flow_run_notification_policy_id,
75
- )
76
- if not flow_run_notification_policy:
77
- raise HTTPException(
78
- status_code=status.HTTP_404_NOT_FOUND,
79
- detail="flow run notification policy not found",
80
- )
81
- return flow_run_notification_policy
82
-
83
-
84
- @router.post("/filter")
85
- async def read_flow_run_notification_policies(
86
- limit: int = dependencies.LimitBody(),
87
- flow_run_notification_policy_filter: schemas.filters.FlowRunNotificationPolicyFilter = None,
88
- offset: int = Body(0, ge=0),
89
- db: PrefectDBInterface = Depends(provide_database_interface),
90
- ) -> List[schemas.core.FlowRunNotificationPolicy]:
91
- """
92
- Query for flow run notification policies.
93
- """
94
- async with db.session_context() as session:
95
- return await models.flow_run_notification_policies.read_flow_run_notification_policies(
96
- session=session,
97
- flow_run_notification_policy_filter=flow_run_notification_policy_filter,
98
- offset=offset,
99
- limit=limit,
100
- )
101
-
102
-
103
- @router.delete("/{id}", status_code=status.HTTP_204_NO_CONTENT)
104
- async def delete_flow_run_notification_policy(
105
- flow_run_notification_policy_id: UUID = Path(
106
- ..., description="The flow run notification policy id", alias="id"
107
- ),
108
- db: PrefectDBInterface = Depends(provide_database_interface),
109
- ) -> None:
110
- """
111
- Delete a flow run notification policy by id.
112
- """
113
- async with db.session_context(begin_transaction=True) as session:
114
- result = await models.flow_run_notification_policies.delete_flow_run_notification_policy(
115
- session=session,
116
- flow_run_notification_policy_id=flow_run_notification_policy_id,
117
- )
118
- if not result:
119
- raise HTTPException(
120
- status_code=status.HTTP_404_NOT_FOUND,
121
- detail="flow run notification policy not found",
122
- )