Coverage for src / lexigram / admin / domain / specifications.py: 0%

36 statements  

« prev     ^ index     » next       coverage.py v7.13.5, created at 2026-08-11 02:25 +0800

1"""Pure-Python specification pattern for admin domain objects.""" 

2 

3from __future__ import annotations 

4 

5from typing import Any, Generic, TypeVar 

6 

7T = TypeVar("T") 

8 

9 

10class SpecificationProtocol(Generic[T]): 

11 """Base specification with combinator support.""" 

12 

13 def is_satisfied_by(self, candidate: T) -> bool: # pragma: no cover 

14 """Return True if *candidate* satisfies this specification.""" 

15 raise NotImplementedError 

16 

17 def __and__(self, other: SpecificationProtocol[T]) -> AndSpec[T]: 

18 return AndSpec(self, other) 

19 

20 def __or__(self, other: SpecificationProtocol[T]) -> OrSpec[T]: 

21 return OrSpec(self, other) 

22 

23 def __invert__(self) -> NotSpec[T]: 

24 return NotSpec(self) 

25 

26 

27class ActiveUserSpec(SpecificationProtocol[Any]): 

28 """Matches candidates whose ``is_active`` attribute is True.""" 

29 

30 def is_satisfied_by(self, candidate: Any) -> bool: 

31 return bool(getattr(candidate, "is_active", False)) 

32 

33 

34class HasRoleSpec(SpecificationProtocol[Any]): 

35 """Matches candidates that have a specific role in their ``roles``.""" 

36 

37 def __init__(self, role: str) -> None: 

38 self._role = role 

39 

40 def is_satisfied_by(self, candidate: Any) -> bool: 

41 roles = getattr(candidate, "roles", []) 

42 return self._role in roles 

43 

44 

45class AndSpec(SpecificationProtocol[T]): 

46 """Logical AND of two specifications.""" 

47 

48 def __init__( 

49 self, left: SpecificationProtocol[T], right: SpecificationProtocol[T] 

50 ) -> None: 

51 self._left = left 

52 self._right = right 

53 

54 def is_satisfied_by(self, candidate: T) -> bool: 

55 return self._left.is_satisfied_by(candidate) and self._right.is_satisfied_by( 

56 candidate 

57 ) 

58 

59 

60class OrSpec(SpecificationProtocol[T]): 

61 """Logical OR of two specifications.""" 

62 

63 def __init__( 

64 self, left: SpecificationProtocol[T], right: SpecificationProtocol[T] 

65 ) -> None: 

66 self._left = left 

67 self._right = right 

68 

69 def is_satisfied_by(self, candidate: T) -> bool: 

70 return self._left.is_satisfied_by(candidate) or self._right.is_satisfied_by( 

71 candidate 

72 ) 

73 

74 

75class NotSpec(SpecificationProtocol[T]): 

76 """Logical NOT of a specification.""" 

77 

78 def __init__(self, spec: SpecificationProtocol[T]) -> None: 

79 self._spec = spec 

80 

81 def is_satisfied_by(self, candidate: T) -> bool: 

82 return not self._spec.is_satisfied_by(candidate)