mirror of
https://github.com/ARM-software/workload-automation.git
synced 2025-01-19 20:34:30 +00:00
59 lines
2.1 KiB
Python
59 lines
2.1 KiB
Python
"""Robust apply mechanism.
|
|
|
|
Provides a function 'call', which can sort out what arguments a given
|
|
callable object can take, and subset the given arguments to match only
|
|
those which are acceptable.
|
|
"""
|
|
|
|
def function(receiver):
|
|
"""Get function-like callable object for given receiver.
|
|
|
|
returns (function_or_method, codeObject, fromMethod)
|
|
|
|
If fromMethod is true, then the callable already has its first
|
|
argument bound.
|
|
"""
|
|
if hasattr(receiver, '__call__'):
|
|
# receiver is a class instance; assume it is callable.
|
|
# Reassign receiver to the actual method that will be called.
|
|
c = receiver.__call__
|
|
if hasattr(c, 'im_func') or hasattr(c, 'im_code'):
|
|
receiver = c
|
|
if hasattr(receiver, 'im_func'):
|
|
# receiver is an instance-method.
|
|
return receiver, receiver.im_func.func_code, 1
|
|
elif not hasattr(receiver, 'func_code'):
|
|
raise ValueError(
|
|
'unknown reciever type %s %s' % (receiver, type(receiver)))
|
|
return receiver, receiver.func_code, 0
|
|
|
|
|
|
def robust_apply(receiver, signature, *arguments, **named):
|
|
"""Call receiver with arguments and appropriate subset of named.
|
|
``signature`` is the callable used to determine the call signature
|
|
of the receiver, in case ``receiver`` is a callable wrapper of the
|
|
actual receiver."""
|
|
signature, code_object, startIndex = function(signature)
|
|
acceptable = code_object.co_varnames[
|
|
startIndex + len(arguments):
|
|
code_object.co_argcount
|
|
]
|
|
for name in code_object.co_varnames[
|
|
startIndex:startIndex + len(arguments)
|
|
]:
|
|
if named.has_key(name):
|
|
raise TypeError(
|
|
'Argument %r specified both positionally '
|
|
'and as a keyword for calling %r'
|
|
% (name, signature)
|
|
)
|
|
if not (code_object.co_flags & 8):
|
|
# fc does not have a **kwds type parameter, therefore
|
|
# remove unacceptable arguments.
|
|
for arg in named.keys():
|
|
if arg not in acceptable:
|
|
del named[arg]
|
|
return receiver(*arguments, **named)
|
|
|
|
|