Add dunder methods to classes decorated with functools.total_ordering.
(
ctx: mypy.plugin.ClassDefContext, auto_attribs_default: bool = False
)
| 50 | |
| 51 | |
| 52 | def functools_total_ordering_maker_callback( |
| 53 | ctx: mypy.plugin.ClassDefContext, auto_attribs_default: bool = False |
| 54 | ) -> bool: |
| 55 | """Add dunder methods to classes decorated with functools.total_ordering.""" |
| 56 | comparison_methods = _analyze_class(ctx) |
| 57 | if not comparison_methods: |
| 58 | ctx.api.fail( |
| 59 | 'No ordering operation defined when using "functools.total_ordering": < > <= >=', |
| 60 | ctx.reason, |
| 61 | ) |
| 62 | return True |
| 63 | |
| 64 | # prefer __lt__ to __le__ to __gt__ to __ge__ |
| 65 | root = max(comparison_methods, key=lambda k: (comparison_methods[k] is None, k)) |
| 66 | root_method = comparison_methods[root] |
| 67 | if not root_method: |
| 68 | # None of the defined comparison methods can be analysed |
| 69 | return True |
| 70 | |
| 71 | other_type = _find_other_type(root_method) |
| 72 | bool_type = ctx.api.named_type("builtins.bool") |
| 73 | ret_type: Type = bool_type |
| 74 | if root_method.type.ret_type != ctx.api.named_type("builtins.bool"): |
| 75 | proper_ret_type = get_proper_type(root_method.type.ret_type) |
| 76 | if not ( |
| 77 | isinstance(proper_ret_type, UnboundType) |
| 78 | and proper_ret_type.name.split(".")[-1] == "bool" |
| 79 | ): |
| 80 | ret_type = AnyType(TypeOfAny.implementation_artifact) |
| 81 | for additional_op in _ORDERING_METHODS: |
| 82 | # Either the method is not implemented |
| 83 | # or has an unknown signature that we can now extrapolate. |
| 84 | if not comparison_methods.get(additional_op): |
| 85 | args = [Argument(Var("other", other_type), other_type, None, ARG_POS)] |
| 86 | add_method_to_class(ctx.api, ctx.cls, additional_op, args, ret_type) |
| 87 | |
| 88 | return True |
| 89 | |
| 90 | |
| 91 | def _find_other_type(method: _MethodInfo) -> Type: |
nothing calls this directly
no test coverage detected
searching dependent graphs…