I have a pretty specific question.
User gives me a function f and a "variables" as arguments of the function. Note, that the signature of f may be arbitrary (i.e. can use any legal combination of 5 kinds of parameters) and some arguments may have an default value. The variables are, in a simplified way, keys to dictionary which translates variables to real values.
I would like do the following things:
Capture how the arguments were passed (to be able to replicate it later, when
fis called)Check before hand, whether it is even possible to call
fwith such parameters (i.e. not wait for the actual call to detect mistakes)Translate variables to real values
Save the exact arguments with which
fis called (i.e. iffhas parameter with default value, I need to know)Call function
fin the way which user specified, as mentioned
My overall goal is to determine whether the two calls of f return the same result (provided that f is pure). Therefore, it is crucial to determine (for example) whether two arguments set differ only in default value of f (in one case being passed explicitly).
Example
There will be roughly the following class:
class VariableCapture:
translation_table = ...
def __init__(self, func):
self._func = func
def set_args(self, ..# someting ..):
# capture arguments
# compare with signature of self._func
# save the actual arguments
def call(self):
self._func(..# something ..)
Here are an example of f:
def f(a,b):
# some magic here, not really my business
vc = VariableCapture(f)
vc.set_args(1, 2, 3) # error -- too many args
vc.set_args(a=1, c=2) # error -- keyword arg with wrong name
vc.set_args(1, 2) # ok
vc.set_args(a=1, b=2) # ok
See, however that there might be difference between two last lines in case of the following f:
def f(*args, **kwargs):
# some magic here, not really my business
After vc.set_args(1, 2) the later call of f should passed both arguments via *args. The later via **kwargs.
My guesses
I think that it is possible to receive any kind of argument specification via set_args(self, *args, **kwargs). However, I am not sure with that.
Also, I don't know, whether I can differentiate between non-equivalent ways how to pass the parameters (from perspective of the particular f).
And, closely related to the previous, whether call of f via statement `self._func(*self.saved_args, *self.saved_kwargs).
I admit, it's rather broad question, but any tips or suggestions are appreciated. Also, any references to libraries which might help are great (I suppose that the key library here is inspect). Thank you!