summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2021-01-30 15:38:44 +0100
committerFlorian Bruhin <me@the-compiler.org>2021-01-30 15:45:44 +0100
commitfbce24d4a34922ec9d40a7af7927fbcebbbb0206 (patch)
tree94b0d3d2227ac268163f8037a57a80cd938eaaa1
parent1a31a4d5ab34e43732f8307162f47b4eeb3d2c27 (diff)
downloadqutebrowser-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.py21
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: