-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
Support __notes__ in pytest.raises #11223
Description
I would like pytest.raises to have some form of support for __notes__.
What's the problem this feature will solve?
I am currently looking into replacing dynamic patching of error messages with the new __notes__ feature added in PEP-678.
However, once I use __notes__ my checks using pytest.raises now fail, and I'd like them to not. Or at least, I would like for pytest to have some features for matching these errors. Since this is a language level feature for python, I think it's usage should be covered by pytest.
Describe the solution you'd like
I would like the regex from pytest.raises to match against the notes as well as the body of the error. It would be fine for this to be specified with a keyword argument.
Example of usage:
import pytest
def foo():
assert False
def bar():
try:
foo()
except AssertionError as e:
e.add_note("Raised by bar")
raise
with pytest.raises(AssertionError, match="Raised by bar"):
bar()Alternative Solutions
Do nothing
I could manually check for notes, but I don't think python makes it obvious which part of an exception is from a note. Here is a small example of what a note looks like:
setup
# Python 3.11.4 | packaged by conda-forge | (main, Jun 10 2023, 18:10:28) [Clang 15.0.7 ] on darwin
# Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>>
>>> def add_note(err: BaseException, msg: str) -> None:
... if sys.version_info < (3, 11):
... err.__notes__ = getattr(err, "__notes__", []) + [msg]
... else:
... err.add_note(msg)
...
>>> def foo():
... raise AssertionError("foo is a bad function")
...
>>> try:
... foo()
... except AssertionError as e:
... add_note(e, "yeah, foo is awful")
... raise eTraceback (most recent call last):
File "<stdin>", line 5, in <module>
File "<stdin>", line 2, in <module>
File "<stdin>", line 2, in foo
AssertionError: foo is a bad function
yeah, foo is awfulI think this would make it quite difficult for someone receiving an exception with notes from an upstream library to know how to match against it.
I'm currently handling this with a helper function:
def check_error_or_notes_match(e: pytest.ExceptionInfo, pattern: str):
"""
Checks whether the printed error message or the notes contains the given pattern.
DOES NOT WORK IN IPYTHON - because of the way IPython handles exceptions
"""
import traceback
message = "".join(traceback.format_exception_only(e.type, e.value))
assert re.search(
pattern, message
), f"Could not find pattern: '{pattern}' in error:\n\n{message}\n"Additional context
This line would have to change:
pytest/src/_pytest/_code/code.py
Line 707 in b20e7f6
| value = str(self.value) |