DebugClients/Python/coverage/xmlreport.py

changeset 5051
3586ebd9fac8
parent 4491
0d8612e24fef
equal deleted inserted replaced
5047:04e5dfbd3f3d 5051:3586ebd9fac8
2 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt 2 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt
3 3
4 """XML reporting for coverage.py""" 4 """XML reporting for coverage.py"""
5 5
6 import os 6 import os
7 import os.path
7 import sys 8 import sys
8 import time 9 import time
9 import xml.dom.minidom 10 import xml.dom.minidom
10 11
12 from coverage import env
11 from coverage import __url__, __version__, files 13 from coverage import __url__, __version__, files
14 from coverage.backward import iitems
15 from coverage.misc import isolate_module
12 from coverage.report import Reporter 16 from coverage.report import Reporter
17
18 os = isolate_module(os)
19
13 20
14 DTD_URL = ( 21 DTD_URL = (
15 'https://raw.githubusercontent.com/cobertura/web/' 22 'https://raw.githubusercontent.com/cobertura/web/'
16 'f0366e5e2cf18f111cbd61fc34ef720a6584ba02' 23 'f0366e5e2cf18f111cbd61fc34ef720a6584ba02'
17 '/htdocs/xml/coverage-03.dtd' 24 '/htdocs/xml/coverage-03.dtd'
31 38
32 def __init__(self, coverage, config): 39 def __init__(self, coverage, config):
33 super(XmlReporter, self).__init__(coverage, config) 40 super(XmlReporter, self).__init__(coverage, config)
34 41
35 self.source_paths = set() 42 self.source_paths = set()
43 if config.source:
44 for src in config.source:
45 if os.path.exists(src):
46 self.source_paths.add(files.canonical_filename(src))
36 self.packages = {} 47 self.packages = {}
37 self.xml_out = None 48 self.xml_out = None
38 self.has_arcs = coverage.data.has_arcs() 49 self.has_arcs = coverage.data.has_arcs()
39 50
40 def report(self, morfs, outfile=None): 51 def report(self, morfs, outfile=None):
79 90
80 xpackages = self.xml_out.createElement("packages") 91 xpackages = self.xml_out.createElement("packages")
81 xcoverage.appendChild(xpackages) 92 xcoverage.appendChild(xpackages)
82 93
83 # Populate the XML DOM with the package info. 94 # Populate the XML DOM with the package info.
84 for pkg_name in sorted(self.packages.keys()): 95 for pkg_name, pkg_data in sorted(iitems(self.packages)):
85 pkg_data = self.packages[pkg_name]
86 class_elts, lhits, lnum, bhits, bnum = pkg_data 96 class_elts, lhits, lnum, bhits, bnum = pkg_data
87 xpackage = self.xml_out.createElement("package") 97 xpackage = self.xml_out.createElement("package")
88 xpackages.appendChild(xpackage) 98 xpackages.appendChild(xpackage)
89 xclasses = self.xml_out.createElement("classes") 99 xclasses = self.xml_out.createElement("classes")
90 xpackage.appendChild(xclasses) 100 xpackage.appendChild(xclasses)
91 for class_name in sorted(class_elts.keys()): 101 for _, class_elt in sorted(iitems(class_elts)):
92 xclasses.appendChild(class_elts[class_name]) 102 xclasses.appendChild(class_elt)
93 xpackage.setAttribute("name", pkg_name.replace(os.sep, '.')) 103 xpackage.setAttribute("name", pkg_name.replace(os.sep, '.'))
94 xpackage.setAttribute("line-rate", rate(lhits, lnum)) 104 xpackage.setAttribute("line-rate", rate(lhits, lnum))
95 if self.has_arcs: 105 if self.has_arcs:
96 branch_rate = rate(bhits, bnum) 106 branch_rate = rate(bhits, bnum)
97 else: 107 else:
110 else: 120 else:
111 branch_rate = "0" 121 branch_rate = "0"
112 xcoverage.setAttribute("branch-rate", branch_rate) 122 xcoverage.setAttribute("branch-rate", branch_rate)
113 123
114 # Use the DOM to write the output file. 124 # Use the DOM to write the output file.
115 outfile.write(self.xml_out.toprettyxml()) 125 out = self.xml_out.toprettyxml()
126 if env.PY2:
127 out = out.encode("utf8")
128 outfile.write(out)
116 129
117 # Return the total percentage. 130 # Return the total percentage.
118 denom = lnum_tot + bnum_tot 131 denom = lnum_tot + bnum_tot
119 if denom == 0: 132 if denom == 0:
120 pct = 0.0 133 pct = 0.0
125 def xml_file(self, fr, analysis): 138 def xml_file(self, fr, analysis):
126 """Add to the XML report for a single file.""" 139 """Add to the XML report for a single file."""
127 140
128 # Create the 'lines' and 'package' XML elements, which 141 # Create the 'lines' and 'package' XML elements, which
129 # are populated later. Note that a package == a directory. 142 # are populated later. Note that a package == a directory.
130 filename = fr.relative_filename() 143 filename = fr.filename.replace("\\", "/")
131 filename = filename.replace("\\", "/") 144 for source_path in self.source_paths:
132 dirname = os.path.dirname(filename) or "." 145 if filename.startswith(source_path.replace("\\", "/") + "/"):
133 parts = dirname.split("/") 146 rel_name = filename[len(source_path)+1:]
134 dirname = "/".join(parts[:self.config.xml_package_depth]) 147 break
148 else:
149 rel_name = fr.relative_filename()
150
151 dirname = os.path.dirname(rel_name) or "."
152 dirname = "/".join(dirname.split("/")[:self.config.xml_package_depth])
135 package_name = dirname.replace("/", ".") 153 package_name = dirname.replace("/", ".")
136 className = fr.relative_filename() 154
137 155 if rel_name != fr.filename:
138 self.source_paths.add(files.relative_directory().rstrip('/')) 156 self.source_paths.add(fr.filename[:-len(rel_name)].rstrip(r"\/"))
139 package = self.packages.setdefault(package_name, [{}, 0, 0, 0, 0]) 157 package = self.packages.setdefault(package_name, [{}, 0, 0, 0, 0])
140 158
141 xclass = self.xml_out.createElement("class") 159 xclass = self.xml_out.createElement("class")
142 160
143 xclass.appendChild(self.xml_out.createElement("methods")) 161 xclass.appendChild(self.xml_out.createElement("methods"))
144 162
145 xlines = self.xml_out.createElement("lines") 163 xlines = self.xml_out.createElement("lines")
146 xclass.appendChild(xlines) 164 xclass.appendChild(xlines)
147 165
148 xclass.setAttribute("name", os.path.relpath(filename, dirname)) 166 xclass.setAttribute("name", os.path.relpath(rel_name, dirname))
149 xclass.setAttribute("filename", filename) 167 xclass.setAttribute("filename", fr.relative_filename().replace("\\", "/"))
150 xclass.setAttribute("complexity", "0") 168 xclass.setAttribute("complexity", "0")
151 169
152 branch_stats = analysis.branch_stats() 170 branch_stats = analysis.branch_stats()
153 missing_branch_arcs = analysis.missing_branch_arcs() 171 missing_branch_arcs = analysis.missing_branch_arcs()
154 172
191 branch_rate = rate(class_br_hits, class_branches) 209 branch_rate = rate(class_br_hits, class_branches)
192 else: 210 else:
193 branch_rate = "0" 211 branch_rate = "0"
194 xclass.setAttribute("branch-rate", branch_rate) 212 xclass.setAttribute("branch-rate", branch_rate)
195 213
196 package[0][className] = xclass 214 package[0][rel_name] = xclass
197 package[1] += class_hits 215 package[1] += class_hits
198 package[2] += class_lines 216 package[2] += class_lines
199 package[3] += class_br_hits 217 package[3] += class_br_hits
200 package[4] += class_branches 218 package[4] += class_branches
201 219

eric ide

mercurial