Refactor QStandardPaths handling.

This commit is contained in:
Florian Bruhin 2015-02-22 19:13:51 +01:00
parent cabe5bf2a3
commit c5a2039da4
14 changed files with 97 additions and 125 deletions

View File

@ -34,7 +34,7 @@ import faulthandler
from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox
from PyQt5.QtGui import QDesktopServices, QPixmap, QIcon
from PyQt5.QtCore import (pyqtSlot, qInstallMessageHandler, QTimer, QUrl,
QStandardPaths, QObject, Qt)
QObject, Qt)
import qutebrowser
import qutebrowser.resources # pylint: disable=unused-import
@ -172,9 +172,9 @@ class Application(QApplication):
readline_bridge = readline.ReadlineBridge()
objreg.register('readline-bridge', readline_bridge)
log.init.debug("Initializing directories...")
standarddir.init()
standarddir.init(self._args)
log.init.debug("Initializing config...")
config.init(self._args)
config.init()
save_manager.init_autosave()
log.init.debug("Initializing web history...")
history.init()
@ -223,8 +223,7 @@ class Application(QApplication):
def _handle_segfault(self):
"""Handle a segfault from a previous run."""
path = standarddir.get(QStandardPaths.DataLocation)
logname = os.path.join(path, 'crash.log')
logname = os.path.join(standarddir.data, 'crash.log')
try:
# First check if an old logfile exists.
if os.path.exists(logname):
@ -248,8 +247,7 @@ class Application(QApplication):
def _init_crashlogfile(self):
"""Start a new logfile and redirect faulthandler to it."""
path = standarddir.get(QStandardPaths.DataLocation)
logname = os.path.join(path, 'crash.log')
logname = os.path.join(standarddir.data, 'crash.log')
try:
self._crashlogfile = open(logname, 'w', encoding='ascii')
except OSError:

View File

@ -25,7 +25,7 @@ import functools
import posixpath
import zipfile
from PyQt5.QtCore import QStandardPaths, QTimer
from PyQt5.QtCore import QTimer
from qutebrowser.config import config
from qutebrowser.utils import objreg, standarddir, log, message
@ -92,8 +92,7 @@ class HostBlocker:
self.blocked_hosts = set()
self._in_progress = []
self._done_count = 0
data_dir = standarddir.get(QStandardPaths.DataLocation)
self._hosts_file = os.path.join(data_dir, 'blocked-hosts')
self._hosts_file = os.path.join(standarddir.data, 'blocked-hosts')
objreg.get('config').changed.connect(self.on_config_changed)
def read_hosts(self):

View File

@ -21,7 +21,6 @@
import os.path
from PyQt5.QtCore import QStandardPaths
from PyQt5.QtNetwork import QNetworkDiskCache, QNetworkCacheMetaData
from qutebrowser.config import config
@ -34,8 +33,7 @@ class DiskCache(QNetworkDiskCache):
def __init__(self, parent=None):
super().__init__(parent)
cache_dir = standarddir.get(QStandardPaths.CacheLocation)
self.setCacheDirectory(os.path.join(cache_dir, 'http'))
self.setCacheDirectory(os.path.join(standarddir.cache, 'http'))
self.setMaximumCacheSize(config.get('storage', 'cache-size'))
objreg.get('config').changed.connect(self.cache_size_changed)

View File

@ -20,7 +20,7 @@
"""Handling of HTTP cookies."""
from PyQt5.QtNetwork import QNetworkCookie, QNetworkCookieJar
from PyQt5.QtCore import pyqtSignal, QStandardPaths, QDateTime
from PyQt5.QtCore import pyqtSignal, QDateTime
from qutebrowser.config import config
from qutebrowser.config.parsers import line as lineparser
@ -70,8 +70,7 @@ class CookieJar(RAMCookieJar):
def __init__(self, parent=None):
super().__init__(parent)
datadir = standarddir.get(QStandardPaths.DataLocation)
self._linecp = lineparser.LineConfigParser(datadir, 'cookies',
self._linecp = lineparser.LineConfigParser(standarddir.data, 'cookies',
binary=True, parent=self)
cookies = []
for line in self._linecp:

View File

@ -28,8 +28,7 @@ import functools
import collections
from PyQt5.QtCore import (pyqtSlot, pyqtSignal, QObject, QTimer,
QStandardPaths, Qt, QVariant, QAbstractListModel,
QModelIndex, QUrl)
Qt, QVariant, QAbstractListModel, QModelIndex, QUrl)
from PyQt5.QtGui import QDesktopServices
from PyQt5.QtNetwork import QNetworkRequest, QNetworkReply
# We need this import so PyQt can use it inside pyqtSlot
@ -414,8 +413,7 @@ class DownloadItem(QObject):
# save it under that filename in the default directory.
download_dir = config.get('storage', 'download-directory')
if download_dir is None:
download_dir = standarddir.get(
QStandardPaths.DownloadLocation)
download_dir = standarddir.download
self._filename = os.path.join(download_dir, filename)
self.basename = filename
log.downloads.debug("Setting filename to {}".format(filename))

