Skip to content

Commit

Permalink
Merge branch 'pydantic-v2-migration'
Browse files Browse the repository at this point in the history
  • Loading branch information
bkis committed Aug 22, 2023
2 parents 28d3e30 + bc68d9f commit 8c26798
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 39 deletions.
41 changes: 31 additions & 10 deletions Tekst-API/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -1775,7 +1775,7 @@
"units"
],
"summary": "Find units",
"description": "Returns a list of all data layer units matching the given criteria.\n\nAs the resulting list may contain units of different types, the\nreturned unit objects cannot be typed to their precise layer unit type.",
"description": "Returns a list of all data layer units matching the given criteria.\n\nRespects restricted layers and inactive texts.\nAs the resulting list may contain units of different types, the\nreturned unit objects cannot be typed to their precise layer unit type.",
"operationId": "findUnits",
"security": [
{
Expand Down Expand Up @@ -3181,10 +3181,17 @@
"example": "5eb7cf5a86d9755df3a6c593"
},
"parentId": {
"type": "string",
"anyOf": [
{
"type": "string",
"example": "5eb7cf5a86d9755df3a6c593"
},
{
"type": "null"
}
],
"title": "Parentid",
"description": "ID of parent node",
"example": "5eb7cf5a86d9755df3a6c593"
"description": "ID of parent node"
},
"level": {
"type": "integer",
Expand Down Expand Up @@ -3246,10 +3253,17 @@
"example": "5eb7cf5a86d9755df3a6c593"
},
"parentId": {
"type": "string",
"anyOf": [
{
"type": "string",
"example": "5eb7cf5a86d9755df3a6c593"
},
{
"type": "null"
}
],
"title": "Parentid",
"description": "ID of parent node",
"example": "5eb7cf5a86d9755df3a6c593"
"description": "ID of parent node"
},
"level": {
"type": "integer",
Expand Down Expand Up @@ -3307,9 +3321,16 @@
"example": "5eb7cf5a86d9755df3a6c593"
},
"parentId": {
"type": "string",
"title": "Parentid",
"example": "5eb7cf5a86d9755df3a6c593"
"anyOf": [
{
"type": "string",
"example": "5eb7cf5a86d9755df3a6c593"
},
{
"type": "null"
}
],
"title": "Parentid"
},
"level": {
"type": "integer",
Expand Down
32 changes: 18 additions & 14 deletions Tekst-API/tekst/models/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,20 +125,24 @@ class Settings(DocumentBase.Settings):
class Node(ModelBase, ModelFactoryMixin):
"""A node in a text structure (e.g. chapter, paragraph, ...)"""

text_id: PydanticObjectId = Field(
..., description="ID of the text this node belongs to"
)
parent_id: PydanticObjectId = Field(None, description="ID of parent node")
level: Annotated[int, Field(ge=0, lt=32)] = Field(
..., description="Index of structure level this node is on"
)
position: Annotated[int, Field(ge=0)] = Field(
..., description="Position among all text nodes on this level"
)
label: Annotated[str, StringConstraints(min_length=1, max_length=256)] = Field(
..., description="Label for identifying this text node in level context"
)
meta: Metadata | None = Field(None, description="Arbitrary metadata")
text_id: Annotated[
PydanticObjectId, Field(description="ID of the text this node belongs to")
]
parent_id: Annotated[
PydanticObjectId | None, Field(description="ID of parent node")
] = None
level: Annotated[
int, Field(ge=0, lt=32, description="Index of structure level this node is on")
]
position: Annotated[
int, Field(ge=0, description="Position among all text nodes on this level")
]
label: Annotated[
str,
StringConstraints(min_length=1, max_length=256),
Field(description="Label for identifying this text node in level context"),
]
meta: Annotated[Metadata | None, Field(description="Arbitrary metadata")] = None


class NodeDocument(Node, DocumentBase):
Expand Down
18 changes: 12 additions & 6 deletions Tekst-API/tekst/routers/layers.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Annotated

from beanie import PydanticObjectId
from beanie.operators import In
from fastapi import APIRouter, HTTPException, Path, Query, status

from tekst.auth import OptionalUserDep, UserDep
Expand All @@ -16,11 +17,9 @@ async def get_layer(
id: PydanticObjectId, user: OptionalUserDep
) -> layer_read_model:
"""A generic route for reading a layer definition from the database"""
layer_doc = (
await layer_document_model.find(layer_document_model.id == id)
.find(layer_document_model.allowed_to_read(user))
.first_or_none()
)
layer_doc = await layer_document_model.find(
layer_document_model.id == id, layer_document_model.allowed_to_read(user)
).first_or_none()
if not layer_doc:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
Expand Down Expand Up @@ -167,9 +166,16 @@ async def find_layers(
if layer_type:
example["layer_type"] = layer_type

active_texts = await TextDocument.find(
TextDocument.is_active == True # noqa: E712
).to_list()

layer_docs = (
await LayerBaseDocument.find(example, with_children=True)
.find(LayerBaseDocument.allowed_to_read(user))
.find(
LayerBaseDocument.allowed_to_read(user),
In(LayerBaseDocument.text_id, [text.id for text in active_texts]),
)
.limit(limit)
.to_list()
)
Expand Down
26 changes: 17 additions & 9 deletions Tekst-API/tekst/routers/units.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from tekst.auth import OptionalUserDep, UserDep
from tekst.layer_types import layer_type_manager
from tekst.models.layer import LayerBaseDocument
from tekst.models.text import TextDocument
from tekst.models.unit import UnitBase, UnitBaseDocument


Expand Down Expand Up @@ -55,9 +56,10 @@ async def create_unit(unit: unit_create_model, user: UserDep) -> unit_read_model
status_code=status.HTTP_401_UNAUTHORIZED,
detail="No write access for units belonging to this layer",
)
dupes_criteria = {"layerId": True, "nodeId": True}
# check for duplicates
if await unit_document_model.find(
unit.model_dump(include=dupes_criteria)
UnitDocumentModel.layer_id == unit.layer_id,
UnitDocumentModel.node_id == unit.node_id,
).first_or_none():
raise HTTPException(
status_code=status.HTTP_409_CONFLICT,
Expand Down Expand Up @@ -169,14 +171,14 @@ async def update_unit(
@router.get("/", response_model=list[dict], status_code=status.HTTP_200_OK)
async def find_units(
user: OptionalUserDep,
layer_id: Annotated[
layer_ids: Annotated[
list[PydanticObjectId],
Query(
alias="layerId",
description="ID (or list of IDs) of layer(s) to return unit data for",
),
] = [],
node_id: Annotated[
node_ids: Annotated[
list[PydanticObjectId],
Query(
alias="nodeId",
Expand All @@ -188,20 +190,26 @@ async def find_units(
"""
Returns a list of all data layer units matching the given criteria.
Respects restricted layers and inactive texts.
As the resulting list may contain units of different types, the
returned unit objects cannot be typed to their precise layer unit type.
"""

active_texts = await TextDocument.find(
TextDocument.is_active == True # noqa: E712
).to_list()

readable_layers = await LayerBaseDocument.find(
LayerBaseDocument.allowed_to_read(user), with_children=True
LayerBaseDocument.allowed_to_read(user),
In(LayerBaseDocument.text_id, [text.id for text in active_texts]),
with_children=True,
).to_list()
readable_layer_ids = [layer.id for layer in readable_layers]

units = (
await UnitBaseDocument.find(
In(UnitBaseDocument.layer_id, layer_id) if layer_id else {},
In(UnitBaseDocument.node_id, node_id) if node_id else {},
In(UnitBaseDocument.layer_id, readable_layer_ids),
In(UnitBaseDocument.layer_id, layer_ids) if layer_ids else {},
In(UnitBaseDocument.node_id, node_ids) if node_ids else {},
In(UnitBaseDocument.layer_id, [layer.id for layer in readable_layers]),
with_children=True,
)
.limit(limit)
Expand Down

0 comments on commit 8c26798

Please sign in to comment.