Skip to content

Commit f6f0278

Browse files
committed
Changed the url coverage code to handle deeper chains of url includes, and to handle url includes through url lists in addition to url modules. Added information in the release coverage dictionaries about the view functions coupled to the urls.
- Legacy-Id: 13706
1 parent 6b69660 commit f6f0278

4 files changed

Lines changed: 45 additions & 32 deletions

File tree

ietf/utils/management/commands/coverage_changes.py

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ def add_arguments(self, parser):
5050
help='Show absolute figures instead of changes from last release.')
5151

5252

53-
diff_line_format = "%-58s %8s %8s\n"
54-
list_line_format = "%-68s %8s\n"
53+
diff_line_format = "%8s %8s %-58s\n"
54+
list_line_format = "%8s %-68s\n"
5555
valid_sections = ['template', 'url', 'code']
5656

5757
def read_coverage(self, filename, version=None):
@@ -109,9 +109,9 @@ def coverage_diff(self, master, latest, sections, release=None, **options):
109109
else:
110110
raise CommandError("The release coverage data has an unknown format ('%s'), quitting." % mformat)
111111
if lformat == 1:
112-
llines, lcov = None, lcoverage[key]
113-
elif lformat == 2:
114-
llines, lcov = lcoverage[key]
112+
linfo, lcov = None, lcoverage[key]
113+
elif lformat in [2, 4]:
114+
linfo, lcov = lcoverage[key]
115115
else:
116116
raise CommandError("The latest coverage data has an unknown format ('%s'), quitting." % lformat)
117117

@@ -124,10 +124,10 @@ def coverage_diff(self, master, latest, sections, release=None, **options):
124124
if mcov != lcov:
125125
if not header_written:
126126
self.stdout.write(self.diff_line_format %
127-
("\n%s"%section.capitalize(), mversion[:7], lversion[:7]))
128-
self.stdout.write(self.diff_line_format % ("-"*58, "-"*8, "-"*8))
127+
(mversion[:7], lversion[:7], "\n%s"%section.capitalize(), ))
128+
self.stdout.write(self.diff_line_format % ("-"*8, "-"*8, "-"*58))
129129
header_written = True
130-
self.stdout.write(self.diff_line_format % (key, mval, lval))
130+
self.stdout.write(self.diff_line_format % (mval, lval, key, ))
131131
lkey_set = set(lkeys)
132132
rkey_set = set(mkeys)
133133
missing_key_set = rkey_set - lkey_set
@@ -156,9 +156,9 @@ def coverage_list(self, latest, sections, **options):
156156

157157
for key in keys:
158158
if lformat == 1:
159-
llines, lcov = None, lcoverage[key]
160-
elif lformat == 2:
161-
llines, lcov = lcoverage[key]
159+
linfo, lcov = None, lcoverage[key]
160+
elif lformat in [2, 4]:
161+
linfo, lcov = lcoverage[key]
162162
else:
163163
raise CommandError("The latest coverage data has an unknown format ('%s'), quitting." % lformat)
164164

@@ -168,10 +168,10 @@ def coverage_list(self, latest, sections, **options):
168168
lval = lcov
169169
if not header_written:
170170
self.stdout.write(self.list_line_format %
171-
("\n%s"%section.capitalize(), lversion[:7]))
172-
self.stdout.write(self.list_line_format % ("-"*58, "-"*8, ))
171+
(lversion[:7], "\n%s"%section.capitalize(), ))
172+
self.stdout.write(self.list_line_format % ("-"*8, "-"*58, ))
173173
header_written = True
174-
self.stdout.write(self.list_line_format % (key, lval))
174+
self.stdout.write(self.list_line_format % (lval, key))
175175

176176
def handle(self, *args, **options):
177177

ietf/utils/management/commands/tests.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,9 @@ def test_coverage_change(self):
8989
os.unlink(latest)
9090

9191
for l in [
92-
r"admin/group/group/change_form.html False True",
93-
r"^api/v1/?$ True False",
94-
r"^community/personal/$ False True",
95-
r"ietf/community/constants - 50.0 %",
92+
r" False True admin/group/group/change_form.html ",
93+
r" True False ^api/v1/?$ ",
94+
r" False True ^community/personal/$ ",
95+
r" - 50.0 % ietf/community/constants ",
9696
]:
9797
self.assertTrue(l in text, msg="Missing line in coverage_change output:\n'%s'\n"%l)

