Coverage for src/c41811/config/basic/_generate_operators.py: 100%
45 statements
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-04 11:16 +0000
« prev ^ index » next coverage.py v7.15.0, created at 2026-07-04 11:16 +0000
1# cython: language_level = 3 # noqa: ERA001
4"""
5辅助生成
7.. versionadded:: 0.2.0
8"""
10from collections.abc import Callable
11from functools import update_wrapper
12from typing import Any
14import wrapt
16from .core import BasicSingleConfigData
17from .factory import ConfigDataFactory
18from .utils import check_read_only
20type Operator = Callable[[Any, Any], Any]
21type InplaceOperator[S] = Callable[[S, Any], S]
24def _generate_operators[S: Any](
25 operate_func: Operator, inplace_func: InplaceOperator[S]
26) -> tuple[Operator, Operator, InplaceOperator[S]]:
27 """
28 闭包绑定操作函数
30 :param operate_func: 操作函数
31 :type operate_func: Operator
32 :param inplace_func: 原地操作函数
33 :type inplace_func: InplaceOperator[S]
35 :return: 绑定后的操作符实现
36 :rtype: tuple[Operator, Operator, InplaceOperator[S]]
37 """
39 def forward_op(self: Any, other: Any) -> Any:
40 return ConfigDataFactory(operate_func(self._data, other))
42 def reverse_op(self: Any, other: Any) -> Any:
43 return ConfigDataFactory(operate_func(other, self._data))
45 def inplace_op(self: S, other: Any) -> S:
46 self._data = inplace_func(self._data, other)
47 return self
49 return forward_op, reverse_op, inplace_op
52def generate[C](cls: type[C]) -> type[C]:
53 """
54 为类生成操作符
56 需要使用 :py:deco:`operate` 装饰器标记要自动生成的操作符
58 :param cls: 目标类
59 :type cls: type[C]
61 :return: 原样返回类
62 :rtype: type[C]
63 """
64 for name, func in dict(vars(cls)).items():
65 if not hasattr(func, "__generate_operators__"):
66 continue
67 operator_funcs = func.__generate_operators__
68 delattr(func, "__generate_operators__")
70 # 动态创建函数
71 forward_op, reverse_op, inplace_op = _generate_operators(
72 operator_funcs["operate_func"], operator_funcs["inplace_func"]
73 )
75 # 设置函数标识符
76 i_name = f"__i{name[2:-2]}__"
77 r_name = f"__r{name[2:-2]}__"
78 forward_op.__qualname__ = func.__qualname__
79 reverse_op.__qualname__ = f"{cls.__qualname__}.{r_name}"
80 inplace_op.__qualname__ = f"{cls.__qualname__}.{i_name}"
82 # 应用装饰器
83 @wrapt.decorator
84 def wrapper(wrapped: Callable[..., Any], _instance: C, args: tuple[Any, ...], kwargs: dict[str, Any]) -> Any:
85 if isinstance(args[0], BasicSingleConfigData):
86 args = (args[0].data, *args[1:])
87 return wrapped(*args, **kwargs)
89 setattr(cls, name, update_wrapper(wrapper(forward_op), forward_op))
90 setattr(cls, r_name, reverse_op)
91 setattr(cls, i_name, update_wrapper(wrapper(check_read_only(inplace_op)), inplace_op))
93 return cls
96def operate[F: Operator](
97 operate_func: Operator,
98 inplace_func: InplaceOperator[Any],
99) -> Callable[[F], F]:
100 """
101 将方法标记为需要生成标记符
103 :param operate_func: 操作函数
104 :type operate_func: Operator
105 :param inplace_func: 原地操作函数
106 :type inplace_func: InplaceOperator[Any]
108 :return: 装饰器
109 :rtype: Callable[[F], F]
110 """
112 def decorator(func: F) -> F:
113 func.__generate_operators__ = { # type: ignore[attr-defined]
114 "operate_func": operate_func,
115 "inplace_func": inplace_func,
116 }
117 return func
119 return decorator
122__all__ = (
123 "generate",
124 "operate",
125)