Skip to content

Commit

Permalink
feat: use query parameter model for SPARQLModelAdapter.query
Browse files Browse the repository at this point in the history
Using a query parameter model for SPARQLModelAdapter.query has many
advantages, e.g. enhanced OpenAPI/Swagger definitions for FastAPI code
and runtime validation for query parameters.

Also, the query parameter model defines a single extension interface
for query parameters.

Closes #150.
  • Loading branch information
lu-pl authored and kevinstadler committed Dec 2, 2024
1 parent ecd70d7 commit 72a273d
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 14 deletions.
2 changes: 1 addition & 1 deletion rdfproxy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from rdfproxy.adapter import SPARQLModelAdapter # noqa: F401
from rdfproxy.mapper import ModelBindingsMapper # noqa: F401
from rdfproxy.utils._types import SPARQLBinding # noqa: F401
from rdfproxy.utils.models import Page # noqa: F401
from rdfproxy.utils.models import Page, QueryParameters # noqa: F401
25 changes: 13 additions & 12 deletions rdfproxy/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from SPARQLWrapper import JSON, SPARQLWrapper
from rdfproxy.mapper import ModelBindingsMapper
from rdfproxy.utils._types import _TModelInstance
from rdfproxy.utils.models import Page
from rdfproxy.utils.models import Page, QueryParameters
from rdfproxy.utils.sparql_utils import (
calculate_offset,
construct_count_query,
Expand Down Expand Up @@ -42,19 +42,14 @@ def __init__(
)
self.sparql_wrapper.setReturnFormat(JSON)

def query(
self,
*,
page: int = 1,
size: int = 100,
) -> Page[_TModelInstance]:
def query(self, query_parameters: QueryParameters) -> Page[_TModelInstance]:
"""Run a query against an endpoint and return a Page model object."""
count_query: str = construct_count_query(query=self._query, model=self._model)
items_query: str = construct_items_query(
query=self._query,
model=self._model,
limit=size,
offset=calculate_offset(page, size),
limit=query_parameters.size,
offset=calculate_offset(query_parameters.page, query_parameters.size),
)

items_query_bindings: Iterator[dict] = query_with_wrapper(
Expand All @@ -65,9 +60,15 @@ def query(

items: list[_TModelInstance] = mapper.get_models()
total: int = self._get_count(count_query)
pages: int = math.ceil(total / size)

return Page(items=items, page=page, size=size, total=total, pages=pages)
pages: int = math.ceil(total / query_parameters.size)

return Page(
items=items,
page=query_parameters.page,
size=query_parameters.size,
total=total,
pages=pages,
)

def _get_count(self, query: str) -> int:
"""Run a count query and return the count result.
Expand Down
12 changes: 11 additions & 1 deletion rdfproxy/utils/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from typing import Generic

from pydantic import BaseModel
from pydantic import BaseModel, Field
from rdfproxy.utils._types import _TModelInstance


Expand All @@ -21,3 +21,13 @@ class Page(BaseModel, Generic[_TModelInstance]):
size: int
total: int
pages: int


class QueryParameters(BaseModel):
"""Query parameter model for SPARQLModelAdapter.query.
See https://fastapi.tiangolo.com/tutorial/query-param-models/
"""

page: int = Field(default=1, gt=0)
size: int = Field(default=100, ge=1)

0 comments on commit 72a273d

Please sign in to comment.