classification
Title: Inheriting from NoneType does not fail consistently
Type: behavior Stage: resolved
Components: Interpreter Core Versions: Python 3.6
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: benjamin.peterson, brechtm, python-dev, yselivanov
Priority: normal Keywords:

Created on 2015-08-06 07:00 by brechtm, last changed 2015-10-07 02:43 by python-dev. This issue is now closed.

Messages (8)
msg248112 - (view) Author: Brecht Machiels (brechtm) Date: 2015-08-06 07:00
These both raise an exception:

    class Null(type(None)): pass

    class Null(object, type(None)): pass

The following does not:

    class Object(object): pass
    class Null(Object, type(None)): pass

This should also raise a TypeError.
Also, the result is not what I expected, as "bool(Null())" yields True.
msg248113 - (view) Author: Armin Rigo (arigo) * (Python committer) Date: 2015-08-06 08:28
FWIW ``bool(Null())`` gives "correctly" the result False in CPython 3.5.

The problem in my opinion is that "!Py_TPFLAGS_BASETYPE" is checked only on the best base instead of on all bases.  It lets this kind of nonsense pass through.

In CPython 2.7 (but not 3.5) the following example also works (and is equally nonsense):

    class A(int): pass
    class Bogus(A, bool): pass

Although we're subclassing NoneType or bool, I did not manage to get a CPython crash from any of these examples.
msg248114 - (view) Author: Brecht Machiels (brechtm) Date: 2015-08-06 08:58
Similar inconsistent behavior for:

    class Object(object): pass
    class Integer(Object, int): pass

versus

    class Integer(object, int): pass

However, I'm successfully using the first version, which saves some boilerplate code for emulating ints. Instances of Integer seem to behave exactly like ints. Personally, I wouldn't like to loose this ability. (May I shouldn't have created this ticket :).
msg248115 - (view) Author: Brecht Machiels (brechtm) Date: 2015-08-06 09:03
This is a real-world example where this type of inheritance is used: https://github.com/brechtm/rinohtype/blob/8bd961243c1059aa7cb738493e4687f7a5930d5b/rinoh/backend/pdf/cos.py#L121

I don't think there is any inherent reason not to subclass from (indirectly) object and int at the same time. I understand this is only a limitation of CPython? Please correct me if I'm wrong.
msg248124 - (view) Author: Armin Rigo (arigo) * (Python committer) Date: 2015-08-06 11:28
@brechtm No, the example you give is wrong.  It is correct that this refuses to work (and unrelated to this bug):

    class Integer(object, int): pass

for reasons explained in the docs.
msg248125 - (view) Author: Armin Rigo (arigo) * (Python committer) Date: 2015-08-06 11:30
To be clearer, this bug report is, more precisely, about subclassing built-in classes that are not meant to be subclassable.  This includes type(None) and bool.
msg248126 - (view) Author: Brecht Machiels (brechtm) Date: 2015-08-06 12:56
Ok. I was afraid a fix for this might affect "class Integer(Object, int)". Good to hear it shouldn't.
msg252447 - (view) Author: Roundup Robot (python-dev) (Python triager) Date: 2015-10-07 02:43
New changeset c46ccfac8763 by Benjamin Peterson in branch '2.7':
prevent unacceptable bases from becoming bases through multiple inheritance (#24806)
https://hg.python.org/cpython/rev/c46ccfac8763

New changeset e670b37e7b14 by Benjamin Peterson in branch '3.4':
prevent unacceptable bases from becoming bases through multiple inheritance (#24806)
https://hg.python.org/cpython/rev/e670b37e7b14

New changeset e02e4afcce6a by Benjamin Peterson in branch '3.5':
merge 3.4 (#24806)
https://hg.python.org/cpython/rev/e02e4afcce6a

New changeset 4b2a2688d2ad by Benjamin Peterson in branch 'default':
merge 3.5 (closes #24806)
https://hg.python.org/cpython/rev/4b2a2688d2ad
History
Date User Action Args
2015-10-07 02:43:12python-devsetstatus: open -> closed

nosy: + python-dev
messages: + msg252447

resolution: fixed
stage: resolved
2015-08-06 15:54:26yselivanovsetnosy: + benjamin.peterson, yselivanov

versions: - Python 2.7, Python 3.2, Python 3.3, Python 3.4, Python 3.5
2015-08-06 12:56:06brechtmsetmessages: + msg248126
2015-08-06 11:30:59arigosetnosy: - arigo
2015-08-06 11:30:36arigosetmessages: + msg248125
2015-08-06 11:28:58arigosetmessages: + msg248124
2015-08-06 09:03:17brechtmsetmessages: + msg248115
2015-08-06 08:58:49brechtmsetmessages: + msg248114
2015-08-06 08:28:03arigosetnosy: + arigo
messages: + msg248113
2015-08-06 07:00:10brechtmcreate