1
- #!/usr/bin/python2.4
1
+ #!/usr/bin/env python
2
2
#
3
3
# Copyright (c) 2009 Google Inc. All rights reserved.
4
4
#
88
88
import string
89
89
import sys
90
90
import unicodedata
91
-
91
+ import logging
92
+ logger = logging .getLogger ('testrunner' )
92
93
93
94
_USAGE = """
94
95
Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
139
140
the top-level categories like 'build' and 'whitespace' will
140
141
also be printed. If 'detailed' is provided, then a count
141
142
is provided for each category like 'build/class'.
143
+
144
+ logfile=filename
145
+ Write TAP output to a logfile.
142
146
"""
143
147
144
148
# We categorize each error message we print. Here are the categories.
@@ -541,6 +545,11 @@ def SetFilters(self, filters):
541
545
raise ValueError ('Every filter in --filters must start with + or -'
542
546
' (%s does not)' % filt )
543
547
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
+
544
553
def ResetErrorCounts (self ):
545
554
"""Sets the module's error statistic back to zero."""
546
555
self .error_count = 0
@@ -558,10 +567,11 @@ def IncrementErrorCount(self, category):
558
567
559
568
def PrintErrorCounts (self ):
560
569
"""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 )
565
575
566
576
_cpplint_state = _CppLintState ()
567
577
@@ -608,6 +618,9 @@ def _SetFilters(filters):
608
618
"""
609
619
_cpplint_state .SetFilters (filters )
610
620
621
+ def _setOutputFile (filename ):
622
+ _cpplint_state .setOutputFile (filename )
623
+
611
624
612
625
class _FunctionState (object ):
613
626
"""Tracks current function name and the number of lines in its body."""
@@ -786,6 +799,15 @@ def Error(filename, linenum, category, confidence, message):
786
799
if _cpplint_state .output_format == 'vs7' :
787
800
sys .stderr .write ('%s(%s): %s [%s] [%d]\n ' % (
788
801
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 ))
789
811
else :
790
812
sys .stderr .write ('%s:%s: %s [%s] [%d]\n ' % (
791
813
filename , linenum , message , category , confidence ))
@@ -2069,7 +2091,7 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, error):
2069
2091
initial_spaces += 1
2070
2092
if line and line [- 1 ].isspace ():
2071
2093
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.' )
2073
2095
# There are certain situations we allow one space, notably for labels
2074
2096
elif ((initial_spaces == 1 or initial_spaces == 3 ) and
2075
2097
not Match (r'\s*\w+\s*:\s*$' , cleansed_line )):
@@ -3002,7 +3024,8 @@ def ProcessFile(filename, vlevel):
3002
3024
'One or more unexpected \\ r (^M) found;'
3003
3025
'better to use only a \\ n' )
3004
3026
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 )
3006
3029
3007
3030
3008
3031
def PrintUsage (message ):
@@ -3041,21 +3064,23 @@ def ParseArguments(args):
3041
3064
try :
3042
3065
(opts , filenames ) = getopt .getopt (args , '' , ['help' , 'output=' , 'verbose=' ,
3043
3066
'counting=' ,
3044
- 'filter=' ])
3067
+ 'filter=' ,
3068
+ 'logfile=' ])
3045
3069
except getopt .GetoptError :
3046
3070
PrintUsage ('Invalid arguments.' )
3047
3071
3048
3072
verbosity = _VerboseLevel ()
3049
3073
output_format = _OutputFormat ()
3050
3074
filters = ''
3051
3075
counting_style = ''
3076
+ output_filename = ''
3052
3077
3053
3078
for (opt , val ) in opts :
3054
3079
if opt == '--help' :
3055
3080
PrintUsage (None )
3056
3081
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 .' )
3059
3084
output_format = val
3060
3085
elif opt == '--verbose' :
3061
3086
verbosity = int (val )
@@ -3067,6 +3092,8 @@ def ParseArguments(args):
3067
3092
if val not in ('total' , 'toplevel' , 'detailed' ):
3068
3093
PrintUsage ('Valid counting options are total, toplevel, and detailed' )
3069
3094
counting_style = val
3095
+ elif opt == '--logfile' :
3096
+ output_filename = val
3070
3097
3071
3098
if not filenames :
3072
3099
PrintUsage ('No files were specified.' )
@@ -3075,6 +3102,8 @@ def ParseArguments(args):
3075
3102
_SetVerboseLevel (verbosity )
3076
3103
_SetFilters (filters )
3077
3104
_SetCountingStyle (counting_style )
3105
+ if output_filename :
3106
+ _setOutputFile (output_filename )
3078
3107
3079
3108
return filenames
3080
3109
@@ -3089,6 +3118,14 @@ def main():
3089
3118
codecs .getwriter ('utf8' ),
3090
3119
'replace' )
3091
3120
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
+
3092
3129
_cpplint_state .ResetErrorCounts ()
3093
3130
for filename in filenames :
3094
3131
ProcessFile (filename , _cpplint_state .verbose_level )
0 commit comments