Skip to content

Commit

Permalink
Rename RequestParameters to MultiParams, refs #799
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Jun 5, 2020
1 parent e994b21 commit 2db60f8
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 16 deletions.
25 changes: 17 additions & 8 deletions datasette/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -753,15 +753,24 @@ def escape_fts(query):
)


class RequestParameters:
class MultiParams:
def __init__(self, data):
# data is a dictionary of key => [list, of, values]
assert isinstance(data, dict), "data should be a dictionary of key => [list]"
for key in data:
assert isinstance(
data[key], list
), "data should be a dictionary of key => [list]"
self._data = data
# data is a dictionary of key => [list, of, values] or a list of [["key", "value"]] pairs
if isinstance(data, dict):
for key in data:
assert isinstance(
data[key], list
), "dictionary data should be a dictionary of key => [list]"
self._data = data
elif isinstance(data, list):
new_data = {}
for item in data:
assert (
isinstance(item, list) and len(item) == 2
), "list data should be a list of [key, value] pairs"
key, value = item
new_data.setdefault(key, []).append(value)
self._data = new_data

def __contains__(self, key):
return key in self._data
Expand Down
4 changes: 2 additions & 2 deletions datasette/utils/asgi.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import json
from datasette.utils import RequestParameters
from datasette.utils import MultiParams
from mimetypes import guess_type
from urllib.parse import parse_qs, urlunparse, parse_qsl
from pathlib import Path
Expand Down Expand Up @@ -68,7 +68,7 @@ def query_string(self):

@property
def args(self):
return RequestParameters(parse_qs(qs=self.query_string))
return MultiParams(parse_qs(qs=self.query_string))

async def post_vars(self):
body = []
Expand Down
4 changes: 2 additions & 2 deletions datasette/views/table.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from datasette.database import QueryInterrupted
from datasette.utils import (
CustomRow,
RequestParameters,
MultiParams,
append_querystring,
compound_keys_after_sql,
escape_sqlite,
Expand Down Expand Up @@ -286,7 +286,7 @@ async def data(
order_by = ""

# Ensure we don't drop anything with an empty value e.g. ?name__exact=
args = RequestParameters(
args = MultiParams(
urllib.parse.parse_qs(request.query_string, keep_blank_values=True)
)

Expand Down
10 changes: 6 additions & 4 deletions docs/internals.rst
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,20 @@ The request object is passed to various plugin hooks. It represents an incoming
``.query_string`` - string
The querystring component of the request, without the ``?`` - e.g. ``name__contains=sam&age__gt=10``.

``.args`` - RequestParameters
``.args`` - MultiParams
An object representing the parsed querystring parameters, see below.

The object also has one awaitable method:

``await request.post_vars()`` - dictionary
Returns a dictionary of form variables that were submitted in the request body via ``POST``.

The RequestParameters class
---------------------------
.. _internals_multiparams:

``request.args`` is a ``RequestParameters`` object - a dictionary-like object which provides access to querystring parameters that may have multiple values.
The MultiParams class
---------------------

``request.args`` is a ``MultiParams`` object - a dictionary-like object which provides access to querystring parameters that may have multiple values.

Consider the querystring ``?foo=1&foo=2&bar=3`` - with two values for ``foo`` and one value for ``bar``.

Expand Down
9 changes: 9 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -437,3 +437,12 @@ def foo(a, b):

with pytest.raises(TypeError):
utils.call_with_supported_arguments(foo, a=1)


def test_multi_params_list():
p1 = utils.MultiParams([["foo", "bar"], ["foo", "baz"]])
assert "bar" == p1["foo"]
assert ["bar", "baz"] == p1.getlist("foo")
# Should raise an error if list isn't pairs
with pytest.raises(AssertionError):
utils.MultiParams([["foo", "bar"], ["foo", "baz", "bar"]])

0 comments on commit 2db60f8

Please sign in to comment.