prefect-client 3.1.11__py3-none-any.whl → 3.1.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. prefect/_experimental/sla/__init__.py +0 -0
  2. prefect/_experimental/sla/client.py +66 -0
  3. prefect/_experimental/sla/objects.py +53 -0
  4. prefect/_version.py +3 -3
  5. prefect/automations.py +236 -30
  6. prefect/blocks/__init__.py +3 -3
  7. prefect/blocks/abstract.py +53 -30
  8. prefect/blocks/core.py +181 -82
  9. prefect/blocks/notifications.py +133 -73
  10. prefect/blocks/redis.py +13 -9
  11. prefect/blocks/system.py +24 -11
  12. prefect/blocks/webhook.py +7 -5
  13. prefect/cache_policies.py +3 -2
  14. prefect/client/orchestration/__init__.py +103 -2006
  15. prefect/client/orchestration/_automations/__init__.py +0 -0
  16. prefect/client/orchestration/_automations/client.py +329 -0
  17. prefect/client/orchestration/_blocks_documents/__init__.py +0 -0
  18. prefect/client/orchestration/_blocks_documents/client.py +334 -0
  19. prefect/client/orchestration/_blocks_schemas/__init__.py +0 -0
  20. prefect/client/orchestration/_blocks_schemas/client.py +200 -0
  21. prefect/client/orchestration/_blocks_types/__init__.py +0 -0
  22. prefect/client/orchestration/_blocks_types/client.py +380 -0
  23. prefect/client/orchestration/_deployments/__init__.py +0 -0
  24. prefect/client/orchestration/_deployments/client.py +1128 -0
  25. prefect/client/orchestration/_flow_runs/__init__.py +0 -0
  26. prefect/client/orchestration/_flow_runs/client.py +903 -0
  27. prefect/client/orchestration/_flows/__init__.py +0 -0
  28. prefect/client/orchestration/_flows/client.py +343 -0
  29. prefect/client/orchestration/_logs/client.py +16 -14
  30. prefect/client/schemas/__init__.py +68 -28
  31. prefect/client/schemas/objects.py +5 -5
  32. prefect/context.py +15 -1
  33. prefect/deployments/base.py +6 -0
  34. prefect/deployments/runner.py +42 -1
  35. prefect/engine.py +17 -4
  36. prefect/filesystems.py +6 -2
  37. prefect/flow_engine.py +47 -38
  38. prefect/flows.py +10 -1
  39. prefect/logging/logging.yml +1 -1
  40. prefect/runner/runner.py +4 -2
  41. prefect/settings/models/cloud.py +5 -0
  42. prefect/settings/models/experiments.py +0 -5
  43. prefect/states.py +57 -38
  44. prefect/task_runners.py +56 -55
  45. prefect/task_worker.py +2 -2
  46. prefect/tasks.py +6 -4
  47. prefect/telemetry/bootstrap.py +10 -9
  48. prefect/telemetry/services.py +4 -0
  49. prefect/utilities/templating.py +25 -1
  50. prefect/workers/base.py +6 -3
  51. prefect/workers/process.py +1 -1
  52. {prefect_client-3.1.11.dist-info → prefect_client-3.1.12.dist-info}/METADATA +2 -2
  53. {prefect_client-3.1.11.dist-info → prefect_client-3.1.12.dist-info}/RECORD +56 -39
  54. {prefect_client-3.1.11.dist-info → prefect_client-3.1.12.dist-info}/LICENSE +0 -0
  55. {prefect_client-3.1.11.dist-info → prefect_client-3.1.12.dist-info}/WHEEL +0 -0
  56. {prefect_client-3.1.11.dist-info → prefect_client-3.1.12.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,200 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from httpx import HTTPStatusError
6
+
7
+ from prefect.client.orchestration.base import BaseAsyncClient, BaseClient
8
+ from prefect.exceptions import ObjectAlreadyExists, ObjectNotFound
9
+
10
+ if TYPE_CHECKING:
11
+ from uuid import UUID
12
+
13
+ from prefect.client.schemas.actions import BlockSchemaCreate
14
+ from prefect.client.schemas.objects import BlockSchema
15
+
16
+
17
+ class BlocksSchemaClient(BaseClient):
18
+ def create_block_schema(self, block_schema: "BlockSchemaCreate") -> "BlockSchema":
19
+ """
20
+ Create a block schema in the Prefect API.
21
+ """
22
+ try:
23
+ response = self.request(
24
+ "POST",
25
+ "/block_schemas/",
26
+ json=block_schema.model_dump(
27
+ mode="json",
28
+ exclude_unset=True,
29
+ exclude={"id", "block_type", "checksum"},
30
+ ),
31
+ )
32
+ except HTTPStatusError as e:
33
+ if e.response.status_code == 409:
34
+ raise ObjectAlreadyExists(http_exc=e) from e
35
+ else:
36
+ raise
37
+ from prefect.client.schemas.objects import BlockSchema
38
+
39
+ return BlockSchema.model_validate(response.json())
40
+
41
+ def read_block_schema_by_checksum(
42
+ self, checksum: str, version: str | None = None
43
+ ) -> "BlockSchema":
44
+ """
45
+ Look up a block schema checksum
46
+ """
47
+ try:
48
+ response = self.request(
49
+ "GET",
50
+ "/block_schemas/checksum/{checksum}",
51
+ path_params={"checksum": checksum},
52
+ **({"params": {"version": version}} if version else {}),
53
+ )
54
+ except HTTPStatusError as e:
55
+ if e.response.status_code == 404:
56
+ raise ObjectNotFound(http_exc=e) from e
57
+ else:
58
+ raise
59
+ from prefect.client.schemas.objects import BlockSchema
60
+
61
+ return BlockSchema.model_validate(response.json())
62
+
63
+ def read_block_schemas(self) -> "list[BlockSchema]":
64
+ """
65
+ Read all block schemas
66
+ Raises:
67
+ httpx.RequestError: if a valid block schema was not found
68
+
69
+ Returns:
70
+ A BlockSchema.
71
+ """
72
+ response = self.request("POST", "/block_schemas/filter", json={})
73
+ from prefect.client.schemas.objects import BlockSchema
74
+
75
+ return BlockSchema.model_validate_list(response.json())
76
+
77
+ def get_most_recent_block_schema_for_block_type(
78
+ self,
79
+ block_type_id: "UUID",
80
+ ) -> "BlockSchema | None":
81
+ """
82
+ Fetches the most recent block schema for a specified block type ID.
83
+
84
+ Args:
85
+ block_type_id: The ID of the block type.
86
+
87
+ Raises:
88
+ httpx.RequestError: If the request fails for any reason.
89
+
90
+ Returns:
91
+ The most recent block schema or None.
92
+ """
93
+ try:
94
+ response = self.request(
95
+ "POST",
96
+ "/block_schemas/filter",
97
+ json={
98
+ "block_schemas": {"block_type_id": {"any_": [str(block_type_id)]}},
99
+ "limit": 1,
100
+ },
101
+ )
102
+ except HTTPStatusError:
103
+ raise
104
+ from prefect.client.schemas.objects import BlockSchema
105
+
106
+ return next(iter(BlockSchema.model_validate_list(response.json())), None)
107
+
108
+
109
+ class BlocksSchemaAsyncClient(BaseAsyncClient):
110
+ async def create_block_schema(
111
+ self, block_schema: "BlockSchemaCreate"
112
+ ) -> "BlockSchema":
113
+ """
114
+ Create a block schema in the Prefect API.
115
+ """
116
+ try:
117
+ response = await self.request(
118
+ "POST",
119
+ "/block_schemas/",
120
+ json=block_schema.model_dump(
121
+ mode="json",
122
+ exclude_unset=True,
123
+ exclude={"id", "block_type", "checksum"},
124
+ ),
125
+ )
126
+ except HTTPStatusError as e:
127
+ if e.response.status_code == 409:
128
+ raise ObjectAlreadyExists(http_exc=e) from e
129
+ else:
130
+ raise
131
+ from prefect.client.schemas.objects import BlockSchema
132
+
133
+ return BlockSchema.model_validate(response.json())
134
+
135
+ async def read_block_schema_by_checksum(
136
+ self, checksum: str, version: str | None = None
137
+ ) -> "BlockSchema":
138
+ """
139
+ Look up a block schema checksum
140
+ """
141
+ try:
142
+ response = await self.request(
143
+ "GET",
144
+ "/block_schemas/checksum/{checksum}",
145
+ path_params={"checksum": checksum},
146
+ **({"params": {"version": version}} if version else {}),
147
+ )
148
+ except HTTPStatusError as e:
149
+ if e.response.status_code == 404:
150
+ raise ObjectNotFound(http_exc=e) from e
151
+ else:
152
+ raise
153
+ from prefect.client.schemas.objects import BlockSchema
154
+
155
+ return BlockSchema.model_validate(response.json())
156
+
157
+ async def read_block_schemas(self) -> "list[BlockSchema]":
158
+ """
159
+ Read all block schemas
160
+ Raises:
161
+ httpx.RequestError: if a valid block schema was not found
162
+
163
+ Returns:
164
+ A BlockSchema.
165
+ """
166
+ response = await self.request("POST", "/block_schemas/filter", json={})
167
+ from prefect.client.schemas.objects import BlockSchema
168
+
169
+ return BlockSchema.model_validate_list(response.json())
170
+
171
+ async def get_most_recent_block_schema_for_block_type(
172
+ self,
173
+ block_type_id: "UUID",
174
+ ) -> "BlockSchema | None":
175
+ """
176
+ Fetches the most recent block schema for a specified block type ID.
177
+
178
+ Args:
179
+ block_type_id: The ID of the block type.
180
+
181
+ Raises:
182
+ httpx.RequestError: If the request fails for any reason.
183
+
184
+ Returns:
185
+ The most recent block schema or None.
186
+ """
187
+ try:
188
+ response = await self.request(
189
+ "POST",
190
+ "/block_schemas/filter",
191
+ json={
192
+ "block_schemas": {"block_type_id": {"any_": [str(block_type_id)]}},
193
+ "limit": 1,
194
+ },
195
+ )
196
+ except HTTPStatusError:
197
+ raise
198
+ from prefect.client.schemas.objects import BlockSchema
199
+
200
+ return next(iter(BlockSchema.model_validate_list(response.json())), None)
File without changes
@@ -0,0 +1,380 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from httpx import HTTPStatusError
6
+
7
+ from prefect.client.orchestration.base import BaseAsyncClient, BaseClient
8
+ from prefect.exceptions import ObjectAlreadyExists, ObjectNotFound, ProtectedBlockError
9
+
10
+ if TYPE_CHECKING:
11
+ from uuid import UUID
12
+
13
+ from prefect.client.schemas.actions import (
14
+ BlockTypeCreate,
15
+ BlockTypeUpdate,
16
+ )
17
+ from prefect.client.schemas.objects import (
18
+ BlockDocument,
19
+ BlockType,
20
+ )
21
+
22
+
23
+ class BlocksTypeClient(BaseClient):
24
+ def read_block_documents_by_type(
25
+ self,
26
+ block_type_slug: str,
27
+ offset: int | None = None,
28
+ limit: int | None = None,
29
+ include_secrets: bool = True,
30
+ ) -> "list[BlockDocument]":
31
+ """Retrieve block documents by block type slug.
32
+
33
+ Args:
34
+ block_type_slug: The block type slug.
35
+ offset: an offset
36
+ limit: the number of blocks to return
37
+ include_secrets: whether to include secret values
38
+
39
+ Returns:
40
+ A list of block documents
41
+ """
42
+ response = self.request(
43
+ "GET",
44
+ "/block_types/slug/{slug}/block_documents",
45
+ path_params={"slug": block_type_slug},
46
+ params=dict(
47
+ offset=offset,
48
+ limit=limit,
49
+ include_secrets=include_secrets,
50
+ ),
51
+ )
52
+
53
+ from prefect.client.schemas.objects import BlockDocument
54
+
55
+ return BlockDocument.model_validate_list(response.json())
56
+
57
+ def create_block_type(self, block_type: "BlockTypeCreate") -> "BlockType":
58
+ """
59
+ Create a block type in the Prefect API.
60
+ """
61
+ try:
62
+ response = self.request(
63
+ "POST",
64
+ "/block_types/",
65
+ json=block_type.model_dump(
66
+ mode="json", exclude_unset=True, exclude={"id"}
67
+ ),
68
+ )
69
+ except HTTPStatusError as e:
70
+ if e.response.status_code == 409:
71
+ raise ObjectAlreadyExists(http_exc=e) from e
72
+ else:
73
+ raise
74
+ from prefect.client.schemas.objects import BlockType
75
+
76
+ return BlockType.model_validate(response.json())
77
+
78
+ def read_block_type_by_slug(self, slug: str) -> "BlockType":
79
+ """
80
+ Read a block type by its slug.
81
+ """
82
+ try:
83
+ response = self.request(
84
+ "GET",
85
+ "/block_types/slug/{slug}",
86
+ path_params={"slug": slug},
87
+ )
88
+ except HTTPStatusError as e:
89
+ if e.response.status_code == 404:
90
+ raise ObjectNotFound(http_exc=e) from e
91
+ else:
92
+ raise
93
+ from prefect.client.schemas.objects import BlockType
94
+
95
+ return BlockType.model_validate(response.json())
96
+
97
+ def update_block_type(
98
+ self, block_type_id: "UUID", block_type: "BlockTypeUpdate"
99
+ ) -> None:
100
+ """
101
+ Update a block document in the Prefect API.
102
+ """
103
+ from prefect.client.schemas.actions import BlockTypeUpdate
104
+
105
+ try:
106
+ self.request(
107
+ "PATCH",
108
+ "/block_types/{id}",
109
+ path_params={"id": block_type_id},
110
+ json=block_type.model_dump(
111
+ mode="json",
112
+ exclude_unset=True,
113
+ include=BlockTypeUpdate.updatable_fields(),
114
+ ),
115
+ )
116
+ except HTTPStatusError as e:
117
+ if e.response.status_code == 404:
118
+ raise ObjectNotFound(http_exc=e) from e
119
+ else:
120
+ raise
121
+
122
+ def delete_block_type(self, block_type_id: "UUID") -> None:
123
+ """
124
+ Delete a block type.
125
+ """
126
+ try:
127
+ self.request(
128
+ "DELETE",
129
+ "/block_types/{id}",
130
+ path_params={"id": block_type_id},
131
+ )
132
+ except HTTPStatusError as e:
133
+ if e.response.status_code == 404:
134
+ raise ObjectNotFound(http_exc=e) from e
135
+ elif (
136
+ e.response.status_code == 403
137
+ and e.response.json()["detail"]
138
+ == "protected block types cannot be deleted."
139
+ ):
140
+ raise ProtectedBlockError(
141
+ "Protected block types cannot be deleted."
142
+ ) from e
143
+ else:
144
+ raise
145
+
146
+ def read_block_types(self) -> "list[BlockType]":
147
+ """
148
+ Read all block types
149
+ Raises:
150
+ httpx.RequestError: if the block types were not found
151
+
152
+ Returns:
153
+ List of BlockTypes.
154
+ """
155
+ response = self.request("POST", "/block_types/filter", json={})
156
+ from prefect.client.schemas.objects import BlockType
157
+
158
+ return BlockType.model_validate_list(response.json())
159
+
160
+ def read_block_document_by_name(
161
+ self,
162
+ name: str,
163
+ block_type_slug: str,
164
+ include_secrets: bool = True,
165
+ ) -> "BlockDocument":
166
+ """
167
+ Read the block document with the specified name that corresponds to a
168
+ specific block type name.
169
+
170
+ Args:
171
+ name: The block document name.
172
+ block_type_slug: The block type slug.
173
+ include_secrets (bool): whether to include secret values
174
+ on the Block, corresponding to Pydantic's `SecretStr` and
175
+ `SecretBytes` fields. These fields are automatically obfuscated
176
+ by Pydantic, but users can additionally choose not to receive
177
+ their values from the API. Note that any business logic on the
178
+ Block may not work if this is `False`.
179
+
180
+ Raises:
181
+ httpx.RequestError: if the block document was not found for any reason
182
+
183
+ Returns:
184
+ A block document or None.
185
+ """
186
+ try:
187
+ response = self.request(
188
+ "GET",
189
+ "/block_types/slug/{slug}/block_documents/name/{block_document_name}",
190
+ path_params={"slug": block_type_slug, "block_document_name": name},
191
+ params=dict(include_secrets=include_secrets),
192
+ )
193
+ except HTTPStatusError as e:
194
+ if e.response.status_code == 404:
195
+ raise ObjectNotFound(http_exc=e) from e
196
+ else:
197
+ raise
198
+ from prefect.client.schemas.objects import BlockDocument
199
+
200
+ return BlockDocument.model_validate(response.json())
201
+
202
+
203
+ class BlocksTypeAsyncClient(BaseAsyncClient):
204
+ async def read_block_documents_by_type(
205
+ self,
206
+ block_type_slug: str,
207
+ offset: int | None = None,
208
+ limit: int | None = None,
209
+ include_secrets: bool = True,
210
+ ) -> "list[BlockDocument]":
211
+ """Retrieve block documents by block type slug.
212
+
213
+ Args:
214
+ block_type_slug: The block type slug.
215
+ offset: an offset
216
+ limit: the number of blocks to return
217
+ include_secrets: whether to include secret values
218
+
219
+ Returns:
220
+ A list of block documents
221
+ """
222
+ response = await self.request(
223
+ "GET",
224
+ "/block_types/slug/{slug}/block_documents",
225
+ path_params={"slug": block_type_slug},
226
+ params=dict(
227
+ offset=offset,
228
+ limit=limit,
229
+ include_secrets=include_secrets,
230
+ ),
231
+ )
232
+
233
+ from prefect.client.schemas.objects import BlockDocument
234
+
235
+ return BlockDocument.model_validate_list(response.json())
236
+
237
+ async def create_block_type(self, block_type: "BlockTypeCreate") -> "BlockType":
238
+ """
239
+ Create a block type in the Prefect API.
240
+ """
241
+ try:
242
+ response = await self.request(
243
+ "POST",
244
+ "/block_types/",
245
+ json=block_type.model_dump(
246
+ mode="json", exclude_unset=True, exclude={"id"}
247
+ ),
248
+ )
249
+ except HTTPStatusError as e:
250
+ if e.response.status_code == 409:
251
+ raise ObjectAlreadyExists(http_exc=e) from e
252
+ else:
253
+ raise
254
+ from prefect.client.schemas.objects import BlockType
255
+
256
+ return BlockType.model_validate(response.json())
257
+
258
+ async def read_block_type_by_slug(self, slug: str) -> "BlockType":
259
+ """
260
+ Read a block type by its slug.
261
+ """
262
+ try:
263
+ response = await self.request(
264
+ "GET",
265
+ "/block_types/slug/{slug}",
266
+ path_params={"slug": slug},
267
+ )
268
+ except HTTPStatusError as e:
269
+ if e.response.status_code == 404:
270
+ raise ObjectNotFound(http_exc=e) from e
271
+ else:
272
+ raise
273
+ from prefect.client.schemas.objects import BlockType
274
+
275
+ return BlockType.model_validate(response.json())
276
+
277
+ async def update_block_type(
278
+ self, block_type_id: "UUID", block_type: "BlockTypeUpdate"
279
+ ) -> None:
280
+ """
281
+ Update a block document in the Prefect API.
282
+ """
283
+ from prefect.client.schemas.actions import BlockTypeUpdate
284
+
285
+ try:
286
+ await self.request(
287
+ "PATCH",
288
+ "/block_types/{id}",
289
+ path_params={"id": block_type_id},
290
+ json=block_type.model_dump(
291
+ mode="json",
292
+ exclude_unset=True,
293
+ include=BlockTypeUpdate.updatable_fields(),
294
+ ),
295
+ )
296
+ except HTTPStatusError as e:
297
+ if e.response.status_code == 404:
298
+ raise ObjectNotFound(http_exc=e) from e
299
+ else:
300
+ raise
301
+
302
+ async def delete_block_type(self, block_type_id: "UUID") -> None:
303
+ """
304
+ Delete a block type.
305
+ """
306
+ try:
307
+ await self.request(
308
+ "DELETE",
309
+ "/block_types/{id}",
310
+ path_params={"id": block_type_id},
311
+ )
312
+ except HTTPStatusError as e:
313
+ if e.response.status_code == 404:
314
+ raise ObjectNotFound(http_exc=e) from e
315
+ elif (
316
+ e.response.status_code == 403
317
+ and e.response.json()["detail"]
318
+ == "protected block types cannot be deleted."
319
+ ):
320
+ raise ProtectedBlockError(
321
+ "Protected block types cannot be deleted."
322
+ ) from e
323
+ else:
324
+ raise
325
+
326
+ async def read_block_types(self) -> "list[BlockType]":
327
+ """
328
+ Read all block types
329
+ Raises:
330
+ httpx.RequestError: if the block types were not found
331
+
332
+ Returns:
333
+ List of BlockTypes.
334
+ """
335
+ response = await self.request("POST", "/block_types/filter", json={})
336
+ from prefect.client.schemas.objects import BlockType
337
+
338
+ return BlockType.model_validate_list(response.json())
339
+
340
+ async def read_block_document_by_name(
341
+ self,
342
+ name: str,
343
+ block_type_slug: str,
344
+ include_secrets: bool = True,
345
+ ) -> "BlockDocument":
346
+ """
347
+ Read the block document with the specified name that corresponds to a
348
+ specific block type name.
349
+
350
+ Args:
351
+ name: The block document name.
352
+ block_type_slug: The block type slug.
353
+ include_secrets (bool): whether to include secret values
354
+ on the Block, corresponding to Pydantic's `SecretStr` and
355
+ `SecretBytes` fields. These fields are automatically obfuscated
356
+ by Pydantic, but users can additionally choose not to receive
357
+ their values from the API. Note that any business logic on the
358
+ Block may not work if this is `False`.
359
+
360
+ Raises:
361
+ httpx.RequestError: if the block document was not found for any reason
362
+
363
+ Returns:
364
+ A block document or None.
365
+ """
366
+ try:
367
+ response = await self.request(
368
+ "GET",
369
+ "/block_types/slug/{slug}/block_documents/name/{block_document_name}",
370
+ path_params={"slug": block_type_slug, "block_document_name": name},
371
+ params=dict(include_secrets=include_secrets),
372
+ )
373
+ except HTTPStatusError as e:
374
+ if e.response.status_code == 404:
375
+ raise ObjectNotFound(http_exc=e) from e
376
+ else:
377
+ raise
378
+ from prefect.client.schemas.objects import BlockDocument
379
+
380
+ return BlockDocument.model_validate(response.json())
File without changes