| 1 | #!/usr/bin/env python2
|
| 2 | from __future__ import print_function
|
| 3 | """Our wrapper around pyflakes 2.4.0.
|
| 4 |
|
| 5 | Newer versions dropped support for Python 2.
|
| 6 |
|
| 7 | All versions: https://pypi.org/simple/pyflakes/
|
| 8 |
|
| 9 | Change log: https://github.com/PyCQA/pyflakes/blob/main/NEWS.rst
|
| 10 | """
|
| 11 |
|
| 12 | import argparse
|
| 13 | import sys
|
| 14 |
|
| 15 | from pyflakes import api
|
| 16 | from pyflakes import reporter
|
| 17 |
|
| 18 | from display import ansi
|
| 19 |
|
| 20 | # Our config for flake8
|
| 21 | # local fatal_errors='E901,E999,F821,F822,F823,F401'
|
| 22 |
|
| 23 | # From flake8/src/flake8/plugins/pyflakes.py
|
| 24 | # "RaiseNotImplemented": "F901",
|
| 25 | # "UndefinedName": "F821",
|
| 26 | # "UndefinedLocal": "F823",
|
| 27 | # "UnusedImport": "F401",
|
| 28 |
|
| 29 | FATAL_CLASS_NAMES = [
|
| 30 | "RaiseNotImplemented",
|
| 31 | "UndefinedName",
|
| 32 | "UndefinedLocal",
|
| 33 | "UnusedImport",
|
| 34 | ]
|
| 35 |
|
| 36 | # Other useful ones
|
| 37 | # "RedefinedWhileUnused": "F811",
|
| 38 |
|
| 39 |
|
| 40 | class OilsReporter(reporter.Reporter):
|
| 41 |
|
| 42 | def __init__(self):
|
| 43 | # Warnings and errors both go to stdout
|
| 44 | reporter.Reporter.__init__(self, sys.stdout, sys.stdout)
|
| 45 | self.num_fatal_errors = 0
|
| 46 |
|
| 47 | def flake(self, message):
|
| 48 | """Pyflakes found something wrong with the code.
|
| 49 |
|
| 50 | @param: A L{pyflakes.messages.Message}.
|
| 51 | """
|
| 52 | type_name = type(message).__name__
|
| 53 |
|
| 54 | # Suppress some errors for now to reducenoise
|
| 55 | if type_name == 'UnusedVariable':
|
| 56 | if message.filename.endswith('_test.py'):
|
| 57 | return
|
| 58 |
|
| 59 | var_name = message.message_args[0]
|
| 60 | if var_name == 'e':
|
| 61 | return
|
| 62 | if var_name.startswith('unused'):
|
| 63 | return
|
| 64 |
|
| 65 | if type_name in FATAL_CLASS_NAMES:
|
| 66 | self.num_fatal_errors += 1
|
| 67 | color = self._stdout.isatty()
|
| 68 | else:
|
| 69 | color = False
|
| 70 |
|
| 71 | if color:
|
| 72 | self._stdout.write(ansi.RED + ansi.BOLD)
|
| 73 | self._stdout.write(str(message))
|
| 74 | self._stdout.write(ansi.RESET)
|
| 75 | else:
|
| 76 | self._stdout.write(str(message))
|
| 77 |
|
| 78 | self._stdout.write('\n')
|
| 79 |
|
| 80 |
|
| 81 | def main(args):
|
| 82 | parser = argparse.ArgumentParser(
|
| 83 | prog=None, description='Check Python source files for errors')
|
| 84 | #parser.add_argument('-V', '--version', action='version', version=_get_version())
|
| 85 | parser.add_argument(
|
| 86 | 'path',
|
| 87 | nargs='*',
|
| 88 | help='Path(s) of Python file(s) to check. STDIN if not given.')
|
| 89 | paths = parser.parse_args(args).path
|
| 90 |
|
| 91 | rep = OilsReporter()
|
| 92 |
|
| 93 | api.checkRecursive(paths, rep)
|
| 94 | return 0 if rep.num_fatal_errors == 0 else 1
|
| 95 |
|
| 96 |
|
| 97 | if __name__ == '__main__':
|
| 98 | try:
|
| 99 | sys.exit(main(sys.argv[1:]))
|
| 100 | except KeyboardInterrupt as e:
|
| 101 | print('%s: interrupted with Ctrl-C' % sys.argv[0], file=sys.stderr)
|
| 102 | sys.exit(1)
|
| 103 | except RuntimeError as e:
|
| 104 | print('FATAL: %s' % e, file=sys.stderr)
|
| 105 | sys.exit(1)
|