Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Running mypy with --disallow-untyped-decorators reports an error for overloaded decorators #4191

Closed
joshstaiger opened this issue Nov 1, 2017 · 2 comments
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-1-normal topic-overloads

Comments

@joshstaiger
Copy link

joshstaiger commented Nov 1, 2017

Running mypy --disallow-untyped-decorators with a decorator that defines overloads always seems to report:

Untyped decorator makes function "xxx" untyped

Even though reveal_type(...) calls on the decorated functions seem to indicate type information.

Consider the following code.

Running mypy --disallow-untyped-decorators here yields the following (mypy 0.540):

dec_issue.py:19: error: Overloaded function signatures 1 and 2 overlap with incompatible return types
dec_issue.py:35: error: Untyped decorator makes function "default" untyped
dec_issue.py:41: error: Revealed type is 'def (*Any, **Any) -> builtins.int*'

The first error seems to be covered by other bug reports here (though, for all I know it may be related).

However, the second error seems to be contradicted by the type_reveal, which indicates at least the return type of the decorated "default" function is being picked up.

I may be missing something, but at very least, it seems like a more descriptive error may be warranted?

from typing import *

R = TypeVar("R")


def _make_decorator(arg: str) -> Callable[[Callable[..., R]], Callable[..., R]]:
    def dec_(fn: Callable[..., R]) -> Callable[..., R]:
        def wrapped(*args: Tuple[Any, ...],
                    **kwargs: Dict[str, Any]) -> R:
            print(f"Prefix {arg}!")
            return fn(*args, **kwargs)

        return wrapped

    return dec_


@overload
def dec(x: Callable[..., R]) -> Callable[..., R]: ...


@overload
def dec(x: str) -> Callable[[Callable[..., R]], Callable[..., R]]: ...


def dec(x: Any) -> Any:
    if isinstance(x, str):
        return _make_decorator(x)
    elif callable(x):
        return _make_decorator("default")(x)
    else:
        raise Exception("unhandled")


@dec
def default(name: str) -> int:
    print(f"Hello, {name}!")
    return 0


reveal_type(default)


@dec("arg")
def arg(name: str) -> int:
    print(f"Hello, {name}!")
    return 0


if __name__ == "__main__":
    default("Bob")
    arg("Bob")
@ilevkivskyi ilevkivskyi added bug mypy got something wrong priority-1-normal false-positive mypy gave an error on correct code topic-overloads labels May 20, 2018
@ilevkivskyi
Copy link
Member

This still fails on master (the "Untyped decorator makes function "default" untyped"). I tried a more precise signature:

F = TypeVar('F', bound=Callable[..., Any])
@overload
def dec(x: F) -> F: ...
@overload
def dec(x: str) -> Callable[[F], F]: ...

And this still fails even though reveal shows def (name: builtins.str) -> builtins.int.

ilevkivskyi pushed a commit that referenced this issue Sep 21, 2018
Running `mypy --disallow-untyped-decorators` when the decorator is a typed callable instance produces an error even though `reveal_type` shows the correct type.

Related to #4191
@ilevkivskyi
Copy link
Member

I don't see any of the original errors here. It looks like this was fixed by #5509

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong false-positive mypy gave an error on correct code priority-1-normal topic-overloads
Projects
None yet
Development

No branches or pull requests

2 participants