Skip to content

Slots class holding a reference to the original version #407

@gmacon

Description

@gmacon

I have a class hierarchy implemented with slots enabled, like this:

import attr

@attr.s(slots=True)
class BaseClass(object):
    foo = attr.ib(default='foo')

@attr.s(slots=True)
class SubClass(BaseClass):
    bar = attr.ib(default='bar')

This works fine until I wanted to introspect the class hierarchy:

BaseClass.__subclasses__()  # returns [<class '__main__.SubClass'>, <class '__main__.SubClass'>]

One of these is the original class, and the other is the new one created and returned by attr.s. This behavior manifests on both Python 3 and Python 2 (3.7.0 and 2.7.14, to be specific).

My understanding was that classes kept weak references to their subclasses to allow the __subclasses__ method to work, and I know that attrs creates and returns a new class when slots=True, but it's not clear to me why the old class stays around. I don't see any obvious place where a strong reference to it is held.

I guessed that there might be a reference cycle somewhere, so I tried adding a call to gc.collect() and checking gc.garbage, but that turned out to be incorrect.

Because I didn't see that the reference-counting mentioned in this comment was ever addressed, I also guessed that this might be a leak due to the __class__ closure cell fixup. I decided that this isn't the cause, either, because Python 2 does not have the __class__ closure cell.

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