Coverage for src/paperap/models/mixins/queryset.py: 64%

25 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-03-20 13:17 -0400

1""" 

2---------------------------------------------------------------------------- 

3 

4 METADATA: 

5 

6 File: queryset.py 

7 Project: paperap 

8 Created: 2025-03-05 

9 Version: 0.0.5 

10 Author: Jess Mann 

11 Email: jess@jmann.me 

12 Copyright (c) 2025 Jess Mann 

13 

14---------------------------------------------------------------------------- 

15 

16 LAST MODIFIED: 

17 

18 2025-03-05 By Jess Mann 

19 

20""" 

21 

22from __future__ import annotations 

23 

24from typing import TYPE_CHECKING, Any, Protocol, Self 

25 

26if TYPE_CHECKING: 

27 from paperap.models.abstract.queryset import BaseQuerySet, StandardQuerySet 

28 

29 

30class QuerySetProtocol(Protocol): 

31 """ 

32 Protocol for querysets. 

33 

34 Used primarily for type hinting. 

35 """ 

36 

37 def all(self) -> Self: ... # pylint: disable=missing-function-docstring 

38 def filter(self, **kwargs: Any) -> Self: ... # pylint: disable=missing-function-docstring 

39 def filter_field_by_str( # pylint: disable=missing-function-docstring 

40 self, field: str, value: str, *, exact: bool = True, case_insensitive: bool = True 

41 ) -> Self: ... 

42 

43 

44class HasDocumentCount(QuerySetProtocol): 

45 """ 

46 Mixin for querysets that have a document_count field. 

47 """ 

48 

49 def document_count(self, count: int) -> Self: 

50 """ 

51 Filter models by document count. 

52 

53 Args: 

54 count: The document count to filter by 

55 

56 Returns: 

57 Filtered QuerySet 

58 

59 """ 

60 return self.filter(document_count=count) 

61 

62 def document_count_over(self, count: int) -> Self: 

63 """ 

64 Filter models by document count greater than a value. 

65 

66 Args: 

67 count: The document count to filter by 

68 

69 Returns: 

70 Filtered QuerySet 

71 

72 """ 

73 return self.filter(document_count__gt=count) 

74 

75 def document_count_under(self, count: int) -> Self: 

76 """ 

77 Filter models by document count less than a value. 

78 

79 Args: 

80 count: The document count to filter by 

81 

82 Returns: 

83 Filtered QuerySet 

84 

85 """ 

86 return self.filter(document_count__lt=count) 

87 

88 def document_count_between(self, lower: int, upper: int) -> Self: 

89 """ 

90 Filter models by document count between two values. 

91 

92 Args: 

93 lower: The lower document count to filter by 

94 upper: The upper document count to filter by 

95 

96 Returns: 

97 Filtered QuerySet 

98 

99 """ 

100 return self.filter(document_count__range=(lower, upper)) 

101 

102 

103class HasOwner(QuerySetProtocol): 

104 """ 

105 Mixin for querysets that have an owner field. 

106 """ 

107 

108 def owner(self, owner: int | list[int] | None) -> Self: 

109 """ 

110 Filter models by owner. 

111 

112 Args: 

113 owner: The owner to filter by 

114 

115 Returns: 

116 Filtered QuerySet 

117 

118 """ 

119 if isinstance(owner, list): 

120 return self.filter(owner__in=owner) 

121 return self.filter(owner=owner) 

122 

123 

124class HasStandard(HasOwner, HasDocumentCount): 

125 """ 

126 Mixin for querysets that have standard fields: owner, document_count, name, slug 

127 """ 

128 

129 def name(self, value: str, *, exact: bool = True, case_insensitive: bool = True) -> Self: 

130 """ 

131 Filter models where name is value 

132 

133 Args: 

134 value (str): The value to compare against 

135 exact (bool): Whether the comparison should be exact 

136 case_sensitive (bool): Whether the comparison should be case insensitive 

137 

138 Returns: 

139 Filtered QuerySet 

140 

141 """ 

142 return self.filter_field_by_str("name", value, exact=exact, case_insensitive=case_insensitive) 

143 

144 def slug(self, value: str, *, exact: bool = True, case_insensitive: bool = True) -> Self: 

145 """ 

146 Filter models where slug is value 

147 

148 Args: 

149 value (str): The value to compare against 

150 exact (bool): Whether the comparison should be exact 

151 case_sensitive (bool): Whether the comparison should be case insensitive 

152 

153 Returns: 

154 Filtered QuerySet 

155 

156 """ 

157 return self.filter_field_by_str("slug", value, exact=exact, case_insensitive=case_insensitive)