Remove support for an empty data/config/cachedir

See #2115
This commit is contained in:
Florian Bruhin 2016-11-14 08:31:06 +01:00
parent b30d37e3e0
commit 81d67f8a2c
25 changed files with 110 additions and 392 deletions

View File

@ -39,13 +39,13 @@ show it.
show this help message and exit show this help message and exit
*-c* 'CONFDIR', *--confdir* 'CONFDIR':: *-c* 'CONFDIR', *--confdir* 'CONFDIR'::
Set config directory (empty for no config storage). Set config directory
*--datadir* 'DATADIR':: *--datadir* 'DATADIR'::
Set data directory (empty for no data storage). Set data directory
*--cachedir* 'CACHEDIR':: *--cachedir* 'CACHEDIR'::
Set cache directory (empty for no cache storage). Set cache directory
*--basedir* 'BASEDIR':: *--basedir* 'BASEDIR'::
Base directory for all storage. Other --*dir arguments are ignored if this is given. Base directory for all storage. Other --*dir arguments are ignored if this is given.

View File

@ -29,7 +29,7 @@ import fnmatch
from qutebrowser.browser import downloads from qutebrowser.browser import downloads
from qutebrowser.config import config from qutebrowser.config import config
from qutebrowser.utils import objreg, standarddir, log, message from qutebrowser.utils import objreg, standarddir, log, message
from qutebrowser.commands import cmdutils, cmdexc from qutebrowser.commands import cmdutils
def guess_zip_filename(zf): def guess_zip_filename(zf):
@ -113,17 +113,11 @@ class HostBlocker:
self._done_count = 0 self._done_count = 0
data_dir = standarddir.data() data_dir = standarddir.data()
if data_dir is None: self._local_hosts_file = os.path.join(data_dir, 'blocked-hosts')
self._local_hosts_file = None
else:
self._local_hosts_file = os.path.join(data_dir, 'blocked-hosts')
self.on_config_changed() self.on_config_changed()
config_dir = standarddir.config() config_dir = standarddir.config()
if config_dir is None: self._config_hosts_file = os.path.join(config_dir, 'blocked-hosts')
self._config_hosts_file = None
else:
self._config_hosts_file = os.path.join(config_dir, 'blocked-hosts')
objreg.get('config').changed.connect(self.on_config_changed) objreg.get('config').changed.connect(self.on_config_changed)
@ -146,7 +140,7 @@ class HostBlocker:
Return: Return:
True if a read was attempted, False otherwise True if a read was attempted, False otherwise
""" """
if filename is None or not os.path.exists(filename): if not os.path.exists(filename):
return False return False
try: try:
@ -162,9 +156,6 @@ class HostBlocker:
"""Read hosts from the existing blocked-hosts file.""" """Read hosts from the existing blocked-hosts file."""
self._blocked_hosts = set() self._blocked_hosts = set()
if self._local_hosts_file is None:
return
self._read_hosts_file(self._config_hosts_file, self._read_hosts_file(self._config_hosts_file,
self._config_blocked_hosts) self._config_blocked_hosts)
@ -186,8 +177,6 @@ class HostBlocker:
""" """
self._read_hosts_file(self._config_hosts_file, self._read_hosts_file(self._config_hosts_file,
self._config_blocked_hosts) self._config_blocked_hosts)
if self._local_hosts_file is None:
raise cmdexc.CommandError("No data storage is configured!")
self._blocked_hosts = set() self._blocked_hosts = set()
self._done_count = 0 self._done_count = 0
urls = config.get('content', 'host-block-lists') urls = config.get('content', 'host-block-lists')
@ -275,7 +264,7 @@ class HostBlocker:
def on_config_changed(self): def on_config_changed(self):
"""Update files when the config changed.""" """Update files when the config changed."""
urls = config.get('content', 'host-block-lists') urls = config.get('content', 'host-block-lists')
if urls is None and self._local_hosts_file is not None: if urls is None:
try: try:
os.remove(self._local_hosts_file) os.remove(self._local_hosts_file)
except FileNotFoundError: except FileNotFoundError:

View File

@ -129,7 +129,6 @@ class WebHistory(QObject):
Attributes: Attributes:
history_dict: An OrderedDict of URLs read from the on-disk history. history_dict: An OrderedDict of URLs read from the on-disk history.
_hist_dir: The directory to store the history in
_lineparser: The AppendLineParser used to save the history. _lineparser: The AppendLineParser used to save the history.
_new_history: A list of Entry items of the current session. _new_history: A list of Entry items of the current session.
_saved_count: How many HistoryEntries have been written to disk. _saved_count: How many HistoryEntries have been written to disk.
@ -157,7 +156,6 @@ class WebHistory(QObject):
super().__init__(parent) super().__init__(parent)
self._initial_read_started = False self._initial_read_started = False
self._initial_read_done = False self._initial_read_done = False
self._hist_dir = hist_dir
self._lineparser = lineparser.AppendLineParser(hist_dir, hist_name, self._lineparser = lineparser.AppendLineParser(hist_dir, hist_name,
parent=self) parent=self)
self.history_dict = collections.OrderedDict() self.history_dict = collections.OrderedDict()
@ -183,12 +181,6 @@ class WebHistory(QObject):
return return
self._initial_read_started = True self._initial_read_started = True
if self._hist_dir is None:
self._initial_read_done = True
self.async_read_done.emit()
assert not self._temp_history
return
with self._lineparser.open(): with self._lineparser.open():
for line in self._lineparser: for line in self._lineparser:
yield yield

View File

