|
@@ -1,128 +0,0 @@
|
|
|
-#!/usr/bin/env python
|
|
|
-from __future__ import absolute_import
|
|
|
-from __future__ import with_statement
|
|
|
-
|
|
|
-import os
|
|
|
-import pprint
|
|
|
-import re
|
|
|
-import sys
|
|
|
-
|
|
|
-from collections import defaultdict
|
|
|
-from itertools import starmap
|
|
|
-from unipath import Path
|
|
|
-
|
|
|
-RE_COMMENT = r'^\s*\#'
|
|
|
-RE_NOQA = r'.+?\#\s+noqa+'
|
|
|
-RE_MULTILINE_COMMENT_O = r'^\s*(?:\'\'\'|""").+?(?:\'\'\'|""")'
|
|
|
-RE_MULTILINE_COMMENT_S = r'^\s*(?:\'\'\'|""")'
|
|
|
-RE_MULTILINE_COMMENT_E = r'(?:^|.+?)(?:\'\'\'|""")'
|
|
|
-RE_WITH = r'(?:^|\s+)with\s+'
|
|
|
-RE_WITH_IMPORT = r'''from\s+ __future__\s+ import\s+ with_statement'''
|
|
|
-RE_PRINT = r'''(?:^|\s+)print\((?:"|')(?:\W+?)?[A-Z0-9:]{2,}'''
|
|
|
-RE_ABS_IMPORT = r'''from\s+ __future__\s+ import\s+ absolute_import'''
|
|
|
-
|
|
|
-acc = defaultdict(lambda: {"abs": False, "print": False})
|
|
|
-
|
|
|
-
|
|
|
-def compile(regex):
|
|
|
- return re.compile(regex, re.VERBOSE)
|
|
|
-
|
|
|
-
|
|
|
-class FlakePP(object):
|
|
|
- re_comment = compile(RE_COMMENT)
|
|
|
- re_ml_comment_o = compile(RE_MULTILINE_COMMENT_O)
|
|
|
- re_ml_comment_s = compile(RE_MULTILINE_COMMENT_S)
|
|
|
- re_ml_comment_e = compile(RE_MULTILINE_COMMENT_E)
|
|
|
- re_abs_import = compile(RE_ABS_IMPORT)
|
|
|
- re_print = compile(RE_PRINT)
|
|
|
- re_with_import = compile(RE_WITH_IMPORT)
|
|
|
- re_with = compile(RE_WITH)
|
|
|
- re_noqa = compile(RE_NOQA)
|
|
|
- map = {"abs": False, "print": False,
|
|
|
- "with": False, "with-used": False}
|
|
|
-
|
|
|
- def __init__(self, verbose=False):
|
|
|
- self.verbose = verbose
|
|
|
- self.steps = (("abs", self.re_abs_import),
|
|
|
- ("with", self.re_with_import),
|
|
|
- ("with-used", self.re_with),
|
|
|
- ("print", self.re_print))
|
|
|
-
|
|
|
- def analyze_fh(self, fh):
|
|
|
- steps = self.steps
|
|
|
- filename = fh.name
|
|
|
- acc = dict(self.map)
|
|
|
- index = 0
|
|
|
- errors = [0]
|
|
|
-
|
|
|
- def error(fmt, **kwargs):
|
|
|
- errors[0] += 1
|
|
|
- self.announce(fmt, **dict(kwargs, filename=filename))
|
|
|
-
|
|
|
- for index, line in enumerate(self.strip_comments(fh)):
|
|
|
- for key, pattern in self.steps:
|
|
|
- if pattern.match(line):
|
|
|
- acc[key] = True
|
|
|
- if index:
|
|
|
- if not acc["abs"]:
|
|
|
- error("%(filename)s: missing abs import")
|
|
|
- if acc["with-used"] and not acc["with"]:
|
|
|
- error("%(filename)s: missing with import")
|
|
|
- if acc["print"]:
|
|
|
- error("%(filename)s: left over print statement")
|
|
|
-
|
|
|
- return filename, errors[0], acc
|
|
|
-
|
|
|
- def analyze_file(self, filename):
|
|
|
- with open(filename) as fh:
|
|
|
- return self.analyze_fh(fh)
|
|
|
-
|
|
|
- def analyze_tree(self, dir):
|
|
|
- for dirpath, _, filenames in os.walk(dir):
|
|
|
- for path in (Path(dirpath, f) for f in filenames):
|
|
|
- if path.endswith(".py"):
|
|
|
- yield self.analyze_file(path)
|
|
|
-
|
|
|
- def analyze(self, *paths):
|
|
|
- for path in map(Path, paths):
|
|
|
- if path.isdir():
|
|
|
- for res in self.analyze_tree(path):
|
|
|
- yield res
|
|
|
- else:
|
|
|
- yield self.analyze_file(path)
|
|
|
-
|
|
|
- def strip_comments(self, fh):
|
|
|
- re_comment = self.re_comment
|
|
|
- re_ml_comment_o = self.re_ml_comment_o
|
|
|
- re_ml_comment_s = self.re_ml_comment_s
|
|
|
- re_ml_comment_e = self.re_ml_comment_e
|
|
|
- re_noqa = self.re_noqa
|
|
|
- in_ml = False
|
|
|
-
|
|
|
- for line in fh.readlines():
|
|
|
- if in_ml:
|
|
|
- if re_ml_comment_e.match(line):
|
|
|
- in_ml = False
|
|
|
- else:
|
|
|
- if re_noqa.match(line) or re_ml_comment_o.match(line):
|
|
|
- pass
|
|
|
- elif re_ml_comment_s.match(line):
|
|
|
- in_ml = True
|
|
|
- elif re_comment.match(line):
|
|
|
- pass
|
|
|
- else:
|
|
|
- yield line
|
|
|
-
|
|
|
- def announce(self, fmt, **kwargs):
|
|
|
- sys.stderr.write((fmt + "\n") % kwargs)
|
|
|
-
|
|
|
-
|
|
|
-def main(argv=sys.argv, exitcode=0):
|
|
|
- for _, errors, _ in FlakePP(verbose=True).analyze(*argv[1:]):
|
|
|
- if errors:
|
|
|
- exitcode = 1
|
|
|
- return exitcode
|
|
|
-
|
|
|
-
|
|
|
-if __name__ == "__main__":
|
|
|
- sys.exit(main())
|