From 3327a2ddf1eaf8cc678f0219ba9edf7d632d1b20 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Fri, 15 Dec 2017 14:13:41 +0200 Subject: bpo-32265: Classify class and static methods of builtin types. (#4776) Add types.ClassMethodDescriptorType for unbound class methods. --- Doc/library/types.rst | 8 ++++++++ Lib/inspect.py | 4 ++-- Lib/test/test_inspect.py | 15 ++++++++++++++- Lib/test/test_types.py | 4 ++++ Lib/types.py | 1 + .../next/Library/2017-12-10-00-57-51.bpo-32265.kELtTE.rst | 3 +++ 6 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2017-12-10-00-57-51.bpo-32265.kELtTE.rst diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 89aca9c..bbc1d13 100644 --- a/Doc/library/types.rst +++ b/Doc/library/types.rst @@ -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 `. Constructor takes the name of the 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 @@ 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): 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 @@ 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): 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 @@ 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 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 @@ 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 index 0000000..16686c1 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2017-12-10-00-57-51.bpo-32265.kELtTE.rst @@ -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. -- cgit v0.12