33# Copyright 2015 (c) Lei Xu <eddyxu@gmail.com>
44
55from __future__ import absolute_import
6+ from builtins import str
67
78import argparse
89import hashlib
@@ -48,6 +49,9 @@ def create_args(params):
4849 parser .add_argument ('-E' , '--exclude-pattern' , dest = 'regexp' ,
4950 action = 'append' , metavar = 'REGEXP' , default = [],
5051 help = 'set exclude file/directory pattern' )
52+ parser .add_argument ('--exclude-lines-pattern' ,
53+ action = 'append' , metavar = 'REGEXP' , default = [],
54+ help = 'set exclude file/directory pattern' )
5155 parser .add_argument ('-x' , '--extension' , metavar = 'EXT' , action = 'append' ,
5256 help = 'set extension of files to process' )
5357 parser .add_argument ('-y' , '--coveralls-yaml' , default = '.coveralls.yml' ,
@@ -236,7 +240,7 @@ def run_gcov(args):
236240 os .path .join (root , files ))
237241
238242
239- def parse_gcov_file (fobj , filename ):
243+ def parse_gcov_file (args , fobj , filename ):
240244 """Parses the content of .gcov file
241245 """
242246 coverage = []
@@ -271,9 +275,7 @@ def parse_gcov_file(fobj, filename):
271275 # Avoid false positives.
272276 if (
273277 ignoring or
274- text .lstrip ().startswith (('inline' , 'static' )) or
275- text .strip () == '}' or
276- re .search (r'\bLCOV_EXCL_LINE\b' , text )
278+ any ([re .search (pattern , text ) for pattern in args .exclude_lines_pattern ])
277279 ):
278280 coverage .append (None )
279281 else :
@@ -291,21 +293,17 @@ def parse_lcov_file_info(args, filepath, line_iter, line_coverage_re, file_end_s
291293 """
292294 coverage = []
293295 lines_covered = []
294- while True :
295- try :
296- line = line_iter .next ()
297- if line != "end_of_record" :
298- line_coverage_match = line_coverage_re .match (line )
299- if line_coverage_match :
300- line_no = line_coverage_match .group (1 )
301- cov_count = int (line_coverage_match .group (2 ))
302- if args .max_cov_count :
303- if cov_count > args .max_cov_count :
304- cov_count = args .max_cov_count + 1
305- lines_covered .append ((line_no , cov_count ))
306- else :
307- break
308- except StopIteration :
296+ for line in line_iter :
297+ if line != "end_of_record" :
298+ line_coverage_match = line_coverage_re .match (line )
299+ if line_coverage_match :
300+ line_no = line_coverage_match .group (1 )
301+ cov_count = int (line_coverage_match .group (2 ))
302+ if args .max_cov_count :
303+ if cov_count > args .max_cov_count :
304+ cov_count = args .max_cov_count + 1
305+ lines_covered .append ((line_no , cov_count ))
306+ else :
309307 break
310308
311309 num_code_lines = len ([line .rstrip ('\n ' ) for line in open (filepath , 'r' )])
@@ -379,6 +377,12 @@ def collect(args):
379377 if os .getenv ('COVERALLS_PARALLEL' , False ):
380378 report ['parallel' ] = 'true'
381379
380+ args .exclude_lines_pattern .extend ([
381+ r'\bLCOV_EXCL_LINE\b' ,
382+ r'^\s*};?\s*$' ,
383+ r'^\s*(inline|static)'
384+ ])
385+
382386 discovered_files = set ()
383387 src_files = {}
384388 abs_root = os .path .abspath (args .root )
@@ -387,27 +391,23 @@ def collect(args):
387391 line_iter = iter (info_lines )
388392 new_file_re = re .compile ('SF:(.*)' )
389393 line_coverage_re = re .compile ('DA:(\d+),(\d+)' );
390- while True :
391- try :
392- line = line_iter .next ()
393- new_file_match = new_file_re .match (line )
394- if new_file_match :
395- src_report = {}
396- filepath = new_file_match .group (1 )
397- if args .build_root :
398- filepath = os .path .relpath (filepath , args .build_root )
399- abs_filepath = os .path .join (abs_root , filepath )
400- src_report ['name' ] = unicode (posix_path (filepath ))
401- with io .open (abs_filepath , mode = 'rb' ) as src_file :
402- src_report ['source_digest' ] = hashlib .md5 (src_file .read ()).hexdigest ()
403- src_report ['coverage' ] = parse_lcov_file_info (args , abs_filepath , line_iter , line_coverage_re , "end_of_record" )
404- src_files [filepath ] = src_report
405- elif line != "TN:" :
406- print ('Invalid info file' )
407- print ('line: ' + line )
408- sys .exit (0 )
409- except StopIteration :
410- break
394+ for line in line_iter :
395+ new_file_match = new_file_re .match (line )
396+ if new_file_match :
397+ src_report = {}
398+ filepath = new_file_match .group (1 )
399+ if args .root :
400+ filepath = os .path .relpath (filepath , args .root )
401+ abs_filepath = os .path .join (abs_root , filepath )
402+ src_report ['name' ] = str (posix_path (filepath ))
403+ with io .open (abs_filepath , mode = 'rb' ) as src_file :
404+ src_report ['source_digest' ] = hashlib .md5 (src_file .read ()).hexdigest ()
405+ src_report ['coverage' ] = parse_lcov_file_info (args , abs_filepath , line_iter , line_coverage_re , "end_of_record" )
406+ src_files [filepath ] = src_report
407+ elif line != "TN:" :
408+ print ('Invalid info file' )
409+ print ('line: ' + line )
410+ sys .exit (0 )
411411 else :
412412 for root , dirs , files in os .walk (args .root , followlinks = args .follow_symlinks ):
413413 dirs [:] = filter_dirs (root , dirs , excl_paths )
@@ -447,7 +447,7 @@ def collect(args):
447447 with io .open (source_file_path , mode = 'rb' ) as src_file :
448448 src_report ['source_digest' ] = hashlib .md5 (src_file .read ()).hexdigest ()
449449
450- src_report ['coverage' ] = parse_gcov_file (fobj , gcov_path )
450+ src_report ['coverage' ] = parse_gcov_file (args , fobj , gcov_path )
451451 if src_path in src_files :
452452 src_files [src_path ] = combine_reports (src_files [src_path ], src_report )
453453 else :
0 commit comments