Better exception formatting and handling.

This commit is contained in:
Florian Bruhin 2014-09-16 08:20:19 +02:00
parent 2e419d413b
commit 5eef6d422d
13 changed files with 69 additions and 83 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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():

View File

@ -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

View File

@ -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,

View File

@ -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):

View File

@ -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', []),

View File

@ -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)))

View File

@ -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.")

View File

@ -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)

View File

@ -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