comparison contrib/check-code.py @ 21926:6c36dc6cd61a stable 3.1-rc

merge default into stable for 3.1 code freeze
author Matt Mackall <mpm@selenic.com>
date Sat, 19 Jul 2014 00:10:22 -0500
parents fb16f6da5b3b
children a5168eb9b2bc
comparison
equal deleted inserted replaced
21876:584bbfd1b50d 21926:6c36dc6cd61a
245 (r'\.isdisjoint\(', "set.isdisjoint not available in Python 2.4"), 245 (r'\.isdisjoint\(', "set.isdisjoint not available in Python 2.4"),
246 (r'^\s*except.* as .*:', "except as not available in Python 2.4"), 246 (r'^\s*except.* as .*:', "except as not available in Python 2.4"),
247 (r'^\s*os\.path\.relpath', "relpath not available in Python 2.4"), 247 (r'^\s*os\.path\.relpath', "relpath not available in Python 2.4"),
248 (r'(?<!def)\s+(any|all|format)\(', 248 (r'(?<!def)\s+(any|all|format)\(',
249 "any/all/format not available in Python 2.4", 'no-py24'), 249 "any/all/format not available in Python 2.4", 'no-py24'),
250 (r'(?<!def)\s+(callable)\(',
251 "callable not available in Python 3, use getattr(f, '__call__', None)"),
252 (r'if\s.*\selse', "if ... else form not available in Python 2.4"), 250 (r'if\s.*\selse', "if ... else form not available in Python 2.4"),
253 (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist), 251 (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist),
254 "gratuitous whitespace after Python keyword"), 252 "gratuitous whitespace after Python keyword"),
255 (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"), 253 (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"),
256 # (r'\s\s=', "gratuitous whitespace before ="), 254 # (r'\s\s=', "gratuitous whitespace before ="),
365 ], 363 ],
366 # warnings 364 # warnings
367 [] 365 []
368 ] 366 ]
369 367
368 webtemplatefilters = []
369
370 webtemplatepats = [
371 [],
372 [
373 (r'{desc(\|(?!websub|firstline)[^\|]*)+}',
374 'follow desc keyword with either firstline or websub'),
375 ]
376 ]
377
370 checks = [ 378 checks = [
371 ('python', r'.*\.(py|cgi)$', pyfilters, pypats), 379 ('python', r'.*\.(py|cgi)$', r'^#!.*python', pyfilters, pypats),
372 ('test script', r'(.*/)?test-[^.~]*$', testfilters, testpats), 380 ('test script', r'(.*/)?test-[^.~]*$', '', testfilters, testpats),
373 ('c', r'.*\.[ch]$', cfilters, cpats), 381 ('c', r'.*\.[ch]$', '', cfilters, cpats),
374 ('unified test', r'.*\.t$', utestfilters, utestpats), 382 ('unified test', r'.*\.t$', '', utestfilters, utestpats),
375 ('layering violation repo in revlog', r'mercurial/revlog\.py', pyfilters, 383 ('layering violation repo in revlog', r'mercurial/revlog\.py', '',
376 inrevlogpats), 384 pyfilters, inrevlogpats),
377 ('layering violation ui in util', r'mercurial/util\.py', pyfilters, 385 ('layering violation ui in util', r'mercurial/util\.py', '', pyfilters,
378 inutilpats), 386 inutilpats),
379 ('txt', r'.*\.txt$', txtfilters, txtpats), 387 ('txt', r'.*\.txt$', '', txtfilters, txtpats),
388 ('web template', r'mercurial/templates/.*\.tmpl', '',
389 webtemplatefilters, webtemplatepats),
380 ] 390 ]
381 391
382 def _preparepats(): 392 def _preparepats():
383 for c in checks: 393 for c in checks:
384 failandwarn = c[-1] 394 failandwarn = c[-1]
390 p = re.sub(r'(?<!\\)\\s', r'[ \\t]', p) 400 p = re.sub(r'(?<!\\)\\s', r'[ \\t]', p)
391 # [^...] doesn't match newline 401 # [^...] doesn't match newline
392 p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p) 402 p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p)
393 403
394 pats[i] = (re.compile(p, re.MULTILINE),) + pseq[1:] 404 pats[i] = (re.compile(p, re.MULTILINE),) + pseq[1:]
395 filters = c[2] 405 filters = c[3]
396 for i, flt in enumerate(filters): 406 for i, flt in enumerate(filters):
397 filters[i] = re.compile(flt[0]), flt[1] 407 filters[i] = re.compile(flt[0]), flt[1]
398 _preparepats() 408 _preparepats()
399 409
400 class norepeatlogger(object): 410 class norepeatlogger(object):
444 454
445 return True if no error is found, False otherwise. 455 return True if no error is found, False otherwise.
446 """ 456 """
447 blamecache = None 457 blamecache = None
448 result = True 458 result = True
449 for name, match, filters, pats in checks: 459
460 try:
461 fp = open(f)
462 except IOError, e:
463 print "Skipping %s, %s" % (f, str(e).split(':', 1)[0])
464 return result
465 pre = post = fp.read()
466 fp.close()
467
468 for name, match, magic, filters, pats in checks:
450 if debug: 469 if debug:
451 print name, f 470 print name, f
452 fc = 0 471 fc = 0
453 if not re.match(match, f): 472 if not (re.match(match, f) or (magic and re.search(magic, f))):
454 if debug: 473 if debug:
455 print "Skipping %s for %s it doesn't match %s" % ( 474 print "Skipping %s for %s it doesn't match %s" % (
456 name, match, f) 475 name, match, f)
457 continue 476 continue
458 try:
459 fp = open(f)
460 except IOError, e:
461 print "Skipping %s, %s" % (f, str(e).split(':', 1)[0])
462 continue
463 pre = post = fp.read()
464 fp.close()
465 if "no-" "check-code" in pre: 477 if "no-" "check-code" in pre:
466 print "Skipping %s it has no-" "check-code" % f 478 print "Skipping %s it has no-" "check-code" % f
467 return "Skip" # skip checking this file 479 return "Skip" # skip checking this file
468 for p, r in filters: 480 for p, r in filters:
469 post = re.sub(p, r, post) 481 post = re.sub(p, r, post)