Skip to content
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

Multiple inheritance error when using slots #667

Closed
jacobg opened this issue Aug 18, 2020 · 5 comments
Closed

Multiple inheritance error when using slots #667

jacobg opened this issue Aug 18, 2020 · 5 comments
Milestone

Comments

@jacobg
Copy link

jacobg commented Aug 18, 2020

The following classes definitions causes an error:

    @attr.s(auto_attribs=True, frozen=True, slots=True, collect_by_mro=True)
    class Foo:
        foo: str

    @attr.s(auto_attribs=True, frozen=True, slots=True, collect_by_mro=True)
    class Bar:
        bar: str

    @attr.s(auto_attribs=True, frozen=True, slots=True, collect_by_mro=True)
    class Baz(Foo, Bar):
        baz: str
>       class Baz(Foo, Bar):
E       TypeError: multiple bases have instance lay-out conflict

Note that this error occurs on master with a commit that seems to purport to fix this problem:
#635

Removing the slots decorator kwargs resolves the error.

Is there a workaround that supports slots?

This was referenced Aug 18, 2020
@jacobg jacobg changed the title Multiple inheritance error Multiple inheritance error when using slots Aug 18, 2020
@hynek
Copy link
Member

hynek commented Aug 18, 2020

To be clear: #635 has nothing to do with this problem and the problem exists in 19.3 too.

I suspect it's related to the way we create slotted classes in

cls = type(self._cls)(self._cls.__name__, self._cls.__bases__, cd)

Since slots become True by default in NG, we should have a look if we can fix this.

@hynek hynek added the Bug label Aug 18, 2020
@hynek hynek added this to the 20.1.0 milestone Aug 18, 2020
@Tinche
Copy link
Member

Tinche commented Aug 18, 2020

An even smaller test case:

import attr


@attr.s(slots=True)
class A:
    a = attr.ib()


@attr.s(slots=True)
class B:
    b = attr.ib()


@attr.s(slots=True)
class C(A, B):
    pass

@Tinche
Copy link
Member

Tinche commented Aug 18, 2020

Actually, C doesn't even have to be an attrs class:

import attr


@attr.s(slots=True)
class A:
    a = attr.ib()


@attr.s(slots=True)
class B:
    b = attr.ib()


class C(A, B):
    pass

In fact, browsing the Python docs (https://docs.python.org/3/reference/datamodel.html#notes-on-using-slots):

Multiple inheritance with multiple slotted parent classes can be used, but only one parent is allowed to have attributes created by slots (the other bases must have empty slot layouts) - violations raise TypeError.

So this is a Python limitation.

@hynek
Copy link
Member

hynek commented Aug 19, 2020

Thank you for the research Tin! I will add an entry to the glossary.

@jacobg
Copy link
Author

jacobg commented Aug 19, 2020

@Tinche @hynek Thank you for looking into this issue!

@hynek hynek added Documentation and removed Bug labels Aug 19, 2020
@hynek hynek closed this as completed in c67a649 Aug 19, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants