1  $ cat > correct.py <<NO_CHECK_EOF
2  > def toto(arg1, arg2):
3  >     del arg2
4  >     return (5 + 6, 9)
5  > NO_CHECK_EOF
6  $ cat > wrong.py <<NO_CHECK_EOF
7  > def toto( arg1, arg2):
8  >     del(arg2)
9  >     return ( 5+6, 9)
10  > def badwrap():
11  >     return 1 + \\
12  >        2
13  > NO_CHECK_EOF
14  $ cat > quote.py <<NO_CHECK_EOF
15  > # let's use quote in comments
16  > (''' ( 4x5 )
17  > but """\\''' and finally''',
18  > """let's fool checkpatch""", '1+2',
19  > '"""', 42+1, """and
20  > ( 4-1 ) """, "( 1+1 )\" and ")
21  > a, '\\\\\\\\', "\\\\\\" x-2", "c-1"
22  > NO_CHECK_EOF
23  $ cat > classstyle.py <<NO_CHECK_EOF
24  > class newstyle_class(object):
25  >     pass
26  >
27  > class oldstyle_class:
28  >     pass
29  >
30  > class empty():
31  >     pass
32  >
33  > no_class = 1:
34  >     pass
35  > NO_CHECK_EOF
36  $ check_code="$TESTDIR"/../contrib/check-code.py
37  $ "$check_code" ./wrong.py ./correct.py ./quote.py ./classstyle.py
38  ./wrong.py:1:
39   > def toto( arg1, arg2):
40   gratuitous whitespace in () or []
41  ./wrong.py:2:
42   >     del(arg2)
43   Python keyword is not a function
44  ./wrong.py:3:
45   >     return ( 5+6, 9)
46   gratuitous whitespace in () or []
47   missing whitespace in expression
48  ./wrong.py:5:
49   >     return 1 + \
50   Use () to wrap long lines in Python, not \
51  ./quote.py:5:
52   > '"""', 42+1, """and
53   missing whitespace in expression
54  ./classstyle.py:4:
55   > class oldstyle_class:
56   old-style class, use class foo(object)
57  ./classstyle.py:7:
58   > class empty():
59   class foo() creates old style object, use class foo(object)
60  [1]
61  $ cat > python3-compat.py << NO_CHECK_EOF
62  > foo <> bar
63  > reduce(lambda a, b: a + b, [1, 2, 3, 4])
64  > dict(key=value)
65  > NO_CHECK_EOF
66  $ "$check_code" python3-compat.py
67  python3-compat.py:1:
68   > foo <> bar
69   <> operator is not available in Python 3+, use !=
70  python3-compat.py:2:
71   > reduce(lambda a, b: a + b, [1, 2, 3, 4])
72   reduce is not available in Python 3+
73  python3-compat.py:3:
74   > dict(key=value)
75   dict() is different in Py2 and 3 and is slower than {}
76  [1]
77
78  $ cat > foo.c <<NO_CHECK_EOF
79  > void narf() {
80  > 	strcpy(foo, bar);
81  > 	// strcpy_s is okay, but this comment is not
82  > 	strcpy_s(foo, bar);
83  > }
84  > NO_CHECK_EOF
85  $ "$check_code" ./foo.c
86  ./foo.c:2:
87   > 	strcpy(foo, bar);
88   don't use strcpy, use strlcpy or memcpy
89  ./foo.c:3:
90   > 	// strcpy_s is okay, but this comment is not
91   don't use //-style comments
92  [1]
93
94  $ cat > is-op.py <<NO_CHECK_EOF
95  > # is-operator comparing number or string literal
96  > x = None
97  > y = x is 'foo'
98  > y = x is "foo"
99  > y = x is 5346
100  > y = x is -6
101  > y = x is not 'foo'
102  > y = x is not "foo"
103  > y = x is not 5346
104  > y = x is not -6
105  > NO_CHECK_EOF
106
107  $ "$check_code" ./is-op.py
108  ./is-op.py:3:
109   > y = x is 'foo'
110   object comparison with literal
111  ./is-op.py:4:
112   > y = x is "foo"
113   object comparison with literal
114  ./is-op.py:5:
115   > y = x is 5346
116   object comparison with literal
117  ./is-op.py:6:
118   > y = x is -6
119   object comparison with literal
120  ./is-op.py:7:
121   > y = x is not 'foo'
122   object comparison with literal
123  ./is-op.py:8:
124   > y = x is not "foo"
125   object comparison with literal
126  ./is-op.py:9:
127   > y = x is not 5346
128   object comparison with literal
129  ./is-op.py:10:
130   > y = x is not -6
131   object comparison with literal
132  [1]
133
134  $ cat > for-nolineno.py <<NO_CHECK_EOF
135  > except:
136  > NO_CHECK_EOF
137  $ "$check_code" for-nolineno.py --nolineno
138  for-nolineno.py:0:
139   > except:
140   naked except clause
141  [1]
142
143  $ cat > warning.t <<NO_CHECK_EOF
144  >   $ function warnonly {
145  >   > }
146  >   $ diff -N aaa
147  >   $ function onwarn {}
148  > NO_CHECK_EOF
149  $ "$check_code" warning.t
150  $ "$check_code" --warn warning.t
151  warning.t:1:
152   >   $ function warnonly {
153   warning: don't use 'function', use old style
154  warning.t:3:
155   >   $ diff -N aaa
156   warning: don't use 'diff -N'
157  warning.t:4:
158   >   $ function onwarn {}
159   warning: don't use 'function', use old style
160  [1]
161  $ cat > error.t <<NO_CHECK_EOF
162  >   $ [ foo == bar ]
163  > NO_CHECK_EOF
164  $ "$check_code" error.t
165  error.t:1:
166   >   $ [ foo == bar ]
167   [ foo == bar ] is a bashism, use [ foo = bar ] instead
168  [1]
169  $ rm error.t
170  $ cat > raise-format.py <<NO_CHECK_EOF
171  > raise SomeException, message
172  > # this next line is okay
173  > raise SomeException(arg1, arg2)
174  > NO_CHECK_EOF
175  $ "$check_code" not-existing.py raise-format.py
176  Skipping*not-existing.py* (glob)
177  raise-format.py:1:
178   > raise SomeException, message
179   don't use old-style two-argument raise, use Exception(message)
180  [1]
181
182  $ cat <<NO_CHECK_EOF > tab.t
183  > 	indent
184  >   > 	heredoc
185  > NO_CHECK_EOF
186  $ "$check_code" tab.t
187  tab.t:1:
188   > 	indent
189   don't use tabs to indent
190  [1]
191  $ rm tab.t
192
193  $ cat > rst.py <<NO_CHECK_EOF
194  > """problematic rst text
195  >
196  > .. note::
197  >     wrong
198  > """
199  >
200  > '''
201  >
202  > .. note::
203  >
204  >     valid
205  >
206  > new text
207  >
208  >     .. note::
209  >
210  >         also valid
211  > '''
212  >
213  > """mixed
214  >
215  > .. note::
216  >
217  >   good
218  >
219  >     .. note::
220  >         plus bad
221  > """
222  > NO_CHECK_EOF
223  $ $check_code -w rst.py
224  rst.py:3:
225   > .. note::
226   warning: add two newlines after '.. note::'
227  rst.py:26:
228   >     .. note::
229   warning: add two newlines after '.. note::'
230  [1]
231
232  $ cat > ./map-inside-gettext.py <<NO_CHECK_EOF
233  > print(_("map inside gettext %s" % v))
234  >
235  > print(_("concatenating " " by " " space %s" % v))
236  > print(_("concatenating " + " by " + " '+' %s" % v))
237  >
238  > print(_("mapping operation in different line %s"
239  >         % v))
240  >
241  > print(_(
242  >         "leading spaces inside of '(' %s" % v))
243  > NO_CHECK_EOF
244  $ "$check_code" ./map-inside-gettext.py
245  ./map-inside-gettext.py:1:
246   > print(_("map inside gettext %s" % v))
247   don't use % inside _()
248  ./map-inside-gettext.py:3:
249   > print(_("concatenating " " by " " space %s" % v))
250   don't use % inside _()
251  ./map-inside-gettext.py:4:
252   > print(_("concatenating " + " by " + " '+' %s" % v))
253   don't use % inside _()
254  ./map-inside-gettext.py:6:
255   > print(_("mapping operation in different line %s"
256   don't use % inside _()
257  ./map-inside-gettext.py:9:
258   > print(_(
259   don't use % inside _()
260  [1]
261
262web templates
263
264  $ mkdir -p mercurial/templates
265  $ cat > mercurial/templates/example.tmpl <<NO_CHECK_EOF
266  > {desc}
267  > {desc|escape}
268  > {desc|firstline}
269  > {desc|websub}
270  > NO_CHECK_EOF
271
272  $ "$check_code" --warnings mercurial/templates/example.tmpl
273  mercurial/templates/example.tmpl:2:
274   > {desc|escape}
275   warning: follow desc keyword with either firstline or websub
276  [1]
277
278'string join across lines with no space' detection
279
280  $ cat > stringjoin.py <<NO_CHECK_EOF
281  > foo = (' foo'
282  >        'bar foo.'
283  >        'bar foo:'
284  >        'bar foo@'
285  >        'bar foo%'
286  >        'bar foo*'
287  >        'bar foo+'
288  >        'bar foo-'
289  >        'bar')
290  > NO_CHECK_EOF
291
292'missing _() in ui message' detection
293
294  $ cat > uigettext.py <<NO_CHECK_EOF
295  > ui.status("% 10s %05d % -3.2f %*s %%"
296  >           # this use '\\\\' instead of '\\', because the latter in
297  >           # heredoc on shell becomes just '\'
298  >           '\\\\ \n \t \0'
299  >           """12345
300  >           """
301  >           '''.:*+-=
302  >           ''' "%-6d \n 123456 .:*+-= foobar")
303  > NO_CHECK_EOF
304
305superfluous pass
306
307  $ cat > superfluous_pass.py <<NO_CHECK_EOF
308  > # correct examples
309  > if foo:
310  >     pass
311  > else:
312  >     # comment-only line means still need pass
313  >     pass
314  > def nothing():
315  >     pass
316  > class empty(object):
317  >     pass
318  > if whatever:
319  >     passvalue(value)
320  > # bad examples
321  > if foo:
322  >     "foo"
323  >     pass
324  > else: # trailing comment doesn't fool checker
325  >     wat()
326  >     pass
327  > def nothing():
328  >     "docstring means no pass"
329  >     pass
330  > class empty(object):
331  >     """multiline
332  >     docstring also
333  >     means no pass"""
334  >     pass
335  > NO_CHECK_EOF
336
337(Checking multiple invalid files at once examines whether caching
338translation table for repquote() works as expected or not. All files
339should break rules depending on result of repquote(), in this case)
340
341  $ "$check_code" stringjoin.py uigettext.py superfluous_pass.py
342  stringjoin.py:1:
343   > foo = (' foo'
344   string join across lines with no space
345  stringjoin.py:2:
346   >        'bar foo.'
347   string join across lines with no space
348  stringjoin.py:3:
349   >        'bar foo:'
350   string join across lines with no space
351  stringjoin.py:4:
352   >        'bar foo@'
353   string join across lines with no space
354  stringjoin.py:5:
355   >        'bar foo%'
356   string join across lines with no space
357  stringjoin.py:6:
358   >        'bar foo*'
359   string join across lines with no space
360  stringjoin.py:7:
361   >        'bar foo+'
362   string join across lines with no space
363  stringjoin.py:8:
364   >        'bar foo-'
365   string join across lines with no space
366  uigettext.py:1:
367   > ui.status("% 10s %05d % -3.2f %*s %%"
368   missing _() in ui message (use () to hide false-positives)
369  superfluous_pass.py:14:
370   > if foo:
371   omit superfluous pass
372  superfluous_pass.py:17:
373   > else: # trailing comment doesn't fool checker
374   omit superfluous pass
375  superfluous_pass.py:20:
376   > def nothing():
377   omit superfluous pass
378  superfluous_pass.py:23:
379   > class empty(object):
380   omit superfluous pass
381  [1]
382
383Check code fragments embedded in test script
384
385  $ cat > embedded-code.t <<NO_CHECK_EOF
386  > code fragment in doctest style
387  >   >>> x = (1,2)
388  >   ...
389  >   ... x = (1,2)
390  >
391  > code fragment in heredoc style
392  >   $ python <<EOF
393  >   > x = (1,2)
394  >   > EOF
395  >
396  > code fragment in file heredoc style
397  >   $ python > file.py <<EOF
398  >   > x = (1,2)
399  >   > EOF
400  > NO_CHECK_EOF
401  $ "$check_code" embedded-code.t
402  embedded-code.t:2:
403   > x = (1,2)
404   missing whitespace after ,
405  embedded-code.t:4:
406   > x = (1,2)
407   missing whitespace after ,
408  embedded-code.t:8:
409   > x = (1,2)
410   missing whitespace after ,
411  embedded-code.t:13:
412   > x = (1,2)
413   missing whitespace after ,
414  [1]
415
416"max warnings per file" is shared by all embedded code fragments
417
418  $ "$check_code" --per-file=3 embedded-code.t
419  embedded-code.t:2:
420   > x = (1,2)
421   missing whitespace after ,
422  embedded-code.t:4:
423   > x = (1,2)
424   missing whitespace after ,
425  embedded-code.t:8:
426   > x = (1,2)
427   missing whitespace after ,
428   (too many errors, giving up)
429  [1]
430