-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
stubtest: error if a dunder method is missing from a stub #12203
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
This comment has been minimized.
This comment has been minimized.
2 similar comments
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment was marked as outdated.
This comment was marked as outdated.
| IGNORED_DUNDERS = frozenset({ | ||
| # Very special attributes | ||
| "__weakref__", | ||
| "__slots__", | ||
| "__dict__", | ||
| "__text_signature__", | ||
| "__match_args__", | ||
| # Pickle methods | ||
| "__setstate__", | ||
| "__getstate__", | ||
| "__getnewargs__", | ||
| "__getinitargs__", | ||
| "__reduce_ex__", | ||
| "__reduce__", | ||
| # typing implementation details | ||
| "__parameters__", | ||
| "__origin__", | ||
| "__args__", | ||
| "__orig_bases__", | ||
| "__mro_entries__", | ||
| "__forward_is_class__", | ||
| "__forward_module__", | ||
| "__final__", | ||
| # isinstance/issubclass hooks that type-checkers don't usually care about | ||
| "__instancecheck__", | ||
| "__subclasshook__", | ||
| "__subclasscheck__", | ||
| # Dataclasses implementation details | ||
| "__dataclass_fields__", | ||
| "__dataclass_params__", | ||
| # ctypes weirdness | ||
| "__ctype_be__", | ||
| "__ctype_le__", | ||
| "__ctypes_from_outparam__", | ||
| # Two float methods only used internally for CPython test suite, not for public use | ||
| "__set_format__", | ||
| "__getformat__", | ||
| # These two are basically useless for type checkers | ||
| "__hash__", | ||
| "__getattr__", | ||
| # For some reason, mypy doesn't infer classes with metaclass=ABCMeta inherit this attribute | ||
| "__abstractmethods__", | ||
| "__doc__", # Can only ever be str | None, who cares? | ||
| "__del__", # Only ever called when an object is being deleted, who cares? | ||
| "__new_member__", # If an enum defines __new__, the method is renamed as __new_member__ | ||
| }) |
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.
This is a fairly arbitrary ignorelist, based on the hits that this patch initially came up with, combined with my judgement as to which were worth fixing and which weren't. I'm happy to add or remove items!
This comment has been minimized.
This comment has been minimized.
1 similar comment
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
hauntsaninja
left a comment
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.
This is great, thanks for doing this!
|
According to mypy_primer, this change has no effect on the checked open source code. 🤖🎉 |
|
Thanks! :D |
Basically a follow up to #12203 New errors in typeshed from this: ``` _decimal.__libmpdec_version__ is not present in stub _heapq.__about__ is not present in stub builtins.__build_class__ is not present in stub cgitb.__UNDEF__ is not present in stub decimal.__libmpdec_version__ is not present in stub sys.__unraisablehook__ is not present in stub ``` Some general housekeeping, moving things around, renaming things, adding some comments.
This isn't actually a reversion. This logic was asymmetrical for reasons lost to time. Although I suspect it was this way because it introduced only a few errors on typeshed. What changed was that as a result of python#12203 we actually started checking a lot more dunder methods. Previously, we only checked dunders if either: a) it was a special dunder, like __init__ or __call, or b) the dunder was defined on the actual stub class itself In particular, we started checking every dunder redefined at runtime that the stub just inherited from object. A possible intermediate option would be to not check positional-only arguments in the case where a stub inherits the definition. I'll experiment with that once typeshed CI is green.
This isn't actually a reversion. This logic was asymmetrical for reasons lost to time. Although I suspect it was this way because the delta only a few errors on typeshed. What changed was that as a result of #12203 we actually started checking a lot more dunder methods. Previously, we only checked dunders if either: a) it was a special dunder, like `__init__` or `__call__`, or b) the dunder was defined on the actual stub class itself In particular, we started checking every dunder redefined at runtime that the stub just inherited from object. A possible intermediate option would be to not check positional-only arguments in the case where a stub inherits the definition. I'll experiment with that once typeshed CI is green. Co-authored-by: hauntsaninja <>
Description
This PR alters stubtest so that it raises an error if a dunder method is missing from a stub. Currently, stubtest does raise an error for a few missing dunders (
__call__,__class_getitem__, etc.). However, for the vast majority of them, it does not raise an error.I have been using this patch to provide a number of fixes to typeshed over the past week or so:
array,tracemallocandunittest.mocktypeshed#7248ipaddressdunders typeshed#7244__(deep)copy__methods typeshed#7242types: Add several missing__(qual)name__attributes typeshed#7216builtinstypeshed#7214itertools.repeat.__length_hint__method typeshed#7212traceback.FrameSummarytypeshed#7210traceback.FrameSummarytypeshed#7210collections: Add missing reflected BinOp methods typeshed#7207EnumMeta.__bool__typeshed#7206__isabstractmethods__attributes inabcandfunctoolstypeshed#7205dataclassesandfunctoolstypeshed#7203With these typeshed fixes merged, here are the new errors stubtest reports from checking typeshed, with this patch applied:
Notes on the new errors reported
typingandcollections.abc. These just need to be allowlisted imo, unless and until we find a good general solution to that problem (refs Decouple collections.abc types from typing aliases typeshed#6257)dict_keys,dict_valuesanddict_itemshaving positional-only differences withtyping.KeysView,typing.ValuesViewandtyping.ItemsView. The way to resolve that would be essentially duplicate every method fromtyping.{Keys, Values, Items}Viewinto those classes (but with pos-only args instead of pos-or-kw args). I don't really have the stomach to do that. These should probably just be allowlisted.weakref.ProxyType,dbm.dum._Database,lib2to3.pytree.Leaf: I don't really know anything about these classes.enum.EnumMeta.__prepare__: this will be resolved by AddEnumMeta.__prepare__typeshed#7243superhas some really weird dunders.property.__set_name__: this is a false positive -- it doesn't exist in real life, just needs to be allowlisted.http.cookieshas some really weird__str__methods.functools.partial.__vectorcalloffset__: no idea what this does or is for.platform.uname_resultis a mess in CPython.pstatshits: these relate to a mypy bug indataclasses__eq__method generation (Mypy incorrectly infers that parameters are positional-only for__eq__methods autogenerated with@dataclass#12186).collections.Counter.__missing__: this always raises an exception, but per Why iscollections.ChainMap.__missing__defined in the stub? typeshed#7188, we could maybe add it to the stub.__bool__overrides stubtest now complains about: we could add these to the stub, though they don't seem particularly useful, since they don't alter the default behaviour ofbool(x)at all. (But I don't think__bool__should be added to the list of ignored dunders: it was useful for this patch to flag the missing__bool__method fixed in AddEnumMeta.__bool__typeshed#7206, as that is an override that changes behaviour from the default.)uuid.UUID.__setattr__: this always raises an exception, I think it should just be allowlisted.Test Plan
I've altered the existing tests so they continue to pass, and added two new test cases.
cc. @hauntsaninja: here is the promised follow-up PR!