diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2017-12-15 14:13:41 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-12-15 14:13:41 +0200 |
commit | 3327a2ddf1eaf8cc678f0219ba9edf7d632d1b20 (patch) | |
tree | d5913c7f893cc889b6a0b10142a66a01c709ac74 | |
parent | 2e3f5701858d1fc04caedefdd9a8ea43810270d2 (diff) | |
download | cpython-git-3327a2ddf1eaf8cc678f0219ba9edf7d632d1b20.tar.gz |
bpo-32265: Classify class and static methods of builtin types. (#4776)
Add types.ClassMethodDescriptorType for unbound class methods.
-rw-r--r-- | Doc/library/types.rst | 8 | ||||
-rw-r--r-- | Lib/inspect.py | 4 | ||||
-rw-r--r-- | Lib/test/test_inspect.py | 15 | ||||
-rw-r--r-- | Lib/test/test_types.py | 4 | ||||
-rw-r--r-- | Lib/types.py | 1 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2017-12-10-00-57-51.bpo-32265.kELtTE.rst | 3 |
6 files changed, 32 insertions, 3 deletions
diff --git a/Doc/library/types.rst b/Doc/library/types.rst index 89aca9c9df..bbc1d1301d 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 <module>`. Constructor takes the name of the diff --git a/Lib/inspect.py b/Lib/inspect.py index 8c121ce96c..b7551878b7 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 5b5bc650d2..e8eddbedf7 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 47488a615b..56848c1bf8 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 c5976f3057..ce4652f371 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 0000000000..16686c1b41 --- /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. |