diff --git a/qutebrowser/misc/crashdialog.py b/qutebrowser/misc/crashdialog.py index cfc125bb9..515435666 100644 --- a/qutebrowser/misc/crashdialog.py +++ b/qutebrowser/misc/crashdialog.py @@ -20,9 +20,11 @@ """The dialog which gets shown when qutebrowser crashes.""" import re +import os import sys import html import getpass +import fnmatch import traceback import pkg_resources @@ -91,6 +93,17 @@ def get_fatal_crash_dialog(debug, data): return QMessageBox(QMessageBox.Critical, title, text, QMessageBox.Ok) +def _get_environment_vars(): + """Gather enveronment variables for the crash info.""" + masks = ('DESKTOP_SESSION', 'DE', 'QT_*', 'PYTHON*', 'LC_*', 'LANG') + info = [] + for key, value in os.environ.items(): + for m in masks: + if fnmatch.fnmatch(key, m): + info.append('%s = %s' % (key, value)) + return '\n'.join(sorted(info)) + + class _CrashDialog(QDialog): """Dialog which gets shown after there was a crash. @@ -234,6 +247,11 @@ class _CrashDialog(QDialog): self._crash_info.append(("Config", conf.dump_userconfig())) except Exception: self._crash_info.append(("Config", traceback.format_exc())) + try: + self._crash_info.append( + ("Environment", _get_environment_vars())) + except Exception: + self._crash_info.append(("Environment", traceback.format_exc())) def _set_crash_info(self): """Set/update the crash info.""" @@ -624,3 +642,8 @@ def dump_exception_info(exc, pages, cmdhist, objects): print('\n'.join(cmdhist), file=sys.stderr) print("\n---- Objects ----", file=sys.stderr) print(objects, file=sys.stderr) + print("\n---- Environment ----", file=sys.stderr) + try: + print(_get_environment_vars(), file=sys.stderr) + except Exception: + traceback.print_exc() diff --git a/tests/unit/misc/test_crashdialog.py b/tests/unit/misc/test_crashdialog.py index ae0078c99..f79f2f1b5 100644 --- a/tests/unit/misc/test_crashdialog.py +++ b/tests/unit/misc/test_crashdialog.py @@ -19,6 +19,8 @@ """Tests for qutebrowser.misc.crashdialog.""" +import os +import pytest from qutebrowser.misc import crashdialog @@ -77,3 +79,26 @@ class TestParseFatalStacktrace: text = INVALID_CRASH_TEXT.strip().replace('_', ' ') typ, func = crashdialog.parse_fatal_stacktrace(text) assert (typ, func) == ('', '') + + +@pytest.mark.parametrize('env, expected', [ + ({'FOO': 'bar'}, ""), + ({'FOO': 'bar', 'LC_ALL': 'baz'}, "LC_ALL = baz"), + ({'LC_ALL': 'baz', 'PYTHONFOO': 'fish'}, "LC_ALL = baz\nPYTHONFOO = fish"), + ( + {'DE': 'KDE', 'DESKTOP_SESSION': 'plasma'}, + "DE = KDE\nDESKTOP_SESSION = plasma" + ), + ( + {'QT5_IM_MODULE': 'fcitx', 'QT_IM_MODULE': 'fcitx'}, + "QT_IM_MODULE = fcitx" + ), + ({'LANGUAGE': 'foo', 'LANG': 'en_US.UTF-8'}, "LANG = en_US.UTF-8"), +]) +def test_get_environment_vars(monkeypatch, env, expected): + """Test for crashdialog._get_environment_vars.""" + for key in os.environ.copy(): + monkeypatch.delenv(key) + for k, v in env.items(): + monkeypatch.setenv(k, v) + assert crashdialog._get_environment_vars() == expected