Skip to content

slots declared on attrs-decorated class are ignored/lost #1637

Description

@couteau

If a slotted attrs class declares its own slots, those slots are lost/ignored when the class is processed by attrs. E.g.

@attrs.define
class A:
    __slots__ = ("private",)

    public: str = "foo"

a = A()

a.private = 1

produces the error TypeError: descriptor 'private' for 'A' objects doesn't apply to a 'A' object.

However, declaring an attrs class that subclasses a class that defines slots, the parent class's slots are preserved. E.g.

class Base:
    __slots__ = ("private",)

@attrs.define
class B(Base):
    public: str = "bar"

b = B()

b.private = 1

sets the slots attribute without issue.

Is this intentional behavior or dictated by the design of attrs? I've looked at the code and it looks like it goes out and gets slots defined on base classes and adds them to the slots defined on the new class. Using that same method, it doesn't look like it would be hard to preserve slots declared on the slotted attrs class itself, but I haven't tried to code it and I don't know if it would break something I'm not seeing. (Note that declaring __slots__ on a class decorated with @attrs.define(slotted=False) doesn't work for other reasons, so this question/issue really only applies to slotted attrs classes).

It can often be useful to have private attributes on a class that may be used for internal instance management but aren't really part of the data model represented by the class and should be ignored by attrs--not included in the init or hash or equality functions. This can, of course, be accomplished by declaring the attribute with init=False, hash=False, and eq=False, but the attribute still shows up in the collections returned by attrs.fields or attrs.fields_dict and is serialized by attrs.asdict (which, similarly, can be worked around with a filter). Declaring slots would be a simple way to allow an instance to have attributes that attrs is entirely unaware of. Using a base class is a workaround, but it would be preferable not to have to create a separate base class or mixin solely to add extra slots.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions