Better exception formatting and handling.
This commit is contained in:
parent
2e419d413b
commit
5eef6d422d
@ -29,6 +29,7 @@ import warnings
|
|||||||
import bdb
|
import bdb
|
||||||
import base64
|
import base64
|
||||||
import functools
|
import functools
|
||||||
|
import traceback
|
||||||
|
|
||||||
from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox
|
from PyQt5.QtWidgets import QApplication, QDialog, QMessageBox
|
||||||
from PyQt5.QtCore import (pyqtSlot, QTimer, QEventLoop, Qt, QStandardPaths,
|
from PyQt5.QtCore import (pyqtSlot, QTimer, QEventLoop, Qt, QStandardPaths,
|
||||||
@ -479,9 +480,8 @@ class Application(QApplication):
|
|||||||
QUrl.RemovePassword | QUrl.FullyEncoded)
|
QUrl.RemovePassword | QUrl.FullyEncoded)
|
||||||
if url:
|
if url:
|
||||||
pages.append(url)
|
pages.append(url)
|
||||||
except Exception as e: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
log.destroy.debug("Error while recovering tab: {}: {}".format(
|
log.destroy.exception("Error while recovering tab")
|
||||||
e.__class__.__name__, e))
|
|
||||||
return pages
|
return pages
|
||||||
|
|
||||||
def _save_geometry(self):
|
def _save_geometry(self):
|
||||||
@ -508,8 +508,8 @@ class Application(QApplication):
|
|||||||
self._crashlogfile.close()
|
self._crashlogfile.close()
|
||||||
try:
|
try:
|
||||||
os.remove(self._crashlogfile.name)
|
os.remove(self._crashlogfile.name)
|
||||||
except (PermissionError, FileNotFoundError) as e:
|
except (PermissionError, FileNotFoundError):
|
||||||
log.destroy.warning("Could not remove crash log ({})!".format(e))
|
log.destroy.exception("Could not remove crash log!")
|
||||||
|
|
||||||
def _exception_hook(self, exctype, excvalue, tb):
|
def _exception_hook(self, exctype, excvalue, tb):
|
||||||
"""Handle uncaught python exceptions.
|
"""Handle uncaught python exceptions.
|
||||||
@ -524,9 +524,8 @@ class Application(QApplication):
|
|||||||
try:
|
try:
|
||||||
self.shutdown()
|
self.shutdown()
|
||||||
return
|
return
|
||||||
except Exception as e:
|
except Exception:
|
||||||
log.init.debug("Error while shutting down: {}: {}".format(
|
log.init.exception("Error while shutting down")
|
||||||
e.__class__.__name__, e))
|
|
||||||
self.quit()
|
self.quit()
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -537,37 +536,32 @@ class Application(QApplication):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
pages = self._recover_pages()
|
pages = self._recover_pages()
|
||||||
except Exception as e:
|
except Exception:
|
||||||
log.destroy.debug("Error while recovering pages: {}: {}".format(
|
log.destroy.exception("Error while recovering pages")
|
||||||
e.__class__.__name__, e))
|
|
||||||
pages = []
|
pages = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
history = self.mainwindow.status.cmd.history[-5:]
|
history = self.mainwindow.status.cmd.history[-5:]
|
||||||
except Exception as e:
|
except Exception:
|
||||||
log.destroy.debug("Error while getting history: {}: {}".format(
|
log.destroy.exception("Error while getting history: {}")
|
||||||
e.__class__.__name__, e))
|
|
||||||
history = []
|
history = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
widgets = self.get_all_widgets()
|
widgets = self.get_all_widgets()
|
||||||
except Exception as e:
|
except Exception:
|
||||||
log.destroy.debug("Error while getting widgets: {}: {}".format(
|
log.destroy.exception("Error while getting widgets")
|
||||||
e.__class__.__name__, e))
|
|
||||||
widgets = ""
|
widgets = ""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
objects = self.get_all_objects()
|
objects = self.get_all_objects()
|
||||||
except Exception as e:
|
except Exception:
|
||||||
log.destroy.debug("Error while getting objects: {}: {}".format(
|
log.destroy.exception("Error while getting objects")
|
||||||
e.__class__.__name__, e))
|
|
||||||
objects = ""
|
objects = ""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.lastWindowClosed.disconnect(self.shutdown)
|
self.lastWindowClosed.disconnect(self.shutdown)
|
||||||
except TypeError as e:
|
except TypeError:
|
||||||
log.destroy.debug("Error while preventing shutdown: {}: {}".format(
|
log.destroy.exception("Error while preventing shutdown")
|
||||||
e.__class__.__name__, e))
|
|
||||||
QApplication.closeAllWindows()
|
QApplication.closeAllWindows()
|
||||||
self._crashdlg = crash.ExceptionCrashDialog(pages, history, exc,
|
self._crashdlg = crash.ExceptionCrashDialog(pages, history, exc,
|
||||||
widgets, objects)
|
widgets, objects)
|
||||||
@ -632,8 +626,8 @@ class Application(QApplication):
|
|||||||
try:
|
try:
|
||||||
r = eval(s) # pylint: disable=eval-used
|
r = eval(s) # pylint: disable=eval-used
|
||||||
out = repr(r)
|
out = repr(r)
|
||||||
except Exception as e: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
out = ': '.join([e.__class__.__name__, str(e)])
|
out = traceback.format_exc()
|
||||||
qutescheme.pyeval_output = out
|
qutescheme.pyeval_output = out
|
||||||
self.mainwindow.tabs.openurl(QUrl('qute:pyeval'), newtab=True)
|
self.mainwindow.tabs.openurl(QUrl('qute:pyeval'), newtab=True)
|
||||||
|
|
||||||
|
@ -178,9 +178,9 @@ class ConfigManager(QObject):
|
|||||||
lines.append("# {}{}:".format(optname, typestr))
|
lines.append("# {}{}:".format(optname, typestr))
|
||||||
try:
|
try:
|
||||||
desc = self.sections[sectname].descriptions[optname]
|
desc = self.sections[sectname].descriptions[optname]
|
||||||
except KeyError as e:
|
except KeyError:
|
||||||
log.misc.debug("No description for {}.{}! ({}: {})".format(
|
log.misc.exception("No description for {}.{}!".format(
|
||||||
sectname, optname, e.__class__.__name__, e))
|
sectname, optname))
|
||||||
continue
|
continue
|
||||||
for descline in desc.splitlines():
|
for descline in desc.splitlines():
|
||||||
lines += wrapper.wrap(descline)
|
lines += wrapper.wrap(descline)
|
||||||
|
@ -90,8 +90,8 @@ class ColorDict(dict):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
val = super().__getitem__(key)
|
val = super().__getitem__(key)
|
||||||
except KeyError as e:
|
except KeyError:
|
||||||
log.style.warning("No color defined for {}!".format(e))
|
log.style.exception("No color defined for {}!")
|
||||||
return ''
|
return ''
|
||||||
if isinstance(val, QColor):
|
if isinstance(val, QColor):
|
||||||
# This could happen when accidentaly declarding something as
|
# This could happen when accidentaly declarding something as
|
||||||
|
@ -65,6 +65,7 @@ def maybe_leave(mode, reason=None):
|
|||||||
try:
|
try:
|
||||||
instance().leave(mode, reason)
|
instance().leave(mode, reason)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
|
# This is rather likely to happen, so we only log to debug log.
|
||||||
log.modes.debug(e)
|
log.modes.debug(e)
|
||||||
|
|
||||||
|
|
||||||
|
@ -893,7 +893,7 @@ class OurTests(AttachmentTestCase):
|
|||||||
|
|
||||||
def setUpModule():
|
def setUpModule():
|
||||||
"""Disable logging."""
|
"""Disable logging."""
|
||||||
logging.disable(logging.WARNING)
|
logging.disable(logging.ERROR)
|
||||||
|
|
||||||
|
|
||||||
def tearDownModule():
|
def tearDownModule():
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
|
|
||||||
import os.path
|
import os.path
|
||||||
|
|
||||||
from qutebrowser.utils import rfc6266
|
from qutebrowser.utils import rfc6266
|
||||||
from qutebrowser.utils import log
|
from qutebrowser.utils import log
|
||||||
|
|
||||||
@ -47,10 +48,8 @@ def parse_content_disposition(reply):
|
|||||||
content_disposition = rfc6266.parse_headers(
|
content_disposition = rfc6266.parse_headers(
|
||||||
bytes(reply.rawHeader('Content-Disposition')))
|
bytes(reply.rawHeader('Content-Disposition')))
|
||||||
filename = content_disposition.filename()
|
filename = content_disposition.filename()
|
||||||
except UnicodeDecodeError as e:
|
except UnicodeDecodeError:
|
||||||
log.misc.warning("Error while getting filename: {}: {}".format(
|
log.misc.exception("Error while decoding filename")
|
||||||
e.__class__.__name__, e))
|
|
||||||
filename = None
|
|
||||||
else:
|
else:
|
||||||
is_inline = content_disposition.is_inline()
|
is_inline = content_disposition.is_inline()
|
||||||
# Then try to get filename from url
|
# Then try to get filename from url
|
||||||
|
@ -309,9 +309,8 @@ def parse_headers(content_disposition):
|
|||||||
content_disposition = normalize_ws(content_disposition)
|
content_disposition = normalize_ws(content_disposition)
|
||||||
try:
|
try:
|
||||||
parsed = peg.parse(content_disposition, ContentDispositionValue)
|
parsed = peg.parse(content_disposition, ContentDispositionValue)
|
||||||
except (SyntaxError, DuplicateParamError, InvalidISO8859Error) as e:
|
except (SyntaxError, DuplicateParamError, InvalidISO8859Error):
|
||||||
log.rfc6266.warning("Error while parsing Content-Disposition: "
|
log.rfc6266.exception("Error while parsing Content-Disposition")
|
||||||
"{} - {}".format(e.__class__.__name__, e))
|
|
||||||
return ContentDisposition()
|
return ContentDisposition()
|
||||||
else:
|
else:
|
||||||
return ContentDisposition(disposition=parsed.dtype,
|
return ContentDisposition(disposition=parsed.dtype,
|
||||||
|
@ -342,12 +342,11 @@ class Question(QObject):
|
|||||||
try:
|
try:
|
||||||
self.aborted.emit()
|
self.aborted.emit()
|
||||||
self.completed.emit()
|
self.completed.emit()
|
||||||
except TypeError as e:
|
except TypeError:
|
||||||
# FIXME
|
# FIXME
|
||||||
# We seem to get "pyqtSignal must be bound to a QObject, not
|
# We seem to get "pyqtSignal must be bound to a QObject, not
|
||||||
# 'Question' here, which makes no sense at all..."
|
# 'Question' here, which makes no sense at all..."
|
||||||
log.misc.debug("Error while aborting question: {}: {}".format(
|
log.misc.exception("Error while aborting question")
|
||||||
e.__class__.__name__, e))
|
|
||||||
|
|
||||||
|
|
||||||
class Timer(QTimer):
|
class Timer(QTimer):
|
||||||
|
@ -64,9 +64,8 @@ def _git_str():
|
|||||||
try:
|
try:
|
||||||
gitpath = os.path.join(os.path.dirname(os.path.realpath(__file__)),
|
gitpath = os.path.join(os.path.dirname(os.path.realpath(__file__)),
|
||||||
os.path.pardir, os.path.pardir)
|
os.path.pardir, os.path.pardir)
|
||||||
except NameError as e:
|
except NameError:
|
||||||
log.misc.debug("Error while getting git path: {}: {}".format(
|
log.misc.exception("Error while getting git path")
|
||||||
e.__class__.__name__, e))
|
|
||||||
else:
|
else:
|
||||||
commit = _git_str_subprocess(gitpath)
|
commit = _git_str_subprocess(gitpath)
|
||||||
if commit is not None:
|
if commit is not None:
|
||||||
@ -112,9 +111,8 @@ def _release_info():
|
|||||||
try:
|
try:
|
||||||
with open(fn, 'r', encoding='utf-8') as f:
|
with open(fn, 'r', encoding='utf-8') as f:
|
||||||
data.append((fn, ''.join(f.readlines())))
|
data.append((fn, ''.join(f.readlines())))
|
||||||
except IOError as e:
|
except IOError:
|
||||||
log.misc.warning("Error while reading {}: {}: {}".format(
|
log.misc.exception("Error while reading {}.".format(fn))
|
||||||
fn, e.__class__.__name__, e))
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
@ -133,9 +131,8 @@ def _module_versions():
|
|||||||
try:
|
try:
|
||||||
lines.append('SIP: {}'.format(
|
lines.append('SIP: {}'.format(
|
||||||
sipconfig.Configuration().sip_version_str))
|
sipconfig.Configuration().sip_version_str))
|
||||||
except (AttributeError, TypeError) as e:
|
except (AttributeError, TypeError):
|
||||||
log.misc.warning("Error while getting SIP version: {}: {}".format(
|
log.misc.exception("Error while getting SIP version")
|
||||||
e.__class__.__name__, e))
|
|
||||||
lines.append('SIP: ?')
|
lines.append('SIP: ?')
|
||||||
modules = collections.OrderedDict([
|
modules = collections.OrderedDict([
|
||||||
('colorlog', []),
|
('colorlog', []),
|
||||||
|
@ -17,11 +17,12 @@
|
|||||||
# You should have received a copy of the GNU General Public License
|
# You should have received a copy of the GNU General Public License
|
||||||
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
# pylint: disable=broad-except
|
||||||
|
|
||||||
"""The dialog which gets shown when qutebrowser crashes."""
|
"""The dialog which gets shown when qutebrowser crashes."""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import traceback
|
import traceback
|
||||||
import urllib.error
|
|
||||||
import getpass
|
import getpass
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QSize
|
from PyQt5.QtCore import Qt, QSize
|
||||||
@ -123,19 +124,17 @@ class _CrashDialog(QDialog):
|
|||||||
try:
|
try:
|
||||||
self._crash_info.append(("Contact info",
|
self._crash_info.append(("Contact info",
|
||||||
"User: {}".format(getpass.getuser())))
|
"User: {}".format(getpass.getuser())))
|
||||||
except Exception as e: # pylint: disable=broad-except
|
except Exception:
|
||||||
self._crash_info.append(("Contact info", "User: {}: {}".format(
|
self._crash_info.append(("Contact info", traceback.format_exc()))
|
||||||
e.__class__.__name__, e)))
|
|
||||||
try:
|
try:
|
||||||
self._crash_info.append(("Version info", version.version()))
|
self._crash_info.append(("Version info", version.version()))
|
||||||
except Exception as e: # pylint: disable=broad-except
|
except Exception:
|
||||||
self._crash_info.append(("Version info", traceback.format_exc()))
|
self._crash_info.append(("Version info", traceback.format_exc()))
|
||||||
try:
|
try:
|
||||||
self._crash_info.append(("Config",
|
self._crash_info.append(("Config",
|
||||||
config.instance().dump_userconfig()))
|
config.instance().dump_userconfig()))
|
||||||
except AttributeError as e:
|
except Exception:
|
||||||
self._crash_info.append(("Config", "{}: {}".format(
|
self._crash_info.append(("Config", traceback.format_exc()))
|
||||||
e.__class__.__name__, e)))
|
|
||||||
|
|
||||||
def _format_crash_info(self):
|
def _format_crash_info(self):
|
||||||
"""Format the gathered crash info to be displayed.
|
"""Format the gathered crash info to be displayed.
|
||||||
@ -157,7 +156,8 @@ class _CrashDialog(QDialog):
|
|||||||
"""Paste the crash info into the pastebin."""
|
"""Paste the crash info into the pastebin."""
|
||||||
try:
|
try:
|
||||||
url = utils.pastebin(self._txt.toPlainText())
|
url = utils.pastebin(self._txt.toPlainText())
|
||||||
except (urllib.error.URLError, ValueError) as e:
|
except Exception as e:
|
||||||
|
log.misc.exception("Error while paste-binning")
|
||||||
self._url.setText('Error while reporting: {}: {}'.format(
|
self._url.setText('Error while reporting: {}: {}'.format(
|
||||||
e.__class__.__name__, e))
|
e.__class__.__name__, e))
|
||||||
return
|
return
|
||||||
@ -230,9 +230,8 @@ class ExceptionCrashDialog(_CrashDialog):
|
|||||||
]
|
]
|
||||||
try:
|
try:
|
||||||
self._crash_info.append(("Debug log", log.ram_handler.dump_log()))
|
self._crash_info.append(("Debug log", log.ram_handler.dump_log()))
|
||||||
except AttributeError as e:
|
except Exception:
|
||||||
self._crash_info.append(("Debug log", "{}: {}".format(
|
self._crash_info.append(("Debug log", traceback.format_exc()))
|
||||||
e.__class__.__name__, e)))
|
|
||||||
|
|
||||||
|
|
||||||
class FatalCrashDialog(_CrashDialog):
|
class FatalCrashDialog(_CrashDialog):
|
||||||
@ -330,6 +329,5 @@ class ReportDialog(_CrashDialog):
|
|||||||
]
|
]
|
||||||
try:
|
try:
|
||||||
self._crash_info.append(("Debug log", log.ram_handler.dump_log()))
|
self._crash_info.append(("Debug log", log.ram_handler.dump_log()))
|
||||||
except AttributeError as e:
|
except Exception:
|
||||||
self._crash_info.append(("Debug log", "{}: {}".format(
|
self._crash_info.append(("Debug log", traceback.format_exc()))
|
||||||
e.__class__.__name__, e)))
|
|
||||||
|
@ -55,16 +55,17 @@ class MainWindow(QWidget):
|
|||||||
data = stateconf['geometry']['mainwindow']
|
data = stateconf['geometry']['mainwindow']
|
||||||
log.init.debug("Restoring mainwindow from {}".format(data))
|
log.init.debug("Restoring mainwindow from {}".format(data))
|
||||||
geom = base64.b64decode(data, validate=True)
|
geom = base64.b64decode(data, validate=True)
|
||||||
except (KeyError, binascii.Error) as e:
|
except KeyError:
|
||||||
log.init.warning("Error while reading geometry: {}: {}".format(
|
# First start
|
||||||
e.__class__.__name__, e))
|
pass
|
||||||
|
except binascii.Error:
|
||||||
|
log.init.exception("Error while reading geometry")
|
||||||
self._set_default_geometry()
|
self._set_default_geometry()
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
ok = self.restoreGeometry(geom)
|
ok = self.restoreGeometry(geom)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
log.init.warning("Error while restoring geometry: {}: "
|
log.init.exception("Error while restoring geometry.")
|
||||||
"{}".format(e.__class__.__name__, e))
|
|
||||||
self._set_default_geometry()
|
self._set_default_geometry()
|
||||||
if not ok:
|
if not ok:
|
||||||
log.init.warning("Error while restoring geometry.")
|
log.init.warning("Error while restoring geometry.")
|
||||||
|
@ -224,9 +224,8 @@ class TabbedBrowser(tabwidget.TabWidget):
|
|||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
self.currentChanged.disconnect()
|
self.currentChanged.disconnect()
|
||||||
except TypeError as e:
|
except TypeError:
|
||||||
log.destroy.debug("Error while shutting down tabs: {}: {}".format(
|
log.destroy.exception("Error while shutting down tabs")
|
||||||
e.__class__.__name__, e))
|
|
||||||
for tab in self.widgets():
|
for tab in self.widgets():
|
||||||
self._remove_tab(tab)
|
self._remove_tab(tab)
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ import argparse
|
|||||||
import collections
|
import collections
|
||||||
import functools
|
import functools
|
||||||
import contextlib
|
import contextlib
|
||||||
|
import traceback
|
||||||
|
|
||||||
import colorama as col
|
import colorama as col
|
||||||
import pep257
|
import pep257
|
||||||
@ -86,8 +87,8 @@ def _run_distutils(name, args):
|
|||||||
ep()
|
ep()
|
||||||
except SystemExit as e:
|
except SystemExit as e:
|
||||||
return e.code
|
return e.code
|
||||||
except Exception as e:
|
except Exception:
|
||||||
print('{}: {}'.format(e.__class__.__name__, e))
|
traceback.print_exc()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@ -95,8 +96,8 @@ def _run_subprocess(name, args):
|
|||||||
"""Run a checker via subprocess."""
|
"""Run a checker via subprocess."""
|
||||||
try:
|
try:
|
||||||
return subprocess.call([name] + args)
|
return subprocess.call([name] + args)
|
||||||
except FileNotFoundError as e:
|
except FileNotFoundError:
|
||||||
print('{}: {}'.format(e.__class__.__name__, e))
|
traceback.print_exc()
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@ -130,9 +131,8 @@ def check_pep257(target):
|
|||||||
status = pep257.main(*pep257.parse_options())
|
status = pep257.main(*pep257.parse_options())
|
||||||
print()
|
print()
|
||||||
return status
|
return status
|
||||||
except Exception as e:
|
except Exception:
|
||||||
print('{}: {}'.format(e.__class__.__name__, e))
|
traceback.print_exc()
|
||||||
print()
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
@ -181,9 +181,8 @@ def check_vcs_conflict(target):
|
|||||||
ok = False
|
ok = False
|
||||||
print()
|
print()
|
||||||
return ok
|
return ok
|
||||||
except Exception as e:
|
except Exception:
|
||||||
print('{}: {}'.format(e.__class__.__name__, e))
|
traceback.print_exc()
|
||||||
print()
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user