Open dckc opened 4 years ago
Yeah, mypy should understand private attributes like __x
. I'm surprised that I couldn't find an existing issue.
Here is another false negative test case:
class C:
__private = 'foo'
print(C.__private)
mypy will not report any errors, but the code breaks at runtime.
There are good arguments for not implementing name mangling:
C.__private
as non-existing is technically correct but counter-intuitiveOn the other hand, mypy is a type checker and not a style checker, so I don't know whether unclean code that does execute correctly should be rejected. The name mangling is documented in the official language reference, so it's not just a CPython detail.
In any case, to solve the false negatives, either name mangling should be implemented or additional checks should be done when a name is looked up, to report private name lookups from outside the class.
Mypy should clearly follow runtime Python semantics and implement name mangling. If the error messages would become confusing, we may have to add some extra logic or notes to error messages.
We'd be happy to review a PR if anybody would like to contribute one!
I personally feel like name mangling should not be supported and mangled names should stay private and filtered as such. People accessing symbols such as _Foobar should not be able to do that in Mypy. I also feel like the AttributeError `"B" has no attribute "x"is fine, even though it's technically wrong.
'_B__x'` is probably simply confusing a lot of users.
The first example in this issue is of code that fails with an AttributeError at runtime but not reported by mypy. It seems clear to me that we should fix that.
I completely agree. I was probably too tunnel-visioned on the potential fix in https://github.com/python/mypy/pull/16715. Sorry for that. I just feel like fully implementing name mangling on the parser level is not a good idea.
Why shouldn't mypy fully support mangling? It's a perfectly well documented and valid part of the language, not deprecated or anything. There's no warnings at all about regular private attribute access, and plenty of things in typeshed include private/undocumented members. Mangled names aren't supposed to be any more private, there's perfectly valid reasons to want to access them from outside the class.
There is the import system exporting rules, but those have ways to specifically allow private names. Even if you do use them, mypy gives a specific error, but still sets the types appropriately so subsequent code is correct. If name mangling wasn't implemented, uses would just be produce Any
.
There is the slight issue where it could conflict with 3.7 positional-only arguments, but it's probably about time to drop support for those anyway?
I agree in general that mypy should model the runtime correctly. It doesn't have to be mypy's job to warn users about access to private attributes, as that's easy enough to do in a general-purpose linter.
I don't think we can afford to deprecate double underscores for positional-only arguments yet, though; there must be a lot of existing code that relies on those. If we add better support for name mangling, we need to be careful not to break those.
Mypy doesn't seem to grok that
self.__x
in a subclass is different fromself.__x
in a superclass. It also doesn't seem to understand order of initialization.bug
mypy should report:
tytest.py:8: error: "B" has no attribute "__x
mypy 0.700
yes (
mypy-0.770+dev.01ca4e062e38a9db8f462b9464fbbd5dd945a8cf
)