mirror of https://github.com/python/cpython
bpo-29418: Implement inspect.ismethodwrapper and fix inspect.isroutine for cases where methodwrapper is given (GH-19261)
Automerge-Triggered-By: GH:isidentical
This commit is contained in:
parent
3954fcb83f
commit
562c13f573
|
@ -429,6 +429,14 @@ attributes:
|
|||
Return ``True`` if the object is a built-in function or a bound built-in method.
|
||||
|
||||
|
||||
.. function:: ismethodwrapper(object)
|
||||
|
||||
Return ``True`` if the type of object is a :class:`~types.MethodWrapperType`.
|
||||
|
||||
These are instances of :class:`~types.MethodWrapperType`, such as :meth:`~object().__str__`,
|
||||
:meth:`~object().__eq__` and :meth:`~object().__repr__`
|
||||
|
||||
|
||||
.. function:: isroutine(object)
|
||||
|
||||
Return ``True`` if the object is a user-defined or built-in function or method.
|
||||
|
|
|
@ -121,6 +121,7 @@ __all__ = [
|
|||
"ismemberdescriptor",
|
||||
"ismethod",
|
||||
"ismethoddescriptor",
|
||||
"ismethodwrapper",
|
||||
"ismodule",
|
||||
"isroutine",
|
||||
"istraceback",
|
||||
|
@ -509,12 +510,17 @@ def isbuiltin(object):
|
|||
__self__ instance to which a method is bound, or None"""
|
||||
return isinstance(object, types.BuiltinFunctionType)
|
||||
|
||||
def ismethodwrapper(object):
|
||||
"""Return true if the object is a method wrapper."""
|
||||
return isinstance(object, types.MethodWrapperType)
|
||||
|
||||
def isroutine(object):
|
||||
"""Return true if the object is any kind of function or method."""
|
||||
return (isbuiltin(object)
|
||||
or isfunction(object)
|
||||
or ismethod(object)
|
||||
or ismethoddescriptor(object))
|
||||
or ismethoddescriptor(object)
|
||||
or ismethodwrapper(object))
|
||||
|
||||
def isabstract(object):
|
||||
"""Return true if the object is an abstract base class (ABC)."""
|
||||
|
@ -1887,13 +1893,9 @@ def getcoroutinelocals(coroutine):
|
|||
###############################################################################
|
||||
|
||||
|
||||
_WrapperDescriptor = type(type.__call__)
|
||||
_MethodWrapper = type(all.__call__)
|
||||
_ClassMethodWrapper = type(int.__dict__['from_bytes'])
|
||||
|
||||
_NonUserDefinedCallables = (_WrapperDescriptor,
|
||||
_MethodWrapper,
|
||||
_ClassMethodWrapper,
|
||||
_NonUserDefinedCallables = (types.WrapperDescriptorType,
|
||||
types.MethodWrapperType,
|
||||
types.ClassMethodDescriptorType,
|
||||
types.BuiltinFunctionType)
|
||||
|
||||
|
||||
|
@ -2533,7 +2535,7 @@ def _signature_from_callable(obj, *,
|
|||
elif not isinstance(obj, _NonUserDefinedCallables):
|
||||
# An object with __call__
|
||||
# We also check that the 'obj' is not an instance of
|
||||
# _WrapperDescriptor or _MethodWrapper to avoid
|
||||
# types.WrapperDescriptorType or types.MethodWrapperType to avoid
|
||||
# infinite recursion (and even potential segfault)
|
||||
call = _signature_get_user_defined_method(type(obj), '__call__')
|
||||
if call is not None:
|
||||
|
|
|
@ -44,7 +44,8 @@ from test.test_import import _ready_to_import
|
|||
# isbuiltin, isroutine, isgenerator, isgeneratorfunction, getmembers,
|
||||
# getdoc, getfile, getmodule, getsourcefile, getcomments, getsource,
|
||||
# getclasstree, getargvalues, formatargvalues,
|
||||
# currentframe, stack, trace, isdatadescriptor
|
||||
# currentframe, stack, trace, isdatadescriptor,
|
||||
# ismethodwrapper
|
||||
|
||||
# NOTE: There are some additional tests relating to interaction with
|
||||
# zipimport in the test_zipimport_support test module.
|
||||
|
@ -93,7 +94,8 @@ class IsTestBase(unittest.TestCase):
|
|||
inspect.ismodule, inspect.istraceback,
|
||||
inspect.isgenerator, inspect.isgeneratorfunction,
|
||||
inspect.iscoroutine, inspect.iscoroutinefunction,
|
||||
inspect.isasyncgen, inspect.isasyncgenfunction])
|
||||
inspect.isasyncgen, inspect.isasyncgenfunction,
|
||||
inspect.ismethodwrapper])
|
||||
|
||||
def istest(self, predicate, exp):
|
||||
obj = eval(exp)
|
||||
|
@ -169,6 +171,14 @@ class TestPredicates(IsTestBase):
|
|||
self.istest(inspect.ismemberdescriptor, 'datetime.timedelta.days')
|
||||
else:
|
||||
self.assertFalse(inspect.ismemberdescriptor(datetime.timedelta.days))
|
||||
self.istest(inspect.ismethodwrapper, "object().__str__")
|
||||
self.istest(inspect.ismethodwrapper, "object().__eq__")
|
||||
self.istest(inspect.ismethodwrapper, "object().__repr__")
|
||||
self.assertFalse(inspect.ismethodwrapper(type))
|
||||
self.assertFalse(inspect.ismethodwrapper(int))
|
||||
self.assertFalse(inspect.ismethodwrapper(type("AnyClass", (), {})))
|
||||
|
||||
|
||||
|
||||
def test_iscoroutine(self):
|
||||
async_gen_coro = async_generator_function_example(1)
|
||||
|
@ -241,8 +251,38 @@ class TestPredicates(IsTestBase):
|
|||
coro.close(); gen_coro.close() # silence warnings
|
||||
|
||||
def test_isroutine(self):
|
||||
self.assertTrue(inspect.isroutine(mod.spam))
|
||||
# method
|
||||
self.assertTrue(inspect.isroutine(git.argue))
|
||||
self.assertTrue(inspect.isroutine(mod.custom_method))
|
||||
self.assertTrue(inspect.isroutine([].count))
|
||||
# function
|
||||
self.assertTrue(inspect.isroutine(mod.spam))
|
||||
self.assertTrue(inspect.isroutine(mod.StupidGit.abuse))
|
||||
# slot-wrapper
|
||||
self.assertTrue(inspect.isroutine(object.__init__))
|
||||
self.assertTrue(inspect.isroutine(object.__str__))
|
||||
self.assertTrue(inspect.isroutine(object.__lt__))
|
||||
self.assertTrue(inspect.isroutine(int.__lt__))
|
||||
# method-wrapper
|
||||
self.assertTrue(inspect.isroutine(object().__init__))
|
||||
self.assertTrue(inspect.isroutine(object().__str__))
|
||||
self.assertTrue(inspect.isroutine(object().__lt__))
|
||||
self.assertTrue(inspect.isroutine((42).__lt__))
|
||||
# method-descriptor
|
||||
self.assertTrue(inspect.isroutine(str.join))
|
||||
self.assertTrue(inspect.isroutine(list.append))
|
||||
self.assertTrue(inspect.isroutine(''.join))
|
||||
self.assertTrue(inspect.isroutine([].append))
|
||||
# object
|
||||
self.assertFalse(inspect.isroutine(object))
|
||||
self.assertFalse(inspect.isroutine(object()))
|
||||
self.assertFalse(inspect.isroutine(str()))
|
||||
# module
|
||||
self.assertFalse(inspect.isroutine(mod))
|
||||
# type
|
||||
self.assertFalse(inspect.isroutine(type))
|
||||
self.assertFalse(inspect.isroutine(int))
|
||||
self.assertFalse(inspect.isroutine(type('some_class', (), {})))
|
||||
|
||||
def test_isclass(self):
|
||||
self.istest(inspect.isclass, 'mod.StupidGit')
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Implement :func:`inspect.ismethodwrapper` and fix :func:`inspect.isroutine` for cases where methodwrapper is given. Patch by Hakan Çelik.
|
Loading…
Reference in New Issue