functools.wraps does not play nice with doc tests?

Vlad VladTheCompiler at gmail.com
Fri May 29 18:04:23 EDT 2015


Hello,

So, I know this topic comes up a lot, but I haven't been able to find any discussion on this particular twist on the topic. Perhaps someone has some insight.

So, I have a function, which is decorated. In order for the doctest test finder to find the doc tests in the decorated function, my wrapper needs to use the functools.wraps decorator inside it. So far so good. *However*, the issue is that if the decorator and the decorated function are defined in different modules, and the decorator is defined at a greater line number in its module than the decorated function in its module, and the doc test fails, the test report lists the failure as occurring at an "unknown line number". This is a problem if you have additional logic built on top of the reporting that relies on line numbers of test failures (and even more fundamentally, it's a pain to manually find which test actually failed). 

Here is a specific example, this is running Python 2.7.9, in case that matters.

File decorator.py
     1  import functools
     2
     3
     4
     5
     6
     7
     8
     9  # The decorator has to be defined at a line number greater than the
    10  # decorated function in order to trigger the bug.
    11  def decorator(func):
    12      @functools.wraps(func)
    13      def wrapper(*args, **kwargs):
    14          print('In Wrapper!')
    15          return func(*args, **kwargs)
    16      return wrapper


File decorated.py
     1  from . import decorator
     2
     3
     4  @decorator.decorator
     5  def my_func():
     6      '''
     7      >>> my_func()
     8      '''
     9      print('my_func!')
    10
    11
    12  if __name__ == '__main__':
    13      import doctest
    14      doctest.testmod()


Now, let's try to run the tests:
> python -m decorated
**********************************************************************
File ".../decorated.py", line ?, in __main__.my_func
Failed example:
    my_func()
Expected nothing
Got:
    In Wrapper!
    my_func!
**********************************************************************
1 items had failures:
   1 of   1 in __main__.my_func
***Test Failed*** 1 failures.


So, the test ran, and failed as we wanted, but the line number was not detected correctly. Has anyone run into this issue, and/or know a workaround? Or perhaps I am missing something obvious here?



More information about the Python-list mailing list