contrib/check-code.py
changeset 28509 9e3ecb6f4995
parent 28399 2af0156cebaa
child 28594 d3990da51637
equal deleted inserted replaced
28508:3c6e94d0811c 28509:9e3ecb6f4995
    17    (you can append a short comment and match this, like: #re-raises, # no-py24)
    17    (you can append a short comment and match this, like: #re-raises, # no-py24)
    18  * change the pattern to a warning and list the exception in test-check-code-hg
    18  * change the pattern to a warning and list the exception in test-check-code-hg
    19  * ONLY use no--check-code for skipping entire files from external sources
    19  * ONLY use no--check-code for skipping entire files from external sources
    20 """
    20 """
    21 
    21 
    22 import re, glob, os, sys
    22 from __future__ import absolute_import, print_function
       
    23 import glob
    23 import keyword
    24 import keyword
    24 import optparse
    25 import optparse
       
    26 import os
       
    27 import re
       
    28 import sys
    25 try:
    29 try:
    26     import re2
    30     import re2
    27 except ImportError:
    31 except ImportError:
    28     re2 = None
    32     re2 = None
    29 
    33 
   441         :msg: error message
   445         :msg: error message
   442         """
   446         """
   443         msgid = fname, lineno, line
   447         msgid = fname, lineno, line
   444         if msgid != self._lastseen:
   448         if msgid != self._lastseen:
   445             if blame:
   449             if blame:
   446                 print "%s:%d (%s):" % (fname, lineno, blame)
   450                 print("%s:%d (%s):" % (fname, lineno, blame))
   447             else:
   451             else:
   448                 print "%s:%d:" % (fname, lineno)
   452                 print("%s:%d:" % (fname, lineno))
   449             print " > %s" % line
   453             print(" > %s" % line)
   450             self._lastseen = msgid
   454             self._lastseen = msgid
   451         print " " + msg
   455         print(" " + msg)
   452 
   456 
   453 _defaultlogger = norepeatlogger()
   457 _defaultlogger = norepeatlogger()
   454 
   458 
   455 def getblame(f):
   459 def getblame(f):
   456     lines = []
   460     lines = []
   476     result = True
   480     result = True
   477 
   481 
   478     try:
   482     try:
   479         fp = open(f)
   483         fp = open(f)
   480     except IOError as e:
   484     except IOError as e:
   481         print "Skipping %s, %s" % (f, str(e).split(':', 1)[0])
   485         print("Skipping %s, %s" % (f, str(e).split(':', 1)[0]))
   482         return result
   486         return result
   483     pre = post = fp.read()
   487     pre = post = fp.read()
   484     fp.close()
   488     fp.close()
   485 
   489 
   486     for name, match, magic, filters, pats in checks:
   490     for name, match, magic, filters, pats in checks:
   487         if debug:
   491         if debug:
   488             print name, f
   492             print(name, f)
   489         fc = 0
   493         fc = 0
   490         if not (re.match(match, f) or (magic and re.search(magic, pre))):
   494         if not (re.match(match, f) or (magic and re.search(magic, pre))):
   491             if debug:
   495             if debug:
   492                 print "Skipping %s for %s it doesn't match %s" % (
   496                 print("Skipping %s for %s it doesn't match %s" % (
   493                        name, match, f)
   497                        name, match, f))
   494             continue
   498             continue
   495         if "no-" "check-code" in pre:
   499         if "no-" "check-code" in pre:
   496             # If you're looking at this line, it's because a file has:
   500             # If you're looking at this line, it's because a file has:
   497             # no- check- code
   501             # no- check- code
   498             # but the reason to output skipping is to make life for
   502             # but the reason to output skipping is to make life for
   499             # tests easier. So, instead of writing it with a normal
   503             # tests easier. So, instead of writing it with a normal
   500             # spelling, we write it with the expected spelling from
   504             # spelling, we write it with the expected spelling from
   501             # tests/test-check-code.t
   505             # tests/test-check-code.t
   502             print "Skipping %s it has no-che?k-code (glob)" % f
   506             print("Skipping %s it has no-che?k-code (glob)" % f)
   503             return "Skip" # skip checking this file
   507             return "Skip" # skip checking this file
   504         for p, r in filters:
   508         for p, r in filters:
   505             post = re.sub(p, r, post)
   509             post = re.sub(p, r, post)
   506         nerrs = len(pats[0]) # nerr elements are errors
   510         nerrs = len(pats[0]) # nerr elements are errors
   507         if warnings:
   511         if warnings:
   509         else:
   513         else:
   510             pats = pats[0]
   514             pats = pats[0]
   511         # print post # uncomment to show filtered version
   515         # print post # uncomment to show filtered version
   512 
   516 
   513         if debug:
   517         if debug:
   514             print "Checking %s for %s" % (name, f)
   518             print("Checking %s for %s" % (name, f))
   515 
   519 
   516         prelines = None
   520         prelines = None
   517         errors = []
   521         errors = []
   518         for i, pat in enumerate(pats):
   522         for i, pat in enumerate(pats):
   519             if len(pat) == 3:
   523             if len(pat) == 3:
   540                     n += 1
   544                     n += 1
   541                 l = prelines[n]
   545                 l = prelines[n]
   542 
   546 
   543                 if ignore and re.search(ignore, l, re.MULTILINE):
   547                 if ignore and re.search(ignore, l, re.MULTILINE):
   544                     if debug:
   548                     if debug:
   545                         print "Skipping %s for %s:%s (ignore pattern)" % (
   549                         print("Skipping %s for %s:%s (ignore pattern)" % (
   546                             name, f, n)
   550                             name, f, n))
   547                     continue
   551                     continue
   548                 bd = ""
   552                 bd = ""
   549                 if blame:
   553                 if blame:
   550                     bd = 'working directory'
   554                     bd = 'working directory'
   551                     if not blamecache:
   555                     if not blamecache:
   561         errors.sort()
   565         errors.sort()
   562         for e in errors:
   566         for e in errors:
   563             logfunc(*e)
   567             logfunc(*e)
   564             fc += 1
   568             fc += 1
   565             if maxerr and fc >= maxerr:
   569             if maxerr and fc >= maxerr:
   566                 print " (too many errors, giving up)"
   570                 print(" (too many errors, giving up)")
   567                 break
   571                 break
   568 
   572 
   569     return result
   573     return result
   570 
   574 
   571 if __name__ == "__main__":
   575 if __name__ == "__main__":