Correct implementation of standard types besides "object" #1340
Correct implementation of standard types besides "object" #1340gvanrossum merged 5 commits intopython:masterfrom
Conversation
| no_type_check = object() | ||
| ClassVar = object() | ||
|
|
||
| class _GenericBaseTypeClass: |
There was a problem hiding this comment.
I would prefer calling this _SpecialForm, which is shorter and more accurate.
|
Looks good, and I like making the typing stubs a bit less magical. This is a bit risky though, so I want to wait for comments from people maintaining type checkers before merging it. |
|
Looks like flake8 isn't happy. Can you try writing things as |
ilevkivskyi
left a comment
There was a problem hiding this comment.
I think in addition to this we need some special casing in mypy, to show tailored error messages if something is wrong with special forms in runtime context.
| ClassVar = object() | ||
|
|
||
| class _SpecialForm: | ||
| def __getitem__(self, typeargs: Any) -> Any: ... |
There was a problem hiding this comment.
I would rather say -> object: ... otherwise Tuple[int].nonexisting(1, 'whatever') will be valid.
There was a problem hiding this comment.
Yes, the return type must not be Any to avoid false negatives. The Any argument type also results in false negatives. It allows things like Tuple[1], which will fail at runtime.
| def __getitem__(self, typeargs: Any) -> Any: ... | ||
|
|
||
| Tuple: _SpecialForm = ... | ||
| Generic: _SpecialForm = ... |
There was a problem hiding this comment.
I would not change this for Generic, it should never appear in runtime context, IOW it is "too special" :-)
There was a problem hiding this comment.
I'm not sure how it's different from the others.
There was a problem hiding this comment.
You can't use Generic in an annotation -- it can only occur in a list of base classes. That's pretty different.
There was a problem hiding this comment.
You can't use
Genericin an annotation -- it can only occur in a list of base classes. That's pretty different.
This is exactly what I mean.
JukkaL
left a comment
There was a problem hiding this comment.
I'm not sure if this can be implemented as a typeshed change in a meaningful way, unfortunately. What's the intended use case?
| ClassVar = object() | ||
|
|
||
| class _SpecialForm: | ||
| def __getitem__(self, typeargs: Any) -> Any: ... |
There was a problem hiding this comment.
Yes, the return type must not be Any to avoid false negatives. The Any argument type also results in false negatives. It allows things like Tuple[1], which will fail at runtime.
|
I suggested doing things this way because it can solve the mypy issue without adding additional special-casing within mypy itself. More generally, I'd like to move the typing stubs to a state where they more closely reflect how typing.py is implemented at runtime, so that tools that use typeshed don't need custom implementations of as many parts of typing. Obviously a change like this isn't going to be perfect in terms of rejecting all things that fail at runtime, but I generally prefer false negatives over false positives. |
| no_type_check = object() | ||
| ClassVar = object() | ||
|
|
||
| class _SpecialForm: |
There was a problem hiding this comment.
Inherit from object explicitly in the PY2 version.
gvanrossum
left a comment
There was a problem hiding this comment.
See previous comments (not just mine).
| ClassVar = object() | ||
|
|
||
| class _SpecialForm: | ||
| def __getitem__(self, typeargs: Any) -> Any: ... |
|
I think everything has been addressed here. @gvanrossum can you take another look? |
|
Does this actually fix python/mypy#2989? If so please close that (and add a note). |
As per python/mypy#2989, these changes help to correctly indicate usage of
Tuple[]among others.Tested this using this script: