Changeset 249

Show
Ignore:
Timestamp:
Mon Apr 17 10:48:10 2006
Author:
drew
Message:

- preliminary version of xix-coverage script

Files:

Legend:

Unmodified
Added
Removed
Modified
  • trunk/scripts/xix-coverage.py

    r248 r249  
    4 4 """  
    5 5  
    6   from xix.utils import cover  
    7   from optparse import OptionParser  
      6 from xix.utils.cover import AnnotationParser, annotationToXML, annotationToHTML  
      7 from xix.utils.cover import CoverageReportParser, reportToXML, _XSLT  
      8 from optparse import OptionParser  
      9  
      10 import lxml.etree as ET  
    8 11  
    9 12 import os, sys  
     
    11 14 from glob import glob  
    12 15 from commands import getoutput  
      16 from StringIO import StringIO  
    13 17  
    14 18 __author__ = 'Drew Smathers'  
     
    61 65     fd.close()  
    62 66  
      67 def generateXML(reportdir, source):  
      68     print 'Generated coverage annotations'  
      69     parser = AnnotationParser()  
      70     for root, dirs, files in os.walk(pj(source)):  
      71         covers = [ f for f in files if f[-6:] == ',cover' ]  
      72         for cover in covers:  
      73             srcname = pj(root, cover.split(',cover')[0])  
      74             srcname = srcname.replace(os.path.sep, '.')[:-3]  
      75             print 'generating XML/HTML for : ', srcname  
      76             xml_fname = 'coverage_' + srcname.replace('.', '-') + '.xml'  
      77             html_fname = 'coverage_' + srcname.replace('.', '-') + '.html'  
      78             annt = parser.parse(open(pj(root, cover)))  
      79             xml = annotationToXML(annt, tree=True)  
      80             fd = open(pj(reportdir, xml_fname), 'w')  
      81             xml.write(fd)  
      82             xslt = ET.parse(StringIO(_XSLT))  
      83             transform = ET.XSLT(xslt)  
      84             html = transform(xml, modname="'%s'" % srcname)  
      85             fd.close()  
      86             fd = open(pj(reportdir, html_fname), 'w')  
      87             html.write(fd)  
      88             fd.close()  
      89  
      90 _REPORT_XSLT = '''<?xml version="1.0"?>  
      91 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">  
      92 <xsl:output method="html"/>  
      93 <xsl:param name="packagename"/>  
      94 <xsl:template match="/">  
      95     <html><head><title>Coverage Report for <xsl:value-of select="$packagename"/></title>  
      96     <link rel="stylesheet" type="text/css" href="coverage.css"/></head>  
      97     <body>  
      98     <h2>Coverage Report for <xsl:value-of select="$packagename"/></h2>  
      99     <table><tr><th>Module Name</th><th>Statements</th><th>Executed</th><th>Coverage</th></tr>  
      100     <xsl:for-each select="//module">  
      101         <tr>  
      102             <td>  
      103                 <a>  
      104                 <xsl:attribute name="href">  
      105                    <xsl:text>coverage_</xsl:text><xsl:value-of select="translate(@name, '.', '-')"/><xsl:text>.html</xsl:text>  
      106                 </xsl:attribute>  
      107                 <xsl:value-of select="@name"/>  
      108                 </a>  
      109             </td>  
      110             <td><xsl:value-of select="@statements"/></td>  
      111             <td><xsl:value-of select="@executed"/></td>  
      112             <td><xsl:value-of select="@coverage"/></td>  
      113         </tr>  
      114     </xsl:for-each>  
      115     </table>  
      116     </body></html>  
      117 </xsl:template>  
      118  
      119 </xsl:stylesheet>'''  
      120  
      121 def generateIndex(reportdir, source):  
      122     report = CoverageReportParser().parse(open('.report'))  
      123     xml = reportToXML(report, tree=True)  
      124     xslt = ET.parse(StringIO(_REPORT_XSLT))  
      125     transform = ET.XSLT(xslt)  
      126     html = transform(xml, packagename="'%s'" % source)  
      127     fd = open(pj(reportdir, 'index.html'), 'w')  
      128     html.write(fd)  
      129     fd.close()  
      130      
    63 131 def main(opts):  
    64 132     if not os.path.exists('coverage.py'):  
     
    66 134         sys.exit(-1)  
    67 135     prepare_fs(opts.source, opts.copy_compiled, opts.exclude_dirs, opts.depends)  
      136     _mkdir(opts.report_dir)  
      137     reportdir = os.path.abspath(opts.report_dir)  
    68 138     os.chdir('.xcoverage')  
    69 139     print getoutput('python coverage.py -x %s' % opts.command)  
    70 140     annotate(opts.source)  
    71       os.chdir('..')  
    72       _mkdir(opts.report_dir)  
    73       xdir = os.path.abspath('.xcoverage')  
      141     linkmap = generateXML(reportdir, opts.source)  
      142     generateIndex(reportdir, opts.source)  
      143     print 'Report complete. See ' + pj(reportdir, 'index.html')  
    74 144      
    75 145  
  • trunk/xix/utils/cover.py

    r247 r249  
    3 3  
    4 4 from UserList import UserList  
    5   import sys  
      5 import sys, os  
    5 5 from StringIO import StringIO  
    6 6 import lxml.etree as ET  
     
    23 23  
    24 24 class AnnotationParser:  
    25       """example usage:  
    26    
    27       Say we have a file as follows:  
    28        
    29       >>> from xix.utils.mock import File  
    30       >>> t = '''> def foo(a):  
    31       ... >     if a:  
    32       ... !         print 'hello'  
    33       ...   #  just a comment  
    34       ...     
    35       ... > r = lambda : 45  
    36       ...       
    37       ... '''  
    38       >>> f = File(t)  
    39    
    40       Create a parser instance and call parse with file object:  
    41        
    42       >>> parser = AnnotationParser()  
    43       >>> ant = parser.parse(f)  
    44    
    45       The annotation object should be created sucessfully.  Let's see:  
    46        
    47       >>> covered = [ line for line in ant if line.covered ]  
    48       >>> isexec = [ line for line in ant if line.isexec ]  
    49       >>> notexec = [ line for line in ant if not line.isexec ]  
    50       >>> for line in covered:  
    51       ...     print line.text  
    52       def foo(a):  
    53           if a:  
    54       r = lambda : 45  
    55       >>> for line in isexec:  
    56       ...     print line.text  
    57       def foo(a):  
    58           if a:  
    59               print \'hello\'  
    60       r = lambda : 45  
    61       >>> for line in notexec:  
    62       ...     print line.text  
    63       #  just a comment  
    64       <BLANKLINE>  
    65       <BLANKLINE>  
    66       <BLANKLINE>  
    67        
      25     """Parser for annotation files generated by coverage.  
    68 26     """  
    69 27     def parse(self, input):  
     
    84 42  
    85 43 def annotationToXML(annotation, tree=False):  
    86       """example:  
      44     """Transform annotation object to XML string or ElementTree instance  
      45     if tree is True.  
    87 46  
    88       >>> s = '''> def foo(a):  
    89       ... !   print "hello"  
    90       ...   # a comment'''  
    91       >>> from xix.utils.mock import File  
    92       >>> ant = AnnotationParser().parse(File(s))  
    93       >>> result = annotationToXML(ant)  
    94    
    95       Parse the result using lxml:  
    96    
    97       >>> buffer = StringIO('<?xml version="1.0"?>' + result)  
    98       >>> doc = ET.parse(buffer)  
    99       >>> root = doc.getroot()  
    100       >>> print root.tag  
    101       coverageAnnotation  
    102       >>> for node in root.getchildren():  
    103       ...    print node.tag, node.attrib['executable'], node.attrib['covered']  
    104       ...    print 'Text:', node.text  
    105       ...  
    106       line true true  
    107       Text: def foo(a):  
    108       line true false  
    109       Text:   print "hello"  
    110       line false false  
    111       Text: # a comment  
      47     @param annotation: Annotation instance  
      48     @param tree: set to true to return ElementTree instance.  
    112 49     """  
    113 50     etree = _annotationToXML(annotation)  
     
    128 65      
    129 66  
    130   def annotationToHTML(annotation, xslt=None, tree=False):  
      67 def annotationToHTML(annotation, xml=None, xslt=None, tree=False):  
      68     """Transform annotation object to HTML string or ElementTree instance  
      69     if tree is True.  
      70  
      71     @param annotation: Annotation instance  
      72     @param xslt: xslt source for transformation  
      73     @param tree: set to true to return ElementTree instance.  
      74     """  
    131 75     style = xslt or _XSLT  
    132 76     if not hasattr(style, 'read'):  
     
    140 84     html.write(buffer)  
    141 85     return buffer.getvalue()  
      86  
      87 ###########################################  
      88 # Coverage reports  
      89 ###########################################  
      90  
      91 class CoverageReport(UserList):  
      92     package_name = None  
      93  
      94 class CoverageReportEntry:  
      95  
      96     def __init__(self, modname, statements, executed, coverage, missing):  
      97         self.modname = modname  
      98         self.statements = statements  
      99         self.executed = executed  
      100         self.coverage = coverage  
      101         self.missing = missing  
      102  
      103 class CoverageReportParser:  
      104  
      105     def parse(self, input):  
      106         fd = input  
      107         if not hasattr(input, 'read'):  
      108             fd = open(input)  
      109         report = CoverageReport()  
      110         for line in fd.readlines()[2:-2]:  
      111             tokens = line.split()  
      112             modname, stmts, execd, coverage = tokens[:4]  
      113             modname = modname.replace(os.path.sep, '.')  
      114             missed = [ tk.replace(',','') for tk in tokens[4:] ]  
      115             report.append(CoverageReportEntry(modname, stmts, execd, coverage, missed))  
      116         return report  
      117  
      118  
      119 def reportToXML(report, tree=False):  
      120     """Transform report object to XML representation as string or ElementTree  
      121     instance if tree arg is set to True.  
      122  
      123     @param report: report instance  
      124     @param tree: set to true to return ElementTree instance  
      125     """  
      126     etree = _reportToXML(report)  
      127     if tree:  
      128         return etree  
      129     buffer = StringIO()  
      130     etree.write(buffer)  
      131     return buffer.getvalue()  
      132  
      133 def _reportToXML(report):  
      134     root = ET.Element('coverage-report')  
      135     for entry in report:  
      136         elm = ET.SubElement(root, 'module')  
      137         attr = elm.attrib  
      138         attr['name'] = entry.modname  
      139         attr['statements'] = entry.statements  
      140         attr['executed'] = entry.executed  
      141         attr['coverage'] = entry.coverage  
      142         melm = ET.SubElement(elm, 'missing-ranges')  
      143         for missed in entry.missing:  
      144             start_end = missed.split('-')  
      145             if len(start_end) == 2:  
      146                 start, end = start_end  
      147             else:  
      148                 start = end = start_end[0]  
      149             relm = ET.SubElement(melm, 'range')  
      150             relm.attrib['start'] = start  
      151             relm.attrib['end'] = end  
      152     return ET.ElementTree(root)  
    142 153      
    143 154  
     
    145 156 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">  
    146 157 <xsl:output method="html"/>  
    147   <xsl:param name="moduleName"/>  
      158 <xsl:param name="modname"/>  
    147 158 <xsl:template match="/">  
    148       <html><head><title>Coverage Results for <xsl:value-of select="$moduleName"/></title>  
      159     <xsl:message>modname is <xsl:value-of select="$modname"/></xsl:message>  
      160     <html><head><title>Coverage Results for <xsl:value-of select="$modname"/></title>  
    149 161     <link rel="stylesheet" type="text/css" href="coverage.css"/></head>  
    150 162     <body>  
    151       <h2>Coverage Results for <xsl:value-of select="$moduleName"/></h2>  
      163     <h2>Coverage Results for <xsl:value-of select="$modname"/></h2>  
    151 163     <div class="annotated-source-code">  
    152 164     <xsl:for-each select="/coverageAnnotation/line">  
  • trunk/runtests.py

    r248 r249  
    10 10 try:  
    11 11     from zope.testing import doctest  
    12       print 'using zope doctest'  
    13 12 except ImportError:  
    14 13     import doctest