Skip to content

Commit

Permalink
Work around CPython bug in HTTPError (#58)
Browse files Browse the repository at this point in the history
  • Loading branch information
Zac-HD committed Mar 12, 2023
1 parent 5fbf14a commit 95b7819
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 1 deletion.
6 changes: 6 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@ Version history

This library adheres to `Semantic Versioning 2.0 <http://semver.org/>`_.

**UNRELEASED**

- Workaround for [CPython issue #98778](https://github.com/python/cpython/issues/98778),
``urllib.error.HTTPError(..., fp=None)`` raises ``KeyError`` on unknown attribute access,
on affected Python versions. (PR by Zac Hatfield-Dodds)

**1.1.0**

- Backported upstream fix for gh-99553 (custom subclasses of ``BaseExceptionGroup`` that
Expand Down
11 changes: 10 additions & 1 deletion src/exceptiongroup/_formatting.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,16 @@ def __init__(
# Capture now to permit freeing resources: only complication is in the
# unofficial API _format_final_exc_line
self._str = _safe_string(exc_value, "exception")
self.__notes__ = getattr(exc_value, "__notes__", None)
try:
self.__notes__ = getattr(exc_value, "__notes__", None)
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_value, HTTPError):
self.__notes__ = None
else:
raise

if exc_type and issubclass(exc_type, SyntaxError):
# Handle SyntaxError's specially
Expand Down
8 changes: 8 additions & 0 deletions tests/test_formatting.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import sys
import traceback
from typing import NoReturn
from urllib.error import HTTPError

import pytest
from _pytest.capture import CaptureFixture
Expand Down Expand Up @@ -528,3 +530,9 @@ def __init__(self, name: str) -> None:
print_exception(e) # does not crash
output = capsys.readouterr().err
assert "NamedAttributeError" in output


def test_works_around_httperror_bug():
# See https://github.com/python/cpython/issues/98778 in Python <= 3.9
err = HTTPError("url", 405, "METHOD NOT ALLOWED", None, None)
traceback.TracebackException(type(err), err, None)

0 comments on commit 95b7819

Please sign in to comment.