Coverage for src / c41811 / config / utils.py: 100%

68 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-09 01:06 +0000

1# cython: language_level = 3 # noqa: ERA001 

2 

3""" 

4杂项实用程序 

5 

6.. versionadded:: 0.2.0 

7""" 

8 

9from collections import OrderedDict 

10from collections.abc import Iterator 

11from collections.abc import Mapping 

12from collections.abc import Sequence 

13from copy import deepcopy 

14from functools import wraps 

15from types import NotImplementedType 

16from typing import Any 

17from typing import Self 

18from typing import cast 

19from typing import override 

20 

21 

22def singleton[C: type[Any]](target_cls: C, /) -> C: 

23 """ 

24 单例模式类装饰器 

25 

26 :param target_cls: 目标类 

27 :type target_cls: C 

28 

29 :return: 装饰后的类 

30 :rtype: C 

31 """ 

32 

33 @wraps(target_cls.__new__) 

34 def new_singleton(cls: C, /, *args: Any, **kwargs: Any) -> C: 

35 if not hasattr(cls, "__singleton_instance__"): 

36 # noinspection PyUnresolvedReferences 

37 cls.__singleton_instance__ = cls.__singleton_new__(cls, *args, **kwargs) 

38 

39 # noinspection PyProtectedMember 

40 return cast(C, cls.__singleton_instance__) 

41 

42 target_cls.__singleton_new__ = target_cls.__new__ 

43 target_cls.__new__ = staticmethod(new_singleton) # type: ignore[assignment] 

44 

45 return target_cls 

46 

47 

48@singleton 

49class UnsetType: 

50 """用于填充默认值的特殊值""" 

51 

52 __slots__ = () 

53 

54 @override 

55 def __str__(self) -> str: 

56 return "<Unset Argument>" 

57 

58 def __bool__(self) -> bool: 

59 return False 

60 

61 

62Unset = UnsetType() 

63""" 

64用于填充默认值的特殊值 

65""" 

66 

67 

68class Ref[T]: 

69 """ 

70 间接持有对象引用的容器 

71 

72 .. versionchanged:: 0.3.0 

73 重命名 ``CellType`` 为 ``Ref`` 

74 

75 重命名字段 ``cell_contents`` 为 ``value`` 

76 """ 

77 

78 __slots__ = ("value",) 

79 

80 def __init__(self, value: T): 

81 """ 

82 :param value: 引用对象 

83 :type value: T 

84 """ # noqa: D205 

85 self.value = value 

86 

87 @override 

88 def __repr__(self) -> str: 

89 return f"<{type(self).__name__} ({self.value!r})>" 

90 

91 

92class FrozenArguments: 

93 """ 

94 存储冻结的参数的容器 

95 

96 .. versionadded:: 0.3.0 

97 """ 

98 

99 def __init__(self, args: Sequence[Any] | None = None, kwargs: Mapping[str, Any] | None = None): 

100 """ 

101 :param args: 位置参数 

102 :type args: Sequence[Any] 

103 :param kwargs: 关键字参数 

104 :type kwargs: Mapping[str, Any] 

105 """ # noqa: D205 

106 self._args = () if args is None else tuple(args) 

107 self._kwargs: tuple[tuple[str, Any], ...] = () if kwargs is None else tuple((k, v) for k, v in kwargs.items()) 

108 

109 @property 

110 def args(self) -> tuple[Any, ...]: 

111 """ 

112 位置参数 

113 

114 :return: 位置参数 

115 :rtype: tuple[Any] 

116 """ 

117 return deepcopy(self._args) 

118 

119 @property 

120 def kwargs(self) -> OrderedDict[str, Any]: 

121 """ 

122 关键字参数 

123 

124 :return: 关键字参数 

125 :rtype: OrderedDict[str, Any] 

126 """ 

127 return OrderedDict(deepcopy(self._kwargs)) 

128 

129 # noinspection PyTypeHints 

130 def __or__(self, other: tuple[Sequence[Any], Mapping[str, Any]] | Self) -> Self | NotImplementedType: 

131 if isinstance(other, tuple): 

132 other = type(self)(*other) 

133 if not isinstance(other, FrozenArguments): 

134 return NotImplemented 

135 merged_args = list(self._args) 

136 merged_args[: len(other._args)] = other.args 

137 

138 merged_kwargs = self.kwargs | other.kwargs 

139 return type(self)(merged_args, merged_kwargs) 

140 

141 def __iter__(self) -> Iterator[tuple[Any, ...] | OrderedDict[str, Any]]: 

142 yield self.args 

143 yield self.kwargs 

144 

145 @override 

146 def __eq__(self, other: Any) -> bool: 

147 if not isinstance(other, FrozenArguments): 

148 return NotImplemented 

149 return self._args == other._args and self._kwargs == other._kwargs 

150 

151 @override 

152 def __hash__(self) -> int: 

153 return hash(self._args) ^ hash(self._kwargs) 

154 

155 

156__all__ = ( 

157 "FrozenArguments", 

158 "Ref", 

159 "Unset", 

160 "UnsetType", 

161 "singleton", 

162)