Tests for @abstractproperty by Jeffrey Yasskin.
(The previous changes to abc.py were also by him).
Put back a comment about using super() for properties
(I didn't realize this worked).
diff --git a/Lib/abc.py b/Lib/abc.py
index ab6325e..07836e6 100644
--- a/Lib/abc.py
+++ b/Lib/abc.py
@@ -30,6 +30,8 @@
Requires that the metaclass is ABCMeta or derived from it. A
class that has a metaclass derived from ABCMeta cannot be
instantiated unless all of its abstract properties are overridden.
+ The abstract properties can be called using any of the the normal
+ 'super' call mechanisms.
Usage:
diff --git a/Lib/test/test_abc.py b/Lib/test/test_abc.py
index aecb800..f93f3d3 100644
--- a/Lib/test/test_abc.py
+++ b/Lib/test/test_abc.py
@@ -19,26 +19,42 @@
def bar(self): pass
self.assertEqual(hasattr(bar, "__isabstractmethod__"), False)
- def test_abstractmethod_integration(self):
+ def test_abstractproperty_basics(self):
+ @abc.abstractproperty
+ def foo(self): pass
+ self.assertEqual(foo.__isabstractmethod__, True)
+ def bar(self): pass
+ self.assertEqual(hasattr(bar, "__isabstractmethod__"), False)
+
class C(metaclass=abc.ABCMeta):
- @abc.abstractmethod
- def foo(self): pass # abstract
- def bar(self): pass # concrete
- self.assertEqual(C.__abstractmethods__, {"foo"})
- self.assertRaises(TypeError, C) # because foo is abstract
+ @abc.abstractproperty
+ def foo(self): return 3
class D(C):
- def bar(self): pass # concrete override of concrete
- self.assertEqual(D.__abstractmethods__, {"foo"})
- self.assertRaises(TypeError, D) # because foo is still abstract
- class E(D):
- def foo(self): pass
- self.assertEqual(E.__abstractmethods__, set())
- E() # now foo is concrete, too
- class F(E):
- @abc.abstractmethod
- def bar(self): pass # abstract override of concrete
- self.assertEqual(F.__abstractmethods__, {"bar"})
- self.assertRaises(TypeError, F) # because bar is abstract now
+ @property
+ def foo(self): return super().foo
+ self.assertEqual(D().foo, 3)
+
+ def test_abstractmethod_integration(self):
+ for abstractthing in [abc.abstractmethod, abc.abstractproperty]:
+ class C(metaclass=abc.ABCMeta):
+ @abstractthing
+ def foo(self): pass # abstract
+ def bar(self): pass # concrete
+ self.assertEqual(C.__abstractmethods__, {"foo"})
+ self.assertRaises(TypeError, C) # because foo is abstract
+ class D(C):
+ def bar(self): pass # concrete override of concrete
+ self.assertEqual(D.__abstractmethods__, {"foo"})
+ self.assertRaises(TypeError, D) # because foo is still abstract
+ class E(D):
+ def foo(self): pass
+ self.assertEqual(E.__abstractmethods__, set())
+ E() # now foo is concrete, too
+ class F(E):
+ @abstractthing
+ def bar(self): pass # abstract override of concrete
+ self.assertEqual(F.__abstractmethods__, {"bar"})
+ self.assertRaises(TypeError, F) # because bar is abstract now
def test_registration_basics(self):
class A(metaclass=abc.ABCMeta):