How to make a decorator transparent to debugger

677 Views Asked by At

I am working on a decorator library that is modifying keyword arguments of a function, and the library is doing what I want it to do, but it's very inconvenient that while debugging, whenever the user function is called, the debugger has to pass through the decorator library code.

I implemented the decorator as a class (see https://github.com/mapa17/configfy/blob/master/configfy/decorator.py)

and the user function is wrapped by the following library code:

def __call__(self, *args, **kwargs):
    if self.needs_wrapping:
        self.needs_wrapping = False
        self.func = args[0]
        functools.update_wrapper(self, self.func)
        self.kwargs = self.__get_kw_args(self.func)

        # If config file is specified in decorator, new kwargs can be precalculated!
        if self.config is not None:
            self.new_kwargs = self._get_new_kwargs()

        return self

    # Use precalculated kwargs if available
    if self.new_kwargs is None:
        new_kwargs = self._get_new_kwargs()
    else:
        new_kwargs = self.new_kwargs

    # Overwrite them with any passed arguments; passed arguments have priority!
    new_kwargs.update(kwargs)

    # Call target (aka user) function with altered kwargs
    return self.func(*args, **new_kwargs)

So is it possible to somehow skip this library code when debugging?

2

There are 2 best solutions below

2
On BEST ANSWER

As @bruno-desthuilliers mentioned, the decorator is a wrapper around the user function, and there is no way to somehow remove it.

What can be done is, to make the debugger skip the decorator module code, using the skip option see

As i am interested in using pudb for debugging, i created a pull request, enabling a similar feature for pdb see

for pdb

import pdb
from configfy import configfy as cfy    

@cfy
def fuu(kw_me=42):
    print(kw_me)

if __name__ == '__main__':
    pdb.Pdb(skip=['configfy.*']).set_trace()
    fuu()

for pudb (if the pull request is accepted)

import pudb
from configfy import configfy as cfy

# Prevent pudb from stepping into the decorator library code
pudb._get_debugger(skip=['configfy.*'])


@cfy
def fuu(kw_me=42):
    print(kw_me)

if __name__ == '__main__':
    pudb.set_trace()
    fuu()
1
On

There's nothing magical with decorators. The @decorator syntax is only syntactic sugar, so when you write:

@decorate
def some_func(...):
   # ...

technically what really happens is:

def some_func(...):
   # ...

some_func = decorate(some_func)

IOW, no, there is no way to "make a decorator transparent to the debugger", since a "decorator" is just a plain ordinary callable that (usually but not necessarily) returns another plain ordinary callable - in fact there's just no such thing as a "decorator", a callable is a decorator if you use it as such, and that's all.