GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — `urllib.error.HTTPError(..., fp=None)` raises a `KeyError` instead of an `AttributeError` on attribute access · Issue #98778 · python/cpython

urllib.error.HTTPError(..., fp=None) raises a KeyError instead of an AttributeError on attribute access #98778

New issue
Copy link
New issue
Copy link
Closed
Closed
urllib.error.HTTPError(..., fp=None) raises a KeyError instead of an AttributeError on attribute access#98778
Copy link
Labels
type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@vxgmichel
vxgmichel
opened on Oct 27, 2022
Issue body actions

Bug report

The exception urllib.error.HTTPError(..., fp=None) raises a KeyError instead of an AttributeError when accessing an attribute that does not exist.

>>> from urllib.error import HTTPError
>>> x = HTTPError("url", 405, "METHOD NOT ALLOWED", None, None)
>>> assert getattr(x, "__notes__", ())  == ()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/vinmic/repos/cpython/Lib/tempfile.py", line 477, in __getattr__
    file = self.__dict__['file']
           ~~~~~~~~~~~~~^^^^^^^^
KeyError: 'file'

Your environment

Python 3.12.0a1+ (heads/main:bded5edd9a, Oct 27 2022, 19:23:58) [GCC 11.3.0] on linux

This bug should be reproducible for all python3 versions on all systems.

Context

I found this error while running a code similar to this:

from logging import getLogger
from urllib.error import HTTPError
try:
    raise HTTPError("url", 405, "METHOD NOT ALLOWED", None, None)
except Exception:
    getLogger().exception("Ooops")

Instead of having the exception logged, I ended up with the following trace:

--- Logging error ---
Traceback (most recent call last):
  File "/home/vinmic/repos/cpython/../test_trio/test_trio.py", line 6, in <module>
    raise HTTPError("url", 405, "METHOD NOT ALLOWED", None, None)
urllib.error.HTTPError: HTTP Error 405: METHOD NOT ALLOWED

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/vinmic/repos/cpython/Lib/logging/__init__.py", line 1160, in emit
    msg = self.format(record)
          ^^^^^^^^^^^^^^^^^^^
  File "/home/vinmic/repos/cpython/Lib/logging/__init__.py", line 999, in format
    return fmt.format(record)
           ^^^^^^^^^^^^^^^^^^
  File "/home/vinmic/repos/cpython/Lib/logging/__init__.py", line 711, in format
    record.exc_text = self.formatException(record.exc_info)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vinmic/repos/cpython/Lib/logging/__init__.py", line 661, in formatException
    traceback.print_exception(ei[0], ei[1], tb, None, sio)
  File "/home/vinmic/repos/cpython/Lib/traceback.py", line 124, in print_exception
    te = TracebackException(type(value), value, tb, limit=limit, compact=True)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vinmic/repos/cpython/Lib/traceback.py", line 697, in __init__
    self.__notes__ = getattr(exc_value, '__notes__', None)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vinmic/repos/cpython/Lib/tempfile.py", line 477, in __getattr__
    file = self.__dict__['file']
           ~~~~~~~~~~~~~^^^^^^^^