View File

@ -22,7 +22,7 @@
import time
import functools
from PyQt5.QtCore import pyqtSignal, QStandardPaths
from PyQt5.QtCore import pyqtSignal
from PyQt5.QtWebKit import QWebHistoryInterface
from qutebrowser.utils import utils, objreg, standarddir
@ -64,8 +64,7 @@ class WebHistory(QWebHistoryInterface):
def __init__(self, parent=None):
super().__init__(parent)
datadir = standarddir.get(QStandardPaths.DataLocation)
self._linecp = lineparser.LineConfigParser(datadir, 'history',
self._linecp = lineparser.LineConfigParser(standarddir.data, 'history',
parent=self)
self._history = [HistoryEntry.from_str(e) for e in self._linecp.data]
objreg.get('save-manager').add_saveable('history', self.save,

View File

@ -28,7 +28,7 @@ import os.path
import functools
import collections
from PyQt5.QtCore import pyqtSignal, QStandardPaths, QUrl, QObject
from PyQt5.QtCore import pyqtSignal, QUrl, QObject
from qutebrowser.utils import message, usertypes, urlutils, standarddir, objreg
from qutebrowser.commands import cmdexc, cmdutils
@ -52,9 +52,8 @@ class QuickmarkManager(QObject):
self.marks = collections.OrderedDict()
confdir = standarddir.get(QStandardPaths.ConfigLocation)
self._linecp = lineparser.LineConfigParser(confdir, 'quickmarks',
parent=self)
self._linecp = lineparser.LineConfigParser(
standarddir.config, 'quickmarks', parent=self)
for line in self._linecp:
try:
key, url = line.rsplit(maxsplit=1)
@ -62,7 +61,7 @@ class QuickmarkManager(QObject):
message.error(0, "Invalid quickmark '{}'".format(line))
else:
self.marks[key] = url
filename = os.path.join(confdir, 'quickmarks')
filename = os.path.join(standarddir.config, 'quickmarks')
objreg.get('save-manager').add_saveable('quickmark-manager', self.save,
self.changed,
filename=filename)

View File

@ -23,8 +23,8 @@ import os
import os.path
import tempfile
from PyQt5.QtCore import (pyqtSignal, pyqtSlot, QObject, QStandardPaths,
QSocketNotifier, QProcessEnvironment, QProcess)
from PyQt5.QtCore import (pyqtSignal, pyqtSlot, QObject, QSocketNotifier,
QProcessEnvironment, QProcess)
from qutebrowser.utils import message, log, objreg, standarddir
from qutebrowser.commands import runners, cmdexc
@ -178,7 +178,6 @@ class _POSIXUserscriptRunner(_BaseUserscriptRunner):
self._reader = None
def run(self, cmd, *args, env=None):
rundir = standarddir.get(QStandardPaths.RuntimeLocation)
try:
# tempfile.mktemp is deprecated and discouraged, but we use it here
# to create a FIFO since the only other alternative would be to
@ -186,7 +185,7 @@ class _POSIXUserscriptRunner(_BaseUserscriptRunner):
# os.mkfifo will raise an exception anyways when the path doesn't
# exist, it shouldn't be a big issue.
self._filepath = tempfile.mktemp(prefix='qutebrowser-userscript-',
dir=rundir)
dir=standarddir.runtime)
os.mkfifo(self._filepath) # pylint: disable=no-member
except OSError as e:
message.error(self._win_id, "Error while creating FIFO: {}".format(

View File

@ -32,8 +32,7 @@ import configparser
import collections
import collections.abc
from PyQt5.QtCore import (pyqtSignal, pyqtSlot, QObject, QStandardPaths, QUrl,
QSettings)
from PyQt5.QtCore import pyqtSignal, pyqtSlot, QObject, QUrl, QSettings
from PyQt5.QtWidgets import QMessageBox
from qutebrowser.config import configdata, configexc, textwrapper
@ -114,16 +113,11 @@ def section(sect):
return objreg.get('config')[sect]
def _init_main_config(args):
"""Initialize the main config.
Args:
args: The argparse namespace.
"""
confdir = standarddir.get(QStandardPaths.ConfigLocation, args)
def _init_main_config():
"""Initialize the main config."""
try:
app = objreg.get('app')
config_obj = ConfigManager(confdir, 'qutebrowser.conf', app)
config_obj = ConfigManager(standarddir.config, 'qutebrowser.conf', app)
except (configexc.Error, configparser.Error, UnicodeDecodeError) as e:
log.init.exception(e)
errstr = "Error while reading config:"
@ -140,8 +134,8 @@ def _init_main_config(args):
sys.exit(1)
else:
objreg.register('config', config_obj)
if confdir is not None:
filename = os.path.join(confdir, 'qutebrowser.conf')
if standarddir.config is not None:
filename = os.path.join(standarddir.config, 'qutebrowser.conf')
save_manager = objreg.get('save-manager')
save_manager.add_saveable(
'config', config_obj.save, config_obj.changed,
@ -155,15 +149,10 @@ def _init_main_config(args):
return
def _init_key_config(args):
"""Initialize the key config.
Args:
args: The argparse namespace.
"""
confdir = standarddir.get(QStandardPaths.ConfigLocation, args)
def _init_key_config():
"""Initialize the key config."""
try:
key_config = keyconf.KeyConfigParser(confdir, 'keys.conf')
key_config = keyconf.KeyConfigParser(standarddir.config, 'keys.conf')
except (keyconf.KeyConfigError, UnicodeDecodeError) as e:
log.init.exception(e)
errstr = "Error while reading key config:\n"
@ -177,29 +166,24 @@ def _init_key_config(args):
sys.exit(1)
else:
objreg.register('key-config', key_config)
if confdir is not None:
if standarddir.config is not None:
save_manager = objreg.get('save-manager')
filename = os.path.join(confdir, 'keys.conf')
filename = os.path.join(standarddir.config, 'keys.conf')
save_manager.add_saveable(
'key-config', key_config.save, key_config.changed,
config_opt=('general', 'auto-save-config'), filename=filename)
def _init_misc(args):
"""Initialize misc. config-related files.
Args:
args: The argparse namespace.
"""
def _init_misc():
"""Initialize misc. config-related files."""
save_manager = objreg.get('save-manager')
datadir = standarddir.get(QStandardPaths.DataLocation, args)
state_config = ini.ReadWriteConfigParser(datadir, 'state')
state_config = ini.ReadWriteConfigParser(standarddir.data, 'state')
objreg.register('state-config', state_config)
save_manager.add_saveable('state-config', state_config.save)
# We need to import this here because lineparser needs config.
from qutebrowser.config.parsers import line
command_history = line.LineConfigParser(datadir, 'cmd-history',
command_history = line.LineConfigParser(standarddir.data, 'cmd-history',
('completion', 'history-length'),
parent=objreg.get('config'))
objreg.register('command-history', command_history)
@ -213,24 +197,19 @@ def _init_misc(args):
# This fixes one of the corruption issues here:
# https://github.com/The-Compiler/qutebrowser/issues/515
config_path = standarddir.get(QStandardPaths.ConfigLocation, args)
if config_path is None:
if standarddir.config is None:
path = os.devnull
else:
path = os.path.join(config_path, 'qsettings')
path = os.path.join(standarddir.config, 'qsettings')
for fmt in (QSettings.NativeFormat, QSettings.IniFormat):
QSettings.setPath(fmt, QSettings.UserScope, path)
def init(args):
"""Initialize the config.
Args:
args: The argparse namespace.
"""
_init_main_config(args)
_init_key_config(args)
_init_misc(args)
def init():
"""Initialize the config."""
_init_main_config()
_init_key_config()
_init_misc()
class ConfigManager(QObject):

View File

@ -29,7 +29,7 @@ Module attributes:
import os.path
from PyQt5.QtWebKit import QWebSettings
from PyQt5.QtCore import QStandardPaths, QUrl
from PyQt5.QtCore import QUrl
from qutebrowser.config import config
from qutebrowser.utils import usertypes, standarddir, objreg
@ -194,15 +194,13 @@ def _set_setting(typ, arg, default=UNSET, value=UNSET):
def init():
"""Initialize the global QWebSettings."""
cachedir = standarddir.get(QStandardPaths.CacheLocation)
QWebSettings.setIconDatabasePath(cachedir)
QWebSettings.setIconDatabasePath(standarddir.cache)
QWebSettings.setOfflineWebApplicationCachePath(
os.path.join(cachedir, 'application-cache'))
datadir = standarddir.get(QStandardPaths.DataLocation)
os.path.join(standarddir.cache, 'application-cache'))
QWebSettings.globalSettings().setLocalStoragePath(
os.path.join(datadir, 'local-storage'))
os.path.join(standarddir.data, 'local-storage'))
QWebSettings.setOfflineStoragePath(
os.path.join(datadir, 'offline-storage'))
os.path.join(standarddir.data, 'offline-storage'))
global settings
settings = QWebSettings.globalSettings()

View File

@ -22,8 +22,7 @@
import os
import os.path
from PyQt5.QtCore import (pyqtSignal, QStandardPaths, QUrl, QObject, QPoint,
QTimer)
from PyQt5.QtCore import pyqtSignal, QUrl, QObject, QPoint, QTimer
from PyQt5.QtWidgets import QApplication
import yaml
try:
@ -65,8 +64,7 @@ class SessionManager(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self._base_path = os.path.join(
standarddir.get(QStandardPaths.DataLocation), 'sessions')
self._base_path = os.path.join(standarddir.data, 'sessions')
self._last_window_session = None
if not os.path.exists(self._base_path):
os.mkdir(self._base_path)

View File

@ -34,7 +34,7 @@ from PyQt5.QtGui import QColor
from qutebrowser.config import config, configexc
from qutebrowser.test import helpers
from qutebrowser.utils import objreg
from qutebrowser.utils import objreg, standarddir
class ConfigParserTests(unittest.TestCase):
@ -184,7 +184,8 @@ class ConfigInitTests(unittest.TestCase):
"""Test initializing with config path set to None."""
args = types.SimpleNamespace(confdir='')
with helpers.environ_set_temp(self.env):
config.init(args)
standarddir.init(args)
config.init()
self.assertFalse(os.listdir(self.conf_path))

View File

@ -26,8 +26,6 @@ import shutil
import unittest
import tempfile
from PyQt5.QtCore import QStandardPaths
from qutebrowser.utils import standarddir
from qutebrowser.test import helpers, qApp
@ -50,53 +48,53 @@ class GetStandardDirLinuxTests(unittest.TestCase):
def test_data_explicit(self):
"""Test data dir with XDG_DATA_HOME explicitely set."""
with helpers.environ_set_temp({'XDG_DATA_HOME': self.temp_dir}):
cur_dir = standarddir.get(QStandardPaths.DataLocation)
self.assertEqual(cur_dir, os.path.join(self.temp_dir,
'qutebrowser'))
standarddir.init(None)
expected = os.path.join(self.temp_dir, 'qutebrowser')
self.assertEqual(standarddir.data, expected)
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_config_explicit(self):
"""Test config dir with XDG_CONFIG_HOME explicitely set."""
with helpers.environ_set_temp({'XDG_CONFIG_HOME': self.temp_dir}):
cur_dir = standarddir.get(QStandardPaths.ConfigLocation)
self.assertEqual(cur_dir, os.path.join(self.temp_dir,
'qutebrowser'))
standarddir.init(None)
expected = os.path.join(self.temp_dir, 'qutebrowser')
self.assertEqual(standarddir.config, expected)
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_cache_explicit(self):
"""Test cache dir with XDG_CACHE_HOME explicitely set."""
with helpers.environ_set_temp({'XDG_CACHE_HOME': self.temp_dir}):
cur_dir = standarddir.get(QStandardPaths.CacheLocation)
self.assertEqual(cur_dir, os.path.join(self.temp_dir,
'qutebrowser'))
standarddir.init(None)
expected = os.path.join(self.temp_dir, 'qutebrowser')
self.assertEqual(standarddir.cache, expected)
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_data(self):
"""Test data dir with XDG_DATA_HOME not set."""
env = {'HOME': self.temp_dir, 'XDG_DATA_HOME': None}
with helpers.environ_set_temp(env):
cur_dir = standarddir.get(QStandardPaths.DataLocation)
self.assertEqual(cur_dir, os.path.join(self.temp_dir, '.local',
'share', 'qutebrowser'))
standarddir.init(None)
expected = os.path.join(self.temp_dir, '.local', 'share',
'qutebrowser')
self.assertEqual(standarddir.data, expected)
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_config(self):
"""Test config dir with XDG_CONFIG_HOME not set."""
env = {'HOME': self.temp_dir, 'XDG_CONFIG_HOME': None}
with helpers.environ_set_temp(env):
cur_dir = standarddir.get(
QStandardPaths.ConfigLocation)
self.assertEqual(cur_dir, os.path.join(self.temp_dir, '.config',
'qutebrowser'))
standarddir.init(None)
expected = os.path.join(self.temp_dir, '.config', 'qutebrowser')
self.assertEqual(standarddir.config, expected)
@unittest.skipUnless(sys.platform.startswith("linux"), "requires Linux")
def test_cache(self):
"""Test cache dir with XDG_CACHE_HOME not set."""
env = {'HOME': self.temp_dir, 'XDG_CACHE_HOME': None}
with helpers.environ_set_temp(env):
cur_dir = standarddir.get(QStandardPaths.CacheLocation)
self.assertEqual(cur_dir, os.path.join(self.temp_dir, '.cache',
'qutebrowser'))
standarddir.init(None)
expected = os.path.join(self.temp_dir, '.cache', 'qutebrowser')
self.assertEqual(standarddir.cache, expected)
def tearDown(self):
qApp.setApplicationName(self.old_name)
@ -115,6 +113,7 @@ class GetStandardDirWindowsTests(unittest.TestCase):
self.old_name = qApp.applicationName()
# We can't store the files in a temp dir, so we don't chose qutebrowser
qApp.setApplicationName('qutebrowser_test')
standarddir.init(None)
def tearDown(self):
qApp.setApplicationName(self.old_name)
@ -122,20 +121,18 @@ class GetStandardDirWindowsTests(unittest.TestCase):
@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
def test_data(self):
"""Test data dir."""
cur_dir = standarddir.get(QStandardPaths.DataLocation)
self.assertEqual(cur_dir.split(os.sep)[-2:],
['qutebrowser_test', 'data'], cur_dir)
self.assertEqual(standarddir.data.split(os.sep)[-2:],
['qutebrowser_test', 'data'], standarddir.data)
@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
def test_config(self):
"""Test config dir."""
cur_dir = standarddir.get(QStandardPaths.ConfigLocation)
self.assertEqual(cur_dir.split(os.sep)[-1], 'qutebrowser_test',
cur_dir)
self.assertEqual(standarddir.config.split(os.sep)[-1],
'qutebrowser_test',
standarddir.config)
@unittest.skipUnless(sys.platform.startswith("win"), "requires Windows")
def test_cache(self):
"""Test cache dir."""
cur_dir = standarddir.get(QStandardPaths.CacheLocation)
self.assertEqual(cur_dir.split(os.sep)[-2:],
['qutebrowser_test', 'cache'], cur_dir)
self.assertEqual(standarddir.cache.split(os.sep)[-2:],
['qutebrowser_test', 'cache'], standarddir.cache)

View File

@ -27,6 +27,13 @@ from PyQt5.QtCore import QCoreApplication, QStandardPaths
from qutebrowser.utils import log, qtutils
config = None
data = None
cache = None
download = None
runtime = None
def _writable_location(typ):
"""Wrapper around QStandardPaths.writableLocation."""
with qtutils.unset_organization():
@ -68,7 +75,7 @@ def _from_args(typ, args):
return (True, arg_value)
def get(typ, args=None):
def _get(typ, args=None):
"""Get the directory where files of the given type should be written to.
Args:
@ -99,11 +106,14 @@ def get(typ, args=None):
return path
def init():
def init(args):
"""Initialize all standard dirs."""
config_dir = get(QStandardPaths.ConfigLocation)
data_dir = get(QStandardPaths.DataLocation)
cache_dir = get(QStandardPaths.CacheLocation)
global config, data, cache, download, runtime
config = _get(QStandardPaths.ConfigLocation, args)
data = _get(QStandardPaths.DataLocation, args)
cache = _get(QStandardPaths.CacheLocation, args)
download = _get(QStandardPaths.DownloadLocation, args)
runtime = _get(QStandardPaths.RuntimeLocation, args)
# 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
@ -113,11 +123,11 @@ def init():
# This is slightly wrong according to the standard as we ensure these paths
# exists while initializing, not when writing the file - but practicality
# beats purity.
for path in (config_dir, data_dir, cache_dir):
for path in (config, data, cache):
if path is not None and not os.path.exists(path):
os.makedirs(path, 0o700)
# http://www.brynosaurus.com/cachedir/spec.html
cachedir_tag = os.path.join(cache_dir, 'CACHEDIR.TAG')
cachedir_tag = os.path.join(cache, 'CACHEDIR.TAG')
if not os.path.exists(cachedir_tag):
try:
with open(cachedir_tag, 'w', encoding='utf-8') as f: