summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorÉric Araujo <merwok@netwok.org>2011-02-24 18:03:10 (GMT)
committerÉric Araujo <merwok@netwok.org>2011-02-24 18:03:10 (GMT)
commit6c3787cb70d8efa5f70939a5db300f56a724d698 (patch)
treebab3ed85944db0993682255f1bb751c788f38001
parent5390d00cc6b99a375140f22e8d75580c1f4cb0a4 (diff)
downloadcpython-6c3787cb70d8efa5f70939a5db300f56a724d698.zip
cpython-6c3787cb70d8efa5f70939a5db300f56a724d698.tar.gz
cpython-6c3787cb70d8efa5f70939a5db300f56a724d698.tar.bz2
Allow usage of SomeABC.register as a class decorator. Patch by Edoardo Spadolini (#10868).
-rw-r--r--Doc/library/abc.rst3
-rw-r--r--Lib/abc.py8
-rw-r--r--Lib/test/test_abc.py24
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS3
5 files changed, 36 insertions, 3 deletions
diff --git a/Doc/library/abc.rst b/Doc/library/abc.rst
index 9fadbd2..2eced45 100644
--- a/Doc/library/abc.rst
+++ b/Doc/library/abc.rst
@@ -55,6 +55,9 @@ This module provides the following class:
assert issubclass(tuple, MyABC)
assert isinstance((), MyABC)
+ .. versionchanged:: 3.3
+ Returns the registered subclass, to allow usage as a class decorator.
+
You can also override this method in an abstract base class:
.. method:: __subclasshook__(subclass)
diff --git a/Lib/abc.py b/Lib/abc.py
index a6c2dc4..40f88b9 100644
--- a/Lib/abc.py
+++ b/Lib/abc.py
@@ -133,11 +133,14 @@ class ABCMeta(type):
return cls
def register(cls, subclass):
- """Register a virtual subclass of an ABC."""
+ """Register a virtual subclass of an ABC.
+
+ Returns the subclass, to allow usage as a class decorator.
+ """
if not isinstance(subclass, type):
raise TypeError("Can only register classes")
if issubclass(subclass, cls):
- return # Already a subclass
+ return subclass # Already a subclass
# Subtle: test for cycles *after* testing for "already a subclass";
# this means we allow X.register(X) and interpret it as a no-op.
if issubclass(cls, subclass):
@@ -145,6 +148,7 @@ class ABCMeta(type):
raise RuntimeError("Refusing to create an inheritance cycle")
cls._abc_registry.add(subclass)
ABCMeta._abc_invalidation_counter += 1 # Invalidate negative cache
+ return subclass
def _dump_registry(cls, file=None):
"""Debug helper to print the ABC registry."""
diff --git a/Lib/test/test_abc.py b/Lib/test/test_abc.py
index d86f97c..1319a64 100644
--- a/Lib/test/test_abc.py
+++ b/Lib/test/test_abc.py
@@ -121,11 +121,32 @@ class TestABC(unittest.TestCase):
self.assertFalse(issubclass(B, (A,)))
self.assertNotIsInstance(b, A)
self.assertNotIsInstance(b, (A,))
- A.register(B)
+ B1 = A.register(B)
+ self.assertTrue(issubclass(B, A))
+ self.assertTrue(issubclass(B, (A,)))
+ self.assertIsInstance(b, A)
+ self.assertIsInstance(b, (A,))
+ self.assertIs(B1, B)
+ class C(B):
+ pass
+ c = C()
+ self.assertTrue(issubclass(C, A))
+ self.assertTrue(issubclass(C, (A,)))
+ self.assertIsInstance(c, A)
+ self.assertIsInstance(c, (A,))
+
+ def test_register_as_class_deco(self):
+ class A(metaclass=abc.ABCMeta):
+ pass
+ @A.register
+ class B(object):
+ pass
+ b = B()
self.assertTrue(issubclass(B, A))
self.assertTrue(issubclass(B, (A,)))
self.assertIsInstance(b, A)
self.assertIsInstance(b, (A,))
+ @A.register
class C(B):
pass
c = C()
@@ -133,6 +154,7 @@ class TestABC(unittest.TestCase):
self.assertTrue(issubclass(C, (A,)))
self.assertIsInstance(c, A)
self.assertIsInstance(c, (A,))
+ self.assertIs(C, A.register(C))
def test_isinstance_invalidation(self):
class A(metaclass=abc.ABCMeta):
diff --git a/Misc/ACKS b/Misc/ACKS
index c22e360..8066ebc 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -798,6 +798,7 @@ Rafal Smotrzyk
Dirk Soede
Paul Sokolovsky
Cody Somerville
+Edoardo Spadolini
Clay Spence
Per Spilling
Joshua Spoerri
diff --git a/Misc/NEWS b/Misc/NEWS
index 91a727a..6df1ace 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -30,6 +30,9 @@ Core and Builtins
Library
-------
+- Issue #10868: Allow usage of the register method of an ABC as a class
+ decorator.
+
- Issue #11224: Fixed a regression in tarfile that affected the file-like
objects returned by TarFile.extractfile() regarding performance, memory
consumption and failures with the stream interface.