import os from io import StringIO from pyflakes import api from pyflakes.checker import Checker from pyflakes.reporter import Reporter def _pyflakes_report_with_nopyflakes(self, messageClass, node, *args, **kwargs): with open(self.filename) as code: if code.readlines()[node.lineno - 1].strip().endswith('# nopyflakes'): return self.messages.append(messageClass(self.filename, node, *args, **kwargs)) def _pyflakes_no_migrations(self, tree, filename='(none)', builtins=None, file_tokens=()): if os.path.basename(os.path.dirname(filename)) == 'migrations': self.messages = [] else: Checker.___init___(self, tree, filename, builtins, file_tokens) def _check_recursive(paths, reporter): """ The builtin recursive checker tries to check .pyc files. """ num_warnings = 0 for path in api.iterSourceCode(paths): if path.endswith('.py'): num_warnings += api.checkPath(path, reporter) return num_warnings def pyflakes(packages): """ Unfortunately, pyflakes does not have a way to suppress certain errors or a way to configure the checker class, so we have to monkey patch it. Returns number of warnings """ Checker.___init___ = Checker.__init__ Checker.__init__ = _pyflakes_no_migrations Checker.report = _pyflakes_report_with_nopyflakes out = StringIO() reporter = Reporter(out, out) paths = [os.path.dirname(package.__file__) for package in packages] return _check_recursive(paths, reporter), out.getvalue()