Improve version output

This commit is contained in:
Florian Bruhin 2016-07-06 23:47:59 +02:00
parent a58c3ff0c6
commit ebf9bc4e0a
4 changed files with 124 additions and 72 deletions

View File

@ -64,12 +64,7 @@ qApp = None
def run(args): def run(args):
"""Initialize everything and run the application.""" """Initialize everything and run the application."""
if args.version: if args.version:
print(version.version(short=True)) print(version.version())
print()
print()
print(qutebrowser.__copyright__)
print()
print(version.GPL_BOILERPLATE.strip())
sys.exit(usertypes.Exit.ok) sys.exit(usertypes.Exit.ok)
if args.temp_basedir: if args.temp_basedir:

View File

@ -110,11 +110,19 @@ def _release_info():
Return: Return:
list of (filename, content) tuples. list of (filename, content) tuples.
""" """
blacklisted = ['ANSI_COLOR=', 'HOME_URL=', 'SUPPORT_URL=',
'BUG_REPORT_URL=']
data = [] data = []
for fn in glob.glob("/etc/*-release"): for fn in glob.glob("/etc/*-release"):
lines = []
try: try:
with open(fn, 'r', encoding='utf-8') as f: with open(fn, 'r', encoding='utf-8') as f:
data.append((fn, f.read())) for line in f.read().strip().splitlines():
if not any(line.startswith(bl) for bl in blacklisted):
lines.append(line)
if lines:
data.append((fn, '\n'.join(lines)))
except OSError: except OSError:
log.misc.exception("Error while reading {}.".format(fn)) log.misc.exception("Error while reading {}.".format(fn))
return data return data
@ -136,6 +144,7 @@ def _module_versions():
('yaml', ['__version__']), ('yaml', ['__version__']),
('cssutils', ['__version__']), ('cssutils', ['__version__']),
('typing', []), ('typing', []),
('PyQt5.QtWebEngineWidgets', []),
]) ])
for name, attributes in modules.items(): for name, attributes in modules.items():
try: try:
@ -210,42 +219,50 @@ def _pdfjs_version():
return '{} ({})'.format(pdfjs_version, file_path) return '{} ({})'.format(pdfjs_version, file_path)
def version(short=False): def version():
"""Return a string with various version informations. """Return a string with various version informations."""
Args:
short: Return a shortened output.
"""
lines = ["qutebrowser v{}".format(qutebrowser.__version__)] lines = ["qutebrowser v{}".format(qutebrowser.__version__)]
gitver = _git_str() gitver = _git_str()
if gitver is not None: if gitver is not None:
lines.append("Git commit: {}".format(gitver)) lines.append("Git commit: {}".format(gitver))
if qVersion() != QT_VERSION_STR:
qt_version = 'Qt: {} (compiled {})'.format(qVersion(), QT_VERSION_STR)
else:
qt_version = 'Qt: {}'.format(qVersion())
lines += [ lines += [
'', '',
'{}: {}'.format(platform.python_implementation(), '{}: {}'.format(platform.python_implementation(),
platform.python_version()), platform.python_version()),
'Qt: {}, runtime: {}'.format(QT_VERSION_STR, qVersion()), qt_version,
'PyQt: {}'.format(PYQT_VERSION_STR), 'PyQt: {}'.format(PYQT_VERSION_STR),
'',
] ]
if not short: lines += _module_versions()
style = QApplication.instance().style()
lines += [
'Style: {}'.format(style.metaObject().className()),
'Desktop: {}'.format(os.environ.get('DESKTOP_SESSION')),
]
lines += _module_versions() lines += [
'pdf.js: {}'.format(_pdfjs_version()),
'Webkit: {}'.format(qWebKitVersion()),
'Harfbuzz: {}'.format(os.environ.get('QT_HARFBUZZ', 'system')),
'SSL: {}'.format(QSslSocket.sslLibraryVersionString()),
'',
]
lines += [ qapp = QApplication.instance()
'pdf.js: {}'.format(_pdfjs_version()), if qapp:
'Webkit: {}'.format(qWebKitVersion()), style = qapp.style()
'Harfbuzz: {}'.format(os.environ.get('QT_HARFBUZZ', 'system')), lines.append('Style: {}'.format(style.metaObject().className()))
'SSL: {}'.format(QSslSocket.sslLibraryVersionString()),
'', importpath = os.path.dirname(os.path.abspath(qutebrowser.__file__))
'Frozen: {}'.format(hasattr(sys, 'frozen')),
'Platform: {}, {}'.format(platform.platform(), lines += [
platform.architecture()[0]), 'Platform: {}, {}'.format(platform.platform(),
] platform.architecture()[0]),
lines += _os_info() 'Desktop: {}'.format(os.environ.get('DESKTOP_SESSION')),
'Frozen: {}'.format(hasattr(sys, 'frozen')),
"Imported from {}".format(importpath),
]
lines += _os_info()
return '\n'.join(lines) return '\n'.join(lines)

