File tree Expand file tree Collapse file tree 3 files changed +33
-10
lines changed Expand file tree Collapse file tree 3 files changed +33
-10
lines changed Original file line number Diff line number Diff 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
Original file line number Diff line number Diff line change @@ -122,8 +122,7 @@ def _abc_caches_clear(cls):
122122 _reset_caches (cls )
123123
124124def 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.
Original file line number Diff line number Diff 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 ):
You can’t perform that action at this time.
0 commit comments