-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
stubtest: error if a class should be decorated with @final #12091
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
Conversation
There are several false positives in that list due to the fact that |
In python/typeshed#6299, I avoided these by just doing a simple (I think you've picked up on several true positives that I missed due to the fact that I'm on Windows, while you're on Linux.) |
It now ignores enum classes. Here are the new results:
|
Haven't manually tested them all, but looks good to me! |
I made it not complain about classes that define You can do this, for example, taken from the tests:
Because
|
Co-authored-by: Alex Waygood <[email protected]>
I no longer think that looking at |
If I were defining class Uncooperative:
def __init_subclass__(cls, **kwargs):
raise TypeError("No.") But if I were defining class Fancy:
def __init_subclass__(cls, *, extra_param, **kwargs):
# do something with extra_param
super().__init_subclass__(**kwargs) So perhaps you could distinguish between classes that have |
I could look at |
Makes sense! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks!
Agreed that the false positive for __init_subclass__
doesn't matter too much. But I think I would prefer if we only reported the message for TypeError
, e.g. the ctypes one is a false positive.
I'm curious if you think there's any value reporting for the reverse: stub marked final, but runtime not.
This is a fun step for stubtest. So far it's been pretty passive in how it interacts with runtime, just imports, getattrs and instancechecks. I'm totally fine with this, but figured I'd mention in case anyone knows some common evil patterns with side-effecting metaclasses or something. Note that there is a more passive version of this check that would work for C classes that aren't subclassable: bool(getattr(runtime, "__flags__") ^ (1 << 10))
Done. Here's the diff of results: -ctypes.Array cannot be subclassed at runtime, but isn't marked with @final in the stub
-ctypes._SimpleCData cannot be subclassed at runtime, but isn't marked with @final in the stub
I added a check like this, but didn't push it yet. Here are the errors it finds in stdlib: +collections._OrderedDictItemsView can be subclassed at runtime, but is marked with @final in the stub
+collections._OrderedDictKeysView can be subclassed at runtime, but is marked with @final in the stub
+collections._OrderedDictValuesView can be subclassed at runtime, but is marked with @final in the stub
+functools._lru_cache_wrapper can be subclassed at runtime, but is marked with @final in the stub All of these were added in python/typeshed#6299. @AlexWaygood Are these intentionally
I don't recall coming across something like this, but I have seen plenty of magic done in |
Check it out: >>> import collections
>>> class Foo(type(collections.OrderedDict().keys())): ...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: type 'odict_keys' is not valid as a base type
>>> class Foo(collections._OrderedDictKeysView): ...
>>> collections._OrderedDictKeysView is type(collections.OrderedDict().keys())
False The C implementations of these classes differ from the pure-Python implementations of these classes. |
I guess there's a theoretical risk of someone doing class Foo:
def __init_subclass__(cls, **kwargs):
download_my_evil_virus() Such that |
Or you know, just call Stubtesting third-party stubs should be done with restricted permissions anyway, because it imports a lot of unreviewed code from pypi by design. This is why typeshed lets stubtest CI jobs only read the repository, for example. |
In other words, the "stub final but runtime subclassable" error found 4 false positives and 0 true positives in stdlib. Not worth pushing, at least for now. |
I agree. |
Thank you! |
We still can have a reverse problem: I will send a PR for this. |
Yes, but see my comment here: #12091 (comment), and our ensuing discussion. |
Description
Stubtest now errors if
class SubClass(some_class): pass
errors at runtime, butsome_class
isn't marked with@final
in the stub.Test Plan
New errors from
--check-typeshed
, checked against typeshed commit 92d135a3: