I'm trying to write a decorator which will do some actions based on kwargs while I want to keep the functions signature at the same time.
Here is the unit test I want to pass:
def test_test_deprecator(self):
@test_deprecator("here is decorator message", 'z'):
def some_method(x, y, z):
return x + y
self.assertEqual(some_method(2, 2, z=6), 4)
# test the original function's signature
argspec = inspect.getargspec(some_method)
self.assertEqual(argspec.args, ["x", "y", "z"])
I wrote something like:
import decorator
def test_decorator(message, args_name):
@decorator.decorator
def _test_docorator(f, *args, **kwargs):
if args_name in kwargs:
print(message)
return f(*args, **kwargs)
return _test_docorator
The unit test can pass, but there is no output message, because kwargs is always empty.
Does anyone know how to achieve this?
I'm not sure what the role of @decorator.decorator is in your code, but here is a decorator doing what you describe:
def test_decorator(message, arg_name):
def _test_decorator(f):
def wrapped_f(*args, **kwargs):
if arg_name in kwargs:
print(message)
return f(*args, **kwargs)
return wrapped_f
return _test_decorator
Updated answer:
I learned a bit about decorators looking into this. In short, though, I think using the wrapt module would work for you:
def test_decorator(message, arg_name):
@wrapt.decorator
def wrapped_f(f, instance, args, kwargs):
if arg_name in kwargs:
print(message)
return f(*args, **kwargs)
return wrapped_f
Test code:
@test_decorator('found it', 'y')
def foo(x="bad", y="dog"):
print("x={}, y={}".format(x, y))
def bar(x="bad", y="dog"):
print("x={}, y={}".format(x, y))
print ("foo argspec={}".format(inspect.getargspec(foo)))
print ("bar argspec={}".format(inspect.getargspec(bar)))
foo(y='cat')
Output:
foo argspec=ArgSpec(args=['x', 'y'], varargs=None, keywords=None, defaults=('bad', 'dog'))
bar argspec=ArgSpec(args=['x', 'y'], varargs=None, keywords=None, defaults=('bad', 'dog'))
found it
x=bad, y=cat
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With