diff --git a/qutebrowser/utils/standarddir.py b/qutebrowser/utils/standarddir.py index bbe61c459..6e78577d4 100644 --- a/qutebrowser/utils/standarddir.py +++ b/qutebrowser/utils/standarddir.py @@ -21,6 +21,7 @@ import os import os.path +import getpass from PyQt5.QtCore import QCoreApplication, QStandardPaths @@ -56,6 +57,11 @@ def runtime(): return _get(QStandardPaths.RuntimeLocation) +def temp(): + """Convenience function to get the temporary files location.""" + return _get(QStandardPaths.TempLocation) + + def _writable_location(typ): """Wrapper around QStandardPaths.writableLocation.""" with qtutils.unset_organization(): @@ -97,7 +103,10 @@ def _from_args(typ, args): if getattr(args, 'basedir', None) is not None: basedir = args.basedir - suffix = basedir_suffix[typ] + try: + suffix = basedir_suffix[typ] + except KeyError: + return (False, None) return (True, os.path.join(basedir, suffix)) try: @@ -124,12 +133,13 @@ def _get(typ): if not overridden: path = _writable_location(typ) appname = QCoreApplication.instance().applicationName() + if (typ == QStandardPaths.ConfigLocation and path.split(os.sep)[-1] != appname): # WORKAROUND - see # https://bugreports.qt.io/browse/QTBUG-38872 path = os.path.join(path, appname) - if typ == QStandardPaths.DataLocation and os.name == 'nt': + elif typ == QStandardPaths.DataLocation and os.name == 'nt': # Under windows, config/data might end up in the same directory. data_path = QStandardPaths.writableLocation( QStandardPaths.DataLocation) @@ -137,6 +147,14 @@ def _get(typ): QStandardPaths.ConfigLocation) if data_path == config_path: path = os.path.join(path, 'data') + elif typ == QStandardPaths.TempLocation: + # "The returned value might be application-specific, shared among + # other applications for this user, or even system-wide." + subdir = '{}-{}'.format(appname, getpass.getuser()) + path = os.path.join(path, subdir) + elif typ == QStandardPaths.RuntimeLocation: + # This is generic, but per-user. + path = os.path.join(path, appname) # From the XDG basedir spec: # If, when attempting to write a file, the destination directory is # non-existant an attempt should be made to create it with permission diff --git a/tests/conftest.py b/tests/conftest.py index bed1dd107..f6a32dcd2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -95,6 +95,12 @@ def pytest_runtest_setup(item): pytest.skip("Can only run when frozen!") +@pytest.fixture(autouse=True, scope='session') +def change_qapp_name(qapp): + """Change the name of the QApplication instance.""" + qapp.setApplicationName('qutebrowser_test') + + class WinRegistryHelper: """Helper class for win_registry.""" diff --git a/tests/unit/utils/test_standarddir.py b/tests/unit/utils/test_standarddir.py index fbe2c268a..0268e387c 100644 --- a/tests/unit/utils/test_standarddir.py +++ b/tests/unit/utils/test_standarddir.py @@ -58,6 +58,12 @@ def reset_standarddir(): standarddir.init(None) +@pytest.fixture(autouse=True) +def patch_username(monkeypatch): + monkeypatch.setattr('qutebrowser.utils.standarddir.getpass.getuser', + lambda: 'user') + + @pytest.mark.parametrize('data_subdir, config_subdir, expected', [ ('foo', 'foo', 'foo/data'), ('foo', 'bar', 'foo'), @@ -118,6 +124,11 @@ class TestGetStandardDirLinux: monkeypatch.setenv('XDG_CACHE_HOME', str(tmpdir)) assert standarddir.cache() == str(tmpdir / 'qutebrowser_test') + def test_temp_explicit(self, monkeypatch, tmpdir): + """Test temp dir with TMPDIR explicitly set.""" + monkeypatch.setenv('TMPDIR', str(tmpdir)) + assert standarddir.temp() == str(tmpdir / 'qutebrowser_test-user') + def test_data(self, monkeypatch, tmpdir): """Test data dir with XDG_DATA_HOME not set.""" monkeypatch.setenv('HOME', str(tmpdir)) @@ -139,6 +150,11 @@ class TestGetStandardDirLinux: expected = tmpdir / '.cache' / 'qutebrowser_test' assert standarddir.cache() == expected + def test_temp(self, monkeypatch, tmpdir): + """Test temp dir with TMPDIR not set.""" + monkeypatch.delenv('TMPDIR', raising=False) + assert standarddir.temp().split(os.sep)[-1] == 'qutebrowser_test-user' + @pytest.mark.windows @pytest.mark.usefixtures('no_cachedir_tag') @@ -160,6 +176,9 @@ class TestGetStandardDirWindows: expected = ['qutebrowser_test', 'cache'] assert standarddir.cache().split(os.sep)[-2:] == expected + def test_temp(self): + assert standarddir.temp().split(os.sep)[-1] == 'qutebrowser_test-user' + DirArgTest = collections.namedtuple('DirArgTest', 'arg, expected') @@ -225,6 +244,13 @@ class TestArguments: func = getattr(standarddir, typ) assert func() == expected + def test_basedir_temp(self, tmpdir): + """Make sure the temp file location is not influenced by basedir.""" + args = types.SimpleNamespace(basedir=str(tmpdir)) + standarddir.init(args) + qute_tempdir = standarddir.temp() + assert not qute_tempdir.startswith(str(tmpdir)) + class TestInitCacheDirTag: