summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2017-12-15 14:13:41 +0200
committerGitHub <noreply@github.com>2017-12-15 14:13:41 +0200
commit3327a2ddf1eaf8cc678f0219ba9edf7d632d1b20 (patch)
treed5913c7f893cc889b6a0b10142a66a01c709ac74
parent2e3f5701858d1fc04caedefdd9a8ea43810270d2 (diff)
downloadcpython-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.rst8
-rw-r--r--Lib/inspect.py4
-rw-r--r--Lib/test/test_inspect.py15
-rw-r--r--Lib/test/test_types.py4
-rw-r--r--Lib/types.py1
-rw-r--r--Misc/NEWS.d/next/Library/2017-12-10-00-57-51.bpo-32265.kELtTE.rst3
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.