KeyError: 'file'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/vinmic/repos/cpython/../test_trio/test_trio.py", line 8, in <module>
    getLogger().exception("Ooops")
  File "/home/vinmic/repos/cpython/Lib/logging/__init__.py", line 1574, in exception
    self.error(msg, *args, exc_info=exc_info, **kwargs)
  File "/home/vinmic/repos/cpython/Lib/logging/__init__.py", line 1568, in error
    self._log(ERROR, msg, args, **kwargs)
  File "/home/vinmic/repos/cpython/Lib/logging/__init__.py", line 1684, in _log
    self.handle(record)
  File "/home/vinmic/repos/cpython/Lib/logging/__init__.py", line 1700, in handle
    self.callHandlers(record)
  File "/home/vinmic/repos/cpython/Lib/logging/__init__.py", line 1770, in callHandlers
    lastResort.handle(record)
  File "/home/vinmic/repos/cpython/Lib/logging/__init__.py", line 1028, in handle
    self.emit(record)
  File "/home/vinmic/repos/cpython/Lib/logging/__init__.py", line 1168, in emit
    self.handleError(record)
  File "/home/vinmic/repos/cpython/Lib/logging/__init__.py", line 1082, in handleError
    traceback.print_exception(t, v, tb, None, sys.stderr)
  File "/home/vinmic/repos/cpython/Lib/traceback.py", line 124, in print_exception
    te = TracebackException(type(value), value, tb, limit=limit, compact=True)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vinmic/repos/cpython/Lib/traceback.py", line 763, in __init__
    context = TracebackException(
              ^^^^^^^^^^^^^^^^^^^
  File "/home/vinmic/repos/cpython/Lib/traceback.py", line 697, in __init__
    self.__notes__ = getattr(exc_value, '__notes__', None)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/vinmic/repos/cpython/Lib/tempfile.py", line 477, in __getattr__
    file = self.__dict__['file']
           ~~~~~~~~~~~~~^^^^^^^^
KeyError: 'file'

Note however that the exception is logged properly on python 3.9 (without the exceptiongroup module imported). So maybe the following patch should be applied on top of HTTPError being fixed in order to make tracebacks more robust:

diff --git a/Lib/traceback.py b/Lib/traceback.py
index 6270100348..a9c15d59be 100644
--- a/Lib/traceback.py
+++ b/Lib/traceback.py
@@ -694,7 +694,10 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None,
         # 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 Exception:
+            self.__notes__ = None
 
         if exc_type and issubclass(exc_type, SyntaxError):
             # Handle SyntaxError's specially

Linked PRs

  • gh-98778: Update HTTPError to initialize properly even if fp is None #99966
  • [3.11] gh-98778: Update HTTPError to initialize properly even if fp is None (gh-99966) #100096
  • [3.10] gh-98778: Update HTTPError to initialize properly even if fp is None (gh-99966) #100097

Activity

  1. vxgmichel
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Oct 27, 2022
  2. serhiy-storchaka commented on Oct 28, 2022

    @serhiy-storchaka
    serhiy-storchaka
    on Oct 28, 2022
    Member
    More actions

    The problem is that HTTPError is a subclass of tempfile._TemporaryFileWrapper, which is not properly initialized if fp is None.

    cpython/Lib/urllib/error.py

    Lines 49 to 50 in 3e07f82

    if fp is not None:
    self.__super_init(fp, hdrs, url, code)

    cc @orsenthil

    Reacted by Łukasz Langa
  3. corona10
    added 3 commits that reference this issue on Dec 3, 2022

    pythongh-98778: Update HTTPError to initialize properly even if fp is…

    003dbd9

    pythongh-98778: Update HTTPError to initialize properly even if fp is…

    448231f

    gh-98778: Update HTTPError to initialize properly even if fp is None (g…

    dc8a868
  4. miss-islington
    added 2 commits that reference this issue on Dec 8, 2022

    pythongh-98778: Update HTTPError to initialize properly even if fp is…

    c699a00

    pythongh-98778: Update HTTPError to initialize properly even if fp is…

    b39b498
  5. corona10
    closed this as completedon Dec 8, 2022
  6. miss-islington
    added 2 commits that reference this issue on Dec 8, 2022

    gh-98778: Update HTTPError to initialize properly even if fp is None (g…

    846898e

    gh-98778: Update HTTPError to initialize properly even if fp is None (g…

    85be258
  7. vxgmichel commented on Dec 8, 2022

    @vxgmichel
    vxgmichel
    on Dec 8, 2022
    ContributorAuthor
    More actions

    Great! Thanks for the fix :)

    Do you think it would be interesting to make traceback more robust and protect it against those kinds of buggy exceptions? I suggested the following patch in my original comment:

    diff --git a/Lib/traceback.py b/Lib/traceback.py
    index 6270100348..a9c15d59be 100644
    --- a/Lib/traceback.py
    +++ b/Lib/traceback.py
    @@ -694,7 +694,10 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None,
             # 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 Exception:
    +            self.__notes__ = None
     
             if exc_type and issubclass(exc_type, SyntaxError):
                 # Handle SyntaxError's specially
  8. corona10 commented on Dec 8, 2022

    @corona10
    corona10
    on Dec 8, 2022
    Member
    More actions

    @vxgmichel
    I think that you can open a new issue if you want.

  9. meili-bors
    added a commit that references this issue on Mar 14, 2023

    Merge #353

    2b49032
  10. gignsky
    added a commit that references this issue on Apr 6, 2023

    Bump exceptiongroup from 1.1.0 to 1.1.1 (#61)

    54f5f72
  11. meili-bors
    added a commit that references this issue on Jul 4, 2023

    Merge #793

    7a2724d
  12. meili-bors
    added a commit that references this issue on Sep 4, 2023

    Merge #837

    797c19a
  13. meili-bors
    added a commit that references this issue on Dec 1, 2023

    Merge #893

    226f14d
  14. mkjpryor
    added a commit that references this issue on Apr 19, 2024

    Bump exceptiongroup from 1.2.0 to 1.2.1 (#76)

    4c84722
  15. github-actions
    added a commit that references this issue on Apr 21, 2024

    Bump exceptiongroup from 1.2.0 to 1.2.1 (#1045)

    49fccf3
  16. meili-bors
    added a commit that references this issue on May 1, 2024

    Merge #953

    b78b726
  17. shaldengeki
    added a commit that references this issue on Jun 6, 2024

    Bump exceptiongroup from 1.2.0 to 1.2.1 in /src/python (#106)

    99d4e81
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402520 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.