Skip to content

Commit 100c226

Browse files
Leverage aiida-core pydantic models
1 parent a88c360 commit 100c226

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2059
-1200
lines changed

aiida_restapi/common/pagination.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""Pagination utilities."""
2+
3+
from __future__ import annotations
4+
5+
import typing as t
6+
7+
import pydantic as pdt
8+
from aiida.orm import Entity
9+
10+
ResultType = t.TypeVar('ResultType', Entity.Model, t.Any)
11+
12+
__all__ = ('PaginatedResults',)
13+
14+
15+
class PaginatedResults(pdt.BaseModel, t.Generic[ResultType]):
16+
total: int
17+
page: int
18+
page_size: int
19+
results: list[ResultType]

aiida_restapi/common/query.py

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
"""REST API query utilities."""
2+
3+
from __future__ import annotations
4+
5+
import json
6+
import typing as t
7+
8+
import pydantic as pdt
9+
from fastapi import HTTPException, Query
10+
11+
12+
class QueryParams(pdt.BaseModel):
13+
filters: dict[str, t.Any] = pdt.Field(
14+
default_factory=dict,
15+
description='AiiDA QueryBuilder filters',
16+
examples=[
17+
{'node_type': {'==': 'data.core.int.Int.'}},
18+
{'attributes.value': {'>': 42}},
19+
],
20+
)
21+
order_by: str | list[str] | dict[str, t.Any] | None = pdt.Field(
22+
None,
23+
description='Fields to sort by',
24+
examples=[
25+
{'attributes.value': 'desc'},
26+
],
27+
)
28+
page_size: pdt.PositiveInt = pdt.Field(
29+
10,
30+
description='Number of results per page',
31+
examples=[10],
32+
)
33+
page: pdt.PositiveInt = pdt.Field(
34+
1,
35+
description='Page number',
36+
examples=[1],
37+
)
38+
39+
40+
def query_params(
41+
filters: str | None = Query(
42+
None,
43+
description='AiiDA QueryBuilder filters as JSON string',
44+
),
45+
order_by: str | None = Query(
46+
None,
47+
description='Comma-separated list of fields to sort by',
48+
),
49+
page_size: pdt.PositiveInt = Query(
50+
10,
51+
description='Number of results per page',
52+
),
53+
page: pdt.PositiveInt = Query(
54+
1,
55+
description='Page number',
56+
),
57+
) -> QueryParams:
58+
"""Parse query parameters into a structured object.
59+
60+
:param filters: AiiDA QueryBuilder filters as JSON string.
61+
:param order_by: Comma-separated string of fields to sort by.
62+
:param page_size: Number of results per page.
63+
:param page: Page number.
64+
:return: Structured query parameters.
65+
:raises HTTPException: If filters cannot be parsed as JSON.
66+
"""
67+
query_filters: dict[str, t.Any] = {}
68+
query_order_by: str | list[str] | dict[str, t.Any] | None = None
69+
if filters:
70+
try:
71+
query_filters = json.loads(filters)
72+
except Exception as exception:
73+
raise HTTPException(
74+
status_code=400,
75+
detail=f'Could not parse filters as JSON: {exception}',
76+
) from exception
77+
if order_by:
78+
try:
79+
query_order_by = json.loads(order_by)
80+
except Exception as exception:
81+
raise HTTPException(
82+
status_code=400,
83+
detail=f'Could not parse order_by as JSON: {exception}',
84+
) from exception
85+
return QueryParams(
86+
filters=query_filters,
87+
order_by=query_order_by,
88+
page_size=page_size,
89+
page=page,
90+
)

aiida_restapi/common/types.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
"""Common type variables."""
2+
3+
from __future__ import annotations
4+
5+
import typing as t
6+
7+
from aiida import orm
8+
9+
EntityType = t.TypeVar('EntityType', bound='orm.Entity')
10+
EntityModelType = t.TypeVar('EntityModelType', bound='orm.Entity.Model')
11+
12+
NodeType = t.TypeVar('NodeType', bound='orm.Node')
13+
NodeModelType = t.TypeVar('NodeModelType', bound='orm.Node.Model')
File renamed without changes.

aiida_restapi/graphql/comments.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import graphene as gr
77
from aiida.orm import Comment
88

9-
from aiida_restapi.filter_syntax import parse_filter_str
9+
from aiida_restapi.graphql.filter_syntax import parse_filter_str
1010

1111
from .orm_factories import (
1212
ENTITY_DICT_TYPE,

aiida_restapi/graphql/computers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import graphene as gr
77
from aiida.orm import Computer
88

9-
from aiida_restapi.filter_syntax import parse_filter_str
9+
from aiida_restapi.graphql.filter_syntax import parse_filter_str
1010
from aiida_restapi.graphql.plugins import QueryPlugin
1111

1212
from .nodes import NodesQuery
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@
1313

1414
from lark import Lark, Token, Tree
1515

16-
from . import static
17-
from .utils import parse_date
16+
from .. import static
17+
from ..utils import parse_date
1818

1919
FILTER_GRAMMAR = resources.open_text(static, 'filter_grammar.lark')
2020

aiida_restapi/graphql/groups.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import graphene as gr
77
from aiida.orm import Group
88

9-
from aiida_restapi.filter_syntax import parse_filter_str
9+
from aiida_restapi.graphql.filter_syntax import parse_filter_str
1010
from aiida_restapi.graphql.nodes import NodesQuery
1111
from aiida_restapi.graphql.plugins import QueryPlugin
1212

aiida_restapi/graphql/logs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import graphene as gr
77
from aiida.orm import Log
88

9-
from aiida_restapi.filter_syntax import parse_filter_str
9+
from aiida_restapi.graphql.filter_syntax import parse_filter_str
1010

1111
from .orm_factories import (
1212
ENTITY_DICT_TYPE,

0 commit comments

Comments
 (0)