Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Doc/whatsnew/3.9.rst
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,12 @@ Changes in the Python API
since the *buffering* parameter has been removed.
(Contributed by Victor Stinner in :issue:`39357`.)

* The inheritance registry for an :class:`~abc.ABCMeta` instance is now
set up in the ``__init__()`` method instead of the ``__new__()`` method.
Be aware of this if you implement a subclass of ``ABCMeta`` and override
its ``__new__()`` or ``__init__()`` methods.
(Contributed by Serhiy Storchaka in :issue:`28869`.)


CPython bytecode changes
------------------------
Expand Down
4 changes: 1 addition & 3 deletions Lib/_py_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,7 @@ class ABCMeta(type):
# external code.
_abc_invalidation_counter = 0

def __new__(mcls, name, bases, namespace, /, **kwargs):
cls = super().__new__(mcls, name, bases, namespace, **kwargs)
def __init__(cls, name, bases, namespace, /, **kwargs):
# Compute set of abstract method names
abstracts = {name
for name, value in namespace.items()
Expand All @@ -49,7 +48,6 @@ def __new__(mcls, name, bases, namespace, /, **kwargs):
cls._abc_cache = WeakSet()
cls._abc_negative_cache = WeakSet()
cls._abc_negative_cache_version = ABCMeta._abc_invalidation_counter
return cls

def register(cls, subclass):
"""Register a virtual subclass of an ABC.
Expand Down
4 changes: 1 addition & 3 deletions Lib/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,8 @@ class ABCMeta(type):
implementations defined by the registering ABC be callable (not
even via super()).
"""
def __new__(mcls, name, bases, namespace, **kwargs):
cls = super().__new__(mcls, name, bases, namespace, **kwargs)
def __init__(cls, name, bases, namespace, /, **kwargs):
_abc_init(cls)
return cls

def register(cls, subclass):
"""Register a virtual subclass of an ABC.
Expand Down
7 changes: 7 additions & 0 deletions Lib/test/test_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,13 @@ class C(with_metaclass(abc_ABCMeta, A, B)):
pass
self.assertEqual(C.__class__, abc_ABCMeta)

def test_type_module(self):
class A(metaclass=abc_ABCMeta):
pass
self.assertEqual(A.__module__, __name__)
B = abc_ABCMeta('B', (), {})
self.assertEqual(B.__module__, __name__)


class TestABCWithInitSubclass(unittest.TestCase):
def test_works_with_init_subclass(self):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Types created by calling :func:`~abc.ABCMeta` have now a proper
:attr:`__module__` attribute.
The inheritance registry for an ``ABCMeta`` instance is now
set up in the ``__init__()`` method instead of the ``__new__()`` method.