|
12 | 12 | import enum |
13 | 13 | import functools |
14 | 14 | import importlib |
15 | | -import importlib.machinery |
16 | 15 | import inspect |
17 | 16 | import os |
18 | 17 | import pkgutil |
|
35 | 34 |
|
36 | 35 | import mypy.build |
37 | 36 | import mypy.checkexpr |
38 | | -import mypy.checkmember |
39 | 37 | import mypy.erasetype |
40 | 38 | import mypy.modulefinder |
41 | 39 | import mypy.nodes |
42 | 40 | import mypy.state |
| 41 | +import mypy.subtypes |
43 | 42 | import mypy.types |
44 | 43 | import mypy.version |
45 | 44 | from mypy import nodes |
@@ -1540,11 +1539,48 @@ def apply_decorator_to_funcitem( |
1540 | 1539 | for decorator in dec.original_decorators: |
1541 | 1540 | resulting_func = apply_decorator_to_funcitem(decorator, func) |
1542 | 1541 | if resulting_func is None: |
| 1542 | + # We couldn't figure out how to apply the decorator by transforming nodes, so try to |
| 1543 | + # reconstitute a FuncDef from the resulting type of the decorator |
| 1544 | + # This is worse because e.g. we lose the values of defaults |
| 1545 | + dec_type = mypy.types.get_proper_type(dec.type) |
| 1546 | + callable_type = None |
| 1547 | + if isinstance(dec_type, mypy.types.Instance): |
| 1548 | + callable_type = mypy.subtypes.find_member( |
| 1549 | + "__call__", dec_type, dec_type, is_operator=True |
| 1550 | + ) |
| 1551 | + elif isinstance(dec_type, mypy.types.CallableType): |
| 1552 | + callable_type = dec_type |
| 1553 | + |
| 1554 | + callable_type = mypy.types.get_proper_type(callable_type) |
| 1555 | + if isinstance(callable_type, mypy.types.CallableType): |
| 1556 | + return _resolve_funcitem_from_callable_type(callable_type) |
1543 | 1557 | return None |
| 1558 | + |
1544 | 1559 | func = resulting_func |
1545 | 1560 | return func |
1546 | 1561 |
|
1547 | 1562 |
|
| 1563 | +def _resolve_funcitem_from_callable_type(typ: mypy.types.CallableType) -> nodes.FuncDef: |
| 1564 | + args: list[nodes.Argument] = [] |
| 1565 | + |
| 1566 | + for i, (arg_type, arg_kind, arg_name) in enumerate( |
| 1567 | + zip(typ.arg_types, typ.arg_kinds, typ.arg_names, strict=True) |
| 1568 | + ): |
| 1569 | + var_name = arg_name if arg_name is not None else f"__arg{i}" |
| 1570 | + var = nodes.Var(var_name, arg_type) |
| 1571 | + pos_only = arg_name is None and arg_kind == nodes.ARG_POS |
| 1572 | + args.append( |
| 1573 | + nodes.Argument( |
| 1574 | + variable=var, |
| 1575 | + type_annotation=arg_type, |
| 1576 | + initializer=None, # CallableType doesn't store the values of defaults |
| 1577 | + kind=arg_kind, |
| 1578 | + pos_only=pos_only, |
| 1579 | + ) |
| 1580 | + ) |
| 1581 | + return nodes.FuncDef(name=typ.name or "", arguments=args, body=nodes.Block([]), typ=typ) |
| 1582 | + |
| 1583 | + |
1548 | 1584 | @verify.register(nodes.Decorator) |
1549 | 1585 | def verify_decorator( |
1550 | 1586 | stub: nodes.Decorator, runtime: MaybeMissing[Any], object_path: list[str] |
|
0 commit comments