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

"error: Name is not defined" and confusing behavior on instance-level classes #8482

Open
slavfox opened this issue Mar 3, 2020 · 2 comments

Comments

@slavfox
Copy link

slavfox commented Mar 3, 2020

Running mypy on the following example:

from typing import Type

class Foo:
    def __init__(self):
        class Bar:
            pass

        self.Bar: Type[Bar] = Bar

foo = Foo()
bar: foo.Bar = foo.Bar()

reveal_type(foo.Bar)
reveal_type(bar)

results in the following slightly confusing and seemingly contradictory output:

example.py:11: error: Name 'foo.Bar' is not defined  # on bar: foo.Bar
example.py:13: note: Revealed type is 'Type[example.Bar@5]'  # on reveal_type(foo.Bar)
example.py:14: note: Revealed type is 'Any'  # on reveal_type(bar)

Ideally, I would have expected reveal_type(bar) to reveal example.Bar@5. I'm not sure if there is a way to correctly type this code without resorting to # type: ignore right now.

Tested on mypy 0.761, Python 3.8.1.

@ilevkivskyi
Copy link
Member

Although the error message is not perfect it is technically correct. Type named foo.Bar can't be statically resolved.

On one hand, this is a really bad pattern, since a new nested class will be created on each instantiation: Foo().Bar and Foo().Bar are two different classes. On the other hand this (surprisingly to me) not the first time this issue appears. So it would make sense to improve the error message.

@slavfox
Copy link
Author

slavfox commented Mar 6, 2020

Yeah, I'm aware this is impossible to type, and for a good reason:

class Foo:
    def __init__(self, baz):
        if baz:
            class Bar(int): ...
        else:
            class Bar(dict): ...
        self.Bar = Bar

This is strictly about the seemingly contradictory 'foo.Bar' is not defined when the type is, in fact, known to mypy, just incompatible with an attempt at static typing.

Apologies if I wasn't clear in the original report 😅

@AlexWaygood AlexWaygood added the topic-error-reporting How we report errors label Apr 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants