Coverage for src/pqlattice/typing/_types_validator.py: 100%

36 statements  

« prev     ^ index     » next       coverage.py v7.11.0, created at 2026-01-12 21:36 +0100

1import logging 

2from collections.abc import Callable 

3from inspect import signature 

4from typing import Any, TypeAliasType, TypeGuard 

5 

6import numpy as np 

7from numpy.typing import NDArray 

8 

9from ._types import Matrix, SquareMatrix, Vector 

10 

11logger = logging.getLogger(__name__) 

12 

13 

14def _is_nparray(obj: Any) -> TypeGuard[NDArray[Any]]: 

15 return isinstance(obj, np.ndarray) 

16 

17 

18def is_Vector(obj: Any) -> TypeGuard[Vector]: 

19 return _is_nparray(obj) and len(obj.shape) == 1 

20 

21 

22def is_Matrix(obj: Any) -> TypeGuard[Matrix]: 

23 return _is_nparray(obj) and len(obj.shape) == 2 

24 

25 

26def is_SquareMatrix(obj: Any) -> TypeGuard[SquareMatrix]: 

27 return is_Matrix(obj) and obj.shape[0] == obj.shape[1] 

28 

29 

30def _get_predicate_for_alias[T: TypeAliasType](type_name: T) -> Callable[[T], bool] | None: 

31 # Bare 

32 if type_name == Vector: 

33 return is_Vector 

34 

35 if type_name == Matrix: 

36 return is_Matrix 

37 

38 if type_name == SquareMatrix: 

39 return is_SquareMatrix 

40 

41 return None 

42 

43 

44def validate_aliases[**P, T](func: Callable[P, T]) -> Callable[P, T]: 

45 def wrapper(*args: P.args, **kwds: P.kwargs) -> T: 

46 sig = signature(func) 

47 bounded_args = sig.bind(*args, **kwds) 

48 bounded_args.apply_defaults() 

49 for arg_name, arg_value in bounded_args.arguments.items(): 

50 if expected_type := func.__annotations__.get(arg_name): # There is a type annotation for the argument 

51 pred = _get_predicate_for_alias(expected_type) 

52 if pred is not None and not pred(arg_value): # type annotations has a predicate to be checked and predicate is not fullfilled 

53 raise TypeError(f"func <{func.__name__}>, arg <{arg_name}> val <{arg_value}> arg's type <{type(arg_value)}> predicate for <{expected_type}> failed") 

54 

55 return func(*args, **kwds) 

56 

57 return wrapper