##// END OF EJS Templates
rust-cpython: leverage py_shared_iterator::from_inner() where appropriate
rust-cpython: leverage py_shared_iterator::from_inner() where appropriate

File last commit:

r43139:4257c33e default
r43161:5ccc08d0 default
Show More
check-code.py
875 lines | 32.2 KiB | text/x-python | PythonLexer
Matt Mackall
Introduce check-code.py...
r10281 #!/usr/bin/env python
#
# check-code - a style and portability checker for Mercurial
#
Matt Mackall
check-code: fix copyright date
r10290 # Copyright 2010 Matt Mackall <mpm@selenic.com>
Matt Mackall
Introduce check-code.py...
r10281 #
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2 or any later version.
Simon Heimberg
check-code: explain what to do when a check-code rule mismatches...
r20241 """style and portability checker for Mercurial
when a rule triggers wrong, do one of the following (prefer one from top):
* do the work-around the rule suggests
* doublecheck that it is a false match
* improve the rule pattern
* add an ignore pattern to the rule (3rd arg) which matches your good line
timeless
py24: remove check-code py24 notation...
r28700 (you can append a short comment and match this, like: #re-raises)
Simon Heimberg
check-code: explain what to do when a check-code rule mismatches...
r20241 * change the pattern to a warning and list the exception in test-check-code-hg
* ONLY use no--check-code for skipping entire files from external sources
"""
Pulkit Goyal
check-code: use absolute_import and print_function
r28509 from __future__ import absolute_import, print_function
import glob
Thomas Arendsen Hein
check-code: check for gratuitous whitespace after Python keywords
r13074 import keyword
Matt Mackall
check-code: add a warnings level...
r10895 import optparse
Pulkit Goyal
check-code: use absolute_import and print_function
r28509 import os
import re
import sys
timeless
check-code: handle py3 open divergence...
r29145 if sys.version_info[0] < 3:
opentext = open
else:
def opentext(f):
Augie Fackler
contrib: have check-code look at files in latin1 instead of ascii...
r39091 return open(f, encoding='latin1')
Simon Heimberg
check-code: introduce function for using re2 when available...
r19310 try:
timeless
check-code: handle range/xrange divergence
r29143 xrange
except NameError:
xrange = range
try:
Simon Heimberg
check-code: introduce function for using re2 when available...
r19310 import re2
except ImportError:
re2 = None
FUJIWARA Katsunori
contrib: make check-code.py check code fragments embedded in test scripts
r41992 import testparseutil
Simon Heimberg
check-code: introduce function for using re2 when available...
r19310 def compilere(pat, multiline=False):
if multiline:
pat = '(?m)' + pat
if re2:
try:
return re2.compile(pat)
except re2.error:
pass
return re.compile(pat)
Matt Mackall
Introduce check-code.py...
r10281
FUJIWARA Katsunori
check-code: build translation table for repquote in global for efficiency...
r29398 # check "rules depending on implementation of repquote()" in each
# patterns (especially pypats), before changing around repquote()
_repquotefixedmap = {' ': ' ', '\n': '\n', '.': 'p', ':': 'q',
'%': '%', '\\': 'b', '*': 'A', '+': 'P', '-': 'M'}
def _repquoteencodechr(i):
if i > 255:
return 'u'
c = chr(i)
if c in _repquotefixedmap:
return _repquotefixedmap[c]
if c.isalpha():
return 'x'
if c.isdigit():
return 'n'
return 'o'
_repquotett = ''.join(_repquoteencodechr(i) for i in xrange(256))
Matt Mackall
Introduce check-code.py...
r10281 def repquote(m):
Simon Heimberg
check-code: more replacement characters...
r19999 t = m.group('text')
FUJIWARA Katsunori
check-code: build translation table for repquote in global for efficiency...
r29398 t = t.translate(_repquotett)
Benoit Boissinot
check-code: improve quote detection regexp, add tests
r10722 return m.group('quote') + t + m.group('quote')
Matt Mackall
Introduce check-code.py...
r10281
Benoit Boissinot
check-code: more tests and more robust python filtering
r10727 def reppython(m):
comment = m.group('comment')
if comment:
Mads Kiilerich
check-code: catch trailing space in comments
r18959 l = len(comment.rstrip())
return "#" * l + comment[l:]
Benoit Boissinot
check-code: more tests and more robust python filtering
r10727 return repquote(m)
Matt Mackall
Introduce check-code.py...
r10281
def repcomment(m):
return m.group(1) + "#" * len(m.group(2))
def repccomment(m):
t = re.sub(r"((?<=\n) )|\S", "x", m.group(2))
return m.group(1) + t + "*/"
def repcallspaces(m):
t = re.sub(r"\n\s+", "\n", m.group(2))
return m.group(1) + t
def repinclude(m):
return m.group(1) + "<foo>"
def rephere(m):
t = re.sub(r"\S", "x", m.group(2))
return m.group(1) + t
testpats = [
Idan Kamara
check-code: separate warnings to avoid repetitive str.startswith
r14009 [
Pierre-Yves David
checkcode: only match pushd/popd as word...
r31877 (r'\b(push|pop)d\b', "don't use 'pushd' or 'popd', use 'cd'"),
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281 (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"),
Martin Geisler
check-code.py: make help strings consistent
r10374 (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"),
Martin von Zweigbergk
check-code: allow "grep pattern filename-containing-dash-a"...
r27989 (r'(?<!hg )grep.* -a', "don't use 'grep -a', use in-line python"),
Matt Mackall
tests: remove sed -i from test-record
r16332 (r'sed.*-i', "don't use 'sed -i', use a temporary file"),
Mads Kiilerich
test-alias: adapt for Windows...
r16965 (r'\becho\b.*\\n', "don't use 'echo \\n', use printf"),
Martin Geisler
check-code: catch "echo -n" in tests
r11884 (r'echo -n', "don't use 'echo -n', use printf"),
Matt Mackall
test-revert.t: fix wc check-code false positive
r23134 (r'(^|\|\s*)\bwc\b[^|]*$\n(?!.*\(re\))', "filter wc output"),
Martin Geisler
check-code.py: make help strings consistent
r10374 (r'head -c', "don't use 'head -c', use 'dd'"),
Danek Duvall
solaris: tests can't use tail -n...
r19628 (r'tail -n', "don't use the '-n' option to tail, just use '-<num>'"),
Matt Mackall
tests: use md5sum.py instead of sha1sum, add check
r15389 (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"),
Matt Harbison
check-code: tighten the check for `ls -R`...
r37258 (r'\bls\b.*-\w*R', "don't use 'ls -R', use 'find'"),
timeless
check-code: fix py3 complaint about \NNN being invalid unicode
r29142 (r'printf.*[^\\]\\([1-9]|0\d)', r"don't use 'printf \NNN', use Python"),
Simon Heimberg
check-code: do not warn on printf \\x or \\[1-9]...
r19380 (r'printf.*[^\\]\\x', "don't use printf \\x, use Python"),
Matt Mackall
Introduce check-code.py...
r10281 (r'rm -rf \*', "don't use naked rm -rf, target a directory"),
Augie Fackler
style: ban [ foo == bar] bashism in tests
r32293 (r'\[[^\]]+==', '[ foo == bar ] is a bashism, use [ foo = bar ] instead'),
Matt Mackall
check-code: fix issues with finding patterns in unified tests, fix tests...
r15372 (r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w',
Matt Mackall
Introduce check-code.py...
r10281 "use egrep for extended grep syntax"),
Jun Wu
check-code: forbid "\S" in egrep regular expression...
r34063 (r'(^|\|\s*)e?grep .*\\S', "don't use \\S in regular expression"),
Jun Wu
check-code: forbid using bash in shebang...
r34062 (r'(?<!!)/bin/', "don't use explicit paths for tools"),
(r'#!.*/bash', "don't use bash in shebang, use sh"),
Matt Mackall
Introduce check-code.py...
r10281 (r'[^\n]\Z', "no trailing newline"),
timeless
check-code: export needs a space to avoid false positives
r27791 (r'export .*=', "don't export and assign at once"),
Matt Mackall
check-code: fix issues with finding patterns in unified tests, fix tests...
r15372 (r'^source\b', "don't use 'source', use '.'"),
Dan Villiom Podlaski Christiansen
tests: compatibility fix....
r12367 (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"),
Yuya Nishihara
check-code: make 'ls' pattern less invasive...
r29330 (r'\bls +[^|\n-]+ +-', "options to 'ls' must come before filenames"),
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281 (r'[^>\n]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"),
Matt Mackall
check-code: fix issues with finding patterns in unified tests, fix tests...
r15372 (r'^stop\(\)', "don't use 'stop' as a shell function name"),
Mads Kiilerich
tests: don't use 'test -e'...
r15282 (r'(\[|\btest\b).*-e ', "don't use 'test -e', use 'test -f'"),
Yuya Nishihara
check-code: ban use of '[[ ]]' in tests
r25588 (r'\[\[\s+[^\]]*\]\]', "don't use '[[ ]]', use '[ ]'"),
Mads Kiilerich
tests: don't use alias...
r16013 (r'^alias\b.*=', "don't use alias, use a function"),
Mads Kiilerich
tests: solaris sh can not negate exit status with '!'
r16485 (r'if\s*!', "don't use '!' to negate exit status"),
Mads Kiilerich
tests: don't use /dev/urandom for largefiles testing...
r16494 (r'/dev/u?random', "don't use entropy, use /dev/zero"),
Mads Kiilerich
tests: use 'do sleep 0' instead of 'do true', also on first line of command...
r16496 (r'do\s*true;\s*done', "don't use true as loop body, use sleep 0"),
Kevin Bullock
check-code: fix sed 'i' command rule newline matching...
r19083 (r'sed (-e )?\'(\d+|/[^/]*/)i(?!\\\n)',
Kevin Bullock
check-code: add a rule against a GNU sed-ism...
r19080 "put a backslash-escaped newline after sed 'i' command"),
Danek Duvall
tests: Solaris diff -U also emits "No differences encountered"...
r27557 (r'^diff *-\w*[uU].*$\n(^ \$ |^$)', "prefix diff -u/-U with cmp"),
(r'^\s+(if)? diff *-\w*[uU]', "prefix diff -u/-U with cmp"),
Augie Fackler
contrib: widen "direct use of `python`" net again...
r33288 (r'[\s="`\']python\s(?!bindings)', "don't use 'python', use '$PYTHON'"),
Pierre-Yves David
check-code: detect and ban 'util.Abort'...
r26588 (r'seq ', "don't use 'seq', use $TESTDIR/seq.py"),
(r'\butil\.Abort\b', "directly use error.Abort"),
timeless
check-code: block non-portable pipe-and
r26777 (r'\|&', "don't use |&, use 2>&1"),
timeless
check-code: enforce strict spacing around assignment
r27640 (r'\w = +\w', "only one space after = allowed"),
timeless
check-code: reject sed ... \\n...
r28781 (r'\bsed\b.*[^\\]\\n', "don't use 'sed ... \\n', use a \\ and a newline"),
Jun Wu
check-code: add a rule to forbid "cp -r"...
r30557 (r'env.*-u', "don't use 'env -u VAR', use 'unset VAR'"),
(r'cp.* -r ', "don't use 'cp -r', use 'cp -R'"),
av6
check-code: grep's context flags don't need an extra space before number...
r35086 (r'grep.* -[ABC]', "don't use grep's context flags"),
Augie Fackler
contrib: ban find(1)'s -printf operator, as it is a GNU-ism...
r35252 (r'find.*-printf',
"don't use 'find -printf', it doesn't exist on BSD find(1)"),
Augie Fackler
contrib: ban $RANDOM using check-code...
r36182 (r'\$RANDOM ', "don't use bash-only $RANDOM to generate random values"),
Idan Kamara
check-code: separate warnings to avoid repetitive str.startswith
r14009 ],
# warnings
Mads Kiilerich
tests: run most check-code sh checks on continued lines too...
r16672 [
(r'^function', "don't use 'function', use old style"),
(r'^diff.*-\w*N', "don't use 'diff -N'"),
Mads Kiilerich
tests: use `pwd` instead of ${PWD} in test-convert-git.t - because of Solaris
r18508 (r'\$PWD|\${PWD}', "don't use $PWD, use `pwd`"),
Mads Kiilerich
tests: run most check-code sh checks on continued lines too...
r16672 (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\^', "^ must be quoted"),
Kevin Bullock
check-code: warn to use killdaemons instead of kill `cat PIDFILE`...
r18575 (r'kill (`|\$\()', "don't use kill, use killdaemons.py")
Mads Kiilerich
tests: run most check-code sh checks on continued lines too...
r16672 ]
Matt Mackall
Introduce check-code.py...
r10281 ]
testfilters = [
Jun Wu
check-code: forbid using bash in shebang...
r34062 (r"( *)(#([^!][^\n]*\S)?)", repcomment),
Matt Mackall
Introduce check-code.py...
r10281 (r"<<(\S+)((.|\n)*?\n\1)", rephere),
]
Matt Mackall
check-code: fix issues with finding patterns in unified tests, fix tests...
r15372 uprefix = r"^ \$ "
Matt Mackall
check-code: add some basic support for unified tests
r12364 utestpats = [
Idan Kamara
check-code: separate warnings to avoid repetitive str.startswith
r14009 [
Matt Mackall
check-code: allow only-whitespace lines in tests...
r27693 (r'^(\S.*|| [$>] \S.*)[ \t]\n', "trailing whitespace on non-output"),
Mads Kiilerich
tests: unify the last sh tests...
r16673 (uprefix + r'.*\|\s*sed[^|>\n]*\n',
"use regex test output patterns instead of sed"),
Matt Mackall
check-code: add some basic support for unified tests
r12364 (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"),
Patrick Mezard
test-svn-subrepo: fix reference output for svn 1.7...
r15607 (uprefix + r'.*(?<!\[)\$\?', "explicit exit code checks unnecessary"),
Matt Mackall
check-code: add some basic support for unified tests
r12364 (uprefix + r'.*\|\| echo.*(fail|error)',
"explicit exit code checks unnecessary"),
(uprefix + r'set -e', "don't use set -e"),
Mads Kiilerich
check-code: check that '>' is used for continued lines...
r19873 (uprefix + r'(\s|fi\b|done\b)', "use > for continued lines"),
Simon Heimberg
tests: rewrite path in test-shelve.t for not being mangled on msys...
r20423 (uprefix + r'.*:\.\S*/', "x:.y in a path does not work on msys, rewrite "
"as x://.y, or see `hg log -k msys` for alternatives", r'-\S+:\.|' #-Rxxx
Matt Mackall
check-code: allow disabling msys path check
r24205 '# no-msys'), # in test-pull.t which is skipped on windows
Augie Fackler
check-code: update test IP address enforcement checks...
r31816 (r'^ [^$>].*27\.0\.0\.1',
'use $LOCALIP not an explicit loopback address'),
Augie Fackler
contrib: improve check-code ban on $LOCALIP in output without (glob)...
r35154 (r'^ (?![>$] ).*\$LOCALIP.*[^)]$',
Augie Fackler
check-code: update test IP address enforcement checks...
r31816 'mark $LOCALIP output lines with (glob) to help tests in BSD jails'),
Matt Harbison
tests: fix the check-code rule for testing non-existent files...
r35463 (r'^ (cat|find): .*: \$ENOENT\$',
Danek Duvall
tests: cat error messages are different on Solaris
r21930 'use test -f to test for file existence'),
FUJIWARA Katsunori
tests: omit -p for external diff via extdiff extension for portability...
r28033 (r'^ diff -[^ -]*p',
"don't use (external) diff with -p for portability"),
Augie Fackler
contrib: add check-code rule banning use of readlink...
r34574 (r' readlink ', 'use readlink.py instead of readlink'),
FUJIWARA Katsunori
tests: make timezone in diff output glob-ed for portability...
r28034 (r'^ [-+][-+][-+] .* [-+]0000 \(glob\)',
"glob timezone field in diff output for portability"),
FUJIWARA Katsunori
tests: make chunk header of external diff glob-ed for portability...
r28035 (r'^ @@ -[0-9]+ [+][0-9]+,[0-9]+ @@',
"use '@@ -N* +N,n @@ (glob)' style chunk header for portability"),
(r'^ @@ -[0-9]+,[0-9]+ [+][0-9]+ @@',
"use '@@ -N,n +N* @@ (glob)' style chunk header for portability"),
(r'^ @@ -[0-9]+ [+][0-9]+ @@',
"use '@@ -N* +N* @@ (glob)' style chunk header for portability"),
FUJIWARA Katsunori
check-code: add rule to detect usage of external diff via extdiff...
r28053 (uprefix + r'hg( +-[^ ]+( +[^ ]+)?)* +extdiff'
r'( +(-[^ po-]+|--(?!program|option)[^ ]+|[^-][^ ]*))*$',
"use $RUNTESTDIR/pdiff via extdiff (or -o/-p for false-positives)"),
Idan Kamara
check-code: separate warnings to avoid repetitive str.startswith
r14009 ],
# warnings
Simon Heimberg
check-code: warn about line glob match with no glob character (?*/)
r18683 [
Jun Wu
runtests: change local IP glob pattern from "127.0.0.1" to "$LOCALIP"...
r31673 (r'^ (?!.*\$LOCALIP)[^*?/\n]* \(glob\)$',
"glob match with no glob string (?, *, /, and $LOCALIP)"),
Simon Heimberg
check-code: warn about line glob match with no glob character (?*/)
r18683 ]
Matt Mackall
check-code: add some basic support for unified tests
r12364 ]
Yuya Nishihara
check-code: allow tabs in heredoc
r35316 # transform plain test rules to unified test's
Mads Kiilerich
check-code: fix checking for sh style in .t tests...
r14203 for i in [0, 1]:
Pierre-Yves David
check-code: allow an escape pattern to be specified for testpattern...
r22101 for tp in testpats[i]:
p = tp[0]
m = tp[1]
Matt Mackall
check-code: fix issues with finding patterns in unified tests, fix tests...
r15372 if p.startswith(r'^'):
Mads Kiilerich
tests: run most check-code sh checks on continued lines too...
r16672 p = r"^ [$>] (%s)" % p[1:]
Mads Kiilerich
check-code: fix checking for sh style in .t tests...
r14203 else:
Mads Kiilerich
tests: run most check-code sh checks on continued lines too...
r16672 p = r"^ [$>] .*(%s)" % p
Pierre-Yves David
check-code: allow an escape pattern to be specified for testpattern...
r22101 utestpats[i].append((p, m) + tp[2:])
Matt Mackall
check-code: add some basic support for unified tests
r12364
Yuya Nishihara
check-code: allow tabs in heredoc
r35316 # don't transform the following rules:
# " > \t" and " \t" should be allowed in unified tests
testpats[0].append((r'^( *)\t', "don't use tabs to indent"))
utestpats[0].append((r'^( ?)\t', "don't use tabs to indent"))
Matt Mackall
check-code: add some basic support for unified tests
r12364 utestfilters = [
Idan Kamara
check-code: replace heredocs in unified tests...
r17711 (r"<<(\S+)((.|\n)*?\n > \1)", rephere),
Jun Wu
check-code: forbid using bash in shebang...
r34062 (r"( +)(#([^!][^\n]*\S)?)", repcomment),
Matt Mackall
check-code: add some basic support for unified tests
r12364 ]
FUJIWARA Katsunori
contrib: split pypats list in check-code.py...
r41987 # common patterns to check *.py
commonpypats = [
Idan Kamara
check-code: separate warnings to avoid repetitive str.startswith
r14009 [
Augie Fackler
contrib: enforce wrapping too-long lines with () instead of \...
r41927 (r'\\$', 'Use () to wrap long lines in Python, not \\'),
Renato Cunha
check-code: check for tuple parameter unpacking (missing in py3k)
r11568 (r'^\s*def\s*\w+\s*\(.*,\s*\(',
"tuple parameter unpacking not available in Python 3+"),
(r'lambda\s*\(.*,.*\)',
"tuple parameter unpacking not available in Python 3+"),
Renato Cunha
check-code: added a check for calls to the builtin cmp function
r11764 (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"),
Yedidya Feldblum
check-code: permit functools.reduce
r30883 (r'(?<!\.)\breduce\s*\(.*', "reduce is not available in Python 3+"),
Yuya Nishihara
check-code: make dict() pattern less invasive...
r29793 (r'\bdict\(.*=', 'dict() is different in Py2 and 3 and is slower than {}',
Augie Fackler
check-code: disallow use of dict(key=value) construction...
r20688 'dict-from-generator'),
Martin Geisler
check-code: catch dict.has_key
r11602 (r'\.has_key\b', "dict.has_key is not available in Python 3+"),
Augie Fackler
check-code: disallow defunct <> operator...
r18183 (r'\s<>\s', '<> operator is not available in Python 3+, use !='),
Matt Mackall
Introduce check-code.py...
r10281 (r'^\s*\t', "don't use tabs"),
Matt Mackall
check-code: import some pylint checks
r10412 (r'\S;\s*\n', "semicolon"),
FUJIWARA Katsunori
check-code: detect "% inside _()" when there are leading whitespaces...
r21097 (r'[^_]_\([ \t\n]*(?:"[^"]+"[ \t\n+]*)+%', "don't use % inside _()"),
(r"[^_]_\([ \t\n]*(?:'[^']+'[ \t\n+]*)+%", "don't use % inside _()"),
Mads Kiilerich
check-code: there must also be whitespace between ')' and operator...
r18054 (r'(\w|\)),\w', "missing whitespace after ,"),
(r'(\w|\))[+/*\-<>]\w', "missing whitespace in expression"),
Mads Kiilerich
check-code: make 'missing whitespace in assignment' more aggressive...
r18055 (r'^\s+(\w|\.)+=\w[^,()\n]*$', "missing whitespace in assignment"),
timeless
check-code: enforce strict spacing around assignment
r27640 (r'\w\s=\s\s+\w', "gratuitous whitespace after ="),
Augie Fackler
contrib: add a check to check-code to ban superfluous pass statements...
r34383 ((
# a line ending with a colon, potentially with trailing comments
r':([ \t]*#[^\n]*)?\n'
# one that is not a pass and not only a comment
r'(?P<indent>[ \t]+)[^#][^\n]+\n'
# more lines at the same indent level
r'((?P=indent)[^\n]+\n)*'
# a pass at the same indent level, which is bogus
r'(?P=indent)pass[ \t\n#]'
), 'omit superfluous pass'),
Matt Mackall
Introduce check-code.py...
r10281 (r'[^\n]\Z', "no trailing newline"),
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
Brodie Rao
cleanup: eradicate long lines
r16683 # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=',
# "don't use underbars in identifiers"),
Martin von Zweigbergk
check-code: fix incorrect capitalization in camelcase regex...
r34084 (r'^\s+(self\.)?[A-Za-z][a-z0-9]+[A-Z]\w* = ',
Siddharth Agarwal
check-code: allow an exception for camelcase where required...
r34430 "don't use camelcase in identifiers", r'#.*camelcase-required'),
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281 (r'^\s*(if|while|def|class|except|try)\s[^[\n]*:\s*[^\\n]#\s]+',
Matt Mackall
check-code: check thyself
r10286 "linebreak after :"),
Jun Wu
check-code: allow old style class with special comments...
r28219 (r'class\s[^( \n]+:', "old-style class, use class foo(object)",
r'#.*old-style'),
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281 (r'class\s[^( \n]+\(\):',
Jun Wu
check-code: allow old style class with special comments...
r28219 "class foo() creates old style object, use class foo(object)",
r'#.*old-style'),
Pierre-Yves David
check-code: allow print and exec as a function...
r25028 (r'\b(%s)\(' % '|'.join(k for k in keyword.kwlist
if k not in ('print', 'exec')),
Thomas Arendsen Hein
check-code: single check for Python keywords used as a function...
r13076 "Python keyword is not a function"),
Matt Mackall
check-code: import some pylint checks
r10412 (r',]', "unneeded trailing ',' in list"),
Matt Mackall
Introduce check-code.py...
r10281 # (r'class\s[A-Z][^\(]*\((?!Exception)',
# "don't capitalize non-exception classes"),
# (r'in range\(', "use xrange"),
# (r'^\s*print\s+', "avoid using print in core and extensions"),
(r'[\x80-\xff]', "non-ASCII character literal"),
Matt Mackall
check-code: reintroduce str.format() ban for 3.x porting...
r25212 (r'("\')\.format\(', "str.format() has no bytes counterpart, use %"),
Thomas Arendsen Hein
check-code: check for gratuitous whitespace after Python keywords
r13074 (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist),
"gratuitous whitespace after Python keyword"),
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281 (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"),
Matt Mackall
Introduce check-code.py...
r10281 # (r'\s\s=', "gratuitous whitespace before ="),
Pierre-Yves David
check-code: recognise %= as an operator
r17167 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S',
Martin Geisler
check-code: reformat long lines
r11345 "missing whitespace around operator"),
Pierre-Yves David
check-code: recognise %= as an operator
r17167 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\s',
Martin Geisler
check-code: reformat long lines
r11345 "missing whitespace around operator"),
Pierre-Yves David
check-code: recognise %= as an operator
r17167 (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S',
Martin Geisler
check-code: reformat long lines
r11345 "missing whitespace around operator"),
Pierre-Yves David
check-code: recognise %= as an operator
r17167 (r'[^^+=*/!<>&| %-](\s=|=\s)[^= ]',
Martin Geisler
check-code: reformat long lines
r11345 "wrong whitespace around ="),
Mads Kiilerich
check-code: check for spaces around = for named parameters
r19872 (r'\([^()]*( =[^=]|[^<>!=]= )',
"no whitespace around = for named parameters"),
Augie Fackler
check-code: disallow two-argument form of raise...
r18180 (r'raise [^,(]+, (\([^\)]+\)|[^,\(\)]+)$',
"don't use old-style two-argument raise, use Exception(message)"),
Idan Kamara
check-code: separate warnings to avoid repetitive str.startswith
r14009 (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"),
(r' [=!]=\s+(True|False|None)',
"comparison with singleton, use 'is' or 'is not' instead"),
Martin Geisler
check-code: flag 0/1 used as constant Boolean expression
r14494 (r'^\s*(while|if) [01]:',
"use True/False for constant Boolean expression"),
Augie Fackler
check-code: prohibit `if False` antipattern...
r33369 (r'^\s*if False(:| +and)', 'Remove code instead of using `if False`'),
Yuya Nishihara
check-code: allow assignment to hasattr variable
r29796 (r'(?:(?<!def)\s+|\()hasattr\(',
Siddharth Agarwal
check-code: allow skipping hasattr check in py3-only code...
r32418 'hasattr(foo, bar) is broken on py2, use util.safehasattr(foo, bar) '
'instead', r'#.*hasattr-py3-only'),
Dan Villiom Podlaski Christiansen
check-code: disallow calling opener(...).read() and opener(..).write()
r14169 (r'opener\([^)]*\).read\(',
"use opener.read() instead"),
(r'opener\([^)]*\).write\(',
"use opener.write() instead"),
Mads Kiilerich
spelling: fixes from proofreading of spell checker issues
r23139 (r'(?i)descend[e]nt', "the proper spelling is descendAnt"),
Matt Mackall
check-code: don't mark debug messages for translation
r14709 (r'\.debug\(\_', "don't mark debug messages for translation"),
Martin Geisler
check-code: catch unnecessary s.strip().split() calls
r16590 (r'\.strip\(\)\.split\(\)', "no need to strip before splitting"),
Simon Heimberg
check-code: do not prepend "warning" to a failure message...
r18762 (r'^\s*except\s*:', "naked except clause", r'#.*re-raises'),
Gregory Szorc
check-code: detect legacy exception syntax...
r25661 (r'^\s*except\s([^\(,]+|\([^\)]+\))\s*,',
'legacy exception syntax; use "as" instead of ","'),
Matt Mackall
check-code: add check for lock release order
r19031 (r'release\(.*wlock, .*lock\)', "wrong lock release order"),
Gregory Szorc
py3: add __bool__ to every class defining __nonzero__...
r31476 (r'\bdef\s+__bool__\b', "__bool__ should be __nonzero__ in Python 2"),
FUJIWARA Katsunori
check-code: check os.path.join(*, '') not working correctly with Python 2.7.9...
r24836 (r'os\.path\.join\(.*, *(""|\'\')\)',
"use pathutil.normasprefix(path) instead of os.path.join(path, '')"),
Gregory Szorc
check-code: detect legacy octal syntax...
r25659 (r'\s0[0-7]+\b', 'legacy octal syntax; use "0o" prefix instead of "0"'),
Pierre-Yves David
check-code: forbid mutable value for default argument...
r26348 # XXX only catch mutable arguments on the first line of the definition
(r'def.*[( ]\w+=\{\}', "don't use mutable default arguments"),
Pierre-Yves David
check-code: detect and ban 'util.Abort'...
r26588 (r'\butil\.Abort\b', "directly use error.Abort"),
Martin von Zweigbergk
check-code: reject module-level @cachefunc...
r30810 (r'^@(\w*\.)?cachefunc', "module-level @cachefunc is risky, please avoid"),
Gregory Szorc
pycompat: export queue module instead of symbols in module (API)...
r37863 (r'^import Queue', "don't use Queue, use pycompat.queue.Queue + "
"pycompat.queue.Empty"),
timeless
check-code: reject import urllib
r28884 (r'^import cStringIO', "don't use cStringIO.StringIO, use util.stringio"),
(r'^import urllib', "don't use urllib, use util.urlreq/util.urlerr"),
Pulkit Goyal
py3: add tests in check-code to load modules from util.py...
r29434 (r'^import SocketServer', "don't use SockerServer, use util.socketserver"),
Gregory Szorc
check-code: recommend util.urlreq when importing urlparse
r31572 (r'^import urlparse', "don't use urlparse, use util.urlreq"),
Pulkit Goyal
py3: add tests in check-code to load modules from util.py...
r29434 (r'^import xmlrpclib', "don't use xmlrpclib, use util.xmlrpclib"),
(r'^import cPickle', "don't use cPickle, use util.pickle"),
(r'^import pickle', "don't use pickle, use util.pickle"),
Pulkit Goyal
py3: conditionalize httplib import...
r29455 (r'^import httplib', "don't use httplib, use util.httplib"),
Pulkit Goyal
py3: conditionalize BaseHTTPServer, SimpleHTTPServer and CGIHTTPServer import...
r29566 (r'^import BaseHTTPServer', "use util.httpserver instead"),
Jun Wu
check-code: suggest policy.importmod...
r32599 (r'^(from|import) mercurial\.(cext|pure|cffi)',
"use mercurial.policy.importmod instead"),
timeless
check-code: reject .next(...)
r29217 (r'\.next\(\)', "don't use .next(), use next(...)"),
Jun Wu
check-code: detect r.revision(r.node(rev))...
r31721 (r'([a-z]*).revision\(\1\.node\(',
Martin von Zweigbergk
check-code: fix "covert" typo
r31786 "don't convert rev to node before passing to revision(nodeorrev)"),
Jun Wu
check-code: forbid platform.system()...
r34643 (r'platform\.system\(\)', "don't use platform.system(), use pycompat"),
FUJIWARA Katsunori
check-code: centralize rules depending on implementation of repquote...
r29278
FUJIWARA Katsunori
contrib: split pypats list in check-code.py...
r41987 ],
# warnings
[
]
]
# patterns to check normal *.py files
pypats = [
[
# Ideally, these should be placed in "commonpypats" for
# consistency of coding rules in Mercurial source tree.
# But on the other hand, these are not so seriously required for
# python code fragments embedded in test scripts. Fixing test
# scripts for these patterns requires many changes, and has less
# profit than effort.
(r'.{81}', "line too long"),
(r'raise Exception', "don't raise generic exceptions"),
(r'[\s\(](open|file)\([^)]*\)\.read\(',
"use util.readfile() instead"),
(r'[\s\(](open|file)\([^)]*\)\.write\(',
"use util.writefile() instead"),
(r'^[\s\(]*(open(er)?|file)\([^)]*\)(?!\.close\(\))',
"always assign an opened file to a variable, and close it afterwards"),
(r'[\s\(](open|file)\([^)]*\)\.(?!close\(\))',
"always assign an opened file to a variable, and close it afterwards"),
(r':\n( )*( ){1,3}[^ ]', "must indent 4 spaces"),
(r'^import atexit', "don't use atexit, use ui.atexit"),
FUJIWARA Katsunori
check-code: centralize rules depending on implementation of repquote...
r29278 # rules depending on implementation of repquote()
FUJIWARA Katsunori
check-code: make repquote distinguish more characters for exact detection...
r29279 (r' x+[xpqo%APM][\'"]\n\s+[\'"]x',
'string join across lines with no space'),
FUJIWARA Katsunori
check-code: detect "missing _() in ui message" more exactly...
r29397 (r'''(?x)ui\.(status|progress|write|note|warn)\(
[ \t\n#]*
(?# any strings/comments might precede a string, which
# contains translatable message)
((['"]|\'\'\'|""")[ \npq%bAPMxno]*(['"]|\'\'\'|""")[ \t\n#]+)*
(?# sequence consisting of below might precede translatable message
# - formatting string: "% 10s", "%05d", "% -3.2f", "%*s", "%%" ...
# - escaped character: "\\", "\n", "\0" ...
# - character other than '%', 'b' as '\', and 'x' as alphabet)
(['"]|\'\'\'|""")
((%([ n]?[PM]?([np]+|A))?x)|%%|b[bnx]|[ \nnpqAPMo])*x
(?# this regexp can't use [^...] style,
# because _preparepats forcibly adds "\n" into [^...],
# even though this regexp wants match it against "\n")''',
FUJIWARA Katsunori
check-code: centralize rules depending on implementation of repquote...
r29278 "missing _() in ui message (use () to hide false-positives)"),
FUJIWARA Katsunori
contrib: split pypats list in check-code.py...
r41987 ] + commonpypats[0],
Idan Kamara
check-code: separate warnings to avoid repetitive str.startswith
r14009 # warnings
[
FUJIWARA Katsunori
check-code: centralize rules depending on implementation of repquote...
r29278 # rules depending on implementation of repquote()
Simon Heimberg
check-code: more replacement characters...
r19999 (r'(^| )pp +xxxxqq[ \n][^\n]', "add two newlines after '.. note::'"),
FUJIWARA Katsunori
contrib: split pypats list in check-code.py...
r41987 ] + commonpypats[1]
Matt Mackall
Introduce check-code.py...
r10281 ]
FUJIWARA Katsunori
contrib: make check-code.py check code fragments embedded in test scripts
r41992 # patterns to check *.py for embedded ones in test script
embeddedpypats = [
[
] + commonpypats[0],
# warnings
[
] + commonpypats[1]
]
FUJIWARA Katsunori
contrib: split pypats list in check-code.py...
r41987 # common filters to convert *.py
commonpyfilters = [
Benoit Boissinot
check-code: more tests and more robust python filtering
r10727 (r"""(?msx)(?P<comment>\#.*?$)|
((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!")))
(?P<text>(([^\\]|\\.)*?))
(?P=quote))""", reppython),
Matt Mackall
Introduce check-code.py...
r10281 ]
FUJIWARA Katsunori
contrib: split pypats list in check-code.py...
r41987 # filters to convert normal *.py files
pyfilters = [
] + commonpyfilters
Jun Wu
check-code: suggest pycompat.is(posix|windows|darwin)...
r34649 # non-filter patterns
pynfpats = [
[
(r'pycompat\.osname\s*[=!]=\s*[\'"]nt[\'"]', "use pycompat.iswindows"),
(r'pycompat\.osname\s*[=!]=\s*[\'"]posix[\'"]', "use pycompat.isposix"),
(r'pycompat\.sysplatform\s*[!=]=\s*[\'"]darwin[\'"]',
"use pycompat.isdarwin"),
],
# warnings
[],
]
FUJIWARA Katsunori
contrib: make check-code.py check code fragments embedded in test scripts
r41992 # filters to convert *.py for embedded ones in test script
embeddedpyfilters = [
] + commonpyfilters
Jun Wu
checkcode: enforce lowercase for extension docstring title...
r31602 # extension non-filter patterns
pyextnfpats = [
[(r'^"""\n?[A-Z]', "don't capitalize docstring title")],
# warnings
[],
]
Mads Kiilerich
check-code: check txt files for trailing whitespace
r18960 txtfilters = []
txtpats = [
[
Gregory Szorc
check-code: use raw string...
r41685 (r'\s$', 'trailing whitespace'),
Simon Heimberg
help: remove last occurrences of ".. note::" without two newlines...
r20532 ('.. note::[ \n][^\n]', 'add two newlines after note::')
Mads Kiilerich
check-code: check txt files for trailing whitespace
r18960 ],
[]
]
Matt Mackall
Introduce check-code.py...
r10281 cpats = [
Idan Kamara
check-code: separate warnings to avoid repetitive str.startswith
r14009 [
Matt Mackall
Introduce check-code.py...
r10281 (r'//', "don't use //-style comments"),
(r'\S\t', "don't use tabs except for indent"),
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"),
Brodie Rao
check-code: promote 80+ character line warning to an error
r16702 (r'.{81}', "line too long"),
Matt Mackall
Introduce check-code.py...
r10281 (r'(while|if|do|for)\(', "use space after while/if/do/for"),
(r'return\(', "return is not a function"),
(r' ;', "no space before ;"),
Laurent Charignon
check-code: in C code, prevent space before closing parenthesis
r24453 (r'[^;] \)', "no space before )"),
Matt Mackall
check-code: add bracket style check
r19745 (r'[)][{]', "space between ) and {"),
Matt Mackall
Introduce check-code.py...
r10281 (r'\w+\* \w+', "use int *foo, not int* foo"),
Matt Mackall
check-code: make casting style check more precise
r19731 (r'\W\([^\)]+\) \w+', "use (int)foo, not (int) foo"),
Matt Mackall
check-code: avoid false-positive on ++
r16413 (r'\w+ (\+\+|--)', "use foo++, not foo ++"),
Matt Mackall
Introduce check-code.py...
r10281 (r'\w,\w', "missing whitespace after ,"),
Matt Mackall
osutil: fix up check-code issues
r13736 (r'^[^#]\w[+/*]\w', "missing whitespace in expression"),
timeless
check-code: enforce strict spacing around assignment
r27640 (r'\w\s=\s\s+\w', "gratuitous whitespace after ="),
Matt Mackall
Introduce check-code.py...
r10281 (r'^#\s+\w', "use #foo, not # foo"),
(r'[^\n]\Z', "no trailing newline"),
Dan Villiom Podlaski Christiansen
osutil: replace #import with #include, and add a check for it
r13748 (r'^\s*#import\b', "use only #include in standard C code"),
Augie Fackler
check-code: prevent use of strcpy
r28594 (r'strcpy\(', "don't use strcpy, use strlcpy or memcpy"),
Augie Fackler
check-code: also ban strcat...
r28595 (r'strcat\(', "don't use strcat"),
FUJIWARA Katsunori
check-code: centralize rules depending on implementation of repquote...
r29278
# rules depending on implementation of repquote()
Idan Kamara
check-code: separate warnings to avoid repetitive str.startswith
r14009 ],
# warnings
FUJIWARA Katsunori
check-code: centralize rules depending on implementation of repquote...
r29278 [
# rules depending on implementation of repquote()
]
Matt Mackall
Introduce check-code.py...
r10281 ]
cfilters = [
(r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment),
Benoit Boissinot
check-code: improve quote detection regexp, add tests
r10722 (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote),
Matt Mackall
Introduce check-code.py...
r10281 (r'''(#\s*include\s+<)([^>]+)>''', repinclude),
(r'(\()([^)]+\))', repcallspaces),
]
timeless
check-code: check for repo in revlog and ui in util
r14137 inutilpats = [
[
(r'\bui\.', "don't use ui in util"),
],
# warnings
[]
]
inrevlogpats = [
[
(r'\brepo\.', "don't use repo in revlog"),
],
# warnings
[]
]
Steven Brown
check-code: check for consistent usage of the websub filter in hgweb templates...
r21487 webtemplatefilters = []
webtemplatepats = [
[],
[
(r'{desc(\|(?!websub|firstline)[^\|]*)+}',
'follow desc keyword with either firstline or websub'),
]
]
FUJIWARA Katsunori
contrib: check reference to old selenic.com domain...
r30246 allfilesfilters = []
allfilespats = [
[
(r'(http|https)://[a-zA-Z0-9./]*selenic.com/',
'use mercurial-scm.org domain URL'),
FUJIWARA Katsunori
misc: replace domain of mercurial ML address by mercurial-scm.org...
r30888 (r'mercurial@selenic\.com',
'use mercurial-scm.org domain for mercurial ML address'),
FUJIWARA Katsunori
misc: replace domain of mercurial-devel ML address by mercurial-scm.org...
r30890 (r'mercurial-devel@selenic\.com',
'use mercurial-scm.org domain for mercurial-devel ML address'),
FUJIWARA Katsunori
contrib: check reference to old selenic.com domain...
r30246 ],
# warnings
[],
]
Pulkit Goyal
py3: add warnings in check-code related to py3...
r30665 py3pats = [
[
Yuya Nishihara
check-code: ignore re-exports of os.environ in encoding.py...
r32185 (r'os\.environ', "use encoding.environ instead (py3)", r'#.*re-exports'),
Pulkit Goyal
py3: add warnings in check-code related to py3...
r30665 (r'os\.name', "use pycompat.osname instead (py3)"),
Matt Harbison
py3: rename pycompat.getcwd() to encoding.getcwd() (API)...
r39843 (r'os\.getcwd', "use encoding.getcwd instead (py3)", r'#.*re-exports'),
Pulkit Goyal
py3: add warnings in check-code related to py3...
r30665 (r'os\.sep', "use pycompat.ossep instead (py3)"),
(r'os\.pathsep', "use pycompat.ospathsep instead (py3)"),
(r'os\.altsep', "use pycompat.osaltsep instead (py3)"),
(r'sys\.platform', "use pycompat.sysplatform instead (py3)"),
(r'getopt\.getopt', "use pycompat.getoptb instead (py3)"),
Pulkit Goyal
py3: replace pycompat.getenv with encoding.environ.get...
r30820 (r'os\.getenv', "use encoding.environ.get instead"),
(r'os\.setenv', "modifying the environ dict is not preferred"),
Gregory Szorc
check-code: ban use of bare xrange()...
r38807 (r'(?<!pycompat\.)xrange', "use pycompat.xrange instead (py3)"),
Pulkit Goyal
py3: add warnings in check-code related to py3...
r30665 ],
# warnings
[],
]
Matt Mackall
Introduce check-code.py...
r10281 checks = [
Matt Mackall
check-code: look at shebang to identify Python scripts
r21222 ('python', r'.*\.(py|cgi)$', r'^#!.*python', pyfilters, pypats),
Jun Wu
check-code: suggest pycompat.is(posix|windows|darwin)...
r34649 ('python', r'.*\.(py|cgi)$', r'^#!.*python', [], pynfpats),
Jun Wu
checkcode: enforce lowercase for extension docstring title...
r31602 ('python', r'.*hgext.*\.py$', '', [], pyextnfpats),
Yuya Nishihara
check-code: exclude demandimport.py and policy.py from Python 3 checks...
r32184 ('python 3', r'.*(hgext|mercurial)/(?!demandimport|policy|pycompat).*\.py',
'', pyfilters, py3pats),
Matt Mackall
check-code: look at shebang to identify Python scripts
r21222 ('test script', r'(.*/)?test-[^.~]*$', '', testfilters, testpats),
('c', r'.*\.[ch]$', '', cfilters, cpats),
('unified test', r'.*\.t$', '', utestfilters, utestpats),
('layering violation repo in revlog', r'mercurial/revlog\.py', '',
pyfilters, inrevlogpats),
('layering violation ui in util', r'mercurial/util\.py', '', pyfilters,
timeless
check-code: check for repo in revlog and ui in util
r14137 inutilpats),
Matt Mackall
check-code: look at shebang to identify Python scripts
r21222 ('txt', r'.*\.txt$', '', txtfilters, txtpats),
Steven Brown
check-code: check for consistent usage of the websub filter in hgweb templates...
r21487 ('web template', r'mercurial/templates/.*\.tmpl', '',
webtemplatefilters, webtemplatepats),
FUJIWARA Katsunori
contrib: check reference to old selenic.com domain...
r30246 ('all except for .po', r'.*(?<!\.po)$', '',
allfilesfilters, allfilespats),
Matt Mackall
Introduce check-code.py...
r10281 ]
FUJIWARA Katsunori
contrib: make check-code.py check code fragments embedded in test scripts
r41992 # (desc,
# func to pick up embedded code fragments,
# list of patterns to convert target files
# list of patterns to detect errors/warnings)
embeddedchecks = [
('embedded python',
testparseutil.pyembedded, embeddedpyfilters, embeddedpypats)
]
Simon Heimberg
check-code: only fix patterns once...
r19307 def _preparepats():
FUJIWARA Katsunori
contrib: refactor preparation logic for patterns of check-code.py...
r41988 def preparefailandwarn(failandwarn):
Simon Heimberg
check-code: only fix patterns once...
r19307 for pats in failandwarn:
for i, pseq in enumerate(pats):
# fix-up regexes for multi-line searches
Simon Heimberg
cleanup: drop unused variables and an unused import
r19378 p = pseq[0]
Augie Fackler
contrib: fix a subtle bug in check-code's regex rewriting...
r36975 # \s doesn't match \n (done in two steps)
# first, we replace \s that appears in a set already
p = re.sub(r'\[\\s', r'[ \\t', p)
# now we replace other \s instances.
p = re.sub(r'(?<!(\\|\[))\\s', r'[ \\t]', p)
Simon Heimberg
check-code: only fix patterns once...
r19307 # [^...] doesn't match newline
p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p)
Simon Heimberg
check-code: compile all patterns on initialisation...
r19308 pats[i] = (re.compile(p, re.MULTILINE),) + pseq[1:]
FUJIWARA Katsunori
contrib: refactor preparation logic for patterns of check-code.py...
r41988
def preparefilters(filters):
Simon Heimberg
check-code: compile filters when loading
r19309 for i, flt in enumerate(filters):
filters[i] = re.compile(flt[0]), flt[1]
Simon Heimberg
check-code: only fix patterns once...
r19307
FUJIWARA Katsunori
contrib: make check-code.py check code fragments embedded in test scripts
r41992 for cs in (checks, embeddedchecks):
FUJIWARA Katsunori
contrib: refactor preparation logic for patterns of check-code.py...
r41988 for c in cs:
failandwarn = c[-1]
preparefailandwarn(failandwarn)
filters = c[-2]
preparefilters(filters)
Pierre-Yves David
code-code: Add a logfunc argument to checkfile...
r10719 class norepeatlogger(object):
def __init__(self):
self._lastseen = None
Matt Mackall
check-code: add --blame switch
r11604 def log(self, fname, lineno, line, msg, blame):
Pierre-Yves David
code-code: Add a logfunc argument to checkfile...
r10719 """print error related a to given line of a given file.
The faulty line will also be printed but only once in the case
of multiple errors.
Matt Mackall
Introduce check-code.py...
r10281
Pierre-Yves David
code-code: Add a logfunc argument to checkfile...
r10719 :fname: filename
:lineno: line number
:line: actual content of the line
:msg: error message
"""
msgid = fname, lineno, line
if msgid != self._lastseen:
Matt Mackall
check-code: add --blame switch
r11604 if blame:
Pulkit Goyal
check-code: use absolute_import and print_function
r28509 print("%s:%d (%s):" % (fname, lineno, blame))
Matt Mackall
check-code: add --blame switch
r11604 else:
Pulkit Goyal
check-code: use absolute_import and print_function
r28509 print("%s:%d:" % (fname, lineno))
print(" > %s" % line)
Pierre-Yves David
code-code: Add a logfunc argument to checkfile...
r10719 self._lastseen = msgid
Pulkit Goyal
check-code: use absolute_import and print_function
r28509 print(" " + msg)
Pierre-Yves David
code-code: Add a logfunc argument to checkfile...
r10719
_defaultlogger = norepeatlogger()
Matt Mackall
check-code: add --blame switch
r11604 def getblame(f):
lines = []
for l in os.popen('hg annotate -un %s' % f):
start, line = l.split(':', 1)
user, rev = start.split()
lines.append((line[1:-1], user, rev))
return lines
def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False,
Mads Kiilerich
check-code: add --nolineno option for hiding line numbers...
r15502 blame=False, debug=False, lineno=True):
Pierre-Yves David
code-code: Add a logfunc argument to checkfile...
r10719 """checks style and portability of a given file
:f: filepath
:logfunc: function used to report error
logfunc(filename, linenumber, linecontent, errormessage)
Mads Kiilerich
fix trivial spelling errors
r17424 :maxerr: number of error to display before aborting.
Mads Kiilerich
tests: keep track of all check-code.py warnings
r15873 Set to false (default) to report all errors
Pierre-Yves David
check-code: add a return value to checkfile function...
r10720
return True if no error is found, False otherwise.
Pierre-Yves David
code-code: Add a logfunc argument to checkfile...
r10719 """
Pierre-Yves David
check-code: add a return value to checkfile function...
r10720 result = True
Matt Mackall
check-code: look at shebang to identify Python scripts
r21222
try:
timeless
check-code: handle py3 open divergence...
r29145 with opentext(f) as fp:
try:
Martin von Zweigbergk
cleanup: delete lots of unused local variables...
r41401 pre = fp.read()
timeless
check-code: handle py3 open divergence...
r29145 except UnicodeDecodeError as e:
print("%s while reading %s" % (e, f))
return result
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except IOError as e:
Pulkit Goyal
check-code: use absolute_import and print_function
r28509 print("Skipping %s, %s" % (f, str(e).split(':', 1)[0]))
Matt Mackall
check-code: look at shebang to identify Python scripts
r21222 return result
FUJIWARA Katsunori
contrib: factor out actual error check for file data of check-code.py...
r41989 # context information shared while single checkfile() invocation
context = {'blamecache': None}
Matt Mackall
check-code: look at shebang to identify Python scripts
r21222 for name, match, magic, filters, pats in checks:
timeless
check-code: adding debug flag
r14135 if debug:
Pulkit Goyal
check-code: use absolute_import and print_function
r28509 print(name, f)
FUJIWARA Katsunori
check-code: examine magic pattern matching against contents of a file...
r28050 if not (re.match(match, f) or (magic and re.search(magic, pre))):
timeless
check-code: adding debug flag
r14135 if debug:
Pulkit Goyal
check-code: use absolute_import and print_function
r28509 print("Skipping %s for %s it doesn't match %s" % (
name, match, f))
Matt Mackall
Introduce check-code.py...
r10281 continue
Simon Heimberg
check-code: concatenate "check-code" on compile time...
r19382 if "no-" "check-code" in pre:
timeless
check-code: improve test-check-code error diffs...
r27560 # If you're looking at this line, it's because a file has:
# no- check- code
# but the reason to output skipping is to make life for
# tests easier. So, instead of writing it with a normal
# spelling, we write it with the expected spelling from
# tests/test-check-code.t
Pulkit Goyal
check-code: use absolute_import and print_function
r28509 print("Skipping %s it has no-che?k-code (glob)" % f)
Simon Heimberg
check-code: always report when a file is skipped by "no-check-code"...
r20239 return "Skip" # skip checking this file
FUJIWARA Katsunori
contrib: factor out actual error check for file data of check-code.py...
r41989
FUJIWARA Katsunori
contrib: change return value of file checking function of check-code.py...
r41990 fc = _checkfiledata(name, f, pre, filters, pats, context,
logfunc, maxerr, warnings, blame, debug, lineno)
if fc:
FUJIWARA Katsunori
contrib: factor out actual error check for file data of check-code.py...
r41989 result = False
FUJIWARA Katsunori
contrib: make check-code.py check code fragments embedded in test scripts
r41992 if f.endswith('.t') and "no-" "check-code" not in pre:
if debug:
print("Checking embedded code in %s" % (f))
prelines = pre.splitlines()
embeddederros = []
for name, embedded, filters, pats in embeddedchecks:
# "reset curmax at each repetition" treats maxerr as "max
# nubmer of errors in an actual file per entry of
# (embedded)checks"
curmaxerr = maxerr
for found in embedded(f, prelines, embeddederros):
filename, starts, ends, code = found
fc = _checkfiledata(name, f, code, filters, pats, context,
logfunc, curmaxerr, warnings, blame, debug,
lineno, offset=starts - 1)
if fc:
result = False
if curmaxerr:
if fc >= curmaxerr:
break
curmaxerr -= fc
FUJIWARA Katsunori
contrib: factor out actual error check for file data of check-code.py...
r41989 return result
def _checkfiledata(name, f, filedata, filters, pats, context,
FUJIWARA Katsunori
contrib: add line offset information to file check function of check-code.py...
r41991 logfunc, maxerr, warnings, blame, debug, lineno,
offset=None):
FUJIWARA Katsunori
contrib: factor out actual error check for file data of check-code.py...
r41989 """Execute actual error check for file data
:name: of the checking category
:f: filepath
:filedata: content of a file
:filters: to be applied before checking
:pats: to detect errors
:context: a dict of information shared while single checkfile() invocation
Valid keys: 'blamecache'.
:logfunc: function used to report error
logfunc(filename, linenumber, linecontent, errormessage)
:maxerr: number of error to display before aborting, or False to
report all errors
:warnings: whether warning level checks should be applied
:blame: whether blame information should be displayed at error reporting
:debug: whether debug information should be displayed
:lineno: whether lineno should be displayed at error reporting
FUJIWARA Katsunori
contrib: add line offset information to file check function of check-code.py...
r41991 :offset: line number offset of 'filedata' in 'f' for checking
an embedded code fragment, or None (offset=0 is different
from offset=None)
FUJIWARA Katsunori
contrib: factor out actual error check for file data of check-code.py...
r41989
FUJIWARA Katsunori
contrib: change return value of file checking function of check-code.py...
r41990 returns number of detected errors.
FUJIWARA Katsunori
contrib: factor out actual error check for file data of check-code.py...
r41989 """
blamecache = context['blamecache']
FUJIWARA Katsunori
contrib: add line offset information to file check function of check-code.py...
r41991 if offset is None:
lineoffset = 0
else:
lineoffset = offset
FUJIWARA Katsunori
contrib: factor out actual error check for file data of check-code.py...
r41989
fc = 0
pre = post = filedata
if True: # TODO: get rid of this redundant 'if' block
Matt Mackall
Introduce check-code.py...
r10281 for p, r in filters:
post = re.sub(p, r, post)
Simon Heimberg
check-code: automatically preppend "warning: " to all warning messages...
r19422 nerrs = len(pats[0]) # nerr elements are errors
Idan Kamara
check-code: separate warnings to avoid repetitive str.startswith
r14009 if warnings:
pats = pats[0] + pats[1]
else:
pats = pats[0]
Matt Mackall
Introduce check-code.py...
r10281 # print post # uncomment to show filtered version
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281
timeless
check-code: adding debug flag
r14135 if debug:
Pulkit Goyal
check-code: use absolute_import and print_function
r28509 print("Checking %s for %s" % (name, f))
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281
prelines = None
errors = []
Simon Heimberg
check-code: automatically preppend "warning: " to all warning messages...
r19422 for i, pat in enumerate(pats):
Brodie Rao
check-code: ignore naked excepts with a "re-raise" comment...
r16705 if len(pat) == 3:
p, msg, ignore = pat
else:
p, msg = pat
ignore = None
Simon Heimberg
check-code: prepend warning prefix only once, but for each warning...
r20005 if i >= nerrs:
msg = "warning: " + msg
Brodie Rao
check-code: ignore naked excepts with a "re-raise" comment...
r16705
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281 pos = 0
n = 0
Simon Heimberg
check-code: compile all patterns on initialisation...
r19308 for m in p.finditer(post):
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281 if prelines is None:
prelines = pre.splitlines()
postlines = post.splitlines(True)
start = m.start()
while n < len(postlines):
step = len(postlines[n])
if pos + step > start:
break
pos += step
n += 1
l = prelines[n]
Simon Heimberg
check-code: drop now unused check-code-ignore...
r20242 if ignore and re.search(ignore, l, re.MULTILINE):
Simon Heimberg
check-code: print debug output when an ignore pattern matches
r20243 if debug:
Pulkit Goyal
check-code: use absolute_import and print_function
r28509 print("Skipping %s for %s:%s (ignore pattern)" % (
FUJIWARA Katsunori
contrib: add line offset information to file check function of check-code.py...
r41991 name, f, (n + lineoffset)))
Brodie Rao
check-code: ignore naked excepts with a "re-raise" comment...
r16705 continue
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281 bd = ""
if blame:
bd = 'working directory'
FUJIWARA Katsunori
contrib: factor out actual error check for file data of check-code.py...
r41989 if blamecache is None:
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281 blamecache = getblame(f)
FUJIWARA Katsunori
contrib: factor out actual error check for file data of check-code.py...
r41989 context['blamecache'] = blamecache
FUJIWARA Katsunori
contrib: add line offset information to file check function of check-code.py...
r41991 if (n + lineoffset) < len(blamecache):
bl, bu, br = blamecache[(n + lineoffset)]
if offset is None and bl == l:
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281 bd = '%s@%s' % (bu, br)
FUJIWARA Katsunori
contrib: add line offset information to file check function of check-code.py...
r41991 elif offset is not None and bl.endswith(l):
# "offset is not None" means "checking
# embedded code fragment". In this case,
# "l" does not have information about the
# beginning of an *original* line in the
# file (e.g. ' > ').
# Therefore, use "str.endswith()", and
# show "maybe" for a little loose
# examination.
bd = '%s@%s, maybe' % (bu, br)
Simon Heimberg
check-code: prepend warning prefix only once, but for each warning...
r20005
FUJIWARA Katsunori
contrib: add line offset information to file check function of check-code.py...
r41991 errors.append((f, lineno and (n + lineoffset + 1), l, msg, bd))
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281
errors.sort()
for e in errors:
logfunc(*e)
fc += 1
Mads Kiilerich
tests: keep track of all check-code.py warnings
r15873 if maxerr and fc >= maxerr:
Pulkit Goyal
check-code: use absolute_import and print_function
r28509 print(" (too many errors, giving up)")
Matt Mackall
Introduce check-code.py...
r10281 break
Matt Mackall
check-code: support multiline matches like try/except/finally...
r15281
FUJIWARA Katsunori
contrib: change return value of file checking function of check-code.py...
r41990 return fc
Pierre-Yves David
check-code: Add a ``checkfile`` function...
r10717
FUJIWARA Katsunori
check-code: factor out boot procedure into main...
r29568 def main():
Jun Wu
check-code: use "-" to specify a list of files from stdin...
r31824 parser = optparse.OptionParser("%prog [options] [files | -]")
Matt Mackall
check-code: add a warnings level...
r10895 parser.add_option("-w", "--warnings", action="store_true",
help="include warning-level checks")
parser.add_option("-p", "--per-file", type="int",
help="max warnings per file")
Matt Mackall
check-code: add --blame switch
r11604 parser.add_option("-b", "--blame", action="store_true",
help="use annotate to generate blame info")
timeless
check-code: adding debug flag
r14135 parser.add_option("", "--debug", action="store_true",
help="show debug information")
Mads Kiilerich
check-code: add --nolineno option for hiding line numbers...
r15502 parser.add_option("", "--nolineno", action="store_false",
dest='lineno', help="don't show line numbers")
Matt Mackall
check-code: add a warnings level...
r10895
Mads Kiilerich
check-code: add --nolineno option for hiding line numbers...
r15502 parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False,
lineno=True)
Matt Mackall
check-code: add a warnings level...
r10895 (options, args) = parser.parse_args()
if len(args) == 0:
Pierre-Yves David
check-code: Only call check-code if __name__ = "__main__"....
r10716 check = glob.glob("*")
Jun Wu
check-code: use "-" to specify a list of files from stdin...
r31824 elif args == ['-']:
# read file list from stdin
check = sys.stdin.read().splitlines()
Pierre-Yves David
check-code: Only call check-code if __name__ = "__main__"....
r10716 else:
Matt Mackall
check-code: add a warnings level...
r10895 check = args
Matt Mackall
Introduce check-code.py...
r10281
FUJIWARA Katsunori
check-code: move fixing up regexp into main procedure...
r29569 _preparepats()
Mads Kiilerich
check-code: fix return code initialization...
r15544 ret = 0
Pierre-Yves David
check-code: Only call check-code if __name__ = "__main__"....
r10716 for f in check:
Alecs King
check-code: add exit status...
r11816 if not checkfile(f, maxerr=options.per_file, warnings=options.warnings,
Mads Kiilerich
check-code: add --nolineno option for hiding line numbers...
r15502 blame=options.blame, debug=options.debug,
lineno=options.lineno):
Alecs King
check-code: add exit status...
r11816 ret = 1
FUJIWARA Katsunori
check-code: factor out boot procedure into main...
r29568 return ret
if __name__ == "__main__":
sys.exit(main())