8000 update_abstractmethods doesn't care about subclasses for now · python/cpython@29dba37 · GitHub
[go: up one dir, main page]

Skip to content

Commit 29dba37

Browse files
author
ben avrahami
committed
update_abstractmethods doesn't care about subclasses for now
1 parent ba8df08 commit 29dba37

File tree

3 files changed

+33
-10
lines changed

3 files changed

+33
-10
lines changed

Doc/library/abc.rst

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -343,10 +343,16 @@ The :mod:`abc` module also provides the following functions:
343343

344344
Returns *cls*, to allow usage as a class decorator.
345345

346-
If *cls* has any subclasses, raises a :exc:`RuntimeError`.
347-
348346
If *cls* is not an instance of ABCMeta, does nothing.
349347

348+
.. note::
349+
350+
Since it is meant to be called before the class is used by anywhere but
351+
in the decorator that called it, this function assumes that *cls* has no
352+
subclasses. This means that if the decorator itself creates subclasses
353+
to *cls*, it must also call *update_abstractmethods* on each of them.
354+
355+
350356
.. versionadded:: 3.10
351357

352358
.. rubric:: Footnotes

Lib/abc.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -122,8 +122,7 @@ def _abc_caches_clear(cls):
122122
_reset_caches(cls)
123123

124124
def update_abstractmethods(cls):
125-
"""Repopulate the abstract methods of an abstract class, or a subclass of
126-
an abstract class.
125+
"""Recalculate the set of abstract methods of an abstract class.
127126
128127
If a class has had one of its abstract methods implemented after the
129128
class was created, the method will not be considered implemented until
@@ -136,8 +135,6 @@ class after this function is called.
136135
137136
Returns cls, to allow usage as a class decorator.
138137
139-
If cls is has any subclasses, raises a RuntimeError.
140-
141138
If cls is not an instance of ABCMeta, does nothing.
142139
"""
143140
if not hasattr(cls, '__abstractmethods__'):
@@ -146,10 +143,6 @@ class after this function is called.
146143
# testing), and we want to handle both cases.
147144
return cls
148145

149-
if cls.__subclasses__():
150-
raise RuntimeError("cannot update abstract methods of class after"
151-
" subclassing")
152-
153146
abstracts = set()
154147
# Check the existing abstract methods of the parents, keep only the ones
155148
# that are not implemented.

Lib/test/test_abc.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,30 @@ def foo(self):
612612
msg = "class C with abstract method foo"
613613
self.assertRaisesRegex(TypeError, msg, C)
614614

615+
def test_update_multi_inheritance(self):
616+
class A(metaclass=abc_ABCMeta):
617+
@abc.abstractmethod
618+
def foo(self):
619+
pass
620+
621+
class B(metaclass=abc_ABCMeta):
622+
def foo(self):
623+
pass
624+
625+
class C(B, A):
626+
@abc.abstractmethod
627+
def foo(self):
628+
pass
629+
630+
self.assertEqual(C.__abstractmethods__, {'foo'})
631+
632+
del C.foo
633+
634+
abc.update_abstractmethods(C)
635+
636+
self.assertEqual(C.__abstractmethods__, set())
637+
638+
C()
615639

616640

617641
class TestABCWithInitSubclass(unittest.TestCase):

0 commit comments

Comments
 (0)
0