]> granicus.if.org Git - python/commitdiff
Allow usage of SomeABC.register as a class decorator. Patch by Edoardo Spadolini...
authorÉric Araujo <merwok@netwok.org>
Thu, 24 Feb 2011 18:03:10 +0000 (18:03 +0000)
committerÉric Araujo <merwok@netwok.org>
Thu, 24 Feb 2011 18:03:10 +0000 (18:03 +0000)
Doc/library/abc.rst
Lib/abc.py
Lib/test/test_abc.py
Misc/ACKS
Misc/NEWS

index 9fadbd234e337b1d0b350e75e1f09b5fd3c15e8b..2eced4541b42ce1e34516340ba1ad5c3bd3069c5 100644 (file)
@@ -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)
index a6c2dc48779d6ab339db70a21a81f56607b89856..40f88b92c0507a0565485327c4db4806cf6528b7 100644 (file)
@@ -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."""
index d86f97c068c743a85d86701460a1df14ab660f18..1319a64ef7c22dc31ddd103a56e776d7a6c5850b 100644 (file)
@@ -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):
index c22e360fa6ac482497178c4beb0e2f3b1ae2448d..8066ebcc16bd8bbcf52539660140f9a078c5a0fa 100644 (file)
--- 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
index 91a727addfbf676c818456deeaed81f59352ec64..6df1acef37dfd7d99eeb68df26d1b535116223a8 100644 (file)
--- 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.