8000 bpo-41905: added abc.update_abstractmethods by bentheiii · Pull Request #22485 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-41905: added abc.update_abstractmethods #22485

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 21 commits into from
Oct 6, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
update_abstractmethods doesn't care about subclasses for now
  • Loading branch information
ben avrahami committed Oct 4, 2020
commit 29dba375c53e5558c68e248cc9f14fb4cb648720
10 changes: 8 additions & 2 deletions Doc/library/abc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -343,10 +343,16 @@ The :mod:`abc` module also provides the following functions:

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

If *cls* has any subclasses, raises a :exc:`RuntimeError`.

If *cls* is not an instance of ABCMeta, does nothing.

.. note::

Since it is meant to be called before the class is used by anywhere but
in the decorator that called it, this function assumes that *cls* has no
subclasses. This means that if the decorator itself creates subclasses
to *cls*, it must also call *update_abstractmethods* on each of them.


.. versionadded:: 3.10

.. rubric:: Footnotes
Expand Down
9 changes: 1 addition & 8 deletions Lib/abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,7 @@ def _abc_caches_clear(cls):
_reset_caches(cls)

def update_abstractmethods(cls):
"""Repopulate the abstract methods of an abstract class, or a subclass of
an abstract class.
"""Recalculate the set of abstract methods of an abstract class.

If a class has had one of its abstract methods implemented after the
class was created, the method will not be considered implemented until
Expand All @@ -136,8 +135,6 @@ class after this function is called.

Returns cls, to allow usage as a class decorator.

If cls is has any subclasses, raises a RuntimeError.

If cls is not an instance of ABCMeta, does nothing.
"""
if not hasattr(cls, '__abstractmethods__'):
Expand All @@ -146,10 +143,6 @@ class after this function is called.
# testing), and we want to handle both cases.
return cls

if cls.__subclasses__():
raise RuntimeError("cannot update abstract methods of class after"
" subclassing")

abstracts = set()
# Check the existing abstract methods of the parents, keep only the ones
# that are not implemented.
Expand Down
24 changes: 24 additions & 0 deletions Lib/test/test_abc.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,30 @@ def foo(self):
msg = "class C with abstract method foo"
self.assertRaisesRegex(TypeError, msg, C)

def test_update_multi_inheritance(self):
class A(metaclass=abc_ABCMeta):
@abc.abstractmethod
def foo(self):
pass

class B(metaclass=abc_ABCMeta):
def foo(self):
pass

class C(B, A):
@abc.abstractmethod
def foo(self):
pass

self.assertEqual(C.__abstractmethods__, {'foo'})

del C.foo

abc.update_abstractmethods(C)

self.assertEqual(C.__abstractmethods__, set())

C()


class TestABCWithInitSubclass(unittest.TestCase):
Expand Down
0