| | 44 | TEMPLATE_MENU = """<html> |
|---|
| | 45 | <head> |
|---|
| | 46 | <title>CherryPy Coverage Menu</title> |
|---|
| | 47 | <style> |
|---|
| | 48 | body {font: 9pt Arial, serif;} |
|---|
| | 49 | #tree {font: 8pt Courier, sans-serif;} |
|---|
| | 50 | #tree a:active, a:focus { |
|---|
| | 51 | background-color: #EEEEFF; |
|---|
| | 52 | padding: 1px; |
|---|
| | 53 | border: 1px solid #9999FF; |
|---|
| | 54 | -moz-outline-style: none; |
|---|
| | 55 | } |
|---|
| | 56 | .fail {color: red;} |
|---|
| | 57 | .pass {color: #888;} |
|---|
| | 58 | #pct {text-align: right;} |
|---|
| | 59 | .inputheader { font-size: small; font-weight: bold; font-style: italic; margin-top: 5px;} |
|---|
| | 60 | input { border: 1px solid #ccc; padding: 2px; } |
|---|
| | 61 | </style> |
|---|
| | 62 | </head> |
|---|
| | 63 | <body> |
|---|
| | 64 | <h2>CherryPy Coverage</h2>""" |
|---|
| | 65 | |
|---|
| | 66 | TEMPLATE_FORM = """ |
|---|
| | 67 | <form action='menu' method=GET> |
|---|
| | 68 | <input type='hidden' name='base' value='%(base)s' /> |
|---|
| | 69 | |
|---|
| | 70 | <div class="inputheader">Options </div> |
|---|
| | 71 | Hide <input type='text' id='hide_depth' name='hide_depth' value='%(hide_depth)s' size='3' /> |
|---|
| | 72 | parent directories<br /> |
|---|
| | 73 | <input type='checkbox' %(showpct)s name='showpct' value='checked'/> show |
|---|
| | 74 | percentages <br /> |
|---|
| | 75 | Hide files over <input type='text' id='pct' name='pct' value='%(pct)s' size='3' /> |
|---|
| | 76 | %% <br /> |
|---|
| | 77 | Exclude files matching<br /> |
|---|
| | 78 | <input type='text' id='exclude' name='exclude' value='%(exclude)s' size='20' /> |
|---|
| | 79 | <br /> |
|---|
| | 80 | |
|---|
| | 81 | <input type='submit' value='Change view' /> |
|---|
| | 82 | </form>""" |
|---|
| | 83 | |
|---|
| | 84 | TEMPLATE_FRAMESET = """<html> |
|---|
| | 85 | <head><title>CherryPy coverage data</title></head> |
|---|
| | 86 | <frameset cols='250, 1*'> |
|---|
| | 87 | <frame src='menu' /> |
|---|
| | 88 | <frame name='main' src='' /> |
|---|
| | 89 | </frameset> |
|---|
| | 90 | </html> |
|---|
| | 91 | """ |
|---|
| | 92 | |
|---|
| | 93 | TEMPLATE_COVERAGE = """<html> |
|---|
| | 94 | <head> |
|---|
| | 95 | <title>Coverage for %(name)s</title> |
|---|
| | 96 | <style> |
|---|
| | 97 | .covered { color: #000; background-color: #fff; } |
|---|
| | 98 | .notcovered { color: #fee; background-color: #500; } |
|---|
| | 99 | .excluded { color: #00f; background-color: #fff; } |
|---|
| | 100 | table .covered, table .notcovered, table .excluded |
|---|
| | 101 | { font-family: Andale Mono, monospace; |
|---|
| | 102 | font-size: 10px; white-space: pre; } |
|---|
| | 103 | |
|---|
| | 104 | .lineno { background-color: #eee;} |
|---|
| | 105 | .notcovered .lineno { background-color: #000;} |
|---|
| | 106 | table { border-collapse: collapse; |
|---|
| | 107 | </style> |
|---|
| | 108 | </head> |
|---|
| | 109 | <body> |
|---|
| | 110 | <h2>%(name)s</h2> |
|---|
| | 111 | <p>Coverage: %(pc)s%%</p>""" |
|---|
| | 112 | |
|---|
| | 113 | TEMPLATE_LOC_COVERED = '<tr class="covered"><td class="lineno">%s </td><td>%s</td></tr>\n' |
|---|
| | 114 | TEMPLATE_LOC_NOT_COVERED = '<tr class="notcovered"><td class="lineno">%s </td><td>%s</td></tr>\n' |
|---|
| | 115 | TEMPLATE_LOC_EXCLUDED = '<tr class="excluded"><td class="lineno">%s </td><td>%s</td></tr>\n' |
|---|
| | 116 | |
|---|
| | 147 | import re |
|---|
| | 148 | def _skip_file(path, exclude): |
|---|
| | 149 | if exclude: |
|---|
| | 150 | return bool(re.search(exclude, path)) |
|---|
| | 151 | |
|---|
| | 152 | def _percent(statements, missing): |
|---|
| | 153 | s = len(statements) |
|---|
| | 154 | e = s - len(missing) |
|---|
| | 155 | if s > 0: |
|---|
| | 156 | return int(round(100.0 * e / s)) |
|---|
| | 157 | return 0 |
|---|
| | 158 | |
|---|
| | 159 | def _show(root, depth=0, path="", pct=0, hide_depth=0, showpct=False): |
|---|
| | 160 | |
|---|
| | 161 | view_depth = depth - hide_depth |
|---|
| | 162 | |
|---|
| | 163 | # Show the directory name and any of our children |
|---|
| | 164 | dirs = [k for k, v in root.iteritems() if v is not None] |
|---|
| | 165 | dirs.sort() |
|---|
| | 166 | for name in dirs: |
|---|
| | 167 | if path: |
|---|
| | 168 | newpath = os.sep.join((path, name)) |
|---|
| | 169 | else: |
|---|
| | 170 | newpath = name |
|---|
| | 171 | |
|---|
| | 172 | if view_depth >= 0: |
|---|
| | 173 | yield "<nobr>" + ("| " * view_depth) + "<b>" |
|---|
| | 174 | yield "<a href='menu?base=%s'>%s</a>" % (newpath, name) |
|---|
| | 175 | yield "</b></nobr><br />\n" |
|---|
| | 176 | |
|---|
| | 177 | for chunk in _show(root[name], depth + 1, newpath, pct, |
|---|
| | 178 | hide_depth, showpct): |
|---|
| | 179 | yield chunk |
|---|
| | 180 | |
|---|
| | 181 | # Now list the files |
|---|
| | 182 | files = [k for k, v in root.iteritems() if v is None] |
|---|
| | 183 | files.sort() |
|---|
| | 184 | for name in files: |
|---|
| | 185 | if path: |
|---|
| | 186 | newpath = os.sep.join((path, name)) |
|---|
| | 187 | else: |
|---|
| | 188 | newpath = name |
|---|
| | 189 | |
|---|
| | 190 | if view_depth < 0: |
|---|
| | 191 | continue |
|---|
| | 192 | |
|---|
| | 193 | pc_str = "" |
|---|
| | 194 | if showpct: |
|---|
| | 195 | try: |
|---|
| | 196 | _, statements, _, missing, _ = coverage.analysis2(newpath) |
|---|
| | 197 | except: |
|---|
| | 198 | # Yes, we really want to pass on all errors. |
|---|
| | 199 | pass |
|---|
| | 200 | else: |
|---|
| | 201 | pc = _percent(statements, missing) |
|---|
| | 202 | pc_str = ("%3d%% " % pc).replace(' ',' ') |
|---|
| | 203 | if pc < float(pct) or pc == -1: |
|---|
| | 204 | pc_str = "<span class='fail'>%s</span>" % pc_str |
|---|
| | 205 | else: |
|---|
| | 206 | pc_str = "<span class='pass'>%s</span>" % pc_str |
|---|
| | 207 | |
|---|
| | 208 | yield ("<nobr>%s%s<a href='report?name=%s' target='main'>%s</a></nobr><br />\n" |
|---|
| | 209 | % ("| " * view_depth, pc_str, newpath, name)) |
|---|
| | 210 | |
|---|
| | 211 | |
|---|
| 84 | | def menu(self, base="", pct=""): |
|---|
| 85 | | yield """<html> |
|---|
| 86 | | <head> |
|---|
| 87 | | <title>CherryPy Coverage Menu</title> |
|---|
| 88 | | <style> |
|---|
| 89 | | body {font: 9pt Arial, serif;} |
|---|
| 90 | | #tree {font: 8pt Courier, sans-serif;} |
|---|
| 91 | | #tree a:active, a:focus { |
|---|
| 92 | | background-color: #EEEEFF; |
|---|
| 93 | | padding: 1px; |
|---|
| 94 | | border: 1px solid #9999FF; |
|---|
| 95 | | -moz-outline-style: none; |
|---|
| 96 | | } |
|---|
| 97 | | .fail {color: red;} |
|---|
| 98 | | #pct {text-align: right;} |
|---|
| 99 | | </style> |
|---|
| 100 | | </head> |
|---|
| 101 | | <body> |
|---|
| 102 | | <h2>CherryPy Coverage</h2>""" |
|---|
| 103 | | |
|---|
| | 218 | def menu(self, base="", pct="50", showpct="", |
|---|
| | 219 | exclude=r'python\d\.\d|test|tut\d|tutorial', |
|---|
| | 220 | hide_depth=str(initial_depth)): |
|---|
| | 221 | |
|---|
| | 222 | yield TEMPLATE_MENU |
|---|
| 126 | | |
|---|
| 127 | | def show(root, depth=0, path=""): |
|---|
| 128 | | dirs = [k for k, v in root.iteritems() if v is not None] |
|---|
| 129 | | dirs.sort() |
|---|
| 130 | | for name in dirs: |
|---|
| 131 | | if path: |
|---|
| 132 | | newpath = os.sep.join((path, name)) |
|---|
| 133 | | else: |
|---|
| 134 | | newpath = name |
|---|
| 135 | | |
|---|
| 136 | | yield "<nobr>" + ("| " * depth) + "<b>" |
|---|
| 137 | | yield "<a href='menu?base=%s'>%s</a>" % (newpath, name) |
|---|
| 138 | | yield "</b></nobr><br />\n" |
|---|
| 139 | | for chunk in show(root[name], depth + 1, newpath): |
|---|
| 140 | | yield chunk |
|---|
| 141 | | |
|---|
| 142 | | files = [k for k, v in root.iteritems() if v is None] |
|---|
| 143 | | files.sort() |
|---|
| 144 | | for name in files: |
|---|
| 145 | | if path: |
|---|
| 146 | | newpath = os.sep.join((path, name)) |
|---|
| 147 | | else: |
|---|
| 148 | | newpath = name |
|---|
| 149 | | |
|---|
| 150 | | pc_str = "" |
|---|
| 151 | | if pct: |
|---|
| 152 | | try: |
|---|
| 153 | | _, statements, _, missing, _ = coverage.analysis2(newpath) |
|---|
| 154 | | except: |
|---|
| 155 | | # Yes, we really want to pass on all errors. |
|---|
| 156 | | pass |
|---|
| 157 | | else: |
|---|
| 158 | | s = len(statements) |
|---|
| 159 | | e = s - len(missing) |
|---|
| 160 | | if s > 0: |
|---|
| 161 | | pc = 100.0 * e / s |
|---|
| 162 | | pc_str = "%d%% " % pc |
|---|
| 163 | | if pc < 100: |
|---|
| 164 | | pc_str = " " + pc_str |
|---|
| 165 | | if pc < 10: |
|---|
| 166 | | pc_str = " " + pc_str |
|---|
| 167 | | if pc < float(pct): |
|---|
| 168 | | pc_str = "<span class='fail'>%s</span>" % pc_str |
|---|
| 169 | | yield ("<nobr>%s%s<a href='report?name=%s' target='main'>%s</a></nobr><br />\n" |
|---|
| 170 | | % ("| " * depth, pc_str, newpath, name)) |
|---|
| 171 | | |
|---|
| 172 | | for chunk in show(tree): |
|---|
| | 241 | for chunk in _show(tree, 0, '/', pct, int(hide_depth), |
|---|
| | 242 | showpct=='checked'): |
|---|
| 193 | | while i < len(statements) and statements[i] < lineno: |
|---|
| 194 | | i = i + 1 |
|---|
| 195 | | while j < len(missing) and missing[j] < lineno: |
|---|
| 196 | | j = j + 1 |
|---|
| 197 | | if i < len(statements) and statements[i] == lineno: |
|---|
| 198 | | covered = j >= len(missing) or missing[j] > lineno |
|---|
| 199 | | if coverage.blank_re.match(line): |
|---|
| 200 | | dest.write(' ') |
|---|
| 201 | | elif coverage.else_re.match(line): |
|---|
| 202 | | # Special logic for lines containing only |
|---|
| 203 | | # 'else:'. See [GDR 2001-12-04b, 3.2]. |
|---|
| 204 | | if i >= len(statements) and j >= len(missing): |
|---|
| 205 | | dest.write('! ') |
|---|
| 206 | | elif i >= len(statements) or j >= len(missing): |
|---|
| 207 | | dest.write('> ') |
|---|
| 208 | | elif statements[i] == missing[j]: |
|---|
| 209 | | dest.write('! ') |
|---|
| 210 | | else: |
|---|
| 211 | | dest.write('> ') |
|---|
| 212 | | elif lineno in excluded: |
|---|
| 213 | | dest.write('- ') |
|---|
| 214 | | elif covered: |
|---|
| 215 | | dest.write('> ') |
|---|
| | 258 | if line == '': |
|---|
| | 259 | yield ' ' |
|---|
| | 260 | continue |
|---|
| | 261 | if lineno in excluded: |
|---|
| | 262 | template = TEMPLATE_LOC_EXCLUDED |
|---|
| | 263 | elif lineno in missing: |
|---|
| | 264 | template = TEMPLATE_LOC_NOT_COVERED |
|---|