bpo-32265: Classify class and static methods of builtin types. (#4776)
Add types.ClassMethodDescriptorType for unbound class methods.
This commit is contained in:
parent
2e3f570185
commit
3327a2ddf1
|
@ -155,6 +155,14 @@ Standard names are defined for the following types:
|
||||||
.. versionadded:: 3.7
|
.. 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)
|
.. class:: ModuleType(name, doc=None)
|
||||||
|
|
||||||
The type of :term:`modules <module>`. Constructor takes the name of the
|
The type of :term:`modules <module>`. Constructor takes the name of the
|
||||||
|
|
|
@ -457,10 +457,10 @@ def classify_class_attrs(cls):
|
||||||
continue
|
continue
|
||||||
obj = get_obj if get_obj is not None else dict_obj
|
obj = get_obj if get_obj is not None else dict_obj
|
||||||
# Classify the object or its descriptor.
|
# Classify the object or its descriptor.
|
||||||
if isinstance(dict_obj, staticmethod):
|
if isinstance(dict_obj, (staticmethod, types.BuiltinMethodType)):
|
||||||
kind = "static method"
|
kind = "static method"
|
||||||
obj = dict_obj
|
obj = dict_obj
|
||||||
elif isinstance(dict_obj, classmethod):
|
elif isinstance(dict_obj, (classmethod, types.ClassMethodDescriptorType)):
|
||||||
kind = "class method"
|
kind = "class method"
|
||||||
obj = dict_obj
|
obj = dict_obj
|
||||||
elif isinstance(dict_obj, property):
|
elif isinstance(dict_obj, property):
|
||||||
|
|
|
@ -858,7 +858,8 @@ class TestClassesAndFunctions(unittest.TestCase):
|
||||||
|
|
||||||
attrs = attrs_wo_objs(A)
|
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(('__init__', 'method', object), attrs, 'missing __init__')
|
||||||
|
|
||||||
self.assertIn(('s', 'static method', A), attrs, 'missing static method')
|
self.assertIn(('s', 'static method', A), attrs, 'missing static method')
|
||||||
|
@ -923,6 +924,18 @@ class TestClassesAndFunctions(unittest.TestCase):
|
||||||
if isinstance(builtin, type):
|
if isinstance(builtin, type):
|
||||||
inspect.classify_class_attrs(builtin)
|
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):
|
def test_classify_DynamicClassAttribute(self):
|
||||||
class Meta(type):
|
class Meta(type):
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
|
|
|
@ -594,6 +594,10 @@ class TypesTests(unittest.TestCase):
|
||||||
self.assertIsInstance(''.join, types.BuiltinMethodType)
|
self.assertIsInstance(''.join, types.BuiltinMethodType)
|
||||||
self.assertIsInstance([].append, 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):
|
class MappingProxyTests(unittest.TestCase):
|
||||||
mappingproxy = types.MappingProxyType
|
mappingproxy = types.MappingProxyType
|
||||||
|
|
|
@ -39,6 +39,7 @@ BuiltinMethodType = type([].append) # Same as BuiltinFunctionType
|
||||||
WrapperDescriptorType = type(object.__init__)
|
WrapperDescriptorType = type(object.__init__)
|
||||||
MethodWrapperType = type(object().__str__)
|
MethodWrapperType = type(object().__str__)
|
||||||
MethodDescriptorType = type(str.join)
|
MethodDescriptorType = type(str.join)
|
||||||
|
ClassMethodDescriptorType = type(dict.__dict__['fromkeys'])
|
||||||
|
|
||||||
ModuleType = type(sys)
|
ModuleType = type(sys)
|
||||||
|
|
||||||
|
|
|
@ -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.
|
Loading…
Reference in New Issue