@ -73,8 +73,7 @@ class UrlMarkManager(QObject):
Attributes: Attributes:
marks: An OrderedDict of all quickmarks/bookmarks. marks: An OrderedDict of all quickmarks/bookmarks.
_lineparser: The LineParser used for the marks, or None _lineparser: The LineParser used for the marks
(when qutebrowser is started with -c '').
Signals: Signals:
changed: Emitted when anything changed. changed: Emitted when anything changed.
@ -91,10 +90,6 @@ class UrlMarkManager(QObject):
super().__init__(parent) super().__init__(parent)
self.marks = collections.OrderedDict() self.marks = collections.OrderedDict()
self._lineparser = None
if standarddir.config() is None:
return
self._init_lineparser() self._init_lineparser()
for line in self._lineparser: for line in self._lineparser:
@ -115,10 +110,8 @@ class UrlMarkManager(QObject):
def save(self): def save(self):
"""Save the marks to disk.""" """Save the marks to disk."""
if self._lineparser is not None: self._lineparser.data = [' '.join(tpl) for tpl in self.marks.items()]
self._lineparser.data = [' '.join(tpl) self._lineparser.save()
for tpl in self.marks.items()]
self._lineparser.save()
def delete(self, key): def delete(self, key):
"""Delete a quickmark/bookmark. """Delete a quickmark/bookmark.

View File

@ -32,23 +32,14 @@ class DiskCache(QNetworkDiskCache):
"""Disk cache which sets correct cache dir and size. """Disk cache which sets correct cache dir and size.
If the cache is deactivated via the command line argument --cachedir="",
both attributes _cache_dir and _http_cache_dir are set to None.
Attributes: Attributes:
_activated: Whether the cache should be used. _activated: Whether the cache should be used.
_cache_dir: The base directory for cache files (standarddir.cache()) or _cache_dir: The base directory for cache files (standarddir.cache())
None.
_http_cache_dir: the HTTP subfolder in _cache_dir or None.
""" """
def __init__(self, cache_dir, parent=None): def __init__(self, cache_dir, parent=None):
super().__init__(parent) super().__init__(parent)
self._cache_dir = cache_dir self._cache_dir = cache_dir
if cache_dir is None:
self._http_cache_dir = None
else:
self._http_cache_dir = os.path.join(cache_dir, 'http')
self._maybe_activate() self._maybe_activate()
objreg.get('config').changed.connect(self.on_config_changed) objreg.get('config').changed.connect(self.on_config_changed)
@ -59,12 +50,11 @@ class DiskCache(QNetworkDiskCache):
def _maybe_activate(self): def _maybe_activate(self):
"""Activate/deactivate the cache based on the config.""" """Activate/deactivate the cache based on the config."""
if (config.get('general', 'private-browsing') or if config.get('general', 'private-browsing'):
self._cache_dir is None):
self._activated = False self._activated = False
else: else:
self._activated = True self._activated = True
self.setCacheDirectory(self._http_cache_dir) self.setCacheDirectory(os.path.join(self._cache_dir, 'http'))
self.setMaximumCacheSize(config.get('storage', 'cache-size')) self.setMaximumCacheSize(config.get('storage', 'cache-size'))
@pyqtSlot(str, str) @pyqtSlot(str, str)

View File

@ -95,18 +95,17 @@ def init():
"""Initialize the global QWebSettings.""" """Initialize the global QWebSettings."""
cache_path = standarddir.cache() cache_path = standarddir.cache()
data_path = standarddir.data() data_path = standarddir.data()
if config.get('general', 'private-browsing') or cache_path is None: if config.get('general', 'private-browsing'):
QWebSettings.setIconDatabasePath('') QWebSettings.setIconDatabasePath('')
else: else:
QWebSettings.setIconDatabasePath(cache_path) QWebSettings.setIconDatabasePath(cache_path)
if cache_path is not None:
QWebSettings.setOfflineWebApplicationCachePath( QWebSettings.setOfflineWebApplicationCachePath(
os.path.join(cache_path, 'application-cache')) os.path.join(cache_path, 'application-cache'))
if data_path is not None: QWebSettings.globalSettings().setLocalStoragePath(
QWebSettings.globalSettings().setLocalStoragePath( os.path.join(data_path, 'local-storage'))
os.path.join(data_path, 'local-storage')) QWebSettings.setOfflineStoragePath(
QWebSettings.setOfflineStoragePath( os.path.join(data_path, 'offline-storage'))
os.path.join(data_path, 'offline-storage'))
websettings.init_mappings(MAPPINGS) websettings.init_mappings(MAPPINGS)
objreg.get('config').changed.connect(update_settings) objreg.get('config').changed.connect(update_settings)

View File

@ -408,15 +408,11 @@ def run_async(tab, cmd, *args, win_id, env, verbose=False):
user_agent = config.get('network', 'user-agent') user_agent = config.get('network', 'user-agent')
if user_agent is not None: if user_agent is not None:
env['QUTE_USER_AGENT'] = user_agent env['QUTE_USER_AGENT'] = user_agent
config_dir = standarddir.config()
if config_dir is not None: env['QUTE_CONFIG_DIR'] = standarddir.config()
env['QUTE_CONFIG_DIR'] = config_dir env['QUTE_DATA_DIR'] = standarddir.data()
data_dir = standarddir.data() env['QUTE_DOWNLOAD_DIR'] = downloads.download_dir()
if data_dir is not None:
env['QUTE_DATA_DIR'] = data_dir
download_dir = downloads.download_dir()
if download_dir is not None:
env['QUTE_DOWNLOAD_DIR'] = download_dir
cmd_path = os.path.expanduser(cmd) cmd_path = os.path.expanduser(cmd)
# if cmd is not given as an absolute path, look it up # if cmd is not given as an absolute path, look it up

View File

