parent
ea76bdfb0f
commit
ec07e4f8be
@ -31,7 +31,7 @@ import functools
|
|||||||
import traceback
|
import traceback
|
||||||
import faulthandler
|
import faulthandler
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QApplication, QDialog
|
from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox
|
||||||
from PyQt5.QtGui import QDesktopServices
|
from PyQt5.QtGui import QDesktopServices
|
||||||
from PyQt5.QtCore import (pyqtSlot, qInstallMessageHandler, QTimer, QUrl,
|
from PyQt5.QtCore import (pyqtSlot, qInstallMessageHandler, QTimer, QUrl,
|
||||||
QStandardPaths, QObject, Qt)
|
QStandardPaths, QObject, Qt)
|
||||||
@ -70,6 +70,7 @@ class Application(QApplication):
|
|||||||
Args:
|
Args:
|
||||||
Argument namespace from argparse.
|
Argument namespace from argparse.
|
||||||
"""
|
"""
|
||||||
|
# pylint: disable=too-many-statements
|
||||||
self._quit_status = {
|
self._quit_status = {
|
||||||
'crash': True,
|
'crash': True,
|
||||||
'tabs': False,
|
'tabs': False,
|
||||||
@ -114,7 +115,14 @@ class Application(QApplication):
|
|||||||
self.setApplicationName("qutebrowser")
|
self.setApplicationName("qutebrowser")
|
||||||
self.setApplicationVersion(qutebrowser.__version__)
|
self.setApplicationVersion(qutebrowser.__version__)
|
||||||
utils.actute_warning()
|
utils.actute_warning()
|
||||||
|
try:
|
||||||
self._init_modules()
|
self._init_modules()
|
||||||
|
except OSError as e:
|
||||||
|
msgbox = QMessageBox(
|
||||||
|
QMessageBox.Critical, "Error while initializing!",
|
||||||
|
"Error while initializing: {}".format(e))
|
||||||
|
msgbox.exec_()
|
||||||
|
sys.exit(1)
|
||||||
QTimer.singleShot(0, self._open_pages)
|
QTimer.singleShot(0, self._open_pages)
|
||||||
|
|
||||||
log.init.debug("Initializing eventfilter...")
|
log.init.debug("Initializing eventfilter...")
|
||||||
@ -184,31 +192,36 @@ class Application(QApplication):
|
|||||||
"""Handle a segfault from a previous run."""
|
"""Handle a segfault from a previous run."""
|
||||||
path = standarddir.get(QStandardPaths.DataLocation)
|
path = standarddir.get(QStandardPaths.DataLocation)
|
||||||
logname = os.path.join(path, 'crash.log')
|
logname = os.path.join(path, 'crash.log')
|
||||||
|
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):
|
||||||
with open(logname, 'r', encoding='ascii') as f:
|
with open(logname, 'r', encoding='ascii') as f:
|
||||||
data = f.read()
|
data = f.read()
|
||||||
try:
|
|
||||||
os.remove(logname)
|
os.remove(logname)
|
||||||
except PermissionError:
|
|
||||||
log.init.warning("Could not remove crash log!")
|
|
||||||
else:
|
|
||||||
self._init_crashlogfile()
|
self._init_crashlogfile()
|
||||||
if data:
|
if data:
|
||||||
# Crashlog exists and has data in it, so something crashed
|
# Crashlog exists and has data in it, so something crashed
|
||||||
# previously.
|
# previously.
|
||||||
self._crashdlg = crash.FatalCrashDialog(self._args.debug, data)
|
self._crashdlg = crash.FatalCrashDialog(self._args.debug,
|
||||||
|
data)
|
||||||
self._crashdlg.show()
|
self._crashdlg.show()
|
||||||
else:
|
else:
|
||||||
# There's no log file, so we can use this to display crashes to the
|
# There's no log file, so we can use this to display crashes to
|
||||||
# user on the next start.
|
# the user on the next start.
|
||||||
|
self._init_crashlogfile()
|
||||||
|
except OSError:
|
||||||
|
log.init.exception("Error while handling crash log file!")
|
||||||
self._init_crashlogfile()
|
self._init_crashlogfile()
|
||||||
|
|
||||||
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."""
|
||||||
path = standarddir.get(QStandardPaths.DataLocation)
|
path = standarddir.get(QStandardPaths.DataLocation)
|
||||||
logname = os.path.join(path, 'crash.log')
|
logname = os.path.join(path, 'crash.log')
|
||||||
|
try:
|
||||||
self._crashlogfile = open(logname, 'w', encoding='ascii')
|
self._crashlogfile = open(logname, 'w', encoding='ascii')
|
||||||
|
except OSError:
|
||||||
|
log.init.exception("Error while opening crash log file!")
|
||||||
|
else:
|
||||||
earlyinit.init_faulthandler(self._crashlogfile)
|
earlyinit.init_faulthandler(self._crashlogfile)
|
||||||
|
|
||||||
def _open_pages(self):
|
def _open_pages(self):
|
||||||
@ -446,10 +459,10 @@ class Application(QApplication):
|
|||||||
faulthandler.enable(sys.__stderr__)
|
faulthandler.enable(sys.__stderr__)
|
||||||
else:
|
else:
|
||||||
faulthandler.disable()
|
faulthandler.disable()
|
||||||
self._crashlogfile.close()
|
|
||||||
try:
|
try:
|
||||||
|
self._crashlogfile.close()
|
||||||
os.remove(self._crashlogfile.name)
|
os.remove(self._crashlogfile.name)
|
||||||
except (PermissionError, FileNotFoundError):
|
except OSError:
|
||||||
log.destroy.exception("Could not remove crash log!")
|
log.destroy.exception("Could not remove crash log!")
|
||||||
|
|
||||||
def _exception_hook(self, exctype, excvalue, tb):
|
def _exception_hook(self, exctype, excvalue, tb):
|
||||||
@ -756,6 +769,11 @@ class Application(QApplication):
|
|||||||
what, utils.qualname(handler)))
|
what, utils.qualname(handler)))
|
||||||
try:
|
try:
|
||||||
handler()
|
handler()
|
||||||
|
except OSError as e:
|
||||||
|
msgbox = QMessageBox(
|
||||||
|
QMessageBox.Critical, "Error while saving!",
|
||||||
|
"Error while saving {}: {}".format(what, e))
|
||||||
|
msgbox.exec_()
|
||||||
except AttributeError as e:
|
except AttributeError as e:
|
||||||
log.destroy.warning("Could not save {}.".format(what))
|
log.destroy.warning("Could not save {}.".format(what))
|
||||||
log.destroy.debug(e)
|
log.destroy.debug(e)
|
||||||
|
@ -100,9 +100,12 @@ 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 os.path.exists(self._hosts_file):
|
if os.path.exists(self._hosts_file):
|
||||||
|
try:
|
||||||
with open(self._hosts_file, 'r', encoding='utf-8') as f:
|
with open(self._hosts_file, 'r', encoding='utf-8') as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
self.blocked_hosts.add(line.strip())
|
self.blocked_hosts.add(line.strip())
|
||||||
|
except OSError:
|
||||||
|
log.misc.exception("Failed to read host blocklist!")
|
||||||
else:
|
else:
|
||||||
if config.get('content', 'host-block-lists') is not None:
|
if config.get('content', 'host-block-lists') is not None:
|
||||||
message.info('last-focused',
|
message.info('last-focused',
|
||||||
@ -120,7 +123,10 @@ class HostBlocker:
|
|||||||
return
|
return
|
||||||
for url in urls:
|
for url in urls:
|
||||||
if url.scheme() == 'file':
|
if url.scheme() == 'file':
|
||||||
|
try:
|
||||||
fileobj = open(url.path(), 'rb')
|
fileobj = open(url.path(), 'rb')
|
||||||
|
except OSError:
|
||||||
|
log.misc.exception("Failed to open block list!")
|
||||||
download = FakeDownload(fileobj)
|
download = FakeDownload(fileobj)
|
||||||
self._in_progress.append(download)
|
self._in_progress.append(download)
|
||||||
self.on_download_finished(download)
|
self.on_download_finished(download)
|
||||||
@ -145,7 +151,7 @@ class HostBlocker:
|
|||||||
line_count = 0
|
line_count = 0
|
||||||
try:
|
try:
|
||||||
f = get_fileobj(byte_io)
|
f = get_fileobj(byte_io)
|
||||||
except (FileNotFoundError, UnicodeDecodeError, zipfile.BadZipFile,
|
except (OSError, UnicodeDecodeError, zipfile.BadZipFile,
|
||||||
zipfile.LargeZipFile) as e:
|
zipfile.LargeZipFile) as e:
|
||||||
message.error('last-focused', "adblock: Error while reading {}: "
|
message.error('last-focused', "adblock: Error while reading {}: "
|
||||||
"{} - {}".format(
|
"{} - {}".format(
|
||||||
@ -213,4 +219,7 @@ class HostBlocker:
|
|||||||
finally:
|
finally:
|
||||||
download.fileobj.close()
|
download.fileobj.close()
|
||||||
if not self._in_progress:
|
if not self._in_progress:
|
||||||
|
try:
|
||||||
self.on_lists_downloaded()
|
self.on_lists_downloaded()
|
||||||
|
except OSError:
|
||||||
|
log.misc.exception("Failed to write host block list!")
|
||||||
|
@ -206,10 +206,10 @@ class CommandDispatcher:
|
|||||||
|
|
||||||
def _editor_cleanup(self, oshandle, filename):
|
def _editor_cleanup(self, oshandle, filename):
|
||||||
"""Clean up temporary file when the editor was closed."""
|
"""Clean up temporary file when the editor was closed."""
|
||||||
os.close(oshandle)
|
|
||||||
try:
|
try:
|
||||||
|
os.close(oshandle)
|
||||||
os.remove(filename)
|
os.remove(filename)
|
||||||
except PermissionError:
|
except OSError:
|
||||||
raise cmdexc.CommandError("Failed to delete tempfile...")
|
raise cmdexc.CommandError("Failed to delete tempfile...")
|
||||||
|
|
||||||
def _get_selection_override(self, left, right, opposite):
|
def _get_selection_override(self, left, right, opposite):
|
||||||
|
@ -307,8 +307,11 @@ class DownloadItem(QObject):
|
|||||||
self.reply = None
|
self.reply = None
|
||||||
if self.fileobj is not None:
|
if self.fileobj is not None:
|
||||||
self.fileobj.close()
|
self.fileobj.close()
|
||||||
|
try:
|
||||||
if self._filename is not None and os.path.exists(self._filename):
|
if self._filename is not None and os.path.exists(self._filename):
|
||||||
os.remove(self._filename)
|
os.remove(self._filename)
|
||||||
|
except OSError:
|
||||||
|
log.downloads.exception("Failed to remove partial file")
|
||||||
self.finished.emit()
|
self.finished.emit()
|
||||||
|
|
||||||
def set_filename(self, filename):
|
def set_filename(self, filename):
|
||||||
|
@ -61,13 +61,18 @@ class _BlockingFIFOReader(QObject):
|
|||||||
|
|
||||||
def read(self):
|
def read(self):
|
||||||
"""Blocking read loop which emits got_line when a new line arrived."""
|
"""Blocking read loop which emits got_line when a new line arrived."""
|
||||||
|
try:
|
||||||
# We open as R/W so we never get EOF and have to reopen the pipe.
|
# We open as R/W so we never get EOF and have to reopen the pipe.
|
||||||
# See http://www.outflux.net/blog/archives/2008/03/09/using-select-on-a-fifo/
|
# See http://www.outflux.net/blog/archives/2008/03/09/using-select-on-a-fifo/
|
||||||
# We also use os.open and os.fdopen rather than built-in open so we can
|
# We also use os.open and os.fdopen rather than built-in open so we
|
||||||
# add O_NONBLOCK.
|
# can add O_NONBLOCK.
|
||||||
fd = os.open(self._filepath, os.O_RDWR |
|
fd = os.open(self._filepath, os.O_RDWR |
|
||||||
os.O_NONBLOCK) # pylint: disable=no-member
|
os.O_NONBLOCK) # pylint: disable=no-member
|
||||||
self.fifo = os.fdopen(fd, 'r')
|
self.fifo = os.fdopen(fd, 'r')
|
||||||
|
except OSError:
|
||||||
|
log.procs.exception("Failed to read FIFO")
|
||||||
|
self.finished.emit()
|
||||||
|
return
|
||||||
while True:
|
while True:
|
||||||
log.procs.debug("thread loop")
|
log.procs.debug("thread loop")
|
||||||
ready_r, _ready_w, _ready_e = select.select([self.fifo], [], [], 1)
|
ready_r, _ready_w, _ready_e = select.select([self.fifo], [], [], 1)
|
||||||
@ -141,7 +146,7 @@ class _BaseUserscriptRunner(QObject):
|
|||||||
"""Clean up the temporary file."""
|
"""Clean up the temporary file."""
|
||||||
try:
|
try:
|
||||||
os.remove(self._filepath)
|
os.remove(self._filepath)
|
||||||
except PermissionError as e:
|
except OSError as e:
|
||||||
# NOTE: Do not replace this with "raise CommandError" as it's
|
# NOTE: Do not replace this with "raise CommandError" as it's
|
||||||
# executed async.
|
# executed async.
|
||||||
message.error(self._win_id,
|
message.error(self._win_id,
|
||||||
@ -196,13 +201,18 @@ class _POSIXUserscriptRunner(_BaseUserscriptRunner):
|
|||||||
|
|
||||||
def run(self, cmd, *args, env=None):
|
def run(self, cmd, *args, env=None):
|
||||||
rundir = standarddir.get(QStandardPaths.RuntimeLocation)
|
rundir = standarddir.get(QStandardPaths.RuntimeLocation)
|
||||||
# tempfile.mktemp is deprecated and discouraged, but we use it here to
|
try:
|
||||||
# create a FIFO since the only other alternative would be to create a
|
# tempfile.mktemp is deprecated and discouraged, but we use it here
|
||||||
# directory and place the FIFO there, which sucks. Since os.kfifo will
|
# to create a FIFO since the only other alternative would be to
|
||||||
# raise an exception anyways when the path doesn't exist, it shouldn't
|
# create a directory and place the FIFO there, which sucks. Since
|
||||||
# be a big issue.
|
# os.kfifo will raise an exception anyways when the path doesn't
|
||||||
|
# exist, it shouldn't be a big issue.
|
||||||
self._filepath = tempfile.mktemp(prefix='userscript-', dir=rundir)
|
self._filepath = tempfile.mktemp(prefix='userscript-', dir=rundir)
|
||||||
os.mkfifo(self._filepath) # pylint: disable=no-member
|
os.mkfifo(self._filepath) # pylint: disable=no-member
|
||||||
|
except OSError as e:
|
||||||
|
message.error(self._win_id, "Error while creating FIFO: {}".format(
|
||||||
|
e))
|
||||||
|
return
|
||||||
|
|
||||||
self._reader = _BlockingFIFOReader(self._filepath)
|
self._reader = _BlockingFIFOReader(self._filepath)
|
||||||
self._thread = QThread(self)
|
self._thread = QThread(self)
|
||||||
@ -262,16 +272,22 @@ class _WindowsUserscriptRunner(_BaseUserscriptRunner):
|
|||||||
|
|
||||||
def _cleanup(self):
|
def _cleanup(self):
|
||||||
"""Clean up temporary files after the userscript finished."""
|
"""Clean up temporary files after the userscript finished."""
|
||||||
|
try:
|
||||||
os.close(self._oshandle)
|
os.close(self._oshandle)
|
||||||
|
except OSError:
|
||||||
|
log.procs.exception("Failed to close file handle!")
|
||||||
super()._cleanup()
|
super()._cleanup()
|
||||||
self._oshandle = None
|
self._oshandle = None
|
||||||
|
|
||||||
def on_proc_finished(self):
|
def on_proc_finished(self):
|
||||||
"""Read back the commands when the process finished."""
|
"""Read back the commands when the process finished."""
|
||||||
log.procs.debug("proc finished")
|
log.procs.debug("proc finished")
|
||||||
|
try:
|
||||||
with open(self._filepath, 'r', encoding='utf-8') as f:
|
with open(self._filepath, 'r', encoding='utf-8') as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
self.got_cmd.emit(line.rstrip())
|
self.got_cmd.emit(line.rstrip())
|
||||||
|
except OSError:
|
||||||
|
log.procs.exception("Failed to read command file!")
|
||||||
self._cleanup()
|
self._cleanup()
|
||||||
self.finished.emit()
|
self.finished.emit()
|
||||||
|
|
||||||
@ -282,7 +298,12 @@ class _WindowsUserscriptRunner(_BaseUserscriptRunner):
|
|||||||
self.finished.emit()
|
self.finished.emit()
|
||||||
|
|
||||||
def run(self, cmd, *args, env=None):
|
def run(self, cmd, *args, env=None):
|
||||||
|
try:
|
||||||
self._oshandle, self._filepath = tempfile.mkstemp(text=True)
|
self._oshandle, self._filepath = tempfile.mkstemp(text=True)
|
||||||
|
except OSError as e:
|
||||||
|
message.error(self._win_id, "Error while creating tempfile: "
|
||||||
|
"{}".format(e))
|
||||||
|
return
|
||||||
self._run_process(cmd, *args, env=env)
|
self._run_process(cmd, *args, env=env)
|
||||||
|
|
||||||
|
|
||||||
|
@ -572,7 +572,14 @@ class ConfigManager(QObject):
|
|||||||
if self._initialized:
|
if self._initialized:
|
||||||
self._after_set(sectname, optname)
|
self._after_set(sectname, optname)
|
||||||
|
|
||||||
@cmdutils.register(instance='config')
|
@cmdutils.register(instance='config', name='save')
|
||||||
|
def save_command(self):
|
||||||
|
"""Save the config file."""
|
||||||
|
try:
|
||||||
|
self.save()
|
||||||
|
except OSError as e:
|
||||||
|
raise cmdexc.CommandError("Could not save config: {}".format(e))
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
"""Save the config file."""
|
"""Save the config file."""
|
||||||
if self._configdir is None:
|
if self._configdir is None:
|
||||||
|
@ -210,6 +210,7 @@ class KeyConfigParser(QObject):
|
|||||||
|
|
||||||
def _read(self):
|
def _read(self):
|
||||||
"""Read the config file from disk and parse it."""
|
"""Read the config file from disk and parse it."""
|
||||||
|
try:
|
||||||
with open(self._configfile, 'r', encoding='utf-8') as f:
|
with open(self._configfile, 'r', encoding='utf-8') as f:
|
||||||
for i, line in enumerate(f):
|
for i, line in enumerate(f):
|
||||||
line = line.rstrip()
|
line = line.rstrip()
|
||||||
@ -218,7 +219,8 @@ class KeyConfigParser(QObject):
|
|||||||
continue
|
continue
|
||||||
elif line.startswith('[') and line.endswith(']'):
|
elif line.startswith('[') and line.endswith(']'):
|
||||||
sectname = line[1:-1]
|
sectname = line[1:-1]
|
||||||
self._cur_section = self._normalize_sectname(sectname)
|
self._cur_section = self._normalize_sectname(
|
||||||
|
sectname)
|
||||||
elif line.startswith((' ', '\t')):
|
elif line.startswith((' ', '\t')):
|
||||||
line = line.strip()
|
line = line.strip()
|
||||||
self._read_keybinding(line)
|
self._read_keybinding(line)
|
||||||
@ -228,6 +230,8 @@ class KeyConfigParser(QObject):
|
|||||||
except KeyConfigError as e:
|
except KeyConfigError as e:
|
||||||
e.lineno = i
|
e.lineno = i
|
||||||
raise
|
raise
|
||||||
|
except OSError:
|
||||||
|
log.keyboard.exception("Failed to read keybindings!")
|
||||||
for sectname in self.keybindings:
|
for sectname in self.keybindings:
|
||||||
self.changed.emit(sectname)
|
self.changed.emit(sectname)
|
||||||
|
|
||||||
|
@ -52,10 +52,10 @@ class ExternalEditor(QObject):
|
|||||||
|
|
||||||
def _cleanup(self):
|
def _cleanup(self):
|
||||||
"""Clean up temporary files after the editor closed."""
|
"""Clean up temporary files after the editor closed."""
|
||||||
os.close(self._oshandle)
|
|
||||||
try:
|
try:
|
||||||
|
os.close(self._oshandle)
|
||||||
os.remove(self._filename)
|
os.remove(self._filename)
|
||||||
except PermissionError as e:
|
except OSError as e:
|
||||||
# NOTE: Do not replace this with "raise CommandError" as it's
|
# NOTE: Do not replace this with "raise CommandError" as it's
|
||||||
# executed async.
|
# executed async.
|
||||||
message.error(self._win_id,
|
message.error(self._win_id,
|
||||||
@ -80,8 +80,15 @@ class ExternalEditor(QObject):
|
|||||||
"{})!".format(exitcode))
|
"{})!".format(exitcode))
|
||||||
return
|
return
|
||||||
encoding = config.get('general', 'editor-encoding')
|
encoding = config.get('general', 'editor-encoding')
|
||||||
|
try:
|
||||||
with open(self._filename, 'r', encoding=encoding) as f:
|
with open(self._filename, 'r', encoding=encoding) as f:
|
||||||
text = ''.join(f.readlines())
|
text = ''.join(f.readlines())
|
||||||
|
except OSError as e:
|
||||||
|
# NOTE: Do not replace this with "raise CommandError" as it's
|
||||||
|
# executed async.
|
||||||
|
message.error(self._win_id, "Failed to read back edited file: "
|
||||||
|
"{}".format(e))
|
||||||
|
return
|
||||||
log.procs.debug("Read back: {}".format(text))
|
log.procs.debug("Read back: {}".format(text))
|
||||||
self.editing_finished.emit(text)
|
self.editing_finished.emit(text)
|
||||||
finally:
|
finally:
|
||||||
@ -114,11 +121,16 @@ class ExternalEditor(QObject):
|
|||||||
if self._text is not None:
|
if self._text is not None:
|
||||||
raise ValueError("Already editing a file!")
|
raise ValueError("Already editing a file!")
|
||||||
self._text = text
|
self._text = text
|
||||||
|
try:
|
||||||
self._oshandle, self._filename = tempfile.mkstemp(text=True)
|
self._oshandle, self._filename = tempfile.mkstemp(text=True)
|
||||||
if text:
|
if text:
|
||||||
encoding = config.get('general', 'editor-encoding')
|
encoding = config.get('general', 'editor-encoding')
|
||||||
with open(self._filename, 'w', encoding=encoding) as f:
|
with open(self._filename, 'w', encoding=encoding) as f:
|
||||||
f.write(text)
|
f.write(text)
|
||||||
|
except OSError as e:
|
||||||
|
message.error(self._win_id, "Failed to create initial file: "
|
||||||
|
"{}".format(e))
|
||||||
|
return
|
||||||
self._proc = QProcess(self)
|
self._proc = QProcess(self)
|
||||||
self._proc.finished.connect(self.on_proc_closed)
|
self._proc.finished.connect(self.on_proc_closed)
|
||||||
self._proc.error.connect(self.on_proc_error)
|
self._proc.error.connect(self.on_proc_error)
|
||||||
|
@ -41,7 +41,7 @@ class Loader(jinja2.BaseLoader):
|
|||||||
path = os.path.join(self._subdir, template)
|
path = os.path.join(self._subdir, template)
|
||||||
try:
|
try:
|
||||||
source = utils.read_file(path)
|
source = utils.read_file(path)
|
||||||
except FileNotFoundError:
|
except OSError:
|
||||||
raise jinja2.TemplateNotFound(template)
|
raise jinja2.TemplateNotFound(template)
|
||||||
# Currently we don't implement auto-reloading, so we always return True
|
# Currently we don't implement auto-reloading, so we always return True
|
||||||
# for up-to-date.
|
# for up-to-date.
|
||||||
|
@ -161,6 +161,7 @@ def deserialize(data, obj):
|
|||||||
def savefile_open(filename, binary=False, encoding='utf-8'):
|
def savefile_open(filename, binary=False, encoding='utf-8'):
|
||||||
"""Context manager to easily use a QSaveFile."""
|
"""Context manager to easily use a QSaveFile."""
|
||||||
f = QSaveFile(filename)
|
f = QSaveFile(filename)
|
||||||
|
new_f = None
|
||||||
try:
|
try:
|
||||||
ok = f.open(QIODevice.WriteOnly)
|
ok = f.open(QIODevice.WriteOnly)
|
||||||
if not ok: # pylint: disable=used-before-assignment
|
if not ok: # pylint: disable=used-before-assignment
|
||||||
@ -174,6 +175,7 @@ def savefile_open(filename, binary=False, encoding='utf-8'):
|
|||||||
f.cancelWriting()
|
f.cancelWriting()
|
||||||
raise
|
raise
|
||||||
finally:
|
finally:
|
||||||
|
if new_f is not None:
|
||||||
new_f.flush()
|
new_f.flush()
|
||||||
ok = f.commit()
|
ok = f.commit()
|
||||||
if not ok:
|
if not ok:
|
||||||
|
@ -24,6 +24,8 @@ import os.path
|
|||||||
|
|
||||||
from PyQt5.QtCore import QCoreApplication, QStandardPaths
|
from PyQt5.QtCore import QCoreApplication, QStandardPaths
|
||||||
|
|
||||||
|
from qutebrowser.utils import log
|
||||||
|
|
||||||
|
|
||||||
def _writable_location(typ):
|
def _writable_location(typ):
|
||||||
"""Wrapper around QStandardPaths.writableLocation."""
|
"""Wrapper around QStandardPaths.writableLocation."""
|
||||||
@ -124,9 +126,12 @@ def init():
|
|||||||
# http://www.brynosaurus.com/cachedir/spec.html
|
# http://www.brynosaurus.com/cachedir/spec.html
|
||||||
cachedir_tag = os.path.join(cache_dir, 'CACHEDIR.TAG')
|
cachedir_tag = os.path.join(cache_dir, 'CACHEDIR.TAG')
|
||||||
if not os.path.exists(cachedir_tag):
|
if not os.path.exists(cachedir_tag):
|
||||||
|
try:
|
||||||
with open(cachedir_tag, 'w', encoding='utf-8') as f:
|
with open(cachedir_tag, 'w', encoding='utf-8') as f:
|
||||||
f.write("Signature: 8a477f597d28d172789f06886806bc55\n")
|
f.write("Signature: 8a477f597d28d172789f06886806bc55\n")
|
||||||
f.write("# This file is a cache directory tag created by "
|
f.write("# This file is a cache directory tag created by "
|
||||||
"qutebrowser.\n")
|
"qutebrowser.\n")
|
||||||
f.write("# For information about cache directory tags, see:\n")
|
f.write("# For information about cache directory tags, see:\n")
|
||||||
f.write("# http://www.brynosaurus.com/cachedir/\n")
|
f.write("# http://www.brynosaurus.com/cachedir/\n")
|
||||||
|
except OSError:
|
||||||
|
log.misc.exception("Failed to create CACHEDIR.TAG")
|
||||||
|
@ -130,17 +130,20 @@ def actute_warning():
|
|||||||
return
|
return
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
try:
|
||||||
with open('/usr/share/X11/locale/en_US.UTF-8/Compose', 'r',
|
with open('/usr/share/X11/locale/en_US.UTF-8/Compose', 'r',
|
||||||
encoding='utf-8') as f:
|
encoding='utf-8') as f:
|
||||||
for line in f:
|
for line in f:
|
||||||
if '<dead_actute>' in line:
|
if '<dead_actute>' in line:
|
||||||
if sys.stdout is not None:
|
if sys.stdout is not None:
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
print("Note: If you got a 'dead_actute' warning above, that "
|
print("Note: If you got a 'dead_actute' warning above, "
|
||||||
"is not a bug in qutebrowser! See "
|
"that is not a bug in qutebrowser! See "
|
||||||
"https://bugs.freedesktop.org/show_bug.cgi?id=69476 for "
|
"https://bugs.freedesktop.org/show_bug.cgi?id=69476 "
|
||||||
"details.")
|
"for details.")
|
||||||
break
|
break
|
||||||
|
except OSError:
|
||||||
|
log.misc.exception("Failed to read Compose file")
|
||||||
|
|
||||||
|
|
||||||
def _get_color_percentage(a_c1, a_c2, a_c3, b_c1, b_c2, b_c3, percent):
|
def _get_color_percentage(a_c1, a_c2, a_c3, b_c1, b_c2, b_c3, percent):
|
||||||
|
@ -73,7 +73,7 @@ def _git_str():
|
|||||||
# If that fails, check the git-commit-id file.
|
# If that fails, check the git-commit-id file.
|
||||||
try:
|
try:
|
||||||
return utils.read_file('git-commit-id')
|
return utils.read_file('git-commit-id')
|
||||||
except (FileNotFoundError, ImportError):
|
except (OSError, ImportError):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user