Skip to content

Commit 45c257f

Browse files
committed
add support for abstract class and static methods python#5867
1 parent 36e7911 commit 45c257f

4 files changed

Lines changed: 107 additions & 1 deletion

File tree

Doc/library/abc.rst

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,32 @@ It also provides the following decorators:
157157
multiple-inheritance.
158158

159159

160+
.. decorator:: abstractclassmethod(function)
161+
162+
A subclass of the built-in :func:`classmethod`, indicating an abstract
163+
classmethod. Otherwise it is similar to :func:`abstractmethod`.
164+
165+
Usage::
166+
167+
class C(metaclass=ABCMeta):
168+
@abstractclassmethod
169+
def my_abstract_classmethod(cls, ...):
170+
...
171+
172+
173+
.. decorator:: abstractstaticmethod(function)
174+
175+
A subclass of the built-in :func:`staticmethod`, indicating an abstract
176+
staticmethod. Otherwise it is similar to :func:`abstractmethod`.
177+
178+
Usage::
179+
180+
class C(metaclass=ABCMeta):
181+
@abstractstaticmethod
182+
def my_abstract_staticmethod(...):
183+
...
184+
185+
160186
.. function:: abstractproperty(fget=None, fset=None, fdel=None, doc=None)
161187

162188
A subclass of the built-in :func:`property`, indicating an abstract property.

Lib/abc.py

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,46 @@ def my_abstract_method(self, ...):
2525
return funcobj
2626

2727

28+
class abstractclassmethod(classmethod):
29+
"""A decorator indicating abstract classmethods.
30+
31+
Similar to abstractmethod.
32+
33+
Usage:
34+
35+
class C(metaclass=ABCMeta):
36+
@abstractclassmethod
37+
def my_abstract_classmethod(cls, ...):
38+
...
39+
"""
40+
41+
__isabstractmethod__ = True
42+
43+
def __init__(self, callable):
44+
callable.__isabstractmethod__ = True
45+
super().__init__(callable)
46+
47+
48+
class abstractstaticmethod(staticmethod):
49+
"""A decorator indicating abstract staticmethods.
50+
51+
Similar to abstractmethod.
52+
53+
Usage:
54+
55+
class C(metaclass=ABCMeta):
56+
@abstractstaticmethod
57+
def my_abstract_staticmethod(...):
58+
...
59+
"""
60+
61+
__isabstractmethod__ = True
62+
63+
def __init__(self, callable):
64+
callable.__isabstractmethod__ = True
65+
super().__init__(callable)
66+
67+
2868
class abstractproperty(property):
2969
"""A decorator indicating abstract properties.
3070

Lib/test/test_abc.py

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,46 @@ class D(C):
3434
def foo(self): return super().foo
3535
self.assertEqual(D().foo, 3)
3636

37+
def test_abstractclassmethod_basics(self):
38+
@abc.abstractclassmethod
39+
def foo(cls): pass
40+
self.assertEqual(foo.__isabstractmethod__, True)
41+
@classmethod
42+
def bar(cls): pass
43+
self.assertEqual(hasattr(bar, "__isabstractmethod__"), False)
44+
45+
class C(metaclass=abc.ABCMeta):
46+
@abc.abstractclassmethod
47+
def foo(cls): return cls.__name__
48+
self.assertRaises(TypeError, C)
49+
class D(C):
50+
@classmethod
51+
def foo(cls): return super().foo()
52+
self.assertEqual(D.foo(), 'D')
53+
self.assertEqual(D().foo(), 'D')
54+
55+
def test_abstractstaticmethod_basics(self):
56+
@abc.abstractstaticmethod
57+
def foo(): pass
58+
self.assertEqual(foo.__isabstractmethod__, True)
59+
@staticmethod
60+
def bar(): pass
61+
self.assertEqual(hasattr(bar, "__isabstractmethod__"), False)
62+
63+
class C(metaclass=abc.ABCMeta):
64+
@abc.abstractstaticmethod
65+
def foo(): return 3
66+
self.assertRaises(TypeError, C)
67+
class D(C):
68+
@staticmethod
69+
def foo(): return 4
70+
self.assertEqual(D.foo(), 4)
71+
self.assertEqual(D().foo(), 4)
72+
3773
def test_abstractmethod_integration(self):
38-
for abstractthing in [abc.abstractmethod, abc.abstractproperty]:
74+
for abstractthing in [abc.abstractmethod, abc.abstractproperty,
75+
abc.abstractclassmethod,
76+
abc.abstractstaticmethod]:
3977
class C(metaclass=abc.ABCMeta):
4078
@abstractthing
4179
def foo(self): pass # abstract

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,8 @@ Extensions
9090
Library
9191
-------
9292

93+
- Issue #5867: Add abc.abstractclassmethod and abc.abstractstaticmethod.
94+
9395
- Issue #9605: posix.getlogin() decodes the username with file filesystem
9496
encoding and surrogateescape error handler. Patch written by David Watson.
9597

0 commit comments

Comments
 (0)