Returns a FuncItem that corresponds to the output of the decorator. Returns None if we can't figure out what that would be. For convenience, this function also accepts FuncItems.
(dec: nodes.OverloadPart)
| 1537 | |
| 1538 | |
| 1539 | def _resolve_funcitem_from_decorator(dec: nodes.OverloadPart) -> nodes.FuncItem | None: |
| 1540 | """Returns a FuncItem that corresponds to the output of the decorator. |
| 1541 | |
| 1542 | Returns None if we can't figure out what that would be. For convenience, this function also |
| 1543 | accepts FuncItems. |
| 1544 | """ |
| 1545 | if isinstance(dec, nodes.FuncItem): |
| 1546 | return dec |
| 1547 | if dec.func.is_property: |
| 1548 | return None |
| 1549 | |
| 1550 | def apply_decorator_to_funcitem( |
| 1551 | decorator: nodes.Expression, func: nodes.FuncItem |
| 1552 | ) -> nodes.FuncItem | None: |
| 1553 | if ( |
| 1554 | isinstance(decorator, nodes.CallExpr) |
| 1555 | and isinstance(decorator.callee, nodes.RefExpr) |
| 1556 | and decorator.callee.fullname in mypy.types.DEPRECATED_TYPE_NAMES |
| 1557 | ): |
| 1558 | return func |
| 1559 | if not isinstance(decorator, nodes.RefExpr): |
| 1560 | return None |
| 1561 | if not decorator.fullname: |
| 1562 | # Happens with namedtuple |
| 1563 | return None |
| 1564 | if ( |
| 1565 | decorator.fullname in ("builtins.staticmethod", "abc.abstractmethod") |
| 1566 | or decorator.fullname in mypy.types.OVERLOAD_NAMES |
| 1567 | or decorator.fullname in mypy.types.OVERRIDE_DECORATOR_NAMES |
| 1568 | or decorator.fullname in mypy.types.FINAL_DECORATOR_NAMES |
| 1569 | ): |
| 1570 | return func |
| 1571 | if decorator.fullname == "builtins.classmethod": |
| 1572 | if func.arguments[0].variable.name not in ("_cls", "cls", "mcs", "metacls"): |
| 1573 | raise StubtestFailure( |
| 1574 | f"unexpected class parameter name {func.arguments[0].variable.name!r} " |
| 1575 | f"in {dec.fullname}" |
| 1576 | ) |
| 1577 | # FuncItem is written so that copy.copy() actually works, even when compiled |
| 1578 | ret = copy.copy(func) |
| 1579 | # Remove the cls argument, since it's not present in inspect.signature of classmethods |
| 1580 | ret.arguments = ret.arguments[1:] |
| 1581 | return ret |
| 1582 | # Just give up on any other decorators. After excluding properties, we don't run into |
| 1583 | # anything else when running on typeshed's stdlib. |
| 1584 | return None |
| 1585 | |
| 1586 | func: nodes.FuncItem = dec.func |
| 1587 | for decorator in dec.original_decorators: |
| 1588 | resulting_func = apply_decorator_to_funcitem(decorator, func) |
| 1589 | if resulting_func is None: |
| 1590 | # We couldn't figure out how to apply the decorator by transforming nodes, so try to |
| 1591 | # reconstitute a FuncDef from the resulting type of the decorator |
| 1592 | # This is worse because e.g. we lose the values of defaults |
| 1593 | dec_type = mypy.types.get_proper_type(dec.type) |
| 1594 | callable_type = None |
| 1595 | if isinstance(dec_type, mypy.types.Instance): |
| 1596 | callable_type = mypy.subtypes.find_member( |
no test coverage detected
searching dependent graphs…