def parse_args(args, path, query, specials):
def one_or_many(fn_, dict_, key):
result = [fn_(value) for value in dict_[key]]
return result[0] if len(result) == 1 else result
kwargs = {}
for arg, parse_fn in six.iteritems(args):
if arg in specials:
kwargs[arg] = specials[arg]()
elif parse_fn is None:
kwargs[arg] = one_or_many(lambda x: x, query, arg)
elif isinstance(parse_fn, tuple):
kwargs[arg] = parse_fn[DEFAULT] if arg not in query else one_or_many(parse_fn[CALLABLE], query, arg)
elif isalambda(parse_fn):
_code = six.get_function_code(parse_fn)
closures = six.get_function_closure(parse_fn)
if closures:
assert len(closures) <= 1
fn = closures[0].cell_contents
else:
fn = eval(".".join(_code.co_names), six.get_function_globals(parse_fn))
kwargs[arg] = fn(**parse_args(get_function_args(parse_fn), path, query, specials))
else:
kwargs[arg] = one_or_many(parse_fn, query, arg)
return kwargs
python类get_function_closure()的实例源码
def get_unwrapped_func(func):
"""Get original function under decorator.
Decorator hides original function inside itself. But in some cases it's
important to get access to original function, for ex: for documentation.
Args:
func (function): function that can be potentially a decorator which
hides original function
Returns:
function: unwrapped function or the same function
"""
if not inspect.isfunction(func) and not inspect.ismethod(func):
return func
if func.__name__ != six.get_function_code(func).co_name:
for cell in six.get_function_closure(func):
obj = cell.cell_contents
if inspect.isfunction(obj):
if func.__name__ == six.get_function_code(obj).co_name:
return obj
else:
return get_unwrapped_func(obj)
return func
def fix_js_args(func):
'''Use this function when unsure whether func takes this and arguments as its last 2 args.
It will append 2 args if it does not.'''
fcode = six.get_function_code(func)
fargs = fcode.co_varnames[fcode.co_argcount-2:fcode.co_argcount]
if fargs==('this', 'arguments') or fargs==('arguments', 'var'):
return func
code = append_arguments(six.get_function_code(func), ('this','arguments'))
return types.FunctionType(code, six.get_function_globals(func), func.__name__, closure=six.get_function_closure(func))
def test_get_function_closure():
def f():
x = 42
def g():
return x
return g
cell = six.get_function_closure(f())[0]
assert type(cell).__name__ == "cell"
def fix_js_args(func):
'''Use this function when unsure whether func takes this and arguments as its last 2 args.
It will append 2 args if it does not.'''
fcode = six.get_function_code(func)
fargs = fcode.co_varnames[fcode.co_argcount-2:fcode.co_argcount]
if fargs==('this', 'arguments') or fargs==('arguments', 'var'):
return func
code = append_arguments(six.get_function_code(func), ('this','arguments'))
return types.FunctionType(code, six.get_function_globals(func), func.__name__, closure=six.get_function_closure(func))
def test_get_function_closure():
def f():
x = 42
def g():
return x
return g
cell = six.get_function_closure(f())[0]
assert type(cell).__name__ == "cell"
def get_decorators(function):
# If we have no func_closure, it means we are not wrapping any other functions.
decorators = []
try:
func_closure = six.get_function_closure(function)
except AttributeError:
return decorators
if not func_closure:
return [function]
# Otherwise, we want to collect all of the recursive results for every closure we have.
for closure in func_closure:
if isinstance(closure.cell_contents, types.FunctionType):
decorators.extend(get_decorators(closure.cell_contents))
return [function] + decorators
def fix_js_args(func):
'''Use this function when unsure whether func takes this and arguments as its last 2 args.
It will append 2 args if it does not.'''
fcode = six.get_function_code(func)
fargs = fcode.co_varnames[fcode.co_argcount-2:fcode.co_argcount]
if fargs==('this', 'arguments') or fargs==('arguments', 'var'):
return func
code = append_arguments(six.get_function_code(func), ('this','arguments'))
return types.FunctionType(code, six.get_function_globals(func), func.__name__, closure=six.get_function_closure(func))
def fix_js_args(func):
'''Use this function when unsure whether func takes this and arguments as its last 2 args.
It will append 2 args if it does not.'''
fcode = six.get_function_code(func)
fargs = fcode.co_varnames[fcode.co_argcount-2:fcode.co_argcount]
if fargs==('this', 'arguments') or fargs==('arguments', 'var'):
return func
code = append_arguments(six.get_function_code(func), ('this','arguments'))
return types.FunctionType(code, six.get_function_globals(func), func.__name__, closure=six.get_function_closure(func))
def test_get_function_closure():
def f():
x = 42
def g():
return x
return g
cell = six.get_function_closure(f())[0]
assert type(cell).__name__ == "cell"
def fix_js_args(func):
'''Use this function when unsure whether func takes this and arguments as its last 2 args.
It will append 2 args if it does not.'''
fcode = six.get_function_code(func)
fargs = fcode.co_varnames[fcode.co_argcount-2:fcode.co_argcount]
if fargs==('this', 'arguments') or fargs==('arguments', 'var'):
return func
code = append_arguments(six.get_function_code(func), ('this','arguments'))
return types.FunctionType(code, six.get_function_globals(func), func.__name__, closure=six.get_function_closure(func))
def serialize(cust_obj):
"""A function to serialize custom objects passed to a model
Args:
cust_obj(callable): a custom layer or function to serialize
Returns:
a dict of the serialized components of the object"""
ser_func = dict()
if isinstance(cust_obj, types.FunctionType):
func_code = six.get_function_code(cust_obj)
func_code_d = dill.dumps(func_code).decode('raw_unicode_escape')
ser_func['func_code_d'] = func_code_d
ser_func['name_d'] = pickle.dumps(
cust_obj.__name__).decode('raw_unicode_escape')
ser_func['args_d'] = pickle.dumps(
six.get_function_defaults(cust_obj)).decode('raw_unicode_escape')
clos = dill.dumps(
six.get_function_closure(cust_obj)).decode('raw_unicode_escape')
ser_func['clos_d'] = clos
ser_func['type_obj'] = 'func'
else:
if hasattr(cust_obj, '__module__'): # pragma: no cover
cust_obj.__module__ = '__main__'
ser_func['name_d'] = None
ser_func['args_d'] = None
ser_func['clos_d'] = None
ser_func['type_obj'] = 'class'
loaded = dill.dumps(cust_obj).decode('raw_unicode_escape')
ser_func['func_code_d'] = loaded
return ser_func
def getargspec(method):
"""
Drill through layers of decorators attempting to locate the actual argspec
for a method.
"""
argspec = _getargspec(method)
args = argspec[0]
if args and args[0] == 'self':
return argspec
if hasattr(method, '__func__'):
method = method.__func__
func_closure = six.get_function_closure(method)
# NOTE(sileht): if the closure is None we cannot look deeper,
# so return actual argspec, this occurs when the method
# is static for example.
if not func_closure:
return argspec
closure = None
# In the case of deeply nested decorators (with arguments), it's possible
# that there are several callables in scope; Take a best guess and go
# with the one that looks most like a pecan controller function
# (has a __code__ object, and 'self' is the first argument)
func_closure = filter(
lambda c: (
six.callable(c.cell_contents) and
hasattr(c.cell_contents, '__code__')
),
func_closure
)
func_closure = sorted(
func_closure,
key=lambda c: 'self' in c.cell_contents.__code__.co_varnames,
reverse=True
)
closure = func_closure[0]
method = closure.cell_contents
return getargspec(method)