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

Methods with the same name as a type sometimes cause error "not valid as a type" #15047

Open
tilsche opened this issue Apr 13, 2023 · 4 comments
Labels
bug mypy got something wrong

Comments

@tilsche
Copy link

tilsche commented Apr 13, 2023

Bug Report

When using a decorator on a class method with the same name as a type used in its return type, and the method is decorated with a decorator that spans multiple lines, an error is thrown.

What puzzles me is that this only causes an error if the decorator spans multiple lines, not if it is just on a single line.

Neither pylint nur flake8 do complain about having a method that shadows another name in general. So I am assuming that this should be generally ok.

To Reproduce

class Foo:
    @property
    # the existence of this comment triggers the error
    def int(self) -> int:
        return 0

Some more examples show that this

  • The error occurs in any situation where the decorator starts more than one line before the function definition.
    • with a blank line in between
    • with a comment line in between
    • with a multi-line argument decorator (this is the case where I initially encountered it when using @deprecated.
  • The error occurs with both built-in decorators (@property) and custom defined decorators.
  • The error occurs both with built-in types and imported types.

Expected Behavior

Use the types from the outer scope to construct the return type and validate correctly.

Actual Behavior

error: Function "__main__.Foo.int" is not valid as a type  [valid-type]
note: Perhaps you need "Callable[...]" or a callback protocol?

Your Environment

  • Mypy version used: 1.2.0, master branch via mypy-play.net
  • Mypy command-line flags: none
  • Mypy configuration options from mypy.ini (and other config files): none
  • Python version used: 3.10 and 3.11 tested
@john-bodley
Copy link

john-bodley commented May 25, 2023

This example seems somewhat similar, i.e.,

class Foo:
    @property
    def type(self) -> str:
        return "foo"

is valid, however,

class Foo:
    @property
    def type(self) -> str:
        return "foo"

    @property
    def foo(self) -> type:
        return Foo

the inclusion of the foo property results in the following Mypy error:

error: Function "__main__.Foo.type" is not valid as a type  [valid-type]
note: Perhaps you need "Callable[...]" or a callback protocol?

@hauntsaninja
Copy link
Collaborator

In your case, mypy's behaviour matches that of Python's scoping, no?

In [1]: class Foo:
   ...:     def type(self) -> str:
   ...:         return "foo"
   ...: 
   ...:     def foo(self) -> type:
   ...:         return Foo
   ...: 

In [2]: Foo.foo.__annotations__
Out[2]: {'return': <function __main__.Foo.type(self) -> str>}

OP's case is definitely buggy, because no matter what mypy's behaviour is it should be robust to the presence of comments and whitespace

@john-bodley
Copy link

john-bodley commented May 25, 2023

Thanks @hauntsaninja for the response. What's your recommendation for a preferred solution? Is it simply to refer to the built-in, i.e.,

In [1]: class Foo:
   ...:     def type(self) -> str:
   ...:         return "foo"
   ...: 
   ...:     def foo(self) -> __builtins__.type:
   ...:         return Foo
   ...: 

In [2]: Foo.foo.__annotations__
Out[2]: {'return': type}

@JelleZijlstra
Copy link
Member

Using builtins.type (and import builtins) is what I'd recommend.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong
Projects
None yet
Development

No branches or pull requests

4 participants