0

I am writing a decorator which will catch TypeError for incorrect number of arguments in a function call and will print a customised message. The code is here:

import inspect

def inspect_signature(f):
    def decorate(*args, **kwargs):
        try:
            f(*args, **kwargs)
        except TypeError as e:
            print('Failed to call "{}" with signature {}. Provided args={} and kwargs={}.'.format(
                f.__name__, inspect.getargspec(f).args, args, kwargs))
        return f
    return decorate


@inspect_signature
def func(foo, bar):
    pass
func('a')
func('a', 'b')

I get the following output:

Failed to call "func" with signature ['foo', 'bar']. Provided args=('a',) and kwargs={}.
Called successfully with foo=a, bar=b
ArgSpec(args=[], varargs='args', keywords='kwargs', defaults=None)

The function signature is empty. Please suggest me a solution how can I retain it?

PS: I am using python2 and cannot switch to python3.

Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
python_user
  • 196
  • 1
  • 5
  • 15

2 Answers2

0

You missed this here. func(*foo, **bar)

In your case func('a') was not working as you gave fixed arg for it.

You need to pass a variable number of arguments to your function

@inspect_signature
def func(*foo, **bar):
    pass
Shivkumar kondi
  • 6,458
  • 9
  • 31
  • 58
  • I am not passing variable number of arguments to the function. I have fixed two arguments. I know `func('a')` will not work so for that I have written a decorator which will print a customized message instead of python inbuilt error message but my original function signature are lost. So I want to retain it. – python_user Feb 21 '17 at 11:11
  • @python_user So what was the definition for your original signature function? – Shivkumar kondi Feb 27 '17 at 12:18
0

You can refer to Preserving signatures of decorated functions.

In a word, you can use decorator module in Python2 and Python3. When you use Python3.4+, you can use inspect.wraps to Preserving signatures of decorated functions.

If you don't want to use decorator module, you can use eval to make a decorator. In General, eval is unpopular, so, decorator module may be the best solution in Python2.

Ryan
  • 235
  • 3
  • 5
  • You probably mean `functools.wraps`. Note that it does not actually preserve behavioral signature as explained here: https://stackoverflow.com/a/55163816/7262247. Also note that `decorator` (and the generalization of its core, `makefun`) rely on `compile` + `exec` :) See https://github.com/micheles/decorator/blob/master/src/decorator.py and https://github.com/smarie/python-makefun/blob/master/makefun/main.py – smarie Mar 14 '19 at 13:34