Skip to content

Commit c73b7bf

Browse files
author
kragen
committed
added summarization code for lists of Congresses, for later display on politician search pages
1 parent ae6389c commit c73b7bf

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

webapp.py

+62
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#!/usr/bin/env python
2+
# -*- coding: utf-8 -*-
23
import re, sys
34
import web
45

@@ -685,6 +686,67 @@ def notfound():
685686
def internalerror():
686687
return web.internalerror(file('templates/500.html').read())
687688

689+
def and_join(phrases):
690+
"""Format a list of phrases as an English list.
691+
692+
This must already exist in web.py but I can't find it."""
693+
phrases = list(phrases)
694+
assert len(phrases) > 0 # caller should special-case this
695+
if len(phrases) == 1:
696+
return phrases[0]
697+
elif len(phrases) == 2:
698+
return ' and '.join(phrases)
699+
else:
700+
return ', '.join(phrases[:-1] + ['and ' + phrases[-1]])
701+
702+
def pluralize(noun, plural, number):
703+
"""Inflect a noun for number."""
704+
if number == 1:
705+
return noun
706+
else:
707+
return plural
708+
709+
def divide_into_ranges(ints):
710+
"""Summarize a sorted sequence of ints as a sequence of contiguous ranges.
711+
712+
Return value is a list of lists of the form `[start, stop]`, where `stop`
713+
is one more than the last item in the range.
714+
"""
715+
rv = []
716+
717+
for item in ints:
718+
if len(rv) == 0:
719+
rv.append([item, item+1])
720+
elif item == rv[-1][1]:
721+
rv[-1][1] += 1
722+
else:
723+
rv.append([item, item+1])
724+
725+
return rv
726+
727+
def congress_ranges(congresses):
728+
"""Format a list of Congress ordinal numbers
729+
as a coalesced English sequence of ranges."""
730+
731+
nthstr = web.utils.nthstr
732+
733+
if not congresses:
734+
return "no known Congresses"
735+
736+
ranges = divide_into_ranges(congresses)
737+
phrases = []
738+
for start, stop in ranges:
739+
if stop == start + 1:
740+
phrases.append(nthstr(start))
741+
elif stop == start + 2:
742+
phrases.append(nthstr(start))
743+
phrases.append(nthstr(start+1))
744+
else:
745+
phrases.append('%s–%s' % (nthstr(start), nthstr(stop-1)))
746+
747+
return "the %s %s" % (and_join(phrases),
748+
pluralize("Congress", "Congresses", len(congresses)))
749+
688750
app.notfound = notfound
689751
if production_mode:
690752
app.internalerror = web.emailerrors(config.send_errors_to, internalerror)

webapp_test.py

+21
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,26 @@ def test_dproperty():
239239
def test_blog():
240240
html('/blog/')
241241

242+
def test_congress_ranges():
243+
ok(webapp.pluralize('Congress', 'Congresses', 0), 'Congresses')
244+
ok(webapp.pluralize('Congress', 'Congresses', 1), 'Congress')
245+
ok(webapp.pluralize('Congress', 'Congresses', 2), 'Congresses')
246+
ok(webapp.pluralize('Congress', 'Congresses', 20), 'Congresses')
247+
248+
ok(webapp.congress_ranges([]), "no known Congresses")
249+
ok(webapp.congress_ranges([104]), "the 104th Congress")
250+
ok(webapp.congress_ranges([102]), "the 102nd Congress")
251+
ok(webapp.congress_ranges([102, 103]), "the 102nd and 103rd Congresses")
252+
ok(webapp.congress_ranges([102, 104, 105]),
253+
"the 102nd, 104th, and 105th Congresses")
254+
ok(webapp.congress_ranges([100, 102, 104, 105]),
255+
"the 100th, 102nd, 104th, and 105th Congresses")
256+
ok(webapp.congress_ranges([102, 103, 104]), "the 102nd–104th Congresses")
257+
ok(webapp.congress_ranges([86, 87, 88, 90, 91, 92]),
258+
"the 86th–88th and 90th–92nd Congresses")
259+
ok(webapp.congress_ranges([86, 87, 88, 90, 91, 92, 94, 95, 96]),
260+
"the 86th–88th, 90th–92nd, and 94th–96th Congresses")
261+
242262
def test_webapp():
243263
"Test the actual watchdog.net webapp.app app."
244264
test_state()
@@ -249,6 +269,7 @@ def test_webapp():
249269
test_find() # slow
250270

251271
def main():
272+
test_congress_ranges()
252273
test_webapp()
253274

254275

0 commit comments

Comments
 (0)