summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
authorBenjamin Peterson <benjamin@python.org>2010-08-17 00:52:52 (GMT)
committerBenjamin Peterson <benjamin@python.org>2010-08-17 00:52:52 (GMT)
commit45c257f193ddb8dfd54a0edb7253ee9254329ab7 (patch)
tree18b04c290ba0aadda9392a63bdebb2e1f64b9718 /Lib
parent36e791179c3bb49d45a17c27fbc39ec9b2a8694f (diff)
downloadcpython-45c257f193ddb8dfd54a0edb7253ee9254329ab7.zip
cpython-45c257f193ddb8dfd54a0edb7253ee9254329ab7.tar.gz
cpython-45c257f193ddb8dfd54a0edb7253ee9254329ab7.tar.bz2
add support for abstract class and static methods #5867
Diffstat (limited to 'Lib')
-rw-r--r--Lib/abc.py40
-rw-r--r--Lib/test/test_abc.py40
2 files changed, 79 insertions, 1 deletions
diff --git a/Lib/abc.py b/Lib/abc.py
index 0f98036..a6c2dc4 100644
--- a/Lib/abc.py
+++ b/Lib/abc.py
@@ -25,6 +25,46 @@ def abstractmethod(funcobj):
return funcobj
+class abstractclassmethod(classmethod):
+ """A decorator indicating abstract classmethods.
+
+ Similar to abstractmethod.
+
+ Usage:
+
+ class C(metaclass=ABCMeta):
+ @abstractclassmethod
+ def my_abstract_classmethod(cls, ...):
+ ...
+ """
+
+ __isabstractmethod__ = True
+
+ def __init__(self, callable):
+ callable.__isabstractmethod__ = True
+ super().__init__(callable)
+
+
+class abstractstaticmethod(staticmethod):
+ """A decorator indicating abstract staticmethods.
+
+ Similar to abstractmethod.
+
+ Usage:
+
+ class C(metaclass=ABCMeta):
+ @abstractstaticmethod
+ def my_abstract_staticmethod(...):
+ ...
+ """
+
+ __isabstractmethod__ = True
+
+ def __init__(self, callable):
+ callable.__isabstractmethod__ = True
+ super().__init__(callable)
+
+
class abstractproperty(property):
"""A decorator indicating abstract properties.
diff --git a/Lib/test/test_abc.py b/Lib/test/test_abc.py
index a6e7062..7fa18fb 100644
--- a/Lib/test/test_abc.py
+++ b/Lib/test/test_abc.py
@@ -34,8 +34,46 @@ class TestABC(unittest.TestCase):
def foo(self): return super().foo
self.assertEqual(D().foo, 3)
+ def test_abstractclassmethod_basics(self):
+ @abc.abstractclassmethod
+ def foo(cls): pass
+ self.assertEqual(foo.__isabstractmethod__, True)
+ @classmethod
+ def bar(cls): pass
+ self.assertEqual(hasattr(bar, "__isabstractmethod__"), False)
+
+ class C(metaclass=abc.ABCMeta):
+ @abc.abstractclassmethod
+ def foo(cls): return cls.__name__
+ self.assertRaises(TypeError, C)
+ class D(C):
+ @classmethod
+ def foo(cls): return super().foo()
+ self.assertEqual(D.foo(), 'D')
+ self.assertEqual(D().foo(), 'D')
+
+ def test_abstractstaticmethod_basics(self):
+ @abc.abstractstaticmethod
+ def foo(): pass
+ self.assertEqual(foo.__isabstractmethod__, True)
+ @staticmethod
+ def bar(): pass
+ self.assertEqual(hasattr(bar, "__isabstractmethod__"), False)
+
+ class C(metaclass=abc.ABCMeta):
+ @abc.abstractstaticmethod
+ def foo(): return 3
+ self.assertRaises(TypeError, C)
+ class D(C):
+ @staticmethod
+ def foo(): return 4
+ self.assertEqual(D.foo(), 4)
+ self.assertEqual(D().foo(), 4)
+
def test_abstractmethod_integration(self):
- for abstractthing in [abc.abstractmethod, abc.abstractproperty]:
+ for abstractthing in [abc.abstractmethod, abc.abstractproperty,
+ abc.abstractclassmethod,
+ abc.abstractstaticmethod]:
class C(metaclass=abc.ABCMeta):
@abstractthing
def foo(self): pass # abstract