Author jab
Recipients izbyshev, jab, methane, serhiy.storchaka
Date 2018-03-07.07:59:07
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1520409547.91.0.467229070634.issue33018@psf.upfronthosting.co.za>
In-reply-to
Content
Creating this issue by request of INADA Naoki to discuss my proposed patch in https://github.com/python/cpython/pull/5944.

Copy/pasting from that PR:

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.
History
Date User Action Args
2018-03-07 07:59:07jabsetrecipients: + jab, methane, serhiy.storchaka, izbyshev
2018-03-07 07:59:07jabsetmessageid: <1520409547.91.0.467229070634.issue33018@psf.upfronthosting.co.za>
2018-03-07 07:59:07jablinkissue33018 messages
2018-03-07 07:59:07jabcreate