Kaydet (Commit) fcef60f5 authored tarafından Jeroen Demeyer's avatar Jeroen Demeyer Kaydeden (comit) Petr Viktorin

bpo-33261: guard access to __code__ attribute in inspect (GH-6448)

üst 487b73ab
......@@ -168,23 +168,30 @@ def isfunction(object):
__kwdefaults__ dict of keyword only parameters with defaults"""
return isinstance(object, types.FunctionType)
def _has_code_flag(f, flag):
"""Return true if ``f`` is a function (or a method or functools.partial
wrapper wrapping a function) whose code object has the given ``flag``
set in its flags."""
while ismethod(f):
f = f.__func__
f = functools._unwrap_partial(f)
if not isfunction(f):
return False
return bool(f.__code__.co_flags & flag)
def isgeneratorfunction(obj):
"""Return true if the object is a user-defined generator function.
Generator function objects provide the same attributes as functions.
See help(isfunction) for a list of attributes."""
obj = functools._unwrap_partial(obj)
return bool((isfunction(obj) or ismethod(obj)) and
obj.__code__.co_flags & CO_GENERATOR)
return _has_code_flag(obj, CO_GENERATOR)
def iscoroutinefunction(obj):
"""Return true if the object is a coroutine function.
Coroutine functions are defined with "async def" syntax.
"""
obj = functools._unwrap_partial(obj)
return bool(((isfunction(obj) or ismethod(obj)) and
obj.__code__.co_flags & CO_COROUTINE))
return _has_code_flag(obj, CO_COROUTINE)
def isasyncgenfunction(obj):
"""Return true if the object is an asynchronous generator function.
......@@ -192,9 +199,7 @@ def isasyncgenfunction(obj):
Asynchronous generator functions are defined with "async def"
syntax and have "yield" expressions in their body.
"""
obj = functools._unwrap_partial(obj)
return bool((isfunction(obj) or ismethod(obj)) and
obj.__code__.co_flags & CO_ASYNC_GENERATOR)
return _has_code_flag(obj, CO_ASYNC_GENERATOR)
def isasyncgen(object):
"""Return true if the object is an asynchronous generator."""
......
......@@ -80,3 +80,14 @@ try:
raise Exception()
except:
tb = sys.exc_info()[2]
class Callable:
def __call__(self, *args):
return args
def as_method_of(self, obj):
from types import MethodType
return MethodType(self, obj)
custom_method = Callable().as_method_of(42)
del Callable
......@@ -146,6 +146,7 @@ class TestPredicates(IsTestBase):
self.istest(inspect.isfunction, 'mod.spam')
self.istest(inspect.isfunction, 'mod.StupidGit.abuse')
self.istest(inspect.ismethod, 'git.argue')
self.istest(inspect.ismethod, 'mod.custom_method')
self.istest(inspect.ismodule, 'mod')
self.istest(inspect.isdatadescriptor, 'collections.defaultdict.default_factory')
self.istest(inspect.isgenerator, '(x for x in range(2))')
......
Do not raise AttributeError when calling the inspect functions
isgeneratorfunction, iscoroutinefunction, isasyncgenfunction on a method
created from an arbitrary callable. Instead, return False.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment