diff options
author | Georg Brandl <georg@python.org> | 2014-10-08 09:09:18 +0200 |
---|---|---|
committer | Georg Brandl <georg@python.org> | 2014-10-08 09:09:18 +0200 |
commit | 6d063d8d28bda60f37b03c7fe130074f92932398 (patch) | |
tree | 946af08ab0d46558c58b246dd5d13fee9bcdfae3 /scripts/check_sources.py | |
parent | 342f9b5f2720ab257cea0ca934f1c82d9cbfab72 (diff) | |
parent | ac3a01c3b86d36b4dc88a11dfe2dfe042ea1c208 (diff) | |
download | pygments-6d063d8d28bda60f37b03c7fe130074f92932398.tar.gz |
Merged in protz/pygments-main/add-envname (pull request #235)
Diffstat (limited to 'scripts/check_sources.py')
-rwxr-xr-x | scripts/check_sources.py | 121 |
1 files changed, 45 insertions, 76 deletions
diff --git a/scripts/check_sources.py b/scripts/check_sources.py index d9e5c2ae..5f233887 100755 --- a/scripts/check_sources.py +++ b/scripts/check_sources.py @@ -7,20 +7,26 @@ Make sure each Python file has a correct file header including copyright and license information. - :copyright: Copyright 2006-2013 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2014 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ -import sys, os, re +from __future__ import print_function + +import io +import os +import re +import sys import getopt -import cStringIO from os.path import join, splitext, abspath checkers = {} + def checker(*suffixes, **kwds): only_pkg = kwds.pop('only_pkg', False) + def deco(func): for suffix in suffixes: checkers.setdefault(suffix, []).append(func) @@ -30,12 +36,10 @@ def checker(*suffixes, **kwds): name_mail_re = r'[\w ]+(<.*?>)?' -copyright_re = re.compile(r'^ :copyright: Copyright 2006-2013 by ' +copyright_re = re.compile(r'^ :copyright: Copyright 2006-2014 by ' r'the Pygments team, see AUTHORS\.$', re.UNICODE) copyright_2_re = re.compile(r'^ %s(, %s)*[,.]$' % (name_mail_re, name_mail_re), re.UNICODE) -coding_re = re.compile(r'coding[:=]\s*([-\w.]+)') -not_ix_re = re.compile(r'\bnot\s+\S+?\s+i[sn]\s\S+') is_const_re = re.compile(r'if.*?==\s+(None|False|True)\b') misspellings = ["developement", "adress", "verificate", # ALLOW-MISSPELLING @@ -44,41 +48,30 @@ misspellings = ["developement", "adress", "verificate", # ALLOW-MISSPELLING @checker('.py') def check_syntax(fn, lines): + if '#!/' in lines[0]: + lines = lines[1:] + if 'coding:' in lines[0]: + lines = lines[1:] try: - compile(''.join(lines), fn, "exec") - except SyntaxError, err: + compile('\n'.join(lines), fn, "exec") + except SyntaxError as err: yield 0, "not compilable: %s" % err @checker('.py') def check_style_and_encoding(fn, lines): - encoding = 'ascii' for lno, line in enumerate(lines): - if len(line) > 90: + if len(line) > 110: yield lno+1, "line too long" - m = not_ix_re.search(line) - if m: - yield lno+1, '"' + m.group() + '"' if is_const_re.search(line): yield lno+1, 'using == None/True/False' - if lno < 2: - co = coding_re.search(line) - if co: - encoding = co.group(1) - try: - line.decode(encoding) - except UnicodeDecodeError, err: - yield lno+1, "not decodable: %s\n Line: %r" % (err, line) - except LookupError, err: - yield 0, "unknown encoding: %s" % encoding - encoding = 'latin1' @checker('.py', only_pkg=True) def check_fileheader(fn, lines): # line number correction c = 1 - if lines[0:1] == ['#!/usr/bin/env python\n']: + if lines[0:1] == ['#!/usr/bin/env python']: lines = lines[1:] c = 2 @@ -87,31 +80,28 @@ def check_fileheader(fn, lines): for lno, l in enumerate(lines): llist.append(l) if lno == 0: - if l == '# -*- coding: rot13 -*-\n': - # special-case pony package - return - elif l != '# -*- coding: utf-8 -*-\n': + if l != '# -*- coding: utf-8 -*-': yield 1, "missing coding declaration" elif lno == 1: - if l != '"""\n' and l != 'r"""\n': + if l != '"""' and l != 'r"""': yield 2, 'missing docstring begin (""")' else: docopen = True elif docopen: - if l == '"""\n': + if l == '"""': # end of docstring if lno <= 4: yield lno+c, "missing module name in docstring" break - if l != "\n" and l[:4] != ' ' and docopen: + if l != "" and l[:4] != ' ' and docopen: yield lno+c, "missing correct docstring indentation" if lno == 2: # if not in package, don't check the module name modname = fn[:-3].replace('/', '.').replace('.__init__', '') while modname: - if l.lower()[4:-1] == modname: + if l.lower()[4:] == modname: break modname = '.'.join(modname.split('.')[1:]) else: @@ -126,11 +116,11 @@ def check_fileheader(fn, lines): # check for copyright and license fields license = llist[-2:-1] - if license != [" :license: BSD, see LICENSE for details.\n"]: + if license != [" :license: BSD, see LICENSE for details."]: yield 0, "no correct license info" ci = -3 - copyright = [s.decode('utf-8') for s in llist[ci:ci+1]] + copyright = llist[ci:ci+1] while copyright and copyright_2_re.match(copyright[0]): ci -= 1 copyright = llist[ci:ci+1] @@ -138,34 +128,11 @@ def check_fileheader(fn, lines): yield 0, "no correct copyright info" -@checker('.py', '.html', '.js') -def check_whitespace_and_spelling(fn, lines): - for lno, line in enumerate(lines): - if "\t" in line: - yield lno+1, "OMG TABS!!!1 " - if line[:-1].rstrip(' \t') != line[:-1]: - yield lno+1, "trailing whitespace" - for word in misspellings: - if word in line and 'ALLOW-MISSPELLING' not in line: - yield lno+1, '"%s" used' % word - - -bad_tags = ('<b>', '<i>', '<u>', '<s>', '<strike>' - '<center>', '<big>', '<small>', '<font') - -@checker('.html') -def check_xhtml(fn, lines): - for lno, line in enumerate(lines): - for bad_tag in bad_tags: - if bad_tag in line: - yield lno+1, "used " + bad_tag - - def main(argv): try: gopts, args = getopt.getopt(argv[1:], "vi:") except getopt.GetoptError: - print "Usage: %s [-v] [-i ignorepath]* [path]" % argv[0] + print("Usage: %s [-v] [-i ignorepath]* [path]" % argv[0]) return 2 opts = {} for opt, val in gopts: @@ -178,30 +145,33 @@ def main(argv): elif len(args) == 1: path = args[0] else: - print "Usage: %s [-v] [-i ignorepath]* [path]" % argv[0] + print("Usage: %s [-v] [-i ignorepath]* [path]" % argv[0]) return 2 verbose = '-v' in opts num = 0 - out = cStringIO.StringIO() + out = io.StringIO() # TODO: replace os.walk run with iteration over output of # `svn list -R`. for root, dirs, files in os.walk(path): - if '.svn' in dirs: - dirs.remove('.svn') + if '.hg' in dirs: + dirs.remove('.hg') + if 'examplefiles' in dirs: + dirs.remove('examplefiles') if '-i' in opts and abspath(root) in opts['-i']: del dirs[:] continue # XXX: awkward: for the Makefile call: don't check non-package # files for file headers - in_pocoo_pkg = root.startswith('./pygments') + in_pygments_pkg = root.startswith('./pygments') for fn in files: fn = join(root, fn) - if fn[:2] == './': fn = fn[2:] + if fn[:2] == './': + fn = fn[2:] if '-i' in opts and abspath(fn) in opts['-i']: continue @@ -212,29 +182,28 @@ def main(argv): continue if verbose: - print "Checking %s..." % fn + print("Checking %s..." % fn) try: - f = open(fn, 'r') - lines = list(f) - except (IOError, OSError), err: - print "%s: cannot open: %s" % (fn, err) + lines = open(fn, 'rb').read().decode('utf-8').splitlines() + except (IOError, OSError) as err: + print("%s: cannot open: %s" % (fn, err)) num += 1 continue for checker in checkerlist: - if not in_pocoo_pkg and checker.only_pkg: + if not in_pygments_pkg and checker.only_pkg: continue for lno, msg in checker(fn, lines): - print >>out, "%s:%d: %s" % (fn, lno, msg) + print(u"%s:%d: %s" % (fn, lno, msg), file=out) num += 1 if verbose: - print + print() if num == 0: - print "No errors found." + print("No errors found.") else: - print out.getvalue().rstrip('\n') - print "%d error%s found." % (num, num > 1 and "s" or "") + print(out.getvalue().rstrip('\n')) + print("%d error%s found." % (num, num > 1 and "s" or "")) return int(num > 0) |