Skip to content

Commit

Permalink
feat(parse_query_string): change the default value of csv to False (
Browse files Browse the repository at this point in the history
#2200)

* feat(parse_query_string): change the default value of `csv` to `False`

* docs(parse_query_string): improve docstring in the light of the new default

* test(parse_query_string): resurrect some older tests for `csv=True`
  • Loading branch information
vytas7 committed Dec 26, 2023
1 parent 5b6e4c4 commit 0648726
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 12 deletions.
6 changes: 6 additions & 0 deletions docs/_newsfragments/1999.breakingchange.rst
@@ -0,0 +1,6 @@
The default value of the ``csv`` parameter in
:func:`~falcon.uri.parse_query_string` was changed to ``False``, matching the
default behavior of other parts of the framework (such as
:attr:`req.params <falcon.Request.params>`, the test client, etc).
If the old behavior fits your use case better, pass the ``csv=True`` keyword
argument explicitly.
2 changes: 1 addition & 1 deletion falcon/cyutil/uri.pyx
Expand Up @@ -251,7 +251,7 @@ cdef cy_parse_query_string(unsigned char* data, Py_ssize_t length,


def parse_query_string(unicode query_string not None, bint keep_blank=False,
bint csv=True):
bint csv=False):
cdef bytes byte_string = query_string.encode('utf-8')
cdef unsigned char* data = byte_string
return cy_parse_query_string(data, len(byte_string), keep_blank, csv)
Expand Down
19 changes: 11 additions & 8 deletions falcon/util/uri.py
Expand Up @@ -337,20 +337,22 @@ def decode(encoded_uri: str, unquote_plus: bool = True) -> str:


def parse_query_string(
query_string: str, keep_blank: bool = False, csv: bool = True
query_string: str, keep_blank: bool = False, csv: bool = False
) -> Dict[str, Union[str, List[str]]]:
"""Parse a query string into a dict.
Query string parameters are assumed to use standard form-encoding. Only
parameters with values are returned. For example, given 'foo=bar&flag',
this function would ignore 'flag' unless the `keep_blank_qs_values` option
this function would ignore 'flag' unless the `keep_blank` option
is set.
Note:
In addition to the standard HTML form-based method for specifying
lists by repeating a given param multiple times, Falcon supports
a more compact form in which the param may be given a single time
but set to a ``list`` of comma-separated elements (e.g., 'foo=a,b,c').
This comma-separated format can be enabled by setting the `csv`
option (see below) to ``True``.
When using this format, all commas uri-encoded will not be treated by
Falcon as a delimiter. If the client wants to send a value as a list,
Expand All @@ -365,12 +367,13 @@ def parse_query_string(
they do not have a value (default ``False``). For comma-separated
values, this option also determines whether or not empty elements
in the parsed list are retained.
csv: Set to ``False`` in order to disable splitting query
parameters on ``,`` (default ``True``). Depending on the user agent,
encoding lists as multiple occurrences of the same parameter might
be preferable. In this case, setting `parse_qs_csv` to ``False``
will cause the framework to treat commas as literal characters in
each occurring parameter value.
csv: Set to ``True`` in order to enable splitting query
parameters on ``,`` (default ``False``).
Depending on the user agent, encoding lists as multiple occurrences
of the same parameter might be preferable. In this case, keeping
`parse_qs_csv` at its default value (``False``) will cause the
framework to treat commas as literal characters in each occurring
parameter value.
Returns:
dict: A dictionary of (*name*, *value*) pairs, one per query
Expand Down
15 changes: 12 additions & 3 deletions tests/test_utils.py
Expand Up @@ -380,13 +380,13 @@ def test_parse_query_string(self):
result = uri.parse_query_string(query_string)
assert result['a'] == decoded_url
assert result['b'] == decoded_json
assert result['c'] == ['1', '2', '3']
assert result['c'] == '1,2,3'
assert result['d'] == 'test'
assert result['e'] == ['a', '&=,']
assert result['e'] == 'a,,&=,'
assert result['f'] == ['a', 'a=b']
assert result['é'] == 'a=b'

result = uri.parse_query_string(query_string, True)
result = uri.parse_query_string(query_string, True, True)
assert result['a'] == decoded_url
assert result['b'] == decoded_json
assert result['c'] == ['1', '2', '3']
Expand All @@ -395,6 +395,15 @@ def test_parse_query_string(self):
assert result['f'] == ['a', 'a=b']
assert result['é'] == 'a=b'

result = uri.parse_query_string(query_string, csv=True)
assert result['a'] == decoded_url
assert result['b'] == decoded_json
assert result['c'] == ['1', '2', '3']
assert result['d'] == 'test'
assert result['e'] == ['a', '&=,']
assert result['f'] == ['a', 'a=b']
assert result['é'] == 'a=b'

@pytest.mark.parametrize(
'query_string,keep_blank,expected',
[
Expand Down

0 comments on commit 0648726

Please sign in to comment.