prefect-client 3.2.1__py3-none-any.whl → 3.2.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- prefect/__init__.py +15 -8
- prefect/_build_info.py +5 -0
- prefect/_internal/schemas/bases.py +4 -7
- prefect/_internal/schemas/validators.py +5 -6
- prefect/_result_records.py +6 -1
- prefect/client/orchestration/__init__.py +18 -6
- prefect/client/schemas/schedules.py +2 -2
- prefect/concurrency/asyncio.py +4 -3
- prefect/concurrency/sync.py +3 -3
- prefect/concurrency/v1/asyncio.py +3 -3
- prefect/concurrency/v1/sync.py +3 -3
- prefect/deployments/flow_runs.py +2 -2
- prefect/docker/docker_image.py +2 -3
- prefect/engine.py +1 -1
- prefect/events/clients.py +4 -3
- prefect/events/related.py +3 -5
- prefect/flows.py +11 -5
- prefect/locking/filesystem.py +8 -8
- prefect/logging/handlers.py +7 -11
- prefect/main.py +0 -2
- prefect/runtime/flow_run.py +10 -17
- prefect/server/api/__init__.py +34 -0
- prefect/server/api/admin.py +85 -0
- prefect/server/api/artifacts.py +224 -0
- prefect/server/api/automations.py +239 -0
- prefect/server/api/block_capabilities.py +25 -0
- prefect/server/api/block_documents.py +164 -0
- prefect/server/api/block_schemas.py +153 -0
- prefect/server/api/block_types.py +211 -0
- prefect/server/api/clients.py +246 -0
- prefect/server/api/collections.py +75 -0
- prefect/server/api/concurrency_limits.py +286 -0
- prefect/server/api/concurrency_limits_v2.py +269 -0
- prefect/server/api/csrf_token.py +38 -0
- prefect/server/api/dependencies.py +196 -0
- prefect/server/api/deployments.py +941 -0
- prefect/server/api/events.py +300 -0
- prefect/server/api/flow_run_notification_policies.py +120 -0
- prefect/server/api/flow_run_states.py +52 -0
- prefect/server/api/flow_runs.py +867 -0
- prefect/server/api/flows.py +210 -0
- prefect/server/api/logs.py +43 -0
- prefect/server/api/middleware.py +73 -0
- prefect/server/api/root.py +35 -0
- prefect/server/api/run_history.py +170 -0
- prefect/server/api/saved_searches.py +99 -0
- prefect/server/api/server.py +891 -0
- prefect/server/api/task_run_states.py +52 -0
- prefect/server/api/task_runs.py +342 -0
- prefect/server/api/task_workers.py +31 -0
- prefect/server/api/templates.py +35 -0
- prefect/server/api/ui/__init__.py +3 -0
- prefect/server/api/ui/flow_runs.py +128 -0
- prefect/server/api/ui/flows.py +173 -0
- prefect/server/api/ui/schemas.py +63 -0
- prefect/server/api/ui/task_runs.py +175 -0
- prefect/server/api/validation.py +382 -0
- prefect/server/api/variables.py +181 -0
- prefect/server/api/work_queues.py +230 -0
- prefect/server/api/workers.py +656 -0
- prefect/settings/sources.py +18 -5
- prefect/states.py +3 -3
- prefect/task_engine.py +3 -3
- prefect/types/_datetime.py +82 -3
- prefect/utilities/dockerutils.py +2 -2
- prefect/workers/base.py +5 -5
- {prefect_client-3.2.1.dist-info → prefect_client-3.2.3.dist-info}/METADATA +10 -15
- {prefect_client-3.2.1.dist-info → prefect_client-3.2.3.dist-info}/RECORD +70 -32
- {prefect_client-3.2.1.dist-info → prefect_client-3.2.3.dist-info}/WHEEL +1 -2
- prefect/_version.py +0 -21
- prefect_client-3.2.1.dist-info/top_level.txt +0 -1
- {prefect_client-3.2.1.dist-info → prefect_client-3.2.3.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,164 @@
|
|
1
|
+
"""
|
2
|
+
Routes for interacting with block objects.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import List, Optional
|
6
|
+
from uuid import UUID
|
7
|
+
|
8
|
+
from fastapi import Body, Depends, HTTPException, Path, Query, status
|
9
|
+
|
10
|
+
from prefect.server import models, schemas
|
11
|
+
from prefect.server.api import dependencies
|
12
|
+
from prefect.server.database import PrefectDBInterface, provide_database_interface
|
13
|
+
from prefect.server.utilities.server import PrefectRouter
|
14
|
+
|
15
|
+
router: PrefectRouter = PrefectRouter(
|
16
|
+
prefix="/block_documents", tags=["Block documents"]
|
17
|
+
)
|
18
|
+
|
19
|
+
|
20
|
+
@router.post("/", status_code=status.HTTP_201_CREATED)
|
21
|
+
async def create_block_document(
|
22
|
+
block_document: schemas.actions.BlockDocumentCreate,
|
23
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
24
|
+
) -> schemas.core.BlockDocument:
|
25
|
+
"""
|
26
|
+
Create a new block document.
|
27
|
+
"""
|
28
|
+
async with db.session_context(begin_transaction=True) as session:
|
29
|
+
if block_document.name is not None:
|
30
|
+
exists = (
|
31
|
+
await models.block_documents.block_document_with_unique_values_exists(
|
32
|
+
session=session,
|
33
|
+
block_type_id=block_document.block_type_id,
|
34
|
+
name=block_document.name,
|
35
|
+
)
|
36
|
+
)
|
37
|
+
if exists:
|
38
|
+
raise HTTPException(
|
39
|
+
status.HTTP_409_CONFLICT,
|
40
|
+
detail="Block already exists",
|
41
|
+
)
|
42
|
+
|
43
|
+
return await models.block_documents.create_block_document(
|
44
|
+
session=session, block_document=block_document
|
45
|
+
)
|
46
|
+
|
47
|
+
|
48
|
+
@router.post("/filter")
|
49
|
+
async def read_block_documents(
|
50
|
+
limit: int = dependencies.LimitBody(),
|
51
|
+
block_documents: Optional[schemas.filters.BlockDocumentFilter] = None,
|
52
|
+
block_types: Optional[schemas.filters.BlockTypeFilter] = None,
|
53
|
+
block_schemas: Optional[schemas.filters.BlockSchemaFilter] = None,
|
54
|
+
include_secrets: bool = Body(
|
55
|
+
False, description="Whether to include sensitive values in the block document."
|
56
|
+
),
|
57
|
+
sort: Optional[schemas.sorting.BlockDocumentSort] = Body(
|
58
|
+
schemas.sorting.BlockDocumentSort.NAME_ASC
|
59
|
+
),
|
60
|
+
offset: int = Body(0, ge=0),
|
61
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
62
|
+
) -> List[schemas.core.BlockDocument]:
|
63
|
+
"""
|
64
|
+
Query for block documents.
|
65
|
+
"""
|
66
|
+
async with db.session_context() as session:
|
67
|
+
result = await models.block_documents.read_block_documents(
|
68
|
+
session=session,
|
69
|
+
block_document_filter=block_documents,
|
70
|
+
block_type_filter=block_types,
|
71
|
+
block_schema_filter=block_schemas,
|
72
|
+
include_secrets=include_secrets,
|
73
|
+
sort=sort,
|
74
|
+
offset=offset,
|
75
|
+
limit=limit,
|
76
|
+
)
|
77
|
+
|
78
|
+
return result
|
79
|
+
|
80
|
+
|
81
|
+
@router.post("/count")
|
82
|
+
async def count_block_documents(
|
83
|
+
block_documents: Optional[schemas.filters.BlockDocumentFilter] = None,
|
84
|
+
block_types: Optional[schemas.filters.BlockTypeFilter] = None,
|
85
|
+
block_schemas: Optional[schemas.filters.BlockSchemaFilter] = None,
|
86
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
87
|
+
) -> int:
|
88
|
+
"""
|
89
|
+
Count block documents.
|
90
|
+
"""
|
91
|
+
async with db.session_context() as session:
|
92
|
+
result = await models.block_documents.count_block_documents(
|
93
|
+
session=session,
|
94
|
+
block_document_filter=block_documents,
|
95
|
+
block_type_filter=block_types,
|
96
|
+
block_schema_filter=block_schemas,
|
97
|
+
)
|
98
|
+
|
99
|
+
return result
|
100
|
+
|
101
|
+
|
102
|
+
@router.get("/{id:uuid}")
|
103
|
+
async def read_block_document_by_id(
|
104
|
+
block_document_id: UUID = Path(
|
105
|
+
..., description="The block document id", alias="id"
|
106
|
+
),
|
107
|
+
include_secrets: bool = Query(
|
108
|
+
False, description="Whether to include sensitive values in the block document."
|
109
|
+
),
|
110
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
111
|
+
) -> schemas.core.BlockDocument:
|
112
|
+
async with db.session_context() as session:
|
113
|
+
block_document = await models.block_documents.read_block_document_by_id(
|
114
|
+
session=session,
|
115
|
+
block_document_id=block_document_id,
|
116
|
+
include_secrets=include_secrets,
|
117
|
+
)
|
118
|
+
if not block_document:
|
119
|
+
raise HTTPException(status.HTTP_404_NOT_FOUND, "Block document not found")
|
120
|
+
return block_document
|
121
|
+
|
122
|
+
|
123
|
+
@router.delete("/{id:uuid}", status_code=status.HTTP_204_NO_CONTENT)
|
124
|
+
async def delete_block_document(
|
125
|
+
block_document_id: UUID = Path(
|
126
|
+
..., description="The block document id", alias="id"
|
127
|
+
),
|
128
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
129
|
+
) -> None:
|
130
|
+
async with db.session_context(begin_transaction=True) as session:
|
131
|
+
result = await models.block_documents.delete_block_document(
|
132
|
+
session=session, block_document_id=block_document_id
|
133
|
+
)
|
134
|
+
if not result:
|
135
|
+
raise HTTPException(
|
136
|
+
status.HTTP_404_NOT_FOUND, detail="Block document not found"
|
137
|
+
)
|
138
|
+
|
139
|
+
|
140
|
+
@router.patch("/{id:uuid}", status_code=status.HTTP_204_NO_CONTENT)
|
141
|
+
async def update_block_document_data(
|
142
|
+
block_document: schemas.actions.BlockDocumentUpdate,
|
143
|
+
block_document_id: UUID = Path(
|
144
|
+
..., description="The block document id", alias="id"
|
145
|
+
),
|
146
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
147
|
+
) -> None:
|
148
|
+
try:
|
149
|
+
async with db.session_context(begin_transaction=True) as session:
|
150
|
+
result = await models.block_documents.update_block_document(
|
151
|
+
session=session,
|
152
|
+
block_document_id=block_document_id,
|
153
|
+
block_document=block_document,
|
154
|
+
)
|
155
|
+
except ValueError as exc:
|
156
|
+
raise HTTPException(
|
157
|
+
status_code=status.HTTP_400_BAD_REQUEST,
|
158
|
+
detail=str(exc),
|
159
|
+
)
|
160
|
+
|
161
|
+
if not result:
|
162
|
+
raise HTTPException(
|
163
|
+
status.HTTP_404_NOT_FOUND, detail="Block document not found"
|
164
|
+
)
|
@@ -0,0 +1,153 @@
|
|
1
|
+
"""
|
2
|
+
Routes for interacting with block schema objects.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from typing import List, Optional
|
6
|
+
from uuid import UUID
|
7
|
+
|
8
|
+
from fastapi import (
|
9
|
+
Body,
|
10
|
+
Depends,
|
11
|
+
HTTPException,
|
12
|
+
Path,
|
13
|
+
Query,
|
14
|
+
Response,
|
15
|
+
status,
|
16
|
+
)
|
17
|
+
|
18
|
+
from prefect.server import models, schemas
|
19
|
+
from prefect.server.api import dependencies
|
20
|
+
from prefect.server.database import PrefectDBInterface, provide_database_interface
|
21
|
+
from prefect.server.models.block_schemas import MissingBlockTypeException
|
22
|
+
from prefect.server.utilities.server import PrefectRouter
|
23
|
+
|
24
|
+
router: PrefectRouter = PrefectRouter(prefix="/block_schemas", tags=["Block schemas"])
|
25
|
+
|
26
|
+
|
27
|
+
@router.post("/", status_code=status.HTTP_201_CREATED)
|
28
|
+
async def create_block_schema(
|
29
|
+
block_schema: schemas.actions.BlockSchemaCreate,
|
30
|
+
response: Response,
|
31
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
32
|
+
) -> schemas.core.BlockSchema:
|
33
|
+
from prefect.blocks.core import Block
|
34
|
+
|
35
|
+
async with db.session_context(begin_transaction=True) as session:
|
36
|
+
block_type = await models.block_types.read_block_type(
|
37
|
+
session=session, block_type_id=block_schema.block_type_id
|
38
|
+
)
|
39
|
+
if block_type is None:
|
40
|
+
raise HTTPException(
|
41
|
+
status.HTTP_404_NOT_FOUND,
|
42
|
+
detail=f"Block type {block_schema.block_type_id} not found.",
|
43
|
+
)
|
44
|
+
|
45
|
+
block_schema_checksum = Block._calculate_schema_checksum(block_schema.fields)
|
46
|
+
existing_block_schema = (
|
47
|
+
await models.block_schemas.read_block_schema_by_checksum(
|
48
|
+
session=session,
|
49
|
+
checksum=block_schema_checksum,
|
50
|
+
version=block_schema.version,
|
51
|
+
)
|
52
|
+
)
|
53
|
+
if existing_block_schema:
|
54
|
+
response.status_code = status.HTTP_200_OK
|
55
|
+
return existing_block_schema
|
56
|
+
try:
|
57
|
+
model = await models.block_schemas.create_block_schema(
|
58
|
+
session=session,
|
59
|
+
block_schema=block_schema,
|
60
|
+
)
|
61
|
+
except MissingBlockTypeException as ex:
|
62
|
+
raise HTTPException(status.HTTP_409_CONFLICT, detail=str(ex))
|
63
|
+
|
64
|
+
return model
|
65
|
+
|
66
|
+
|
67
|
+
@router.delete("/{id}", status_code=status.HTTP_204_NO_CONTENT)
|
68
|
+
async def delete_block_schema(
|
69
|
+
block_schema_id: UUID = Path(..., description="The block schema id", alias="id"),
|
70
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
71
|
+
api_version: str = Depends(dependencies.provide_request_api_version),
|
72
|
+
) -> None:
|
73
|
+
"""
|
74
|
+
Delete a block schema by id.
|
75
|
+
"""
|
76
|
+
async with db.session_context(begin_transaction=True) as session:
|
77
|
+
block_schema = await models.block_schemas.read_block_schema(
|
78
|
+
session=session, block_schema_id=block_schema_id
|
79
|
+
)
|
80
|
+
if not block_schema:
|
81
|
+
raise HTTPException(
|
82
|
+
status_code=status.HTTP_404_NOT_FOUND, detail="Block schema not found"
|
83
|
+
)
|
84
|
+
|
85
|
+
if block_schema.block_type.is_protected:
|
86
|
+
raise HTTPException(
|
87
|
+
status.HTTP_403_FORBIDDEN,
|
88
|
+
detail="Block schemas for protected block types cannot be deleted.",
|
89
|
+
)
|
90
|
+
|
91
|
+
await models.block_schemas.delete_block_schema(
|
92
|
+
session=session, block_schema_id=block_schema_id
|
93
|
+
)
|
94
|
+
|
95
|
+
|
96
|
+
@router.post("/filter")
|
97
|
+
async def read_block_schemas(
|
98
|
+
block_schemas: Optional[schemas.filters.BlockSchemaFilter] = None,
|
99
|
+
limit: int = dependencies.LimitBody(),
|
100
|
+
offset: int = Body(0, ge=0),
|
101
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
102
|
+
) -> List[schemas.core.BlockSchema]:
|
103
|
+
"""
|
104
|
+
Read all block schemas, optionally filtered by type
|
105
|
+
"""
|
106
|
+
async with db.session_context() as session:
|
107
|
+
result = await models.block_schemas.read_block_schemas(
|
108
|
+
session=session,
|
109
|
+
block_schema_filter=block_schemas,
|
110
|
+
limit=limit,
|
111
|
+
offset=offset,
|
112
|
+
)
|
113
|
+
return result
|
114
|
+
|
115
|
+
|
116
|
+
@router.get("/{id}")
|
117
|
+
async def read_block_schema_by_id(
|
118
|
+
block_schema_id: UUID = Path(..., description="The block schema id", alias="id"),
|
119
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
120
|
+
) -> schemas.core.BlockSchema:
|
121
|
+
"""
|
122
|
+
Get a block schema by id.
|
123
|
+
"""
|
124
|
+
async with db.session_context() as session:
|
125
|
+
block_schema = await models.block_schemas.read_block_schema(
|
126
|
+
session=session, block_schema_id=block_schema_id
|
127
|
+
)
|
128
|
+
if not block_schema:
|
129
|
+
raise HTTPException(status.HTTP_404_NOT_FOUND, detail="Block schema not found")
|
130
|
+
return block_schema
|
131
|
+
|
132
|
+
|
133
|
+
@router.get("/checksum/{checksum}")
|
134
|
+
async def read_block_schema_by_checksum(
|
135
|
+
block_schema_checksum: str = Path(
|
136
|
+
..., description="The block schema checksum", alias="checksum"
|
137
|
+
),
|
138
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
139
|
+
version: Optional[str] = Query(
|
140
|
+
None,
|
141
|
+
description=(
|
142
|
+
"Version of block schema. If not provided the most recently created block"
|
143
|
+
" schema with the matching checksum will be returned."
|
144
|
+
),
|
145
|
+
),
|
146
|
+
) -> schemas.core.BlockSchema:
|
147
|
+
async with db.session_context() as session:
|
148
|
+
block_schema = await models.block_schemas.read_block_schema_by_checksum(
|
149
|
+
session=session, checksum=block_schema_checksum, version=version
|
150
|
+
)
|
151
|
+
if not block_schema:
|
152
|
+
raise HTTPException(status.HTTP_404_NOT_FOUND, detail="Block schema not found")
|
153
|
+
return block_schema
|
@@ -0,0 +1,211 @@
|
|
1
|
+
from typing import List, Optional
|
2
|
+
from uuid import UUID
|
3
|
+
|
4
|
+
import sqlalchemy as sa
|
5
|
+
from fastapi import Body, Depends, HTTPException, Path, Query, status
|
6
|
+
|
7
|
+
from prefect.blocks.core import _should_update_block_type
|
8
|
+
from prefect.server import models, schemas
|
9
|
+
from prefect.server.api import dependencies
|
10
|
+
from prefect.server.database import PrefectDBInterface, provide_database_interface
|
11
|
+
from prefect.server.utilities.server import PrefectRouter
|
12
|
+
|
13
|
+
router: PrefectRouter = PrefectRouter(prefix="/block_types", tags=["Block types"])
|
14
|
+
|
15
|
+
|
16
|
+
@router.post("/", status_code=status.HTTP_201_CREATED)
|
17
|
+
async def create_block_type(
|
18
|
+
block_type: schemas.actions.BlockTypeCreate,
|
19
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
20
|
+
) -> schemas.core.BlockType:
|
21
|
+
"""
|
22
|
+
Create a new block type
|
23
|
+
"""
|
24
|
+
# API-created blocks cannot start with the word "Prefect"
|
25
|
+
# as it is reserved for system use
|
26
|
+
if block_type.name.lower().startswith("prefect"):
|
27
|
+
raise HTTPException(
|
28
|
+
status.HTTP_403_FORBIDDEN,
|
29
|
+
detail="Block type names beginning with 'Prefect' are reserved.",
|
30
|
+
)
|
31
|
+
try:
|
32
|
+
async with db.session_context(begin_transaction=True) as session:
|
33
|
+
created_block_type = await models.block_types.create_block_type(
|
34
|
+
session, block_type=block_type
|
35
|
+
)
|
36
|
+
except sa.exc.IntegrityError:
|
37
|
+
raise HTTPException(
|
38
|
+
status.HTTP_409_CONFLICT,
|
39
|
+
detail=f'Block type with name "{block_type.name}" already exists',
|
40
|
+
)
|
41
|
+
return created_block_type
|
42
|
+
|
43
|
+
|
44
|
+
@router.get("/{id}")
|
45
|
+
async def read_block_type_by_id(
|
46
|
+
block_type_id: UUID = Path(..., description="The block type ID", alias="id"),
|
47
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
48
|
+
) -> schemas.core.BlockType:
|
49
|
+
"""
|
50
|
+
Get a block type by ID.
|
51
|
+
"""
|
52
|
+
async with db.session_context() as session:
|
53
|
+
block_type = await models.block_types.read_block_type(
|
54
|
+
session=session, block_type_id=block_type_id
|
55
|
+
)
|
56
|
+
if not block_type:
|
57
|
+
raise HTTPException(status.HTTP_404_NOT_FOUND, detail="Block type not found")
|
58
|
+
return block_type
|
59
|
+
|
60
|
+
|
61
|
+
@router.get("/slug/{slug}")
|
62
|
+
async def read_block_type_by_slug(
|
63
|
+
block_type_slug: str = Path(..., description="The block type name", alias="slug"),
|
64
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
65
|
+
) -> schemas.core.BlockType:
|
66
|
+
"""
|
67
|
+
Get a block type by name.
|
68
|
+
"""
|
69
|
+
async with db.session_context() as session:
|
70
|
+
block_type = await models.block_types.read_block_type_by_slug(
|
71
|
+
session=session, block_type_slug=block_type_slug
|
72
|
+
)
|
73
|
+
if not block_type:
|
74
|
+
raise HTTPException(status.HTTP_404_NOT_FOUND, detail="Block type not found")
|
75
|
+
return block_type
|
76
|
+
|
77
|
+
|
78
|
+
@router.post("/filter")
|
79
|
+
async def read_block_types(
|
80
|
+
block_types: Optional[schemas.filters.BlockTypeFilter] = None,
|
81
|
+
block_schemas: Optional[schemas.filters.BlockSchemaFilter] = None,
|
82
|
+
limit: int = dependencies.LimitBody(),
|
83
|
+
offset: int = Body(0, ge=0),
|
84
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
85
|
+
) -> List[schemas.core.BlockType]:
|
86
|
+
"""
|
87
|
+
Gets all block types. Optionally limit return with limit and offset.
|
88
|
+
"""
|
89
|
+
async with db.session_context() as session:
|
90
|
+
return await models.block_types.read_block_types(
|
91
|
+
session=session,
|
92
|
+
limit=limit,
|
93
|
+
offset=offset,
|
94
|
+
block_type_filter=block_types,
|
95
|
+
block_schema_filter=block_schemas,
|
96
|
+
)
|
97
|
+
|
98
|
+
|
99
|
+
@router.patch("/{id}", status_code=status.HTTP_204_NO_CONTENT)
|
100
|
+
async def update_block_type(
|
101
|
+
block_type: schemas.actions.BlockTypeUpdate,
|
102
|
+
block_type_id: UUID = Path(..., description="The block type ID", alias="id"),
|
103
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
104
|
+
) -> None:
|
105
|
+
"""
|
106
|
+
Update a block type.
|
107
|
+
"""
|
108
|
+
async with db.session_context(begin_transaction=True) as session:
|
109
|
+
db_block_type = await models.block_types.read_block_type(
|
110
|
+
session=session, block_type_id=block_type_id
|
111
|
+
)
|
112
|
+
if db_block_type is None:
|
113
|
+
raise HTTPException(
|
114
|
+
status.HTTP_404_NOT_FOUND, detail="Block type not found"
|
115
|
+
)
|
116
|
+
|
117
|
+
# Only update the block type if there is any meaningful changes.
|
118
|
+
# This avoids deadlocks when creating multiple blocks of the same type.
|
119
|
+
# This check happens client side, but we do it server side as well
|
120
|
+
# to accommodate older clients.
|
121
|
+
if _should_update_block_type(
|
122
|
+
block_type,
|
123
|
+
schemas.core.BlockType.model_validate(db_block_type, from_attributes=True),
|
124
|
+
):
|
125
|
+
await models.block_types.update_block_type(
|
126
|
+
session=session, block_type=block_type, block_type_id=block_type_id
|
127
|
+
)
|
128
|
+
|
129
|
+
|
130
|
+
@router.delete("/{id}", status_code=status.HTTP_204_NO_CONTENT)
|
131
|
+
async def delete_block_type(
|
132
|
+
block_type_id: UUID = Path(..., description="The block type ID", alias="id"),
|
133
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
134
|
+
) -> None:
|
135
|
+
async with db.session_context(begin_transaction=True) as session:
|
136
|
+
db_block_type = await models.block_types.read_block_type(
|
137
|
+
session=session, block_type_id=block_type_id
|
138
|
+
)
|
139
|
+
if db_block_type is None:
|
140
|
+
raise HTTPException(
|
141
|
+
status_code=status.HTTP_404_NOT_FOUND, detail="Block type not found"
|
142
|
+
)
|
143
|
+
elif db_block_type.is_protected:
|
144
|
+
raise HTTPException(
|
145
|
+
status.HTTP_403_FORBIDDEN,
|
146
|
+
detail="protected block types cannot be deleted.",
|
147
|
+
)
|
148
|
+
await models.block_types.delete_block_type(
|
149
|
+
session=session, block_type_id=block_type_id
|
150
|
+
)
|
151
|
+
|
152
|
+
|
153
|
+
@router.get("/slug/{slug}/block_documents", tags=router.tags + ["Block documents"])
|
154
|
+
async def read_block_documents_for_block_type(
|
155
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
156
|
+
block_type_slug: str = Path(..., description="The block type name", alias="slug"),
|
157
|
+
include_secrets: bool = Query(
|
158
|
+
False, description="Whether to include sensitive values in the block document."
|
159
|
+
),
|
160
|
+
) -> List[schemas.core.BlockDocument]:
|
161
|
+
async with db.session_context() as session:
|
162
|
+
block_type = await models.block_types.read_block_type_by_slug(
|
163
|
+
session=session, block_type_slug=block_type_slug
|
164
|
+
)
|
165
|
+
if not block_type:
|
166
|
+
raise HTTPException(
|
167
|
+
status.HTTP_404_NOT_FOUND, detail="Block type not found"
|
168
|
+
)
|
169
|
+
return await models.block_documents.read_block_documents(
|
170
|
+
session=session,
|
171
|
+
block_document_filter=schemas.filters.BlockDocumentFilter(
|
172
|
+
block_type_id=dict(any_=[block_type.id])
|
173
|
+
),
|
174
|
+
include_secrets=include_secrets,
|
175
|
+
)
|
176
|
+
|
177
|
+
|
178
|
+
@router.get(
|
179
|
+
"/slug/{slug}/block_documents/name/{block_document_name}",
|
180
|
+
tags=router.tags + ["Block documents"],
|
181
|
+
)
|
182
|
+
async def read_block_document_by_name_for_block_type(
|
183
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
184
|
+
block_type_slug: str = Path(..., description="The block type name", alias="slug"),
|
185
|
+
block_document_name: str = Path(..., description="The block type name"),
|
186
|
+
include_secrets: bool = Query(
|
187
|
+
False, description="Whether to include sensitive values in the block document."
|
188
|
+
),
|
189
|
+
) -> schemas.core.BlockDocument:
|
190
|
+
async with db.session_context() as session:
|
191
|
+
block_document = await models.block_documents.read_block_document_by_name(
|
192
|
+
session=session,
|
193
|
+
block_type_slug=block_type_slug,
|
194
|
+
name=block_document_name,
|
195
|
+
include_secrets=include_secrets,
|
196
|
+
)
|
197
|
+
if not block_document:
|
198
|
+
raise HTTPException(
|
199
|
+
status.HTTP_404_NOT_FOUND, detail="Block document not found"
|
200
|
+
)
|
201
|
+
return block_document
|
202
|
+
|
203
|
+
|
204
|
+
@router.post("/install_system_block_types")
|
205
|
+
async def install_system_block_types(
|
206
|
+
db: PrefectDBInterface = Depends(provide_database_interface),
|
207
|
+
) -> None:
|
208
|
+
# Don't begin a transaction. _install_protected_system_blocks will manage
|
209
|
+
# the transactions.
|
210
|
+
async with db.session_context(begin_transaction=False) as session:
|
211
|
+
await models.block_registration._install_protected_system_blocks(session)
|