blob: 01eb4d08dae506687a55473e4f2414a068437dd8 [file] [log] [blame] [edit]
import re
import warnings
import pytest
from webob.acceptparse import (
Accept,
AcceptCharset,
AcceptCharsetInvalidHeader,
AcceptCharsetNoHeader,
AcceptCharsetValidHeader,
AcceptEncoding,
AcceptEncodingInvalidHeader,
AcceptEncodingNoHeader,
AcceptEncodingValidHeader,
AcceptInvalidHeader,
AcceptLanguage,
AcceptLanguageInvalidHeader,
AcceptLanguageNoHeader,
AcceptLanguageValidHeader,
AcceptNoHeader,
AcceptValidHeader,
MIMEAccept,
_item_n_weight_re,
_list_1_or_more__compiled_re,
accept_charset_property,
accept_encoding_property,
accept_language_property,
accept_property,
create_accept_charset_header,
create_accept_encoding_header,
create_accept_header,
create_accept_language_header,
)
from webob.request import Request
class Test_ItemNWeightRe(object):
@pytest.mark.parametrize('header_value', [
'q=',
'q=1',
';q',
';q=',
';q=1',
'foo;',
'foo;q',
'foo;q1',
'foo;q=',
'foo;q=-1',
'foo;q=2',
'foo;q=1.001',
'foo;q=0.0001',
'foo;q=00',
'foo;q=01',
'foo;q=00.1',
'foo,q=0.1',
'foo;q =1',
'foo;q= 1',
])
def test_invalid(self, header_value):
regex = _item_n_weight_re(item_re='foo')
assert re.match('^' + regex + '$', header_value, re.VERBOSE) is None
@pytest.mark.parametrize('header_value, groups', [
('foo', ('foo', None)),
('foo;q=0', ('foo', '0')),
('foo;q=0.0', ('foo', '0.0')),
('foo;q=0.00', ('foo', '0.00')),
('foo;q=0.000', ('foo', '0.000')),
('foo;q=1', ('foo', '1')),
('foo;q=1.0', ('foo', '1.0')),
('foo;q=1.00', ('foo', '1.00')),
('foo;q=1.000', ('foo', '1.000')),
('foo;q=0.1', ('foo', '0.1')),
('foo;q=0.87', ('foo', '0.87')),
('foo;q=0.382', ('foo', '0.382')),
('foo;Q=0.382', ('foo', '0.382')),
('foo ;Q=0.382', ('foo', '0.382')),
('foo; Q=0.382', ('foo', '0.382')),
('foo ; Q=0.382', ('foo', '0.382')),
])
def test_valid(self, header_value, groups):
regex = _item_n_weight_re(item_re='foo')
assert re.match(
'^' + regex + '$', header_value, re.VERBOSE,
).groups() == groups
class Test_List1OrMoreCompiledRe(object):
@pytest.mark.parametrize('header_value', [
# RFC 7230 Section 7
',',
', ,',
# RFC 7230 Errata ID: 4169
'foo , ,bar,charlie ',
# Our tests
' foo , ,bar,charlie',
' ,foo , ,bar,charlie',
',foo , ,bar,charlie, ',
'\tfoo , ,bar,charlie',
'\t,foo , ,bar,charlie',
',foo , ,bar,charlie\t',
',foo , ,bar,charlie,\t',
])
def test_invalid(self, header_value):
regex = _list_1_or_more__compiled_re(element_re='([a-z]+)')
assert regex.match(header_value) is None
@pytest.mark.parametrize('header_value', [
# RFC 7230 Section 7
'foo,bar',
'foo, bar,',
# RFC 7230 Errata ID: 4169
'foo , ,bar,charlie',
# Our tests
'foo , ,bar,charlie',
',foo , ,bar,charlie',
',foo , ,bar,charlie,',
',\t ,,, \t \t, ,\t\t\t,foo \t\t,, bar, ,\tcharlie \t,, ,',
])
def test_valid(self, header_value):
regex = _list_1_or_more__compiled_re(element_re='([a-z]+)')
assert regex.match(header_value)
class TestAccept(object):
@pytest.mark.parametrize('value', [
', ',
', , ',
'noslash',
'/',
'text/',
'/html',
'text/html;',
'text/html;param',
'text/html;param=',
'text/html ;param=val;',
'text/html; param=val;',
'text/html;param=val;',
'text/html;param=\x19',
'text/html;param=\x22',
'text/html;param=\x5c',
'text/html;param=\x7f',
r'text/html;param="\"',
r'text/html;param="\\\"',
r'text/html;param="\\""',
'text/html;param="\\\x19"',
'text/html;param="\\\x7f"',
'text/html;q',
'text/html;q=',
'text/html;q=-1',
'text/html;q=2',
'text/html;q=1.001',
'text/html;q=0.0001',
'text/html;q=00',
'text/html;q=01',
'text/html;q=00.1',
'text/html,q=0.1',
'text/html;q =1',
'text/html;q= 1',
'text/html;q=1;',
'text/html;param;q=1',
'text/html;q=1;extparam;',
'text/html;q=1;extparam=val;',
'text/html;q=1;extparam="val";',
'text/html;q=1;extparam="',
'text/html;q=1;extparam="val',
'text/html;q=1;extparam=val"',
'text/html;q=1;extparam=\x19',
'text/html;q=1;extparam=\x22',
'text/html;q=1;extparam=\x5c',
'text/html;q=1;extparam=\x7f',
r'text/html;q=1;extparam="\"',
r'text/html;q=1;extparam="\\\"',
r'text/html;q=1;extparam="\\""',
'text/html;q=1;extparam="\\\x19"',
'text/html;q=1;extparam="\\\x7f"',
'text/html;param=\x19;q=1;extparam',
'text/html;param=val;q=1;extparam=\x19',
])
def test_parse__invalid_header(self, value):
with pytest.raises(ValueError):
AcceptValidHeader.parse(value=value)
@pytest.mark.parametrize('value, expected_list', [
# Examples from RFC 7231, Section 5.3.2 "Accept":
(
'audio/*; q=0.2, audio/basic',
[('audio/*', 0.2, [], []), ('audio/basic', 1.0, [], [])],
),
(
'text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c',
[
('text/plain', 0.5, [], []),
('text/html', 1.0, [], []),
('text/x-dvi', 0.8, [], []),
('text/x-c', 1.0, [], []),
],
),
(
'text/*, text/plain, text/plain;format=flowed, */*',
[
('text/*', 1.0, [], []),
('text/plain', 1.0, [], []),
('text/plain;format=flowed', 1.0, [('format', 'flowed')], []),
('*/*', 1.0, [], []),
],
),
(
'text/*;q=0.3, text/html;q=0.7, text/html;level=1, '
'text/html;level=2;q=0.4, */*;q=0.5',
[
('text/*', 0.3, [], []),
('text/html', 0.7, [], []),
('text/html;level=1', 1.0, [('level', '1')], []),
('text/html;level=2', 0.4, [('level', '2')], []),
('*/*', 0.5, [], []),
],
),
# Our tests
('', []),
(',', []),
(', ,', []),
(
'*/*, text/*, text/html',
[
('*/*', 1.0, [], []),
('text/*', 1.0, [], []),
('text/html', 1.0, [], []),
]
),
# It does not seem from RFC 7231, section 5.3.2 "Accept" that the '*'
# in a range like '*/html' was intended to have any special meaning
# (the section lists '*/*', 'type/*' and 'type/subtype', but not
# '*/subtype'). However, because type and subtype are tokens (section
# 3.1.1.1), and a token may contain '*'s, '*/subtype' is valid.
('*/html', [('*/html', 1.0, [], [])]),
(
'text/html \t;\t param1=val1\t; param2="val2" ' +
r'; param3="\"\\\\"',
[(
r'text/html;param1=val1;param2=val2;param3="\"\\\\"', 1.0,
[('param1', 'val1'), ('param2', 'val2'), ('param3', r'"\\')],
[],
)],
),
(
'text/html;param=!#$%&\'*+-.^_`|~09AZaz',
[(
'text/html;param=!#$%&\'*+-.^_`|~09AZaz', 1.0,
[('param', '!#$%&\'*+-.^_`|~09AZaz')], [],
)],
),
(
'text/html;param=""',
[('text/html;param=""', 1.0, [('param', '')], [])],
),
(
'text/html;param="\t \x21\x23\x24\x5a\x5b\x5d\x5e\x7d\x7e"',
[(
'text/html;param="\t \x21\x23\x24\x5a\x5b\x5d\x5e\x7d\x7e"',
1.0,
[('param', '\t \x21\x23\x24\x5a\x5b\x5d\x5e\x7d\x7e')], [],
)],
),
(
'text/html;param="\x80\x81\xfe\xff\\\x22\\\x5c"',
[(
'text/html;param="\x80\x81\xfe\xff\\\x22\\\x5c"', 1.0,
[('param', '\x80\x81\xfe\xff\x22\x5c')], [],
)],
),
(
'text/html;param="\\\t\\ \\\x21\\\x7e\\\x80\\\xff"',
[(
'text/html;param="\t \x21\x7e\x80\xff"', 1.0,
[('param', '\t \x21\x7e\x80\xff')], [],
)],
),
(
"text/html;param='val'",
# This makes it look like the media type parameter value could be
# surrounded with single quotes instead of double quotes, but the
# single quotes are actually part of the media type parameter value
# token
[("text/html;param='val'", 1.0, [('param', "'val'")], [])],
),
('text/html;q=0.9', [('text/html', 0.9, [], [])]),
('text/html;q=0', [('text/html', 0.0, [], [])]),
('text/html;q=0.0', [('text/html', 0.0, [], [])]),
('text/html;q=0.00', [('text/html', 0.0, [], [])]),
('text/html;q=0.000', [('text/html', 0.0, [], [])]),
('text/html;q=1', [('text/html', 1.0, [], [])]),
('text/html;q=1.0', [('text/html', 1.0, [], [])]),
('text/html;q=1.00', [('text/html', 1.0, [], [])]),
('text/html;q=1.000', [('text/html', 1.0, [], [])]),
('text/html;q=0.1', [('text/html', 0.1, [], [])]),
('text/html;q=0.87', [('text/html', 0.87, [], [])]),
('text/html;q=0.382', [('text/html', 0.382, [], [])]),
('text/html;Q=0.382', [('text/html', 0.382, [], [])]),
('text/html ;Q=0.382', [('text/html', 0.382, [], [])]),
('text/html; Q=0.382', [('text/html', 0.382, [], [])]),
('text/html ; Q=0.382', [('text/html', 0.382, [], [])]),
('text/html;q=0.9;q=0.8', [('text/html', 0.9, [], [('q', '0.8')])]),
(
'text/html;q=1;q=1;q=1',
[('text/html', 1.0, [], [('q', '1'), ('q', '1')])],
),
(
'text/html;q=0.9;extparam1;extparam2=val2;extparam3="val3"',
[(
'text/html', 0.9, [],
['extparam1', ('extparam2', 'val2'), ('extparam3', 'val3')]
)],
),
(
'text/html;q=1;extparam=!#$%&\'*+-.^_`|~09AZaz',
[('text/html', 1.0, [], [('extparam', '!#$%&\'*+-.^_`|~09AZaz')])],
),
(
'text/html;q=1;extparam=""',
[('text/html', 1.0, [], [('extparam', '')])],
),
(
'text/html;q=1;extparam="\t \x21\x23\x24\x5a\x5b\x5d\x5e\x7d\x7e"',
[(
'text/html', 1.0, [],
[('extparam', '\t \x21\x23\x24\x5a\x5b\x5d\x5e\x7d\x7e')],
)],
),
(
'text/html;q=1;extparam="\x80\x81\xfe\xff\\\x22\\\x5c"',
[(
'text/html', 1.0, [],
[('extparam', '\x80\x81\xfe\xff\x22\x5c')],
)],
),
(
'text/html;q=1;extparam="\\\t\\ \\\x21\\\x7e\\\x80\\\xff"',
[('text/html', 1.0, [], [('extparam', '\t \x21\x7e\x80\xff')])],
),
(
"text/html;q=1;extparam='val'",
# This makes it look like the extension parameter value could be
# surrounded with single quotes instead of double quotes, but the
# single quotes are actually part of the extension parameter value
# token
[('text/html', 1.0, [], [('extparam', "'val'")])],
),
(
'text/html;param1="val1";param2=val2;q=0.9;extparam1="val1"'
';extparam2;extparam3=val3',
[(
'text/html;param1=val1;param2=val2', 0.9,
[('param1', 'val1'), ('param2', 'val2')],
[('extparam1', 'val1'), 'extparam2', ('extparam3', 'val3')],
)],
),
(
', ,, a/b \t;\t p1=1 ;\t\tp2=2 ; q=0.6\t \t;\t\t e1\t; e2, ,',
[('a/b;p1=1;p2=2', 0.6, [('p1', '1'), ('p2', '2')], ['e1', 'e2'])],
),
(
(
',\t , a/b;q=1;e1;e2=v2 \t,\t\t c/d, e/f;p1=v1;q=0;e1, ' +
'g/h;p1=v1\t ;\t\tp2=v2;q=0.5 \t,'
),
[
('a/b', 1.0, [], ['e1', ('e2', 'v2')]),
('c/d', 1.0, [], []),
('e/f;p1=v1', 0.0, [('p1', 'v1')], ['e1']),
('g/h;p1=v1;p2=v2', 0.5, [('p1', 'v1'), ('p2', 'v2')], []),
],
),
])
def test_parse__valid_header(self, value, expected_list):
returned = AcceptValidHeader.parse(value=value)
list_of_returned = list(returned)
assert list_of_returned == expected_list
class TestAcceptValidHeader(object):
def test_parse__inherited(self):
returned = AcceptValidHeader.parse(
value=(
',\t , a/b;q=1;e1;e2=v2 \t,\t\t c/d, e/f;p1=v1;q=0;e1, '
+ 'g/h;p1=v1\t ;\t\tp2=v2;q=0.5 \t,'
),
)
list_of_returned = list(returned)
assert list_of_returned == [
('a/b', 1.0, [], ['e1', ('e2', 'v2')]),
('c/d', 1.0, [], []),
('e/f;p1=v1', 0.0, [('p1', 'v1')], ['e1']),
('g/h;p1=v1;p2=v2', 0.5, [('p1', 'v1'), ('p2', 'v2')], []),
]
@pytest.mark.parametrize('header_value', [
', ',
'text/html;param=val;q=1;extparam=\x19',
])
def test___init___invalid_header(self, header_value):
with pytest.raises(ValueError):
AcceptValidHeader(header_value=header_value)
def test___init___valid_header(self):
header_value = (
',\t , a/b;q=1;e1;e2=v2 \t,\t\t c/d, e/f;p1=v1;q=0;e1, ' +
'g/h;p1=v1\t ;\t\tp2=v2;q=0.5 \t,'
)
instance = AcceptValidHeader(header_value=header_value)
assert instance.header_value == header_value
assert instance.parsed == [
('a/b', 1.0, [], ['e1', ('e2', 'v2')]),
('c/d', 1.0, [], []),
('e/f;p1=v1', 0.0, [('p1', 'v1')], ['e1']),
('g/h;p1=v1;p2=v2', 0.5, [('p1', 'v1'), ('p2', 'v2')], []),
]
assert instance._parsed_nonzero == [
('a/b', 1.0, [], ['e1', ('e2', 'v2')]),
('c/d', 1.0, [], []),
('g/h;p1=v1;p2=v2', 0.5, [('p1', 'v1'), ('p2', 'v2')], []),
]
assert isinstance(instance, Accept)
def test___add___None(self):
left_operand = AcceptValidHeader(header_value='text/html')
result = left_operand + None
assert isinstance(result, AcceptValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
@pytest.mark.parametrize('right_operand', [
', ',
[', '],
(', ',),
{', ': 1.0},
{', ;level=1': (1.0, ';e1=1')},
'a/b, c/d;q=1;e1;',
['a/b', 'c/d;q=1;e1;'],
('a/b', 'c/d;q=1;e1;',),
{'a/b': 1.0, 'cd': 1.0},
{'a/b': (1.0, ';e1=1'), 'c/d': (1.0, ';e2=2;')},
])
def test___add___invalid_value(self, right_operand):
left_operand = AcceptValidHeader(header_value='text/html')
result = left_operand + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
@pytest.mark.parametrize('str_', [', ', 'a/b, c/d;q=1;e1;'])
def test___add___other_type_with_invalid___str__(self, str_,):
left_operand = AcceptValidHeader(header_value='text/html')
class Other(object):
def __str__(self):
return str_
right_operand = Other()
result = left_operand + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
@pytest.mark.parametrize('value', [
'',
[],
(),
{},
])
def test___add___valid_empty_value(self, value):
left_operand = AcceptValidHeader(header_value=',\t ,i/j, k/l;q=0.333,')
result = left_operand + value
assert isinstance(result, AcceptValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
def test___add___other_type_with_valid___str___empty(self):
left_operand = AcceptValidHeader(header_value=',\t ,i/j, k/l;q=0.333,')
class Other(object):
def __str__(self):
return ''
result = left_operand + Other()
assert isinstance(result, AcceptValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
@pytest.mark.parametrize('value, value_as_header', [
# str
(
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of strs
(
['a/b;q=0.5', 'c/d;p1=1;q=0', 'e/f', 'g/h;p1=1;q=1;e1=1'],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of 3-item tuples, with extension parameters
(
[
('a/b', 0.5, ''), ('c/d;p1=1', 0.0, ''),
('e/f', 1.0, ''), ('g/h;p1=1', 1.0, ';e1=1'),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of 2-item tuples, without extension parameters
(
[
('a/b', 0.5), ('c/d;p1=1', 0.0),
('e/f', 1.0), ('g/h;p1=1', 1.0),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1',
),
# list of a mixture of strs, 3-item tuples and 2-item tuples
(
[
('a/b', 0.5), ('c/d;p1=1', 0.0, ''),
'e/f', ('g/h;p1=1', 1.0, ';e1=1'),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of strs
(
('a/b;q=0.5', 'c/d;p1=1;q=0', 'e/f', 'g/h;p1=1;q=1;e1=1'),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of 3-item tuples, with extension parameters
(
(
('a/b', 0.5, ''), ('c/d;p1=1', 0.0, ''),
('e/f', 1.0, ''), ('g/h;p1=1', 1.0, ';e1=1'),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of 2-item tuples, without extension parameters
(
(
('a/b', 0.5), ('c/d;p1=1', 0.0),
('e/f', 1.0), ('g/h;p1=1', 1.0),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1',
),
# tuple of a mixture of strs, 3-item tuples and 2-item tuples
(
(
('a/b', 0.5), ('c/d;p1=1', 0.0, ''),
'e/f', ('g/h;p1=1', 1.0, ';e1=1'),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# dict
(
{
'a/b': (0.5, ';e1=1'), 'c/d': 0.0,
'e/f;p1=1': (1.0, ';e1=1;e2=2')
},
'e/f;p1=1;q=1;e1=1;e2=2, a/b;q=0.5;e1=1, c/d;q=0',
),
])
def test___add___valid_value(self, value, value_as_header):
header = ',\t ,i/j, k/l;q=0.333,'
result = AcceptValidHeader(header_value=header) + value
assert isinstance(result, AcceptValidHeader)
assert result.header_value == header + ', ' + value_as_header
def test___add___other_type_with_valid___str___not_empty(self):
header = ',\t ,i/j, k/l;q=0.333,'
class Other(object):
def __str__(self):
return 'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1'
right_operand = Other()
result = AcceptValidHeader(header_value=header) + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == header + ', ' + str(right_operand)
def test___add___AcceptValidHeader_header_value_empty(self):
left_operand = AcceptValidHeader(
header_value='a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
)
right_operand = AcceptValidHeader(header_value='')
result = left_operand + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
def test___add___AcceptValidHeader_header_value_not_empty(self):
left_operand = AcceptValidHeader(
header_value='a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
)
right_operand = AcceptValidHeader(
header_value=',\t ,i/j, k/l;q=0.333,',
)
result = left_operand + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == left_operand.header_value + ', ' + \
right_operand.header_value
def test___add___AcceptNoHeader(self):
valid_header_instance = AcceptValidHeader(header_value='a/b')
result = valid_header_instance + AcceptNoHeader()
assert isinstance(result, AcceptValidHeader)
assert result.header_value == valid_header_instance.header_value
assert result is not valid_header_instance
@pytest.mark.parametrize('header_value', [
', ',
'a/b;p1=1;p2=2;q=0.8;e1;e2="',
])
def test___add___AcceptInvalidHeader(self, header_value):
valid_header_instance = AcceptValidHeader(header_value='a/b')
result = valid_header_instance + AcceptInvalidHeader(
header_value=header_value,
)
assert isinstance(result, AcceptValidHeader)
assert result.header_value == valid_header_instance.header_value
assert result is not valid_header_instance
def test___bool__(self):
instance = AcceptValidHeader(header_value='type/subtype')
returned = bool(instance)
assert returned is True
def test___contains__(self):
accept = AcceptValidHeader('A/a, B/b, C/c')
assert 'A/a' in accept
assert 'A/*' in accept
assert '*/a' in accept
assert 'A/b' not in accept
assert 'B/a' not in accept
for mask in ['*/*', 'text/html', 'TEXT/HTML']:
assert 'text/html' in AcceptValidHeader(mask)
def test___iter__(self):
instance = AcceptValidHeader(
header_value=(
'text/plain; q=0.5, text/html; q=0, text/x-dvi; q=0.8, '
'text/x-c'
),
)
assert list(instance) == ['text/x-c', 'text/x-dvi', 'text/plain']
def test___radd___None(self):
right_operand = AcceptValidHeader(header_value='a/b')
result = None + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
@pytest.mark.parametrize('left_operand', [
', ',
[', '],
(', ',),
{', ': 1.0},
{', ;level=1': (1.0, ';e1=1')},
'a/b, c/d;q=1;e1;',
['a/b', 'c/d;q=1;e1;'],
('a/b', 'c/d;q=1;e1;',),
{'a/b': 1.0, 'cd': 1.0},
{'a/b': (1.0, ';e1=1'), 'c/d': (1.0, ';e2=2;')},
])
def test___radd___invalid_value(self, left_operand):
right_operand = AcceptValidHeader(header_value='a/b')
result = left_operand + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
@pytest.mark.parametrize('str_', [', ', 'a/b, c/d;q=1;e1;'])
def test___radd___other_type_with_invalid___str__(self, str_,):
right_operand = AcceptValidHeader(header_value='a/b')
class Other(object):
def __str__(self):
return str_
result = Other() + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
@pytest.mark.parametrize('value', [
'',
[],
(),
{},
])
def test___radd___valid_empty_value(self, value):
right_operand = AcceptValidHeader(header_value='a/b')
result = value + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
def test___radd___other_type_with_valid___str___empty(self):
right_operand = AcceptValidHeader(
header_value=',\t ,i/j, k/l;q=0.333,',
)
class Other(object):
def __str__(self):
return ''
result = Other() + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
@pytest.mark.parametrize('value, value_as_header', [
# str
(
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of strs
(
['a/b;q=0.5', 'c/d;p1=1;q=0', 'e/f', 'g/h;p1=1;q=1;e1=1'],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of 3-item tuples, with extension parameters
(
[
('a/b', 0.5, ''), ('c/d;p1=1', 0.0, ''),
('e/f', 1.0, ''), ('g/h;p1=1', 1.0, ';e1=1'),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of 2-item tuples, without extension parameters
(
[
('a/b', 0.5), ('c/d;p1=1', 0.0),
('e/f', 1.0), ('g/h;p1=1', 1.0),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1',
),
# list of a mixture of strs, 3-item tuples and 2-item tuples
(
[
('a/b', 0.5), ('c/d;p1=1', 0.0, ''),
'e/f', ('g/h;p1=1', 1.0, ';e1=1'),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of strs
(
('a/b;q=0.5', 'c/d;p1=1;q=0', 'e/f', 'g/h;p1=1;q=1;e1=1'),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of 3-item tuples, with extension parameters
(
(
('a/b', 0.5, ''), ('c/d;p1=1', 0.0, ''),
('e/f', 1.0, ''), ('g/h;p1=1', 1.0, ';e1=1'),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of 2-item tuples, without extension parameters
(
(
('a/b', 0.5), ('c/d;p1=1', 0.0),
('e/f', 1.0), ('g/h;p1=1', 1.0),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1',
),
# tuple of a mixture of strs, 3-item tuples and 2-item tuples
(
(
('a/b', 0.5), ('c/d;p1=1', 0.0, ''),
'e/f', ('g/h;p1=1', 1.0, ';e1=1'),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# dict
(
{
'a/b': (0.5, ';e1=1'), 'c/d': 0.0,
'e/f;p1=1': (1.0, ';e1=1;e2=2')
},
'e/f;p1=1;q=1;e1=1;e2=2, a/b;q=0.5;e1=1, c/d;q=0',
),
])
def test___radd___valid_non_empty_value(self, value, value_as_header):
header = ',\t ,i/j, k/l;q=0.333,'
result = value + AcceptValidHeader(header_value=header)
assert isinstance(result, AcceptValidHeader)
assert result.header_value == value_as_header + ', ' + header
def test___radd___other_type_with_valid___str___not_empty(self):
header = ',\t ,i/j, k/l;q=0.333,'
class Other(object):
def __str__(self):
return 'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1'
left_operand = Other()
result = left_operand + AcceptValidHeader(header_value=header)
assert isinstance(result, AcceptValidHeader)
assert result.header_value == str(left_operand) + ', ' + header
@pytest.mark.parametrize('header_value, expected_returned', [
('', "<AcceptValidHeader ('')>"),
(
r',,text/html ; p1="\"\1\"" ; q=0.50; e1=1 ;e2 , text/plain ,',
r'''<AcceptValidHeader ('text/html;p1="\\"1\\"";q=0.5;e1=1;e2''' +
", text/plain')>",
),
(
',\t, a/b ; p1=1 ; p2=2 ;\t q=0.20 ;\te1="\\"\\1\\""\t; e2 ; ' +
'e3=3, c/d ,,',
r'''<AcceptValidHeader ('a/b;p1=1;p2=2;q=0.2;e1="\\"1\\"";e2''' +
";e3=3, c/d')>"
),
])
def test___repr__(self, header_value, expected_returned):
instance = AcceptValidHeader(header_value=header_value)
assert repr(instance) == expected_returned
@pytest.mark.parametrize('header_value, expected_returned', [
('', ''),
(
r',,text/html ; p1="\"\1\"" ; q=0.50; e1=1 ;e2 , text/plain ,',
r'text/html;p1="\"1\"";q=0.5;e1=1;e2, text/plain',
),
(
',\t, a/b ; p1=1 ; p2=2 ;\t q=0.20 ;\te1="\\"\\1\\""\t; e2 ; ' +
'e3=3, c/d ,,',
'a/b;p1=1;p2=2;q=0.2;e1="\\"1\\"";e2;e3=3, c/d'
),
])
def test___str__(self, header_value, expected_returned):
instance = AcceptValidHeader(header_value=header_value)
assert str(instance) == expected_returned
def test__old_match(self):
accept = AcceptValidHeader('image/jpg')
assert accept._old_match('image/jpg', 'image/jpg')
assert accept._old_match('image/*', 'image/jpg')
assert accept._old_match('*/*', 'image/jpg')
assert not accept._old_match('text/html', 'image/jpg')
mismatches = [
('B/b', 'A/a'),
('B/b', 'B/a'),
('B/b', 'A/b'),
('A/a', 'B/b'),
('B/a', 'B/b'),
('A/b', 'B/b')
]
for mask, offer in mismatches:
assert not accept._old_match(mask, offer)
def test__old_match_wildcard_matching(self):
"""
Wildcard matching forces the match to take place against the type or
subtype of the mask and offer (depending on where the wildcard matches)
"""
accept = AcceptValidHeader('type/subtype')
matches = [
('*/*', '*/*'),
('*/*', 'A/*'),
('*/*', '*/a'),
('*/*', 'A/a'),
('A/*', '*/*'),
('A/*', 'A/*'),
('A/*', '*/a'),
('A/*', 'A/a'),
('*/a', '*/*'),
('*/a', 'A/*'),
('*/a', '*/a'),
('*/a', 'A/a'),
('A/a', '*/*'),
('A/a', 'A/*'),
('A/a', '*/a'),
('A/a', 'A/a'),
# Offers might not contain a subtype
('*/*', '*'),
('A/*', '*'),
('*/a', '*')]
for mask, offer in matches:
assert accept._old_match(mask, offer)
# Test malformed mask and offer variants where either is missing a
# type or subtype
assert accept._old_match('A', offer)
assert accept._old_match(mask, 'a')
mismatches = [
('B/b', 'A/*'),
('B/*', 'A/a'),
('B/*', 'A/*'),
('*/b', '*/a')]
for mask, offer in mismatches:
assert not accept._old_match(mask, offer)
@pytest.mark.parametrize('header_value, returned', [
('tExt/HtMl', True),
('APPlication/XHTML+xml', True),
('appliCATION/xMl', True),
('TeXt/XmL', True),
('image/jpg', False),
('TeXt/Plain', False),
('image/jpg, text/html', True),
])
def test_accept_html(self, header_value, returned):
instance = AcceptValidHeader(header_value=header_value)
assert instance.accept_html() is returned
@pytest.mark.parametrize('header_value, returned', [
('tExt/HtMl', True),
('APPlication/XHTML+xml', True),
('appliCATION/xMl', True),
('TeXt/XmL', True),
('image/jpg', False),
('TeXt/Plain', False),
('image/jpg, text/html', True),
])
def test_accepts_html(self, header_value, returned):
instance = AcceptValidHeader(header_value=header_value)
assert instance.accepts_html is returned
@pytest.mark.parametrize('offers', [
['text/html;p=1;q=0.5'],
['text/html;q=0.5'],
['text/html;q=0.5;e=1'],
['text/html', 'text/plain;p=1;q=0.5;e=1'],
])
def test_acceptable_offers__invalid_offers(self, offers):
instance = AcceptValidHeader(header_value='text/html')
with pytest.raises(ValueError):
instance.acceptable_offers(offers=offers)
@pytest.mark.parametrize('header_value, offers, expected_returned', [
# RFC 7231, section 5.3.2
(
'audio/*; q=0.2, audio/basic',
['audio/mpeg', 'audio/basic'],
[('audio/basic', 1.0), ('audio/mpeg', 0.2)],
),
(
'text/plain; q=0.5, text/html, text/x-dvi; q=0.8, text/x-c',
['text/x-dvi', 'text/x-c', 'text/html', 'text/plain'],
[
('text/x-c', 1.0), ('text/html', 1.0), ('text/x-dvi', 0.8),
('text/plain', 0.5),
],
),
(
'text/*;q=0.3, text/html;q=0.7, text/html;level=1, ' +
'text/html;level=2;q=0.4, */*;q=0.5',
[
'text/html;level=1',
'text/html',
'text/plain',
'image/jpeg',
'text/html;level=2',
'text/html;level=3',
],
[
('text/html;level=1', 1.0),
('text/html', 0.7),
('text/html;level=3', 0.7),
('image/jpeg', 0.5),
('text/html;level=2', 0.4),
('text/plain', 0.3),
],
),
# Our tests
(
'teXT/*;Q=0.5, TeXt/hTmL;LeVeL=1',
['tExT/HtMl;lEvEl=1', 'TExt/PlAiN'],
[('tExT/HtMl;lEvEl=1', 1.0), ('TExt/PlAiN', 0.5)],
),
(
'text/html, application/json',
['text/html', 'application/json'],
[('text/html', 1.0), ('application/json', 1.0)],
),
(
'text/html ;\t level=1',
['text/html\t\t ; \tlevel=1'],
[('text/html\t\t ; \tlevel=1', 1.0)],
),
('', ['text/html'], []),
('text/html, image/jpeg', ['audio/basic', 'text/plain'], []),
(
r'text/html;p1=1;p2=2;p3="\""', [r'text/html;p1=1;p2="2";p3="\""'],
[(r'text/html;p1=1;p2="2";p3="\""', 1.0)],
),
('text/html;p1=1', ['text/html;p1=2'], []),
('text/html', ['text/html;p1=1'], [('text/html;p1=1', 1.0)]),
('text/html;p1=1', ['text/html'], []),
('text/html', ['text/html'], [('text/html', 1.0)]),
('text/*', ['text/html;p=1'], [('text/html;p=1', 1.0)]),
('*/*', ['text/html;p=1'], [('text/html;p=1', 1.0)]),
('text/*', ['text/html'], [('text/html', 1.0)]),
('*/*', ['text/html'], [('text/html', 1.0)]),
('text/html;p1=1;q=0', ['text/html;p1=1'], []),
('text/html;q=0', ['text/html;p1=1', 'text/html'], []),
('text/*;q=0', ['text/html;p1=1', 'text/html', 'text/plain'], []),
(
'*/*;q=0',
['text/html;p1=1', 'text/html', 'text/plain', 'image/jpeg'], [],
),
(
'*/*;q=0, audio/mpeg',
[
'text/html;p1=1', 'audio/mpeg', 'text/html', 'text/plain',
'image/jpeg',
],
[('audio/mpeg', 1.0)],
),
(
'text/html;p1=1, text/html;q=0',
['text/html;p1=1'],
[('text/html;p1=1', 1.0)],
),
('text/html, text/*;q=0', ['text/html'], [('text/html', 1.0)]),
('text/*, */*;q=0', ['text/html'], [('text/html', 1.0)]),
('text/html;q=0, text/html', ['text/html'], []),
(
'text/html',
['text/html;level=1', 'text/html', 'text/html;level=2'],
[
('text/html;level=1', 1.0),
('text/html', 1.0),
('text/html;level=2', 1.0),
],
),
(
'text/*;q=0.3, text/html;q=0, image/png, text/html;level=1, ' +
'text/html;level=2;q=0.4, image/jpeg;q=0.5',
[
'text/html;level=1',
'text/html',
'text/plain',
'image/jpeg',
'text/html;level=2',
'text/html;level=3',
'audio/basic',
],
[
('text/html;level=1', 1.0),
('image/jpeg', 0.5),
('text/html;level=2', 0.4),
('text/plain', 0.3),
],
),
])
def test_acceptable_offers__valid_offers(
self, header_value, offers, expected_returned,
):
instance = AcceptValidHeader(header_value=header_value)
returned = instance.acceptable_offers(offers=offers)
assert returned == expected_returned
def test_best_match(self):
accept = AcceptValidHeader('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),
'text/html']) == 'text/html'
assert accept.best_match([('foo/bar', 0.5),
('text/html', 0.4)]) == 'foo/bar'
def test_best_match_with_one_lower_q(self):
accept = AcceptValidHeader('text/html, foo/bar;q=0.5')
assert accept.best_match(['text/html', 'foo/bar']) == 'text/html'
accept = AcceptValidHeader('text/html;q=0.5, foo/bar')
assert accept.best_match(['text/html', 'foo/bar']) == 'foo/bar'
def test_best_match_with_complex_q(self):
accept = AcceptValidHeader(
'text/html, foo/bar;q=0.55, baz/gort;q=0.59'
)
assert accept.best_match(['text/html', 'foo/bar']) == 'text/html'
accept = AcceptValidHeader(
'text/html;q=0.5, foo/bar;q=0.586, baz/gort;q=0.596'
)
assert accept.best_match(['text/html', 'baz/gort']) == 'baz/gort'
def test_best_match_json(self):
accept = AcceptValidHeader('text/html, */*; q=0.2')
assert accept.best_match(['application/json']) == 'application/json'
def test_best_match_mixedcase(self):
accept = AcceptValidHeader(
'image/jpg; q=0.2, Image/pNg; Q=0.4, image/*; q=0.05'
)
assert accept.best_match(['Image/JpG']) == 'Image/JpG'
assert accept.best_match(['image/Tiff']) == 'image/Tiff'
assert accept.best_match(['image/Tiff', 'image/PnG', 'image/jpg']) == \
'image/PnG'
def test_best_match_zero_quality(self):
assert AcceptValidHeader('text/plain, */*;q=0').best_match(
['text/html']
) is None
assert 'audio/basic' not in AcceptValidHeader('*/*;q=0')
def test_quality(self):
accept = AcceptValidHeader('text/html')
assert accept.quality('text/html') == 1
accept = AcceptValidHeader('text/html;q=0.5')
assert accept.quality('text/html') == 0.5
def test_quality_not_found(self):
accept = AcceptValidHeader('text/html')
assert accept.quality('foo/bar') is None
class TestAcceptNoHeader(object):
def test_parse__inherited(self):
returned = AcceptNoHeader.parse(
value=(
',\t , a/b;q=1;e1;e2=v2 \t,\t\t c/d, e/f;p1=v1;q=0;e1, '
+ 'g/h;p1=v1\t ;\t\tp2=v2;q=0.5 \t,'
),
)
list_of_returned = list(returned)
assert list_of_returned == [
('a/b', 1.0, [], ['e1', ('e2', 'v2')]),
('c/d', 1.0, [], []),
('e/f;p1=v1', 0.0, [('p1', 'v1')], ['e1']),
('g/h;p1=v1;p2=v2', 0.5, [('p1', 'v1'), ('p2', 'v2')], []),
]
def test___init__(self):
instance = AcceptNoHeader()
assert instance.header_value is None
assert instance.parsed is None
assert instance._parsed_nonzero is None
assert isinstance(instance, Accept)
def test___add___None(self):
left_operand = AcceptNoHeader()
result = left_operand + None
assert isinstance(result, AcceptNoHeader)
@pytest.mark.parametrize('right_operand', [
', ',
[', '],
(', ',),
{', ': 1.0},
{', ;level=1': (1.0, ';e1=1')},
'a/b, c/d;q=1;e1;',
['a/b', 'c/d;q=1;e1;'],
('a/b', 'c/d;q=1;e1;',),
{'a/b': 1.0, 'cd': 1.0},
{'a/b': (1.0, ';e1=1'), 'c/d': (1.0, ';e2=2;')},
])
def test___add___invalid_value(self, right_operand):
left_operand = AcceptNoHeader()
result = left_operand + right_operand
assert isinstance(result, AcceptNoHeader)
@pytest.mark.parametrize('str_', [', ', 'a/b, c/d;q=1;e1;'])
def test___add___other_type_with_invalid___str__(self, str_,):
left_operand = AcceptNoHeader()
class Other(object):
def __str__(self):
return str_
right_operand = Other()
result = left_operand + right_operand
assert isinstance(result, AcceptNoHeader)
@pytest.mark.parametrize('value', [
'',
[],
(),
{},
])
def test___add___valid_empty_value(self, value):
left_operand = AcceptNoHeader()
result = left_operand + value
assert isinstance(result, AcceptValidHeader)
assert result.header_value == ''
def test___add___other_type_with_valid___str___empty(self):
left_operand = AcceptNoHeader()
class Other(object):
def __str__(self):
return ''
result = left_operand + Other()
assert isinstance(result, AcceptValidHeader)
assert result.header_value == ''
@pytest.mark.parametrize('value, value_as_header', [
# str
(
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of strs
(
['a/b;q=0.5', 'c/d;p1=1;q=0', 'e/f', 'g/h;p1=1;q=1;e1=1'],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of 3-item tuples, with extension parameters
(
[
('a/b', 0.5, ''), ('c/d;p1=1', 0.0, ''),
('e/f', 1.0, ''), ('g/h;p1=1', 1.0, ';e1=1'),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of 2-item tuples, without extension parameters
(
[
('a/b', 0.5), ('c/d;p1=1', 0.0),
('e/f', 1.0), ('g/h;p1=1', 1.0),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1',
),
# list of a mixture of strs, 3-item tuples and 2-item tuples
(
[
('a/b', 0.5), ('c/d;p1=1', 0.0, ''),
'e/f', ('g/h;p1=1', 1.0, ';e1=1'),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of strs
(
('a/b;q=0.5', 'c/d;p1=1;q=0', 'e/f', 'g/h;p1=1;q=1;e1=1'),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of 3-item tuples, with extension parameters
(
(
('a/b', 0.5, ''), ('c/d;p1=1', 0.0, ''),
('e/f', 1.0, ''), ('g/h;p1=1', 1.0, ';e1=1'),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of 2-item tuples, without extension parameters
(
(
('a/b', 0.5), ('c/d;p1=1', 0.0),
('e/f', 1.0), ('g/h;p1=1', 1.0),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1',
),
# tuple of a mixture of strs, 3-item tuples and 2-item tuples
(
(
('a/b', 0.5), ('c/d;p1=1', 0.0, ''),
'e/f', ('g/h;p1=1', 1.0, ';e1=1'),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# dict
(
{
'a/b': (0.5, ';e1=1'), 'c/d': 0.0,
'e/f;p1=1': (1.0, ';e1=1;e2=2')
},
'e/f;p1=1;q=1;e1=1;e2=2, a/b;q=0.5;e1=1, c/d;q=0',
),
])
def test___add___valid_value(self, value, value_as_header):
result = AcceptNoHeader() + value
assert isinstance(result, AcceptValidHeader)
assert result.header_value == value_as_header
def test___add___other_type_with_valid___str___not_empty(self):
class Other(object):
def __str__(self):
return 'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1'
right_operand = Other()
result = AcceptNoHeader() + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == str(right_operand)
def test___add___AcceptValidHeader_header_value_empty(self):
right_operand = AcceptValidHeader(header_value='')
result = AcceptNoHeader() + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
def test___add___AcceptValidHeader_header_value_not_empty(self):
right_operand = AcceptValidHeader(
header_value=',\t ,i/j, k/l;q=0.333,',
)
result = AcceptNoHeader() + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == right_operand.header_value
def test___add___AcceptNoHeader(self):
left_operand = AcceptNoHeader()
right_operand = AcceptNoHeader()
result = left_operand + right_operand
assert isinstance(result, AcceptNoHeader)
assert result is not left_operand
assert result is not right_operand
@pytest.mark.parametrize('header_value', [
', ',
'a/b;p1=1;p2=2;q=0.8;e1;e2="',
])
def test___add___AcceptInvalidHeader(self, header_value):
left_operand = AcceptNoHeader()
result = left_operand + AcceptInvalidHeader(header_value=header_value)
assert isinstance(result, AcceptNoHeader)
assert result is not left_operand
def test___bool__(self):
instance = AcceptNoHeader()
returned = bool(instance)
assert returned is False
def test___contains__(self):
instance = AcceptNoHeader()
returned = ('type/subtype' in instance)
assert returned is True
def test___iter__(self):
instance = AcceptNoHeader()
returned = list(instance)
assert returned == []
def test___radd___None(self):
right_operand = AcceptNoHeader()
result = None + right_operand
assert isinstance(result, AcceptNoHeader)
assert result is not right_operand
@pytest.mark.parametrize('left_operand', [
', ',
[', '],
(', ',),
{', ': 1.0},
{', ;level=1': (1.0, ';e1=1')},
'a/b, c/d;q=1;e1;',
['a/b', 'c/d;q=1;e1;'],
('a/b', 'c/d;q=1;e1;',),
{'a/b': 1.0, 'cd': 1.0},
{'a/b': (1.0, ';e1=1'), 'c/d': (1.0, ';e2=2;')},
])
def test___radd___invalid_value(self, left_operand):
right_operand = AcceptNoHeader()
result = left_operand + right_operand
assert isinstance(result, AcceptNoHeader)
assert result is not right_operand
@pytest.mark.parametrize('str_', [', ', 'a/b, c/d;q=1;e1;'])
def test___radd___other_type_with_invalid___str__(self, str_,):
right_operand = AcceptNoHeader()
class Other(object):
def __str__(self):
return str_
result = Other() + right_operand
assert isinstance(result, AcceptNoHeader)
assert result is not right_operand
@pytest.mark.parametrize('value', [
'',
[],
(),
{},
])
def test___radd___valid_empty_value(self, value):
result = value + AcceptNoHeader()
assert isinstance(result, AcceptValidHeader)
assert result.header_value == ''
def test___radd___other_type_with_valid___str___empty(self):
class Other(object):
def __str__(self):
return ''
result = Other() + AcceptNoHeader()
assert isinstance(result, AcceptValidHeader)
assert result.header_value == ''
@pytest.mark.parametrize('value, value_as_header', [
# str
(
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of strs
(
['a/b;q=0.5', 'c/d;p1=1;q=0', 'e/f', 'g/h;p1=1;q=1;e1=1'],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of 3-item tuples, with extension parameters
(
[
('a/b', 0.5, ''), ('c/d;p1=1', 0.0, ''),
('e/f', 1.0, ''), ('g/h;p1=1', 1.0, ';e1=1'),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of 2-item tuples, without extension parameters
(
[
('a/b', 0.5), ('c/d;p1=1', 0.0),
('e/f', 1.0), ('g/h;p1=1', 1.0),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1',
),
# list of a mixture of strs, 3-item tuples and 2-item tuples
(
[
('a/b', 0.5), ('c/d;p1=1', 0.0, ''),
'e/f', ('g/h;p1=1', 1.0, ';e1=1'),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of strs
(
('a/b;q=0.5', 'c/d;p1=1;q=0', 'e/f', 'g/h;p1=1;q=1;e1=1'),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of 3-item tuples, with extension parameters
(
(
('a/b', 0.5, ''), ('c/d;p1=1', 0.0, ''),
('e/f', 1.0, ''), ('g/h;p1=1', 1.0, ';e1=1'),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of 2-item tuples, without extension parameters
(
(
('a/b', 0.5), ('c/d;p1=1', 0.0),
('e/f', 1.0), ('g/h;p1=1', 1.0),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1',
),
# tuple of a mixture of strs, 3-item tuples and 2-item tuples
(
(
('a/b', 0.5), ('c/d;p1=1', 0.0, ''),
'e/f', ('g/h;p1=1', 1.0, ';e1=1'),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# dict
(
{
'a/b': (0.5, ';e1=1'), 'c/d': 0.0,
'e/f;p1=1': (1.0, ';e1=1;e2=2')
},
'e/f;p1=1;q=1;e1=1;e2=2, a/b;q=0.5;e1=1, c/d;q=0',
),
])
def test___radd___valid_non_empty_value(self, value, value_as_header):
result = value + AcceptNoHeader()
assert isinstance(result, AcceptValidHeader)
assert result.header_value == value_as_header
def test___radd___other_type_with_valid___str___not_empty(self):
class Other(object):
def __str__(self):
return 'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1'
left_operand = Other()
result = left_operand + AcceptNoHeader()
assert isinstance(result, AcceptValidHeader)
assert result.header_value == str(left_operand)
def test___repr__(self):
instance = AcceptNoHeader()
assert repr(instance) == '<AcceptNoHeader>'
def test___str__(self):
instance = AcceptNoHeader()
assert str(instance) == '<no header in request>'
def test_accept_html(self):
instance = AcceptNoHeader()
assert instance.accept_html() is True
def test_accepts_html(self):
instance = AcceptNoHeader()
assert instance.accepts_html is True
def test_acceptable_offers(self):
instance = AcceptNoHeader()
returned = instance.acceptable_offers(offers=['a/b', 'c/d', 'e/f'])
assert returned == [('a/b', 1.0), ('c/d', 1.0), ('e/f', 1.0)]
def test_best_match(self):
accept = AcceptNoHeader()
assert accept.best_match(['text/html', 'audio/basic']) == 'text/html'
assert accept.best_match([('text/html', 1), ('audio/basic', 0.5)]) == \
'text/html'
assert accept.best_match([('text/html', 0.5), ('audio/basic', 1)]) == \
'audio/basic'
assert accept.best_match([('text/html', 0.5), 'audio/basic']) == \
'audio/basic'
assert accept.best_match(
[('text/html', 0.5), 'audio/basic'], default_match=True
) == 'audio/basic'
assert accept.best_match(
[('text/html', 0.5), 'audio/basic'], default_match=False
) == 'audio/basic'
assert accept.best_match([], default_match='fallback') == 'fallback'
def test_quality(self):
instance = AcceptNoHeader()
returned = instance.quality(offer='type/subtype')
assert returned == 1.0
class TestAcceptInvalidHeader(object):
def test_parse__inherited(self):
returned = AcceptInvalidHeader.parse(
value=(
',\t , a/b;q=1;e1;e2=v2 \t,\t\t c/d, e/f;p1=v1;q=0;e1, '
+ 'g/h;p1=v1\t ;\t\tp2=v2;q=0.5 \t,'
),
)
list_of_returned = list(returned)
assert list_of_returned == [
('a/b', 1.0, [], ['e1', ('e2', 'v2')]),
('c/d', 1.0, [], []),
('e/f;p1=v1', 0.0, [('p1', 'v1')], ['e1']),
('g/h;p1=v1;p2=v2', 0.5, [('p1', 'v1'), ('p2', 'v2')], []),
]
def test___init__(self):
header_value = ', '
instance = AcceptInvalidHeader(header_value=header_value)
assert instance.header_value == header_value
assert instance.parsed is None
assert instance._parsed_nonzero is None
assert isinstance(instance, Accept)
def test___add___None(self):
left_operand = AcceptInvalidHeader(header_value=', ')
result = left_operand + None
assert isinstance(result, AcceptNoHeader)
@pytest.mark.parametrize('right_operand', [
', ',
[', '],
(', ',),
{', ': 1.0},
{', ;level=1': (1.0, ';e1=1')},
'a/b, c/d;q=1;e1;',
['a/b', 'c/d;q=1;e1;'],
('a/b', 'c/d;q=1;e1;',),
{'a/b': 1.0, 'cd': 1.0},
{'a/b': (1.0, ';e1=1'), 'c/d': (1.0, ';e2=2;')},
])
def test___add___invalid_value(self, right_operand):
left_operand = AcceptInvalidHeader(header_value='invalid header')
result = left_operand + right_operand
assert isinstance(result, AcceptNoHeader)
@pytest.mark.parametrize('str_', [', ', 'a/b, c/d;q=1;e1;'])
def test___add___other_type_with_invalid___str__(self, str_,):
left_operand = AcceptInvalidHeader(header_value='invalid header')
class Other(object):
def __str__(self):
return str_
right_operand = Other()
result = left_operand + right_operand
assert isinstance(result, AcceptNoHeader)
@pytest.mark.parametrize('value', [
'',
[],
(),
{},
])
def test___add___valid_empty_value(self, value):
left_operand = AcceptInvalidHeader(header_value=', ')
result = left_operand + value
assert isinstance(result, AcceptValidHeader)
assert result.header_value == ''
def test___add___other_type_with_valid___str___empty(self):
left_operand = AcceptInvalidHeader(header_value=', ')
class Other(object):
def __str__(self):
return ''
result = left_operand + Other()
assert isinstance(result, AcceptValidHeader)
assert result.header_value == ''
@pytest.mark.parametrize('value, value_as_header', [
# str
(
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of strs
(
['a/b;q=0.5', 'c/d;p1=1;q=0', 'e/f', 'g/h;p1=1;q=1;e1=1'],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of 3-item tuples, with extension parameters
(
[
('a/b', 0.5, ''), ('c/d;p1=1', 0.0, ''),
('e/f', 1.0, ''), ('g/h;p1=1', 1.0, ';e1=1'),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of 2-item tuples, without extension parameters
(
[
('a/b', 0.5), ('c/d;p1=1', 0.0),
('e/f', 1.0), ('g/h;p1=1', 1.0),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1',
),
# list of a mixture of strs, 3-item tuples and 2-item tuples
(
[
('a/b', 0.5), ('c/d;p1=1', 0.0, ''),
'e/f', ('g/h;p1=1', 1.0, ';e1=1'),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of strs
(
('a/b;q=0.5', 'c/d;p1=1;q=0', 'e/f', 'g/h;p1=1;q=1;e1=1'),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of 3-item tuples, with extension parameters
(
(
('a/b', 0.5, ''), ('c/d;p1=1', 0.0, ''),
('e/f', 1.0, ''), ('g/h;p1=1', 1.0, ';e1=1'),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of 2-item tuples, without extension parameters
(
(
('a/b', 0.5), ('c/d;p1=1', 0.0),
('e/f', 1.0), ('g/h;p1=1', 1.0),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1',
),
# tuple of a mixture of strs, 3-item tuples and 2-item tuples
(
(
('a/b', 0.5), ('c/d;p1=1', 0.0, ''),
'e/f', ('g/h;p1=1', 1.0, ';e1=1'),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# dict
(
{
'a/b': (0.5, ';e1=1'), 'c/d': 0.0,
'e/f;p1=1': (1.0, ';e1=1;e2=2')
},
'e/f;p1=1;q=1;e1=1;e2=2, a/b;q=0.5;e1=1, c/d;q=0',
),
])
def test___add___valid_value(self, value, value_as_header):
result = AcceptInvalidHeader(header_value=', ') + value
assert isinstance(result, AcceptValidHeader)
assert result.header_value == value_as_header
def test___add___other_type_with_valid___str___not_empty(self):
class Other(object):
def __str__(self):
return 'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1'
right_operand = Other()
result = AcceptInvalidHeader(header_value=', ') + \
right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == str(right_operand)
def test___add___AcceptValidHeader_header_value_empty(self):
left_operand = AcceptInvalidHeader(header_value=', ')
right_operand = AcceptValidHeader(header_value='')
result = left_operand + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
def test___add___AcceptValidHeader_header_value_not_empty(self):
left_operand = AcceptInvalidHeader(header_value=', ')
right_operand = AcceptValidHeader(
header_value=',\t ,i/j, k/l;q=0.333,',
)
result = left_operand + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == right_operand.header_value
def test___add___AcceptNoHeader(self):
left_operand = AcceptInvalidHeader(header_value=', ')
right_operand = AcceptNoHeader()
result = left_operand + right_operand
assert isinstance(result, AcceptNoHeader)
assert result is not right_operand
@pytest.mark.parametrize('header_value', [
', ',
'a/b;p1=1;p2=2;q=0.8;e1;e2="',
])
def test___add___AcceptInvalidHeader(self, header_value):
result = AcceptInvalidHeader(header_value=', ') + \
AcceptInvalidHeader(header_value=header_value)
assert isinstance(result, AcceptNoHeader)
def test___bool__(self):
instance = AcceptInvalidHeader(header_value=', ')
returned = bool(instance)
assert returned is False
def test___contains__(self):
instance = AcceptInvalidHeader(header_value=', ')
returned = ('type/subtype' in instance)
assert returned is True
def test___iter__(self):
instance = AcceptInvalidHeader(header_value=', ')
returned = list(instance)
assert returned == []
def test___radd___None(self):
right_operand = AcceptInvalidHeader(header_value=', ')
result = None + right_operand
assert isinstance(result, AcceptNoHeader)
@pytest.mark.parametrize('left_operand', [
', ',
[', '],
(', ',),
{', ': 1.0},
{', ;level=1': (1.0, ';e1=1')},
'a/b, c/d;q=1;e1;',
['a/b', 'c/d;q=1;e1;'],
('a/b', 'c/d;q=1;e1;',),
{'a/b': 1.0, 'cd': 1.0},
{'a/b': (1.0, ';e1=1'), 'c/d': (1.0, ';e2=2;')},
])
def test___radd___invalid_value(self, left_operand):
right_operand = AcceptInvalidHeader(header_value=', ')
result = left_operand + right_operand
assert isinstance(result, AcceptNoHeader)
@pytest.mark.parametrize('str_', [', ', 'a/b, c/d;q=1;e1;'])
def test___radd___other_type_with_invalid___str__(self, str_,):
right_operand = AcceptInvalidHeader(header_value=', ')
class Other(object):
def __str__(self):
return str_
result = Other() + right_operand
assert isinstance(result, AcceptNoHeader)
@pytest.mark.parametrize('value', [
'',
[],
(),
{},
])
def test___radd___valid_empty_value(self, value):
right_operand = AcceptInvalidHeader(header_value='invalid header')
result = value + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == ''
def test___radd___other_type_with_valid___str___empty(self):
right_operand = AcceptInvalidHeader(header_value='invalid header')
class Other(object):
def __str__(self):
return ''
result = Other() + right_operand
assert isinstance(result, AcceptValidHeader)
assert result.header_value == ''
@pytest.mark.parametrize('value, value_as_header', [
# str
(
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of strs
(
['a/b;q=0.5', 'c/d;p1=1;q=0', 'e/f', 'g/h;p1=1;q=1;e1=1'],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of 3-item tuples, with extension parameters
(
[
('a/b', 0.5, ''), ('c/d;p1=1', 0.0, ''),
('e/f', 1.0, ''), ('g/h;p1=1', 1.0, ';e1=1'),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of 2-item tuples, without extension parameters
(
[
('a/b', 0.5), ('c/d;p1=1', 0.0),
('e/f', 1.0), ('g/h;p1=1', 1.0),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1',
),
# list of a mixture of strs, 3-item tuples and 2-item tuples
(
[
('a/b', 0.5), ('c/d;p1=1', 0.0, ''),
'e/f', ('g/h;p1=1', 1.0, ';e1=1'),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of strs
(
('a/b;q=0.5', 'c/d;p1=1;q=0', 'e/f', 'g/h;p1=1;q=1;e1=1'),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of 3-item tuples, with extension parameters
(
(
('a/b', 0.5, ''), ('c/d;p1=1', 0.0, ''),
('e/f', 1.0, ''), ('g/h;p1=1', 1.0, ';e1=1'),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of 2-item tuples, without extension parameters
(
(
('a/b', 0.5), ('c/d;p1=1', 0.0),
('e/f', 1.0), ('g/h;p1=1', 1.0),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1',
),
# tuple of a mixture of strs, 3-item tuples and 2-item tuples
(
(
('a/b', 0.5), ('c/d;p1=1', 0.0, ''),
'e/f', ('g/h;p1=1', 1.0, ';e1=1'),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# dict
(
{
'a/b': (0.5, ';e1=1'), 'c/d': 0.0,
'e/f;p1=1': (1.0, ';e1=1;e2=2')
},
'e/f;p1=1;q=1;e1=1;e2=2, a/b;q=0.5;e1=1, c/d;q=0',
),
])
def test___radd___valid_non_empty_value(self, value, value_as_header):
result = value + AcceptInvalidHeader(header_value='invalid header')
assert isinstance(result, AcceptValidHeader)
assert result.header_value == value_as_header
def test___radd___other_type_with_valid___str___not_empty(self):
class Other(object):
def __str__(self):
return 'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1'
left_operand = Other()
result = left_operand + AcceptInvalidHeader(
header_value='invalid header',
)
assert isinstance(result, AcceptValidHeader)
assert result.header_value == str(left_operand)
def test___repr__(self):
instance = AcceptInvalidHeader(header_value='\x00')
assert repr(instance) == '<AcceptInvalidHeader>'
def test___str__(self):
instance = AcceptInvalidHeader(header_value=", ")
assert str(instance) == '<invalid header value>'
def test_accept_html(self):
instance = AcceptInvalidHeader(header_value=', ')
assert instance.accept_html() is True
def test_accepts_html(self):
instance = AcceptInvalidHeader(header_value=', ')
assert instance.accepts_html is True
def test_acceptable_offers(self):
instance = AcceptInvalidHeader(header_value=', ')
returned = instance.acceptable_offers(offers=['a/b', 'c/d', 'e/f'])
assert returned == [('a/b', 1.0), ('c/d', 1.0), ('e/f', 1.0)]
def test_best_match(self):
accept = AcceptInvalidHeader(header_value=', ')
assert accept.best_match(['text/html', 'audio/basic']) == 'text/html'
assert accept.best_match([('text/html', 1), ('audio/basic', 0.5)]) == \
'text/html'
assert accept.best_match([('text/html', 0.5), ('audio/basic', 1)]) == \
'audio/basic'
assert accept.best_match([('text/html', 0.5), 'audio/basic']) == \
'audio/basic'
assert accept.best_match(
[('text/html', 0.5), 'audio/basic'], default_match=True
) == 'audio/basic'
assert accept.best_match(
[('text/html', 0.5), 'audio/basic'], default_match=False
) == 'audio/basic'
assert accept.best_match([], default_match='fallback') == 'fallback'
def test_quality(self):
instance = AcceptInvalidHeader(header_value=', ')
returned = instance.quality(offer='type/subtype')
assert returned == 1.0
class TestCreateAcceptHeader(object):
def test_header_value_is_None(self):
header_value = None
returned = create_accept_header(header_value=header_value)
assert isinstance(returned, AcceptNoHeader)
assert returned.header_value == header_value
def test_header_value_is_valid(self):
header_value = 'text/html, text/plain;q=0.9'
returned = create_accept_header(header_value=header_value)
assert isinstance(returned, AcceptValidHeader)
assert returned.header_value == header_value
@pytest.mark.parametrize('header_value', [', ', 'noslash'])
def test_header_value_is_invalid(self, header_value):
returned = create_accept_header(header_value=header_value)
assert isinstance(returned, AcceptInvalidHeader)
assert returned.header_value == header_value
class TestAcceptProperty(object):
def test_fget_header_is_valid(self):
header_value = 'text/html;p1="1";p2=v2;q=0.9;e1="1";e2, audio/basic'
request = Request.blank('/', environ={'HTTP_ACCEPT': header_value})
property_ = accept_property()
returned = property_.fget(request=request)
assert isinstance(returned, AcceptValidHeader)
assert returned.header_value == header_value
def test_fget_header_is_None(self):
request = Request.blank('/', environ={'HTTP_ACCEPT': None})
property_ = accept_property()
returned = property_.fget(request=request)
assert isinstance(returned, AcceptNoHeader)
def test_fget_header_is_invalid(self):
header_value = 'invalid'
request = Request.blank('/', environ={'HTTP_ACCEPT': header_value})
property_ = accept_property()
returned = property_.fget(request=request)
assert isinstance(returned, AcceptInvalidHeader)
assert returned.header_value == header_value
def test_fset_value_is_valid(self):
request = Request.blank('/', environ={'HTTP_ACCEPT': 'text/html'})
header_value = 'text/html;p1="1";p2=v2;q=0.9;e1="1";e2, audio/basic'
property_ = accept_property()
property_.fset(request=request, value=header_value)
assert request.environ['HTTP_ACCEPT'] == header_value
def test_fset_value_is_None(self):
request = Request.blank('/', environ={'HTTP_ACCEPT': 'text/html'})
property_ = accept_property()
property_.fset(request=request, value=None)
assert 'HTTP_ACCEPT' not in request.environ
def test_fset_value_is_invalid(self):
request = Request.blank('/', environ={'HTTP_ACCEPT': 'text/html'})
header_value = 'invalid'
property_ = accept_property()
property_.fset(request=request, value=header_value)
assert request.environ['HTTP_ACCEPT'] == header_value
@pytest.mark.parametrize('value, value_as_header', [
('', ''),
([], ''),
((), ''),
({}, ''),
# str
(
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of strs
(
['a/b;q=0.5', 'c/d;p1=1;q=0', 'e/f', 'g/h;p1=1;q=1;e1=1'],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of 3-item tuples, with extension parameters
(
[
('a/b', 0.5, ''), ('c/d;p1=1', 0.0, ''),
('e/f', 1.0, ''), ('g/h;p1=1', 1.0, ';e1=1'),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# list of 2-item tuples, without extension parameters
(
[
('a/b', 0.5), ('c/d;p1=1', 0.0),
('e/f', 1.0), ('g/h;p1=1', 1.0),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1',
),
# list of a mixture of strs, 3-item tuples and 2-item tuples
(
[
('a/b', 0.5), ('c/d;p1=1', 0.0, ''),
'e/f', ('g/h;p1=1', 1.0, ';e1=1'),
],
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of strs
(
('a/b;q=0.5', 'c/d;p1=1;q=0', 'e/f', 'g/h;p1=1;q=1;e1=1'),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of 3-item tuples, with extension parameters
(
(
('a/b', 0.5, ''), ('c/d;p1=1', 0.0, ''),
('e/f', 1.0, ''), ('g/h;p1=1', 1.0, ';e1=1'),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# tuple of 2-item tuples, without extension parameters
(
(
('a/b', 0.5), ('c/d;p1=1', 0.0),
('e/f', 1.0), ('g/h;p1=1', 1.0),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1',
),
# tuple of a mixture of strs, 3-item tuples and 2-item tuples
(
(
('a/b', 0.5), ('c/d;p1=1', 0.0, ''),
'e/f', ('g/h;p1=1', 1.0, ';e1=1'),
),
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
),
# dict
(
{
'a/b': (0.5, ';e1=1'), 'c/d': 0.0,
'e/f;p1=1': (1.0, ';e1=1;e2=2')
},
'e/f;p1=1;q=1;e1=1;e2=2, a/b;q=0.5;e1=1, c/d;q=0',
),
])
def test_fset_value_types(self, value, value_as_header):
request = Request.blank('/', environ={'HTTP_ACCEPT': 'text/html'})
property_ = accept_property()
property_.fset(request=request, value=value)
assert request.environ['HTTP_ACCEPT'] == value_as_header
@pytest.mark.parametrize('header_value', [
'',
'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1',
])
def test_fset_other_type_with___str__(self, header_value):
request = Request.blank('/', environ={'HTTP_ACCEPT': 'text/html'})
property_ = accept_property()
class Other(object):
def __str__(self):
return header_value
value = Other()
property_.fset(request=request, value=value)
assert request.environ['HTTP_ACCEPT'] == str(value)
def test_fset_AcceptValidHeader(self):
request = Request.blank('/', environ={})
header_value = 'a/b;q=0.5, c/d;p1=1;q=0, e/f, g/h;p1=1;q=1;e1=1'
header = AcceptValidHeader(header_value=header_value)
property_ = accept_property()
property_.fset(request=request, value=header)
assert request.environ['HTTP_ACCEPT'] == header.header_value
def test_fset_AcceptNoHeader(self):
request = Request.blank('/', environ={'HTTP_ACCEPT': 'text/html'})
property_ = accept_property()
header = AcceptNoHeader()
property_.fset(request=request, value=header)
assert 'HTTP_ACCEPT' not in request.environ
def test_fset_AcceptInvalidHeader(self):
request = Request.blank('/', environ={})
header_value = 'invalid'
header = AcceptInvalidHeader(header_value=header_value)
property_ = accept_property()
property_.fset(request=request, value=header)
assert request.environ['HTTP_ACCEPT'] == header.header_value
def test_fdel_header_key_in_environ(self):
request = Request.blank('/', environ={'HTTP_ACCEPT': 'text/html'})
property_ = accept_property()
property_.fdel(request=request)
assert 'HTTP_ACCEPT' not in request.environ
def test_fdel_header_key_not_in_environ(self):
request = Request.blank('/')
property_ = accept_property()
property_.fdel(request=request)
assert 'HTTP_ACCEPT' not in request.environ
class TestAcceptCharset(object):
@pytest.mark.parametrize('value', [
'',
'"',
'(',
')',
'/',
':',
';',
'<',
'=',
'>',
'?',
'@',
'[',
'\\',
']',
'{',
'}',
'foo, bar, baz;q= 0.001',
'foo , ,bar,charlie ',
])
def test_parse__invalid_header(self, value):
with pytest.raises(ValueError):
AcceptCharset.parse(value=value)
@pytest.mark.parametrize('value, expected_list', [
('*', [('*', 1.0)]),
("!#$%&'*+-.^_`|~;q=0.5", [("!#$%&'*+-.^_`|~", 0.5)]),
('0123456789', [('0123456789', 1.0)]),
(
',\t foo \t;\t q=0.345,, bar ; Q=0.456 \t, ,\tcharlie \t,, ,',
[('foo', 0.345), ('bar', 0.456), ('charlie', 1.0)]
),
(
'iso-8859-5;q=0.372,unicode-1-1;q=0.977,UTF-8, *;q=0.000',
[
('iso-8859-5', 0.372), ('unicode-1-1', 0.977), ('UTF-8', 1.0),
('*', 0.0)
]
),
# RFC 7230 Section 7
('foo,bar', [('foo', 1.0), ('bar', 1.0)]),
('foo, bar,', [('foo', 1.0), ('bar', 1.0)]),
# RFC 7230 Errata ID: 4169
('foo , ,bar,charlie', [('foo', 1.0), ('bar', 1.0), ('charlie', 1.0)]),
])
def test_parse__valid_header(self, value, expected_list):
returned = AcceptCharset.parse(value=value)
list_of_returned = list(returned)
assert list_of_returned == expected_list
class TestAcceptCharsetValidHeader(object):
def test_parse__inherited(self):
returned = AcceptCharsetValidHeader.parse(
value=',iso-8859-5 ; q=0.333 , ,utf-8,unicode-1-1 ;q=0.90,',
)
list_of_returned = list(returned)
assert list_of_returned == [
('iso-8859-5', 0.333),
('utf-8', 1.0),
('unicode-1-1', 0.9),
]
@pytest.mark.parametrize('header_value', [
'',
', iso-8859-5 ',
])
def test___init___invalid_header(self, header_value):
with pytest.raises(ValueError):
AcceptCharsetValidHeader(header_value=header_value)
def test___init___valid_header(self):
header_value = \
'iso-8859-5;q=0.372,unicode-1-1;q=0.977,UTF-8, *;q=0.000'
instance = AcceptCharsetValidHeader(header_value=header_value)
assert instance.header_value == header_value
assert instance.parsed == [
('iso-8859-5', 0.372), ('unicode-1-1', 0.977), ('UTF-8', 1.0),
('*', 0.0)
]
assert instance._parsed_nonzero == [
('iso-8859-5', 0.372), ('unicode-1-1', 0.977), ('UTF-8', 1.0),
]
assert isinstance(instance, AcceptCharset)
def test___add___None(self):
left_operand = AcceptCharsetValidHeader(header_value='iso-8859-5')
result = left_operand + None
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
@pytest.mark.parametrize('right_operand', [
'',
[],
(),
{},
'UTF/8',
['UTF/8'],
('UTF/8',),
{'UTF/8': 1.0},
])
def test___add___invalid_value(self, right_operand):
left_operand = AcceptCharsetValidHeader(header_value='iso-8859-5')
result = left_operand + right_operand
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
@pytest.mark.parametrize('str_', ['', 'UTF/8'])
def test___add___other_type_with_invalid___str__(self, str_,):
left_operand = AcceptCharsetValidHeader(header_value='iso-8859-5')
class Other(object):
def __str__(self):
return str_
right_operand = Other()
result = left_operand + right_operand
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
@pytest.mark.parametrize('value, value_as_header', [
(
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
[('UTF-7', 0.5), ('unicode-1-1', 0.0), 'UTF-8'],
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
(('UTF-7', 0.5), ('unicode-1-1', 0.0), 'UTF-8'),
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
{'UTF-7': 0.5, 'unicode-1-1': 0.0, 'UTF-8': 1.0},
'UTF-8, UTF-7;q=0.5, unicode-1-1;q=0',
),
])
def test___add___valid_value(self, value, value_as_header):
left_operand = AcceptCharsetValidHeader(
header_value=',\t ,iso-8859-5;q=0.333,',
)
result = left_operand + value
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == left_operand.header_value + ', ' + \
value_as_header
def test___add___other_type_with_valid___str__(self):
left_operand = AcceptCharsetValidHeader(
header_value=',\t ,iso-8859-5;q=0.333,',
)
class Other(object):
def __str__(self):
return 'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8'
right_operand = Other()
result = left_operand + right_operand
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == left_operand.header_value + ', ' + \
str(right_operand)
def test___add___AcceptCharsetValidHeader(self):
left_operand = AcceptCharsetValidHeader(
header_value=',\t ,iso-8859-5;q=0.333,',
)
right_operand = AcceptCharsetValidHeader(
header_value=', ,utf-7;q=0, \tutf-8;q=1,',
)
result = left_operand + right_operand
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == left_operand.header_value + ', ' + \
right_operand.header_value
def test___add___AcceptCharsetNoHeader(self):
valid_header_instance = AcceptCharsetValidHeader(
header_value=', ,utf-7;q=0, \tutf-8;q=1,'
)
result = valid_header_instance + AcceptCharsetNoHeader()
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == valid_header_instance.header_value
assert result is not valid_header_instance
@pytest.mark.parametrize('header_value', ['', 'utf/8'])
def test___add___AcceptCharsetInvalidHeader(self, header_value):
valid_header_instance = AcceptCharsetValidHeader(
header_value='header',
)
result = valid_header_instance + AcceptCharsetInvalidHeader(
header_value=header_value,
)
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == valid_header_instance.header_value
assert result is not valid_header_instance
def test___bool__(self):
instance = AcceptCharsetValidHeader(header_value='valid-header')
returned = bool(instance)
assert returned is True
def test___contains__(self):
for mask in ['*', 'utf-8', 'UTF-8']:
assert 'utf-8' in AcceptCharsetValidHeader(mask)
assert 'utf-8' not in AcceptCharsetValidHeader('utf-7')
def test___contains___not(self):
accept = AcceptCharsetValidHeader('utf-8')
assert 'utf-7' not in accept
def test___contains___zero_quality(self):
assert 'foo' not in AcceptCharsetValidHeader('*;q=0')
def test___iter__(self):
instance = AcceptCharsetValidHeader(
header_value=\
'utf-8; q=0.5, utf-7; q=0, iso-8859-5; q=0.8, unicode-1-1',
)
assert list(instance) == ['unicode-1-1', 'iso-8859-5', 'utf-8']
def test___radd___None(self):
right_operand = AcceptCharsetValidHeader(header_value='iso-8859-5')
result = None + right_operand
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
@pytest.mark.parametrize('left_operand', [
'',
[],
(),
{},
'UTF/8',
['UTF/8'],
('UTF/8',),
{'UTF/8': 1.0},
])
def test___radd___invalid_value(self, left_operand):
right_operand = AcceptCharsetValidHeader(header_value='iso-8859-5')
result = left_operand + right_operand
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
@pytest.mark.parametrize('str_', ['', 'UTF/8'])
def test___radd___other_type_with_invalid___str__(self, str_,):
right_operand = AcceptCharsetValidHeader(header_value='iso-8859-5')
class Other(object):
def __str__(self):
return str_
result = Other() + right_operand
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
@pytest.mark.parametrize('value, value_as_header', [
(
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
[('UTF-7', 0.5), ('unicode-1-1', 0.0), 'UTF-8'],
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
(('UTF-7', 0.5), ('unicode-1-1', 0.0), 'UTF-8'),
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
{'UTF-7': 0.5, 'unicode-1-1': 0.0, 'UTF-8': 1.0},
'UTF-8, UTF-7;q=0.5, unicode-1-1;q=0',
),
])
def test___radd___valid_value(self, value, value_as_header):
right_operand = AcceptCharsetValidHeader(
header_value=',\t ,iso-8859-5;q=0.333,',
)
result = value + right_operand
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == value_as_header + ', ' + \
right_operand.header_value
def test___radd___other_type_with_valid___str__(self):
right_operand = AcceptCharsetValidHeader(
header_value=',\t ,iso-8859-5;q=0.333,',
)
class Other(object):
def __str__(self):
return 'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8'
left_operand = Other()
result = left_operand + right_operand
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == str(left_operand) + ', ' + \
right_operand.header_value
def test___repr__(self):
instance = AcceptCharsetValidHeader(
header_value=',utf-7;q=0.200,UTF-8;q=0.300',
)
assert repr(instance) == \
"<AcceptCharsetValidHeader ('utf-7;q=0.2, UTF-8;q=0.3')>"
def test___str__(self):
header_value = (
', \t,iso-8859-5;q=0.000 \t, utf-8;q=1.000, UTF-7, '
'unicode-1-1;q=0.210 ,'
)
instance = AcceptCharsetValidHeader(header_value=header_value)
assert str(instance) == \
'iso-8859-5;q=0, utf-8, UTF-7, unicode-1-1;q=0.21'
@pytest.mark.parametrize('header_value, offers, returned', [
('UTF-7, unicode-1-1', ['UTF-8', 'iso-8859-5'], []),
(
'utf-8, unicode-1-1, iSo-8859-5',
['UTF-8', 'iso-8859-5'],
[('UTF-8', 1.0), ('iso-8859-5', 1.0)],
),
(
'utF-8;q=0.2, uniCode-1-1;q=0.9, iSo-8859-5;q=0.8',
['iso-8859-5', 'unicode-1-1', 'utf-8'],
[('unicode-1-1', 0.9), ('iso-8859-5', 0.8), ('utf-8', 0.2)],
),
(
'utf-8, unicode-1-1;q=0.9, iSo-8859-5;q=0.9',
['iso-8859-5', 'utf-8', 'unicode-1-1'],
[('utf-8', 1.0), ('iso-8859-5', 0.9), ('unicode-1-1', 0.9)],
),
('*', ['UTF-8', 'iso-8859-5'], [('UTF-8', 1.0), ('iso-8859-5', 1.0)]),
(
'*;q=0.8',
['UTF-8', 'iso-8859-5'],
[('UTF-8', 0.8), ('iso-8859-5', 0.8)],
),
('UTF-7, *', ['UTF-8', 'UTF-7'], [('UTF-8', 1.0), ('UTF-7', 1.0)]),
(
'UTF-7;q=0.5, *',
['UTF-7', 'UTF-8'],
[('UTF-8', 1.0), ('UTF-7', 0.5)],
),
('UTF-8, *;q=0', ['UTF-7'], []),
('UTF-8, *;q=0', ['UTF-8'], [('UTF-8', 1.0)]),
('UTF-8;q=0, *', ['UTF-8'], []),
('UTF-8;q=0, *;q=0', ['UTF-8', 'UTF-7'], []),
('UTF-8, UTF-8;q=0', ['UTF-8'], [('UTF-8', 1.0)]),
(
'UTF-8, UTF-8;q=0, UTF-7',
['UTF-8', 'UTF-7'],
[('UTF-8', 1.0), ('UTF-7', 1.0)]
),
(
'UTF-8;q=0.5, UTF-8;q=0.7, UTF-8;q=0.6, UTF-7',
['UTF-8', 'UTF-7'],
[('UTF-7', 1.0), ('UTF-8', 0.5)],
),
(
'UTF-8;q=0.8, *;q=0.9, *;q=0',
['UTF-8', 'UTF-7'],
[('UTF-7', 0.9), ('UTF-8', 0.8)]
),
(
'UTF-8;q=0.8, *;q=0, *;q=0.9',
['UTF-8', 'UTF-7'],
[('UTF-8', 0.8)]
),
])
def test_acceptable_offers(self, header_value, offers, returned):
instance = AcceptCharsetValidHeader(header_value=header_value)
assert instance.acceptable_offers(offers=offers) == returned
def test_best_match(self):
accept = AcceptCharsetValidHeader('utf-8, iso-8859-5')
assert accept.best_match(['utf-8', 'iso-8859-5']) == 'utf-8'
assert accept.best_match(['iso-8859-5', 'utf-8']) == 'iso-8859-5'
assert accept.best_match([('iso-8859-5', 0.5), 'utf-8']) == 'utf-8'
assert accept.best_match([('iso-8859-5', 0.5), ('utf-8', 0.4)]) == \
'iso-8859-5'
def test_best_match_with_one_lower_q(self):
accept = AcceptCharsetValidHeader('utf-8, iso-8859-5;q=0.5')
assert accept.best_match(['utf-8', 'iso-8859-5']) == 'utf-8'
accept = AcceptCharsetValidHeader('utf-8;q=0.5, iso-8859-5')
assert accept.best_match(['utf-8', 'iso-8859-5']) == 'iso-8859-5'
def test_best_match_with_complex_q(self):
accept = AcceptCharsetValidHeader(
'utf-8, iso-8859-5;q=0.55, utf-7;q=0.59'
)
assert accept.best_match(['utf-8', 'iso-8859-5']) == 'utf-8'
accept = AcceptCharsetValidHeader(
'utf-8;q=0.5, iso-8859-5;q=0.586, utf-7;q=0.596'
)
assert accept.best_match(['utf-8', 'utf-7']) == 'utf-7'
def test_best_match_mixedcase(self):
accept = AcceptCharsetValidHeader(
'uTf-8; q=0.2, UtF-7; Q=0.4, *; q=0.05'
)
assert accept.best_match(['UtF-8']) == 'UtF-8'
assert accept.best_match(['IsO-8859-5']) == 'IsO-8859-5'
assert accept.best_match(['iSo-8859-5', 'uTF-7', 'UtF-8']) == 'uTF-7'
def test_best_match_zero_quality(self):
assert AcceptCharsetValidHeader('utf-7, *;q=0').best_match(
['utf-8']
) is None
assert 'char-set' not in AcceptCharsetValidHeader('*;q=0')
def test_quality(self):
accept = AcceptCharsetValidHeader('utf-8')
assert accept.quality('utf-8') == 1.0
accept = AcceptCharsetValidHeader('utf-8;q=0.5')
assert accept.quality('utf-8') == 0.5
def test_quality_not_found(self):
accept = AcceptCharsetValidHeader('utf-8')
assert accept.quality('iso-8859-5') is None
class TestAcceptCharsetNoHeader(object):
def test_parse__inherited(self):
returned = AcceptCharsetNoHeader.parse(
value=',iso-8859-5 ; q=0.333 , ,utf-8,unicode-1-1 ;q=0.90,',
)
list_of_returned = list(returned)
assert list_of_returned == [
('iso-8859-5', 0.333),
('utf-8', 1.0),
('unicode-1-1', 0.9),
]
def test___init__(self):
instance = AcceptCharsetNoHeader()
assert instance.header_value is None
assert instance.parsed is None
assert instance._parsed_nonzero is None
assert isinstance(instance, AcceptCharset)
def test___add___None(self):
instance = AcceptCharsetNoHeader()
result = instance + None
assert isinstance(result, AcceptCharsetNoHeader)
assert result is not instance
@pytest.mark.parametrize('right_operand', [
'',
[],
(),
{},
'UTF/8',
['UTF/8'],
('UTF/8',),
{'UTF/8': 1.0},
])
def test___add___invalid_value(self, right_operand):
left_operand = AcceptCharsetNoHeader()
result = left_operand + right_operand
assert isinstance(result, AcceptCharsetNoHeader)
assert result is not left_operand
@pytest.mark.parametrize('str_', ['', 'UTF/8'])
def test___add___other_type_with_invalid___str__(self, str_,):
left_operand = AcceptCharsetNoHeader()
class Other(object):
def __str__(self):
return str_
result = left_operand + Other()
assert isinstance(result, AcceptCharsetNoHeader)
assert result is not left_operand
@pytest.mark.parametrize('value, value_as_header', [
(
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
[('UTF-7', 0.5), ('unicode-1-1', 0.0), 'UTF-8'],
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
(('UTF-7', 0.5), ('unicode-1-1', 0.0), 'UTF-8'),
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
{'UTF-7': 0.5, 'unicode-1-1': 0.0, 'UTF-8': 1.0},
'UTF-8, UTF-7;q=0.5, unicode-1-1;q=0',
),
])
def test___add___valid_value(self, value, value_as_header):
result = AcceptCharsetNoHeader() + value
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == value_as_header
def test___add___other_type_with_valid___str__(self):
class Other(object):
def __str__(self):
return 'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8'
right_operand = Other()
result = AcceptCharsetNoHeader() + right_operand
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == str(right_operand)
def test___add___AcceptCharsetValidHeader(self):
right_operand = AcceptCharsetValidHeader(
header_value=', ,utf-7;q=0, \tutf-8;q=1,',
)
result = AcceptCharsetNoHeader() + right_operand
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
def test___add___AcceptCharsetNoHeader(self):
left_operand = AcceptCharsetNoHeader()
right_operand = AcceptCharsetNoHeader()
result = left_operand + right_operand
assert isinstance(result, AcceptCharsetNoHeader)
assert result is not left_operand
assert result is not right_operand
@pytest.mark.parametrize('header_value', ['', 'utf/8'])
def test___add___AcceptCharsetInvalidHeader(self, header_value):
left_operand = AcceptCharsetNoHeader()
result = left_operand + AcceptCharsetInvalidHeader(
header_value=header_value,
)
assert isinstance(result, AcceptCharsetNoHeader)
assert result is not left_operand
def test___bool__(self):
instance = AcceptCharsetNoHeader()
returned = bool(instance)
assert returned is False
def test___contains__(self):
instance = AcceptCharsetNoHeader()
returned = ('char-set' in instance)
assert returned is True
def test___iter__(self):
instance = AcceptCharsetNoHeader()
returned = list(instance)
assert returned == []
def test___radd___None(self):
right_operand = AcceptCharsetNoHeader()
result = None + right_operand
assert isinstance(result, AcceptCharsetNoHeader)
assert result is not right_operand
@pytest.mark.parametrize('left_operand', [
'',
[],
(),
{},
'UTF/8',
['UTF/8'],
('UTF/8',),
{'UTF/8': 1.0},
])
def test___radd___invalid_value(self, left_operand):
right_operand = AcceptCharsetNoHeader()
result = left_operand + right_operand
assert isinstance(result, AcceptCharsetNoHeader)
assert result is not right_operand
@pytest.mark.parametrize('str_', ['', 'UTF/8'])
def test___radd___other_type_with_invalid___str__(self, str_,):
right_operand = AcceptCharsetNoHeader()
class Other(object):
def __str__(self):
return str_
result = Other() + right_operand
assert isinstance(result, AcceptCharsetNoHeader)
assert result is not right_operand
@pytest.mark.parametrize('value, value_as_header', [
(
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
[('UTF-7', 0.5), ('unicode-1-1', 0.0), 'UTF-8'],
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
(('UTF-7', 0.5), ('unicode-1-1', 0.0), 'UTF-8'),
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
{'UTF-7': 0.5, 'unicode-1-1': 0.0, 'UTF-8': 1.0},
'UTF-8, UTF-7;q=0.5, unicode-1-1;q=0',
),
])
def test___radd___valid_value(self, value, value_as_header):
result = value + AcceptCharsetNoHeader()
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == value_as_header
def test___radd___other_type_with_valid___str__(self):
class Other(object):
def __str__(self):
return 'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8'
left_operand = Other()
result = left_operand + AcceptCharsetNoHeader()
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == str(left_operand)
def test___repr__(self):
instance = AcceptCharsetNoHeader()
assert repr(instance) == '<AcceptCharsetNoHeader>'
def test___str__(self):
instance = AcceptCharsetNoHeader()
assert str(instance) == '<no header in request>'
def test_acceptable_offers(self):
instance = AcceptCharsetNoHeader()
returned = instance.acceptable_offers(
offers=['utf-8', 'utf-7', 'unicode-1-1'],
)
assert returned == [
('utf-8', 1.0), ('utf-7', 1.0), ('unicode-1-1', 1.0)
]
def test_best_match(self):
accept = AcceptCharsetNoHeader()
assert accept.best_match(['utf-8', 'iso-8859-5']) == 'utf-8'
assert accept.best_match([('utf-8', 1), ('iso-8859-5', 0.5)]) == \
'utf-8'
assert accept.best_match([('utf-8', 0.5), ('iso-8859-5', 1)]) == \
'iso-8859-5'
assert accept.best_match([('utf-8', 0.5), 'iso-8859-5']) == \
'iso-8859-5'
assert accept.best_match(
[('utf-8', 0.5), 'iso-8859-5'], default_match=True
) == 'iso-8859-5'
assert accept.best_match(
[('utf-8', 0.5), 'iso-8859-5'], default_match=False
) == 'iso-8859-5'
assert accept.best_match([], default_match='fallback') == 'fallback'
def test_quality(self):
instance = AcceptCharsetNoHeader()
returned = instance.quality(offer='char-set')
assert returned == 1.0
class TestAcceptCharsetInvalidHeader(object):
def test_parse__inherited(self):
returned = AcceptCharsetInvalidHeader.parse(
value=',iso-8859-5 ; q=0.333 , ,utf-8,unicode-1-1 ;q=0.90,',
)
list_of_returned = list(returned)
assert list_of_returned == [
('iso-8859-5', 0.333),
('utf-8', 1.0),
('unicode-1-1', 0.9),
]
def test___init__(self):
header_value = 'invalid header'
instance = AcceptCharsetInvalidHeader(header_value=header_value)
assert instance.header_value == header_value
assert instance.parsed is None
assert instance._parsed_nonzero is None
assert isinstance(instance, AcceptCharset)
def test___add___None(self):
instance = AcceptCharsetInvalidHeader(header_value='')
result = instance + None
assert isinstance(result, AcceptCharsetNoHeader)
@pytest.mark.parametrize('right_operand', [
'',
[],
(),
{},
'UTF/8',
['UTF/8'],
('UTF/8',),
{'UTF/8': 1.0},
])
def test___add___invalid_value(self, right_operand):
result = AcceptCharsetInvalidHeader(header_value='') + right_operand
assert isinstance(result, AcceptCharsetNoHeader)
@pytest.mark.parametrize('str_', ['', 'UTF/8'])
def test___add___other_type_with_invalid___str__(self, str_):
class Other(object):
def __str__(self):
return str_
result = AcceptCharsetInvalidHeader(header_value='') + Other()
assert isinstance(result, AcceptCharsetNoHeader)
@pytest.mark.parametrize('value, value_as_header', [
(
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
[('UTF-7', 0.5), ('unicode-1-1', 0.0), 'UTF-8'],
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
(('UTF-7', 0.5), ('unicode-1-1', 0.0), 'UTF-8'),
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
{'UTF-7': 0.5, 'unicode-1-1': 0.0, 'UTF-8': 1.0},
'UTF-8, UTF-7;q=0.5, unicode-1-1;q=0',
),
])
def test___add___valid_header_value(self, value, value_as_header):
result = AcceptCharsetInvalidHeader(header_value='') + value
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == value_as_header
def test___add___other_type_valid_header_value(self):
class Other(object):
def __str__(self):
return 'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8'
right_operand = Other()
result = AcceptCharsetInvalidHeader(header_value='') + right_operand
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == str(right_operand)
def test___add___AcceptCharsetValidHeader(self):
right_operand = AcceptCharsetValidHeader(
header_value=', ,utf-7;q=0, \tutf-8;q=1,',
)
result = AcceptCharsetInvalidHeader(header_value='') + right_operand
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
def test___add___AcceptCharsetNoHeader(self):
right_operand = AcceptCharsetNoHeader()
result = AcceptCharsetInvalidHeader(header_value='') + right_operand
assert isinstance(result, AcceptCharsetNoHeader)
assert result is not right_operand
def test___add___AcceptCharsetInvalidHeader(self):
result = AcceptCharsetInvalidHeader(header_value='') + \
AcceptCharsetInvalidHeader(header_value='utf/8')
assert isinstance(result, AcceptCharsetNoHeader)
def test___bool__(self):
instance = AcceptCharsetInvalidHeader(header_value='')
returned = bool(instance)
assert returned is False
def test___contains__(self):
instance = AcceptCharsetInvalidHeader(header_value='')
returned = ('char-set' in instance)
assert returned is True
def test___iter__(self):
instance = AcceptCharsetInvalidHeader(header_value='')
returned = list(instance)
assert returned == []
def test___radd___None(self):
result = None + AcceptCharsetInvalidHeader(header_value='')
assert isinstance(result, AcceptCharsetNoHeader)
@pytest.mark.parametrize('left_operand', [
'',
[],
(),
{},
'UTF/8',
['UTF/8'],
('UTF/8',),
{'UTF/8': 1.0},
])
def test___radd___invalid_value(self, left_operand):
result = left_operand + AcceptCharsetInvalidHeader(header_value='')
assert isinstance(result, AcceptCharsetNoHeader)
@pytest.mark.parametrize('str_', ['', 'UTF/8'])
def test___radd___other_type_with_invalid___str__(self, str_):
class Other(object):
def __str__(self):
return str_
result = Other() + AcceptCharsetInvalidHeader(header_value='')
assert isinstance(result, AcceptCharsetNoHeader)
@pytest.mark.parametrize('value, value_as_header', [
(
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
[('UTF-7', 0.5), ('unicode-1-1', 0.0), 'UTF-8'],
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
(('UTF-7', 0.5), ('unicode-1-1', 0.0), 'UTF-8'),
'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8',
),
(
{'UTF-7': 0.5, 'unicode-1-1': 0.0, 'UTF-8': 1.0},
'UTF-8, UTF-7;q=0.5, unicode-1-1;q=0',
),
])
def test___radd___valid_header_value(self, value, value_as_header):
result = value + AcceptCharsetInvalidHeader(header_value='')
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == value_as_header
def test___radd___other_type_valid_header_value(self):
class Other(object):
def __str__(self):
return 'UTF-7;q=0.5, unicode-1-1;q=0, UTF-8'
left_operand = Other()
result = left_operand + AcceptCharsetInvalidHeader(header_value='')
assert isinstance(result, AcceptCharsetValidHeader)
assert result.header_value == str(left_operand)
def test___repr__(self):
instance = AcceptCharsetInvalidHeader(header_value='\x00')
assert repr(instance) == '<AcceptCharsetInvalidHeader>'
def test___str__(self):
instance = AcceptCharsetInvalidHeader(header_value='')
assert str(instance) == '<invalid header value>'
def test_acceptable_offers(self):
instance = AcceptCharsetInvalidHeader(header_value='')
returned = instance.acceptable_offers(
offers=['utf-8', 'utf-7', 'unicode-1-1'],
)
assert returned == [
('utf-8', 1.0), ('utf-7', 1.0), ('unicode-1-1', 1.0)
]
def test_best_match(self):
accept = AcceptCharsetInvalidHeader(header_value='')
assert accept.best_match(['utf-8', 'iso-8859-5']) == 'utf-8'
assert accept.best_match([('utf-8', 1), ('iso-8859-5', 0.5)]) == \
'utf-8'
assert accept.best_match([('utf-8', 0.5), ('iso-8859-5', 1)]) == \
'iso-8859-5'
assert accept.best_match([('utf-8', 0.5), 'iso-8859-5']) == \
'iso-8859-5'
assert accept.best_match(
[('utf-8', 0.5), 'iso-8859-5'], default_match=True
) == 'iso-8859-5'
assert accept.best_match(
[('utf-8', 0.5), 'iso-8859-5'], default_match=False
) == 'iso-8859-5'
assert accept.best_match([], default_match='fallback') == 'fallback'
def test_quality(self):
instance = AcceptCharsetInvalidHeader(header_value='')
returned = instance.quality(offer='char-set')
assert returned == 1.0
class TestCreateAcceptCharsetHeader(object):
def test_header_value_is_valid(self):
header_value = 'iso-8859-5, unicode-1-1;q=0.8'
returned = create_accept_charset_header(header_value=header_value)
assert isinstance(returned, AcceptCharsetValidHeader)
assert returned.header_value == header_value
def test_header_value_is_None(self):
header_value = None
returned = create_accept_charset_header(header_value=header_value)
assert isinstance(returned, AcceptCharsetNoHeader)
assert returned.header_value == header_value
@pytest.mark.parametrize('header_value', ['', 'iso-8859-5, unicode/1'])
def test_header_value_is_invalid(self, header_value):
returned = create_accept_charset_header(header_value=header_value)
assert isinstance(returned, AcceptCharsetInvalidHeader)
assert returned.header_value == header_value
class TestAcceptCharsetProperty(object):
def test_fget_header_is_None(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': None})
property_ = accept_charset_property()
returned = property_.fget(request=request)
assert isinstance(returned, AcceptCharsetNoHeader)
def test_fget_header_is_valid(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'UTF-8'})
property_ = accept_charset_property()
returned = property_.fget(request=request)
assert isinstance(returned, AcceptCharsetValidHeader)
def test_fget_header_is_invalid(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': ''})
property_ = accept_charset_property()
returned = property_.fget(request=request)
assert isinstance(returned, AcceptCharsetInvalidHeader)
def test_fset_value_is_None(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'UTF-8'})
property_ = accept_charset_property()
property_.fset(request=request, value=None)
assert isinstance(request.accept_charset, AcceptCharsetNoHeader)
assert 'HTTP_ACCEPT_CHARSET' not in request.environ
def test_fset_value_is_invalid(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'UTF-8'})
property_ = accept_charset_property()
property_.fset(request=request, value='')
assert isinstance(request.accept_charset, AcceptCharsetInvalidHeader)
assert request.environ['HTTP_ACCEPT_CHARSET'] == ''
def test_fset_value_is_valid(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'UTF-8'})
property_ = accept_charset_property()
property_.fset(request=request, value='UTF-7')
assert isinstance(request.accept_charset, AcceptCharsetValidHeader)
assert request.environ['HTTP_ACCEPT_CHARSET'] == 'UTF-7'
@pytest.mark.parametrize('value, value_as_header', [
(
'utf-8;q=0.5, iso-8859-5;q=0, utf-7',
'utf-8;q=0.5, iso-8859-5;q=0, utf-7',
),
(
[('utf-8', 0.5), ('iso-8859-5', 0.0), 'utf-7'],
'utf-8;q=0.5, iso-8859-5;q=0, utf-7',
),
(
(('utf-8', 0.5), ('iso-8859-5', 0.0), 'utf-7'),
'utf-8;q=0.5, iso-8859-5;q=0, utf-7',
),
(
{'utf-8': 0.5, 'iso-8859-5': 0.0, 'utf-7': 1.0},
'utf-7, utf-8;q=0.5, iso-8859-5;q=0',
),
])
def test_fset_value_types(self, value, value_as_header):
request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': ''})
property_ = accept_charset_property()
property_.fset(request=request, value=value)
assert isinstance(request.accept_charset, AcceptCharsetValidHeader)
assert request.environ['HTTP_ACCEPT_CHARSET'] == value_as_header
def test_fset_other_type_with_valid___str__(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': ''})
property_ = accept_charset_property()
class Other(object):
def __str__(self):
return 'utf-8;q=0.5, iso-8859-5;q=0, utf-7'
value = Other()
property_.fset(request=request, value=value)
assert isinstance(request.accept_charset, AcceptCharsetValidHeader)
assert request.environ['HTTP_ACCEPT_CHARSET'] == str(value)
def test_fset_AcceptCharsetNoHeader(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'utf-8'})
property_ = accept_charset_property()
header = AcceptCharsetNoHeader()
property_.fset(request=request, value=header)
assert isinstance(request.accept_charset, AcceptCharsetNoHeader)
assert 'HTTP_ACCEPT_CHARSET' not in request.environ
def test_fset_AcceptCharsetValidHeader(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'utf-8'})
property_ = accept_charset_property()
header = AcceptCharsetValidHeader('utf-7')
property_.fset(request=request, value=header)
assert isinstance(request.accept_charset, AcceptCharsetValidHeader)
assert request.environ['HTTP_ACCEPT_CHARSET'] == header.header_value
def test_fset_AcceptCharsetInvalidHeader(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'utf-8'})
property_ = accept_charset_property()
header = AcceptCharsetInvalidHeader('')
property_.fset(request=request, value=header)
assert isinstance(request.accept_charset, AcceptCharsetInvalidHeader)
assert request.environ['HTTP_ACCEPT_CHARSET'] == header.header_value
def test_fdel_header_key_in_environ(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_CHARSET': 'utf-8'})
property_ = accept_charset_property()
property_.fdel(request=request)
assert isinstance(request.accept_charset, AcceptCharsetNoHeader)
assert 'HTTP_ACCEPT_CHARSET' not in request.environ
def test_fdel_header_key_not_in_environ(self):
request = Request.blank('/')
property_ = accept_charset_property()
property_.fdel(request=request)
assert isinstance(request.accept_charset, AcceptCharsetNoHeader)
assert 'HTTP_ACCEPT_CHARSET' not in request.environ
class TestAcceptEncoding(object):
@pytest.mark.parametrize('value', [
'"',
'(',
')',
'/',
':',
';',
'<',
'=',
'>',
'?',
'@',
'[',
'\\',
']',
'{',
'}',
', ',
', , ',
'gzip;q=1.0, identity; q =0.5, *;q=0',
])
def test_parse__invalid_header(self, value):
with pytest.raises(ValueError):
AcceptEncoding.parse(value=value)
@pytest.mark.parametrize('value, expected_list', [
(',', []),
(', ,', []),
('*', [('*', 1.0)]),
("!#$%&'*+-.^_`|~;q=0.5", [("!#$%&'*+-.^_`|~", 0.5)]),
('0123456789', [('0123456789', 1.0)]),
(
',,\t foo \t;\t q=0.345,, bar ; Q=0.456 \t, ,\tCHARLIE \t,, ,',
[('foo', 0.345), ('bar', 0.456), ('CHARLIE', 1.0)]
),
# RFC 7231, section 5.3.4
('compress, gzip', [('compress', 1.0), ('gzip', 1.0)]),
('', []),
('*', [('*', 1.0)]),
('compress;q=0.5, gzip;q=1.0', [('compress', 0.5), ('gzip', 1.0)]),
(
'gzip;q=1.0, identity; q=0.5, *;q=0',
[('gzip', 1.0), ('identity', 0.5), ('*', 0.0)],
),
])
def test_parse__valid_header(self, value, expected_list):
returned = AcceptEncoding.parse(value=value)
list_of_returned = list(returned)
assert list_of_returned == expected_list
class TestAcceptEncodingValidHeader(object):
def test_parse__inherited(self):
returned = AcceptEncodingValidHeader.parse(
value=',,\t gzip;q=1.0, identity; q=0.5, *;q=0 \t ,',
)
list_of_returned = list(returned)
assert list_of_returned == \
[('gzip', 1.0), ('identity', 0.5), ('*', 0.0)]
@pytest.mark.parametrize('header_value', [
', ',
'gzip;q=1.0, identity; q =0.5, *;q=0',
])
def test___init___invalid_header(self, header_value):
with pytest.raises(ValueError):
AcceptEncodingValidHeader(header_value=header_value)
def test___init___valid_header(self):
header_value = ',,\t gzip;q=1.0, identity; q=0, *;q=0.5 \t ,'
instance = AcceptEncodingValidHeader(header_value=header_value)
assert instance.header_value == header_value
assert instance.parsed == [
('gzip', 1.0), ('identity', 0.0), ('*', 0.5),
]
assert instance._parsed_nonzero == [('gzip', 1.0), ('*', 0.5)]
assert isinstance(instance, AcceptEncoding)
def test___add___None(self):
left_operand = AcceptEncodingValidHeader(header_value='gzip')
result = left_operand + None
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
@pytest.mark.parametrize('right_operand', [
', ',
[', '],
(', ',),
{', ': 1.0},
])
def test___add___invalid_value(self, right_operand):
left_operand = AcceptEncodingValidHeader(header_value='gzip')
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
def test___add___other_type_with_invalid___str__(self):
left_operand = AcceptEncodingValidHeader(header_value='gzip')
class Other(object):
def __str__(self):
return ', '
right_operand = Other()
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
@pytest.mark.parametrize('value', [
'',
[],
(),
{},
])
def test___add___valid_empty_value(self, value):
left_operand = AcceptEncodingValidHeader(header_value='gzip')
result = left_operand + value
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
def test___add___other_type_with_valid___str___empty(self):
left_operand = AcceptEncodingValidHeader(header_value='gzip')
class Other(object):
def __str__(self):
return ''
result = left_operand + Other()
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
@pytest.mark.parametrize('value, value_as_header', [
('compress;q=0.5, deflate;q=0, *', 'compress;q=0.5, deflate;q=0, *'),
(
['compress;q=0.5', 'deflate;q=0', '*'],
'compress;q=0.5, deflate;q=0, *',
),
(
[('compress', 0.5), ('deflate', 0.0), ('*', 1.0)],
'compress;q=0.5, deflate;q=0, *',
),
(
('compress;q=0.5', 'deflate;q=0', '*'),
'compress;q=0.5, deflate;q=0, *',
),
(
(('compress', 0.5), ('deflate', 0.0), ('*', 1.0)),
'compress;q=0.5, deflate;q=0, *',
),
(
{'compress': 0.5, 'deflate': 0.0, '*': 1.0},
'*, compress;q=0.5, deflate;q=0',
),
])
def test___add___valid_value(self, value, value_as_header):
header = ',\t ,gzip, identity;q=0.333,'
result = AcceptEncodingValidHeader(header_value=header) + value
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == header + ', ' + value_as_header
def test___add___other_type_with_valid___str___not_empty(self):
header = ',\t ,gzip, identity;q=0.333,'
class Other(object):
def __str__(self):
return 'compress;q=0.5, deflate;q=0, *'
right_operand = Other()
result = AcceptEncodingValidHeader(header_value=header) + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == header + ', ' + str(right_operand)
def test___add___AcceptEncodingValidHeader_header_value_empty(self):
left_operand = AcceptEncodingValidHeader(
header_value=',\t ,gzip, identity;q=0.333,'
)
right_operand = AcceptEncodingValidHeader(header_value='')
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
def test___add___AcceptEncodingValidHeader_header_value_not_empty(self):
left_operand = AcceptEncodingValidHeader(
header_value=',\t ,gzip, identity;q=0.333,',
)
right_operand = AcceptEncodingValidHeader(
header_value='compress;q=0.5, deflate;q=0, *',
)
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == left_operand.header_value + ', ' + \
right_operand.header_value
def test___add___AcceptEncodingNoHeader(self):
valid_header_instance = AcceptEncodingValidHeader(header_value='gzip')
result = valid_header_instance + AcceptEncodingNoHeader()
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == valid_header_instance.header_value
assert result is not valid_header_instance
@pytest.mark.parametrize('header_value', [
', ',
'compress;q=1.001',
])
def test___add___AcceptEncodingInvalidHeader(self, header_value):
valid_header_instance = AcceptEncodingValidHeader(header_value='gzip')
result = valid_header_instance + AcceptEncodingInvalidHeader(
header_value=header_value,
)
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == valid_header_instance.header_value
assert result is not valid_header_instance
def test___bool__(self):
instance = AcceptEncodingValidHeader(header_value='gzip')
returned = bool(instance)
assert returned is True
def test___contains__(self):
accept = AcceptEncodingValidHeader('gzip, compress')
assert 'gzip' in accept
assert 'deflate' not in accept
for mask in ['*', 'gzip', 'gZIP']:
assert 'gzip' in AcceptEncodingValidHeader(mask)
def test___iter__(self):
instance = AcceptEncodingValidHeader(
header_value='gzip; q=0.5, *; q=0, deflate; q=0.8, compress',
)
assert list(instance) == ['compress', 'deflate', 'gzip']
def test___radd___None(self):
right_operand = AcceptEncodingValidHeader(header_value='gzip')
result = None + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
@pytest.mark.parametrize('left_operand', [
', ',
[', '],
(', ',),
{', ': 1.0},
])
def test___radd___invalid_value(self, left_operand):
right_operand = AcceptEncodingValidHeader(header_value='gzip')
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
def test___radd___other_type_with_invalid___str__(self):
right_operand = AcceptEncodingValidHeader(header_value='gzip')
class Other(object):
def __str__(self):
return ', '
result = Other() + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
@pytest.mark.parametrize('value', [
'',
[],
(),
{},
])
def test___radd___valid_empty_value(self, value):
right_operand = AcceptEncodingValidHeader(header_value='gzip')
result = value + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
def test___radd___other_type_with_valid___str___empty(self):
right_operand = AcceptEncodingValidHeader(header_value='gzip')
class Other(object):
def __str__(self):
return ''
result = Other() + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
@pytest.mark.parametrize('value, value_as_header', [
('compress;q=0.5, deflate;q=0, *', 'compress;q=0.5, deflate;q=0, *'),
(
['compress;q=0.5', 'deflate;q=0', '*'],
'compress;q=0.5, deflate;q=0, *',
),
(
[('compress', 0.5), ('deflate', 0.0), ('*', 1.0)],
'compress;q=0.5, deflate;q=0, *',
),
(
('compress;q=0.5', 'deflate;q=0', '*'),
'compress;q=0.5, deflate;q=0, *',
),
(
(('compress', 0.5), ('deflate', 0.0), ('*', 1.0)),
'compress;q=0.5, deflate;q=0, *',
),
(
{'compress': 0.5, 'deflate': 0.0, '*': 1.0},
'*, compress;q=0.5, deflate;q=0',
),
])
def test___radd___valid_non_empty_value(self, value, value_as_header):
header = ',\t ,gzip, identity;q=0.333,'
result = value + AcceptEncodingValidHeader(header_value=header)
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == value_as_header + ', ' + header
def test___radd___other_type_with_valid___str___not_empty(self):
header = ',\t ,gzip, identity;q=0.333,'
class Other(object):
def __str__(self):
return 'compress;q=0.5, deflate;q=0, *'
left_operand = Other()
result = left_operand + AcceptEncodingValidHeader(header_value=header)
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == str(left_operand) + ', ' + header
@pytest.mark.parametrize('header_value, expected_returned', [
('', "<AcceptEncodingValidHeader ('')>"),
(
",\t, a ;\t q=0.20 , b ,',",
# single quote is valid character in token
"""<AcceptEncodingValidHeader ("a;q=0.2, b, \'")>"""
),
])
def test___repr__(self, header_value, expected_returned):
instance = AcceptEncodingValidHeader(header_value=header_value)
assert repr(instance) == expected_returned
@pytest.mark.parametrize('header_value, expected_returned', [
('', ''),
(",\t, a ;\t q=0.20 , b ,',", "a;q=0.2, b, '"),
])
def test___str__(self, header_value, expected_returned):
instance = AcceptEncodingValidHeader(header_value=header_value)
assert str(instance) == expected_returned
@pytest.mark.parametrize('header_value, offers, expected_returned', [
('', [], []),
('gzip, compress', [], []),
('', ['gzip', 'deflate'], []),
('', ['gzip', 'identity'], [('identity', 1.0)]),
('compress, deflate, gzip', ['identity'], [('identity', 1.0)]),
('compress, identity;q=0, gzip', ['identity'], []),
# *;q=0 does not make sense, but is valid
('*;q=0', ['identity'], []),
('*;q=0, deflate, gzip', ['identity'], []),
('*;q=0, deflate, identity;q=0, gzip', ['identity'], []),
(
'*;q=0, deflate, identity;q=0.1, gzip',
['identity'],
[('identity', 0.1)],
),
(
'compress, deflate, gzip',
['identity', 'gzip'],
[('identity', 1.0), ('gzip', 1.0)],
),
(
'compress, deflate, gzip',
['gzip', 'identity'],
[('gzip', 1.0), ('identity', 1.0)],
),
(
'IDentity;q=0.5, deflATE;q=0, gZIP;q=0, COMPress',
['GZip', 'DEFlate', 'IDENTity', 'comPRESS'],
[('comPRESS', 1.0), ('IDENTity', 0.5)],
),
(
'compress;q=0, identity, *;q=0.5, identity;q=0, *;q=0, compress',
# does not make sense, but is valid
['compress', 'identity', 'deflate', 'gzip'],
[('identity', 1.0), ('deflate', 0.5), ('gzip', 0.5)],
),
])
def test_acceptable_offers(
self, header_value, offers, expected_returned,
):
instance = AcceptEncodingValidHeader(header_value=header_value)
returned = instance.acceptable_offers(offers=offers)
assert returned == expected_returned
def test_best_match(self):
accept = AcceptEncodingValidHeader('gzip, iso-8859-5')
assert accept.best_match(['gzip', 'iso-8859-5']) == 'gzip'
assert accept.best_match(['iso-8859-5', 'gzip']) == 'iso-8859-5'
assert accept.best_match([('iso-8859-5', 0.5), 'gzip']) == 'gzip'
assert accept.best_match([('iso-8859-5', 0.5), ('gzip', 0.4)]) == \
'iso-8859-5'
def test_best_match_with_one_lower_q(self):
accept = AcceptEncodingValidHeader('gzip, compress;q=0.5')
assert accept.best_match(['gzip', 'compress']) == 'gzip'
accept = AcceptEncodingValidHeader('gzip;q=0.5, compress')
assert accept.best_match(['gzip', 'compress']) == 'compress'
def test_best_match_with_complex_q(self):
accept = AcceptEncodingValidHeader(
'gzip, compress;q=0.55, deflate;q=0.59'
)
assert accept.best_match(['gzip', 'compress']) == 'gzip'
accept = AcceptEncodingValidHeader(
'gzip;q=0.5, compress;q=0.586, deflate;q=0.596'
)
assert accept.best_match(['gzip', 'deflate']) == 'deflate'
def test_best_match_mixedcase(self):
accept = AcceptEncodingValidHeader(
'gZiP; q=0.2, COMPress; Q=0.4, *; q=0.05'
)
assert accept.best_match(['gzIP']) == 'gzIP'
assert accept.best_match(['DeFlAte']) == 'DeFlAte'
assert accept.best_match(['deflaTe', 'compRess', 'UtF-8']) == \
'compRess'
def test_best_match_zero_quality(self):
assert AcceptEncodingValidHeader('deflate, *;q=0').best_match(
['gzip']
) is None
assert 'content-coding' not in AcceptEncodingValidHeader('*;q=0')
def test_quality(self):
accept = AcceptEncodingValidHeader('gzip')
assert accept.quality('gzip') == 1
accept = AcceptEncodingValidHeader('gzip;q=0.5')
assert accept.quality('gzip') == 0.5
def test_quality_not_found(self):
accept = AcceptEncodingValidHeader('gzip')
assert accept.quality('compress') is None
class TestAcceptEncodingNoHeader(object):
def test_parse__inherited(self):
returned = AcceptEncodingNoHeader.parse(
value=',,\t gzip;q=1.0, identity; q=0.5, *;q=0 \t ,',
)
list_of_returned = list(returned)
assert list_of_returned == \
[('gzip', 1.0), ('identity', 0.5), ('*', 0.0)]
def test___init__(self):
instance = AcceptEncodingNoHeader()
assert instance.header_value is None
assert instance.parsed is None
assert instance._parsed_nonzero is None
assert isinstance(instance, AcceptEncoding)
def test___add___None(self):
left_operand = AcceptEncodingNoHeader()
result = left_operand + None
assert isinstance(result, AcceptEncodingNoHeader)
@pytest.mark.parametrize('right_operand', [
', ',
[', '],
(', ',),
{', ': 1.0},
])
def test___add___invalid_value(self, right_operand):
left_operand = AcceptEncodingNoHeader()
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingNoHeader)
def test___add___other_type_with_invalid___str__(self):
left_operand = AcceptEncodingNoHeader()
class Other(object):
def __str__(self):
return ', '
right_operand = Other()
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingNoHeader)
@pytest.mark.parametrize('value', [
'',
[],
(),
{},
])
def test___add___valid_empty_value(self, value):
left_operand = AcceptEncodingNoHeader()
result = left_operand + value
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == ''
def test___add___other_type_with_valid___str___empty(self):
left_operand = AcceptEncodingNoHeader()
class Other(object):
def __str__(self):
return ''
result = left_operand + Other()
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == ''
@pytest.mark.parametrize('value, value_as_header', [
('compress;q=0.5, deflate;q=0, *', 'compress;q=0.5, deflate;q=0, *'),
(
['compress;q=0.5', 'deflate;q=0', '*'],
'compress;q=0.5, deflate;q=0, *',
),
(
[('compress', 0.5), ('deflate', 0.0), ('*', 1.0)],
'compress;q=0.5, deflate;q=0, *',
),
(
('compress;q=0.5', 'deflate;q=0', '*'),
'compress;q=0.5, deflate;q=0, *',
),
(
(('compress', 0.5), ('deflate', 0.0), ('*', 1.0)),
'compress;q=0.5, deflate;q=0, *',
),
(
{'compress': 0.5, 'deflate': 0.0, '*': 1.0},
'*, compress;q=0.5, deflate;q=0',
),
])
def test___add___valid_value(self, value, value_as_header):
result = AcceptEncodingNoHeader() + value
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == value_as_header
def test___add___other_type_with_valid___str___not_empty(self):
class Other(object):
def __str__(self):
return 'compress;q=0.5, deflate;q=0, *'
right_operand = Other()
result = AcceptEncodingNoHeader() + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == str(right_operand)
def test___add___AcceptEncodingValidHeader_header_value_empty(self):
right_operand = AcceptEncodingValidHeader(header_value='')
result = AcceptEncodingNoHeader() + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
def test___add___AcceptEncodingValidHeader_header_value_not_empty(self):
right_operand = AcceptEncodingValidHeader(
header_value='compress;q=0.5, deflate;q=0, *',
)
result = AcceptEncodingNoHeader() + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == right_operand.header_value
def test___add___AcceptEncodingNoHeader(self):
left_operand = AcceptEncodingNoHeader()
right_operand = AcceptEncodingNoHeader()
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingNoHeader)
assert result is not left_operand
assert result is not right_operand
@pytest.mark.parametrize('header_value', [
', ',
'compress;q=1.001',
])
def test___add___AcceptEncodingInvalidHeader(self, header_value):
left_operand = AcceptEncodingNoHeader()
result = left_operand + AcceptEncodingInvalidHeader(
header_value=header_value,
)
assert isinstance(result, AcceptEncodingNoHeader)
assert result is not left_operand
def test___bool__(self):
instance = AcceptEncodingNoHeader()
returned = bool(instance)
assert returned is False
def test___contains__(self):
instance = AcceptEncodingNoHeader()
returned = ('content-coding' in instance)
assert returned is True
def test___iter__(self):
instance = AcceptEncodingNoHeader()
returned = list(instance)
assert returned == []
def test___radd___None(self):
right_operand = AcceptEncodingNoHeader()
result = None + right_operand
assert isinstance(result, AcceptEncodingNoHeader)
assert result is not right_operand
@pytest.mark.parametrize('left_operand', [
', ',
[', '],
(', ',),
{', ': 1.0},
])
def test___radd___invalid_value(self, left_operand):
right_operand = AcceptEncodingNoHeader()
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingNoHeader)
assert result is not right_operand
def test___radd___other_type_with_invalid___str__(self):
right_operand = AcceptEncodingNoHeader()
class Other(object):
def __str__(self):
return ', '
result = Other() + right_operand
assert isinstance(result, AcceptEncodingNoHeader)
assert result is not right_operand
@pytest.mark.parametrize('value', [
'',
[],
(),
{},
])
def test___radd___valid_empty_value(self, value):
result = value + AcceptEncodingNoHeader()
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == ''
def test___radd___other_type_with_valid___str___empty(self):
class Other(object):
def __str__(self):
return ''
result = Other() + AcceptEncodingNoHeader()
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == ''
@pytest.mark.parametrize('value, value_as_header', [
('compress;q=0.5, deflate;q=0, *', 'compress;q=0.5, deflate;q=0, *'),
(
['compress;q=0.5', 'deflate;q=0', '*'],
'compress;q=0.5, deflate;q=0, *',
),
(
[('compress', 0.5), ('deflate', 0.0), ('*', 1.0)],
'compress;q=0.5, deflate;q=0, *',
),
(
('compress;q=0.5', 'deflate;q=0', '*'),
'compress;q=0.5, deflate;q=0, *',
),
(
(('compress', 0.5), ('deflate', 0.0), ('*', 1.0)),
'compress;q=0.5, deflate;q=0, *',
),
(
{'compress': 0.5, 'deflate': 0.0, '*': 1.0},
'*, compress;q=0.5, deflate;q=0',
),
])
def test___radd___valid_non_empty_value(self, value, value_as_header):
result = value + AcceptEncodingNoHeader()
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == value_as_header
def test___radd___other_type_with_valid___str___not_empty(self):
class Other(object):
def __str__(self):
return 'compress;q=0.5, deflate;q=0, *'
left_operand = Other()
result = left_operand + AcceptEncodingNoHeader()
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == str(left_operand)
def test___repr__(self):
instance = AcceptEncodingNoHeader()
assert repr(instance) == '<AcceptEncodingNoHeader>'
def test___str__(self):
instance = AcceptEncodingNoHeader()
assert str(instance) == '<no header in request>'
def test_acceptable_offers(self):
instance = AcceptEncodingNoHeader()
returned = instance.acceptable_offers(offers=['a', 'b', 'c'])
assert returned == [('a', 1.0), ('b', 1.0), ('c', 1.0)]
def test_best_match(self):
accept = AcceptEncodingNoHeader()
assert accept.best_match(['gzip', 'compress']) == 'gzip'
assert accept.best_match([('gzip', 1), ('compress', 0.5)]) == 'gzip'
assert accept.best_match([('gzip', 0.5), ('compress', 1)]) == \
'compress'
assert accept.best_match([('gzip', 0.5), 'compress']) == 'compress'
assert accept.best_match(
[('gzip', 0.5), 'compress'], default_match=True
) == 'compress'
assert accept.best_match(
[('gzip', 0.5), 'compress'], default_match=False
) == 'compress'
assert accept.best_match([], default_match='fallback') == 'fallback'
def test_quality(self):
instance = AcceptEncodingNoHeader()
returned = instance.quality(offer='content-coding')
assert returned == 1.0
class TestAcceptEncodingInvalidHeader(object):
def test_parse__inherited(self):
returned = AcceptEncodingInvalidHeader.parse(
value=',,\t gzip;q=1.0, identity; q=0.5, *;q=0 \t ,',
)
list_of_returned = list(returned)
assert list_of_returned == \
[('gzip', 1.0), ('identity', 0.5), ('*', 0.0)]
def test___init__(self):
header_value = 'invalid header'
instance = AcceptEncodingInvalidHeader(header_value=header_value)
assert instance.header_value == header_value
assert instance.parsed is None
assert instance._parsed_nonzero is None
assert isinstance(instance, AcceptEncoding)
def test___add___None(self):
left_operand = AcceptEncodingInvalidHeader(header_value=', ')
result = left_operand + None
assert isinstance(result, AcceptEncodingNoHeader)
@pytest.mark.parametrize('right_operand', [
', ',
[', '],
(', ',),
{', ': 1.0},
])
def test___add___invalid_value(self, right_operand):
left_operand = AcceptEncodingInvalidHeader(
header_value='invalid header',
)
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingNoHeader)
def test___add___other_type_with_invalid___str__(self):
left_operand = AcceptEncodingInvalidHeader(
header_value='invalid header',
)
class Other(object):
def __str__(self):
return ', '
right_operand = Other()
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingNoHeader)
@pytest.mark.parametrize('value', [
'',
[],
(),
{},
])
def test___add___valid_empty_value(self, value):
left_operand = AcceptEncodingInvalidHeader(header_value=', ')
result = left_operand + value
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == ''
def test___add___other_type_with_valid___str___empty(self):
left_operand = AcceptEncodingInvalidHeader(header_value=', ')
class Other(object):
def __str__(self):
return ''
result = left_operand + Other()
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == ''
@pytest.mark.parametrize('value, value_as_header', [
('compress;q=0.5, deflate;q=0, *', 'compress;q=0.5, deflate;q=0, *'),
(
['compress;q=0.5', 'deflate;q=0', '*'],
'compress;q=0.5, deflate;q=0, *',
),
(
[('compress', 0.5), ('deflate', 0.0), ('*', 1.0)],
'compress;q=0.5, deflate;q=0, *',
),
(
('compress;q=0.5', 'deflate;q=0', '*'),
'compress;q=0.5, deflate;q=0, *',
),
(
(('compress', 0.5), ('deflate', 0.0), ('*', 1.0)),
'compress;q=0.5, deflate;q=0, *',
),
(
{'compress': 0.5, 'deflate': 0.0, '*': 1.0},
'*, compress;q=0.5, deflate;q=0',
),
])
def test___add___valid_value(self, value, value_as_header):
result = AcceptEncodingInvalidHeader(header_value=', ') + value
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == value_as_header
def test___add___other_type_with_valid___str___not_empty(self):
class Other(object):
def __str__(self):
return '*, compress;q=0.5, deflate;q=0'
right_operand = Other()
result = AcceptEncodingInvalidHeader(header_value=', ') + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == str(right_operand)
def test___add___AcceptEncodingValidHeader_header_value_empty(self):
left_operand = AcceptEncodingInvalidHeader(header_value=', ')
right_operand = AcceptEncodingValidHeader(header_value='')
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
def test___add___AcceptEncodingValidHeader_header_value_not_empty(self):
left_operand = AcceptEncodingInvalidHeader(header_value=', ')
right_operand = AcceptEncodingValidHeader(
header_value='compress;q=0.5, deflate;q=0, *',
)
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == right_operand.header_value
def test___add___AcceptEncodingNoHeader(self):
left_operand = AcceptEncodingInvalidHeader(header_value=', ')
right_operand = AcceptEncodingNoHeader()
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingNoHeader)
assert result is not right_operand
@pytest.mark.parametrize('header_value', [
', ',
'compress;q=1.001',
])
def test___add___AcceptEncodingInvalidHeader(self, header_value):
result = AcceptEncodingInvalidHeader(header_value='gzip;;q=1') + \
AcceptEncodingInvalidHeader(header_value=header_value)
assert isinstance(result, AcceptEncodingNoHeader)
def test___bool__(self):
instance = AcceptEncodingInvalidHeader(header_value=', ')
returned = bool(instance)
assert returned is False
def test___contains__(self):
instance = AcceptEncodingInvalidHeader(header_value=', ')
returned = ('content-coding' in instance)
assert returned is True
def test___iter__(self):
instance = AcceptEncodingInvalidHeader(header_value=', ')
returned = list(instance)
assert returned == []
def test___radd___None(self):
right_operand = AcceptEncodingInvalidHeader(header_value=', ')
result = None + right_operand
assert isinstance(result, AcceptEncodingNoHeader)
@pytest.mark.parametrize('left_operand', [
', ',
[', '],
(', ',),
{', ': 1.0},
])
def test___radd___invalid_value(self, left_operand):
right_operand = AcceptEncodingInvalidHeader(header_value='gzip;q= 1')
result = left_operand + right_operand
assert isinstance(result, AcceptEncodingNoHeader)
def test___radd___other_type_with_invalid___str__(self):
right_operand = AcceptEncodingInvalidHeader(header_value='gzip;q= 1')
class Other(object):
def __str__(self):
return ', '
result = Other() + right_operand
assert isinstance(result, AcceptEncodingNoHeader)
@pytest.mark.parametrize('value', [
'',
[],
(),
{},
])
def test___radd___valid_empty_value(self, value):
right_operand = AcceptEncodingInvalidHeader(header_value=', ')
result = value + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == ''
def test___radd___other_type_with_valid___str___empty(self):
right_operand = AcceptEncodingInvalidHeader(header_value=', ')
class Other(object):
def __str__(self):
return ''
result = Other() + right_operand
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == ''
@pytest.mark.parametrize('value, value_as_header', [
('compress;q=0.5, deflate;q=0, *', 'compress;q=0.5, deflate;q=0, *'),
(
['compress;q=0.5', 'deflate;q=0', '*'],
'compress;q=0.5, deflate;q=0, *',
),
(
[('compress', 0.5), ('deflate', 0.0), ('*', 1.0)],
'compress;q=0.5, deflate;q=0, *',
),
(
('compress;q=0.5', 'deflate;q=0', '*'),
'compress;q=0.5, deflate;q=0, *',
),
(
(('compress', 0.5), ('deflate', 0.0), ('*', 1.0)),
'compress;q=0.5, deflate;q=0, *',
),
(
{'compress': 0.5, 'deflate': 0.0, '*': 1.0},
'*, compress;q=0.5, deflate;q=0',
),
])
def test___radd___valid_non_empty_value(self, value, value_as_header):
result = value + AcceptEncodingInvalidHeader(header_value=', ')
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == value_as_header
def test___radd___other_type_with_valid___str___not_empty(self):
class Other(object):
def __str__(self):
return 'compress;q=0.5, deflate;q=0, *'
left_operand = Other()
result = left_operand + AcceptEncodingInvalidHeader(header_value=', ')
assert isinstance(result, AcceptEncodingValidHeader)
assert result.header_value == str(left_operand)
def test___repr__(self):
instance = AcceptEncodingInvalidHeader(header_value='\x00')
assert repr(instance) == '<AcceptEncodingInvalidHeader>'
def test___str__(self):
instance = AcceptEncodingInvalidHeader(header_value=", ")
assert str(instance) == '<invalid header value>'
def test_acceptable_offers(self):
instance = AcceptEncodingInvalidHeader(header_value=', ')
returned = instance.acceptable_offers(offers=['a', 'b', 'c'])
assert returned == [('a', 1.0), ('b', 1.0), ('c', 1.0)]
def test_best_match(self):
accept = AcceptEncodingInvalidHeader(header_value=', ')
assert accept.best_match(['gzip', 'compress']) == 'gzip'
assert accept.best_match([('gzip', 1), ('compress', 0.5)]) == 'gzip'
assert accept.best_match([('gzip', 0.5), ('compress', 1)]) == \
'compress'
assert accept.best_match([('gzip', 0.5), 'compress']) == 'compress'
assert accept.best_match(
[('gzip', 0.5), 'compress'], default_match=True
) == 'compress'
assert accept.best_match(
[('gzip', 0.5), 'compress'], default_match=False
) == 'compress'
assert accept.best_match([], default_match='fallback') == 'fallback'
def test_quality(self):
instance = AcceptEncodingInvalidHeader(header_value=', ')
returned = instance.quality(offer='content-coding')
assert returned == 1.0
class TestCreateAcceptEncodingHeader(object):
def test_header_value_is_None(self):
header_value = None
returned = create_accept_encoding_header(header_value=header_value)
assert isinstance(returned, AcceptEncodingNoHeader)
assert returned.header_value == header_value
def test_header_value_is_valid(self):
header_value = 'gzip, identity;q=0.9'
returned = create_accept_encoding_header(header_value=header_value)
assert isinstance(returned, AcceptEncodingValidHeader)
assert returned.header_value == header_value
@pytest.mark.parametrize('header_value', [', ', 'gzip;q= 1'])
def test_header_value_is_invalid(self, header_value):
returned = create_accept_encoding_header(header_value=header_value)
assert isinstance(returned, AcceptEncodingInvalidHeader)
assert returned.header_value == header_value
class TestAcceptEncodingProperty(object):
def test_fget_header_is_None(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': None})
property_ = accept_encoding_property()
returned = property_.fget(request=request)
assert isinstance(returned, AcceptEncodingNoHeader)
def test_fget_header_is_valid(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': 'gzip'})
property_ = accept_encoding_property()
returned = property_.fget(request=request)
assert isinstance(returned, AcceptEncodingValidHeader)
def test_fget_header_is_invalid(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': ', '})
property_ = accept_encoding_property()
returned = property_.fget(request=request)
assert isinstance(returned, AcceptEncodingInvalidHeader)
def test_fset_value_is_None(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': 'gzip'})
property_ = accept_encoding_property()
property_.fset(request=request, value=None)
assert isinstance(request.accept_encoding, AcceptEncodingNoHeader)
assert 'HTTP_ACCEPT_ENCODING' not in request.environ
def test_fset_value_is_invalid(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': 'gzip'})
property_ = accept_encoding_property()
property_.fset(request=request, value=', ')
assert isinstance(request.accept_encoding, AcceptEncodingInvalidHeader)
assert request.environ['HTTP_ACCEPT_ENCODING'] == ', '
def test_fset_value_is_valid(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': 'gzip'})
property_ = accept_encoding_property()
property_.fset(request=request, value='compress')
assert isinstance(request.accept_encoding, AcceptEncodingValidHeader)
assert request.environ['HTTP_ACCEPT_ENCODING'] == 'compress'
@pytest.mark.parametrize('value, value_as_header', [
(
'gzip;q=0.5, compress;q=0, deflate',
'gzip;q=0.5, compress;q=0, deflate',
),
(
[('gzip', 0.5), ('compress', 0.0), 'deflate'],
'gzip;q=0.5, compress;q=0, deflate',
),
(
(('gzip', 0.5), ('compress', 0.0), 'deflate'),
'gzip;q=0.5, compress;q=0, deflate',
),
(
{'gzip': 0.5, 'compress': 0.0, 'deflate': 1.0},
'deflate, gzip;q=0.5, compress;q=0',
),
])
def test_fset_value_types(self, value, value_as_header):
request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': ''})
property_ = accept_encoding_property()
property_.fset(request=request, value=value)
assert isinstance(request.accept_encoding, AcceptEncodingValidHeader)
assert request.environ['HTTP_ACCEPT_ENCODING'] == value_as_header
def test_fset_other_type_with_valid___str__(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': ''})
property_ = accept_encoding_property()
class Other(object):
def __str__(self):
return 'gzip;q=0.5, compress;q=0, deflate'
value = Other()
property_.fset(request=request, value=value)
assert isinstance(request.accept_encoding, AcceptEncodingValidHeader)
assert request.environ['HTTP_ACCEPT_ENCODING'] == str(value)
def test_fset_AcceptEncodingNoHeader(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': ''})
property_ = accept_encoding_property()
header = AcceptEncodingNoHeader()
property_.fset(request=request, value=header)
assert isinstance(request.accept_encoding, AcceptEncodingNoHeader)
assert 'HTTP_ACCEPT_ENCODING' not in request.environ
def test_fset_AcceptEncodingValidHeader(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': ''})
property_ = accept_encoding_property()
header = AcceptEncodingValidHeader('gzip')
property_.fset(request=request, value=header)
assert isinstance(request.accept_encoding, AcceptEncodingValidHeader)
assert request.environ['HTTP_ACCEPT_ENCODING'] == header.header_value
def test_fset_AcceptEncodingInvalidHeader(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': 'gzip'})
property_ = accept_encoding_property()
header = AcceptEncodingInvalidHeader(', ')
property_.fset(request=request, value=header)
assert isinstance(request.accept_encoding, AcceptEncodingInvalidHeader)
assert request.environ['HTTP_ACCEPT_ENCODING'] == header.header_value
def test_fdel_header_key_in_environ(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_ENCODING': 'gzip'})
property_ = accept_encoding_property()
property_.fdel(request=request)
assert isinstance(request.accept_encoding, AcceptEncodingNoHeader)
assert 'HTTP_ACCEPT_ENCODING' not in request.environ
def test_fdel_header_key_not_in_environ(self):
request = Request.blank('/')
property_ = accept_encoding_property()
property_.fdel(request=request)
assert isinstance(request.accept_encoding, AcceptEncodingNoHeader)
assert 'HTTP_ACCEPT_ENCODING' not in request.environ
class TestAcceptLanguage(object):
@pytest.mark.parametrize('value', [
'',
'*s',
'*-a',
'a-*',
'a' * 9,
'a-' + 'a' * 9,
'a-a-' + 'a' * 9,
'-',
'a-',
'-a',
'---',
'--a',
'1-a',
'1-a-a',
'en_gb',
'en/gb',
'foo, bar, baz;q= 0.001',
'foo , ,bar,charlie ',
])
def test_parse__invalid_header(self, value):
with pytest.raises(ValueError):
AcceptLanguage.parse(value=value)
@pytest.mark.parametrize('value, expected_list', [
('*', [('*', 1.0)]),
('fR;q=0.5', [('fR', 0.5)]),
('zh-Hant;q=0.500', [('zh-Hant', 0.5)]),
('zh-Hans-CN;q=1', [('zh-Hans-CN', 1.0)]),
('de-CH-x-phonebk;q=1.0', [('de-CH-x-phonebk', 1.0)]),
('az-Arab-x-AZE-derbend;q=1.00', [('az-Arab-x-AZE-derbend', 1.0)]),
('zh-CN-a-myExt-x-private;q=1.000', [('zh-CN-a-myExt-x-private', 1.0)]),
('aaaaaaaa', [('aaaaaaaa', 1.0)]),
('aaaaaaaa-a', [('aaaaaaaa-a', 1.0)]),
('aaaaaaaa-aaaaaaaa', [('aaaaaaaa-aaaaaaaa', 1.0)]),
('a-aaaaaaaa-aaaaaaaa', [('a-aaaaaaaa-aaaaaaaa', 1.0)]),
('aaaaaaaa-a-aaaaaaaa', [('aaaaaaaa-a-aaaaaaaa', 1.0)]),
(
'zh-Hant;q=0.372,zh-CN-a-myExt-x-private;q=0.977,de,*;q=0.000',
[
('zh-Hant', 0.372), ('zh-CN-a-myExt-x-private', 0.977),
('de', 1.0), ('*', 0.0)
]
),
(
',\t foo \t;\t q=0.345,, bar ; Q=0.456 \t, ,\tcharlie \t,, ,',
[('foo', 0.345), ('bar', 0.456), ('charlie', 1.0)]
),
# RFC 7230 Section 7
('foo,bar', [('foo', 1.0), ('bar', 1.0)]),
('foo, bar,', [('foo', 1.0), ('bar', 1.0)]),
# RFC 7230 Errata ID: 4169
('foo , ,bar,charlie', [('foo', 1.0), ('bar', 1.0), ('charlie', 1.0)]),
])
def test_parse__valid_header(self, value, expected_list):
returned = AcceptLanguage.parse(value=value)
list_of_returned = list(returned)
assert list_of_returned == expected_list
class TestAcceptLanguageValidHeader(object):
@pytest.mark.parametrize('header_value', [
'',
', da;q=0.2, en-gb;q=0.3 ',
])
def test___init___invalid_header(self, header_value):
with pytest.raises(ValueError):
AcceptLanguageValidHeader(header_value=header_value)
def test___init___valid_header(self):
header_value = \
'zh-Hant;q=0.372,zh-CN-a-myExt-x-private;q=0.977,de,*;q=0.000'
instance = AcceptLanguageValidHeader(header_value=header_value)
assert instance.header_value == header_value
assert instance.parsed == [
('zh-Hant', 0.372), ('zh-CN-a-myExt-x-private', 0.977),
('de', 1.0), ('*', 0.0)
]
assert instance._parsed_nonzero == [
('zh-Hant', 0.372), ('zh-CN-a-myExt-x-private', 0.977),
('de', 1.0)
]
assert isinstance(instance, AcceptLanguage)
def test___add___None(self):
left_operand = AcceptLanguageValidHeader(header_value='en')
result = left_operand + None
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
@pytest.mark.parametrize('right_operand', [
'',
[],
(),
{},
'en_gb',
['en_gb'],
('en_gb',),
{'en_gb': 1.0},
',',
[','],
(',',),
{',': 1.0},
])
def test___add___invalid_value(self, right_operand):
left_operand = AcceptLanguageValidHeader(header_value='en')
result = left_operand + right_operand
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
@pytest.mark.parametrize('str_', ['', 'en_gb', ','])
def test___add___other_type_with_invalid___str__(self, str_,):
left_operand = AcceptLanguageValidHeader(header_value='en')
class Other(object):
def __str__(self):
return str_
right_operand = Other()
result = left_operand + right_operand
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == left_operand.header_value
assert result is not left_operand
@pytest.mark.parametrize('value, value_as_header', [
('en-gb;q=0.5, fr;q=0, es', 'en-gb;q=0.5, fr;q=0, es'),
([('en-gb', 0.5), ('fr', 0.0), 'es'], 'en-gb;q=0.5, fr;q=0, es'),
((('en-gb', 0.5), ('fr', 0.0), 'es'), 'en-gb;q=0.5, fr;q=0, es'),
({'en-gb': 0.5, 'fr': 0.0, 'es': 1.0}, 'es, en-gb;q=0.5, fr;q=0'),
])
def test___add___valid_value(self, value, value_as_header):
header = ',\t ,de, zh-Hans;q=0.333,'
result = AcceptLanguageValidHeader(header_value=header) + value
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == header + ', ' + value_as_header
def test___add___other_type_with_valid___str__(self):
header = ',\t ,de, zh-Hans;q=0.333,'
class Other(object):
def __str__(self):
return 'en-gb;q=0.5, fr;q=0, es'
right_operand = Other()
result = AcceptLanguageValidHeader(header_value=header) + right_operand
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == header + ', ' + str(right_operand)
def test___add___AcceptLanguageValidHeader(self):
header1 = ',\t ,de, zh-Hans;q=0.333,'
header2 = ', ,fr;q=0, \tes;q=1,'
result = AcceptLanguageValidHeader(header_value=header1) + \
AcceptLanguageValidHeader(header_value=header2)
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == header1 + ', ' + header2
def test___add___AcceptLanguageNoHeader(self):
valid_header_instance = AcceptLanguageValidHeader(header_value='es')
result = valid_header_instance + AcceptLanguageNoHeader()
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == valid_header_instance.header_value
assert result is not valid_header_instance
@pytest.mark.parametrize('header_value', ['', 'en_gb', ','])
def test___add___AcceptLanguageInvalidHeader(self, header_value):
valid_header_instance = AcceptLanguageValidHeader(
header_value='header',
)
result = valid_header_instance + AcceptLanguageInvalidHeader(
header_value=header_value,
)
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == valid_header_instance.header_value
assert result is not valid_header_instance
def test___bool__(self):
instance = AcceptLanguageValidHeader(header_value='valid-header')
returned = bool(instance)
assert returned is True
@pytest.mark.parametrize('header_value, offer', [
('*', 'da'),
('da', 'DA'),
('en', 'en-gb'),
('en-gb', 'en-gb'),
('en-gb', 'en'),
('en-gb', 'en_GB'),
])
def test___contains___in(self, header_value, offer):
instance = AcceptLanguageValidHeader(header_value=header_value)
assert offer in instance
@pytest.mark.parametrize('header_value, offer', [
('en-gb', 'en-us'),
('en-gb', 'fr-fr'),
('en-gb', 'fr'),
('en', 'fr-fr'),
])
def test___contains___not_in(self, header_value, offer):
instance = AcceptLanguageValidHeader(header_value=header_value)
assert offer not in instance
@pytest.mark.parametrize('header_value, expected_list', [
('fr;q=0, jp;q=0', []),
('en-gb, da', ['en-gb', 'da']),
('en-gb;q=0.5, da;q=0.5', ['en-gb', 'da']),
(
'de;q=0.8, de-DE-1996;q=0.5, de-Deva;q=0, de-Latn-DE',
['de-Latn-DE', 'de', 'de-DE-1996']
),
# __iter__ is currently a simple filter for the ranges in the header
# with non-0 qvalues, and does not attempt to account for the special
# meanings of q=0 and *:
('en-gb;q=0, *', ['*']),
('de, de;q=0', ['de']),
])
def test___iter__(self, header_value, expected_list):
instance = AcceptLanguageValidHeader(header_value=header_value)
assert list(instance) == expected_list
def test___radd___None(self):
right_operand = AcceptLanguageValidHeader(header_value='en')
result = None + right_operand
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
@pytest.mark.parametrize('left_operand', [
'',
[],
(),
{},
'en_gb',
['en_gb'],
('en_gb',),
{'en_gb': 1.0},
',',
[','],
(',',),
{',': 1.0},
])
def test___radd___invalid_value(self, left_operand):
right_operand = AcceptLanguageValidHeader(header_value='en')
result = left_operand + right_operand
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
@pytest.mark.parametrize('str_', ['', 'en_gb', ','])
def test___radd___other_type_with_invalid___str__(self, str_,):
right_operand = AcceptLanguageValidHeader(header_value='en')
class Other(object):
def __str__(self):
return str_
result = Other() + right_operand
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
@pytest.mark.parametrize('value, value_as_header', [
('en-gb;q=0.5, fr;q=0, es', 'en-gb;q=0.5, fr;q=0, es'),
([('en-gb', 0.5), ('fr', 0.0), 'es'], 'en-gb;q=0.5, fr;q=0, es'),
((('en-gb', 0.5), ('fr', 0.0), 'es'), 'en-gb;q=0.5, fr;q=0, es'),
({'en-gb': 0.5, 'fr': 0.0, 'es': 1.0}, 'es, en-gb;q=0.5, fr;q=0'),
])
def test___radd___valid_value(self, value, value_as_header):
right_operand = AcceptLanguageValidHeader(
header_value=',\t ,de, zh-Hans;q=0.333,',
)
result = value + right_operand
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == value_as_header + ', ' + \
right_operand.header_value
def test___radd___other_type_with_valid___str__(self):
right_operand = AcceptLanguageValidHeader(
header_value=',\t ,de, zh-Hans;q=0.333,',
)
class Other(object):
def __str__(self):
return 'en-gb;q=0.5, fr;q=0, es'
left_operand = Other()
result = left_operand + right_operand
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == str(left_operand) + ', ' + \
right_operand.header_value
def test___repr__(self):
instance = AcceptLanguageValidHeader(
header_value=',da;q=0.200,en-gb;q=0.300',
)
assert repr(instance) == \
"<AcceptLanguageValidHeader ('da;q=0.2, en-gb;q=0.3')>"
def test___str__(self):
header_value = \
', \t,de;q=0.000 \t, es;q=1.000, zh, jp;q=0.210 ,'
instance = AcceptLanguageValidHeader(header_value=header_value)
assert str(instance) == 'de;q=0, es, zh, jp;q=0.21'
@pytest.mark.parametrize(
'header_value, language_tags, expected_returned',
[
# Example from RFC 4647, Section 3.4
(
'de-de',
['de', 'de-DE-1996', 'de-Deva', 'de-Latn-DE'],
[('de-DE-1996', 1.0)]
),
# Empty `language_tags`
(
'a',
[],
[]
),
# No matches
(
'a, b',
['c', 'd'],
[]
),
# Several ranges and tags, no matches
(
'a-b;q=0.9, c-d;q=0.5, e-f',
('a', 'b', 'c', 'd', 'e', 'f'),
[]
),
# Case-insensitive match
(
'foO, BaR',
['foo', 'bar'],
[('foo', 1.0), ('bar', 1.0)]
),
# If a tag matches a non-'*' range with q=0, tag is filtered out
(
'b-c, a, b;q=0, d;q=0',
['b-c', 'a', 'b-c-d', 'd-e-f'],
[('a', 1.0)]
),
# Match if a range exactly equals a tag
(
'd-e-f',
['a-b-c', 'd-e-f'],
[('d-e-f', 1.0)]
),
# Match if a range exactly equals a prefix of the tag such that the
# first character following the prefix is '-'
(
'a-b-c-d, a-b-c-d-e, a-b-c-d-f-g-h',
['a-b-c-d-f-g'],
[('a-b-c-d-f-g', 1.0)]
),
# '*', when it is the only range in the header, matches everything
(
'*',
['a', 'b'],
[('a', 1.0), ('b', 1.0)]
),
# '*' range matches only tags not matched by any other range
(
'*;q=0.2, a;q=0.5, b',
['a-a', 'b-a', 'c-a', 'd-a'],
[('b-a', 1.0), ('a-a', 0.5), ('c-a', 0.2), ('d-a', 0.2)]
),
# '*' range without a qvalue gives a matched qvalue of 1.0
(
'a;q=0.5, b, *',
['a-a', 'b-a', 'c-a', 'd-a'],
[('b-a', 1.0), ('c-a', 1.0), ('d-a', 1.0), ('a-a', 0.5)]
),
# The qvalue for the '*' range works the same way as qvalues for
# non-'*' ranges.
(
'a;q=0.5, *;q=0.9',
# (meaning: prefer anything other than 'a', with 'a' as a
# fallback)
['a', 'b'],
[('b', 0.9), ('a', 0.5)]
),
# More than one range matching the same tag: range with the highest
# qvalue is matched
(
'a-b-c;q=0.7, a;q=0.9, a-b;q=0.8',
['a-b-c'],
[('a-b-c', 0.9)]
),
# More than one range with the same qvalue matching the same tag:
# the range in an earlier position in the header is matched
(
'a-b-c;q=0.7, a;q=0.9, b;q=0.9, a-b;q=0.9',
['a-b-c', 'b'],
[('a-b-c', 0.9), ('b', 0.9)]
),
# The returned list of tuples is sorted in descending order of qvalue
(
'a;q=0.7, b;q=0.3, c, d;q=0.5',
['d', 'c', 'b', 'a'],
[('c', 1.0), ('a', 0.7), ('d', 0.5), ('b', 0.3)]
),
# When qvalues are the same, the tag whose matched range appears
# earlier in the header comes first
(
'a, c, b',
['b', 'a', 'c'],
[('a', 1.0), ('c', 1.0), ('b', 1.0)]
),
# When many tags match the same range (so same qvalue and same
# matched range position in header), they are returned in order of
# their position in the `language_tags` argument
(
'a',
['a-b', 'a', 'a-b-c'],
[('a-b', 1.0), ('a', 1.0), ('a-b-c', 1.0)]
),
# When a non-'*' range appears in the header more than once, we use
# the first one for matching and ignore the others
(
'a;q=0.5, c;q=0.6, b;q=0.7, c;q=0.9',
['a', 'b', 'c'],
[('b', 0.7), ('c', 0.6), ('a', 0.5)]
),
(
'a, b, c;q=0.5, c;q=0',
['a-a', 'b-a', 'c-a'],
[('a-a', 1.0), ('b-a', 1.0), ('c-a', 0.5)]
),
(
'a;q=0.5, c;q=0.9, b;q=0.9, c;q=0.9',
['a', 'b', 'c'],
[('c', 0.9), ('b', 0.9), ('a', 0.5)]
),
# When the '*' range appears in the header more than once, we use
# the first one for matching and ignore the others
(
'a;q=0.5, *;q=0.6, b;q=0.7, *;q=0.9',
['a', 'b', 'c'],
[('b', 0.7), ('c', 0.6), ('a', 0.5)]
),
(
'a, b, *;q=0.5, *;q=0',
['a-a', 'b-a', 'c-a'],
[('a-a', 1.0), ('b-a', 1.0), ('c-a', 0.5)]
),
(
'a;q=0.5, *;q=0.9, b;q=0.9, *;q=0.9',
['a', 'b', 'c'],
[('c', 0.9), ('b', 0.9), ('a', 0.5)]
),
# Both '*' and non-'*' ranges appearing more than once
(
'a-b;q=0.5, c-d, *, a-b, c-d;q=0.3, *;q=0',
['a-b-c', 'c-d-e', 'e-f-g'],
[('c-d-e', 1.0), ('e-f-g', 1.0), ('a-b-c', 0.5)]
),
]
)
def test_basic_filtering(
self, header_value, language_tags, expected_returned,
):
instance = AcceptLanguageValidHeader(header_value=header_value)
returned = instance.basic_filtering(language_tags=language_tags)
assert returned == expected_returned
@pytest.mark.parametrize(
'header_value, offers, default_match, expected_returned', [
('bar, *;q=0', ['foo'], None, None),
('en-gb, sr-Cyrl', ['sr-Cyrl', 'en-gb'], None, 'sr-Cyrl'),
('en-gb, sr-Cyrl', ['en-gb', 'sr-Cyrl'], None, 'en-gb'),
('en-gb, sr-Cyrl', [('sr-Cyrl', 0.5), 'en-gb'], None, 'en-gb'),
(
'en-gb, sr-Cyrl', [('sr-Cyrl', 0.5), ('en-gb', 0.4)], None,
'sr-Cyrl',
),
('en-gb, sr-Cyrl;q=0.5', ['en-gb', 'sr-Cyrl'], None, 'en-gb'),
('en-gb;q=0.5, sr-Cyrl', ['en-gb', 'sr-Cyrl'], None, 'sr-Cyrl'),
(
'en-gb, sr-Cyrl;q=0.55, es;q=0.59', ['en-gb', 'sr-Cyrl'], None,
'en-gb',
),
(
'en-gb;q=0.5, sr-Cyrl;q=0.586, es-419;q=0.597',
['en-gb', 'es-419'], None, 'es-419',
),
]
)
def test_best_match(
self, header_value, offers, default_match, expected_returned,
):
instance = AcceptLanguageValidHeader(header_value=header_value)
returned = instance.best_match(
offers=offers, default_match=default_match,
)
assert returned == expected_returned
def test_lookup_default_tag_and_default_cannot_both_be_None(self):
instance = AcceptLanguageValidHeader(header_value='valid-header')
with pytest.raises(TypeError):
instance.lookup(
language_tags=['tag'],
default_range='language-range',
default_tag=None,
default=None,
)
def test_lookup_default_range_cannot_be_asterisk(self):
instance = AcceptLanguageValidHeader(header_value='valid-header')
with pytest.raises(ValueError):
instance.lookup(
language_tags=['tag'],
default_range='*',
default_tag='default-tag',
default=None,
)
@pytest.mark.parametrize(
(
'header_value, language_tags, default_range, default_tag, default'
', expected'
),
[
# Each language range in the header is considered in turn, in
# descending order of qvalue
(
'aA;q=0.3, Bb, cC;q=0.7',
['Aa', 'bB', 'Cc'],
None, 'default-tag', None,
'bB',
),
# For ranges with the same qvalue, position in header is the
# tiebreaker.
(
'bB-Cc;q=0.8, aA;q=0.9, Bb;q=0.9',
['bb', 'aa'],
None, 'default-tag', None,
'aa',
),
# Each language range represents the most specific tag that is an
# acceptable match. Examples from RFC 4647, section 3.4, first
# paragraph:
(
'de-ch',
['de-CH-1996', 'de-CH', 'de'],
None, 'default-tag', None,
'de-CH',
),
(
'de-ch',
['de-CH-1996', 'de'],
None, 'default-tag', None,
'de',
),
# The language range is progressively truncated from the end until
# a matching language tag is located. From the example of a Lookup
# Fallback Pattern in RFC 4647, section 3.4:
(
'zh-Hant-CN-x-private1-private2',
[
'zh-Hant-CN-x-private1-private2',
'zh-Hant-CN-x-private1',
'zh-Hant-CN-x',
'zh-Hant-CN',
'zh-Hant',
'zh',
],
None, 'default-tag', None,
'zh-Hant-CN-x-private1-private2',
),
(
'zh-Hant-CN-x-private1-private2',
[
'zh-Hant-CN-x-private1',
'zh-Hant-CN-x',
'zh-Hant-CN',
'zh-Hant',
'zh',
],
None, 'default-tag', None,
'zh-Hant-CN-x-private1',
),
(
'zh-Hant-CN-x-private1-private2',
[
'zh-Hant-CN-x',
'zh-Hant-CN',
'zh-Hant',
'zh',
],
None, 'default-tag', None,
'zh-Hant-CN',
),
(
'zh-Hant-CN-x-private1-private2',
[
'zh-Hant-CN',
'zh-Hant',
'zh',
],
None, 'default-tag', None,
'zh-Hant-CN',
),
(
'zh-Hant-CN-x-private1-private2',
[
'zh-Hant',
'zh',
],
None, 'default-tag', None,
'zh-Hant',
),
(
'zh-Hant-CN-x-private1-private2',
['zh'],
None, 'default-tag', None,
'zh',
),
(
'zh-Hant-CN-x-private1-private2',
['some-other-tag-1', 'some-other-tag-2'],
None, 'default-tag', None,
'default-tag',
),
# Further tests to check that single-letter or -digit subtags are
# removed at the same time as their closest trailing subtag:
(
'AA-T-subtag',
['Aa-t', 'aA'],
None, 'default-tag', None,
'aA',
),
(
'AA-1-subtag',
['aa-1', 'aA'],
None, 'default-tag', None,
'aA',
),
(
'Aa-P-subtag-8-subtag',
['Aa-p-subtag-8', 'Aa-p', 'aA'],
None, 'default-tag', None,
'aA',
),
(
'aA-3-subTag-C-subtag',
['aA-3-subtag-c', 'aA-3', 'aA'],
None, 'default-tag', None,
'aA',
),
# Test that single-letter or -digit subtag in first position works
# as expected
(
'T-subtag',
['t-SubTag', 'another'],
None, 'default-tag', None,
't-SubTag',
),
(
'T-subtag',
['another'],
None, 'default-tag', None,
'default-tag',
),
# If the language range "*" is followed by other language ranges,
# it is skipped.
(
'*, Aa-aA-AA',
['bb', 'aA'],
None, 'default-tag', None,
'aA',
),
# If the language range "*" is the only one in the header, lookup
# proceeds to the default arguments.
(
'*',
['bb', 'aa'],
None, 'default-tag', None,
'default-tag',
),
# If no other language range follows the "*" in the header, lookup
# proceeds to the default arguments.
(
'dd, cc, *',
['bb', 'aa'],
None, 'default-tag', None,
'default-tag',
),
# If a non-'*' range has q=0, any tag that matches the range
# exactly (without subtag truncation) is not acceptable.
(
'aa, bB-Cc-DD;q=0, bB-Cc, cc',
['bb', 'bb-Cc-DD', 'bb-cC-dd', 'Bb-cc', 'bb-cC-dd'],
None, 'default-tag', None,
'Bb-cc',
),
# ;q=0 and ;q={not 0} both in header: q=0 takes precedence and
# makes the exact match not acceptable, but the q={not 0} means
# that tags can still match after subtag truncation.
(
'aa, bB-Cc-DD;q=0.9, cc, Bb-cC-dD;q=0',
['bb', 'Bb-Cc', 'Bb-cC-dD'],
None, 'default-tag', None,
'Bb-Cc',
),
# If none of the ranges in the header match any of the language
# tags, and the `default_range` argument is not None and does not
# match any q=0 range in the header, we search through it by
# progressively truncating from the end, as we do with the ranges
# in the header. Example from RFC 4647, section 3.4.1:
(
'fr-FR, zh-Hant',
[
'fr-FR',
'fr',
'zh-Hant',
'zh',
'ja-JP',
'ja',
],
'ja-JP', 'default-tag', None,
'fr-FR',
),
(
'fr-FR, zh-Hant',
[
'fr',
'zh-Hant',
'zh',
'ja-JP',
'ja',
],
'ja-JP', 'default-tag', None,
'fr',
),
(
'fr-FR, zh-Hant',
[
'zh-Hant',
'zh',
'ja-JP',
'ja',
],
'ja-JP', 'default-tag', None,
'zh-Hant',
),
(
'fr-FR, zh-Hant',
[
'zh',
'ja-JP',
'ja',
],
'ja-JP', 'default-tag', None,
'zh',
),
(
'fr-FR, zh-Hant',
[
'ja-JP',
'ja',
],
'ja-JP', 'default-tag', None,
'ja-JP',
),
(
'fr-FR, zh-Hant',
['ja'],
'ja-JP', 'default-tag', None,
'ja',
),
(
'fr-FR, zh-Hant',
['some-other-tag-1', 'some-other-tag-2'],
'ja-JP', 'default-tag', None,
'default-tag',
),
# If none of the ranges in the header match the language tags, the
# `default_range` argument is not None, and there is a '*;q=0'
# range in the header, then the `default_range` and its substrings
# from subtag truncation are not acceptable.
(
'aa-bb, cc-dd, *;q=0',
['ee-ff', 'ee'],
'ee-ff', None, 'default',
'default',
),
# If none of the ranges in the header match the language tags, the
# `default_range` argument is not None, and the argument exactly
# matches a non-'*' range in the header with q=0 (without fallback
# subtag truncation), then the `default_range` itself is not
# acceptable...
(
'aa-bb, cc-dd, eE-Ff;q=0',
['Ee-fF'],
'EE-FF', 'default-tag', None,
'default-tag',
),
# ...but it should still be searched with subtag truncation,
# because its substrings other than itself are still acceptable:
(
'aa-bb, cc-dd, eE-Ff-Gg;q=0',
['Ee', 'Ee-fF-gG', 'Ee-fF'],
'EE-FF-GG', 'default-tag', None,
'Ee-fF',
),
(
'aa-bb, cc-dd, eE-Ff-Gg;q=0',
['Ee-fF-gG', 'Ee'],
'EE-FF-GG', 'default-tag', None,
'Ee',
),
# If `default_range` only has one subtag, then no subtag truncation
# is possible, and we proceed to `default-tag`:
(
'aa-bb, cc-dd, eE;q=0',
['Ee'],
'EE', 'default-tag', None,
'default-tag',
),
# If the `default_range` argument would only match a non-'*' range
# in the header with q=0 exactly if the `default_range` had subtags
# from the end truncated, then it is acceptable, and we attempt to
# match it with the language tags using subtag truncation. However,
# the tag equivalent of the range with q=0 would be considered not
# acceptable and ruled out, if we reach it during the subtag
# truncation search.
(
'aa-bb, cc-dd, eE-Ff;q=0',
['Ee-fF', 'Ee-fF-33', 'ee'],
'EE-FF-33', 'default-tag', None,
'Ee-fF-33',
),
(
'aa-bb, cc-dd, eE-Ff;q=0',
['Ee-fF', 'eE'],
'EE-FF-33', 'default-tag', None,
'eE',
),
# If none of the ranges in the header match, the `default_range`
# argument is None or does not match, and the `default_tag`
# argument is not None and does not match any range in the header
# with q=0, then the `default_tag` argument is returned.
(
'aa-bb, cc-dd',
['ee-ff', 'ee'],
None, 'default-tag', None,
'default-tag',
),
(
'aa-bb, cc-dd',
['ee-ff', 'ee'],
'gg-hh', 'default-tag', None,
'default-tag',
),
# If none of the ranges in the header match, the `default_range`
# argument is None or does not match, the `default_tag` argument is
# not None, and there is a '*' range in the header with q=0, then
# the `default_tag` argument is not acceptable.
(
'aa-bb, cc-dd, *;q=0',
['ee-ff', 'ee'],
'gg-hh', 'ii-jj', 'default',
'default',
),
# If none of the ranges in the header match, the `default_range`
# argument is None or does not match, the `default_tag` argument is
# not None and matches a non-'*' range in the header with q=0
# exactly, then the `default_tag` argument is not acceptable.
(
'aa-bb, cc-dd, iI-jJ;q=0',
['ee-ff', 'ee'],
'gg-hh', 'Ii-Jj', 'default',
'default',
),
# If none of the ranges in the header match, the `default_range`
# argument is None or does not match, and the `default_tag`
# argument is None, then we proceed to the `default` argument.
(
'aa-bb, cc-dd',
['ee-ff', 'ee'],
None, None, 'default',
'default',
),
(
'aa-bb, cc-dd',
['ee-ff', 'ee'],
'gg-hh', None, 'default',
'default',
),
# If we fall back to the `default` argument, and it is not a
# callable, the argument itself is returned.
(
'aa',
['bb'],
None, None, 0,
0,
),
(
'Aa, cC;q=0',
['bb'],
'aA-Cc', 'Cc', ['non-callable object'],
['non-callable object'],
),
# If we fall back to the `default` argument, and it is a callable,
# it is called, and the callable's return value is returned by the
# method.
(
'aa',
['bb'],
None, None, lambda: 'callable called',
'callable called',
),
(
'Aa, cc;q=0',
['bb'],
'aA-cC', 'cc', lambda: 'callable called',
'callable called',
),
# Even if the 'default' argument is a str that matches a q=0 range
# in the header, it is still returned.
(
'aa, *;q=0',
['bb'],
None, None, 'cc',
'cc',
),
(
'aa, cc;q=0',
['bb'],
None, None, 'cc',
'cc',
),
# If the `default_tag` argument is not acceptable because of a q=0
# range in the header, and the `default` argument is None, then
# None is returned.
(
'aa, Bb;q=0',
['cc'],
None, 'bB', None,
None,
),
(
'aa, *;q=0',
['cc'],
None, 'bb', None,
None,
),
# Test that method works with empty `language_tags`:
(
'range',
[],
None, 'default-tag', None,
'default-tag',
),
# Test that method works with empty `default_range`:
(
'range',
[],
'', 'default-tag', None,
'default-tag',
),
(
'range',
['tag'],
'', 'default-tag', None,
'default-tag',
),
# Test that method works with empty `default_tag`:
(
'range',
[],
'', '', None,
'',
),
(
'range',
['tag'],
'default-range', '', None,
'',
),
]
)
def test_lookup(
self, header_value, language_tags, default_range, default_tag,
default, expected,
):
instance = AcceptLanguageValidHeader(header_value=header_value)
returned = instance.lookup(
language_tags=language_tags,
default_range=default_range,
default_tag=default_tag,
default=default,
)
assert returned == expected
@pytest.mark.parametrize('header_value, offer, expected_returned', [
('en-gb', 'en-gb', 1),
('en-gb;q=0.5', 'en-gb', 0.5),
('en-gb', 'sr-Cyrl', None),
])
def test_quality(self, header_value, offer, expected_returned):
instance = AcceptLanguageValidHeader(header_value=header_value)
returned = instance.quality(offer=offer)
assert returned == expected_returned
class TestAcceptLanguageNoHeader(object):
def test___init__(self):
instance = AcceptLanguageNoHeader()
assert instance.header_value is None
assert instance.parsed is None
assert instance._parsed_nonzero is None
assert isinstance(instance, AcceptLanguage)
def test___add___None(self):
instance = AcceptLanguageNoHeader()
result = instance + None
assert isinstance(result, AcceptLanguageNoHeader)
assert result is not instance
@pytest.mark.parametrize('right_operand', [
'',
[],
(),
{},
'en_gb',
['en_gb'],
('en_gb',),
{'en_gb': 1.0},
])
def test___add___invalid_value(self, right_operand):
left_operand = AcceptLanguageNoHeader()
result = left_operand + right_operand
assert isinstance(result, AcceptLanguageNoHeader)
assert result is not left_operand
@pytest.mark.parametrize('str_', ['', 'en_gb'])
def test___add___other_type_with_invalid___str__(self, str_,):
left_operand = AcceptLanguageNoHeader()
class Other(object):
def __str__(self):
return str_
result = left_operand + Other()
assert isinstance(result, AcceptLanguageNoHeader)
assert result is not left_operand
@pytest.mark.parametrize('value, value_as_header', [
('en-gb;q=0.5, fr;q=0, es', 'en-gb;q=0.5, fr;q=0, es'),
([('en-gb', 0.5), ('fr', 0.0), 'es'], 'en-gb;q=0.5, fr;q=0, es'),
((('en-gb', 0.5), ('fr', 0.0), 'es'), 'en-gb;q=0.5, fr;q=0, es'),
({'en-gb': 0.5, 'fr': 0.0, 'es': 1.0}, 'es, en-gb;q=0.5, fr;q=0'),
])
def test___add___valid_value(self, value, value_as_header):
result = AcceptLanguageNoHeader() + value
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == value_as_header
def test___add___other_type_with_valid___str__(self):
class Other(object):
def __str__(self):
return 'en-gb;q=0.5, fr;q=0, es'
right_operand = Other()
result = AcceptLanguageNoHeader() + right_operand
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == str(right_operand)
def test___add___AcceptLanguageValidHeader(self):
right_operand = AcceptLanguageValidHeader(
header_value=', ,fr;q=0, \tes;q=1,',
)
result = AcceptLanguageNoHeader() + right_operand
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == right_operand.header_value
def test___add___AcceptLanguageNoHeader(self):
left_operand = AcceptLanguageNoHeader()
right_operand = AcceptLanguageNoHeader()
result = left_operand + right_operand
assert isinstance(result, AcceptLanguageNoHeader)
assert result is not left_operand
assert result is not right_operand
@pytest.mark.parametrize('invalid_header_value', ['', 'en_gb'])
def test___add___AcceptLanguageInvalidHeader(self, invalid_header_value):
left_operand = AcceptLanguageNoHeader()
result = left_operand + AcceptLanguageInvalidHeader(
header_value=invalid_header_value,
)
assert isinstance(result, AcceptLanguageNoHeader)
assert result is not left_operand
def test___bool__(self):
instance = AcceptLanguageNoHeader()
returned = bool(instance)
assert returned is False
def test___contains__(self):
instance = AcceptLanguageNoHeader()
returned = ('any-tag' in instance)
assert returned is True
def test___iter__(self):
instance = AcceptLanguageNoHeader()
returned = list(instance)
assert returned == []
def test___radd___None(self):
right_operand = AcceptLanguageNoHeader()
result = None + right_operand
assert isinstance(result, AcceptLanguageNoHeader)
assert result is not right_operand
@pytest.mark.parametrize('left_operand', [
'',
[],
(),
{},
'en_gb',
['en_gb'],
('en_gb',),
{'en_gb': 1.0},
])
def test___radd___invalid_value(self, left_operand):
right_operand = AcceptLanguageNoHeader()
result = left_operand + right_operand
assert isinstance(result, AcceptLanguageNoHeader)
assert result is not right_operand
@pytest.mark.parametrize('str_', ['', 'en_gb', ','])
def test___radd___other_type_with_invalid___str__(self, str_,):
right_operand = AcceptLanguageNoHeader()
class Other(object):
def __str__(self):
return str_
result = Other() + right_operand
assert isinstance(result, AcceptLanguageNoHeader)
assert result is not right_operand
@pytest.mark.parametrize('value, value_as_header', [
('en-gb;q=0.5, fr;q=0, es', 'en-gb;q=0.5, fr;q=0, es'),
([('en-gb', 0.5), ('fr', 0.0), 'es'], 'en-gb;q=0.5, fr;q=0, es'),
((('en-gb', 0.5), ('fr', 0.0), 'es'), 'en-gb;q=0.5, fr;q=0, es'),
({'en-gb': 0.5, 'fr': 0.0, 'es': 1.0}, 'es, en-gb;q=0.5, fr;q=0'),
])
def test___radd___valid_value(self, value, value_as_header):
result = value + AcceptLanguageNoHeader()
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == value_as_header
def test___radd___other_type_with_valid___str__(self):
class Other(object):
def __str__(self):
return 'en-gb;q=0.5, fr;q=0, es'
left_operand = Other()
result = left_operand + AcceptLanguageNoHeader()
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == str(left_operand)
def test___repr__(self):
instance = AcceptLanguageNoHeader()
assert repr(instance) == '<AcceptLanguageNoHeader>'
def test___str__(self):
instance = AcceptLanguageNoHeader()
assert str(instance) == '<no header in request>'
def test_basic_filtering(self):
instance = AcceptLanguageNoHeader()
returned = instance.basic_filtering(language_tags=['tag1', 'tag2'])
assert returned == []
@pytest.mark.parametrize('offers, default_match, expected_returned', [
(['foo', 'bar'], None, 'foo'),
([('foo', 1), ('bar', 0.5)], None, 'foo'),
([('foo', 0.5), ('bar', 1)], None, 'bar'),
([('foo', 0.5), 'bar'], None, 'bar'),
([('foo', 0.5), 'bar'], object(), 'bar'),
([], 'fallback', 'fallback'),
])
def test_best_match(self, offers, default_match, expected_returned):
instance = AcceptLanguageNoHeader()
returned = instance.best_match(
offers=offers, default_match=default_match,
)
assert returned == expected_returned
def test_lookup_default_tag_and_default_cannot_both_be_None(self):
instance = AcceptLanguageNoHeader()
with pytest.raises(TypeError):
instance.lookup(default_tag=None, default=None)
@pytest.mark.parametrize('default_tag, default, expected', [
# If `default_tag` is not None, it is returned.
('default-tag', 'default', 'default-tag'),
# If `default_tag` is None, we proceed to the `default` argument. If
# `default` is not a callable, the argument itself is returned.
(None, 0, 0),
# If `default` is a callable, it is called, and the callable's return
# value is returned by the method.
(None, lambda: 'callable called', 'callable called'),
])
def test_lookup(self, default_tag, default, expected):
instance = AcceptLanguageNoHeader()
returned = instance.lookup(
default_tag=default_tag,
default=default,
)
assert returned == expected
def test_quality(self):
instance = AcceptLanguageNoHeader()
returned = instance.quality(offer='any-tag')
assert returned == 1.0
class TestAcceptLanguageInvalidHeader(object):
def test___init__(self):
header_value = 'invalid header'
instance = AcceptLanguageInvalidHeader(header_value=header_value)
assert instance.header_value == header_value
assert instance.parsed is None
assert instance._parsed_nonzero is None
assert isinstance(instance, AcceptLanguage)
def test___add___None(self):
instance = AcceptLanguageInvalidHeader(header_value='')
result = instance + None
assert isinstance(result, AcceptLanguageNoHeader)
@pytest.mark.parametrize('right_operand', [
'',
[],
(),
{},
'en_gb',
['en_gb'],
('en_gb',),
{'en_gb': 1.0},
])
def test___add___invalid_value(self, right_operand):
result = AcceptLanguageInvalidHeader(header_value='') + right_operand
assert isinstance(result, AcceptLanguageNoHeader)
@pytest.mark.parametrize('str_', ['', 'en_gb'])
def test___add___other_type_with_invalid___str__(self, str_):
class Other(object):
def __str__(self):
return str_
result = AcceptLanguageInvalidHeader(header_value='') + Other()
assert isinstance(result, AcceptLanguageNoHeader)
@pytest.mark.parametrize('value', [
'en',
['en'],
('en',),
{'en': 1.0},
])
def test___add___valid_header_value(self, value):
result = AcceptLanguageInvalidHeader(header_value='') + value
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == 'en'
def test___add___other_type_valid_header_value(self):
class Other(object):
def __str__(self):
return 'en'
result = AcceptLanguageInvalidHeader(header_value='') + Other()
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == 'en'
def test___add___AcceptLanguageValidHeader(self):
right_operand = AcceptLanguageValidHeader(header_value='en')
result = AcceptLanguageInvalidHeader(header_value='') + right_operand
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == right_operand.header_value
assert result is not right_operand
def test___add___AcceptLanguageNoHeader(self):
right_operand = AcceptLanguageNoHeader()
result = AcceptLanguageInvalidHeader(header_value='') + right_operand
assert isinstance(result, AcceptLanguageNoHeader)
assert result is not right_operand
def test___add___AcceptLanguageInvalidHeader(self):
result = AcceptLanguageInvalidHeader(header_value='') + \
AcceptLanguageInvalidHeader(header_value='')
assert isinstance(result, AcceptLanguageNoHeader)
def test___bool__(self):
instance = AcceptLanguageInvalidHeader(header_value='')
returned = bool(instance)
assert returned is False
def test___contains__(self):
instance = AcceptLanguageInvalidHeader(header_value='')
returned = ('any-tag' in instance)
assert returned is True
def test___iter__(self):
instance = AcceptLanguageInvalidHeader(header_value='')
returned = list(instance)
assert returned == []
def test___radd___None(self):
instance = AcceptLanguageInvalidHeader(header_value='')
result = None + instance
assert isinstance(result, AcceptLanguageNoHeader)
@pytest.mark.parametrize('left_operand', [
'',
[],
(),
{},
'en_gb',
['en_gb'],
('en_gb',),
{'en_gb': 1.0},
])
def test___radd___invalid_value(self, left_operand):
result = left_operand + AcceptLanguageInvalidHeader(header_value='')
assert isinstance(result, AcceptLanguageNoHeader)
@pytest.mark.parametrize('str_', ['', 'en_gb'])
def test___radd___other_type_with_invalid___str__(self, str_):
class Other(object):
def __str__(self):
return str_
result = Other() + AcceptLanguageInvalidHeader(header_value='')
assert isinstance(result, AcceptLanguageNoHeader)
@pytest.mark.parametrize('value', [
'en',
['en'],
('en',),
{'en': 1.0},
])
def test___radd___valid_header_value(self, value):
result = value + AcceptLanguageInvalidHeader(header_value='')
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == 'en'
def test___radd___other_type_valid_header_value(self):
class Other(object):
def __str__(self):
return 'en'
result = Other() + AcceptLanguageInvalidHeader(header_value='')
assert isinstance(result, AcceptLanguageValidHeader)
assert result.header_value == 'en'
def test___repr__(self):
instance = AcceptLanguageInvalidHeader(header_value='\x00')
assert repr(instance) == '<AcceptLanguageInvalidHeader>'
def test___str__(self):
instance = AcceptLanguageInvalidHeader(header_value="invalid header")
assert str(instance) == '<invalid header value>'
def test_basic_filtering(self):
instance = AcceptLanguageInvalidHeader(header_value='')
returned = instance.basic_filtering(language_tags=['tag1', 'tag2'])
assert returned == []
@pytest.mark.parametrize('offers, default_match, expected_returned', [
(['foo', 'bar'], None, 'foo'),
([('foo', 1), ('bar', 0.5)], None, 'foo'),
([('foo', 0.5), ('bar', 1)], None, 'bar'),
([('foo', 0.5), 'bar'], None, 'bar'),
([('foo', 0.5), 'bar'], object(), 'bar'),
([], 'fallback', 'fallback'),
])
def test_best_match(self, offers, default_match, expected_returned):
instance = AcceptLanguageInvalidHeader(header_value='')
returned = instance.best_match(
offers=offers, default_match=default_match,
)
assert returned == expected_returned
def test_lookup_default_tag_and_default_cannot_both_be_None(self):
instance = AcceptLanguageInvalidHeader(header_value='')
with pytest.raises(TypeError):
instance.lookup(default_tag=None, default=None)
@pytest.mark.parametrize('default_tag, default, expected', [
# If `default_tag` is not None, it is returned.
('default-tag', 'default', 'default-tag'),
# If `default_tag` is None, we proceed to the `default` argument. If
# `default` is not a callable, the argument itself is returned.
(None, 0, 0),
# If `default` is a callable, it is called, and the callable's return
# value is returned by the method.
(None, lambda: 'callable called', 'callable called'),
])
def test_lookup(self, default_tag, default, expected):
instance = AcceptLanguageInvalidHeader(header_value='')
returned = instance.lookup(
default_tag=default_tag,
default=default,
)
assert returned == expected
def test_quality(self):
instance = AcceptLanguageInvalidHeader(header_value='')
returned = instance.quality(offer='any-tag')
assert returned == 1.0
class TestCreateAcceptLanguageHeader(object):
def test_header_value_is_None(self):
header_value = None
returned = create_accept_language_header(header_value=header_value)
assert isinstance(returned, AcceptLanguageNoHeader)
assert returned.header_value == header_value
def test_header_value_is_valid(self):
header_value = 'es, ja'
returned = create_accept_language_header(header_value=header_value)
assert isinstance(returned, AcceptLanguageValidHeader)
assert returned.header_value == header_value
@pytest.mark.parametrize('header_value', ['', 'en_gb'])
def test_header_value_is_invalid(self, header_value):
returned = create_accept_language_header(header_value=header_value)
assert isinstance(returned, AcceptLanguageInvalidHeader)
assert returned.header_value == header_value
class TestAcceptLanguageProperty(object):
def test_fget_header_is_None(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_LANGUAGE': None})
property_ = accept_language_property()
returned = property_.fget(request=request)
assert isinstance(returned, AcceptLanguageNoHeader)
def test_fget_header_is_valid(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_LANGUAGE': 'es'})
property_ = accept_language_property()
returned = property_.fget(request=request)
assert isinstance(returned, AcceptLanguageValidHeader)
def test_fget_header_is_invalid(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_LANGUAGE': 'en_gb'})
property_ = accept_language_property()
returned = property_.fget(request=request)
assert isinstance(returned, AcceptLanguageInvalidHeader)
def test_fset_value_is_None(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_LANGUAGE': 'es'})
property_ = accept_language_property()
property_.fset(request=request, value=None)
assert isinstance(request.accept_language, AcceptLanguageNoHeader)
assert 'HTTP_ACCEPT_LANGUAGE' not in request.environ
def test_fset_value_is_invalid(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_LANGUAGE': 'es'})
property_ = accept_language_property()
property_.fset(request=request, value='en_GB')
assert isinstance(request.accept_language, AcceptLanguageInvalidHeader)
assert request.environ['HTTP_ACCEPT_LANGUAGE'] == 'en_GB'
def test_fset_value_is_valid(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_LANGUAGE': 'es'})
property_ = accept_language_property()
property_.fset(request=request, value='en-GB')
assert isinstance(request.accept_language, AcceptLanguageValidHeader)
assert request.environ['HTTP_ACCEPT_LANGUAGE'] == 'en-GB'
@pytest.mark.parametrize('value, value_as_header', [
('en-gb;q=0.5, fr;q=0, es', 'en-gb;q=0.5, fr;q=0, es'),
([('en-gb', 0.5), ('fr', 0.0), 'es'], 'en-gb;q=0.5, fr;q=0, es'),
((('en-gb', 0.5), ('fr', 0.0), 'es'), 'en-gb;q=0.5, fr;q=0, es'),
({'en-gb': 0.5, 'fr': 0.0, 'es': 1.0}, 'es, en-gb;q=0.5, fr;q=0'),
])
def test_fset_value_types(self, value, value_as_header):
request = Request.blank('/', environ={'HTTP_ACCEPT_LANGUAGE': ''})
property_ = accept_language_property()
property_.fset(request=request, value=value)
assert isinstance(request.accept_language, AcceptLanguageValidHeader)
assert request.environ['HTTP_ACCEPT_LANGUAGE'] == value_as_header
def test_fset_other_type_with_valid___str__(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_LANGUAGE': ''})
property_ = accept_language_property()
class Other(object):
def __str__(self):
return 'en-gb;q=0.5, fr;q=0, es'
value = Other()
property_.fset(request=request, value=value)
assert isinstance(request.accept_language, AcceptLanguageValidHeader)
assert request.environ['HTTP_ACCEPT_LANGUAGE'] == str(value)
def test_fset_AcceptLanguageNoHeader(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_LANGUAGE': 'en'})
property_ = accept_language_property()
header = AcceptLanguageNoHeader()
property_.fset(request=request, value=header)
assert isinstance(request.accept_language, AcceptLanguageNoHeader)
assert 'HTTP_ACCEPT_LANGUAGE' not in request.environ
def test_fset_AcceptLanguageValidHeader(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_LANGUAGE': ''})
property_ = accept_language_property()
header = AcceptLanguageValidHeader('es')
property_.fset(request=request, value=header)
assert isinstance(request.accept_language, AcceptLanguageValidHeader)
assert request.environ['HTTP_ACCEPT_LANGUAGE'] == header.header_value
def test_fset_AcceptLanguageInvalidHeader(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_LANGUAGE': ''})
property_ = accept_language_property()
header = AcceptLanguageInvalidHeader('en_gb')
property_.fset(request=request, value=header)
assert isinstance(request.accept_language, AcceptLanguageInvalidHeader)
assert request.environ['HTTP_ACCEPT_LANGUAGE'] == header.header_value
def test_fdel_header_key_in_environ(self):
request = Request.blank('/', environ={'HTTP_ACCEPT_LANGUAGE': 'es'})
property_ = accept_language_property()
property_.fdel(request=request)
assert isinstance(request.accept_language, AcceptLanguageNoHeader)
assert 'HTTP_ACCEPT_LANGUAGE' not in request.environ
def test_fdel_header_key_not_in_environ(self):
request = Request.blank('/')
property_ = accept_language_property()
property_.fdel(request=request)
assert isinstance(request.accept_language, AcceptLanguageNoHeader)
assert 'HTTP_ACCEPT_LANGUAGE' not in request.environ
# Deprecated tests:
def test_mime_init():
with warnings.catch_warnings(record=True) as warning:
warnings.simplefilter("always")
MIMEAccept('image/jpg')
assert len(warning) == 1