[pypy-issue] Issue #2480: cpyext tp_bases doesn't properly expose multiple inheritance (pypy/pypy)

Jason Rhinelander issues-reply at bitbucket.org
Thu Feb 23 11:54:08 EST 2017


New issue 2480: cpyext tp_bases doesn't properly expose multiple inheritance
https://bitbucket.org/pypy/pypy/issues/2480/cpyext-tp_bases-doesnt-properly-expose

Jason Rhinelander:

I'm working to extend pybind11's multiple inheritance support to allow multiple inheritance from the Python side (https://github.com/pybind/pybind11/pull/693), and ran into an issue where PyPy's `PyTypeObject.tp_bases` only contains the first parent class, e.g.:

```
class B1(object):
    pass
class B2(object):
    pass
class A(B1, B2):
    pass
```

cpyext code that gets the `PyTypeObject *` for `A` will have `tp_bases` set to a tuple of just `B1` instead of both `B1` and `B2`.

`A.__bases__`, however, contains the correct types.

My test code for this in this commit: https://github.com/jagerman/pybind11/commit/7e13ad2d044de7fd8641bac07ab70871c130421a

combined with this test code:
```
from __future__ import print_function
from pybind11_tests import Base1, Base2, debug_tp_bases
class A(object):
    pass
class A2(object):
    pass
class A3(A, A2):
    pass
class B(Base1, Base2):
    def __init__(self):
        Base1.__init__(self, 1)
        Base2.__init__(self, 2)
class C(A, B):
    def __init__(self):
        B.__init__(self)
print("A.__bases__:", A.__bases__)
debug_tp_bases(A)
print("A3.__bases__:", A3.__bases__)
debug_tp_bases(A3)
print("B.__bases__:", B.__bases__)
debug_tp_bases(B)
print("C.__bases__:", C.__bases__)
debug_tp_bases(C)
```
gives me (using current pypy nightly):
```
A.__bases__: (<type 'object'>,)
Type `A' tp_bases:
    - object
A3.__bases__: (<class '__main__.A'>, <class '__main__.A2'>)
Type `A3' tp_bases:
    - A
B.__bases__: (<class 'pybind11_tests.Base1'>, <class 'pybind11_tests.Base2'>)
Type `B' tp_bases:
    - Base1
C.__bases__: (<class '__main__.A'>, <class '__main__.B'>)
Type `C' tp_bases:
    - A
```

whereas CPython 2 and 3 give:
```
A.__bases__: (<type 'object'>,)
Type `A' tp_bases:
    - object
A3.__bases__: (<class '__main__.A'>, <class '__main__.A2'>)
Type `A3' tp_bases:
    - A
    - A2
B.__bases__: (<class 'pybind11_tests.Base1'>, <class 'pybind11_tests.Base2'>)
Type `B' tp_bases:
    - pybind11_tests.Base1
    - pybind11_tests.Base2
C.__bases__: (<class '__main__.A'>, <class '__main__.B'>)
Type `C' tp_bases:
    - A
    - B
```




More information about the pypy-issue mailing list