Skip to content

Commit

Permalink
feat: implement result ordering by model fields
Browse files Browse the repository at this point in the history
Concerns #171.
  • Loading branch information
lu-pl committed Feb 6, 2025
1 parent 87bffd1 commit 5490035
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 7 deletions.
17 changes: 13 additions & 4 deletions rdfproxy/constructor.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ def __init__(
self.group_by: str | None = self.bindings_map.get(
model.model_config.get("group_by")
)
self.order_by: str | None = self.bindings_map.get(query_parameters.order_by)

print("DEBUG: ", self.order_by)

def get_items_query(self) -> str:
"""Construct a SPARQL items query for use in rdfproxy.SPARQLModelAdapter."""
Expand Down Expand Up @@ -118,7 +121,13 @@ def _compute_select_clause(self):
return f"select distinct ?{self.group_by}"

def _compute_order_by_value(self):
"""Stub: Only basic logic for now."""
if self.group_by is None:
return get_query_projection(self.query)[0]
return f"{self.group_by}"
"""Compute a value for ORDER BY used in RDFProxy query modification."""
match (self.group_by, self.order_by):
case None, None:
return f"?{get_query_projection(self.query)[0]}"
case group_by, None:
return f"?{group_by}"
case _, order_by:
return f"{'DESC' if self.query_parameters.desc else 'ASC'}(?{order_by})"
case _: # pragma: no cover
assert False, "Unreachable case in _compute_order_by_value"
36 changes: 33 additions & 3 deletions rdfproxy/utils/models.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
"""Pydantic Model definitions for rdfproxy."""

from typing import Generic
from enum import StrEnum, auto
from typing import Any, Generic, get_origin

from pydantic import BaseModel, Field
from pydantic import BaseModel, Field, model_validator
from pydantic.fields import FieldInfo
from rdfproxy.utils._types import _TModelInstance


Expand All @@ -23,11 +25,39 @@ class Page(BaseModel, Generic[_TModelInstance]):
pages: int


class QueryParameters(BaseModel):
class QueryParameters(
BaseModel,
Generic[_TModelInstance],
):
"""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)

order_by: str | None = Field(default=None)
desc: bool = Field(default=False)

@model_validator(mode="after")
@classmethod
def _check_desc_order_by_dependency(cls, data: Any) -> Any:
"""Check the dependency of desc on order_by."""
_desc_defined, _order_by_defined = data.desc, data.order_by

if _desc_defined and not _order_by_defined:
raise ValueError("Field 'desc' requires on Field 'order_by'.")
return data

def __class_getitem__(cls, model: type[_TModelInstance]):
_order_by_fields = [
(k, auto())
for k, v in model.model_fields.items()
if get_origin(v.annotation) is not list
]

OrderByEnum = StrEnum("OrderByEnum", _order_by_fields)
cls.model_fields["order_by"] = FieldInfo(annotation=OrderByEnum, default=None)

return cls

0 comments on commit 5490035

Please sign in to comment.