Mercurial > hg-stable
annotate contrib/check-code.py @ 16548:e49e039acd5e stable
doc: update copyright years to 2012
I sometimes look at a piece of software and if the man page says
"Copyright 2004", then I'm inclined to think that the project is stale
or that the authors are lazy. Neither is good publicity for us :-)
author | Martin Geisler <mg@aragost.com> |
---|---|
date | Mon, 30 Apr 2012 12:04:30 +0200 |
parents | c326fe884daa |
children | 7f76c97361e0 |
rev | line source |
---|---|
10281 | 1 #!/usr/bin/env python |
2 # | |
3 # check-code - a style and portability checker for Mercurial | |
4 # | |
10290
7cc60de189d7
check-code: fix copyright date
Matt Mackall <mpm@selenic.com>
parents:
10287
diff
changeset
|
5 # Copyright 2010 Matt Mackall <mpm@selenic.com> |
10281 | 6 # |
7 # This software may be used and distributed according to the terms of the | |
8 # GNU General Public License version 2 or any later version. | |
9 | |
11816
e1359ad582f6
check-code: add exit status
Alecs King <alecsk@gmail.com>
parents:
11764
diff
changeset
|
10 import re, glob, os, sys |
13074
637627f31c74
check-code: check for gratuitous whitespace after Python keywords
Thomas Arendsen Hein <thomas@jtah.de>
parents:
13031
diff
changeset
|
11 import keyword |
10895
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
12 import optparse |
10281 | 13 |
14 def repquote(m): | |
10722
c4fb2103e734
check-code: improve quote detection regexp, add tests
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10720
diff
changeset
|
15 t = re.sub(r"\w", "x", m.group('text')) |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
16 t = re.sub(r"[^\s\nx]", "o", t) |
10722
c4fb2103e734
check-code: improve quote detection regexp, add tests
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10720
diff
changeset
|
17 return m.group('quote') + t + m.group('quote') |
10281 | 18 |
10727
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
19 def reppython(m): |
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
20 comment = m.group('comment') |
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
21 if comment: |
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
22 return "#" * len(comment) |
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
23 return repquote(m) |
10281 | 24 |
25 def repcomment(m): | |
26 return m.group(1) + "#" * len(m.group(2)) | |
27 | |
28 def repccomment(m): | |
29 t = re.sub(r"((?<=\n) )|\S", "x", m.group(2)) | |
30 return m.group(1) + t + "*/" | |
31 | |
32 def repcallspaces(m): | |
33 t = re.sub(r"\n\s+", "\n", m.group(2)) | |
34 return m.group(1) + t | |
35 | |
36 def repinclude(m): | |
37 return m.group(1) + "<foo>" | |
38 | |
39 def rephere(m): | |
40 t = re.sub(r"\S", "x", m.group(2)) | |
41 return m.group(1) + t | |
42 | |
43 | |
44 testpats = [ | |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
45 [ |
16495
5f9835ed3d6d
check-code: put grouping around regexps generated from testpats
Mads Kiilerich <mads@kiilerich.com>
parents:
16494
diff
changeset
|
46 (r'pushd|popd', "don't use 'pushd' or 'popd', use 'cd'"), |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
47 (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"), |
15372
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
48 (r'^function', "don't use 'function', use old style"), |
10374
3aa35db5e38c
check-code.py: make help strings consistent
Martin Geisler <mg@lazybytes.net>
parents:
10373
diff
changeset
|
49 (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"), |
16332
42e95631887d
tests: remove sed -i from test-record
Matt Mackall <mpm@selenic.com>
parents:
16249
diff
changeset
|
50 (r'sed.*-i', "don't use 'sed -i', use a temporary file"), |
10373
e4c7972002e4
check-code.py: escape backslash
Mads Kiilerich <mads@kiilerich.com>
parents:
10291
diff
changeset
|
51 (r'echo.*\\n', "don't use 'echo \\n', use printf"), |
11884
932448701e7d
check-code: catch "echo -n" in tests
Martin Geisler <mg@lazybytes.net>
parents:
11599
diff
changeset
|
52 (r'echo -n', "don't use 'echo -n', use printf"), |
15372
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
53 (r'^diff.*-\w*N', "don't use 'diff -N'"), |
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
54 (r'(^| )wc[^|]*$\n(?!.*\(re\))', "filter wc output"), |
10374
3aa35db5e38c
check-code.py: make help strings consistent
Martin Geisler <mg@lazybytes.net>
parents:
10373
diff
changeset
|
55 (r'head -c', "don't use 'head -c', use 'dd'"), |
15389
3bece03bf3c6
tests: use md5sum.py instead of sha1sum, add check
Matt Mackall <mpm@selenic.com>
parents:
15372
diff
changeset
|
56 (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"), |
10374
3aa35db5e38c
check-code.py: make help strings consistent
Martin Geisler <mg@lazybytes.net>
parents:
10373
diff
changeset
|
57 (r'ls.*-\w*R', "don't use 'ls -R', use 'find'"), |
16486
ac987a9d8d49
check-code: 'printf \0' is apparently fine - accept it in check-code
Mads Kiilerich <mads@kiilerich.com>
parents:
16485
diff
changeset
|
58 (r'printf.*\\([1-9]|0\d)', "don't use 'printf \NNN', use Python"), |
10374
3aa35db5e38c
check-code.py: make help strings consistent
Martin Geisler <mg@lazybytes.net>
parents:
10373
diff
changeset
|
59 (r'printf.*\\x', "don't use printf \\x, use Python"), |
10281 | 60 (r'\$\(.*\)', "don't use $(expr), use `expr`"), |
61 (r'rm -rf \*', "don't use naked rm -rf, target a directory"), | |
15372
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
62 (r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w', |
10281 | 63 "use egrep for extended grep syntax"), |
64 (r'/bin/', "don't use explicit paths for tools"), | |
65 (r'\$PWD', "don't use $PWD, use `pwd`"), | |
66 (r'[^\n]\Z', "no trailing newline"), | |
10658
95c7c4b7e67a
test-merge-default and check-code.py: No "export x=x" in sh
Mads Kiilerich <mads@kiilerich.com>
parents:
10451
diff
changeset
|
67 (r'export.*=', "don't export and assign at once"), |
16483
3c4910364797
tests: ^ must be quoted when used on solaris sh
Mads Kiilerich <mads@kiilerich.com>
parents:
16428
diff
changeset
|
68 (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\^', "^ must be quoted"), |
15372
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
69 (r'^source\b', "don't use 'source', use '.'"), |
12367
3acd5f7ab9d0
tests: compatibility fix.
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
12366
diff
changeset
|
70 (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"), |
15364
572c22c88be6
tests: fix check-code detection of anchored expressions, fix echo -n usage
Matt Mackall <mpm@selenic.com>
parents:
15334
diff
changeset
|
71 (r'ls +[^|\n-]+ +-', "options to 'ls' must come before filenames"), |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
72 (r'[^>\n]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"), |
15372
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
73 (r'^stop\(\)', "don't use 'stop' as a shell function name"), |
15282
d4addef0ec74
tests: don't use 'test -e'
Mads Kiilerich <mads@kiilerich.com>
parents:
14978
diff
changeset
|
74 (r'(\[|\btest\b).*-e ', "don't use 'test -e', use 'test -f'"), |
16013
2a1d97630f7f
tests: don't use alias
Mads Kiilerich <mads@kiilerich.com>
parents:
15873
diff
changeset
|
75 (r'^alias\b.*=', "don't use alias, use a function"), |
16485
f48b075ff088
tests: solaris sh can not negate exit status with '!'
Mads Kiilerich <mads@kiilerich.com>
parents:
16483
diff
changeset
|
76 (r'if\s*!', "don't use '!' to negate exit status"), |
16494
e1f0305eabe4
tests: don't use /dev/urandom for largefiles testing
Mads Kiilerich <mads@kiilerich.com>
parents:
16487
diff
changeset
|
77 (r'/dev/u?random', "don't use entropy, use /dev/zero"), |
16496
abbabbbe4ec2
tests: use 'do sleep 0' instead of 'do true', also on first line of command
Mads Kiilerich <mads@kiilerich.com>
parents:
16495
diff
changeset
|
78 (r'do\s*true;\s*done', "don't use true as loop body, use sleep 0"), |
16497
c326fe884daa
tests: avoid tab indent on all kinds of lines of sh commands
Mads Kiilerich <mads@kiilerich.com>
parents:
16496
diff
changeset
|
79 (r'^( *)\t', "don't use tabs to indent"), |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
80 ], |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
81 # warnings |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
82 [] |
10281 | 83 ] |
84 | |
85 testfilters = [ | |
86 (r"( *)(#([^\n]*\S)?)", repcomment), | |
87 (r"<<(\S+)((.|\n)*?\n\1)", rephere), | |
88 ] | |
89 | |
15372
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
90 uprefix = r"^ \$ " |
12364
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
91 utestpats = [ |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
92 [ |
15372
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
93 (r'^(\S| $ ).*(\S[ \t]+|^[ \t]+)\n', "trailing whitespace on non-output"), |
12366
c01dc9087d9a
tests: drop a bunch of sed calls from unified tests
Matt Mackall <mpm@selenic.com>
parents:
12364
diff
changeset
|
94 (uprefix + r'.*\|\s*sed', "use regex test output patterns instead of sed"), |
12364
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
95 (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"), |
15607
fab28a577a38
test-svn-subrepo: fix reference output for svn 1.7
Patrick Mezard <pmezard@gmail.com>
parents:
15389
diff
changeset
|
96 (uprefix + r'.*(?<!\[)\$\?', "explicit exit code checks unnecessary"), |
12364
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
97 (uprefix + r'.*\|\| echo.*(fail|error)', |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
98 "explicit exit code checks unnecessary"), |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
99 (uprefix + r'set -e', "don't use set -e"), |
16487
4fe874697a4d
tests: fix incorrect markup of continued lines of sh commands
Mads Kiilerich <mads@kiilerich.com>
parents:
16486
diff
changeset
|
100 (uprefix + r'\s', "don't indent commands, use > for continued lines"), |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
101 ], |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
102 # warnings |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
103 [] |
12364
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
104 ] |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
105 |
14203
b230922eb0c3
check-code: fix checking for sh style in .t tests
Mads Kiilerich <mads@kiilerich.com>
parents:
14169
diff
changeset
|
106 for i in [0, 1]: |
b230922eb0c3
check-code: fix checking for sh style in .t tests
Mads Kiilerich <mads@kiilerich.com>
parents:
14169
diff
changeset
|
107 for p, m in testpats[i]: |
15372
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
108 if p.startswith(r'^'): |
16495
5f9835ed3d6d
check-code: put grouping around regexps generated from testpats
Mads Kiilerich <mads@kiilerich.com>
parents:
16494
diff
changeset
|
109 p = r"^ \$ (%s)" % p[1:] |
14203
b230922eb0c3
check-code: fix checking for sh style in .t tests
Mads Kiilerich <mads@kiilerich.com>
parents:
14169
diff
changeset
|
110 else: |
16495
5f9835ed3d6d
check-code: put grouping around regexps generated from testpats
Mads Kiilerich <mads@kiilerich.com>
parents:
16494
diff
changeset
|
111 p = r"^ \$ .*(%s)" % p |
14203
b230922eb0c3
check-code: fix checking for sh style in .t tests
Mads Kiilerich <mads@kiilerich.com>
parents:
14169
diff
changeset
|
112 utestpats[i].append((p, m)) |
12364
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
113 |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
114 utestfilters = [ |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
115 (r"( *)(#([^\n]*\S)?)", repcomment), |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
116 ] |
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
117 |
10281 | 118 pypats = [ |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
119 [ |
11568
d5d4e6a30613
check-code: check for tuple parameter unpacking (missing in py3k)
Renato Cunha <renatoc@gmail.com>
parents:
11522
diff
changeset
|
120 (r'^\s*def\s*\w+\s*\(.*,\s*\(', |
d5d4e6a30613
check-code: check for tuple parameter unpacking (missing in py3k)
Renato Cunha <renatoc@gmail.com>
parents:
11522
diff
changeset
|
121 "tuple parameter unpacking not available in Python 3+"), |
d5d4e6a30613
check-code: check for tuple parameter unpacking (missing in py3k)
Renato Cunha <renatoc@gmail.com>
parents:
11522
diff
changeset
|
122 (r'lambda\s*\(.*,.*\)', |
d5d4e6a30613
check-code: check for tuple parameter unpacking (missing in py3k)
Renato Cunha <renatoc@gmail.com>
parents:
11522
diff
changeset
|
123 "tuple parameter unpacking not available in Python 3+"), |
11764
16723af520b0
check-code: added a check for calls to the builtin cmp function
Renato Cunha <renatoc@gmail.com>
parents:
11672
diff
changeset
|
124 (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"), |
11569
f8576644a222
check-code: added check for reduce usage
Renato Cunha <renatoc@gmail.com>
parents:
11568
diff
changeset
|
125 (r'\breduce\s*\(.*', "reduce is not available in Python 3+"), |
11602
ba2520dd1e29
check-code: catch dict.has_key
Martin Geisler <mg@lazybytes.net>
parents:
11601
diff
changeset
|
126 (r'\.has_key\b', "dict.has_key is not available in Python 3+"), |
10281 | 127 (r'^\s*\t', "don't use tabs"), |
10412
5326800d6937
check-code: import some pylint checks
Matt Mackall <mpm@selenic.com>
parents:
10374
diff
changeset
|
128 (r'\S;\s*\n', "semicolon"), |
16234
a6941d7033fa
check-code: check for % inside _()
Matt Mackall <mpm@selenic.com>
parents:
16098
diff
changeset
|
129 (r'[^_]_\("[^"]+"\s*%', "don't use % inside _()"), |
a6941d7033fa
check-code: check for % inside _()
Matt Mackall <mpm@selenic.com>
parents:
16098
diff
changeset
|
130 (r"[^_]_\('[^']+'\s*%", "don't use % inside _()"), |
10281 | 131 (r'\w,\w', "missing whitespace after ,"), |
132 (r'\w[+/*\-<>]\w', "missing whitespace in expression"), | |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
133 (r'^\s+\w+=\w+[^,)\n]$', "missing whitespace in assignment"), |
15372
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
134 (r'(\s+)try:\n((?:\n|\1\s.*\n)+?)\1except.*?:\n' |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
135 r'((?:\n|\1\s.*\n)+?)\1finally:', 'no try/except/finally in Py2.4'), |
10281 | 136 (r'.{85}', "line too long"), |
15372
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
137 (r' x+[xo][\'"]\n\s+[\'"]x', 'string join across lines with no space'), |
10281 | 138 (r'[^\n]\Z', "no trailing newline"), |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
139 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"), |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
140 # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', "don't use underbars in identifiers"), |
15457
1470f8b00694
check-code: enable camelcase check, fix up problems
Matt Mackall <mpm@selenic.com>
parents:
15389
diff
changeset
|
141 (r'^\s+(self\.)?[A-za-z][a-z0-9]+[A-Z]\w* = ', |
1470f8b00694
check-code: enable camelcase check, fix up problems
Matt Mackall <mpm@selenic.com>
parents:
15389
diff
changeset
|
142 "don't use camelcase in identifiers"), |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
143 (r'^\s*(if|while|def|class|except|try)\s[^[\n]*:\s*[^\\n]#\s]+', |
10286 | 144 "linebreak after :"), |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
145 (r'class\s[^( \n]+:', "old-style class, use class foo(object)"), |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
146 (r'class\s[^( \n]+\(\):', |
14763
b071cd58af50
check-code: fix class style checking (with tests)
Thomas Arendsen Hein <thomas@intevation.de>
parents:
14709
diff
changeset
|
147 "class foo() not available in Python 2.4, use class foo(object)"), |
13076
a861c7155f09
check-code: single check for Python keywords used as a function
Thomas Arendsen Hein <thomas@jtah.de>
parents:
13074
diff
changeset
|
148 (r'\b(%s)\(' % '|'.join(keyword.kwlist), |
a861c7155f09
check-code: single check for Python keywords used as a function
Thomas Arendsen Hein <thomas@jtah.de>
parents:
13074
diff
changeset
|
149 "Python keyword is not a function"), |
10412
5326800d6937
check-code: import some pylint checks
Matt Mackall <mpm@selenic.com>
parents:
10374
diff
changeset
|
150 (r',]', "unneeded trailing ',' in list"), |
10281 | 151 # (r'class\s[A-Z][^\(]*\((?!Exception)', |
152 # "don't capitalize non-exception classes"), | |
153 # (r'in range\(', "use xrange"), | |
154 # (r'^\s*print\s+', "avoid using print in core and extensions"), | |
155 (r'[\x80-\xff]', "non-ASCII character literal"), | |
156 (r'("\')\.format\(', "str.format() not available in Python 2.4"), | |
157 (r'^\s*with\s+', "with not available in Python 2.4"), | |
14267
6332c02b3d68
check-code: complain about set.isdisjoint
Matt Mackall <mpm@selenic.com>
parents:
14203
diff
changeset
|
158 (r'\.isdisjoint\(', "set.isdisjoint not available in Python 2.4"), |
13160
07d08c130892
check-code: catch "except as"
Matt Mackall <mpm@selenic.com>
parents:
13076
diff
changeset
|
159 (r'^\s*except.* as .*:', "except as not available in Python 2.4"), |
13161
11eb53464e68
check-code: catch os.path.relpath
Matt Mackall <mpm@selenic.com>
parents:
13160
diff
changeset
|
160 (r'^\s*os\.path\.relpath', "relpath not available in Python 2.4"), |
11345
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
161 (r'(?<!def)\s+(any|all|format)\(', |
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
162 "any/all/format not available in Python 2.4"), |
11522
eaa7666ad53f
check-code: add test for callable
Martin Geisler <mg@aragost.com>
parents:
11345
diff
changeset
|
163 (r'(?<!def)\s+(callable)\(', |
14978
5a0fdc715769
check-code: disallow use of hasattr()
Augie Fackler <durin42@gmail.com>
parents:
14831
diff
changeset
|
164 "callable not available in Python 3, use getattr(f, '__call__', None)"), |
10281 | 165 (r'if\s.*\selse', "if ... else form not available in Python 2.4"), |
13074
637627f31c74
check-code: check for gratuitous whitespace after Python keywords
Thomas Arendsen Hein <thomas@jtah.de>
parents:
13031
diff
changeset
|
166 (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist), |
637627f31c74
check-code: check for gratuitous whitespace after Python keywords
Thomas Arendsen Hein <thomas@jtah.de>
parents:
13031
diff
changeset
|
167 "gratuitous whitespace after Python keyword"), |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
168 (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"), |
10281 | 169 # (r'\s\s=', "gratuitous whitespace before ="), |
11345
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
170 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\S', |
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
171 "missing whitespace around operator"), |
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
172 (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=)\s', |
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
173 "missing whitespace around operator"), |
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
174 (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=)\S', |
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
175 "missing whitespace around operator"), |
16249 | 176 (r'[^^+=*/!<>&| -](\s=|=\s)[^= ]', |
11345
4b81f82b03e3
check-code: reformat long lines
Martin Geisler <mg@aragost.com>
parents:
11343
diff
changeset
|
177 "wrong whitespace around ="), |
10451
63a9bfad50ff
check-code: two more rules
Matt Mackall <mpm@selenic.com>
parents:
10412
diff
changeset
|
178 (r'raise Exception', "don't raise generic exceptions"), |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
179 (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"), |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
180 (r' [=!]=\s+(True|False|None)', |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
181 "comparison with singleton, use 'is' or 'is not' instead"), |
14494
1ffeeb91c55d
check-code: flag 0/1 used as constant Boolean expression
Martin Geisler <mg@lazybytes.net>
parents:
14303
diff
changeset
|
182 (r'^\s*(while|if) [01]:', |
1ffeeb91c55d
check-code: flag 0/1 used as constant Boolean expression
Martin Geisler <mg@lazybytes.net>
parents:
14303
diff
changeset
|
183 "use True/False for constant Boolean expression"), |
16416
c3aedd526d53
mq: replace hasattr() with util.safehasattr(), update check-code.py
Patrick Mezard <patrick@mezard.eu>
parents:
16364
diff
changeset
|
184 (r'(?:(?<!def)\s+|\()hasattr', |
14978
5a0fdc715769
check-code: disallow use of hasattr()
Augie Fackler <durin42@gmail.com>
parents:
14831
diff
changeset
|
185 'hasattr(foo, bar) is broken, use util.safehasattr(foo, bar) instead'), |
14169
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
186 (r'opener\([^)]*\).read\(', |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
187 "use opener.read() instead"), |
15334
24856af7237c
check-code: catch BaseException and os.path.relpath
Matt Mackall <mpm@selenic.com>
parents:
15296
diff
changeset
|
188 (r'BaseException', 'not in Py2.4, use Exception'), |
24856af7237c
check-code: catch BaseException and os.path.relpath
Matt Mackall <mpm@selenic.com>
parents:
15296
diff
changeset
|
189 (r'os\.path\.relpath', 'os.path.relpath is not in Py2.5'), |
14169
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
190 (r'opener\([^)]*\).write\(', |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
191 "use opener.write() instead"), |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
192 (r'[\s\(](open|file)\([^)]*\)\.read\(', |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
193 "use util.readfile() instead"), |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
194 (r'[\s\(](open|file)\([^)]*\)\.write\(', |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
195 "use util.readfile() instead"), |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
196 (r'^[\s\(]*(open(er)?|file)\([^)]*\)', |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
197 "always assign an opened file to a variable, and close it afterwards"), |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
198 (r'[\s\(](open|file)\([^)]*\)\.', |
1b4b82063ce2
check-code: disallow calling opener(...).read() and opener(..).write()
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
14137
diff
changeset
|
199 "always assign an opened file to a variable, and close it afterwards"), |
14549
48ec0763afbb
check-code: catch misspellings of descendant
Matt Mackall <mpm@selenic.com>
parents:
14494
diff
changeset
|
200 (r'(?i)descendent', "the proper spelling is descendAnt"), |
14709
6c7283faa967
check-code: don't mark debug messages for translation
Matt Mackall <mpm@selenic.com>
parents:
14549
diff
changeset
|
201 (r'\.debug\(\_', "don't mark debug messages for translation"), |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
202 ], |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
203 # warnings |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
204 [ |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
205 (r'.{81}', "warning: line over 80 characters"), |
14005
bb391e0515ba
check-code: warn about naked except clauses
Idan Kamara <idankk86@gmail.com>
parents:
13748
diff
changeset
|
206 (r'^\s*except:$', "warning: naked except clause"), |
11599
6fcc066c0c2c
check-code: warn about untranslated ui.warn calls
Martin Geisler <mg@lazybytes.net>
parents:
11522
diff
changeset
|
207 (r'ui\.(status|progress|write|note|warn)\([\'\"]x', |
10895
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
208 "warning: unwrapped ui message"), |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
209 ] |
10281 | 210 ] |
211 | |
212 pyfilters = [ | |
10727
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
213 (r"""(?msx)(?P<comment>\#.*?$)| |
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
214 ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!"))) |
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
215 (?P<text>(([^\\]|\\.)*?)) |
62b8f15683f2
check-code: more tests and more robust python filtering
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10723
diff
changeset
|
216 (?P=quote))""", reppython), |
10281 | 217 ] |
218 | |
219 cpats = [ | |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
220 [ |
10281 | 221 (r'//', "don't use //-style comments"), |
222 (r'^ ', "don't use spaces to indent"), | |
223 (r'\S\t', "don't use tabs except for indent"), | |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
224 (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"), |
10281 | 225 (r'.{85}', "line too long"), |
226 (r'(while|if|do|for)\(', "use space after while/if/do/for"), | |
227 (r'return\(', "return is not a function"), | |
228 (r' ;', "no space before ;"), | |
229 (r'\w+\* \w+', "use int *foo, not int* foo"), | |
230 (r'\([^\)]+\) \w+', "use (int)foo, not (int) foo"), | |
16413
1a420761fcb7
check-code: avoid false-positive on ++
Matt Mackall <mpm@selenic.com>
parents:
16373
diff
changeset
|
231 (r'\w+ (\+\+|--)', "use foo++, not foo ++"), |
10281 | 232 (r'\w,\w', "missing whitespace after ,"), |
13736
f3c4421e121c
osutil: fix up check-code issues
Matt Mackall <mpm@selenic.com>
parents:
13524
diff
changeset
|
233 (r'^[^#]\w[+/*]\w', "missing whitespace in expression"), |
10281 | 234 (r'^#\s+\w', "use #foo, not # foo"), |
235 (r'[^\n]\Z', "no trailing newline"), | |
13748
26f8844d1757
osutil: replace #import with #include, and add a check for it
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13736
diff
changeset
|
236 (r'^\s*#import\b', "use only #include in standard C code"), |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
237 ], |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
238 # warnings |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
239 [] |
10281 | 240 ] |
241 | |
242 cfilters = [ | |
243 (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment), | |
10722
c4fb2103e734
check-code: improve quote detection regexp, add tests
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents:
10720
diff
changeset
|
244 (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote), |
10281 | 245 (r'''(#\s*include\s+<)([^>]+)>''', repinclude), |
246 (r'(\()([^)]+\))', repcallspaces), | |
247 ] | |
248 | |
14137
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
249 inutilpats = [ |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
250 [ |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
251 (r'\bui\.', "don't use ui in util"), |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
252 ], |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
253 # warnings |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
254 [] |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
255 ] |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
256 |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
257 inrevlogpats = [ |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
258 [ |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
259 (r'\brepo\.', "don't use repo in revlog"), |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
260 ], |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
261 # warnings |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
262 [] |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
263 ] |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
264 |
10281 | 265 checks = [ |
266 ('python', r'.*\.(py|cgi)$', pyfilters, pypats), | |
267 ('test script', r'(.*/)?test-[^.~]*$', testfilters, testpats), | |
268 ('c', r'.*\.c$', cfilters, cpats), | |
12364
e128fa4615f2
check-code: add some basic support for unified tests
Matt Mackall <mpm@selenic.com>
parents:
11886
diff
changeset
|
269 ('unified test', r'.*\.t$', utestfilters, utestpats), |
14137
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
270 ('layering violation repo in revlog', r'mercurial/revlog\.py', pyfilters, |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
271 inrevlogpats), |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
272 ('layering violation ui in util', r'mercurial/util\.py', pyfilters, |
83a94c2fe6f4
check-code: check for repo in revlog and ui in util
timeless <timeless@mozdev.org>
parents:
14136
diff
changeset
|
273 inutilpats), |
10281 | 274 ] |
275 | |
10719
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
276 class norepeatlogger(object): |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
277 def __init__(self): |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
278 self._lastseen = None |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
279 |
11604
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
280 def log(self, fname, lineno, line, msg, blame): |
10719
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
281 """print error related a to given line of a given file. |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
282 |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
283 The faulty line will also be printed but only once in the case |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
284 of multiple errors. |
10281 | 285 |
10719
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
286 :fname: filename |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
287 :lineno: line number |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
288 :line: actual content of the line |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
289 :msg: error message |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
290 """ |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
291 msgid = fname, lineno, line |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
292 if msgid != self._lastseen: |
11604
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
293 if blame: |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
294 print "%s:%d (%s):" % (fname, lineno, blame) |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
295 else: |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
296 print "%s:%d:" % (fname, lineno) |
10719
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
297 print " > %s" % line |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
298 self._lastseen = msgid |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
299 print " " + msg |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
300 |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
301 _defaultlogger = norepeatlogger() |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
302 |
11604
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
303 def getblame(f): |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
304 lines = [] |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
305 for l in os.popen('hg annotate -un %s' % f): |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
306 start, line = l.split(':', 1) |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
307 user, rev = start.split() |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
308 lines.append((line[1:-1], user, rev)) |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
309 return lines |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
310 |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
311 def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False, |
15502
7917a104a285
check-code: add --nolineno option for hiding line numbers
Mads Kiilerich <mads@kiilerich.com>
parents:
15457
diff
changeset
|
312 blame=False, debug=False, lineno=True): |
10719
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
313 """checks style and portability of a given file |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
314 |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
315 :f: filepath |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
316 :logfunc: function used to report error |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
317 logfunc(filename, linenumber, linecontent, errormessage) |
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
318 :maxerr: number of error to display before arborting. |
15873
a153a86a472c
tests: keep track of all check-code.py warnings
Mads Kiilerich <mads@kiilerich.com>
parents:
15611
diff
changeset
|
319 Set to false (default) to report all errors |
10720
fbcccf9ec58f
check-code: add a return value to checkfile function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10719
diff
changeset
|
320 |
fbcccf9ec58f
check-code: add a return value to checkfile function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10719
diff
changeset
|
321 return True if no error is found, False otherwise. |
10719
3be9ae49b628
code-code: Add a logfunc argument to checkfile
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10718
diff
changeset
|
322 """ |
11604
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
323 blamecache = None |
10720
fbcccf9ec58f
check-code: add a return value to checkfile function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10719
diff
changeset
|
324 result = True |
10281 | 325 for name, match, filters, pats in checks: |
14135
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
326 if debug: |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
327 print name, f |
10281 | 328 fc = 0 |
329 if not re.match(match, f): | |
14135
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
330 if debug: |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
331 print "Skipping %s for %s it doesn't match %s" % ( |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
332 name, match, f) |
10281 | 333 continue |
13400
14f3795a5ed7
explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13301
diff
changeset
|
334 fp = open(f) |
14f3795a5ed7
explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13301
diff
changeset
|
335 pre = post = fp.read() |
14f3795a5ed7
explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents:
13301
diff
changeset
|
336 fp.close() |
10287
5da892be3497
check-code: add some ignore hints
Matt Mackall <mpm@selenic.com>
parents:
10286
diff
changeset
|
337 if "no-" + "check-code" in pre: |
14135
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
338 if debug: |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
339 print "Skipping %s for %s it has no- and check-code" % ( |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
340 name, f) |
10287
5da892be3497
check-code: add some ignore hints
Matt Mackall <mpm@selenic.com>
parents:
10286
diff
changeset
|
341 break |
10281 | 342 for p, r in filters: |
343 post = re.sub(p, r, post) | |
14009
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
344 if warnings: |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
345 pats = pats[0] + pats[1] |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
346 else: |
64de9ca66511
check-code: separate warnings to avoid repetitive str.startswith
Idan Kamara <idankk86@gmail.com>
parents:
14005
diff
changeset
|
347 pats = pats[0] |
10281 | 348 # print post # uncomment to show filtered version |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
349 |
14135
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
350 if debug: |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
351 print "Checking %s for %s" % (name, f) |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
352 |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
353 prelines = None |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
354 errors = [] |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
355 for p, msg in pats: |
15372
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
356 # fix-up regexes for multiline searches |
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
357 po = p |
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
358 # \s doesn't match \n |
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
359 p = re.sub(r'(?<!\\)\\s', r'[ \\t]', p) |
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
360 # [^...] doesn't match newline |
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
361 p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p) |
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
362 |
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
363 #print po, '=>', p |
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
364 |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
365 pos = 0 |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
366 n = 0 |
15372
695ac6aca77f
check-code: fix issues with finding patterns in unified tests, fix tests
Matt Mackall <mpm@selenic.com>
parents:
15364
diff
changeset
|
367 for m in re.finditer(p, post, re.MULTILINE): |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
368 if prelines is None: |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
369 prelines = pre.splitlines() |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
370 postlines = post.splitlines(True) |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
371 |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
372 start = m.start() |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
373 while n < len(postlines): |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
374 step = len(postlines[n]) |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
375 if pos + step > start: |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
376 break |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
377 pos += step |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
378 n += 1 |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
379 l = prelines[n] |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
380 |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
381 if "check-code" + "-ignore" in l: |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
382 if debug: |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
383 print "Skipping %s for %s:%s (check-code -ignore)" % ( |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
384 name, f, n) |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
385 continue |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
386 bd = "" |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
387 if blame: |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
388 bd = 'working directory' |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
389 if not blamecache: |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
390 blamecache = getblame(f) |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
391 if n < len(blamecache): |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
392 bl, bu, br = blamecache[n] |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
393 if bl == l: |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
394 bd = '%s@%s' % (bu, br) |
15502
7917a104a285
check-code: add --nolineno option for hiding line numbers
Mads Kiilerich <mads@kiilerich.com>
parents:
15457
diff
changeset
|
395 errors.append((f, lineno and n + 1, l, msg, bd)) |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
396 result = False |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
397 |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
398 errors.sort() |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
399 for e in errors: |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
400 logfunc(*e) |
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
401 fc += 1 |
15873
a153a86a472c
tests: keep track of all check-code.py warnings
Mads Kiilerich <mads@kiilerich.com>
parents:
15611
diff
changeset
|
402 if maxerr and fc >= maxerr: |
10281 | 403 print " (too many errors, giving up)" |
404 break | |
15281
aeeb2afcdc25
check-code: support multiline matches like try/except/finally
Matt Mackall <mpm@selenic.com>
parents:
14978
diff
changeset
|
405 |
10720
fbcccf9ec58f
check-code: add a return value to checkfile function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10719
diff
changeset
|
406 return result |
10717
b1f4fcef99b3
check-code: Add a ``checkfile`` function
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10716
diff
changeset
|
407 |
10716
5f92bde72eef
check-code: Only call check-code if __name__ = "__main__".
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10707
diff
changeset
|
408 if __name__ == "__main__": |
10895
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
409 parser = optparse.OptionParser("%prog [options] [files]") |
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
410 parser.add_option("-w", "--warnings", action="store_true", |
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
411 help="include warning-level checks") |
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
412 parser.add_option("-p", "--per-file", type="int", |
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
413 help="max warnings per file") |
11604
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
414 parser.add_option("-b", "--blame", action="store_true", |
c5d40818b270
check-code: add --blame switch
Matt Mackall <mpm@selenic.com>
parents:
11602
diff
changeset
|
415 help="use annotate to generate blame info") |
14135
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
416 parser.add_option("", "--debug", action="store_true", |
673abd432104
check-code: adding debug flag
timeless <timeless@mozdev.org>
parents:
14009
diff
changeset
|
417 help="show debug information") |
15502
7917a104a285
check-code: add --nolineno option for hiding line numbers
Mads Kiilerich <mads@kiilerich.com>
parents:
15457
diff
changeset
|
418 parser.add_option("", "--nolineno", action="store_false", |
7917a104a285
check-code: add --nolineno option for hiding line numbers
Mads Kiilerich <mads@kiilerich.com>
parents:
15457
diff
changeset
|
419 dest='lineno', help="don't show line numbers") |
10895
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
420 |
15502
7917a104a285
check-code: add --nolineno option for hiding line numbers
Mads Kiilerich <mads@kiilerich.com>
parents:
15457
diff
changeset
|
421 parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False, |
7917a104a285
check-code: add --nolineno option for hiding line numbers
Mads Kiilerich <mads@kiilerich.com>
parents:
15457
diff
changeset
|
422 lineno=True) |
10895
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
423 (options, args) = parser.parse_args() |
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
424 |
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
425 if len(args) == 0: |
10716
5f92bde72eef
check-code: Only call check-code if __name__ = "__main__".
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10707
diff
changeset
|
426 check = glob.glob("*") |
5f92bde72eef
check-code: Only call check-code if __name__ = "__main__".
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10707
diff
changeset
|
427 else: |
10895
217557b26bc7
check-code: add a warnings level
Matt Mackall <mpm@selenic.com>
parents:
10814
diff
changeset
|
428 check = args |
10281 | 429 |
15544
53ef627cda30
check-code: fix return code initialization
Mads Kiilerich <mads@kiilerich.com>
parents:
15502
diff
changeset
|
430 ret = 0 |
10716
5f92bde72eef
check-code: Only call check-code if __name__ = "__main__".
Pierre-Yves David <pierre-yves.david@logilab.fr>
parents:
10707
diff
changeset
|
431 for f in check: |
11816
e1359ad582f6
check-code: add exit status
Alecs King <alecsk@gmail.com>
parents:
11764
diff
changeset
|
432 if not checkfile(f, maxerr=options.per_file, warnings=options.warnings, |
15502
7917a104a285
check-code: add --nolineno option for hiding line numbers
Mads Kiilerich <mads@kiilerich.com>
parents:
15457
diff
changeset
|
433 blame=options.blame, debug=options.debug, |
7917a104a285
check-code: add --nolineno option for hiding line numbers
Mads Kiilerich <mads@kiilerich.com>
parents:
15457
diff
changeset
|
434 lineno=options.lineno): |
11816
e1359ad582f6
check-code: add exit status
Alecs King <alecsk@gmail.com>
parents:
11764
diff
changeset
|
435 ret = 1 |
e1359ad582f6
check-code: add exit status
Alecs King <alecsk@gmail.com>
parents:
11764
diff
changeset
|
436 sys.exit(ret) |