@ -160,19 +160,18 @@ def _init_main_config(parent=None):
sys.exit(usertypes.Exit.err_config) sys.exit(usertypes.Exit.err_config)
else: else:
objreg.register('config', config_obj) objreg.register('config', config_obj)
if standarddir.config() is not None: filename = os.path.join(standarddir.config(), 'qutebrowser.conf')
filename = os.path.join(standarddir.config(), 'qutebrowser.conf') save_manager = objreg.get('save-manager')
save_manager = objreg.get('save-manager') save_manager.add_saveable(
save_manager.add_saveable( 'config', config_obj.save, config_obj.changed,
'config', config_obj.save, config_obj.changed, config_opt=('general', 'auto-save-config'), filename=filename)
config_opt=('general', 'auto-save-config'), filename=filename) for sect in config_obj.sections.values():
for sect in config_obj.sections.values(): for opt in sect.values.values():
for opt in sect.values.values(): if opt.values['conf'] is None:
if opt.values['conf'] is None: # Option added to built-in defaults but not in user's
# Option added to built-in defaults but not in user's # config yet
# config yet save_manager.save('config', explicit=True, force=True)
save_manager.save('config', explicit=True, force=True) return
return
def _init_key_config(parent): def _init_key_config(parent):
@ -197,13 +196,12 @@ def _init_key_config(parent):
sys.exit(usertypes.Exit.err_key_config) sys.exit(usertypes.Exit.err_key_config)
else: else:
objreg.register('key-config', key_config) objreg.register('key-config', key_config)
if standarddir.config() is not None: save_manager = objreg.get('save-manager')
save_manager = objreg.get('save-manager') filename = os.path.join(standarddir.config(), 'keys.conf')
filename = os.path.join(standarddir.config(), 'keys.conf') save_manager.add_saveable(
save_manager.add_saveable( 'key-config', key_config.save, key_config.config_dirty,
'key-config', key_config.save, key_config.config_dirty, config_opt=('general', 'auto-save-config'), filename=filename,
config_opt=('general', 'auto-save-config'), filename=filename, dirty=key_config.is_dirty)
dirty=key_config.is_dirty)
def _init_misc(): def _init_misc():
@ -237,10 +235,7 @@ def _init_misc():
# This fixes one of the corruption issues here: # This fixes one of the corruption issues here:
# https://github.com/The-Compiler/qutebrowser/issues/515 # https://github.com/The-Compiler/qutebrowser/issues/515
if standarddir.config() is None: path = os.path.join(standarddir.config(), 'qsettings')
path = os.devnull
else:
path = os.path.join(standarddir.config(), 'qsettings')
for fmt in [QSettings.NativeFormat, QSettings.IniFormat]: for fmt in [QSettings.NativeFormat, QSettings.IniFormat]:
QSettings.setPath(fmt, QSettings.UserScope, path) QSettings.setPath(fmt, QSettings.UserScope, path)
@ -659,15 +654,11 @@ class ConfigManager(QObject):
def read(self, configdir, fname, relaxed=False): def read(self, configdir, fname, relaxed=False):
"""Read the config from the given directory/file.""" """Read the config from the given directory/file."""
self._fname = fname self._fname = fname
if configdir is None: self._configdir = configdir
self._configdir = None parser = ini.ReadConfigParser(configdir, fname)
self._initialized = True self._from_cp(parser, relaxed)
else: self._initialized = True
self._configdir = configdir self._validate_all()
parser = ini.ReadConfigParser(configdir, fname)
self._from_cp(parser, relaxed)
self._initialized = True
self._validate_all()
def items(self, sectname, raw=True): def items(self, sectname, raw=True):
"""Get a list of (optname, value) tuples for a section. """Get a list of (optname, value) tuples for a section.
@ -884,8 +875,6 @@ class ConfigManager(QObject):
def save(self): def save(self):
"""Save the config file.""" """Save the config file."""
if self._configdir is None:
return
configfile = os.path.join(self._configdir, self._fname) configfile = os.path.join(self._configdir, self._fname)
log.destroy.debug("Saving config to {}".format(configfile)) log.destroy.debug("Saving config to {}".format(configfile))
with qtutils.savefile_open(configfile) as f: with qtutils.savefile_open(configfile) as f:

View File

@ -859,9 +859,7 @@ class File(BaseType):
value = os.path.expanduser(value) value = os.path.expanduser(value)
value = os.path.expandvars(value) value = os.path.expandvars(value)
if not os.path.isabs(value): if not os.path.isabs(value):
cfgdir = standarddir.config() value = os.path.join(standarddir.config(), value)
assert cfgdir is not None
value = os.path.join(cfgdir, value)
return value return value
def validate(self, value): def validate(self, value):
@ -872,12 +870,7 @@ class File(BaseType):
value = os.path.expandvars(value) value = os.path.expandvars(value)
try: try:
if not os.path.isabs(value): if not os.path.isabs(value):
cfgdir = standarddir.config() value = os.path.join(standarddir.config(), value)
if cfgdir is None:
raise configexc.ValidationError(
value, "must be an absolute path when not using a "
"config directory!")
value = os.path.join(cfgdir, value)
not_isfile_message = ("must be a valid path relative to the " not_isfile_message = ("must be a valid path relative to the "
"config directory!") "config directory!")
else: else:
@ -1180,14 +1173,7 @@ class UserStyleSheet(File):
if not value: if not value:
return None return None
if standarddir.config() is None: path = super().transform(value)
# We can't call super().transform() here as this counts on the
# validation previously ensuring that we don't have a relative path
# when starting with -c "".
path = None
else:
path = super().transform(value)
if path is not None and os.path.exists(path): if path is not None and os.path.exists(path):
return QUrl.fromLocalFile(path) return QUrl.fromLocalFile(path)
else: else:

View File

