Coverage for src/c41811/config/basic/sequence.py: 100%

105 statements  

« prev     ^ index     » next       coverage.py v7.15.0, created at 2026-07-04 11:16 +0000

1# cython: language_level = 3 # noqa: ERA001 

2 

3 

4""" 

5序列类型配置数据实现 

6 

7.. versionadded:: 0.2.0 

8""" 

9 

10import operator 

11from collections.abc import Iterable 

12from collections.abc import Iterator 

13from collections.abc import MutableSequence 

14from collections.abc import Sequence 

15from typing import Any 

16from typing import Literal 

17from typing import Self 

18from typing import cast 

19from typing import override 

20 

21from ._generate_operators import generate 

22from ._generate_operators import operate 

23from .core import BasicIndexedConfigData 

24from .core import BasicSingleConfigData 

25from .utils import check_read_only 

26 

27 

28@generate 

29class SequenceConfigData[D: Sequence[Any]](BasicIndexedConfigData[D], MutableSequence[Any]): 

30 """ 

31 序列配置数据 

32 

33 .. versionadded:: 0.1.5 

34 """ 

35 

36 _data: D 

37 data: D 

38 

39 def __init__(self, data: D | None = None): # type: ignore[var-annotated] # mypy抽风 

40 """ 

41 :param data: 序列数据 

42 :type data: D | None 

43 """ # noqa: D205 

44 if data is None: 

45 data = [] 

46 if not isinstance(data, Sequence): 

47 msg = f"must be sequence, not {type(data).__name__}" 

48 raise TypeError(msg) 

49 super().__init__(cast(D, data)) 

50 

51 @property 

52 @override 

53 def data_read_only(self) -> bool: 

54 return not isinstance(self._data, MutableSequence) 

55 

56 @override 

57 @check_read_only 

58 def append(self, value: Any) -> None: 

59 self._data.append(value) # type: ignore[attr-defined] 

60 

61 @override 

62 @check_read_only 

63 def insert(self, index: int, value: Any) -> None: 

64 self._data.insert(index, value) # type: ignore[attr-defined] 

65 

66 @override 

67 @check_read_only 

68 def extend(self, values: Iterable[Any]) -> None: 

69 self._data.extend(values) # type: ignore[attr-defined] 

70 

71 @override 

72 def index(self, *args: Any) -> int: 

73 return self._data.index(*args) 

74 

75 @override 

76 def count(self, value: Any) -> int: 

77 return self._data.count(value) 

78 

79 @override 

80 @check_read_only 

81 def pop(self, index: int = -1) -> Any: 

82 return self._data.pop(index) # type: ignore[attr-defined] 

83 

84 @override 

85 @check_read_only 

86 def remove(self, value: Any) -> None: 

87 self._data.remove(value) # type: ignore[attr-defined] 

88 

89 @override 

90 @check_read_only 

91 def clear(self) -> None: 

92 self._data.clear() # type: ignore[attr-defined] 

93 

94 @override 

95 @check_read_only 

96 def reverse(self) -> None: 

97 self._data.reverse() # type: ignore[attr-defined] 

98 

99 @override 

100 def __reversed__(self) -> Iterator[D]: 

101 return reversed(self._data) 

102 

103 @operate(operator.mul, operator.imul) 

104 def __mul__(self, other: Any) -> Self: # type: ignore[empty-body] 

105 ... 

106 

107 @operate(operator.add, operator.iadd) 

108 def __add__(self, other: Any) -> Self: # type: ignore[empty-body] 

109 ... 

110 

111 def __rmul__(self, other: Any) -> Self: # type: ignore[empty-body] 

112 ... 

113 

114 def __radd__(self, other: Any) -> Self: # type: ignore[empty-body] 

115 ... 

116 

117 

118@generate 

119class StringConfigData[D: str | bytes](BasicSingleConfigData[D]): 

120 """字符/字节串配置数据""" 

121 

122 _data: D 

123 

124 def __init__(self, data: D | None = None): 

125 """ 

126 :param data: 配置数据 

127 :type data: D | None 

128 """ # noqa: D205 

129 if data is None: 

130 data = "" 

131 if not isinstance(data, str | bytes): 

132 msg = f"must be str or bytes, not {type(data).__name__}" 

133 raise TypeError(msg) 

134 super().__init__(cast(D, data)) 

135 

136 @property 

137 @override 

138 def data_read_only(self) -> Literal[False]: 

139 """ 

140 配置数据是否为只读 

141 

142 :return: 配置数据是否为只读 

143 :rtype: Literal[False] 

144 

145 .. note:: 

146 该配置数据类始终认为配置数据非只读,使其能正确作为配置数据容器使用 

147 """ # noqa: RUF002 

148 return False 

149 

150 @property # type: ignore[explicit-override] # mypy抽风 

151 @override 

152 def data(self) -> D: 

153 """ 

154 配置的原始数据 

155 

156 .. caution:: 

157 未默认做深拷贝,可能导致非预期的行为 

158 

159 .. versionchanged:: 0.3.0 

160 现在是可写属性 

161 """ # noqa: RUF002 

162 return self._data 

163 

164 @data.setter 

165 def data(self, data: D) -> None: 

166 self._data = data 

167 

168 @override 

169 def __format__(self, format_spec: str) -> str: 

170 return self._data.__format__(format_spec) 

171 

172 @operate(operator.add, operator.iadd) 

173 def __add__(self, other: Any) -> Self: # type: ignore[empty-body] 

174 ... 

175 

176 @operate(operator.mul, operator.imul) 

177 def __mul__(self, other: Any) -> Self: # type: ignore[empty-body] 

178 ... 

179 

180 def __contains__(self, key: Any) -> bool: 

181 return key in self._data 

182 

183 def __iter__(self) -> Iterator[D]: 

184 return iter(cast(Iterable[D], self._data)) 

185 

186 def __len__(self) -> int: 

187 return len(self._data) 

188 

189 def __getitem__(self, item: Any) -> D: 

190 return cast(D, self._data[item]) 

191 

192 @check_read_only 

193 def __setitem__(self, key: Any, value: D) -> None: 

194 self._data[key] = value # type: ignore[index] 

195 

196 @check_read_only 

197 def __delitem__(self, key: Any) -> None: 

198 del self._data[key] # type: ignore[union-attr] 

199 

200 def __reversed__(self) -> Any: # 不支持reversed[D]语法 

201 return reversed(self._data) 

202 

203 

204__all__ = ( 

205 "SequenceConfigData", 

206 "StringConfigData", 

207)