Skip to content

ABCMeta adds __weakref__ but not to __slots__ #128866

@barakatzir

Description

@barakatzir

Bug report

Bug description:

I stumbled upon the following error (code snippet from python 3.12.3 with gcc 13.2.0, but I also checked with 3.11 and 3.13):

>> from abc import ABCMeta
>>> class Abstract(metaclass=ABCMeta):
...  ...
... 
>>> class Concrete(Abstract):
...  __slots__ = ('__weakref__',)
... 
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<frozen abc>", line 106, in __new__
TypeError: __weakref__ slot disallowed: we already got one

This also happens when inheriting from abc.ABC. This surprised me since the documentation does not mention __weakref__ being added.
Adding to my confusion, the common abstract base classes from collections.abc do not have this behavior (I only checked Mapping, Sequence and Collection), i.e., __weakref__ attribute is not added to the class.

Another peculiarity here is that while a class with metaclass =ABCMeta is automatically weakref-able, and has a __weakref__ attribute, the __weakref__ cannot be found in its __slots__, and in fact there might not even be a __slots__ attribute anywhere in the MRO!

>>> import abc
>>> class A(abc.ABC): ...
... 
>>> A.__weakref__
<attribute '__weakref__' of 'A' objects>
>>> A.__slots__  # __slots__ attribute exist but no __weakref__
()
>>> class B(metaclass=abc.ABCMeta): ...
... 
>>> B.__weakref__
<attribute '__weakref__' of 'B' objects>
>>> B.__slots__  # __slots__ attribute does not exist
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'B' has no attribute '__slots__'. Did you mean: '__class__'?

At the very least this warrant adding documentation to abc.ABC and abc.ABCMeta. A better fix IMO is adding __weakref__ to __slots__.
Another solution (which I like the most) is not adding __weakref__ to abstract classes to begin with, but I suspect this might break some code.

CPython versions tested on:

3.11, 3.12, 3.13

Operating systems tested on:

Linux

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirstdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions