Skip to content

Commit

Permalink
Fix an edge case where ExceptionInfo._stringify_exception could crash…
Browse files Browse the repository at this point in the history
… pytest.raises (pytest-dev#11879)

Co-authored-by: Bruno Oliveira <bruno@soliv.dev>
Co-authored-by: Zac Hatfield-Dodds <zac.hatfield.dodds@gmail.com>
  • Loading branch information
3 people committed Jan 30, 2024
1 parent 21bec6c commit 407d984
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 1 deletion.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ Christopher Dignam
Christopher Gilling
Claire Cecil
Claudio Madotto
Clément M.T. Robert
CrazyMerlyn
Cristian Vera
Cyrus Maden
Expand Down
1 change: 1 addition & 0 deletions changelog/11879.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix an edge case where ``ExceptionInfo._stringify_exception`` could crash :func:`pytest.raises`.
13 changes: 12 additions & 1 deletion src/_pytest/_code/code.py
Original file line number Diff line number Diff line change
Expand Up @@ -699,10 +699,21 @@ def getrepr(
return fmt.repr_excinfo(self)

def _stringify_exception(self, exc: BaseException) -> str:
try:
notes = getattr(exc, "__notes__", [])
except KeyError:
# Workaround for https://github.com/python/cpython/issues/98778 on
# Python <= 3.9, and some 3.10 and 3.11 patch versions.
HTTPError = getattr(sys.modules.get("urllib.error", None), "HTTPError", ())
if sys.version_info[:2] <= (3, 11) and isinstance(exc, HTTPError):
notes = []
else:
raise

return "\n".join(
[
str(exc),
*getattr(exc, "__notes__", []),
*notes,
]
)

Expand Down
13 changes: 13 additions & 0 deletions testing/python/raises.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,3 +302,16 @@ class NotAnException:
with pytest.raises(("hello", NotAnException)): # type: ignore[arg-type]
pass # pragma: no cover
assert "must be a BaseException type, not str" in str(excinfo.value)

def test_issue_11872(self) -> None:
"""Regression test for #11872.
urllib.error.HTTPError on Python<=3.9 raises KeyError instead of
AttributeError on invalid attribute access.
https://github.com/python/cpython/issues/98778
"""
from urllib.error import HTTPError

with pytest.raises(HTTPError, match="Not Found"):
raise HTTPError(code=404, msg="Not Found", fp=None, hdrs=None, url="") # type: ignore [arg-type]

0 comments on commit 407d984

Please sign in to comment.