-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Caching exceptions seems to interfer with pytests traceback cleaning #10363
Description
This was originally reported in #10362 and was deemed "probably [...] a pytest bug" by @RonnyPfannschmidt.
We have tests that are paremetrized with two values. Let's call them foo and bar for this. Every foo has multiple bar's associated with it. Our tests look something like this:
@pytest.mark.parametrize(("foo", "bar"), ...)
def test_foo_bar(foo, bar):
processed_foo = do_something_expensive_with_foo(foo)
do_something_with_foo_and_bar(processed_foo, bar)This means do_something_expensive_with_foo will be hit a lot with the same inputs and thus we want to cache it. Since the call can fail and we want to cache nevertheless, we have our own @cache decorator that is able to do that:
def cache(fn):
"""Similar to :func:`functools.cache` (Python >= 3.8) or :func:`functools.lru_cache` with infinite cache size,
but this also caches exceptions.
"""
sentinel = object()
out_cache = {}
exc_cache = {}
@functools.wraps(fn)
def wrapper(*args, **kwargs):
key = args + tuple(kwargs.values())
out = out_cache.get(key, sentinel)
if out is not sentinel:
return out
exc = exc_cache.get(key, sentinel)
if exc is not sentinel:
raise exc
try:
out = fn(*args, **kwargs)
except Exception as exc:
exc_cache[key] = exc
raise exc
out_cache[key] = out
return out
return wrapperIt works exactly as intended except for one thing: if the call fails, it creates traceback abominations like this:
Traceback
Traceback (most recent call last):
File "/home/philip/git/pytorch/torchvision/test/test_prototype_transforms_functional.py", line 91, in test_scripted_vs_eager
kernel_scripted = script(kernel_eager)
File "/home/philip/git/pytorch/torchvision/test/common_utils.py", line 225, in wrapper
raise exc
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 338, in from_call
result: Optional[TResult] = func()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 259, in <lambda>
lambda: ihook(item=item, **kwds), when=when, reraise=reraise
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_hooks.py", line 265, in __call__
return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_manager.py", line 80, in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 60, in _multicall
return outcome.get_result()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_result.py", line 60, in get_result
raise ex[1].with_traceback(ex[2])
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 39, in _multicall
res = hook_impl.function(*args)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 174, in pytest_runtest_call
raise e
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 166, in pytest_runtest_call
item.runtest()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/python.py", line 1761, in runtest
self.ihook.pytest_pyfunc_call(pyfuncitem=self)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_hooks.py", line 265, in __call__
return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_manager.py", line 80, in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 60, in _multicall
return outcome.get_result()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_result.py", line 60, in get_result
raise ex[1].with_traceback(ex[2])
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 39, in _multicall
res = hook_impl.function(*args)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/python.py", line 192, in pytest_pyfunc_call
result = testfunction(**testargs)
File "/home/philip/git/pytorch/torchvision/test/test_prototype_transforms_functional.py", line 91, in test_scripted_vs_eager
kernel_scripted = script(kernel_eager)
File "/home/philip/git/pytorch/torchvision/test/common_utils.py", line 225, in wrapper
raise exc
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 338, in from_call
result: Optional[TResult] = func()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 259, in <lambda>
lambda: ihook(item=item, **kwds), when=when, reraise=reraise
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_hooks.py", line 265, in __call__
return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_manager.py", line 80, in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 60, in _multicall
return outcome.get_result()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_result.py", line 60, in get_result
raise ex[1].with_traceback(ex[2])
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 39, in _multicall
res = hook_impl.function(*args)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 174, in pytest_runtest_call
raise e
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 166, in pytest_runtest_call
item.runtest()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/python.py", line 1761, in runtest
self.ihook.pytest_pyfunc_call(pyfuncitem=self)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_hooks.py", line 265, in __call__
return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_manager.py", line 80, in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 60, in _multicall
return outcome.get_result()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_result.py", line 60, in get_result
raise ex[1].with_traceback(ex[2])
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 39, in _multicall
res = hook_impl.function(*args)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/python.py", line 192, in pytest_pyfunc_call
result = testfunction(**testargs)
File "/home/philip/git/pytorch/torchvision/test/test_prototype_transforms_functional.py", line 91, in test_scripted_vs_eager
kernel_scripted = script(kernel_eager)
File "/home/philip/git/pytorch/torchvision/test/common_utils.py", line 225, in wrapper
raise exc
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 338, in from_call
result: Optional[TResult] = func()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 259, in <lambda>
lambda: ihook(item=item, **kwds), when=when, reraise=reraise
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_hooks.py", line 265, in __call__
return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_manager.py", line 80, in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 60, in _multicall
return outcome.get_result()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_result.py", line 60, in get_result
raise ex[1].with_traceback(ex[2])
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 39, in _multicall
res = hook_impl.function(*args)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 174, in pytest_runtest_call
raise e
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 166, in pytest_runtest_call
item.runtest()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/python.py", line 1761, in runtest
self.ihook.pytest_pyfunc_call(pyfuncitem=self)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_hooks.py", line 265, in __call__
return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_manager.py", line 80, in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 60, in _multicall
return outcome.get_result()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_result.py", line 60, in get_result
raise ex[1].with_traceback(ex[2])
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 39, in _multicall
res = hook_impl.function(*args)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/python.py", line 192, in pytest_pyfunc_call
result = testfunction(**testargs)
File "/home/philip/git/pytorch/torchvision/test/test_prototype_transforms_functional.py", line 91, in test_scripted_vs_eager
kernel_scripted = script(kernel_eager)
File "/home/philip/git/pytorch/torchvision/test/common_utils.py", line 225, in wrapper
raise exc
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 338, in from_call
result: Optional[TResult] = func()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 259, in <lambda>
lambda: ihook(item=item, **kwds), when=when, reraise=reraise
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_hooks.py", line 265, in __call__
return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_manager.py", line 80, in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 60, in _multicall
return outcome.get_result()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_result.py", line 60, in get_result
raise ex[1].with_traceback(ex[2])
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 39, in _multicall
res = hook_impl.function(*args)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 174, in pytest_runtest_call
raise e
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 166, in pytest_runtest_call
item.runtest()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/python.py", line 1761, in runtest
self.ihook.pytest_pyfunc_call(pyfuncitem=self)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_hooks.py", line 265, in __call__
return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_manager.py", line 80, in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 60, in _multicall
return outcome.get_result()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_result.py", line 60, in get_result
raise ex[1].with_traceback(ex[2])
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 39, in _multicall
res = hook_impl.function(*args)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/python.py", line 192, in pytest_pyfunc_call
result = testfunction(**testargs)
File "/home/philip/git/pytorch/torchvision/test/test_prototype_transforms_functional.py", line 91, in test_scripted_vs_eager
kernel_scripted = script(kernel_eager)
File "/home/philip/git/pytorch/torchvision/test/common_utils.py", line 225, in wrapper
raise exc
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 338, in from_call
result: Optional[TResult] = func()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 259, in <lambda>
lambda: ihook(item=item, **kwds), when=when, reraise=reraise
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_hooks.py", line 265, in __call__
return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_manager.py", line 80, in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 60, in _multicall
return outcome.get_result()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_result.py", line 60, in get_result
raise ex[1].with_traceback(ex[2])
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 39, in _multicall
res = hook_impl.function(*args)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 174, in pytest_runtest_call
raise e
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/runner.py", line 166, in pytest_runtest_call
item.runtest()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/python.py", line 1761, in runtest
self.ihook.pytest_pyfunc_call(pyfuncitem=self)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_hooks.py", line 265, in __call__
return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_manager.py", line 80, in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 60, in _multicall
return outcome.get_result()
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_result.py", line 60, in get_result
raise ex[1].with_traceback(ex[2])
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/pluggy/_callers.py", line 39, in _multicall
res = hook_impl.function(*args)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/_pytest/python.py", line 192, in pytest_pyfunc_call
result = testfunction(**testargs)
File "/home/philip/git/pytorch/torchvision/test/test_prototype_transforms_functional.py", line 91, in test_scripted_vs_eager
kernel_scripted = script(kernel_eager)
File "/home/philip/git/pytorch/torchvision/test/common_utils.py", line 231, in wrapper
raise exc
File "/home/philip/git/pytorch/torchvision/test/common_utils.py", line 228, in wrapper
out = fn(*args, **kwargs)
File "/home/philip/git/pytorch/torchvision/test/test_prototype_transforms_functional.py", line 24, in script
return torch.jit.script(fn)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/torch/jit/_script.py", line 1344, in script
qualified_name, ast, _rcb, get_default_args(obj)
RuntimeError:
Ellipses followed by tensor indexing is currently not supported:
File "/home/philip/git/pytorch/torchvision/torchvision/prototype/transforms/functional/_geometry.py", line 53
)
bounding_box[..., [0, 2]] = image_size[1] - bounding_box[..., [2, 0]]
~~~~~~~~~~~~~~~~~~~~~~~~ <--- HERE
return convert_format_bounding_box(
As you can see, the largest part of the traceback is coming from pytest and has nothing to do with the actual failure. Removing the @cache decorator from do_something_expensive_with_foo gives a normal traceback:
Traceback
Traceback (most recent call last):
File "/home/philip/git/pytorch/torchvision/test/test_prototype_transforms_functional.py", line 91, in test_scripted_vs_eager
kernel_scripted = script(kernel_eager)
File "/home/philip/git/pytorch/torchvision/test/test_prototype_transforms_functional.py", line 24, in script
return torch.jit.script(fn)
File "/home/philip/.local/opt/mambaforge/envs/torchvision-dev/lib/python3.7/site-packages/torch/jit/_script.py", line 1344, in script
qualified_name, ast, _rcb, get_default_args(obj)
RuntimeError:
Ellipses followed by tensor indexing is currently not supported:
File "/home/philip/git/pytorch/torchvision/torchvision/prototype/transforms/functional/_geometry.py", line 53
)
bounding_box[..., [0, 2]] = image_size[1] - bounding_box[..., [2, 0]]
~~~~~~~~~~~~~~~~~~~~~~~~ <--- HERE
return convert_format_bounding_box(
I'm guessing pytest removes all the internal calls from the traceback here. Caching exceptions seem to interfer with that.
This happens on the latest pytest==7.1.3. We are running with --tb=native, but I'm guessing this plays no role here, since the caching seems to be the root cause.