11import operator
22from collections .abc import Callable
33from typing import Any
4+ from typing import TypeVarTuple
45
56from scim2_models import AttributeBinding
67from scim2_models import InvalidCursorException
4647from .mapping import ResourceMapping
4748from .mapping import _Collection
4849from .mapping import _Column
50+ from .mapping import _python_type
4951
5052_ORDERINGS : dict [CompareOperator , Callable [[Any , Any ], Any ]] = {
5153 CompareOperator .eq : operator .eq ,
5658}
5759
5860
61+ _Row = TypeVarTuple ("_Row" )
62+
63+
5964def _as_key (column : _Column , value : Any ) -> Any :
6065 """Return an identifier in the type of its column, or None when it cannot have that type."""
61- try :
62- python_type = column .expression .type .python_type
63- except NotImplementedError :
66+ python_type = _python_type (column .expression )
67+ if python_type is None :
6468 return value
6569 try :
6670 return python_type (value )
@@ -381,14 +385,18 @@ def _where(
381385 return _FilterTranslator (mapping , scim_filter , comparator ).visit (scim_filter .ast )
382386
383387
384- def _cursor_page (page : Select [Any ], search_request : SearchRequest [Any ]) -> Select [Any ]:
388+ def _cursor_page (
389+ page : Select [* _Row ], search_request : SearchRequest [Any ]
390+ ) -> Select [* _Row ]:
385391 """Limit a cursor page to count + 1 rows, the last one telling whether a page follows."""
386392 if search_request .count is None :
387393 return page
388394 return page .limit (search_request .count + 1 )
389395
390396
391- def _index_page (page : Select [Any ], search_request : SearchRequest [Any ]) -> Select [Any ]:
397+ def _index_page (
398+ page : Select [* _Row ], search_request : SearchRequest [Any ]
399+ ) -> Select [* _Row ]:
392400 """Limit a page to the records from startIndex, at most count of them."""
393401 page = page .offset (search_request .start_index_0 or 0 )
394402 if search_request .count is None :
@@ -401,7 +409,7 @@ def _search_statements(
401409 search_request : SearchRequest [Any ],
402410 comparator : _Comparator ,
403411 anchor : _Anchor | None = None ,
404- ) -> tuple [Select [tuple [ int ]] , Select [tuple [ Any , Any , str ] ]]:
412+ ) -> tuple [Select [int ], Select [Any , Any , str ]]:
405413 """Return the statement counting the matching records, and the one selecting a page of them.
406414
407415 The page lists each record with its sort value and its identifier as
@@ -443,7 +451,7 @@ def _root_statements(
443451 search_request : SearchRequest [Any ],
444452 comparator : _Comparator ,
445453 anchor : _Anchor | None = None ,
446- ) -> tuple [Select [tuple [ int ]] , Select [tuple [ int , str , Any ] ]]:
454+ ) -> tuple [Select [int ], Select [int , str , Any ]]:
447455 """Return the statement counting the matching records of several mappings, and the one selecting a page of them.
448456
449457 The page lists the position of the mapping, the identifier of each
@@ -496,7 +504,7 @@ def _root_statements(
496504
497505def _records_statement (
498506 mapping : ResourceMapping , ids : list [str ], parameters : ResponseParameters [Any ]
499- ) -> Select [tuple [ str , Any ] ]:
507+ ) -> Select [str , Any ]:
500508 """Return the statement loading the records of a page, each with its identifier as text."""
501509 keys = [_as_key (mapping ._id , value ) for value in ids ]
502510 return (
0 commit comments