blob: 736a68267931b4feac38ab43657c20f8f0f0d0f8 [file] [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
IGNORE_BEST_MATCH = "ignore:.*best_match.*"
IGNORE_QUALITY = "ignore:.*quality.*"
IGNORE_CONTAINS = "ignore:.*__contains__.*"
IGNORE_ITER = "ignore:.*__iter__.*"
IGNORE_MIMEACCEPT = "ignore:.*MIMEAccept.*"
class Test_ItemNWeightRe:
@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:
@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:
@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
@pytest.mark.parametrize(
"offer, expected_return, expected_str",
[
["text/html", ("text", "html", ()), "text/html"],
[
"text/html;charset=utf8",
("text", "html", (("charset", "utf8"),)),
"text/html;charset=utf8",
],
[
"text/html;charset=utf8;x-version=1",
("text", "html", (("charset", "utf8"), ("x-version", "1"))),
"text/html;charset=utf8;x-version=1",
],
[
"text/HtMl;cHaRseT=UtF-8;X-Version=1",
("text", "html", (("charset", "UtF-8"), ("x-version", "1"))),
"text/html;charset=UtF-8;x-version=1",
],
],
)
def test_parse_offer__valid(self, offer, expected_return, expected_str):
result = Accept.parse_offer(offer)
assert result == expected_return
assert str(result) == expected_str
assert result is Accept.parse_offer(result)
@pytest.mark.parametrize(
"offer",
[
"",
"foo",
"foo/bar/baz",
"*/plain",
"*/plain;charset=utf8",
"*/plain;charset=utf8;x-version=1",
"*/*;charset=utf8",
"text/*;charset=utf8",
"text/*",
"*/*",
],
)
def test_parse_offer__invalid(self, offer):
with pytest.raises(ValueError):
Accept.parse_offer(offer)
class TestAcceptValidHeader:
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:
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:
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:
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
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
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)
@pytest.mark.filterwarnings(IGNORE_ITER)
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:
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:
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:
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, expected_returned",
[
(["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", "foo"], [("text/html", 1.0)]),
],
)
def test_acceptable_offers__invalid_offers(self, offers, expected_returned):
assert (
AcceptValidHeader("text/html").acceptable_offers(offers=offers)
== expected_returned
)
@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),
],
),
(
"text/*;q=0.3, text/html;q=0.5, text/html;level=1;q=0.7",
["text/*", "*/*", "text/html", "image/*"],
[("text/html", 0.5)],
),
(
"text/html;level=1;q=0.7",
["text/*", "*/*", "text/html", "text/html;level=1", "image/*"],
[("text/html;level=1", 0.7)],
),
("*/*", ["text/*"], []),
("", ["text/*", "*/*", "text/html", "text/html;level=1", "image/*"], []),
],
)
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_acceptable_offers_uses_AcceptOffer_objects(self):
from webob.acceptparse import AcceptOffer
offer = AcceptOffer("text", "html", (("level", "1"),))
instance = AcceptValidHeader(header_value="text/*;q=0.5")
result = instance.acceptable_offers([offer])
assert result == [(offer, 0.5)]
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
def test_best_match_json(self):
accept = AcceptValidHeader("text/html, */*; q=0.2")
assert accept.best_match(["application/json"]) == "application/json"
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
)
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
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")
@pytest.mark.filterwarnings(IGNORE_QUALITY)
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
@pytest.mark.filterwarnings(IGNORE_QUALITY)
def test_quality_not_found(self):
accept = AcceptValidHeader("text/html")
assert accept.quality("foo/bar") is None
class TestAcceptNoHeader:
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:
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:
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:
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
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
def test___contains__(self):
instance = AcceptNoHeader()
returned = "type/subtype" in instance
assert returned is True
@pytest.mark.filterwarnings(IGNORE_ITER)
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:
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:
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:
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
@pytest.mark.parametrize(
"offers, expected_returned",
[
(["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", "foo"], [("text/html", 1.0)]),
],
)
def test_acceptable_offers__invalid_offers(self, offers, expected_returned):
assert AcceptNoHeader().acceptable_offers(offers=offers) == expected_returned
def test_acceptable_offers__valid_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)]
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_QUALITY)
def test_quality(self):
instance = AcceptNoHeader()
returned = instance.quality(offer="type/subtype")
assert returned == 1.0
class TestAcceptInvalidHeader:
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:
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:
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:
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
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
def test___contains__(self):
instance = AcceptInvalidHeader(header_value=", ")
returned = "type/subtype" in instance
assert returned is True
@pytest.mark.filterwarnings(IGNORE_ITER)
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:
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:
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:
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
@pytest.mark.parametrize(
"offers, expected_returned",
[
(["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", "foo"], [("text/html", 1.0)]),
],
)
def test_acceptable_offers__invalid_offers(self, offers, expected_returned):
assert (
AcceptInvalidHeader(header_value=", ").acceptable_offers(offers=offers)
== expected_returned
)
def test_acceptable_offers__valid_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)]
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_QUALITY)
def test_quality(self):
instance = AcceptInvalidHeader(header_value=", ")
returned = instance.quality(offer="type/subtype")
assert returned == 1.0
class TestCreateAcceptHeader:
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
returned2 = create_accept_header(returned)
assert returned2 is not returned
assert returned2._header_value == returned._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
returned2 = create_accept_header(returned)
assert returned2 is not returned
assert returned2._header_value == returned._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
returned2 = create_accept_header(returned)
assert returned2 is not returned
assert returned2._header_value == returned._header_value
class TestAcceptProperty:
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:
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:
@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:
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:
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:
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
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
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")
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
def test___contains___not(self):
accept = AcceptCharsetValidHeader("utf-8")
assert "utf-7" not in accept
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
def test___contains___zero_quality(self):
assert "foo" not in AcceptCharsetValidHeader("*;q=0")
@pytest.mark.filterwarnings(IGNORE_ITER)
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:
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:
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
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
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")
@pytest.mark.filterwarnings(IGNORE_QUALITY)
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
@pytest.mark.filterwarnings(IGNORE_QUALITY)
def test_quality_not_found(self):
accept = AcceptCharsetValidHeader("utf-8")
assert accept.quality("iso-8859-5") is None
class TestAcceptCharsetNoHeader:
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:
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:
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
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
def test___contains__(self):
instance = AcceptCharsetNoHeader()
returned = "char-set" in instance
assert returned is True
@pytest.mark.filterwarnings(IGNORE_ITER)
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:
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:
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)]
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_QUALITY)
def test_quality(self):
instance = AcceptCharsetNoHeader()
returned = instance.quality(offer="char-set")
assert returned == 1.0
class TestAcceptCharsetInvalidHeader:
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:
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:
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
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
def test___contains__(self):
instance = AcceptCharsetInvalidHeader(header_value="")
returned = "char-set" in instance
assert returned is True
@pytest.mark.filterwarnings(IGNORE_ITER)
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:
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:
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)]
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_QUALITY)
def test_quality(self):
instance = AcceptCharsetInvalidHeader(header_value="")
returned = instance.quality(offer="char-set")
assert returned == 1.0
class TestCreateAcceptCharsetHeader:
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
returned2 = create_accept_charset_header(returned)
assert returned2 is not returned
assert returned2._header_value == returned._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
returned2 = create_accept_charset_header(returned)
assert returned2 is not returned
assert returned2._header_value == returned._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
returned2 = create_accept_charset_header(returned)
assert returned2 is not returned
assert returned2._header_value == returned._header_value
class TestAcceptCharsetProperty:
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:
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:
@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:
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:
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:
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:
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
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
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)
@pytest.mark.filterwarnings(IGNORE_ITER)
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:
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:
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:
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
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
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")
@pytest.mark.filterwarnings(IGNORE_QUALITY)
def test_quality(self):
accept = AcceptEncodingValidHeader("gzip")
assert accept.quality("gzip") == 1
accept = AcceptEncodingValidHeader("gzip;q=0.5")
assert accept.quality("gzip") == 0.5
@pytest.mark.filterwarnings(IGNORE_QUALITY)
def test_quality_not_found(self):
accept = AcceptEncodingValidHeader("gzip")
assert accept.quality("compress") is None
class TestAcceptEncodingNoHeader:
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:
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:
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:
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
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
def test___contains__(self):
instance = AcceptEncodingNoHeader()
returned = "content-coding" in instance
assert returned is True
@pytest.mark.filterwarnings(IGNORE_ITER)
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:
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:
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:
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)]
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_QUALITY)
def test_quality(self):
instance = AcceptEncodingNoHeader()
returned = instance.quality(offer="content-coding")
assert returned == 1.0
class TestAcceptEncodingInvalidHeader:
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:
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:
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:
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
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
def test___contains__(self):
instance = AcceptEncodingInvalidHeader(header_value=", ")
returned = "content-coding" in instance
assert returned is True
@pytest.mark.filterwarnings(IGNORE_ITER)
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:
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:
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:
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)]
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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"
@pytest.mark.filterwarnings(IGNORE_QUALITY)
def test_quality(self):
instance = AcceptEncodingInvalidHeader(header_value=", ")
returned = instance.quality(offer="content-coding")
assert returned == 1.0
class TestCreateAcceptEncodingHeader:
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
returned2 = create_accept_encoding_header(returned)
assert returned2 is not returned
assert returned2._header_value == returned._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
returned2 = create_accept_encoding_header(returned)
assert returned2 is not returned
assert returned2._header_value == returned._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
returned2 = create_accept_encoding_header(returned)
assert returned2 is not returned
assert returned2._header_value == returned._header_value
class TestAcceptEncodingProperty:
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:
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:
@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:
@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:
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:
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"),
],
)
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
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")],
)
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
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"]),
],
)
@pytest.mark.filterwarnings(IGNORE_ITER)
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:
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:
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",
),
],
)
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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),
],
)
@pytest.mark.filterwarnings(IGNORE_QUALITY)
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:
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:
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:
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
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
def test___contains__(self):
instance = AcceptLanguageNoHeader()
returned = "any-tag" in instance
assert returned is True
@pytest.mark.filterwarnings(IGNORE_ITER)
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:
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:
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"),
],
)
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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
@pytest.mark.filterwarnings(IGNORE_QUALITY)
def test_quality(self):
instance = AcceptLanguageNoHeader()
returned = instance.quality(offer="any-tag")
assert returned == 1.0
class TestAcceptLanguageInvalidHeader:
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:
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:
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
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
def test___contains__(self):
instance = AcceptLanguageInvalidHeader(header_value="")
returned = "any-tag" in instance
assert returned is True
@pytest.mark.filterwarnings(IGNORE_ITER)
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:
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:
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"),
],
)
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
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
@pytest.mark.filterwarnings(IGNORE_QUALITY)
def test_quality(self):
instance = AcceptLanguageInvalidHeader(header_value="")
returned = instance.quality(offer="any-tag")
assert returned == 1.0
class TestCreateAcceptLanguageHeader:
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
returned2 = create_accept_language_header(returned)
assert returned2 is not returned
assert returned2._header_value == returned._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
returned2 = create_accept_language_header(returned)
assert returned2 is not returned
assert returned2._header_value == returned._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
returned2 = create_accept_language_header(returned)
assert returned2 is not returned
assert returned2._header_value == returned._header_value
class TestAcceptLanguageProperty:
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:
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:
@pytest.mark.filterwarnings(IGNORE_MIMEACCEPT)
def test_MIMEAccept_init_warns():
with warnings.catch_warnings(record=True) as warning:
warnings.simplefilter("always")
MIMEAccept("image/jpg")
assert len(warning) == 1
@pytest.mark.filterwarnings(IGNORE_MIMEACCEPT)
def test_MIMEAccept_init():
mimeaccept = MIMEAccept("image/jpg")
assert mimeaccept._parsed == [("image/jpg", 1)]
mimeaccept = MIMEAccept("image/png, image/jpg;q=0.5")
assert mimeaccept._parsed == [("image/png", 1), ("image/jpg", 0.5)]
mimeaccept = MIMEAccept("image, image/jpg;q=0.5")
assert mimeaccept._parsed == []
mimeaccept = MIMEAccept("*/*")
assert mimeaccept._parsed == [("*/*", 1)]
mimeaccept = MIMEAccept("*/png")
assert mimeaccept._parsed == [("*/png", 1)]
mimeaccept = MIMEAccept("image/pn*")
assert mimeaccept._parsed == [("image/pn*", 1.0)]
mimeaccept = MIMEAccept("image/*")
assert mimeaccept._parsed == [("image/*", 1)]
@pytest.mark.filterwarnings(IGNORE_MIMEACCEPT)
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
def test_MIMEAccept_parse():
assert list(MIMEAccept.parse("image/jpg")) == [("image/jpg", 1)]
assert list(MIMEAccept.parse("invalid")) == []
@pytest.mark.filterwarnings(IGNORE_MIMEACCEPT)
def test_MIMEAccept_accept_html():
mimeaccept = MIMEAccept("image/jpg")
assert not mimeaccept.accept_html()
mimeaccept = MIMEAccept("image/jpg, text/html")
assert mimeaccept.accept_html()
@pytest.mark.filterwarnings(IGNORE_MIMEACCEPT)
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
def test_MIMEAccept_contains():
mimeaccept = MIMEAccept("A/a, B/b, C/c")
assert "A/a" in mimeaccept
assert "A/*" in mimeaccept
assert "*/a" in mimeaccept
assert "A/b" not in mimeaccept
assert "B/a" not in mimeaccept
@pytest.mark.filterwarnings(IGNORE_MIMEACCEPT)
@pytest.mark.filterwarnings(IGNORE_BEST_MATCH)
def test_MIMEAccept_json():
mimeaccept = MIMEAccept("text/html, */*; q=.2")
assert mimeaccept.best_match(["application/json"]) == "application/json"
@pytest.mark.filterwarnings(IGNORE_MIMEACCEPT)
def test_MIMEAccept_no_raise_invalid():
assert MIMEAccept("invalid")
@pytest.mark.filterwarnings(IGNORE_MIMEACCEPT)
@pytest.mark.filterwarnings(IGNORE_ITER)
def test_MIMEAccept_iter():
assert list(iter(MIMEAccept("text/html, other/whatever"))) == [
"text/html",
"other/whatever",
]
@pytest.mark.filterwarnings(IGNORE_MIMEACCEPT)
def test_MIMEAccept_str():
assert str(MIMEAccept("image/jpg")) == "image/jpg"
@pytest.mark.filterwarnings(IGNORE_MIMEACCEPT)
def test_MIMEAccept_add():
assert str(MIMEAccept("image/jpg") + "image/png") == "image/jpg, image/png"
assert (
str(MIMEAccept("image/jpg") + MIMEAccept("image/png")) == "image/jpg, image/png"
)
assert isinstance(MIMEAccept("image/jpg") + "image/png", MIMEAccept)
assert isinstance(MIMEAccept("image/jpg") + MIMEAccept("image/png"), MIMEAccept)
@pytest.mark.filterwarnings(IGNORE_MIMEACCEPT)
def test_MIMEAccept_radd():
assert str("image/png" + MIMEAccept("image/jpg")) == "image/png, image/jpg"
assert isinstance("image/png" + MIMEAccept("image/jpg"), MIMEAccept)
@pytest.mark.filterwarnings(IGNORE_MIMEACCEPT)
@pytest.mark.filterwarnings(IGNORE_CONTAINS)
def test_MIMEAccept_repr():
assert "image/jpg" in repr(MIMEAccept("image/jpg"))
@pytest.mark.filterwarnings(IGNORE_MIMEACCEPT)
@pytest.mark.filterwarnings(IGNORE_QUALITY)
def test_MIMEAccept_quality():
assert MIMEAccept("image/jpg;q=0.9").quality("image/jpg") == 0.9
assert MIMEAccept("image/png;q=0.9").quality("image/jpg") is None