summaryrefslogtreecommitdiff
path: root/.config/qutebrowser/scripts/dev/run_vulture.py
diff options
context:
space:
mode:
authorVito Graffagnino <vito@graffagnino.xyz>2020-09-08 18:10:49 +0100
committerVito Graffagnino <vito@graffagnino.xyz>2020-09-08 18:10:49 +0100
commit3b0142cedcde39e4c2097ecd916a870a3ced5ec6 (patch)
tree2116c49a845dfc0945778f2aa3e2118d72be428b /.config/qutebrowser/scripts/dev/run_vulture.py
parent8cc927e930d5b6aafe3e9862a61e81705479a1b4 (diff)
Added the relevent parts of the .config directory. Alss add ssh config
Diffstat (limited to '.config/qutebrowser/scripts/dev/run_vulture.py')
-rwxr-xr-x.config/qutebrowser/scripts/dev/run_vulture.py196
1 files changed, 196 insertions, 0 deletions
diff --git a/.config/qutebrowser/scripts/dev/run_vulture.py b/.config/qutebrowser/scripts/dev/run_vulture.py
new file mode 100755
index 0000000..cb19d62
--- /dev/null
+++ b/.config/qutebrowser/scripts/dev/run_vulture.py
@@ -0,0 +1,196 @@
+#!/usr/bin/env python
+# vim: ft=python fileencoding=utf-8 sts=4 sw=4 et:
+
+# Copyright 2015-2018 Florian Bruhin (The Compiler) <mail@qutebrowser.org>
+
+# This file is part of qutebrowser.
+#
+# qutebrowser is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# qutebrowser is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with qutebrowser. If not, see <http://www.gnu.org/licenses/>.
+
+"""Run vulture on the source files and filter out false-positives."""
+
+import sys
+import os
+import re
+import tempfile
+import inspect
+import argparse
+
+import vulture
+
+import qutebrowser.app # pylint: disable=unused-import
+from qutebrowser.commands import cmdutils
+from qutebrowser.utils import utils
+from qutebrowser.browser.webkit import rfc6266
+# To run the decorators from there
+# pylint: disable=unused-import
+from qutebrowser.browser.webkit.network import webkitqutescheme
+# pylint: enable=unused-import
+from qutebrowser.browser import qutescheme
+from qutebrowser.config import configtypes
+
+
+def whitelist_generator(): # noqa
+ """Generator which yields lines to add to a vulture whitelist."""
+ # qutebrowser commands
+ for cmd in cmdutils.cmd_dict.values():
+ yield utils.qualname(cmd.handler)
+
+ # pyPEG2 classes
+ for name, member in inspect.getmembers(rfc6266, inspect.isclass):
+ for attr in ['grammar', 'regex']:
+ if hasattr(member, attr):
+ yield 'qutebrowser.browser.webkit.rfc6266.{}.{}'.format(name,
+ attr)
+
+ # PyQt properties
+ yield 'qutebrowser.mainwindow.statusbar.bar.StatusBar.color_flags'
+ yield 'qutebrowser.mainwindow.statusbar.url.UrlText.urltype'
+
+ # Not used yet, but soon (or when debugging)
+ yield 'qutebrowser.utils.debug.log_events'
+ yield 'qutebrowser.utils.debug.log_signals'
+ yield 'qutebrowser.utils.debug.qflags_key'
+ yield 'qutebrowser.utils.qtutils.QtOSError.qt_errno'
+ yield 'scripts.utils.bg_colors'
+
+ # Qt attributes
+ yield 'PyQt5.QtWebKit.QWebPage.ErrorPageExtensionReturn().baseUrl'
+ yield 'PyQt5.QtWebKit.QWebPage.ErrorPageExtensionReturn().content'
+ yield 'PyQt5.QtWebKit.QWebPage.ErrorPageExtensionReturn().encoding'
+ yield 'PyQt5.QtWebKit.QWebPage.ErrorPageExtensionReturn().fileNames'
+ yield 'PyQt5.QtWidgets.QStyleOptionViewItem.backgroundColor'
+
+ ## qute://... handlers
+ for name in qutescheme._HANDLERS: # pylint: disable=protected-access
+ name = name.replace('-', '_')
+ yield 'qutebrowser.browser.qutescheme.qute_' + name
+
+ # Other false-positives
+ yield 'qutebrowser.completion.models.listcategory.ListCategory().lessThan'
+ yield 'qutebrowser.utils.jinja.Loader.get_source'
+ yield 'qutebrowser.utils.log.QtWarningFilter.filter'
+ yield 'qutebrowser.browser.pdfjs.is_available'
+ yield 'qutebrowser.misc.guiprocess.spawn_output'
+ yield 'QEvent.posted'
+ yield 'log_stack' # from message.py
+ yield 'propagate' # logging.getLogger('...).propagate = False
+ # vulture doesn't notice the hasattr() and thus thinks netrc_used is unused
+ # in NetworkManager.on_authentication_required
+ yield 'PyQt5.QtNetwork.QNetworkReply.netrc_used'
+ yield 'qutebrowser.browser.downloads.last_used_directory'
+ yield 'PaintContext.clip' # from completiondelegate.py
+ yield 'logging.LogRecord.log_color' # from logging.py
+ yield 'scripts.utils.use_color' # from asciidoc2html.py
+ for attr in ['pyeval_output', 'log_clipboard', 'fake_clipboard']:
+ yield 'qutebrowser.misc.utilcmds.' + attr
+
+ for attr in ['fileno', 'truncate', 'closed', 'readable']:
+ yield 'qutebrowser.utils.qtutils.PyQIODevice.' + attr
+
+ for attr in ['msgs', 'priority', 'visit_attribute']:
+ yield 'scripts.dev.pylint_checkers.config.' + attr
+ for attr in ['visit_call', 'process_module']:
+ yield 'scripts.dev.pylint_checkers.modeline.' + attr
+
+ for name, _member in inspect.getmembers(configtypes, inspect.isclass):
+ yield 'qutebrowser.config.configtypes.' + name
+ yield 'qutebrowser.config.configexc.ConfigErrorDesc.traceback'
+ yield 'qutebrowser.config.configfiles.ConfigAPI.load_autoconfig'
+ yield 'types.ModuleType.c' # configfiles:read_config_py
+ for name in ['configdir', 'datadir']:
+ yield 'qutebrowser.config.configfiles.ConfigAPI.' + name
+
+ yield 'include_aliases'
+
+ for attr in ['_get_default_metavar_for_optional',
+ '_get_default_metavar_for_positional', '_metavar_formatter']:
+ yield 'scripts.dev.src2asciidoc.UsageFormatter.' + attr
+
+ # attrs
+ yield 'qutebrowser.browser.webkit.network.networkmanager.ProxyId.hostname'
+ yield 'qutebrowser.command.command.ArgInfo._validate_exclusive'
+ yield 'scripts.get_coredumpctl_traces.Line.uid'
+ yield 'scripts.get_coredumpctl_traces.Line.gid'
+ yield 'scripts.importer.import_moz_places.places.row_factory'
+
+
+def filter_func(item):
+ """Check if a missing function should be filtered or not.
+
+ Return:
+ True if the missing function should be filtered/ignored, False
+ otherwise.
+ """
+ return bool(re.fullmatch(r'[a-z]+[A-Z][a-zA-Z]+', item.name))
+
+
+def report(items):
+ """Generate a report based on the given vulture.Item's.
+
+ Based on vulture.Vulture.report, but we can't use that as we can't set the
+ properties which get used for the items.
+ """
+ output = []
+ for item in sorted(items,
+ key=lambda e: (e.filename.lower(), e.first_lineno)):
+ output.append(item.get_report())
+ return output
+
+
+def run(files):
+ """Run vulture over the given files."""
+ with tempfile.NamedTemporaryFile(mode='w', delete=False) as whitelist_file:
+ for line in whitelist_generator():
+ whitelist_file.write(line + '\n')
+
+ whitelist_file.close()
+
+ vult = vulture.Vulture(verbose=False)
+ vult.scavenge(files + [whitelist_file.name])
+
+ os.remove(whitelist_file.name)
+
+ filters = {
+ 'unused_funcs': filter_func,
+ 'unused_props': lambda item: False,
+ 'unused_vars': lambda item: False,
+ 'unused_attrs': lambda item: False,
+ }
+
+ items = []
+
+ for attr, func in filters.items():
+ sub_items = getattr(vult, attr)
+ for item in sub_items:
+ filtered = func(item)
+ if not filtered:
+ items.append(item)
+
+ return report(items)
+
+
+def main():
+ parser = argparse.ArgumentParser()
+ parser.add_argument('files', nargs='*', default=['qutebrowser', 'scripts',
+ 'setup.py'])
+ args = parser.parse_args()
+ out = run(args.files)
+ for line in out:
+ print(line)
+ sys.exit(bool(out))
+
+
+if __name__ == '__main__':
+ main()