add support for abstract class and static methods #5867
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 @@
     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 @@
             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