summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Bruhin <me@the-compiler.org>2023-11-22 20:11:41 +0100
committerFlorian Bruhin <me@the-compiler.org>2023-11-22 20:14:33 +0100
commit8a53e9b282749f5ff17d40366077bc8a00a1ef16 (patch)
treeb799eb1e1571dbaf890ca4b695c1acd14925f281
parent2e2e0c8031ed3449565aefd7908435661c1c2b48 (diff)
downloadqutebrowser-pakjoy.tar.gz
qutebrowser-pakjoy.zip
pakjoy: Use proper logic to discover resources dirpakjoy
-rw-r--r--qutebrowser/misc/pakjoy.py42
-rw-r--r--tests/unit/misc/test_pakjoy.py90
2 files changed, 120 insertions, 12 deletions
diff --git a/qutebrowser/misc/pakjoy.py b/qutebrowser/misc/pakjoy.py
index ec9906731..6765c8687 100644
--- a/qutebrowser/misc/pakjoy.py
+++ b/qutebrowser/misc/pakjoy.py
@@ -31,7 +31,7 @@ import pathlib
import dataclasses
from typing import ClassVar, IO, Optional, Dict, Tuple
-from qutebrowser.misc import binparsing
+from qutebrowser.misc import binparsing, objects
from qutebrowser.utils import qtutils, standarddir, version, utils, log
HANGOUTS_MARKER = b"// Extension ID: nkeimhogjdpnpccoofpliimaahmaaome"
@@ -146,17 +146,43 @@ class PakParser:
raise binparsing.ParseError("Couldn't find hangouts manifest")
-def copy_webengine_resources() -> Optional[pathlib.Path]:
- """Copy qtwebengine resources to local dir for patching."""
- resources_dir = qtutils.library_path(qtutils.LibraryPath.data)
+def _find_webengine_resources() -> pathlib.Path:
+ """Find the QtWebEngine resources dir.
+
+ Mirrors logic from QtWebEngine:
+ https://github.com/qt/qtwebengine/blob/v6.6.0/src/core/web_engine_library_info.cpp#L293-L341
+ """
+ if RESOURCES_ENV_VAR in os.environ:
+ return pathlib.Path(os.environ[RESOURCES_ENV_VAR])
+
+ candidates = []
+ qt_data_path = qtutils.library_path(qtutils.LibraryPath.data)
if utils.is_mac: # pragma: no cover
# I'm not sure how to arrive at this path without hardcoding it
# ourselves. importlib_resources("PyQt6.Qt6") can serve as a
# replacement for the qtutils bit but it doesn't seem to help find the
- # actually Resources folder.
- resources_dir /= pathlib.Path("lib", "QtWebEngineCore.framework", "Resources")
- else:
- resources_dir /= "resources"
+ # actuall Resources folder.
+ candidates.append(
+ qt_data_path / "lib" / "QtWebEngineCore.framework" / "Resources"
+ )
+
+ candidates += [
+ qt_data_path / "resources",
+ qt_data_path,
+ pathlib.Path(objects.qapp.applicationDirPath()),
+ pathlib.Path.home() / f".{objects.qapp.applicationName()}",
+ ]
+
+ for candidate in candidates:
+ if (candidate / PAK_FILENAME).exists():
+ return candidate
+
+ raise binparsing.ParseError("Couldn't find webengine resources dir")
+
+
+def copy_webengine_resources() -> Optional[pathlib.Path]:
+ """Copy qtwebengine resources to local dir for patching."""
+ resources_dir = _find_webengine_resources()
work_dir = pathlib.Path(standarddir.cache()) / CACHE_DIR_NAME
if work_dir.exists():
diff --git a/tests/unit/misc/test_pakjoy.py b/tests/unit/misc/test_pakjoy.py
index e8463a8b2..55a147269 100644
--- a/tests/unit/misc/test_pakjoy.py
+++ b/tests/unit/misc/test_pakjoy.py
@@ -36,10 +36,9 @@ skip_if_unsupported = pytest.mark.skipif(
@pytest.fixture(autouse=True)
-def clean_env():
- yield
- if pakjoy.RESOURCES_ENV_VAR in os.environ:
- del os.environ[pakjoy.RESOURCES_ENV_VAR]
+def prepare_env(qapp, monkeypatch):
+ monkeypatch.setattr(pakjoy.objects, "qapp", qapp)
+ monkeypatch.delenv(pakjoy.RESOURCES_ENV_VAR, raising=False)
def patch_version(monkeypatch, *args):
@@ -78,6 +77,86 @@ def test_version_gate(cache_tmpdir, unaffected_version, mocker, workdir_exists):
assert not workdir.exists()
+class TestFindWebengineResources:
+ @pytest.fixture
+ def qt_data_path(self, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path):
+ """Patch qtutils.library_path() to return a temp dir."""
+ qt_data_path = tmp_path / "qt_data"
+ qt_data_path.mkdir()
+ monkeypatch.setattr(pakjoy.qtutils, "library_path", lambda _which: qt_data_path)
+ return qt_data_path
+
+ @pytest.fixture
+ def application_dir_path(
+ self,
+ monkeypatch: pytest.MonkeyPatch,
+ tmp_path: pathlib.Path,
+ qt_data_path: pathlib.Path, # needs patching
+ ):
+ """Patch QApplication.applicationDirPath() to return a temp dir."""
+ app_dir_path = tmp_path / "app_dir"
+ app_dir_path.mkdir()
+ monkeypatch.setattr(
+ pakjoy.objects.qapp, "applicationDirPath", lambda: app_dir_path
+ )
+ return app_dir_path
+
+ @pytest.fixture
+ def fallback_path(
+ self,
+ monkeypatch: pytest.MonkeyPatch,
+ tmp_path: pathlib.Path,
+ qt_data_path: pathlib.Path, # needs patching
+ application_dir_path: pathlib.Path, # needs patching
+ ):
+ """Patch the fallback path to return a temp dir."""
+ home_path = tmp_path / "home"
+ monkeypatch.setattr(pakjoy.pathlib.Path, "home", lambda: home_path)
+
+ app_path = home_path / f".{pakjoy.objects.qapp.applicationName()}"
+ app_path.mkdir(parents=True)
+ return app_path
+
+ @pytest.mark.parametrize("create_file", [True, False])
+ def test_overridden(
+ self, monkeypatch: pytest.MonkeyPatch, tmp_path: pathlib.Path, create_file: bool
+ ):
+ """Test the overridden path is used."""
+ override_path = tmp_path / "override"
+ override_path.mkdir()
+ monkeypatch.setenv(pakjoy.RESOURCES_ENV_VAR, str(override_path))
+ if create_file: # should get this no matter if file exists or not
+ (override_path / pakjoy.PAK_FILENAME).touch()
+ assert pakjoy._find_webengine_resources() == override_path
+
+ @pytest.mark.parametrize("with_subfolder", [True, False])
+ def test_qt_data_path(self, qt_data_path: pathlib.Path, with_subfolder: bool):
+ """Test qtutils.library_path() is used."""
+ resources_path = qt_data_path
+ if with_subfolder:
+ resources_path /= "resources"
+ resources_path.mkdir()
+ (resources_path / pakjoy.PAK_FILENAME).touch()
+ assert pakjoy._find_webengine_resources() == resources_path
+
+ def test_application_dir_path(self, application_dir_path: pathlib.Path):
+ """Test QApplication.applicationDirPath() is used."""
+ (application_dir_path / pakjoy.PAK_FILENAME).touch()
+ assert pakjoy._find_webengine_resources() == application_dir_path
+
+ def test_fallback_path(self, fallback_path: pathlib.Path):
+ """Test fallback path is used."""
+ (fallback_path / pakjoy.PAK_FILENAME).touch()
+ assert pakjoy._find_webengine_resources() == fallback_path
+
+ def test_nowhere(self, fallback_path: pathlib.Path):
+ """Test we raise if we can't find the resources."""
+ with pytest.raises(
+ binparsing.ParseError, match="Couldn't find webengine resources dir"
+ ):
+ pakjoy._find_webengine_resources()
+
+
def json_without_comments(bytestring):
str_without_comments = "\n".join(
[
@@ -131,6 +210,9 @@ class TestWithRealResourcesFile:
tmpfile = work_dir / "tmp.txt"
tmpfile.touch()
+ # Set by first call to copy_webengine_resources()
+ del os.environ[pakjoy.RESOURCES_ENV_VAR]
+
pakjoy.copy_webengine_resources()
assert not tmpfile.exists()