prefect-client 3.1.11__py3-none-any.whl → 3.1.13__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 (133) hide show
  1. prefect/_experimental/sla/__init__.py +0 -0
  2. prefect/_experimental/sla/client.py +92 -0
  3. prefect/_experimental/sla/objects.py +61 -0
  4. prefect/_internal/concurrency/services.py +2 -2
  5. prefect/_internal/concurrency/threads.py +6 -0
  6. prefect/_internal/retries.py +6 -3
  7. prefect/_internal/schemas/validators.py +6 -4
  8. prefect/_version.py +3 -3
  9. prefect/artifacts.py +4 -1
  10. prefect/automations.py +236 -30
  11. prefect/blocks/__init__.py +3 -3
  12. prefect/blocks/abstract.py +57 -31
  13. prefect/blocks/core.py +181 -82
  14. prefect/blocks/notifications.py +134 -73
  15. prefect/blocks/redis.py +13 -9
  16. prefect/blocks/system.py +24 -11
  17. prefect/blocks/webhook.py +7 -5
  18. prefect/cache_policies.py +23 -22
  19. prefect/client/orchestration/__init__.py +103 -2006
  20. prefect/client/orchestration/_automations/__init__.py +0 -0
  21. prefect/client/orchestration/_automations/client.py +329 -0
  22. prefect/client/orchestration/_blocks_documents/__init__.py +0 -0
  23. prefect/client/orchestration/_blocks_documents/client.py +334 -0
  24. prefect/client/orchestration/_blocks_schemas/__init__.py +0 -0
  25. prefect/client/orchestration/_blocks_schemas/client.py +200 -0
  26. prefect/client/orchestration/_blocks_types/__init__.py +0 -0
  27. prefect/client/orchestration/_blocks_types/client.py +380 -0
  28. prefect/client/orchestration/_deployments/__init__.py +0 -0
  29. prefect/client/orchestration/_deployments/client.py +1128 -0
  30. prefect/client/orchestration/_flow_runs/__init__.py +0 -0
  31. prefect/client/orchestration/_flow_runs/client.py +903 -0
  32. prefect/client/orchestration/_flows/__init__.py +0 -0
  33. prefect/client/orchestration/_flows/client.py +343 -0
  34. prefect/client/orchestration/_logs/client.py +16 -14
  35. prefect/client/schemas/__init__.py +68 -28
  36. prefect/client/schemas/objects.py +5 -5
  37. prefect/client/utilities.py +3 -3
  38. prefect/context.py +15 -1
  39. prefect/deployments/base.py +13 -4
  40. prefect/deployments/flow_runs.py +5 -1
  41. prefect/deployments/runner.py +37 -1
  42. prefect/deployments/steps/core.py +1 -1
  43. prefect/deployments/steps/pull.py +8 -3
  44. prefect/deployments/steps/utility.py +2 -2
  45. prefect/docker/docker_image.py +13 -9
  46. prefect/engine.py +33 -11
  47. prefect/events/cli/automations.py +4 -4
  48. prefect/events/clients.py +17 -14
  49. prefect/events/schemas/automations.py +12 -8
  50. prefect/events/schemas/events.py +5 -1
  51. prefect/events/worker.py +1 -1
  52. prefect/filesystems.py +7 -3
  53. prefect/flow_engine.py +64 -47
  54. prefect/flows.py +128 -74
  55. prefect/futures.py +14 -7
  56. prefect/infrastructure/provisioners/__init__.py +2 -0
  57. prefect/infrastructure/provisioners/cloud_run.py +4 -4
  58. prefect/infrastructure/provisioners/coiled.py +249 -0
  59. prefect/infrastructure/provisioners/container_instance.py +4 -3
  60. prefect/infrastructure/provisioners/ecs.py +55 -43
  61. prefect/infrastructure/provisioners/modal.py +5 -4
  62. prefect/input/actions.py +5 -1
  63. prefect/input/run_input.py +157 -43
  64. prefect/logging/configuration.py +3 -3
  65. prefect/logging/filters.py +2 -2
  66. prefect/logging/formatters.py +15 -11
  67. prefect/logging/handlers.py +24 -14
  68. prefect/logging/highlighters.py +5 -5
  69. prefect/logging/loggers.py +28 -18
  70. prefect/logging/logging.yml +1 -1
  71. prefect/main.py +3 -1
  72. prefect/results.py +166 -86
  73. prefect/runner/runner.py +38 -29
  74. prefect/runner/server.py +3 -1
  75. prefect/runner/storage.py +18 -18
  76. prefect/runner/submit.py +19 -12
  77. prefect/runtime/deployment.py +15 -8
  78. prefect/runtime/flow_run.py +19 -6
  79. prefect/runtime/task_run.py +7 -3
  80. prefect/settings/base.py +17 -7
  81. prefect/settings/legacy.py +4 -4
  82. prefect/settings/models/api.py +4 -3
  83. prefect/settings/models/cli.py +4 -3
  84. prefect/settings/models/client.py +7 -4
  85. prefect/settings/models/cloud.py +9 -3
  86. prefect/settings/models/deployments.py +4 -3
  87. prefect/settings/models/experiments.py +4 -8
  88. prefect/settings/models/flows.py +4 -3
  89. prefect/settings/models/internal.py +4 -3
  90. prefect/settings/models/logging.py +8 -6
  91. prefect/settings/models/results.py +4 -3
  92. prefect/settings/models/root.py +11 -16
  93. prefect/settings/models/runner.py +8 -5
  94. prefect/settings/models/server/api.py +6 -3
  95. prefect/settings/models/server/database.py +120 -25
  96. prefect/settings/models/server/deployments.py +4 -3
  97. prefect/settings/models/server/ephemeral.py +7 -4
  98. prefect/settings/models/server/events.py +6 -3
  99. prefect/settings/models/server/flow_run_graph.py +4 -3
  100. prefect/settings/models/server/root.py +4 -3
  101. prefect/settings/models/server/services.py +15 -12
  102. prefect/settings/models/server/tasks.py +7 -4
  103. prefect/settings/models/server/ui.py +4 -3
  104. prefect/settings/models/tasks.py +10 -5
  105. prefect/settings/models/testing.py +4 -3
  106. prefect/settings/models/worker.py +7 -4
  107. prefect/settings/profiles.py +13 -12
  108. prefect/settings/sources.py +20 -19
  109. prefect/states.py +74 -51
  110. prefect/task_engine.py +43 -33
  111. prefect/task_runners.py +85 -72
  112. prefect/task_runs.py +20 -11
  113. prefect/task_worker.py +14 -9
  114. prefect/tasks.py +36 -28
  115. prefect/telemetry/bootstrap.py +13 -9
  116. prefect/telemetry/run_telemetry.py +15 -13
  117. prefect/telemetry/services.py +4 -0
  118. prefect/transactions.py +3 -3
  119. prefect/types/__init__.py +3 -1
  120. prefect/utilities/_deprecated.py +38 -0
  121. prefect/utilities/engine.py +11 -4
  122. prefect/utilities/filesystem.py +2 -2
  123. prefect/utilities/generics.py +1 -1
  124. prefect/utilities/pydantic.py +21 -36
  125. prefect/utilities/templating.py +25 -1
  126. prefect/workers/base.py +58 -33
  127. prefect/workers/process.py +20 -15
  128. prefect/workers/server.py +4 -5
  129. {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/METADATA +3 -3
  130. {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/RECORD +133 -114
  131. {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/LICENSE +0 -0
  132. {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/WHEEL +0 -0
  133. {prefect_client-3.1.11.dist-info → prefect_client-3.1.13.dist-info}/top_level.txt +0 -0
File without changes
@@ -0,0 +1,329 @@
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 ObjectNotFound
9
+
10
+ if TYPE_CHECKING:
11
+ from uuid import UUID
12
+
13
+ from prefect.events.schemas.automations import Automation, AutomationCore
14
+
15
+
16
+ class AutomationClient(BaseClient):
17
+ def create_automation(self, automation: "AutomationCore") -> "UUID":
18
+ """Creates an automation in Prefect Cloud."""
19
+ response = self.request(
20
+ "POST",
21
+ "/automations/",
22
+ json=automation.model_dump(mode="json"),
23
+ )
24
+ from uuid import UUID
25
+
26
+ return UUID(response.json()["id"])
27
+
28
+ def update_automation(
29
+ self, automation_id: "UUID", automation: "AutomationCore"
30
+ ) -> None:
31
+ """Updates an automation in Prefect Cloud."""
32
+ response = self.request(
33
+ "PUT",
34
+ "/automations/{id}",
35
+ path_params={"id": automation_id},
36
+ json=automation.model_dump(mode="json", exclude_unset=True),
37
+ )
38
+ response.raise_for_status()
39
+
40
+ def read_automations(self) -> list["Automation"]:
41
+ response = self.request("POST", "/automations/filter")
42
+ response.raise_for_status()
43
+ from prefect.events.schemas.automations import Automation
44
+
45
+ return Automation.model_validate_list(response.json())
46
+
47
+ def find_automation(self, id_or_name: "str | UUID") -> "Automation | None":
48
+ if isinstance(id_or_name, str):
49
+ name = id_or_name
50
+ try:
51
+ id = UUID(id_or_name)
52
+ except ValueError:
53
+ id = None
54
+ else:
55
+ id = id_or_name
56
+ name = str(id)
57
+
58
+ if id:
59
+ try:
60
+ automation = self.read_automation(id)
61
+ return automation
62
+ except HTTPStatusError as e:
63
+ if e.response.status_code == 404:
64
+ raise ObjectNotFound(http_exc=e) from e
65
+
66
+ automations = self.read_automations()
67
+
68
+ # Look for it by an exact name
69
+ for automation in automations:
70
+ if automation.name == name:
71
+ return automation
72
+
73
+ # Look for it by a case-insensitive name
74
+ for automation in automations:
75
+ if automation.name.lower() == name.lower():
76
+ return automation
77
+
78
+ return None
79
+
80
+ def read_automation(self, automation_id: "UUID | str") -> "Automation | None":
81
+ response = self.request(
82
+ "GET", "/automations/{id}", path_params={"id": automation_id}
83
+ )
84
+ if response.status_code == 404:
85
+ return None
86
+ response.raise_for_status()
87
+ from prefect.events.schemas.automations import Automation
88
+
89
+ return Automation.model_validate(response.json())
90
+
91
+ def read_automations_by_name(self, name: str) -> list["Automation"]:
92
+ """
93
+ Query the Prefect API for an automation by name. Only automations matching the provided name will be returned.
94
+
95
+ Args:
96
+ name: the name of the automation to query
97
+
98
+ Returns:
99
+ a list of Automation model representations of the automations
100
+ """
101
+ from prefect.client.schemas.sorting import AutomationSort
102
+ from prefect.events.filters import (
103
+ AutomationFilter,
104
+ AutomationFilterName,
105
+ )
106
+
107
+ automation_filter = AutomationFilter(name=AutomationFilterName(any_=[name]))
108
+
109
+ response = self.request(
110
+ "POST",
111
+ "/automations/filter",
112
+ json={
113
+ "sort": AutomationSort.UPDATED_DESC,
114
+ "automations": automation_filter.model_dump(mode="json")
115
+ if automation_filter
116
+ else None,
117
+ },
118
+ )
119
+
120
+ response.raise_for_status()
121
+ from prefect.events.schemas.automations import Automation
122
+
123
+ return Automation.model_validate_list(response.json())
124
+
125
+ def pause_automation(self, automation_id: "UUID") -> None:
126
+ response = self.request(
127
+ "PATCH",
128
+ "/automations/{id}",
129
+ path_params={"id": automation_id},
130
+ json={"enabled": False},
131
+ )
132
+ response.raise_for_status()
133
+
134
+ def resume_automation(self, automation_id: "UUID") -> None:
135
+ response = self.request(
136
+ "PATCH",
137
+ "/automations/{id}",
138
+ path_params={"id": automation_id},
139
+ json={"enabled": True},
140
+ )
141
+ response.raise_for_status()
142
+
143
+ def delete_automation(self, automation_id: "UUID") -> None:
144
+ response = self.request(
145
+ "DELETE",
146
+ "/automations/{id}",
147
+ path_params={"id": automation_id},
148
+ )
149
+ if response.status_code == 404:
150
+ return
151
+
152
+ response.raise_for_status()
153
+
154
+ def read_resource_related_automations(self, resource_id: str) -> list["Automation"]:
155
+ response = self.request(
156
+ "GET",
157
+ "/automations/related-to/{resource_id}",
158
+ path_params={"resource_id": resource_id},
159
+ )
160
+ response.raise_for_status()
161
+ from prefect.events.schemas.automations import Automation
162
+
163
+ return Automation.model_validate_list(response.json())
164
+
165
+ def delete_resource_owned_automations(self, resource_id: str) -> None:
166
+ self.request(
167
+ "DELETE",
168
+ "/automations/owned-by/{resource_id}",
169
+ path_params={"resource_id": resource_id},
170
+ )
171
+
172
+
173
+ class AutomationAsyncClient(BaseAsyncClient):
174
+ async def create_automation(self, automation: "AutomationCore") -> "UUID":
175
+ """Creates an automation in Prefect Cloud."""
176
+ response = await self.request(
177
+ "POST",
178
+ "/automations/",
179
+ json=automation.model_dump(mode="json"),
180
+ )
181
+ from uuid import UUID
182
+
183
+ return UUID(response.json()["id"])
184
+
185
+ async def update_automation(
186
+ self, automation_id: "UUID", automation: "AutomationCore"
187
+ ) -> None:
188
+ """Updates an automation in Prefect Cloud."""
189
+ response = await self.request(
190
+ "PUT",
191
+ "/automations/{id}",
192
+ path_params={"id": automation_id},
193
+ json=automation.model_dump(mode="json", exclude_unset=True),
194
+ )
195
+ response.raise_for_status()
196
+
197
+ async def read_automations(self) -> list["Automation"]:
198
+ response = await self.request("POST", "/automations/filter")
199
+ response.raise_for_status()
200
+ from prefect.events.schemas.automations import Automation
201
+
202
+ return Automation.model_validate_list(response.json())
203
+
204
+ async def find_automation(self, id_or_name: "str | UUID") -> "Automation | None":
205
+ if isinstance(id_or_name, str):
206
+ name = id_or_name
207
+ try:
208
+ id = UUID(id_or_name)
209
+ except ValueError:
210
+ id = None
211
+ else:
212
+ id = id_or_name
213
+ name = str(id)
214
+
215
+ if id:
216
+ try:
217
+ automation = await self.read_automation(id)
218
+ return automation
219
+ except HTTPStatusError as e:
220
+ if e.response.status_code == 404:
221
+ raise ObjectNotFound(http_exc=e) from e
222
+
223
+ automations = await self.read_automations()
224
+
225
+ # Look for it by an exact name
226
+ for automation in automations:
227
+ if automation.name == name:
228
+ return automation
229
+
230
+ # Look for it by a case-insensitive name
231
+ for automation in automations:
232
+ if automation.name.lower() == name.lower():
233
+ return automation
234
+
235
+ return None
236
+
237
+ async def read_automation(self, automation_id: "UUID | str") -> "Automation | None":
238
+ response = await self.request(
239
+ "GET", "/automations/{id}", path_params={"id": automation_id}
240
+ )
241
+ if response.status_code == 404:
242
+ return None
243
+ response.raise_for_status()
244
+ from prefect.events.schemas.automations import Automation
245
+
246
+ return Automation.model_validate(response.json())
247
+
248
+ async def read_automations_by_name(self, name: str) -> list["Automation"]:
249
+ """
250
+ Query the Prefect API for an automation by name. Only automations matching the provided name will be returned.
251
+
252
+ Args:
253
+ name: the name of the automation to query
254
+
255
+ Returns:
256
+ a list of Automation model representations of the automations
257
+ """
258
+ from prefect.client.schemas.sorting import AutomationSort
259
+ from prefect.events.filters import (
260
+ AutomationFilter,
261
+ AutomationFilterName,
262
+ )
263
+
264
+ automation_filter = AutomationFilter(name=AutomationFilterName(any_=[name]))
265
+
266
+ response = await self.request(
267
+ "POST",
268
+ "/automations/filter",
269
+ json={
270
+ "sort": AutomationSort.UPDATED_DESC,
271
+ "automations": automation_filter.model_dump(mode="json")
272
+ if automation_filter
273
+ else None,
274
+ },
275
+ )
276
+
277
+ response.raise_for_status()
278
+ from prefect.events.schemas.automations import Automation
279
+
280
+ return Automation.model_validate_list(response.json())
281
+
282
+ async def pause_automation(self, automation_id: "UUID") -> None:
283
+ response = await self.request(
284
+ "PATCH",
285
+ "/automations/{id}",
286
+ path_params={"id": automation_id},
287
+ json={"enabled": False},
288
+ )
289
+ response.raise_for_status()
290
+
291
+ async def resume_automation(self, automation_id: "UUID") -> None:
292
+ response = await self.request(
293
+ "PATCH",
294
+ "/automations/{id}",
295
+ path_params={"id": automation_id},
296
+ json={"enabled": True},
297
+ )
298
+ response.raise_for_status()
299
+
300
+ async def delete_automation(self, automation_id: "UUID") -> None:
301
+ response = await self.request(
302
+ "DELETE",
303
+ "/automations/{id}",
304
+ path_params={"id": automation_id},
305
+ )
306
+ if response.status_code == 404:
307
+ return
308
+
309
+ response.raise_for_status()
310
+
311
+ async def read_resource_related_automations(
312
+ self, resource_id: str
313
+ ) -> list["Automation"]:
314
+ response = await self.request(
315
+ "GET",
316
+ "/automations/related-to/{resource_id}",
317
+ path_params={"resource_id": resource_id},
318
+ )
319
+ response.raise_for_status()
320
+ from prefect.events.schemas.automations import Automation
321
+
322
+ return Automation.model_validate_list(response.json())
323
+
324
+ async def delete_resource_owned_automations(self, resource_id: str) -> None:
325
+ await self.request(
326
+ "DELETE",
327
+ "/automations/owned-by/{resource_id}",
328
+ path_params={"resource_id": resource_id},
329
+ )
@@ -0,0 +1,334 @@
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 (
14
+ BlockDocumentCreate,
15
+ BlockDocumentUpdate,
16
+ )
17
+ from prefect.client.schemas.objects import (
18
+ BlockDocument,
19
+ )
20
+
21
+
22
+ class BlocksDocumentClient(BaseClient):
23
+ def create_block_document(
24
+ self,
25
+ block_document: "BlockDocument | BlockDocumentCreate",
26
+ include_secrets: bool = True,
27
+ ) -> "BlockDocument":
28
+ """
29
+ Create a block document in the Prefect API. This data is used to configure a
30
+ corresponding Block.
31
+
32
+ Args:
33
+ include_secrets (bool): whether to include secret values
34
+ on the stored Block, corresponding to Pydantic's `SecretStr` and
35
+ `SecretBytes` fields. Note Blocks may not work as expected if
36
+ this is set to `False`.
37
+ """
38
+ block_document_data = block_document.model_dump(
39
+ mode="json",
40
+ exclude_unset=True,
41
+ exclude={"id", "block_schema", "block_type"},
42
+ context={"include_secrets": include_secrets},
43
+ serialize_as_any=True,
44
+ )
45
+ try:
46
+ response = self.request(
47
+ "POST",
48
+ "/block_documents/",
49
+ json=block_document_data,
50
+ )
51
+ except HTTPStatusError as e:
52
+ if e.response.status_code == 409:
53
+ raise ObjectAlreadyExists(http_exc=e) from e
54
+ else:
55
+ raise
56
+ from prefect.client.schemas.objects import BlockDocument
57
+
58
+ return BlockDocument.model_validate(response.json())
59
+
60
+ def update_block_document(
61
+ self,
62
+ block_document_id: "UUID",
63
+ block_document: "BlockDocumentUpdate",
64
+ ) -> None:
65
+ """
66
+ Update a block document in the Prefect API.
67
+ """
68
+ try:
69
+ self.request(
70
+ "PATCH",
71
+ "/block_documents/{id}",
72
+ path_params={"id": block_document_id},
73
+ json=block_document.model_dump(
74
+ mode="json",
75
+ exclude_unset=True,
76
+ include={"data", "merge_existing_data", "block_schema_id"},
77
+ ),
78
+ )
79
+ except HTTPStatusError as e:
80
+ if e.response.status_code == 404:
81
+ raise ObjectNotFound(http_exc=e) from e
82
+ else:
83
+ raise
84
+
85
+ def delete_block_document(self, block_document_id: "UUID") -> None:
86
+ """
87
+ Delete a block document.
88
+ """
89
+ try:
90
+ self.request(
91
+ "DELETE",
92
+ "/block_documents/{id}",
93
+ path_params={"id": block_document_id},
94
+ )
95
+ except HTTPStatusError as e:
96
+ if e.response.status_code == 404:
97
+ raise ObjectNotFound(http_exc=e) from e
98
+ else:
99
+ raise
100
+
101
+ def read_block_document(
102
+ self,
103
+ block_document_id: "UUID",
104
+ include_secrets: bool = True,
105
+ ) -> "BlockDocument":
106
+ """
107
+ Read the block document with the specified ID.
108
+
109
+ Args:
110
+ block_document_id: the block document id
111
+ include_secrets (bool): whether to include secret values
112
+ on the Block, corresponding to Pydantic's `SecretStr` and
113
+ `SecretBytes` fields. These fields are automatically obfuscated
114
+ by Pydantic, but users can additionally choose not to receive
115
+ their values from the API. Note that any business logic on the
116
+ Block may not work if this is `False`.
117
+
118
+ Raises:
119
+ httpx.RequestError: if the block document was not found for any reason
120
+
121
+ Returns:
122
+ A block document or None.
123
+ """
124
+
125
+ try:
126
+ response = self.request(
127
+ "GET",
128
+ "/block_documents/{id}",
129
+ path_params={"id": block_document_id},
130
+ params=dict(include_secrets=include_secrets),
131
+ )
132
+ except HTTPStatusError as e:
133
+ if e.response.status_code == 404:
134
+ raise ObjectNotFound(http_exc=e) from e
135
+ else:
136
+ raise
137
+ from prefect.client.schemas.objects import BlockDocument
138
+
139
+ return BlockDocument.model_validate(response.json())
140
+
141
+ def read_block_documents(
142
+ self,
143
+ block_schema_type: str | None = None,
144
+ offset: int | None = None,
145
+ limit: int | None = None,
146
+ include_secrets: bool = True,
147
+ ) -> "list[BlockDocument]":
148
+ """
149
+ Read block documents
150
+
151
+ Args:
152
+ block_schema_type: an optional block schema type
153
+ offset: an offset
154
+ limit: the number of blocks to return
155
+ include_secrets (bool): whether to include secret values
156
+ on the Block, corresponding to Pydantic's `SecretStr` and
157
+ `SecretBytes` fields. These fields are automatically obfuscated
158
+ by Pydantic, but users can additionally choose not to receive
159
+ their values from the API. Note that any business logic on the
160
+ Block may not work if this is `False`.
161
+
162
+ Returns:
163
+ A list of block documents
164
+ """
165
+ response = self.request(
166
+ "POST",
167
+ "/block_documents/filter",
168
+ json=dict(
169
+ block_schema_type=block_schema_type,
170
+ offset=offset,
171
+ limit=limit,
172
+ include_secrets=include_secrets,
173
+ ),
174
+ )
175
+ from prefect.client.schemas.objects import BlockDocument
176
+
177
+ return BlockDocument.model_validate_list(response.json())
178
+
179
+
180
+ class BlocksDocumentAsyncClient(BaseAsyncClient):
181
+ async def create_block_document(
182
+ self,
183
+ block_document: "BlockDocument | BlockDocumentCreate",
184
+ include_secrets: bool = True,
185
+ ) -> "BlockDocument":
186
+ """
187
+ Create a block document in the Prefect API. This data is used to configure a
188
+ corresponding Block.
189
+
190
+ Args:
191
+ include_secrets (bool): whether to include secret values
192
+ on the stored Block, corresponding to Pydantic's `SecretStr` and
193
+ `SecretBytes` fields. Note Blocks may not work as expected if
194
+ this is set to `False`.
195
+ """
196
+ block_document_data = block_document.model_dump(
197
+ mode="json",
198
+ exclude_unset=True,
199
+ exclude={"id", "block_schema", "block_type"},
200
+ context={"include_secrets": include_secrets},
201
+ serialize_as_any=True,
202
+ )
203
+ try:
204
+ response = await self.request(
205
+ "POST",
206
+ "/block_documents/",
207
+ json=block_document_data,
208
+ )
209
+ except HTTPStatusError as e:
210
+ if e.response.status_code == 409:
211
+ raise ObjectAlreadyExists(http_exc=e) from e
212
+ else:
213
+ raise
214
+ from prefect.client.schemas.objects import BlockDocument
215
+
216
+ return BlockDocument.model_validate(response.json())
217
+
218
+ async def update_block_document(
219
+ self,
220
+ block_document_id: "UUID",
221
+ block_document: "BlockDocumentUpdate",
222
+ ) -> None:
223
+ """
224
+ Update a block document in the Prefect API.
225
+ """
226
+ try:
227
+ await self.request(
228
+ "PATCH",
229
+ "/block_documents/{id}",
230
+ path_params={"id": block_document_id},
231
+ json=block_document.model_dump(
232
+ mode="json",
233
+ exclude_unset=True,
234
+ include={"data", "merge_existing_data", "block_schema_id"},
235
+ ),
236
+ )
237
+ except HTTPStatusError as e:
238
+ if e.response.status_code == 404:
239
+ raise ObjectNotFound(http_exc=e) from e
240
+ else:
241
+ raise
242
+
243
+ async def delete_block_document(self, block_document_id: "UUID") -> None:
244
+ """
245
+ Delete a block document.
246
+ """
247
+ try:
248
+ await self.request(
249
+ "DELETE",
250
+ "/block_documents/{id}",
251
+ path_params={"id": block_document_id},
252
+ )
253
+ except HTTPStatusError as e:
254
+ if e.response.status_code == 404:
255
+ raise ObjectNotFound(http_exc=e) from e
256
+ else:
257
+ raise
258
+
259
+ async def read_block_document(
260
+ self,
261
+ block_document_id: "UUID",
262
+ include_secrets: bool = True,
263
+ ) -> "BlockDocument":
264
+ """
265
+ Read the block document with the specified ID.
266
+
267
+ Args:
268
+ block_document_id: the block document id
269
+ include_secrets (bool): whether to include secret values
270
+ on the Block, corresponding to Pydantic's `SecretStr` and
271
+ `SecretBytes` fields. These fields are automatically obfuscated
272
+ by Pydantic, but users can additionally choose not to receive
273
+ their values from the API. Note that any business logic on the
274
+ Block may not work if this is `False`.
275
+
276
+ Raises:
277
+ httpx.RequestError: if the block document was not found for any reason
278
+
279
+ Returns:
280
+ A block document or None.
281
+ """
282
+ try:
283
+ response = await self.request(
284
+ "GET",
285
+ "/block_documents/{id}",
286
+ path_params={"id": block_document_id},
287
+ params=dict(include_secrets=include_secrets),
288
+ )
289
+ except HTTPStatusError as e:
290
+ if e.response.status_code == 404:
291
+ raise ObjectNotFound(http_exc=e) from e
292
+ else:
293
+ raise
294
+ from prefect.client.schemas.objects import BlockDocument
295
+
296
+ return BlockDocument.model_validate(response.json())
297
+
298
+ async def read_block_documents(
299
+ self,
300
+ block_schema_type: str | None = None,
301
+ offset: int | None = None,
302
+ limit: int | None = None,
303
+ include_secrets: bool = True,
304
+ ) -> "list[BlockDocument]":
305
+ """
306
+ Read block documents
307
+
308
+ Args:
309
+ block_schema_type: an optional block schema type
310
+ offset: an offset
311
+ limit: the number of blocks to return
312
+ include_secrets (bool): whether to include secret values
313
+ on the Block, corresponding to Pydantic's `SecretStr` and
314
+ `SecretBytes` fields. These fields are automatically obfuscated
315
+ by Pydantic, but users can additionally choose not to receive
316
+ their values from the API. Note that any business logic on the
317
+ Block may not work if this is `False`.
318
+
319
+ Returns:
320
+ A list of block documents
321
+ """
322
+ response = await self.request(
323
+ "POST",
324
+ "/block_documents/filter",
325
+ json=dict(
326
+ block_schema_type=block_schema_type,
327
+ offset=offset,
328
+ limit=limit,
329
+ include_secrets=include_secrets,
330
+ ),
331
+ )
332
+ from prefect.client.schemas.objects import BlockDocument
333
+
334
+ return BlockDocument.model_validate_list(response.json())