View File

@ -124,8 +124,15 @@ class FakeQApplication:
"""Stub to insert as QApplication module.""" """Stub to insert as QApplication module."""
def __init__(self, style=None, all_widgets=None, active_window=None): UNSET = object()
self.instance = mock.Mock(return_value=self)
def __init__(self, style=None, all_widgets=None, active_window=None,
instance=UNSET):
if instance is self.UNSET:
self.instance = mock.Mock(return_value=self)
else:
self.instance = mock.Mock(return_value=instance)
self.style = mock.Mock(spec=QCommonStyle) self.style = mock.Mock(spec=QCommonStyle)
self.style().metaObject().className.return_value = style self.style().metaObject().className.return_value = style

View File

@ -276,13 +276,24 @@ class ReleaseInfoFake:
@pytest.mark.parametrize('files, expected', [ @pytest.mark.parametrize('files, expected', [
# no files -> no output
({}, []), ({}, []),
({'file': ['']}, [('file', '')]), # empty files are stripped
({'file': []}, [('file', '')]), ({'file': ['']}, []),
({'file': []}, []),
# newlines at EOL are stripped
( (
{'file1': ['foo\n', 'bar\n'], 'file2': ['baz\n']}, {'file1': ['foo\n', 'bar\n'], 'file2': ['baz\n']},
[('file1', 'foo\nbar\n'), ('file2', 'baz\n')] [('file1', 'foo\nbar'), ('file2', 'baz')]
), ),
# blacklisted lines
(
{'file': ['HOME_URL=example.com\n', 'NAME=FOO']},
[('file', 'NAME=FOO')]
),
# only blacklisted lines
({'file': ['HOME_URL=example.com']}, []),
# broken file
(None, []), (None, []),
]) ])
def test_release_info(files, expected, caplog, monkeypatch): def test_release_info(files, expected, caplog, monkeypatch):
@ -326,6 +337,7 @@ class ImportFake:
'yaml': True, 'yaml': True,
'cssutils': True, 'cssutils': True,
'typing': True, 'typing': True,
'PyQt5.QtWebEngineWidgets': True,
} }
self.version_attribute = '__version__' self.version_attribute = '__version__'
self.version = '1.2.3' self.version = '1.2.3'
@ -385,7 +397,8 @@ class TestModuleVersions:
"""Test with all modules present in version 1.2.3.""" """Test with all modules present in version 1.2.3."""
expected = ['sip: yes', 'colorama: 1.2.3', 'pypeg2: 1.2.3', expected = ['sip: yes', 'colorama: 1.2.3', 'pypeg2: 1.2.3',
'jinja2: 1.2.3', 'pygments: 1.2.3', 'yaml: 1.2.3', 'jinja2: 1.2.3', 'pygments: 1.2.3', 'yaml: 1.2.3',
'cssutils: 1.2.3', 'typing: yes'] 'cssutils: 1.2.3', 'typing: yes',
'PyQt5.QtWebEngineWidgets: yes']
assert version._module_versions() == expected assert version._module_versions() == expected
@pytest.mark.parametrize('module, idx, expected', [ @pytest.mark.parametrize('module, idx, expected', [
@ -407,12 +420,15 @@ class TestModuleVersions:
@pytest.mark.parametrize('value, expected', [ @pytest.mark.parametrize('value, expected', [
('VERSION', ['sip: yes', 'colorama: 1.2.3', 'pypeg2: yes', ('VERSION', ['sip: yes', 'colorama: 1.2.3', 'pypeg2: yes',
'jinja2: yes', 'pygments: yes', 'yaml: yes', 'jinja2: yes', 'pygments: yes', 'yaml: yes',
'cssutils: yes', 'typing: yes']), 'cssutils: yes', 'typing: yes',
'PyQt5.QtWebEngineWidgets: yes']),
('SIP_VERSION_STR', ['sip: 1.2.3', 'colorama: yes', 'pypeg2: yes', ('SIP_VERSION_STR', ['sip: 1.2.3', 'colorama: yes', 'pypeg2: yes',
'jinja2: yes', 'pygments: yes', 'yaml: yes', 'jinja2: yes', 'pygments: yes', 'yaml: yes',
'cssutils: yes', 'typing: yes']), 'cssutils: yes', 'typing: yes',
'PyQt5.QtWebEngineWidgets: yes']),
(None, ['sip: yes', 'colorama: yes', 'pypeg2: yes', 'jinja2: yes', (None, ['sip: yes', 'colorama: yes', 'pypeg2: yes', 'jinja2: yes',
'pygments: yes', 'yaml: yes', 'cssutils: yes', 'typing: yes']), 'pygments: yes', 'yaml: yes', 'cssutils: yes', 'typing: yes',
'PyQt5.QtWebEngineWidgets: yes']),
]) ])
def test_version_attribute(self, value, expected, import_fake): def test_version_attribute(self, value, expected, import_fake):
"""Test with a different version attribute. """Test with a different version attribute.
@ -598,24 +614,23 @@ class FakeQSslSocket:
return self._version return self._version
@pytest.mark.parametrize('git_commit, harfbuzz, frozen, short', [ @pytest.mark.parametrize('git_commit, harfbuzz, frozen, style, equal_qt', [
(True, True, False, False), # normal (True, True, False, True, True), # normal
(False, True, False, False), # no git commit (False, True, False, True, True), # no git commit
(True, False, False, False), # HARFBUZZ unset (True, False, False, True, True), # HARFBUZZ unset
(True, True, True, False), # frozen (True, True, True, True, True), # frozen
(True, True, False, True), # short (True, True, True, False, True), # no style
(False, True, False, True), # short and no git commit (True, True, False, True, False), # different Qt
]) ])
def test_version_output(git_commit, harfbuzz, frozen, short, stubs, def test_version_output(git_commit, harfbuzz, frozen, style, equal_qt,
monkeypatch): stubs, monkeypatch):
"""Test version.version().""" """Test version.version()."""
patches = { patches = {
'qutebrowser.__file__': '/IMPORTPATH/__init__.py',
'qutebrowser.__version__': 'VERSION', 'qutebrowser.__version__': 'VERSION',
'_git_str': lambda: ('GIT COMMIT' if git_commit else None), '_git_str': lambda: ('GIT COMMIT' if git_commit else None),
'platform.python_implementation': lambda: 'PYTHON IMPLEMENTATION', 'platform.python_implementation': lambda: 'PYTHON IMPLEMENTATION',
'platform.python_version': lambda: 'PYTHON VERSION', 'platform.python_version': lambda: 'PYTHON VERSION',
'QT_VERSION_STR': 'QT VERSION',
'qVersion': lambda: 'QT RUNTIME VERSION',
'PYQT_VERSION_STR': 'PYQT VERSION', 'PYQT_VERSION_STR': 'PYQT VERSION',
'_module_versions': lambda: ['MODULE VERSION 1', 'MODULE VERSION 2'], '_module_versions': lambda: ['MODULE VERSION 1', 'MODULE VERSION 2'],
'_pdfjs_version': lambda: 'PDFJS VERSION', '_pdfjs_version': lambda: 'PDFJS VERSION',
@ -624,9 +639,20 @@ def test_version_output(git_commit, harfbuzz, frozen, short, stubs,
'platform.platform': lambda: 'PLATFORM', 'platform.platform': lambda: 'PLATFORM',
'platform.architecture': lambda: ('ARCHITECTURE', ''), 'platform.architecture': lambda: ('ARCHITECTURE', ''),
'_os_info': lambda: ['OS INFO 1', 'OS INFO 2'], '_os_info': lambda: ['OS INFO 1', 'OS INFO 2'],
'QApplication': stubs.FakeQApplication(style='STYLE'),
} }
if equal_qt:
patches['QT_VERSION_STR'] = 'QT VERSION'
patches['qVersion'] = lambda: 'QT VERSION'
else:
patches['QT_VERSION_STR'] = 'QT VERSION'
patches['qVersion'] = lambda: 'QT RUNTIME VERSION'
if style:
patches['QApplication'] = stubs.FakeQApplication(style='STYLE')
else:
patches['QApplication'] = stubs.FakeQApplication(instance=None)
for attr, val in patches.items(): for attr, val in patches.items():
monkeypatch.setattr('qutebrowser.utils.version.' + attr, val) monkeypatch.setattr('qutebrowser.utils.version.' + attr, val)
@ -646,8 +672,22 @@ def test_version_output(git_commit, harfbuzz, frozen, short, stubs,
qutebrowser vVERSION qutebrowser vVERSION
{git_commit} {git_commit}
PYTHON IMPLEMENTATION: PYTHON VERSION PYTHON IMPLEMENTATION: PYTHON VERSION
Qt: QT VERSION, runtime: QT RUNTIME VERSION Qt: {qt}
PyQt: PYQT VERSION PyQt: PYQT VERSION
MODULE VERSION 1
MODULE VERSION 2
pdf.js: PDFJS VERSION
Webkit: WEBKIT VERSION
Harfbuzz: {harfbuzz}
SSL: SSL VERSION
{style}
Platform: PLATFORM, ARCHITECTURE
Desktop: DESKTOP
Frozen: {frozen}
Imported from /IMPORTPATH
OS INFO 1
OS INFO 2
""".lstrip('\n')) """.lstrip('\n'))
if git_commit: if git_commit:
@ -655,25 +695,18 @@ def test_version_output(git_commit, harfbuzz, frozen, short, stubs,
else: else:
substitutions = {'git_commit': ''} substitutions = {'git_commit': ''}
if not short: if style:
template += textwrap.dedent(""" substitutions['style'] = '\nStyle: STYLE'
Style: STYLE else:
Desktop: DESKTOP substitutions['style'] = ''
MODULE VERSION 1
MODULE VERSION 2
pdf.js: PDFJS VERSION
Webkit: WEBKIT VERSION
Harfbuzz: {harfbuzz}
SSL: SSL VERSION
Frozen: {frozen} if equal_qt:
Platform: PLATFORM, ARCHITECTURE substitutions['qt'] = 'QT VERSION'
OS INFO 1 else:
OS INFO 2 substitutions['qt'] = 'QT RUNTIME VERSION (compiled QT VERSION)'
""".lstrip('\n'))
substitutions['harfbuzz'] = 'HARFBUZZ' if harfbuzz else 'system' substitutions['harfbuzz'] = 'HARFBUZZ' if harfbuzz else 'system'
substitutions['frozen'] = str(frozen) substitutions['frozen'] = str(frozen)
expected = template.rstrip('\n').format(**substitutions) expected = template.rstrip('\n').format(**substitutions)
assert version.version(short=short) == expected assert version.version() == expected