Coverage for src / c41811 / config / basic / _generate_operators.py: 100%
45 statements
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-09 01:06 +0000
« prev ^ index » next coverage.py v7.13.0, created at 2025-12-09 01:06 +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 # noinspection PyTypeHints
46 def inplace_op(self: S, other: Any) -> S:
47 self._data = inplace_func(self._data, other)
48 return self
50 return forward_op, reverse_op, inplace_op
53def generate[C](cls: type[C]) -> type[C]:
54 """
55 为类生成操作符
57 需要使用 :py:deco:`operate` 装饰器标记要自动生成的操作符
59 :param cls: 目标类
60 :type cls: type[C]
62 :return: 原样返回类
63 :rtype: type[C]
64 """
65 for name, func in dict(vars(cls)).items():
66 if not hasattr(func, "__generate_operators__"):
67 continue
68 operator_funcs = func.__generate_operators__
69 delattr(func, "__generate_operators__")
71 # 动态创建函数
72 forward_op, reverse_op, inplace_op = _generate_operators(
73 operator_funcs["operate_func"], operator_funcs["inplace_func"]
74 )
76 # 设置函数标识符
77 i_name = f"__i{name[2:-2]}__"
78 r_name = f"__r{name[2:-2]}__"
79 forward_op.__qualname__ = func.__qualname__
80 reverse_op.__qualname__ = f"{cls.__qualname__}.{r_name}"
81 inplace_op.__qualname__ = f"{cls.__qualname__}.{i_name}"
83 # 应用装饰器
84 @wrapt.decorator
85 def wrapper(wrapped: Callable[..., Any], _instance: C, args: tuple[Any, ...], kwargs: dict[str, Any]) -> Any:
86 if isinstance(args[0], BasicSingleConfigData):
87 args = (args[0].data, *args[1:])
88 return wrapped(*args, **kwargs)
90 setattr(cls, name, update_wrapper(wrapper(forward_op), forward_op))
91 setattr(cls, r_name, reverse_op)
92 setattr(cls, i_name, update_wrapper(wrapper(check_read_only(inplace_op)), inplace_op))
94 return cls
97def operate[F: Operator](
98 operate_func: Operator,
99 inplace_func: InplaceOperator[Any],
100) -> Callable[[F], F]:
101 """
102 将方法标记为需要生成标记符
104 :param operate_func: 操作函数
105 :type operate_func: Operator
106 :param inplace_func: 原地操作函数
107 :type inplace_func: InplaceOperator[Any]
109 :return: 装饰器
110 :rtype: Callable[[F], F]
111 """
113 def decorator(func: F) -> F:
114 func.__generate_operators__ = { # type: ignore[attr-defined]
115 "operate_func": operate_func,
116 "inplace_func": inplace_func,
117 }
118 return func
120 return decorator
123__all__ = (
124 "generate",
125 "operate",
126)