summaryrefslogtreecommitdiff
path: root/qutebrowser/utils/utils.py
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:11 +0100
commit9313523ae144f350ce5c930e735ba9257c34067e (patch)
treef61198e35cb72b9641d9fa766a01366ea476a91a /qutebrowser/utils/utils.py
parent5ba5fbfe2a74f963d2ca0f1fd261975d19812d59 (diff)
downloadqutebrowser-9313523ae144f350ce5c930e735ba9257c34067e.tar.gz
qutebrowser-9313523ae144f350ce5c930e735ba9257c34067e.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
Diffstat (limited to 'qutebrowser/utils/utils.py')
-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: