diff options
author | Florian Bruhin <me@the-compiler.org> | 2021-01-30 15:38:44 +0100 |
---|---|---|
committer | Florian Bruhin <me@the-compiler.org> | 2021-01-30 15:45:44 +0100 |
commit | fbce24d4a34922ec9d40a7af7927fbcebbbb0206 (patch) | |
tree | 94b0d3d2227ac268163f8037a57a80cd938eaaa1 | |
parent | 1a31a4d5ab34e43732f8307162f47b4eeb3d2c27 (diff) | |
download | qutebrowser-fbce24d4a34922ec9d40a7af7927fbcebbbb0206.tar.gz qutebrowser-fbce24d4a34922ec9d40a7af7927fbcebbbb0206.zip |
Handle KeyError for unknown resources
When importlib.resources (or the importlib_resources backport) uses
zipfile.Path in the Python 3.8/3.9 stdlib (rather than the zipp
backport), we get KeyError rather than a FileNotFoundError if a resource
does not exist. See https://bugs.python.org/issue43063.
We work around this by re-raising a KeyError as FileNotFoundError.
Fixes #6086
(cherry picked from commit 9313523ae144f350ce5c930e735ba9257c34067e)
-rw-r--r-- | qutebrowser/utils/utils.py | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/qutebrowser/utils/utils.py b/qutebrowser/utils/utils.py index 5e4c418ff..a52c5fada 100644 --- a/qutebrowser/utils/utils.py +++ b/qutebrowser/utils/utils.py @@ -192,6 +192,21 @@ def _resource_path(filename: str) -> pathlib.Path: return importlib_resources.files(qutebrowser) / filename +@contextlib.contextmanager +def _resource_keyerror_workaround() -> Iterator[None]: + """Re-raise KeyErrors as FileNotFoundErrors. + + WORKAROUND for zipfile.Path resources raising KeyError when a file was notfound: + https://bugs.python.org/issue43063 + + Only needed for Python 3.8 and 3.9. + """ + try: + yield + except KeyError as e: + raise FileNotFoundError(str(e)) + + def _glob_resources( resource_path: pathlib.Path, subdir: str, @@ -240,7 +255,8 @@ def read_file(filename: str) -> str: return _resource_cache[filename] path = _resource_path(filename) - return path.read_text(encoding='utf-8') + with _resource_keyerror_workaround(): + return path.read_text(encoding='utf-8') def read_file_binary(filename: str) -> bytes: @@ -253,7 +269,8 @@ def read_file_binary(filename: str) -> bytes: The file contents as a bytes object. """ path = _resource_path(filename) - return path.read_bytes() + with _resource_keyerror_workaround(): + return path.read_bytes() def parse_version(version: str) -> VersionNumber: |