1- #!/usr/bin/python2.4
1+ #!/usr/bin/env python
22#
33# Copyright (c) 2009 Google Inc. All rights reserved.
44#
8888import string
8989import sys
9090import unicodedata
91-
91+ import logging
92+ logger = logging .getLogger ('testrunner' )
9293
9394_USAGE = """
9495Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
139140 the top-level categories like 'build' and 'whitespace' will
140141 also be printed. If 'detailed' is provided, then a count
141142 is provided for each category like 'build/class'.
143+
144+ logfile=filename
145+ Write TAP output to a logfile.
142146"""
143147
144148# We categorize each error message we print. Here are the categories.
@@ -541,6 +545,11 @@ def SetFilters(self, filters):
541545 raise ValueError ('Every filter in --filters must start with + or -'
542546 ' (%s does not)' % filt )
543547
548+ def setOutputFile (self , filename ):
549+ """attempts to create a file which we write output to."""
550+ fh = logging .FileHandler (filename , mode = 'wb' )
551+ logger .addHandler (fh )
552+
544553 def ResetErrorCounts (self ):
545554 """Sets the module's error statistic back to zero."""
546555 self .error_count = 0
@@ -558,10 +567,11 @@ def IncrementErrorCount(self, category):
558567
559568 def PrintErrorCounts (self ):
560569 """Print a summary of errors by category, and the total."""
561- for category , count in self .errors_by_category .iteritems ():
562- sys .stderr .write ('Category \' %s\' errors found: %d\n ' %
563- (category , count ))
564- sys .stderr .write ('Total errors found: %d\n ' % self .error_count )
570+ if not _cpplint_state .output_format == 'tap' :
571+ for category , count in self .errors_by_category .iteritems ():
572+ sys .stderr .write ('Category \' %s\' errors found: %d\n ' %
573+ (category , count ))
574+ sys .stderr .write ('Total errors found: %d\n ' % self .error_count )
565575
566576_cpplint_state = _CppLintState ()
567577
@@ -608,6 +618,9 @@ def _SetFilters(filters):
608618 """
609619 _cpplint_state .SetFilters (filters )
610620
621+ def _setOutputFile (filename ):
622+ _cpplint_state .setOutputFile (filename )
623+
611624
612625class _FunctionState (object ):
613626 """Tracks current function name and the number of lines in its body."""
@@ -786,6 +799,15 @@ def Error(filename, linenum, category, confidence, message):
786799 if _cpplint_state .output_format == 'vs7' :
787800 sys .stderr .write ('%s(%s): %s [%s] [%d]\n ' % (
788801 filename , linenum , message , category , confidence ))
802+ elif _cpplint_state .output_format == 'tap' :
803+ template = ('not ok %s\n '
804+ ' ---\n '
805+ ' message: %s\n '
806+ ' data:\n '
807+ ' line: %d\n '
808+ ' ruleId: %s\n '
809+ ' ...' )
810+ logger .info (template % (filename , message , linenum , category ))
789811 else :
790812 sys .stderr .write ('%s:%s: %s [%s] [%d]\n ' % (
791813 filename , linenum , message , category , confidence ))
@@ -2069,7 +2091,7 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, error):
20692091 initial_spaces += 1
20702092 if line and line [- 1 ].isspace ():
20712093 error (filename , linenum , 'whitespace/end_of_line' , 4 ,
2072- 'Line ends in whitespace. Consider deleting these extra spaces.' )
2094+ 'Line ends in whitespace. Consider deleting these extra spaces.' )
20732095 # There are certain situations we allow one space, notably for labels
20742096 elif ((initial_spaces == 1 or initial_spaces == 3 ) and
20752097 not Match (r'\s*\w+\s*:\s*$' , cleansed_line )):
@@ -3002,7 +3024,8 @@ def ProcessFile(filename, vlevel):
30023024 'One or more unexpected \\ r (^M) found;'
30033025 'better to use only a \\ n' )
30043026
3005- sys .stderr .write ('Done processing %s\n ' % filename )
3027+ if not _cpplint_state .output_format == 'tap' :
3028+ sys .stderr .write ('Done processing %s\n ' % filename )
30063029
30073030
30083031def PrintUsage (message ):
@@ -3041,21 +3064,23 @@ def ParseArguments(args):
30413064 try :
30423065 (opts , filenames ) = getopt .getopt (args , '' , ['help' , 'output=' , 'verbose=' ,
30433066 'counting=' ,
3044- 'filter=' ])
3067+ 'filter=' ,
3068+ 'logfile=' ])
30453069 except getopt .GetoptError :
30463070 PrintUsage ('Invalid arguments.' )
30473071
30483072 verbosity = _VerboseLevel ()
30493073 output_format = _OutputFormat ()
30503074 filters = ''
30513075 counting_style = ''
3076+ output_filename = ''
30523077
30533078 for (opt , val ) in opts :
30543079 if opt == '--help' :
30553080 PrintUsage (None )
30563081 elif opt == '--output' :
3057- if not val in ('emacs' , 'vs7' ):
3058- PrintUsage ('The only allowed output formats are emacs and vs7 .' )
3082+ if not val in ('emacs' , 'vs7' , 'tap' ):
3083+ PrintUsage ('The only allowed output formats are emacs, vs7 and tap .' )
30593084 output_format = val
30603085 elif opt == '--verbose' :
30613086 verbosity = int (val )
@@ -3067,6 +3092,8 @@ def ParseArguments(args):
30673092 if val not in ('total' , 'toplevel' , 'detailed' ):
30683093 PrintUsage ('Valid counting options are total, toplevel, and detailed' )
30693094 counting_style = val
3095+ elif opt == '--logfile' :
3096+ output_filename = val
30703097
30713098 if not filenames :
30723099 PrintUsage ('No files were specified.' )
@@ -3075,6 +3102,8 @@ def ParseArguments(args):
30753102 _SetVerboseLevel (verbosity )
30763103 _SetFilters (filters )
30773104 _SetCountingStyle (counting_style )
3105+ if output_filename :
3106+ _setOutputFile (output_filename )
30783107
30793108 return filenames
30803109
@@ -3089,6 +3118,14 @@ def main():
30893118 codecs .getwriter ('utf8' ),
30903119 'replace' )
30913120
3121+
3122+ ch = logging .StreamHandler (sys .stdout )
3123+ logger .addHandler (ch )
3124+ logger .setLevel (logging .INFO )
3125+
3126+ if _cpplint_state .output_format == 'tap' :
3127+ logger .info ('TAP version 13' )
3128+
30923129 _cpplint_state .ResetErrorCounts ()
30933130 for filename in filenames :
30943131 ProcessFile (filename , _cpplint_state .verbose_level )
0 commit comments