Skip to content

Commit ec0fb69

Browse files
committed
accept_language parse; fix priority order; preserve insertion order
There are conditions under which the order is not correctly returned. Use hashq.hashpop in a loop to get items out of hash (list) in proper priority order. Make 3 element tuples in hashq include insertion order. This makes tuples inserted later lower in priority when priority q values are the same. Makes: "zn;q=1.0;q= 1.0,pt-br,en-US; q=0.5" return ['zn', 'pt_br', 'en_US'] (pt_br is default prio of 1 like zn). Otherwise we get ['pt_br', 'zn', 'en_US'] since 'p' > 'z'.
1 parent ec27f48 commit ec0fb69

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

roundup/cgi/accept_language.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,18 @@ def parse(language_header):
6464
# use a heap queue to sort by quality values.
6565
# the value of each item is 1.0 complement.
6666
pq = []
67+
order=0
6768
for l in qls:
69+
order +=1
6870
if l[0] != '':
69-
heapq.heappush(pq, (0.0, l[0]))
71+
heapq.heappush(pq, (0.0, order, l[0]))
7072
else:
71-
heapq.heappush(pq, (1.0-float(l[2]), l[1]))
73+
heapq.heappush(pq, (1.0-float(l[2]), order, l[1]))
7274

7375
# get the languages ordered by quality
7476
# and replace - by _
75-
return [x[1].replace('-', '_') for x in pq]
77+
return [ heapq.heappop(pq)[2].replace('-','_')
78+
for x in range(len(pq)) ]
7679

7780
if __name__ == "__main__":
7881
import doctest

test/test_misc.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,18 @@ class AcceptLanguageTest(unittest.TestCase):
88
def testParse(self):
99
self.assertEqual(parse("da, en-gb;q=0.8, en;q=0.7"),
1010
['da', 'en_gb', 'en'])
11+
self.assertEqual(parse("da, en-gb;q=0.7, en;q=0.8"),
12+
['da', 'en', 'en_gb'])
1113
self.assertEqual(parse("en;q=0.2, fr;q=1"), ['fr', 'en'])
1214
self.assertEqual(parse("zn; q = 0.2 ,pt-br;q =1"), ['pt_br', 'zn'])
15+
self.assertEqual(parse("pt-br;q =1, zn; q = 0.2"), ['pt_br', 'zn'])
16+
self.assertEqual(parse("pt-br,zn;q= 0.1, en-US;q=0.5"),
17+
['pt_br', 'en_US', 'zn'])
18+
# verify that items with q=1.0 are in same output order as input
19+
self.assertEqual(parse("pt-br,en-US; q=0.5, zn;q= 1.0" ),
20+
['pt_br', 'zn', 'en_US'])
21+
self.assertEqual(parse("zn;q=1.0;q= 1.0,pt-br,en-US; q=0.5" ),
22+
['zn', 'pt_br', 'en_US'])
1323
self.assertEqual(parse("es-AR"), ['es_AR'])
1424
self.assertEqual(parse("es-es-cat"), ['es_es_cat'])
1525
self.assertEqual(parse(""), [])

0 commit comments

Comments
 (0)