pytest icon indicating copy to clipboard operation
pytest copied to clipboard

ExceptionInfo.value not available if pytest.raises fails

Open dpinol opened this issue 6 months ago • 7 comments

When pytest.raise fails, exc_info.value is not available.

def test():
    try:
        with pytest.raises(AssertionError) as exc_info:
            raise Exception()
    except Exception as e:
        exc_info.value
        pass

I get this error

test_testchecks.py:33: in test
    exc_info.value
/home/dani/.virtualenvs/sc-tools--PFlaRe2/lib/python3.13/site-packages/_pytest/_code/code.py:607: in value
    assert self._excinfo is not None, (
           ^^^^^^^^^^^^^^^^^^^^^^^^^
E   AssertionError: .value can only be used after the context manager exits
pytest            8.4.0
Python 3.13.3
Ubuntu 25.04

dpinol avatar Jun 12 '25 12:06 dpinol

pytest.raises reraises the exception if it fails to catch it, and you're catching it with except Exception as e:, so just replace exc_info.value with e and you're good. There's no reason to access it through exc_info.value

(not a regression from 8.4)

jakkdl avatar Jun 12 '25 12:06 jakkdl

Hi, thanks,

just replace exc_info.value with e and you're good

Not quite, what I need is my exception raised within pytest.raise context, not the exception pytest raises.

not a regression from 8.4

Not in this simplified case, but for instance when expected_exception matches but the regex doesn't, this worked in pytest 8.3.5

dpinol avatar Jun 12 '25 12:06 dpinol

Hi, thanks,

just replace exc_info.value with e and you're good

Not quite, what I need is my exception raised within pytest.raise context, not the exception pytest raises.

in your example pytest doesn't raise any exception until you try to access exc_info.value, the original exception passes through pytest.raises without being modified.

not a regression from 8.4

Not in this simplified case, but for instance when expected_exception matches but the regex doesn't, this worked in pytest 8.3.5

Ah true, that is a regression. And it might make sense to make your original example work at the same time.

See https://github.com/pytest-dev/pytest/issues/13286 for more discussion on what should be raised when.

jakkdl avatar Jun 12 '25 18:06 jakkdl

When raises isn't matching it isn't providing data

Else malformed code easily working by accident and mixing up boundaries

RonnyPfannschmidt avatar Jun 12 '25 18:06 RonnyPfannschmidt

Ah yeah. The original example also breaks typing, pytest.raises(T).__enter__() -> ContextManager[ExceptionInfo[T]].

jakkdl avatar Jun 12 '25 18:06 jakkdl

Not in this simplified case, but for instance when expected_exception matches but the regex doesn't, this worked in pytest 8.3.5

Previous logic definitely filled exc_info before checking match. It's possible that was simply a byproduct of making use of ExceptionInfo for doing the matching, but I suppose we can restore that functionality.

https://github.com/pytest-dev/pytest/blob/b55ab2aabb68c0ce94c3903139b062d0c2790152/src/_pytest/python_api.py#L1011-L1028

jakkdl avatar Jun 12 '25 18:06 jakkdl

I believe this is a artifact of how match was implemented

Its definitely a bug that this was possible to begin with

If it's indeed a regression id like to warn about using it like that

RonnyPfannschmidt avatar Jun 12 '25 18:06 RonnyPfannschmidt