Code

- add comment to clarify semantics if pytz is installed
[roundup.git] / roundup / cgi / accept_language.py
1 """Parse the Accept-Language header as defined in RFC2616.
3 See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4
4 for details.  This module should follow the spec.
5 Author: Hernan M. Foffani (hfoffani@gmail.com)
6 Some use samples:
8 >>> parse("da, en-gb;q=0.8, en;q=0.7")
9 ['da', 'en_gb', 'en']
10 >>> parse("en;q=0.2, fr;q=1")
11 ['fr', 'en']
12 >>> parse("zn; q = 0.2 ,pt-br;q =1")
13 ['pt_br', 'zn']
14 >>> parse("es-AR")
15 ['es_AR']
16 >>> parse("es-es-cat")
17 ['es_es_cat']
18 >>> parse("")
19 []
20 >>> parse(None)
21 []
22 >>> parse("   ")
23 []
24 >>> parse("en,")
25 ['en']
26 """
28 import re
29 import heapq
31 # regexp for languange-range search
32 nqlre = "([A-Za-z]+[-[A-Za-z]+]*)$"
33 # regexp for languange-range search with quality value
34 qlre  = "([A-Za-z]+[-[A-Za-z]+]*);q=([\d\.]+)"
35 # both
36 lre   = re.compile(nqlre + "|" + qlre)
38 ascii = ''.join([chr(x) for x in range(256)])
39 whitespace = ' \t\n\r\v\f'
41 def parse(language_header):
42     """parse(string_with_accept_header_content) -> languages list"""
44     if language_header is None: return []
46     # strip whitespaces.
47     lh = language_header.translate(ascii, whitespace)
49     # if nothing, return
50     if lh == "": return []
52     # split by commas and parse the quality values.
53     pls = [lre.findall(x) for x in lh.split(',')]
55     # drop uncomformant
56     qls = [x[0] for x in pls if len(x) > 0]
58     # use a heap queue to sort by quality values.
59     # the value of each item is 1.0 complement.
60     pq = []
61     for l in qls:
62         if l[0] != '':
63             heapq.heappush(pq, (0.0, l[0]))
64         else:
65             heapq.heappush(pq, (1.0-float(l[2]), l[1]))
67     # get the languages ordered by quality
68     # and replace - by _
69     return [x[1].replace('-','_') for x in pq]
71 if __name__ == "__main__":
72     import doctest
73     doctest.testmod()
75 # vim: set et sts=4 sw=4 :