@ -47,15 +47,12 @@ class ReadConfigParser(configparser.ConfigParser):
self.optionxform = lambda opt: opt # be case-insensitive self.optionxform = lambda opt: opt # be case-insensitive
self._configdir = configdir self._configdir = configdir
self._fname = fname self._fname = fname
if self._configdir is None:
self._configfile = None
return
self._configfile = os.path.join(self._configdir, fname) self._configfile = os.path.join(self._configdir, fname)
if not os.path.isfile(self._configfile): if not os.path.isfile(self._configfile):
return return
log.init.debug("Reading config from {}".format(self._configfile)) log.init.debug("Reading config from {}".format(self._configfile))
if self._configfile is not None: self.read(self._configfile, encoding='utf-8')
self.read(self._configfile, encoding='utf-8')
def __repr__(self): def __repr__(self):
return utils.get_repr(self, constructor=True, return utils.get_repr(self, constructor=True,

View File

@ -89,11 +89,9 @@ class KeyConfigParser(QObject):
self._cur_command = None self._cur_command = None
# Mapping of section name(s) to key binding -> command dicts. # Mapping of section name(s) to key binding -> command dicts.
self.keybindings = collections.OrderedDict() self.keybindings = collections.OrderedDict()
if configdir is None: self._configfile = os.path.join(configdir, fname)
self._configfile = None
else: if not os.path.exists(self._configfile):
self._configfile = os.path.join(configdir, fname)
if self._configfile is None or not os.path.exists(self._configfile):
self._load_default() self._load_default()
else: else:
self._read(relaxed) self._read(relaxed)
@ -143,8 +141,6 @@ class KeyConfigParser(QObject):
def save(self): def save(self):
"""Save the key config file.""" """Save the key config file."""
if self._configfile is None:
return
log.destroy.debug("Saving key config to {}".format(self._configfile)) log.destroy.debug("Saving key config to {}".format(self._configfile))
with qtutils.savefile_open(self._configfile, encoding='utf-8') as f: with qtutils.savefile_open(self._configfile, encoding='utf-8') as f:
data = str(self) data = str(self)

View File

@ -72,10 +72,7 @@ class CrashHandler(QObject):
def handle_segfault(self): def handle_segfault(self):
"""Handle a segfault from a previous run.""" """Handle a segfault from a previous run."""
data_dir = standarddir.data() logname = os.path.join(standarddir.data(), 'crash.log')
if data_dir is None:
return
logname = os.path.join(data_dir, 'crash.log')
try: try:
# First check if an old logfile exists. # First check if an old logfile exists.
if os.path.exists(logname): if os.path.exists(logname):
@ -131,10 +128,7 @@ class CrashHandler(QObject):
def _init_crashlogfile(self): def _init_crashlogfile(self):
"""Start a new logfile and redirect faulthandler to it.""" """Start a new logfile and redirect faulthandler to it."""
assert not self._args.no_err_windows assert not self._args.no_err_windows
data_dir = standarddir.data() logname = os.path.join(standarddir.data(), 'crash.log')
if data_dir is None:
return
logname = os.path.join(data_dir, 'crash.log')
try: try:
self._crash_log_file = open(logname, 'w', encoding='ascii') self._crash_log_file = open(logname, 'w', encoding='ascii')
except OSError: except OSError:

View File

@ -57,10 +57,7 @@ class BaseLineParser(QObject):
""" """
super().__init__(parent) super().__init__(parent)
self._configdir = configdir self._configdir = configdir
if self._configdir is None: self._configfile = os.path.join(self._configdir, fname)
self._configfile = None
else:
self._configfile = os.path.join(self._configdir, fname)
self._fname = fname self._fname = fname
self._binary = binary self._binary = binary
self._opened = False self._opened = False
@ -76,8 +73,6 @@ class BaseLineParser(QObject):
Return: Return:
True if the file should be saved, False otherwise. True if the file should be saved, False otherwise.
""" """
if self._configdir is None:
return False
if not os.path.exists(self._configdir): if not os.path.exists(self._configdir):
os.makedirs(self._configdir, 0o755) os.makedirs(self._configdir, 0o755)
return True return True
@ -222,7 +217,7 @@ class LineParser(BaseLineParser):
binary: Whether to open the file in binary mode. binary: Whether to open the file in binary mode.
""" """
super().__init__(configdir, fname, binary=binary, parent=parent) super().__init__(configdir, fname, binary=binary, parent=parent)
if configdir is None or not os.path.isfile(self._configfile): if not os.path.isfile(self._configfile):
self.data = [] self.data = []
else: else:
log.init.debug("Reading {}".format(self._configfile)) log.init.debug("Reading {}".format(self._configfile))

View File

@ -47,15 +47,11 @@ def init(parent=None):
Args: Args:
parent: The parent to use for the SessionManager. parent: The parent to use for the SessionManager.
""" """
data_dir = standarddir.data() base_path = os.path.join(standarddir.data(), 'sessions')
if data_dir is None: try:
base_path = None os.mkdir(base_path)
else: except FileExistsError:
base_path = os.path.join(standarddir.data(), 'sessions') pass
try:
os.mkdir(base_path)
except FileExistsError:
pass
session_manager = SessionManager(base_path, parent) session_manager = SessionManager(base_path, parent)
objreg.register('session-manager', session_manager) objreg.register('session-manager', session_manager)
@ -137,11 +133,6 @@ class SessionManager(QObject):
if os.path.isabs(path) and ((not check_exists) or if os.path.isabs(path) and ((not check_exists) or
os.path.exists(path)): os.path.exists(path)):
return path return path
elif self._base_path is None:
if check_exists:
raise SessionNotFoundError(name)
else:
return None
else: else:
path = os.path.join(self._base_path, name + '.yml') path = os.path.join(self._base_path, name + '.yml')
if check_exists and not os.path.exists(path): if check_exists and not os.path.exists(path):
@ -279,8 +270,6 @@ class SessionManager(QObject):
""" """
name = self._get_session_name(name) name = self._get_session_name(name)
path = self._get_session_path(name) path = self._get_session_path(name)
if path is None:
raise SessionError("No data storage configured.")
log.sessions.debug("Saving session {} to {}...".format(name, path)) log.sessions.debug("Saving session {} to {}...".format(name, path))
if last_window: if last_window:
@ -392,8 +381,6 @@ class SessionManager(QObject):
def list_sessions(self): def list_sessions(self):
"""Get a list of all session names.""" """Get a list of all session names."""
sessions = [] sessions = []
if self._base_path is None:
return sessions
for filename in os.listdir(self._base_path): for filename in os.listdir(self._base_path):
base, ext = os.path.splitext(filename) base, ext = os.path.splitext(filename)
if ext == '.yml': if ext == '.yml':

View File

@ -47,12 +47,11 @@ def get_argparser():
"""Get the argparse parser.""" """Get the argparse parser."""
parser = argparse.ArgumentParser(prog='qutebrowser', parser = argparse.ArgumentParser(prog='qutebrowser',
description=qutebrowser.__description__) description=qutebrowser.__description__)
parser.add_argument('-c', '--confdir', help="Set config directory (empty " parser.add_argument('-c', '--confdir', help="Set config directory",
"for no config storage).") type=directory)
parser.add_argument('--datadir', help="Set data directory (empty for " parser.add_argument('--datadir', help="Set data directory", type=directory)
"no data storage).") parser.add_argument('--cachedir', help="Set cache directory",
parser.add_argument('--cachedir', help="Set cache directory (empty for " type=directory)
"no cache storage).")
parser.add_argument('--basedir', help="Base directory for all storage. " parser.add_argument('--basedir', help="Base directory for all storage. "
"Other --*dir arguments are ignored if this is given.") "Other --*dir arguments are ignored if this is given.")
parser.add_argument('-V', '--version', help="Show version and quit.", parser.add_argument('-V', '--version', help="Show version and quit.",
@ -124,6 +123,11 @@ def get_argparser():
return parser return parser
def directory(arg):
if not arg:
raise argparse.ArgumentTypeError("Invalid empty value")
def logfilter_error(logfilter: str): def logfilter_error(logfilter: str):
"""Validate logger names passed to --logfilter. """Validate logger names passed to --logfilter.

View File

@ -43,7 +43,7 @@ def config():
# WORKAROUND - see # WORKAROUND - see
# https://bugreports.qt.io/browse/QTBUG-38872 # https://bugreports.qt.io/browse/QTBUG-38872
path = os.path.join(path, appname) path = os.path.join(path, appname)
_maybe_create(path) _create(path)
return path return path
@ -61,7 +61,7 @@ def data():
QStandardPaths.ConfigLocation) QStandardPaths.ConfigLocation)
if data_path == config_path: if data_path == config_path:
path = os.path.join(path, 'data') path = os.path.join(path, 'data')
_maybe_create(path) _create(path)
return path return path
@ -82,7 +82,7 @@ def cache():
overridden, path = _from_args(typ, _args) overridden, path = _from_args(typ, _args)
if not overridden: if not overridden:
path = _writable_location(typ) path = _writable_location(typ)
_maybe_create(path) _create(path)
return path return path
@ -92,7 +92,7 @@ def download():
overridden, path = _from_args(typ, _args) overridden, path = _from_args(typ, _args)
if not overridden: if not overridden:
path = _writable_location(typ) path = _writable_location(typ)
_maybe_create(path) _create(path)
return path return path
@ -116,7 +116,7 @@ def runtime():
# maximum length of 104 chars), so we don't add the username here... # maximum length of 104 chars), so we don't add the username here...
appname = QCoreApplication.instance().applicationName() appname = QCoreApplication.instance().applicationName()
path = os.path.join(path, appname) path = os.path.join(path, appname)
_maybe_create(path) _create(path)
return path return path
@ -175,16 +175,16 @@ def _from_args(typ, args):
except KeyError: except KeyError:
return (False, None) return (False, None)
arg_value = getattr(args, argname) arg_value = getattr(args, argname)
assert arg_value != '', argname
if arg_value is None: if arg_value is None:
return (False, None) return (False, None)
elif arg_value == '':
return (True, None)
else: else:
return (True, arg_value) return (True, arg_value)
def _maybe_create(path): def _create(path):
"""Create the `path` directory if path is not None. """Create the `path` directory.
From the XDG basedir spec: From the XDG basedir spec:
If, when attempting to write a file, the destination directory is If, when attempting to write a file, the destination directory is
@ -192,11 +192,10 @@ def _maybe_create(path):
0700. If the destination directory exists already the permissions 0700. If the destination directory exists already the permissions
should not be changed. should not be changed.
""" """
if path is not None: try:
try: os.makedirs(path, 0o700)
os.makedirs(path, 0o700) except FileExistsError:
except FileExistsError: pass
pass
def init(args): def init(args):
@ -214,10 +213,7 @@ def _init_cachedir_tag():
See http://www.brynosaurus.com/cachedir/spec.html See http://www.brynosaurus.com/cachedir/spec.html
""" """
cache_dir = cache() cachedir_tag = os.path.join(cache(), 'CACHEDIR.TAG')
if cache_dir is None:
return
cachedir_tag = os.path.join(cache_dir, 'CACHEDIR.TAG')
if not os.path.exists(cachedir_tag): if not os.path.exists(cachedir_tag):
try: try:
with open(cachedir_tag, 'w', encoding='utf-8') as f: with open(cachedir_tag, 'w', encoding='utf-8') as f:

View File

@ -68,24 +68,6 @@ def temp_basedir_env(tmpdir, short_tmpdir):
return env return env
@pytest.mark.linux
def test_no_config(request, temp_basedir_env, quteproc_new):
"""Test starting with -c ""."""
args = ['-c', ''] + _base_args(request.config)
quteproc_new.start(args, env=temp_basedir_env)
quteproc_new.send_cmd(':quit')
quteproc_new.wait_for_quit()
@pytest.mark.linux
def test_no_cache(request, temp_basedir_env, quteproc_new):
"""Test starting with --cachedir=""."""
args = ['--cachedir='] + _base_args(request.config)
quteproc_new.start(args, env=temp_basedir_env)
quteproc_new.send_cmd(':quit')
quteproc_new.wait_for_quit()
@pytest.mark.linux @pytest.mark.linux
def test_ascii_locale(request, httpbin, tmpdir, quteproc_new): def test_ascii_locale(request, httpbin, tmpdir, quteproc_new):
"""Test downloads with LC_ALL=C set. """Test downloads with LC_ALL=C set.

View File

@ -29,7 +29,6 @@ from PyQt5.QtCore import pyqtSignal, QUrl, QObject
from qutebrowser.browser import adblock from qutebrowser.browser import adblock
from qutebrowser.utils import objreg from qutebrowser.utils import objreg
from qutebrowser.commands import cmdexc
pytestmark = pytest.mark.usefixtures('qapp', 'config_tmpdir') pytestmark = pytest.mark.usefixtures('qapp', 'config_tmpdir')
@ -225,32 +224,6 @@ def generic_blocklists(directory):
return [blocklist1, blocklist2, blocklist3, blocklist4, blocklist5] return [blocklist1, blocklist2, blocklist3, blocklist4, blocklist5]
def test_without_datadir(config_stub, tmpdir, monkeypatch, win_registry):
"""No directory for data configured so no hosts file exists.
Ensure CommandError is raised and no URL is blocked.
"""
config_stub.data = {
'content': {
'host-block-lists': generic_blocklists(tmpdir),
'host-blocking-enabled': True,
}
}
monkeypatch.setattr('qutebrowser.utils.standarddir.data', lambda: None)
host_blocker = adblock.HostBlocker()
with pytest.raises(cmdexc.CommandError) as excinfo:
host_blocker.adblock_update()
assert str(excinfo.value) == "No data storage is configured!"
host_blocker.read_hosts()
for str_url in URLS_TO_CHECK:
assert not host_blocker.is_blocked(QUrl(str_url))
# To test on_config_changed
config_stub.set('content', 'host-block-lists', None)
def test_disabled_blocking_update(basedir, config_stub, download_stub, def test_disabled_blocking_update(basedir, config_stub, download_stub,
data_tmpdir, tmpdir, win_registry, caplog): data_tmpdir, tmpdir, win_registry, caplog):
"""Ensure no URL is blocked when host blocking is disabled.""" """Ensure no URL is blocked when host blocking is disabled."""

View File

@ -111,16 +111,6 @@ def test_cache_size_deactivated(config_stub, tmpdir):
assert disk_cache.cacheSize() == 0 assert disk_cache.cacheSize() == 0
def test_cache_no_cache_dir(config_stub):
"""Confirm that the cache is deactivated when cache_dir is None."""
config_stub.data = {
'storage': {'cache-size': 1024},
'general': {'private-browsing': False},
}
disk_cache = cache.DiskCache(None)
assert disk_cache.cacheSize() == 0
def test_cache_existing_metadata_file(config_stub, tmpdir): def test_cache_existing_metadata_file(config_stub, tmpdir):
"""Test querying existing meta data file from activated cache.""" """Test querying existing meta data file from activated cache."""
config_stub.data = { config_stub.data = {

View File

@ -65,13 +65,6 @@ def test_async_read_twice(monkeypatch, qtbot, tmpdir, caplog):
assert caplog.records[0].msg == expected assert caplog.records[0].msg == expected
def test_async_read_no_datadir(qtbot, config_stub, fake_save_manager):
config_stub.data = {'general': {'private-browsing': False}}
hist = history.WebHistory(hist_dir=None, hist_name='history')
with qtbot.waitSignal(hist.async_read_done):
list(hist.async_read())
@pytest.mark.parametrize('redirect', [True, False]) @pytest.mark.parametrize('redirect', [True, False])
def test_adding_item_during_async_read(qtbot, hist, redirect): def test_adding_item_during_async_read(qtbot, hist, redirect):
"""Check what happens when adding URL while reading the history.""" """Check what happens when adding URL while reading the history."""

View File

@ -23,9 +23,7 @@ import os.path
import configparser import configparser
import collections import collections
import shutil import shutil
from unittest import mock
from PyQt5.QtCore import QObject
from PyQt5.QtGui import QColor from PyQt5.QtGui import QColor
import pytest import pytest
@ -33,7 +31,6 @@ import qutebrowser
from qutebrowser.config import config, configexc, configdata from qutebrowser.config import config, configexc, configdata
from qutebrowser.config.parsers import keyconf from qutebrowser.config.parsers import keyconf
from qutebrowser.commands import runners from qutebrowser.commands import runners
from qutebrowser.utils import objreg, standarddir
class TestConfigParser: class TestConfigParser:
@ -43,12 +40,12 @@ class TestConfigParser:
Objects = collections.namedtuple('Objects', ['cp', 'cfg']) Objects = collections.namedtuple('Objects', ['cp', 'cfg'])
@pytest.fixture @pytest.fixture
def objects(self): def objects(self, tmpdir):
cp = configparser.ConfigParser(interpolation=None, cp = configparser.ConfigParser(interpolation=None,
comment_prefixes='#') comment_prefixes='#')
cp.optionxform = lambda opt: opt # be case-insensitive cp.optionxform = lambda opt: opt # be case-insensitive
cfg = config.ConfigManager() cfg = config.ConfigManager()
cfg.read(None, None) cfg.read(str(tmpdir), 'qutebrowser.conf')
return self.Objects(cp=cp, cfg=cfg) return self.Objects(cp=cp, cfg=cfg)
@pytest.mark.parametrize('config, section, option, value', [ @pytest.mark.parametrize('config, section, option, value', [
@ -247,7 +244,7 @@ class TestKeyConfigParser:
"""Test config.parsers.keyconf.KeyConfigParser.""" """Test config.parsers.keyconf.KeyConfigParser."""
def test_cmd_binding(self, cmdline_test, config_stub): def test_cmd_binding(self, cmdline_test, config_stub, tmpdir):
"""Test various command bindings. """Test various command bindings.
See https://github.com/The-Compiler/qutebrowser/issues/615 See https://github.com/The-Compiler/qutebrowser/issues/615
@ -256,7 +253,7 @@ class TestKeyConfigParser:
cmdline_test: A pytest fixture which provides testcases. cmdline_test: A pytest fixture which provides testcases.
""" """
config_stub.data = {'aliases': []} config_stub.data = {'aliases': []}
kcp = keyconf.KeyConfigParser(None, None) kcp = keyconf.KeyConfigParser(str(tmpdir), 'keys.conf')
kcp._cur_section = 'normal' kcp._cur_section = 'normal'
if cmdline_test.valid: if cmdline_test.valid:
kcp._read_command(cmdline_test.cmd) kcp._read_command(cmdline_test.cmd)
@ -379,17 +376,17 @@ class TestDefaultConfig:
"""Test validating of the default config.""" """Test validating of the default config."""
@pytest.mark.usefixtures('qapp') @pytest.mark.usefixtures('qapp')
def test_default_config(self): def test_default_config(self, tmpdir):
"""Test validating of the default config.""" """Test validating of the default config."""
conf = config.ConfigManager() conf = config.ConfigManager()
conf.read(None, None) conf.read(str(tmpdir), 'qutebrowser.conf')
conf._validate_all() conf._validate_all()
def test_default_key_config(self): def test_default_key_config(self, tmpdir):
"""Test validating of the default key config.""" """Test validating of the default key config."""
# We import qutebrowser.app so the cmdutils.register decorators run. # We import qutebrowser.app so the cmdutils.register decorators run.
import qutebrowser.app # pylint: disable=unused-variable import qutebrowser.app # pylint: disable=unused-variable
conf = keyconf.KeyConfigParser(None, None) conf = keyconf.KeyConfigParser(str(tmpdir), 'keys.conf')
runner = runners.CommandRunner(win_id=0) runner = runners.CommandRunner(win_id=0)
for sectname in configdata.KEY_DATA: for sectname in configdata.KEY_DATA:
for cmd in conf.get_bindings_for(sectname).values(): for cmd in conf.get_bindings_for(sectname).values():
@ -418,48 +415,3 @@ class TestDefaultConfig:
shutil.copy(full_path, str(tmpdir / 'qutebrowser.conf')) shutil.copy(full_path, str(tmpdir / 'qutebrowser.conf'))
conf = config.ConfigManager() conf = config.ConfigManager()
conf.read(str(tmpdir), 'qutebrowser.conf') conf.read(str(tmpdir), 'qutebrowser.conf')
@pytest.mark.integration
class TestConfigInit:
"""Test initializing of the config."""
@pytest.fixture(autouse=True)
def patch(self, fake_args):
objreg.register('app', QObject())
objreg.register('save-manager', mock.MagicMock())
fake_args.relaxed_config = False
old_standarddir_args = standarddir._args
yield
objreg.delete('app')
objreg.delete('save-manager')
# registered by config.init()
objreg.delete('config')
objreg.delete('key-config')
objreg.delete('state-config')
standarddir._args = old_standarddir_args
@pytest.fixture
def env(self, tmpdir):
conf_path = (tmpdir / 'config').ensure(dir=1)
data_path = (tmpdir / 'data').ensure(dir=1)
cache_path = (tmpdir / 'cache').ensure(dir=1)
env = {
'XDG_CONFIG_HOME': str(conf_path),
'XDG_DATA_HOME': str(data_path),
'XDG_CACHE_HOME': str(cache_path),
}
return env
def test_config_none(self, monkeypatch, env, fake_args):
"""Test initializing with config path set to None."""
fake_args.confdir = ''
fake_args.datadir = ''
fake_args.cachedir = ''
fake_args.basedir = None
for k, v in env.items():
monkeypatch.setenv(k, v)
standarddir.init(fake_args)
config.init()
assert not os.listdir(env['XDG_CONFIG_HOME'])

View File

@ -1284,14 +1284,6 @@ class TestFileAndUserStyleSheet:
os_mock.path.join.assert_called_once_with( os_mock.path.join.assert_called_once_with(
'/home/foo/.config/', 'foobar') '/home/foo/.config/', 'foobar')
def test_validate_rel_config_none_file(self, os_mock, monkeypatch):
"""Test with a relative path and standarddir.config returning None."""
monkeypatch.setattr(
'qutebrowser.config.configtypes.standarddir.config', lambda: None)
os_mock.path.isabs.return_value = False
with pytest.raises(configexc.ValidationError):
configtypes.File().validate('foobar')
@pytest.mark.parametrize('configtype, value, raises', [ @pytest.mark.parametrize('configtype, value, raises', [
(configtypes.File(), 'foobar', True), (configtypes.File(), 'foobar', True),
(configtypes.UserStyleSheet(), 'foobar', False), (configtypes.UserStyleSheet(), 'foobar', False),
@ -1355,14 +1347,8 @@ class TestFileAndUserStyleSheet:
expected = self._expected(klass, '/configdir/foo') expected = self._expected(klass, '/configdir/foo')
assert klass().transform('foo') == expected assert klass().transform('foo') == expected
@pytest.mark.parametrize('no_config', [False, True]) def test_transform_userstylesheet_base64(self, monkeypatch):
def test_transform_userstylesheet_base64(self, monkeypatch, no_config):
"""Test transform with a data string.""" """Test transform with a data string."""
if no_config:
monkeypatch.setattr(
'qutebrowser.config.configtypes.standarddir.config',
lambda: None)
b64 = base64.b64encode(b"test").decode('ascii') b64 = base64.b64encode(b"test").decode('ascii')
url = QUrl("data:text/css;charset=utf-8;base64,{}".format(b64)) url = QUrl("data:text/css;charset=utf-8;base64,{}".format(b64))
assert configtypes.UserStyleSheet().transform("test") == url assert configtypes.UserStyleSheet().transform("test") == url

View File

@ -52,15 +52,6 @@ class TestBaseLineParser:
lineparser._prepare_save() lineparser._prepare_save()
os_mock.makedirs.assert_called_with(self.CONFDIR, 0o755) os_mock.makedirs.assert_called_with(self.CONFDIR, 0o755)
def test_prepare_save_no_config(self, mocker):
"""Test if _prepare_save doesn't create a None config dir."""
os_mock = mocker.patch('qutebrowser.misc.lineparser.os')
os_mock.path.exists.return_value = True
lineparser = lineparsermod.BaseLineParser(None, self.FILENAME)
assert not lineparser._prepare_save()
assert not os_mock.makedirs.called
def test_double_open(self, mocker, lineparser): def test_double_open(self, mocker, lineparser):
"""Test if _open refuses reentry.""" """Test if _open refuses reentry."""
mocker.patch('builtins.open', mock.mock_open()) mocker.patch('builtins.open', mock.mock_open())
@ -158,15 +149,6 @@ class TestAppendLineParser:
lineparser.save() lineparser.save()
assert (tmpdir / 'file').read() == self._get_expected(new_data) assert (tmpdir / 'file').read() == self._get_expected(new_data)
def test_save_without_configdir(self, tmpdir, lineparser):
"""Test save() failing because no configdir was set."""
new_data = ['new data 1', 'new data 2']
lineparser.new_data = new_data
lineparser._configdir = None
assert not lineparser.save()
# make sure new data is still there
assert lineparser.new_data == new_data
def test_clear(self, tmpdir, lineparser): def test_clear(self, tmpdir, lineparser):
"""Check if calling clear() empties both pending and persisted data.""" """Check if calling clear() empties both pending and persisted data."""
lineparser.new_data = ['one', 'two'] lineparser.new_data = ['one', 'two']
@ -179,14 +161,6 @@ class TestAppendLineParser:
assert not lineparser.new_data assert not lineparser.new_data
assert (tmpdir / 'file').read() == "" assert (tmpdir / 'file').read() == ""
def test_clear_without_configdir(self, tmpdir, lineparser):
"""Test clear() failing because no configdir was set."""
new_data = ['new data 1', 'new data 2']
lineparser.new_data = new_data
lineparser._configdir = None
assert not lineparser.clear()
assert lineparser.new_data == new_data
def test_iter_without_open(self, lineparser): def test_iter_without_open(self, lineparser):
"""Test __iter__ without having called open().""" """Test __iter__ without having called open()."""
with pytest.raises(ValueError): with pytest.raises(ValueError):

View File

@ -40,9 +40,9 @@ webengine_refactoring_xfail = pytest.mark.xfail(
@pytest.fixture @pytest.fixture
def sess_man(): def sess_man(tmpdir):
"""Fixture providing a SessionManager with no session dir.""" """Fixture providing a SessionManager."""
return sessions.SessionManager(base_path=None) return sessions.SessionManager(base_path=str(tmpdir))
class TestInit: class TestInit:
@ -52,13 +52,6 @@ class TestInit:
yield yield
objreg.delete('session-manager') objreg.delete('session-manager')
def test_no_standarddir(self, monkeypatch):
monkeypatch.setattr('qutebrowser.misc.sessions.standarddir.data',
lambda: None)
sessions.init()
manager = objreg.get('session-manager')
assert manager._base_path is None
@pytest.mark.parametrize('create_dir', [True, False]) @pytest.mark.parametrize('create_dir', [True, False])
def test_with_standarddir(self, tmpdir, monkeypatch, create_dir): def test_with_standarddir(self, tmpdir, monkeypatch, create_dir):
monkeypatch.setattr('qutebrowser.misc.sessions.standarddir.data', monkeypatch.setattr('qutebrowser.misc.sessions.standarddir.data',
@ -110,16 +103,6 @@ class TestExists:
assert not man.exists(name) assert not man.exists(name)
@pytest.mark.parametrize('absolute', [True, False])
def test_no_datadir(self, sess_man, tmpdir, absolute):
abs_session = tmpdir / 'foo.yml'
abs_session.ensure()
if absolute:
assert sess_man.exists(str(abs_session))
else:
assert not sess_man.exists('foo')
@webengine_refactoring_xfail @webengine_refactoring_xfail
class TestSaveTab: class TestSaveTab:
@ -247,11 +230,6 @@ class TestSave:
objreg.delete('main-window', scope='window', window=0) objreg.delete('main-window', scope='window', window=0)
objreg.delete('tabbed-browser', scope='window', window=0) objreg.delete('tabbed-browser', scope='window', window=0)
def test_no_config_storage(self, sess_man):
with pytest.raises(sessions.SessionError) as excinfo:
sess_man.save('foo')
assert str(excinfo.value) == "No data storage configured."
def test_update_completion_signal(self, sess_man, tmpdir, qtbot): def test_update_completion_signal(self, sess_man, tmpdir, qtbot):
session_path = tmpdir / 'foo.yml' session_path = tmpdir / 'foo.yml'
with qtbot.waitSignal(sess_man.update_completion): with qtbot.waitSignal(sess_man.update_completion):
@ -415,9 +393,6 @@ def test_delete_update_completion_signal(sess_man, qtbot, tmpdir):
class TestListSessions: class TestListSessions:
def test_no_base_path(self, sess_man):
assert not sess_man.list_sessions()
def test_no_sessions(self, tmpdir): def test_no_sessions(self, tmpdir):
sess_man = sessions.SessionManager(str(tmpdir)) sess_man = sessions.SessionManager(str(tmpdir))
assert not sess_man.list_sessions() assert not sess_man.list_sessions()

View File

@ -165,15 +165,12 @@ class TestArguments:
"""Tests with confdir/cachedir/datadir arguments.""" """Tests with confdir/cachedir/datadir arguments."""
@pytest.fixture(params=[DirArgTest('', None), DirArgTest('foo', 'foo')]) @pytest.fixture(params=[DirArgTest('foo', 'foo')])
def testcase(self, request, tmpdir): def testcase(self, request, tmpdir):
"""Fixture providing testcases.""" """Fixture providing testcases."""
if request.param.expected is None: # prepend tmpdir to both
return request.param arg = str(tmpdir / request.param.arg)
else: return DirArgTest(arg, arg)
# prepend tmpdir to both
arg = str(tmpdir / request.param.arg)
return DirArgTest(arg, arg)
def test_confdir(self, testcase): def test_confdir(self, testcase):
"""Test --confdir.""" """Test --confdir."""
@ -210,8 +207,8 @@ class TestArguments:
monkeypatch.setattr( monkeypatch.setattr(
'qutebrowser.utils.standarddir.QStandardPaths.writableLocation', 'qutebrowser.utils.standarddir.QStandardPaths.writableLocation',
lambda _typ: str(tmpdir)) lambda _typ: str(tmpdir))
args = types.SimpleNamespace(confdir=None, cachedir=None, datadir=None, args = types.SimpleNamespace(confdir=None, cachedir=None,
basedir=None) datadir=None, basedir=None)
standarddir.init(args) standarddir.init(args)
assert standarddir.runtime() == str(tmpdir / 'qute_test') assert standarddir.runtime() == str(tmpdir / 'qute_test')
@ -239,13 +236,6 @@ class TestInitCacheDirTag:
"""Tests for _init_cachedir_tag.""" """Tests for _init_cachedir_tag."""
def test_no_cache_dir(self, mocker, monkeypatch):
"""Smoke test with cache() returning None."""
monkeypatch.setattr('qutebrowser.utils.standarddir.cache',
lambda: None)
mocker.patch('builtins.open', side_effect=AssertionError)
standarddir._init_cachedir_tag()
def test_existent_cache_dir_tag(self, tmpdir, mocker, monkeypatch): def test_existent_cache_dir_tag(self, tmpdir, mocker, monkeypatch):
"""Test with an existent CACHEDIR.TAG.""" """Test with an existent CACHEDIR.TAG."""
monkeypatch.setattr('qutebrowser.utils.standarddir.cache', monkeypatch.setattr('qutebrowser.utils.standarddir.cache',