<s> """<STR_LIT>""" <EOL> from __future__ import print_function <EOL> __docformat__ = "<STR_LIT>" <EOL> import sys <EOL> import os <EOL> import datetime <EOL> import cgi <EOL> import subprocess <EOL> import optparse <EOL> import tempfile <EOL> HIGHLIGHT_COMMAND = [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' , <EOL> '<STR_LIT>' , '<STR_LIT:->' ] <EOL> class Lazy ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , func ) : <EOL> self . func = func <EOL> self . name = func . __name__ <EOL> def __get__ ( self , obj , cls ) : <EOL> if obj is None : <EOL> return self <EOL> value = self . func ( obj ) <EOL> obj . __dict__ [ self . name ] = value <EOL> return value <EOL> class CoverageNode ( dict ) : <EOL> """<STR_LIT>""" <EOL> @ Lazy <EOL> def covered ( self ) : <EOL> return sum ( child . covered for child in self . values ( ) ) <EOL> @ Lazy <EOL> def total ( self ) : <EOL> return sum ( child . total for child in self . values ( ) ) <EOL> @ Lazy <EOL> def uncovered ( self ) : <EOL> return self . total - self . covered <EOL> @ Lazy <EOL> def percent ( self ) : <EOL> if self . total != <NUM_LIT:0> : <EOL> return <NUM_LIT:100> * self . covered // self . total <EOL> else : <EOL> return <NUM_LIT:100> <EOL> @ Lazy <EOL> def html_source ( self ) : <EOL> return '<STR_LIT>' <EOL> def __str__ ( self ) : <EOL> return '<STR_LIT>' % ( self . percent , self . uncovered , self . total ) <EOL> def get_at ( self , path ) : <EOL> """<STR_LIT>""" <EOL> node = self <EOL> for name in path : <EOL> node = node [ name ] <EOL> return node <EOL> def set_at ( self , path , node ) : <EOL> """<STR_LIT>""" <EOL> parent = self <EOL> for name in path [ : - <NUM_LIT:1> ] : <EOL> parent = parent . setdefault ( name , CoverageNode ( ) ) <EOL> parent [ path [ - <NUM_LIT:1> ] ] = node <EOL> class TraceCoverageNode ( CoverageNode ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , cover_filename ) : <EOL> self . cover_filename = cover_filename <EOL> self . covered , self . total = self . _parse ( cover_filename ) <EOL> def _parse ( self , filename ) : <EOL> """<STR_LIT>""" <EOL> covered = <NUM_LIT:0> <EOL> total = <NUM_LIT:0> <EOL> with open ( filename ) as file : <EOL> for line in file : <EOL> if line . startswith ( '<STR_LIT:U+0020>' * <NUM_LIT:7> ) or len ( line ) < <NUM_LIT:7> : <EOL> continue <EOL> total += <NUM_LIT:1> <EOL> if not line . startswith ( '<STR_LIT>' ) : <EOL> covered += <NUM_LIT:1> <EOL> return ( covered , total ) <EOL> @ Lazy <EOL> def html_source ( self ) : <EOL> text = syntax_highlight ( self . cover_filename ) <EOL> text = highlight_uncovered_lines ( text ) <EOL> return '<STR_LIT>' % text <EOL> class CoverageCoverageNode ( CoverageNode ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , cov , source_filename ) : <EOL> self . cov = cov <EOL> self . source_filename = source_filename <EOL> ( filename_again , statements , excluded , missing , <EOL> missing_str ) = cov . analysis2 ( source_filename ) <EOL> self . covered = len ( statements ) - len ( excluded ) - len ( missing ) <EOL> self . total = len ( statements ) - len ( excluded ) <EOL> self . _missing = set ( missing ) <EOL> self . _statements = set ( statements ) <EOL> self . _excluded = set ( excluded ) <EOL> @ Lazy <EOL> def annotated_source ( self ) : <EOL> MISSING = '<STR_LIT>' <EOL> STATEMENT = '<STR_LIT>' <EOL> EXCLUDED = '<STR_LIT>' <EOL> OTHER = '<STR_LIT:U+0020>' <EOL> lines = [ ] <EOL> f = open ( self . source_filename ) <EOL> for n , line in enumerate ( f ) : <EOL> n += <NUM_LIT:1> <EOL> if n in self . _missing : prefix = MISSING <EOL> elif n in self . _excluded : prefix = EXCLUDED <EOL> elif n in self . _statements : prefix = STATEMENT <EOL> else : prefix = OTHER <EOL> lines . append ( prefix + line ) <EOL> return '<STR_LIT>' . join ( lines ) <EOL> @ Lazy <EOL> def html_source ( self ) : <EOL> tmpdir = tempfile . mkdtemp ( prefix = '<STR_LIT>' ) <EOL> tmpfilename = os . path . join ( tmpdir , <EOL> os . path . basename ( self . source_filename ) + '<STR_LIT>' ) <EOL> tmpf = open ( tmpfilename , '<STR_LIT:w>' ) <EOL> tmpf . write ( self . annotated_source ) <EOL> tmpf . close ( ) <EOL> text = syntax_highlight ( tmpf . name ) <EOL> os . unlink ( tmpfilename ) <EOL> os . rmdir ( tmpdir ) <EOL> text = highlight_uncovered_lines ( text ) <EOL> return '<STR_LIT>' % text <EOL> def get_file_list ( path , filter_fn = None ) : <EOL> """<STR_LIT>""" <EOL> return filter ( filter_fn , os . listdir ( path ) ) <EOL> def filename_to_list ( filename ) : <EOL> """<STR_LIT>""" <EOL> return filename . split ( '<STR_LIT:.>' ) [ : - <NUM_LIT:1> ] <EOL> def create_tree_from_files ( filelist , path ) : <EOL> """<STR_LIT>""" <EOL> root = CoverageNode ( ) <EOL> for filename in filelist : <EOL> tree_index = filename_to_list ( filename ) <EOL> filepath = os . path . join ( path , filename ) <EOL> root . set_at ( tree_index , TraceCoverageNode ( filepath ) ) <EOL> return root <EOL> def create_tree_from_coverage ( cov , strip_prefix = None , path_aliases = None , cover = [ ] , exclude = [ ] ) : <EOL> """<STR_LIT>""" <EOL> root = CoverageNode ( ) <EOL> if path_aliases : <EOL> apply_path_aliases ( cov , dict ( [ alias . partition ( '<STR_LIT:=>' ) [ : : <NUM_LIT:2> ] <EOL> for alias in path_aliases ] ) ) <EOL> for filename in cov . data . measured_files ( ) : <EOL> if not any ( pattern in filename . replace ( '<STR_LIT:/>' , '<STR_LIT:.>' ) for pattern in cover ) : <EOL> continue <EOL> if any ( pattern in filename . replace ( '<STR_LIT:/>' , '<STR_LIT:.>' ) for pattern in exclude ) : <EOL> continue <EOL> if strip_prefix and filename . startswith ( strip_prefix ) : <EOL> short_name = filename [ len ( strip_prefix ) : ] <EOL> short_name = short_name . replace ( '<STR_LIT:/>' , os . path . sep ) <EOL> short_name = short_name . lstrip ( os . path . sep ) <EOL> else : <EOL> short_name = cov . file_locator . relative_filename ( filename ) <EOL> tree_index = filename_to_list ( short_name . replace ( os . path . sep , '<STR_LIT:.>' ) ) <EOL> if '<STR_LIT>' in tree_index or '<STR_LIT>' in tree_index : <EOL> continue <EOL> root . set_at ( tree_index , CoverageCoverageNode ( cov , filename ) ) <EOL> return root <EOL> def apply_path_aliases ( cov , aliases ) : <EOL> """<STR_LIT>""" <EOL> aliases = sorted ( <EOL> aliases . items ( ) , key = lambda i : len ( i [ <NUM_LIT:0> ] ) , reverse = True ) <EOL> def fixup_filename ( filename ) : <EOL> for alias , local in aliases : <EOL> if filename . startswith ( alias ) : <EOL> return local + filename [ len ( alias ) : ] <EOL> return filename <EOL> cov . data . lines = map_and_merge_dict_keys ( fixup_filename , cov . data . lines ) <EOL> cov . data . arcs = map_dict_keys ( fixup_filename , cov . data . arcs ) <EOL> def map_and_merge_dict_keys ( fn , d ) : <EOL> def merge_fn ( * args ) : <EOL> accumulated = set ( ) <EOL> for l in args : <EOL> accumulated . update ( l ) <EOL> return sorted ( accumulated ) <EOL> output = { } <EOL> for k , v in d . iteritems ( ) : <EOL> if fn ( k ) not in output : <EOL> output [ fn ( k ) ] = [ ] <EOL> output [ fn ( k ) ] . append ( v ) <EOL> return dict ( ( f_k , merge_fn ( * v ) ) for f_k , v in output . iteritems ( ) ) <EOL> def map_dict_keys ( fn , d ) : <EOL> """<STR_LIT>""" <EOL> return dict ( ( fn ( k ) , v ) for k , v in d . items ( ) ) <EOL> def traverse_tree ( tree , index , function ) : <EOL> """<STR_LIT>""" <EOL> function ( tree , index ) <EOL> for key , node in tree . items ( ) : <EOL> traverse_tree ( node , index + [ key ] , function ) <EOL> def traverse_tree_in_order ( tree , index , function , order_by ) : <EOL> """<STR_LIT>""" <EOL> function ( tree , index ) <EOL> for key , node in sorted ( tree . items ( ) , key = order_by ) : <EOL> traverse_tree_in_order ( node , index + [ key ] , function , order_by ) <EOL> def index_to_url ( index ) : <EOL> """<STR_LIT>""" <EOL> if index : <EOL> return '<STR_LIT>' % '<STR_LIT:.>' . join ( index ) <EOL> return '<STR_LIT>' <EOL> def index_to_nice_name ( index ) : <EOL> """<STR_LIT>""" <EOL> if index : <EOL> return '<STR_LIT>' * <NUM_LIT:4> * ( len ( index ) - <NUM_LIT:1> ) + index [ - <NUM_LIT:1> ] <EOL> else : <EOL> return '<STR_LIT>' <EOL> def index_to_name ( index ) : <EOL> """<STR_LIT>""" <EOL> if index : <EOL> return '<STR_LIT:.>' . join ( index ) <EOL> return '<STR_LIT>' <EOL> def percent_to_colour ( percent ) : <EOL> if percent == <NUM_LIT:100> : <EOL> return '<STR_LIT>' <EOL> elif percent >= <NUM_LIT> : <EOL> return '<STR_LIT>' <EOL> elif percent >= <NUM_LIT> : <EOL> return '<STR_LIT>' <EOL> elif percent >= <NUM_LIT> : <EOL> return '<STR_LIT>' <EOL> else : <EOL> return '<STR_LIT>' <EOL> def print_table_row ( html , node , file_index ) : <EOL> """<STR_LIT>""" <EOL> nice_name = index_to_nice_name ( file_index ) <EOL> if not node . keys ( ) : <EOL> nice_name += '<STR_LIT>' <EOL> else : <EOL> nice_name += '<STR_LIT:/>' <EOL> print ( '<STR_LIT>' % ( index_to_url ( file_index ) , nice_name ) , file = html ) <EOL> print ( '<STR_LIT>' % ( percent_to_colour ( node . percent ) ) , file = html ) <EOL> print ( '<STR_LIT>' % ( node . percent , node . uncovered , node . total ) , file = html ) <EOL> HEADER = """<STR_LIT>""" <EOL> FOOTER = """<STR_LIT>""" <EOL> def generate_html ( output_filename , tree , my_index , info , path , footer = "<STR_LIT>" ) : <EOL> """<STR_LIT>""" <EOL> html = open ( output_filename , '<STR_LIT:w>' ) <EOL> print ( HEADER % { '<STR_LIT:name>' : index_to_name ( my_index ) } , file = html ) <EOL> info = [ ( tree . get_at ( node_path ) , node_path ) for node_path in info ] <EOL> def key ( node_info ) : <EOL> ( node , node_path ) = node_info <EOL> return ( len ( node_path ) , - node . uncovered , node_path and node_path [ - <NUM_LIT:1> ] ) <EOL> info . sort ( key = key ) <EOL> for node , file_index in info : <EOL> if not file_index : <EOL> continue <EOL> print_table_row ( html , node , file_index ) <EOL> print ( '<STR_LIT>' , file = html ) <EOL> print ( tree . get_at ( my_index ) . html_source , file = html ) <EOL> print ( FOOTER % footer , file = html ) <EOL> html . close ( ) <EOL> def syntax_highlight ( filename ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> pipe = subprocess . Popen ( HIGHLIGHT_COMMAND + [ filename ] , <EOL> stdout = subprocess . PIPE ) <EOL> text , stderr = pipe . communicate ( ) <EOL> if pipe . returncode != <NUM_LIT:0> : <EOL> raise OSError <EOL> except OSError : <EOL> with open ( filename , '<STR_LIT:r>' ) as file : <EOL> text = cgi . escape ( file . read ( ) ) <EOL> else : <EOL> text = text [ text . find ( '<STR_LIT>' ) + len ( '<STR_LIT>' ) : ] <EOL> text = text [ : text . find ( '<STR_LIT>' ) ] <EOL> return text <EOL> def highlight_uncovered_lines ( text ) : <EOL> """<STR_LIT>""" <EOL> def color_uncov ( line ) : <EOL> if line . startswith ( '<STR_LIT>' * <NUM_LIT:6> ) or '<STR_LIT:>>' + '<STR_LIT>' * <NUM_LIT:6> in line : <EOL> return ( '<STR_LIT>' <EOL> % line . rstrip ( '<STR_LIT:\n>' ) ) <EOL> return line <EOL> text = '<STR_LIT>' . join ( map ( color_uncov , text . splitlines ( True ) ) ) <EOL> return text <EOL> def generate_htmls_from_tree ( tree , path , report_path , footer = "<STR_LIT>" ) : <EOL> """<STR_LIT>""" <EOL> def make_html ( node , my_index ) : <EOL> info = [ ] <EOL> def list_parents_and_children ( node , index ) : <EOL> position = len ( index ) <EOL> my_position = len ( my_index ) <EOL> if position <= my_position and index == my_index [ : position ] : <EOL> info . append ( index ) <EOL> elif ( position == my_position + <NUM_LIT:1> and <EOL> index [ : my_position ] == my_index ) : <EOL> info . append ( index ) <EOL> return <EOL> traverse_tree ( tree , [ ] , list_parents_and_children ) <EOL> output_filename = os . path . join ( report_path , index_to_url ( my_index ) ) <EOL> if not my_index : <EOL> return <EOL> generate_html ( output_filename , tree , my_index , info , path , footer ) <EOL> traverse_tree ( tree , [ ] , make_html ) <EOL> def generate_overall_html_from_tree ( tree , output_filename , footer = "<STR_LIT>" ) : <EOL> """<STR_LIT>""" <EOL> html = open ( output_filename , '<STR_LIT:w>' ) <EOL> print ( HEADER % { '<STR_LIT:name>' : '<STR_LIT:U+002CU+0020>' . join ( sorted ( tree . keys ( ) ) ) } , file = html ) <EOL> def print_node ( node , file_index ) : <EOL> if file_index : <EOL> print_table_row ( html , node , file_index ) <EOL> def sort_by ( node_info ) : <EOL> ( key , node ) = node_info <EOL> return ( - node . uncovered , key ) <EOL> traverse_tree_in_order ( tree , [ ] , print_node , sort_by ) <EOL> print ( '<STR_LIT>' , file = html ) <EOL> print ( FOOTER % footer , file = html ) <EOL> html . close ( ) <EOL> def create_report_path ( report_path ) : <EOL> if not os . path . exists ( report_path ) : <EOL> os . makedirs ( report_path ) <EOL> def filter_fn ( filename ) : <EOL> """<STR_LIT>""" <EOL> parts = filename . split ( '<STR_LIT:.>' ) <EOL> return ( filename . endswith ( '<STR_LIT>' ) and <EOL> not filename . startswith ( '<STR_LIT:<>' ) and <EOL> '<STR_LIT>' not in parts and <EOL> '<STR_LIT>' not in parts ) <EOL> def load_coverage ( path , opts ) : <EOL> """<STR_LIT>""" <EOL> if os . path . isdir ( path ) : <EOL> filelist = get_file_list ( path , filter_fn ) <EOL> tree = create_tree_from_files ( filelist , path ) <EOL> return tree <EOL> else : <EOL> import coverage <EOL> cov = coverage . coverage ( data_file = path , config_file = False ) <EOL> cov . load ( ) <EOL> tree = create_tree_from_coverage ( cov , strip_prefix = opts . strip_prefix , <EOL> path_aliases = opts . path_alias , <EOL> cover = opts . cover , <EOL> exclude = opts . exclude ) <EOL> return tree <EOL> def make_coverage_reports ( path , report_path , opts ) : <EOL> """<STR_LIT>""" <EOL> if opts . verbose : <EOL> print ( "<STR_LIT>" % path ) <EOL> tree = load_coverage ( path , opts = opts ) <EOL> if opts . verbose : <EOL> print ( tree ) <EOL> rev = get_git_revision ( os . path . join ( path , os . path . pardir ) ) <EOL> timestamp = str ( datetime . datetime . utcnow ( ) ) + "<STR_LIT>" <EOL> footer = "<STR_LIT>" % ( rev , timestamp ) <EOL> create_report_path ( report_path ) <EOL> generate_htmls_from_tree ( tree , path , report_path , footer ) <EOL> generate_overall_html_from_tree ( <EOL> tree , os . path . join ( report_path , '<STR_LIT>' ) , footer ) <EOL> if opts . verbose : <EOL> print ( "<STR_LIT>" % report_path ) <EOL> def get_svn_revision ( path ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> pipe = subprocess . Popen ( [ '<STR_LIT>' , path ] , stdout = subprocess . PIPE , <EOL> stderr = subprocess . PIPE ) <EOL> stdout , stderr = pipe . communicate ( ) <EOL> rev = stdout . strip ( ) <EOL> except OSError : <EOL> rev = "<STR_LIT>" <EOL> if not rev : <EOL> rev = "<STR_LIT>" <EOL> return rev <EOL> def get_git_revision ( path ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> pipe = subprocess . Popen ( [ '<STR_LIT>' , '<STR_LIT>' , '<STR_LIT>' ] , stdout = subprocess . PIPE , <EOL> stderr = subprocess . PIPE ) <EOL> stdout , stderr = pipe . communicate ( ) <EOL> rev = stdout . strip ( ) <EOL> except OSError : <EOL> rev = "<STR_LIT>" <EOL> if not rev : <EOL> rev = "<STR_LIT>" <EOL> return rev <EOL> def main ( args = None ) : <EOL> """<STR_LIT>""" <EOL> parser = optparse . OptionParser ( <EOL> "<STR_LIT>" , <EOL> description = <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> parser . add_option ( '<STR_LIT>' , '<STR_LIT>' , help = '<STR_LIT>' , <EOL> action = '<STR_LIT>' , const = <NUM_LIT:0> , dest = '<STR_LIT>' ) <EOL> parser . add_option ( '<STR_LIT>' , '<STR_LIT>' , help = '<STR_LIT>' , <EOL> action = '<STR_LIT>' , const = <NUM_LIT:1> , dest = '<STR_LIT>' , default = <NUM_LIT:1> ) <EOL> parser . add_option ( '<STR_LIT>' , metavar = '<STR_LIT>' , <EOL> help = '<STR_LIT>' ) <EOL> parser . add_option ( '<STR_LIT>' , metavar = '<STR_LIT>' , <EOL> help = '<STR_LIT>' , <EOL> action = '<STR_LIT>' ) <EOL> parser . add_option ( '<STR_LIT>' , default = [ ] , action = '<STR_LIT>' ) <EOL> parser . add_option ( '<STR_LIT>' , default = [ ] , action = '<STR_LIT>' ) <EOL> if args is None : <EOL> args = sys . argv [ <NUM_LIT:1> : ] <EOL> opts , args = parser . parse_args ( list ( args ) ) <EOL> if len ( args ) > <NUM_LIT:0> : <EOL> path = args [ <NUM_LIT:0> ] <EOL> else : <EOL> if os . path . exists ( '<STR_LIT>' ) : <EOL> path = '<STR_LIT>' <EOL> else : <EOL> path = '<STR_LIT>' <EOL> if len ( args ) > <NUM_LIT:1> : <EOL> report_path = args [ <NUM_LIT:1> ] <EOL> else : <EOL> if os . path . isdir ( path ) : <EOL> report_path = os . path . join ( path , '<STR_LIT>' ) <EOL> else : <EOL> report_path = '<STR_LIT>' <EOL> if len ( args ) > <NUM_LIT:2> : <EOL> parser . error ( "<STR_LIT>" ) <EOL> make_coverage_reports ( path , report_path , opts = opts ) <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> main ( ) </s>
