File tree 3 files changed +33
-10
lines changed
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:
343
343
344
344
Returns *cls *, to allow usage as a class decorator.
345
345
346
- If *cls * has any subclasses, raises a :exc: `RuntimeError `.
347
-
348
346
If *cls * is not an instance of ABCMeta, does nothing.
349
347
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
+
350
356
.. versionadded :: 3.10
351
357
352
358
.. rubric :: Footnotes
Original file line number Diff line number Diff line change @@ -122,8 +122,7 @@ def _abc_caches_clear(cls):
122
122
_reset_caches (cls )
123
123
124
124
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.
127
126
128
127
If a class has had one of its abstract methods implemented after the
129
128
class was created, the method will not be considered implemented until
@@ -136,8 +135,6 @@ class after this function is called.
136
135
137
136
Returns cls, to allow usage as a class decorator.
138
137
139
- If cls is has any subclasses, raises a RuntimeError.
140
-
141
138
If cls is not an instance of ABCMeta, does nothing.
142
139
"""
143
140
if not hasattr (cls , '__abstractmethods__' ):
@@ -146,10 +143,6 @@ class after this function is called.
146
143
# testing), and we want to handle both cases.
147
144
return cls
148
145
149
- if cls .__subclasses__ ():
150
- raise RuntimeError ("cannot update abstract methods of class after"
151
- " subclassing" )
152
-
153
146
abstracts = set ()
154
147
# Check the existing abstract methods of the parents, keep only the ones
155
148
# that are not implemented.
Original file line number Diff line number Diff line change @@ -612,6 +612,30 @@ def foo(self):
612
612
msg = "class C with abstract method foo"
613
613
self .assertRaisesRegex (TypeError , msg , C )
614
614
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 ()
615
639
616
640
617
641
class TestABCWithInitSubclass (unittest .TestCase ):
You can’t perform that action at this time.