Expose function signature fetching function

This function is the recommended way to get information
about functions going forward, so all the variations of
getargspec can just use this instead (including the variations
of this used in openstack).

This exposes a 'get_signature' function that correctly aliases
the exposed function in python3.x and the backwards compat
library (funcsigs) that exposes this same information in python2.x

Internally in the other reflection functions we now switch
away from using getargspec as well, and replace it with using
this new signature object/function instead.

Depends-On: I1aa0054089ca57fc2d68779f4ee133a9750fec2a

Change-Id: I910b353f5db290832ef87bf7c5e5bb2e9788e3ec
This commit is contained in:
Joshua Harlow 2015-10-14 11:39:09 -07:00
parent 9ec6cccb77
commit 43451e5cc7
2 changed files with 23 additions and 23 deletions

View File

@ -29,6 +29,17 @@ except AttributeError:
# others)...
_BUILTIN_MODULES = ('builtins', '__builtin__', '__builtins__', 'exceptions')
if six.PY3:
Parameter = inspect.Parameter
Signature = inspect.Signature
get_signature = inspect.signature
else:
# Provide an equivalent but use funcsigs instead...
import funcsigs
Parameter = funcsigs.Parameter
Signature = funcsigs.Signature
get_signature = funcsigs.signature
def get_members(obj, exclude_hidden=True):
"""Yields the members of an object, filtering by hidden/not hidden."""
@ -173,19 +184,6 @@ def is_subclass(obj, cls):
return inspect.isclass(obj) and issubclass(obj, cls)
def _get_arg_spec(function):
if isinstance(function, _TYPE_TYPE):
bound = True
function = function.__init__
elif isinstance(function, (types.FunctionType, types.MethodType)):
bound = is_bound_method(function)
function = getattr(function, '__wrapped__', function)
else:
function = function.__call__
bound = is_bound_method(function)
return inspect.getargspec(function), bound
def get_callable_args(function, required_only=False):
"""Get names of callable arguments.
@ -195,16 +193,17 @@ def get_callable_args(function, required_only=False):
If required_only is True, optional arguments (with default values)
are not included into output.
"""
argspec, bound = _get_arg_spec(function)
f_args = argspec.args
if required_only and argspec.defaults:
f_args = f_args[:-len(argspec.defaults)]
if bound:
f_args = f_args[1:]
return f_args
sig = get_signature(function)
function_args = list(six.iterkeys(sig.parameters))
for param_name, p in six.iteritems(sig.parameters):
if (p.kind in (Parameter.VAR_POSITIONAL, Parameter.VAR_KEYWORD)
or (required_only and p.default is not Parameter.empty)):
function_args.remove(param_name)
return function_args
def accepts_kwargs(function):
"""Returns True if function accepts kwargs."""
argspec, _bound = _get_arg_spec(function)
return bool(argspec.keywords)
"""Returns ``True`` if function accepts kwargs otherwise ``False``."""
sig = get_signature(function)
return any(p.kind == Parameter.VAR_KEYWORD
for p in six.itervalues(sig.parameters))

View File

@ -10,6 +10,7 @@
pbr>=1.6
Babel>=1.3
six>=1.9.0
funcsigs>=0.4;python_version=='2.7' or python_version=='2.6'
iso8601>=0.1.9
oslo.i18n>=1.5.0 # Apache-2.0
monotonic>=0.3 # Apache-2.0