]> granicus.if.org Git - python/commitdiff
bpo-32265: Classify class and static methods of builtin types. (#4776)
authorSerhiy Storchaka <storchaka@gmail.com>
Fri, 15 Dec 2017 12:13:41 +0000 (14:13 +0200)
committerGitHub <noreply@github.com>
Fri, 15 Dec 2017 12:13:41 +0000 (14:13 +0200)
Add types.ClassMethodDescriptorType for unbound class methods.

Doc/library/types.rst
Lib/inspect.py
Lib/test/test_inspect.py
Lib/test/test_types.py
Lib/types.py
Misc/NEWS.d/next/Library/2017-12-10-00-57-51.bpo-32265.kELtTE.rst [new file with mode: 0644]

index 89aca9c9df864a83718540845f3078c51e00c95e..bbc1d1301d2c2a291e3ff1e30a6faa7002686528 100644 (file)
@@ -155,6 +155,14 @@ Standard names are defined for the following types:
    .. versionadded:: 3.7
 
 
+.. data:: ClassMethodDescriptorType
+
+   The type of *unbound* class methods of some built-in data types such as
+   ``dict.__dict__['fromkeys']``.
+
+   .. versionadded:: 3.7
+
+
 .. class:: ModuleType(name, doc=None)
 
    The type of :term:`modules <module>`. Constructor takes the name of the
index 8c121ce96c415871122169ac6c0363604a7811e1..b7551878b74994ad70fe6de97d2d3b9e709ad510 100644 (file)
@@ -457,10 +457,10 @@ def classify_class_attrs(cls):
             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):
index 5b5bc650d2f828f4ee9819b5d85b91426101fd32..e8eddbedf7e1af0d4ef271ec7ada26008359d20d 100644 (file)
@@ -858,7 +858,8 @@ class TestClassesAndFunctions(unittest.TestCase):
 
         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 @@ class TestClassesAndFunctions(unittest.TestCase):
             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):
index 47488a615b1ebed3bff166f1bf1d16978140314d..56848c1bf87eb57fda71298cddb1f48862965052 100644 (file)
@@ -594,6 +594,10 @@ class TypesTests(unittest.TestCase):
         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
index c5976f3057ffc5cf0f8d6ff0ca660443000cf426..ce4652f37189763dbce5b3946d53b45d4e076493 100644 (file)
@@ -39,6 +39,7 @@ BuiltinMethodType = type([].append)     # Same as BuiltinFunctionType
 WrapperDescriptorType = type(object.__init__)
 MethodWrapperType = type(object().__str__)
 MethodDescriptorType = type(str.join)
+ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
 
 ModuleType = type(sys)
 
diff --git a/Misc/NEWS.d/next/Library/2017-12-10-00-57-51.bpo-32265.kELtTE.rst b/Misc/NEWS.d/next/Library/2017-12-10-00-57-51.bpo-32265.kELtTE.rst
new file mode 100644 (file)
index 0000000..16686c1
--- /dev/null
@@ -0,0 +1,3 @@
+All class and static methods of builtin types now are correctly classified
+by inspect.classify_class_attrs() and grouped in pydoc ouput. Added
+types.ClassMethodDescriptorType for unbound class methods of builtin types.