diff options
| author | Sergey Schetinin <sergey@maluke.com> | 2011-09-07 22:24:37 +0300 |
|---|---|---|
| committer | Sergey Schetinin <sergey@maluke.com> | 2011-09-07 22:24:37 +0300 |
| commit | 66ffc0b7a04ce5ef749b6c25f5d152fccb645ea0 (patch) | |
| tree | 6c2591e3aa19b3985acada9eba9af4c9b6af8d9f | |
| parent | 254b49df3508f78997906d885c0b5fc386223065 (diff) | |
| download | webob-66ffc0b7a04ce5ef749b6c25f5d152fccb645ea0.tar.gz | |
* add AcceptCharset and AcceptLanguage subclasses instead of branching in Accept.__init__
* that allows us to remove Accept.header_name
* and change Accept.__repr__ to be more straightforward
| -rw-r--r-- | docs/reference.txt | 2 | ||||
| -rw-r--r-- | docs/test_request.txt | 4 | ||||
| -rw-r--r-- | tests/test_acceptparse.py | 163 | ||||
| -rw-r--r-- | webob/acceptparse.py | 115 | ||||
| -rw-r--r-- | webob/request.py | 6 |
5 files changed, 128 insertions, 162 deletions
diff --git a/docs/reference.txt b/docs/reference.txt index 194589b..f44d80e 100644 --- a/docs/reference.txt +++ b/docs/reference.txt @@ -345,7 +345,7 @@ example means that ``text/html`` is okay, but >>> req.accept = 'text/html;q=0.5, application/xhtml+xml;q=1' >>> req.accept - <MIMEAccept at ... Accept: text/html;q=0.5, application/xhtml+xml> + <MIMEAccept('text/html;q=0.5, application/xhtml+xml')> >>> 'text/html' in req.accept True diff --git a/docs/test_request.txt b/docs/test_request.txt index 5319592..f708e40 100644 --- a/docs/test_request.txt +++ b/docs/test_request.txt @@ -215,7 +215,7 @@ mime types are not supported. >>> req = Request.blank('/') >>> req.environ['HTTP_ACCEPT'] = "text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.1" >>> req.accept # doctest: +ELLIPSIS - <MIMEAccept at ... Accept: text/*;q=0.3, text/html;q=0.7, text/html, text/html;q=0.4, */*;q=0.1> + <MIMEAccept('text/*;q=0.3, text/html;q=0.7, text/html, text/html;q=0.4, */*;q=0.1')> >>> for item, quality in req.accept._parsed: ... print '%s: %0.1f' % (item, quality) text/*: 0.3 @@ -233,7 +233,7 @@ mime types are not supported. True >>> req.environ['HTTP_ACCEPT'] = "text/html, application/xml; q=0.7, text/*; q=0.5, */*; q=0.1" >>> req.accept # doctest: +ELLIPSIS - <MIMEAccept at ... Accept: text/html, application/xml;q=0.7, text/*;q=0.5, */*;q=0.1> + <MIMEAccept('text/html, application/xml;q=0.7, text/*;q=0.5, */*;q=0.1')> >>> req.accept.best_match(['text/plain', 'application/xml']) 'application/xml' >>> req.accept.first_match(['application/xml', 'text/html']) diff --git a/tests/test_acceptparse.py b/tests/test_acceptparse.py index a1e8adc..7fb1394 100644 --- a/tests/test_acceptparse.py +++ b/tests/test_acceptparse.py @@ -1,101 +1,78 @@ from webob import Request -from webob.acceptparse import Accept, MIMEAccept, NilAccept, NoAccept, accept_property, parse_accept +from webob.acceptparse import Accept, MIMEAccept, NilAccept, NoAccept, accept_property, AcceptLanguage, AcceptCharset from nose.tools import eq_, assert_raises def test_parse_accept_badq(): - assert parse_accept("value1; q=0.1.2") == [('value1', 1)] + assert list(Accept.parse("value1; q=0.1.2")) == [('value1', 1)] def test_init_accept_content_type(): - name, value = ('Content-Type', 'text/html') - accept = Accept(name, value) - assert accept.header_name == name - assert accept.header_value == value + accept = Accept('text/html') assert accept._parsed == [('text/html', 1)] def test_init_accept_accept_charset(): - name, value = ('Accept-Charset', 'iso-8859-5, unicode-1-1;q=0.8') - accept = Accept(name, value) - assert accept.header_name == name - assert accept.header_value == value + accept = AcceptCharset('iso-8859-5, unicode-1-1;q=0.8') assert accept._parsed == [('iso-8859-5', 1), ('unicode-1-1', 0.80000000000000004), ('iso-8859-1', 1)] def test_init_accept_accept_charset_with_iso_8859_1(): - name, value = ('Accept-Charset', 'iso-8859-1') - accept = Accept(name, value) - assert accept.header_name == name - assert accept.header_value == value + accept = Accept('iso-8859-1') assert accept._parsed == [('iso-8859-1', 1)] def test_init_accept_accept_charset_wildcard(): - name, value = ('Accept-Charset', '*') - accept = Accept(name, value) - assert accept.header_name == name - assert accept.header_value == value + accept = Accept('*') assert accept._parsed == [('*', 1)] def test_init_accept_accept_language(): - name, value = ('Accept-Language', 'da, en-gb;q=0.8, en;q=0.7') - accept = Accept(name, value) - assert accept.header_name == name - assert accept.header_value == value + accept = AcceptLanguage('da, en-gb;q=0.8, en;q=0.7') assert accept._parsed == [('da', 1), ('en-gb', 0.80000000000000004), ('en', 0.69999999999999996)] def test_init_accept_invalid_value(): - name, value = ('Accept-Language', 'da, q, en-gb;q=0.8') - accept = Accept(name, value) + accept = AcceptLanguage('da, q, en-gb;q=0.8') # The "q" value should not be there. assert accept._parsed == [('da', 1), ('en-gb', 0.80000000000000004)] def test_init_accept_invalid_q_value(): - name, value = ('Accept-Language', 'da, en-gb;q=foo') - accept = Accept(name, value) + accept = AcceptLanguage('da, en-gb;q=foo') # I can't get to cover line 40-41 (webob.acceptparse) as the regex # will prevent from hitting these lines (aconrad) assert accept._parsed == [('da', 1), ('en-gb', 1)] def test_accept_repr(): - name, value = ('Content-Type', 'text/html') - accept = Accept(name, value) - assert repr(accept) == '<%s at 0x%x %s: %s>' % ('Accept', - abs(id(accept)), - name, - str(accept)) + accept = Accept('text/html') + assert repr(accept) == "<Accept('text/html')>" def test_accept_str(): - name, value = ('Content-Type', 'text/html') - accept = Accept(name, value) - assert str(accept) == value + accept = Accept('text/html') + assert str(accept) == 'text/html' def test_zero_quality(): - assert Accept('Accept-Encoding', 'bar, *;q=0').best_match(['foo']) is None - assert 'foo' not in Accept('Accept-Encoding', '*;q=0') - assert Accept('Accept-Encoding', 'foo, *;q=0').first_match(['bar', 'foo']) == 'foo' + assert Accept('bar, *;q=0').best_match(['foo']) is None + assert 'foo' not in Accept('*;q=0') + assert Accept('foo, *;q=0').first_match(['bar', 'foo']) == 'foo' def test_accept_str_with_q_not_1(): - name, value = ('Content-Type', 'text/html;q=0.5') - accept = Accept(name, value) + value = 'text/html;q=0.5' + accept = Accept(value) assert str(accept) == value def test_accept_str_with_q_not_1_multiple(): - name, value = ('Content-Type', 'text/html;q=0.5, foo/bar') - accept = Accept(name, value) + value = 'text/html;q=0.5, foo/bar' + accept = Accept(value) assert str(accept) == value def test_accept_add_other_accept(): - accept = Accept('Content-Type', 'text/html') + \ - Accept('Content-Type', 'foo/bar') + accept = Accept('text/html') + Accept('foo/bar') assert str(accept) == 'text/html, foo/bar' - accept += Accept('Content-Type', 'bar/baz;q=0.5') + accept += Accept('bar/baz;q=0.5') assert str(accept) == 'text/html, foo/bar, bar/baz;q=0.5' def test_accept_add_other_list_of_tuples(): - accept = Accept('Content-Type', 'text/html') + accept = Accept('text/html') accept += [('foo/bar', 1)] assert str(accept) == 'text/html, foo/bar' accept += [('bar/baz', 0.5)] @@ -105,42 +82,42 @@ def test_accept_add_other_list_of_tuples(): 'she/bangs, the/house') def test_accept_add_other_dict(): - accept = Accept('Content-Type', 'text/html') + accept = Accept('text/html') accept += {'foo/bar': 1} assert str(accept) == 'text/html, foo/bar' accept += {'bar/baz': 0.5} assert str(accept) == 'text/html, foo/bar, bar/baz;q=0.5' def test_accept_add_other_empty_str(): - accept = Accept('Content-Type', 'text/html') + accept = Accept('text/html') accept += '' assert str(accept) == 'text/html' def test_accept_with_no_value_add_other_str(): - accept = Accept('Content-Type', '') + accept = Accept('') accept += 'text/html' assert str(accept) == 'text/html' def test_contains(): - accept = Accept('Content-Type', 'text/html') + accept = Accept('text/html') assert 'text/html' in accept def test_contains_not(): - accept = Accept('Content-Type', 'text/html') + accept = Accept('text/html') assert not 'foo/bar' in accept def test_quality(): - accept = Accept('Content-Type', 'text/html') + accept = Accept('text/html') assert accept.quality('text/html') == 1 - accept = Accept('Content-Type', 'text/html;q=0.5') + accept = Accept('text/html;q=0.5') assert accept.quality('text/html') == 0.5 def test_quality_not_found(): - accept = Accept('Content-Type', 'text/html') + accept = Accept('text/html') assert accept.quality('foo/bar') is None def test_first_match(): - accept = Accept('Content-Type', 'text/html, foo/bar') + accept = Accept('text/html, foo/bar') assert accept.first_match(['text/html', 'foo/bar']) == 'text/html' assert accept.first_match(['foo/bar', 'text/html']) == 'foo/bar' assert accept.first_match(['xxx/xxx', 'text/html']) == 'text/html' @@ -151,7 +128,7 @@ def test_first_match(): assert_raises(ValueError, accept.first_match, []) def test_best_match(): - accept = Accept('Content-Type', 'text/html, foo/bar') + accept = Accept('text/html, foo/bar') assert accept.best_match(['text/html', 'foo/bar']) == 'text/html' assert accept.best_match(['foo/bar', 'text/html']) == 'foo/bar' assert accept.best_match([('foo/bar', 0.5), @@ -161,25 +138,25 @@ def test_best_match(): assert_raises(ValueError, accept.best_match, ['text/*']) def test_best_match_with_one_lower_q(): - accept = Accept('Content-Type', 'text/html, foo/bar;q=0.5') + accept = Accept('text/html, foo/bar;q=0.5') assert accept.best_match(['text/html', 'foo/bar']) == 'text/html' - accept = Accept('Content-Type', 'text/html;q=0.5, foo/bar') + accept = Accept('text/html;q=0.5, foo/bar') assert accept.best_match(['text/html', 'foo/bar']) == 'foo/bar' def test_best_matches(): - accept = Accept('Content-Type', 'text/html, foo/bar') + accept = Accept('text/html, foo/bar') assert accept.best_matches() == ['text/html', 'foo/bar'] - accept = Accept('Content-Type', 'text/html, foo/bar;q=0.5') + accept = Accept('text/html, foo/bar;q=0.5') assert accept.best_matches() == ['text/html', 'foo/bar'] - accept = Accept('Content-Type', 'text/html;q=0.5, foo/bar') + accept = Accept('text/html;q=0.5, foo/bar') assert accept.best_matches() == ['foo/bar', 'text/html'] def test_best_matches_with_fallback(): - accept = Accept('Content-Type', 'text/html, foo/bar') + accept = Accept('text/html, foo/bar') assert accept.best_matches('xxx/yyy') == ['text/html', 'foo/bar', 'xxx/yyy'] - accept = Accept('Content-Type', 'text/html;q=0.5, foo/bar') + accept = Accept('text/html;q=0.5, foo/bar') assert accept.best_matches('xxx/yyy') == ['foo/bar', 'text/html', 'xxx/yyy'] @@ -188,8 +165,8 @@ def test_best_matches_with_fallback(): def test_accept_match(): for mask in ['*', 'text/html', 'TEXT/HTML']: - assert 'text/html' in Accept('Content-Type', mask) - assert 'text/html' not in Accept('Content-Type', 'foo/bar') + assert 'text/html' in Accept(mask) + assert 'text/html' not in Accept('foo/bar') def test_accept_match_lang(): for mask, lang in [ @@ -198,16 +175,15 @@ def test_accept_match_lang(): ('en', 'en-gb'), ('en-gb', 'en-gb'), ]: - assert lang in Accept('Accept-Language', mask) - assert 'fr-fr' not in Accept('Accept-Language', 'en-gb') + assert lang in AcceptLanguage(mask) + assert 'fr-fr' not in AcceptLanguage('en-gb') # NilAccept tests def test_nil(): - nilaccept = NilAccept('Connection-Close') - assert nilaccept.header_name == 'Connection-Close' + nilaccept = NilAccept() eq_(repr(nilaccept), - "<NilAccept for Connection-Close: <class 'webob.acceptparse.Accept'>>" + "<NilAccept: <class 'webob.acceptparse.Accept'>>" ) assert not nilaccept assert str(nilaccept) == '' @@ -217,21 +193,19 @@ def test_nil(): def test_nil_add(): - nilaccept = NilAccept('Connection-Close') - accept = Accept('Content-Type', 'text/html') + nilaccept = NilAccept() + accept = Accept('text/html') assert nilaccept + accept is accept new_accept = nilaccept + nilaccept assert isinstance(new_accept, accept.__class__) - assert new_accept.header_name == 'Connection-Close' assert new_accept.header_value == '' new_accept = nilaccept + 'foo' assert isinstance(new_accept, accept.__class__) - assert new_accept.header_name == 'Connection-Close' assert new_accept.header_value == 'foo' def test_nil_radd(): - nilaccept = NilAccept('Connection-Close') - accept = Accept('Content-Type', 'text/html') + nilaccept = NilAccept() + accept = Accept('text/html') assert isinstance('foo' + nilaccept, accept.__class__) assert ('foo' + nilaccept).header_value == 'foo' # How to test ``if isinstance(item, self.MasterClass): return item`` @@ -239,22 +213,22 @@ def test_nil_radd(): def test_nil_radd_masterclass(): # Is this "reaching into" __radd__ legit? - nilaccept = NilAccept('Connection-Close') - accept = Accept('Content-Type', 'text/html') + nilaccept = NilAccept() + accept = Accept('text/html') assert nilaccept.__radd__(accept) is accept def test_nil_contains(): - nilaccept = NilAccept('Connection-Close') + nilaccept = NilAccept() assert 'anything' in nilaccept def test_nil_first_match(): - nilaccept = NilAccept('Connection-Close') + nilaccept = NilAccept() # NilAccept.first_match always returns element 0 of the list assert nilaccept.first_match(['dummy', '']) == 'dummy' assert nilaccept.first_match(['', 'dummy']) == '' def test_nil_best_match(): - nilaccept = NilAccept('Connection-Close') + nilaccept = NilAccept() assert nilaccept.best_match(['foo', 'bar']) == 'foo' assert nilaccept.best_match([('foo', 1), ('bar', 0.5)]) == 'foo' assert nilaccept.best_match([('foo', 0.5), ('bar', 1)]) == 'bar' @@ -268,33 +242,33 @@ def test_nil_best_match(): # NoAccept tests def test_noaccept_contains(): - assert 'text/plain' not in NoAccept('Connection-Close') + assert 'text/plain' not in NoAccept() # MIMEAccept tests def test_mime_init(): - mimeaccept = MIMEAccept('Content-Type', 'image/jpg') + mimeaccept = MIMEAccept('image/jpg') assert mimeaccept._parsed == [('image/jpg', 1)] - mimeaccept = MIMEAccept('Content-Type', 'image/png, image/jpg;q=0.5') + mimeaccept = MIMEAccept('image/png, image/jpg;q=0.5') assert mimeaccept._parsed == [('image/png', 1), ('image/jpg', 0.5)] - mimeaccept = MIMEAccept('Content-Type', 'image, image/jpg;q=0.5') + mimeaccept = MIMEAccept('image, image/jpg;q=0.5') assert mimeaccept._parsed == [('image/jpg', 0.5)] - mimeaccept = MIMEAccept('Content-Type', '*/*') + mimeaccept = MIMEAccept('*/*') assert mimeaccept._parsed == [('*/*', 1)] - mimeaccept = MIMEAccept('Content-Type', '*/png') + mimeaccept = MIMEAccept('*/png') assert mimeaccept._parsed == [] - mimeaccept = MIMEAccept('Content-Type', 'image/*') + mimeaccept = MIMEAccept('image/*') assert mimeaccept._parsed == [('image/*', 1)] def test_accept_html(): - mimeaccept = MIMEAccept('Content-Type', 'image/jpg') + mimeaccept = MIMEAccept('image/jpg') assert not mimeaccept.accept_html() - mimeaccept = MIMEAccept('Content-Type', 'image/jpg, text/html') + mimeaccept = MIMEAccept('image/jpg, text/html') assert mimeaccept.accept_html() def test_match(): - mimeaccept = MIMEAccept('Content-Type', 'image/jpg') + mimeaccept = MIMEAccept('image/jpg') assert mimeaccept._match('image/jpg', 'image/jpg') assert mimeaccept._match('image/*', 'image/jpg') assert mimeaccept._match('*/*', 'image/jpg') @@ -302,7 +276,7 @@ def test_match(): assert_raises(ValueError, mimeaccept._match, 'image/jpg', '*/*') def test_accept_json(): - mimeaccept = MIMEAccept('Accept', 'text/html, *; q=.2, */*; q=.2') + mimeaccept = MIMEAccept('text/html, *; q=.2, */*; q=.2') assert mimeaccept.best_match(['application/json']) == 'application/json' # property tests @@ -325,10 +299,9 @@ def test_accept_property_fset(): eq_(desc.fget(req).header_value, 'baz') def test_accept_property_fset_acceptclass(): - desc = accept_property('Accept-Charset', '14.2') req = Request.blank('/', environ={'envkey': 'envval'}) - desc.fset(req, ['utf-8', 'latin-11']) - eq_(desc.fget(req).header_value, 'utf-8, latin-11, iso-8859-1') + req.accept_charset = ['utf-8', 'latin-11'] + eq_(req.accept_charset.header_value, 'utf-8, latin-11, iso-8859-1') def test_accept_property_fdel(): desc = accept_property('Accept-Charset', '14.2') diff --git a/webob/acceptparse.py b/webob/acceptparse.py index 062f793..eaed2d1 100644 --- a/webob/acceptparse.py +++ b/webob/acceptparse.py @@ -18,28 +18,6 @@ part_re = re.compile( -def parse_accept(value): - """ - Parses an ``Accept-*`` style header. - - A list of ``[(value, quality), ...]`` is returned. ``quality`` - will be 1 if it was not given. - """ - result = [] - for match in part_re.finditer(','+value): - name = match.group(1) - if name == 'q': - continue - quality = match.group(2) or '' - if not quality: - quality = 1 - else: - try: - quality = max(min(float(quality), 1), 0) - except ValueError: - quality = 1 - result.append((name, quality)) - return result def _warn_first_match(): # TODO: remove .first_match in version 1.3 @@ -53,26 +31,36 @@ class Accept(object): ``accept_obj + 'accept_thing'`` to get a new object """ - def __init__(self, header_name, header_value): - self.header_name = header_name + def __init__(self, header_value): self.header_value = header_value - self._parsed = parse_accept(header_value) - if header_name == 'Accept-Charset': - for k, v in self._parsed: - if k == '*' or k == 'iso-8859-1': - break - else: - self._parsed.append(('iso-8859-1', 1)) - elif header_name == 'Accept-Language': - self._match = self._match_lang + self._parsed = list(self.parse(header_value)) self._parsed_nonzero = [(m,q) for (m,q) in self._parsed if q] + @staticmethod + def parse(value): + """ + Parse ``Accept-*`` style header. + + Return iterator of ``(value, quality)`` pairs. + ``quality`` defaults to 1. + """ + for match in part_re.finditer(','+value): + name = match.group(1) + if name == 'q': + continue + quality = match.group(2) or '' + if quality: + try: + quality = max(min(float(quality), 1), 0) + yield (name, quality) + continue + except ValueError: + pass + yield (name, 1) + def __repr__(self): - return '<%s at 0x%x %s: %s>' % ( - self.__class__.__name__, - abs(id(self)), - self.header_name, str(self)) + return '<%s(%r)>' % (self.__class__.__name__, str(self)) def __str__(self): result = [] @@ -106,7 +94,7 @@ class Accept(object): new_value = other else: new_value = my_value + ', ' + other - return self.__class__(self.header_name, new_value) + return self.__class__(new_value) def __radd__(self, other): return self.__add__(other, True) @@ -207,12 +195,6 @@ class Accept(object): _check_offer(offer) return mask == '*' or offer.lower() == mask.lower() - def _match_lang(self, mask, item): - return (mask == '*' - or item.lower() == mask.lower() - or item.lower().split('-')[0] == mask.lower() - ) - class NilAccept(object): @@ -223,12 +205,8 @@ class NilAccept(object): MasterClass = Accept - def __init__(self, header_name): - self.header_name = header_name - def __repr__(self): - return '<%s for %s: %s>' % ( - self.__class__.__name__, self.header_name, self.MasterClass) + return '<%s: %s>' % (self.__class__.__name__, self.MasterClass) def __str__(self): return '' @@ -240,13 +218,13 @@ class NilAccept(object): if isinstance(item, self.MasterClass): return item else: - return self.MasterClass(self.header_name, '') + item + return self.MasterClass('') + item def __radd__(self, item): if isinstance(item, self.MasterClass): return item else: - return item + self.MasterClass(self.header_name, '') + return item + self.MasterClass('') def __contains__(self, item): _check_offer(item) @@ -283,6 +261,24 @@ class NoAccept(NilAccept): def __contains__(self, item): return False +class AcceptCharset(Accept): + @staticmethod + def parse(value): + latin1_found = False + for m, q in Accept.parse(value): + if m == '*' or m == 'iso-8859-1': + latin1_found = True + yield m, q + if not latin1_found: + yield ('iso-8859-1', 1) + +class AcceptLanguage(Accept): + def _match(self, mask, item): + return (mask == '*' + or item.lower() == mask.lower() + or item.lower().split('-')[0] == mask.lower() + ) + class MIMEAccept(Accept): """ @@ -290,19 +286,16 @@ class MIMEAccept(Accept): This class knows about mime wildcards, like ``image/*`` """ - def __init__(self, header_name, header_value): - Accept.__init__(self, header_name, header_value) - parsed = [] - for mask, q in self._parsed: + @staticmethod + def parse(value): + for mask, q in Accept.parse(value): try: mask_major, mask_minor = mask.split('/') except ValueError: continue if mask_major == '*' and mask_minor != '*': continue - parsed.append((mask, q)) - self._parsed = parsed - self._parsed_nonzero = [(m,q) for (m,q) in self._parsed if q] + yield (mask, q) def accept_html(self): """ @@ -349,12 +342,12 @@ def accept_property(header, rfc_section, def fget(req): value = req.environ.get(key) if not value: - return NilClass(header) - return AcceptClass(header, value) + return NilClass() + return AcceptClass(value) def fset(req, val): if val: if isinstance(val, (list, tuple, dict)): - val = AcceptClass(header, '') + val + val = AcceptClass('') + val val = str(val) req.environ[key] = val or None def fdel(req): diff --git a/webob/request.py b/webob/request.py index 4355122..3f7193f 100644 --- a/webob/request.py +++ b/webob/request.py @@ -6,7 +6,7 @@ else: from cStringIO import StringIO # pragma nocover from webob.headers import EnvironHeaders -from webob.acceptparse import accept_property, Accept, MIMEAccept, NilAccept, MIMENilAccept, NoAccept +from webob.acceptparse import accept_property, Accept, MIMEAccept, AcceptCharset, NilAccept, MIMENilAccept, NoAccept, AcceptLanguage from webob.multidict import TrackableMultiDict, MultiDict, UnicodeMultiDict, NestedMultiDict, NoVars from webob.cachecontrol import CacheControl, serialize_cache_control from webob.etag import etag_property, AnyETag, NoETag @@ -852,9 +852,9 @@ class BaseRequest(object): accept = accept_property('Accept', '14.1', MIMEAccept, MIMENilAccept) - accept_charset = accept_property('Accept-Charset', '14.2') + accept_charset = accept_property('Accept-Charset', '14.2', AcceptCharset) accept_encoding = accept_property('Accept-Encoding', '14.3', NilClass=NoAccept) - accept_language = accept_property('Accept-Language', '14.4') + accept_language = accept_property('Accept-Language', '14.4', AcceptLanguage) authorization = converter( environ_getter('HTTP_AUTHORIZATION', None, '14.8'), |
