Skip to content

bpo-33018: Improve issubclass() error checking and message. #5944

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

Merged
merged 3 commits into from
Mar 22, 2018

Conversation

jab
Copy link
Contributor

@jab jab commented Mar 1, 2018

If you try something like issubclass('not a class', str), you get a helpful error message that immediately clues you in on what you did wrong:

>>> issubclass('not a class', str)
TypeError: issubclass() arg 1 must be a class

("AHA! I meant isinstance there. Thanks, friendly error message!")

But if you try this with some ABC, the error message is much less friendly!

>>> from some_library import SomeAbc
>>> issubclass('not a class', SomeAbc)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/abc.py", line 230, in __subclasscheck__
    cls._abc_negative_cache.add(subclass)
  File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/_weakrefset.py", line 84, in add
    self.data.add(ref(item, self._remove))
TypeError: cannot create weak reference to 'str' object

("WTF just went wrong?" Several more minutes of head-scratching ensues. Maybe a less experienced Python programmer who hits this hasn't seen weakrefs before and gets overwhelmed, maybe needlessly proceeding down a deep rabbit hole before realizing no knowledge of weakrefs was required to understand what they did wrong.)

Or how about this example:

>>> from collections import Reversible
>>> issubclass([1, 2, 3], Reversible)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/abc.py", line 207, in __subclasscheck__
    ok = cls.__subclasshook__(subclass)
  File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/_collections_abc.py", line 305, in __subclasshook__
    return _check_methods(C, "__reversed__", "__iter__")
  File "/usr/local/Cellar/python3/3.6.4_2/Frameworks/Python.framework/Versions/3.6/lib/python3.6/_collections_abc.py", line 73, in _check_methods
    mro = C.__mro__
AttributeError: 'list' object has no attribute '__mro__'

Here you don't even get the same type of error (AttributeError rather than TypeError), which seems unintentionally inconsistent.

This trivial patch fixes this, and will hopefully save untold numbers of future Python programmers some time and headache.

Let me know if any further changes are required, and thanks in advance for reviewing.

https://bugs.python.org/issue33018

@jab
Copy link
Contributor Author

jab commented Mar 1, 2018

Here's a build with this patch applied showing the fix in action:

Python 3.8.0a0 (heads/master-dirty:f0daa880a4, Mar  1 2018, 10:46:05)
[Clang 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from collections.abc import Reversible
>>> issubclass([1, 2, 3], Reversible)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jab/src/cpython/Lib/abc.py", line 143, in __subclasscheck__
    return _abc_subclasscheck(cls, subclass)
TypeError: issubclass() arg 1 must be a class

@zhangyangyu
Copy link
Member

zhangyangyu commented Mar 7, 2018

Check https://bugs.python.org/issue32999 please, some core devs don't want to limit the first arg only to type objects.

@zhangyangyu zhangyangyu requested a review from methane March 7, 2018 07:49
@methane
Copy link
Member

methane commented Mar 7, 2018

Please create new issue and discuss on it.

@jab
Copy link
Contributor Author

jab commented Mar 7, 2018

@methane methane changed the title Improve issubclass() error checking and message. bpo-33018: Improve issubclass() error checking and message. Mar 7, 2018
Copy link
Member

@ilevkivskyi ilevkivskyi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I think this looks good. Could you please add a NEWS item?

Copy link
Member

@methane methane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you revert fc7df0e too?

((PyTypeObject *)subclass)->tp_mro must be valid tuple.

@bedevere-bot
Copy link

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@ilevkivskyi
Copy link
Member

Would you revert fc7df0e too?

I don't think we need to revert it. First of all the tests should stay, so I would just make another PR in addition to this one. Or you want to add the change to ->tp_mro to this PR?

@methane
Copy link
Member

methane commented Mar 22, 2018

I don't think we need to revert it. First of all the tests should stay, so I would just make another PR in addition to this one. Or you want to add the change to ->tp_mro to this PR?

Yes. I didn't mean revert adding test.
I want to minimize diff between 3.7 and 3.8 as possible at this time.
It's OK to make another change (before 3.7b3) to use ->tp_mro if it will be merged into 3.7 branch too.

@jab
Copy link
Contributor Author

jab commented Mar 22, 2018

Just added the NEWS entry: I have made the requested changes; please review again.

First time (getting a patch accepted (🎉!) and) using blurb. Hopefully that turned out ok.

Thanks for helping to get this landed!

@bedevere-bot
Copy link

Thanks for making the requested changes!

@methane, @ilevkivskyi: please review the changes made to this pull request.

Copy link
Member

@methane methane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I will create another PR later.

@ilevkivskyi
Copy link
Member

@methane

OK, I will create another PR later.

Thanks! Don't forget to backport your PR to 3.7, as I am backporting this one to 3.7 as @gvanrossum suggested.

Copy link
Member

@ilevkivskyi ilevkivskyi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks!

@ilevkivskyi ilevkivskyi merged commit 40472dd into python:master Mar 22, 2018
@miss-islington
Copy link
Contributor

Thanks @jab for the PR, and @ilevkivskyi for merging it 🌮🎉.. I'm working now to backport this PR to: 3.7.
🐍🍒⛏🤖

@bedevere-bot
Copy link

GH-6188 is a backport of this pull request to the 3.7 branch.

@ilevkivskyi
Copy link
Member

@jab Congrats on your first contribution!

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Mar 22, 2018
…-5944)

This improves error message for situations when a non-class is
checked w.r.t. an abstract base class.
(cherry picked from commit 40472dd)

Co-authored-by: jab <jab@users.noreply.github.com>
@jab
Copy link
Contributor Author

jab commented Mar 22, 2018

Thanks for making it possible!

miss-islington added a commit that referenced this pull request Mar 22, 2018
This improves error message for situations when a non-class is
checked w.r.t. an abstract base class.
(cherry picked from commit 40472dd)

Co-authored-by: jab <jab@users.noreply.github.com>
methane added a commit to methane/cpython that referenced this pull request Mar 22, 2018
bpo-33018 (pythonGH-5944) fixed bpo-32999 too.  So fc7df0e is not required
anymore.  Revert it except test case.
miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Mar 22, 2018
bpo-33018 (pythonGH-5944) fixed bpo-32999 too.  So fc7df0e is not required
anymore.  Revert it except test case.
(cherry picked from commit f757b72)

Co-authored-by: INADA Naoki <methane@users.noreply.github.com>
methane added a commit that referenced this pull request Mar 22, 2018
bpo-33018 (GH-5944) fixed bpo-32999 too.  So fc7df0e is not required
anymore.  Revert it except test case.
ilevkivskyi pushed a commit that referenced this pull request Mar 22, 2018
bpo-33018 (GH-5944) fixed bpo-32999 too.  So fc7df0e is not required
anymore.  Revert it except test case.
(cherry picked from commit f757b72)

Co-authored-by: INADA Naoki <methane@users.noreply.github.com>
jo2y pushed a commit to jo2y/cpython that referenced this pull request Mar 23, 2018
…-5944)

This improves error message for situations when a non-class is
checked w.r.t. an abstract base class.
jo2y pushed a commit to jo2y/cpython that referenced this pull request Mar 23, 2018
bpo-33018 (pythonGH-5944) fixed bpo-32999 too.  So fc7df0e is not required
anymore.  Revert it except test case.
@jab jab deleted the jab-improve-subclasshook-error branch March 23, 2018 07:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants