[3.8] bpo-42967: only use '&' as a query string separator (GH-24297) … · python/cpython@e3110c3 (original) (raw)
`@@ -32,16 +32,10 @@
`
32
32
` (b"&a=b", [(b'a', b'b')]),
`
33
33
` (b"a=a+b&b=b+c", [(b'a', b'a b'), (b'b', b'b c')]),
`
34
34
` (b"a=1&a=2", [(b'a', b'1'), (b'a', b'2')]),
`
35
``
`-
(";", []),
`
36
``
`-
(";;", []),
`
37
``
`-
(";a=b", [('a', 'b')]),
`
38
``
`-
("a=a+b;b=b+c", [('a', 'a b'), ('b', 'b c')]),
`
39
``
`-
("a=1;a=2", [('a', '1'), ('a', '2')]),
`
40
``
`-
(b";", []),
`
41
``
`-
(b";;", []),
`
42
``
`-
(b";a=b", [(b'a', b'b')]),
`
43
``
`-
(b"a=a+b;b=b+c", [(b'a', b'a b'), (b'b', b'b c')]),
`
44
``
`-
(b"a=1;a=2", [(b'a', b'1'), (b'a', b'2')]),
`
``
35
`+
(";a=b", [(';a', 'b')]),
`
``
36
`+
("a=a+b;b=b+c", [('a', 'a b;b=b c')]),
`
``
37
`+
(b";a=b", [(b';a', b'b')]),
`
``
38
`+
(b"a=a+b;b=b+c", [(b'a', b'a b;b=b c')]),
`
45
39
`]
`
46
40
``
47
41
`# Each parse_qs testcase is a two-tuple that contains
`
`@@ -68,16 +62,10 @@
`
68
62
` (b"&a=b", {b'a': [b'b']}),
`
69
63
` (b"a=a+b&b=b+c", {b'a': [b'a b'], b'b': [b'b c']}),
`
70
64
` (b"a=1&a=2", {b'a': [b'1', b'2']}),
`
71
``
`-
(";", {}),
`
72
``
`-
(";;", {}),
`
73
``
`-
(";a=b", {'a': ['b']}),
`
74
``
`-
("a=a+b;b=b+c", {'a': ['a b'], 'b': ['b c']}),
`
75
``
`-
("a=1;a=2", {'a': ['1', '2']}),
`
76
``
`-
(b";", {}),
`
77
``
`-
(b";;", {}),
`
78
``
`-
(b";a=b", {b'a': [b'b']}),
`
79
``
`-
(b"a=a+b;b=b+c", {b'a': [b'a b'], b'b': [b'b c']}),
`
80
``
`-
(b"a=1;a=2", {b'a': [b'1', b'2']}),
`
``
65
`+
(";a=b", {';a': ['b']}),
`
``
66
`+
("a=a+b;b=b+c", {'a': ['a b;b=b c']}),
`
``
67
`+
(b";a=b", {b';a': [b'b']}),
`
``
68
`+
(b"a=a+b;b=b+c", {b'a':[ b'a b;b=b c']}),
`
81
69
`]
`
82
70
``
83
71
`class UrlParseTestCase(unittest.TestCase):
`
`@@ -884,10 +872,46 @@ def test_parse_qsl_encoding(self):
`
884
872
`def test_parse_qsl_max_num_fields(self):
`
885
873
`with self.assertRaises(ValueError):
`
886
874
`urllib.parse.parse_qs('&'.join(['a=a']*11), max_num_fields=10)
`
887
``
`-
with self.assertRaises(ValueError):
`
888
``
`-
urllib.parse.parse_qs(';'.join(['a=a']*11), max_num_fields=10)
`
889
875
`urllib.parse.parse_qs('&'.join(['a=a']*10), max_num_fields=10)
`
890
876
``
``
877
`+
def test_parse_qs_separator(self):
`
``
878
`+
parse_qs_semicolon_cases = [
`
``
879
`+
(";", {}),
`
``
880
`+
(";;", {}),
`
``
881
`+
(";a=b", {'a': ['b']}),
`
``
882
`+
("a=a+b;b=b+c", {'a': ['a b'], 'b': ['b c']}),
`
``
883
`+
("a=1;a=2", {'a': ['1', '2']}),
`
``
884
`+
(b";", {}),
`
``
885
`+
(b";;", {}),
`
``
886
`+
(b";a=b", {b'a': [b'b']}),
`
``
887
`+
(b"a=a+b;b=b+c", {b'a': [b'a b'], b'b': [b'b c']}),
`
``
888
`+
(b"a=1;a=2", {b'a': [b'1', b'2']}),
`
``
889
`+
]
`
``
890
`+
for orig, expect in parse_qs_semicolon_cases:
`
``
891
`+
with self.subTest(f"Original: {orig!r}, Expected: {expect!r}"):
`
``
892
`+
result = urllib.parse.parse_qs(orig, separator=';')
`
``
893
`+
self.assertEqual(result, expect, "Error parsing %r" % orig)
`
``
894
+
``
895
+
``
896
`+
def test_parse_qsl_separator(self):
`
``
897
`+
parse_qsl_semicolon_cases = [
`
``
898
`+
(";", []),
`
``
899
`+
(";;", []),
`
``
900
`+
(";a=b", [('a', 'b')]),
`
``
901
`+
("a=a+b;b=b+c", [('a', 'a b'), ('b', 'b c')]),
`
``
902
`+
("a=1;a=2", [('a', '1'), ('a', '2')]),
`
``
903
`+
(b";", []),
`
``
904
`+
(b";;", []),
`
``
905
`+
(b";a=b", [(b'a', b'b')]),
`
``
906
`+
(b"a=a+b;b=b+c", [(b'a', b'a b'), (b'b', b'b c')]),
`
``
907
`+
(b"a=1;a=2", [(b'a', b'1'), (b'a', b'2')]),
`
``
908
`+
]
`
``
909
`+
for orig, expect in parse_qsl_semicolon_cases:
`
``
910
`+
with self.subTest(f"Original: {orig!r}, Expected: {expect!r}"):
`
``
911
`+
result = urllib.parse.parse_qsl(orig, separator=';')
`
``
912
`+
self.assertEqual(result, expect, "Error parsing %r" % orig)
`
``
913
+
``
914
+
891
915
`def test_urlencode_sequences(self):
`
892
916
`# Other tests incidentally urlencode things; test non-covered cases:
`
893
917
`# Sequence and object values.
`