ietf/utils/test_runner.py

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -147,18 +147,28 @@ def exclude(name):
147147
if re.search(pat, name):
148148
return True
149149
return False
150+
def append(res, p0, p1, item):
151+
if p1.startswith("^"):
152+
res.append((p0 + p1[1:], item))
153+
else:
154+
res.append((item.p0 + ".*" + p1, item))
150155
if not hasattr(module, 'urlpatterns'):
151156
return []
152157
res = []
153158
for item in module.urlpatterns:
154-
if isinstance(item, RegexURLResolver) and not type(item.urlconf_module) is list:
155-
if include(item.urlconf_module.__name__) and not exclude(item.regex.pattern):
156-
subpatterns = get_url_patterns(item.urlconf_module)
157-
for sub, subitem in subpatterns:
158-
if sub.startswith("^"):
159-
res.append((item.regex.pattern + sub[1:], subitem))
159+
if isinstance(item, RegexURLResolver):
160+
if type(item.urlconf_module) is list:
161+
for subitem in item.urlconf_module:
162+
if isinstance(subitem, RegexURLResolver):
163+
res += get_url_patterns(subitem.urlconf_module)
160164
else:
161-
res.append((item.regex.pattern + ".*" + sub, subitem))
165+
sub = subitem.regex.pattern
166+
append(res, item.regex.pattern, subitem.regex.pattern, subitem)
167+
else:
168+
if include(item.urlconf_module.__name__) and not exclude(item.regex.pattern):
169+
subpatterns = get_url_patterns(item.urlconf_module)
170+
for sub, subitem in subpatterns:
171+
append(res, item.regex.pattern, sub, subitem)
162172
else:
163173
res.append((item.regex.pattern, item))
164174
return res
@@ -287,6 +297,7 @@ def template_coverage_test(self):
287297
self.runner.coverage_data["template"] = {
288298
"coverage": (1.0*len(covered)/len(all)) if len(all)>0 else float('nan'),
289299
"covered": dict( (k, k in covered) for k in all ),
300+
"format": 1,
290301
}
291302
self.report_test_result("template")
292303
else:
@@ -296,30 +307,32 @@ def url_coverage_test(self):
296307
if self.runner.check_coverage:
297308
import ietf.urls
298309
url_patterns = get_url_patterns(ietf.urls, self.runner.test_apps)
310+
#debug.pprint('[ r for r,p in url_patterns]')
299311

300312
# skip some patterns that we don't bother with
301313
def ignore_pattern(regex, pattern):
302314
import django.views.static
303315
return (regex in ("^_test500/$", "^accounts/testemail/$")
304316
or regex.startswith("^admin/")
317+
or re.search('^api/v1/[^/]+/[^/]+/', regex)
305318
or getattr(pattern.callback, "__name__", "") == "RedirectView"
306319
or getattr(pattern.callback, "__name__", "") == "TemplateView"
307320
or pattern.callback == django.views.static.serve)
308321

309-
patterns = [(regex, re.compile(regex, re.U)) for regex, pattern in url_patterns
310-
if not ignore_pattern(regex, pattern)]
311-
all = [ regex for regex, compiled in patterns ]
322+
patterns = [(regex, re.compile(regex, re.U), obj) for regex, obj in url_patterns
323+
if not ignore_pattern(regex, obj)]
312324

313325
covered = set()
314326
for url in visited_urls:
315-
for regex, compiled in patterns:
327+
for regex, compiled, obj in patterns:
316328
if regex not in covered and compiled.match(url[1:]): # strip leading /
317329
covered.add(regex)
318330
break
319331

320332
self.runner.coverage_data["url"] = {
321-
"coverage": 1.0*len(covered)/len(all),
322-
"covered": dict( (k, k in covered) for k in all ),
333+
"coverage": 1.0*len(covered)/len(patterns),
334+
"covered": dict( (k, (o.lookup_str, k in covered)) for k,p,o in patterns ),
335+
"format": 4,
323336
}
324337

325338
self.report_test_result("url")
@@ -475,7 +488,7 @@ def setup_test_environment(self, **kwargs):
475488
"url": {
476489
"coverage": 0.0,
477490
"covered": {},
478-
"format": 1,
491+
"format": 4,
479492
},
480493
"code": {
481494
"coverage": 0.0,

release-coverage.json.gz

18.6 KB
Binary file not shown.

0 commit comments

Comments
 (0)