bpo-32265: Classify class and static methods of builtin types. (#4776)

Add types.ClassMethodDescriptorType for unbound class methods.
diff --git a/Lib/inspect.py b/Lib/inspect.py
index 8c121ce..b755187 100644
--- a/Lib/inspect.py
+++ b/Lib/inspect.py
@@ -457,10 +457,10 @@
             continue
         obj = get_obj if get_obj is not None else dict_obj
         # Classify the object or its descriptor.
-        if isinstance(dict_obj, staticmethod):
+        if isinstance(dict_obj, (staticmethod, types.BuiltinMethodType)):
             kind = "static method"
             obj = dict_obj
-        elif isinstance(dict_obj, classmethod):
+        elif isinstance(dict_obj, (classmethod, types.ClassMethodDescriptorType)):
             kind = "class method"
             obj = dict_obj
         elif isinstance(dict_obj, property):
diff --git a/Lib/test/test_inspect.py b/Lib/test/test_inspect.py
index 5b5bc65..e8eddbe 100644
--- a/Lib/test/test_inspect.py
+++ b/Lib/test/test_inspect.py
@@ -858,7 +858,8 @@
 
         attrs = attrs_wo_objs(A)
 
-        self.assertIn(('__new__', 'method', object), attrs, 'missing __new__')
+        self.assertIn(('__new__', 'static method', object), attrs,
+                      'missing __new__')
         self.assertIn(('__init__', 'method', object), attrs, 'missing __init__')
 
         self.assertIn(('s', 'static method', A), attrs, 'missing static method')
@@ -923,6 +924,18 @@
             if isinstance(builtin, type):
                 inspect.classify_class_attrs(builtin)
 
+        attrs = attrs_wo_objs(bool)
+        self.assertIn(('__new__', 'static method', bool), attrs,
+                      'missing __new__')
+        self.assertIn(('from_bytes', 'class method', int), attrs,
+                      'missing class method')
+        self.assertIn(('to_bytes', 'method', int), attrs,
+                      'missing plain method')
+        self.assertIn(('__add__', 'method', int), attrs,
+                      'missing plain method')
+        self.assertIn(('__and__', 'method', bool), attrs,
+                      'missing plain method')
+
     def test_classify_DynamicClassAttribute(self):
         class Meta(type):
             def __getattr__(self, name):
diff --git a/Lib/test/test_types.py b/Lib/test/test_types.py
index 47488a6..56848c1 100644
--- a/Lib/test/test_types.py
+++ b/Lib/test/test_types.py
@@ -594,6 +594,10 @@
         self.assertIsInstance(''.join, types.BuiltinMethodType)
         self.assertIsInstance([].append, types.BuiltinMethodType)
 
+        self.assertIsInstance(int.__dict__['from_bytes'], types.ClassMethodDescriptorType)
+        self.assertIsInstance(int.from_bytes, types.BuiltinMethodType)
+        self.assertIsInstance(int.__new__, types.BuiltinMethodType)
+
 
 class MappingProxyTests(unittest.TestCase):
     mappingproxy = types.MappingProxyType
diff --git a/Lib/types.py b/Lib/types.py
index c5976f3..ce4652f 100644
--- a/Lib/types.py
+++ b/Lib/types.py
@@ -39,6 +39,7 @@
 WrapperDescriptorType = type(object.__init__)
 MethodWrapperType = type(object().__str__)
 MethodDescriptorType = type(str.join)
+ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
 
 ModuleType = type(sys)