ValueError: wrapper loop when unwrapping

血红的双手。 提交于 2020-02-23 10:22:42

问题


Python3 test cases (doctests) are failing with my sample code. But the same is working fine in Python2.

test.py

class Test(object):
    def __init__(self, a=0):
        self.a = a

    def __getattr__(self, attr):
        return Test(a=str(self.a) + attr)

tst.py

from test import Test

t = Test()

Run test cases: python3 -m doctest -v tst.py

Error:

Traceback (most recent call last):
  File "/usr/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/usr/lib/python3.6/doctest.py", line 2787, in <module>
    sys.exit(_test())
  File "/usr/lib/python3.6/doctest.py", line 2777, in _test
    failures, _ = testmod(m, verbose=verbose, optionflags=options)
  File "/usr/lib/python3.6/doctest.py", line 1950, in testmod
    for test in finder.find(m, name, globs=globs, extraglobs=extraglobs):
  File "/usr/lib/python3.6/doctest.py", line 933, in find
    self._find(tests, obj, name, module, source_lines, globs, {})
  File "/usr/lib/python3.6/doctest.py", line 992, in _find
    if ((inspect.isroutine(inspect.unwrap(val))
  File "/usr/lib/python3.6/inspect.py", line 513, in unwrap
    raise ValueError('wrapper loop when unwrapping {!r}'.format(f))
ValueError: wrapper loop when unwrapping <test.Test object at 0x7f6e80028550>

Can anyone please help in how to overcome this error.

Thanks.


回答1:


This is arguably a bug in doctest. What's happening is that doctest is searching for functions/methods/callables with a docstring, and while doing so it's unwrapping any decorators it finds. Why it does this, I have no idea. But anyway, doctest ends up calling inspect.unwrap(t) (where t is a Test instance), which is essentially equivalent to doing this:

while True:
   try:
       t = t.__wrapped__
   except AttributeError:
       break

Because t is a Test instance, accessing t.__wrapped__ calls __getattr__ and returns a new Test instance. This would go on forever, but inspect.unwrap is smart enough to notice that it's not getting anywhere, and throws an exception instead of entering an infinite loop.


As a workaround, you can rewrite your __getattr__ method to throw an AttributeError when __wrapped__ is accessed. Even better, throw an AttributeError when any dunder-attribute is accessed:

def __getattr__(self, attr):
    if attr.startswith('__') and attr.endswith('__'):
        raise AttributeError
    return Test(a=str(self.a) + attr)



回答2:


For unittest.mock try importing items as

from unittest import mock

instead of

from unittest.mock import patch

This worked around the bug for me.



来源:https://stackoverflow.com/questions/49271586/valueerror-wrapper-loop-when-unwrapping

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!