github.com/covergates/covergates@v0.2.2-0.20201009050117-42ef8a19fb95/service/python/report.go (about)

     1  package python
     2  
     3  import (
     4  	"context"
     5  	"encoding/xml"
     6  	"io"
     7  	"io/ioutil"
     8  	"path/filepath"
     9  
    10  	"github.com/covergates/covergates/core"
    11  	"github.com/covergates/covergates/service/common"
    12  )
    13  
    14  // CoverageService of python
    15  type CoverageService struct{}
    16  
    17  type coverage struct {
    18  	XMLName  xml.Name `xml:"coverage"`
    19  	Sources  []string `xml:"sources>source"`
    20  	Packages []pkg    `xml:"packages>package"`
    21  }
    22  
    23  type pkg struct {
    24  	Name    string  `xml:"name,attr"`
    25  	Classes []class `xml:"classes>class"`
    26  }
    27  
    28  type class struct {
    29  	Name     string  `xml:"filename,attr"`
    30  	Lines    []line  `xml:"lines>line"`
    31  	LineRate float64 `xml:"line-rate,attr"`
    32  }
    33  
    34  type line struct {
    35  	Number int `xml:"number,attr"`
    36  	Hits   int `xml:"hits,attr"`
    37  }
    38  
    39  // Report of python coverage
    40  func (s *CoverageService) Report(ctx context.Context, reader io.Reader) (*core.CoverageReport, error) {
    41  	data, err := ioutil.ReadAll(reader)
    42  	if err != nil {
    43  		return nil, err
    44  	}
    45  	c := &coverage{}
    46  	if err := xml.Unmarshal(data, c); err != nil {
    47  		return nil, err
    48  	}
    49  	result := make([]*core.File, 0)
    50  	for _, pkg := range c.Packages {
    51  		files := pkg.toFiles(c.Source())
    52  		result = append(result, files...)
    53  	}
    54  	report := &core.CoverageReport{
    55  		Type:  core.ReportPython,
    56  		Files: result,
    57  	}
    58  	report.StatementCoverage = report.ComputeStatementCoverage()
    59  	return report, nil
    60  }
    61  
    62  //Find python coverage report in xml format
    63  func (s *CoverageService) Find(ctx context.Context, path string) (string, error) {
    64  	return common.FindReport(path, "coverage.xml")
    65  }
    66  
    67  // Open reader of python coverage report
    68  func (s *CoverageService) Open(ctx context.Context, path string) (io.Reader, error) {
    69  	return common.OpenFileReader(path)
    70  }
    71  
    72  func (c coverage) Source() string {
    73  	return c.Sources[0]
    74  }
    75  
    76  func (p pkg) toFiles(parent string) []*core.File {
    77  	files := make([]*core.File, len(p.Classes))
    78  	for i, class := range p.Classes {
    79  		statementHist := make([]*core.StatementHit, len(class.Lines))
    80  		for j, line := range class.Lines {
    81  			statementHist[j] = &core.StatementHit{
    82  				Hits:       line.Hits,
    83  				LineNumber: line.Number,
    84  			}
    85  		}
    86  		files[i] = &core.File{
    87  			Name:              filepath.Join(parent, class.Name),
    88  			StatementHits:     statementHist,
    89  			StatementCoverage: class.LineRate,
    90  		}
    91  	}
    92  	return files
    93  }