33
44from fastapi import APIRouter , Depends , HTTPException , Request
55from pydantic import Json , NonNegativeInt , ValidationError
6- from dp3 .common .datatype import primitive_data_types
7-
86
97from dp3 .api .internal .config import DB , MODEL_SPEC , TASK_WRITER
108from dp3 .api .internal .entity_response_models import (
2321from dp3 .api .internal .response_models import ErrorResponse , RequestValidationError , SuccessResponse
2422from dp3 .common .attrspec import AttrType
2523from dp3 .common .datapoint import to_json_friendly
24+ from dp3 .common .datatype import primitive_data_types
2625from dp3 .common .task import DataPointTask , task_context
2726from dp3 .common .types import AwareDatetime
2827from dp3 .database .database import DatabaseError
@@ -132,62 +131,63 @@ def _validate_snapshot_filters(fulltext_filters, generic_filter):
132131 return fulltext_filters , generic_filter
133132
134133
135- def _validate_sort_params (etype : str , sort_by : str | None , sort_order : int | None ) -> tuple [str | None , int ]:
134+ def _validate_sort_params (
135+ etype : str , sort_by : str | None , sort_order : int | None
136+ ) -> tuple [str | None , int ]:
136137 """Validate sorting parameters.
137-
138+
138139 Args:
139140 etype: entity type
140141 sort_by: attribute name to sort by (None for no sorting)
141142 sort_order: 1 for ascending, -1 for descending (default: 1)
142-
143+
143144 Returns:
144145 Tuple of (validated_sort_by, validated_sort_order)
145-
146+
146147 Raises:
147148 RequestValidationError if parameters are invalid
148149 """
149150 if sort_by is None :
150151 if sort_order is not None :
151152 return None , sort_order
152153 return None , 1 # default sorting direction is ascending
153-
154+
154155 if sort_order is None :
155156 sort_order = 1
156-
157+
157158 if sort_order not in (1 , - 1 ):
158159 raise RequestValidationError (
159160 ["query" , "sort_order" ],
160- f"Sort order must be 1 (ascending) or -1 (descending), got { sort_order } "
161+ f"Sort order must be 1 (ascending) or -1 (descending), got { sort_order } " ,
161162 )
162-
163+
163164 entity_attribs = MODEL_SPEC .attribs (etype )
164-
165+
165166 if sort_by not in entity_attribs :
166- raise RequestValidationError (
167- ["query" , "sort_by" ],
168- f"Attribute '{ sort_by } ' doesn't exist"
169- )
170-
167+ raise RequestValidationError (["query" , "sort_by" ], f"Attribute '{ sort_by } ' doesn't exist" )
168+
171169 # get attribute specification
172170 attr_spec = entity_attribs [sort_by ]
173-
171+
174172 # Check if attribute type is supported for sorting
175173 if attr_spec .t not in (AttrType .PLAIN , AttrType .OBSERVATIONS ) and not attr_spec .multi_value :
176174 raise RequestValidationError (
177175 ["query" , "sort_by" ],
178- f"Cannot sort by attribute '{ sort_by } ': only plain and observations attributes with no multi_value are supported"
176+ f"Cannot sort by attribute '{ sort_by } ': "
177+ f"only plain and observations attributes with no multi_value are supported" ,
179178 )
180-
179+
181180 data_type_str = str (attr_spec .data_type )
182181 allowed_primitives = set (primitive_data_types .keys ()) - {"json" }
183182
184183 # only sort primitives types without json
185184 if data_type_str not in allowed_primitives :
186185 raise RequestValidationError (
187186 ["query" , "sort_by" ],
188- f"Cannot sort by attribute '{ sort_by } ': data type '{ data_type_str } ' is not supported for sorting"
187+ f"Cannot sort by attribute '{ sort_by } ': "
188+ f"data type '{ data_type_str } ' is not supported for sorting" ,
189189 )
190-
190+
191191 return sort_by , sort_order
192192
193193
@@ -281,7 +281,7 @@ async def get_entity_type_eids(
281281 There are no attribute name checks (may be added in the future).
282282
283283 Generic and fulltext filters are merged - fulltext overrides conflicting keys.
284-
284+
285285 Sorting is supported for plain and observations attributes with primitive data types
286286 (excluding json and multi_value observations). Use sort_by to specify the attribute
287287 and sort_order (1 for ascending, -1 for descending) to control the direction.
@@ -291,11 +291,11 @@ async def get_entity_type_eids(
291291
292292 try :
293293 cursor = DB .snapshots .find_latest (etype , fulltext_filters , generic_filter )
294-
294+
295295 # Apply sorting if specified
296296 if sort_by :
297297 cursor = cursor .sort ([("last." + sort_by , sort_order )])
298-
298+
299299 cursor_page = cursor .skip (skip ).limit (limit )
300300 except DatabaseError as e :
301301 raise HTTPException (status_code = 400 , detail = str (e )) from e
0 commit comments