From: Tom Christie Date: Tue, 30 Jul 2019 23:27:20 +0000 (+0100) Subject: Tweak query param types (#175) X-Git-Tag: 0.7.0~31 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=66754ad0c58d61d34489294530351aa4b17e217f;p=thirdparty%2Fhttpx.git Tweak query param types (#175) * Tweak query param types * Handle primitive data types for queryparams * QueryParam keys as str-only, not PrimitiveData --- diff --git a/httpx/models.py b/httpx/models.py index f98447cd..df5d0715 100644 --- a/httpx/models.py +++ b/httpx/models.py @@ -34,14 +34,17 @@ from .utils import ( is_known_encoding, normalize_header_key, normalize_header_value, + str_query_param ) +PrimitiveData = typing.Union[str, int, float, bool, type(None)] + URLTypes = typing.Union["URL", str] QueryParamTypes = typing.Union[ "QueryParams", - typing.Mapping[str, str], - typing.List[typing.Tuple[typing.Any, typing.Any]], + typing.Mapping[str, PrimitiveData], + typing.List[typing.Tuple[str, PrimitiveData]], str, ] @@ -268,8 +271,8 @@ class QueryParams(typing.Mapping[str, str]): else: items = value.items() # type: ignore - self._list = [(str(k), str(v)) for k, v in items] - self._dict = {str(k): str(v) for k, v in items} + self._list = [(str(k), str_query_param(v)) for k, v in items] + self._dict = {str(k): str_query_param(v) for k, v in items} def getlist(self, key: typing.Any) -> typing.List[str]: return [item_value for item_key, item_value in self._list if item_key == key] diff --git a/httpx/utils.py b/httpx/utils.py index 3d0d6607..e96335f5 100644 --- a/httpx/utils.py +++ b/httpx/utils.py @@ -20,6 +20,21 @@ def normalize_header_value(value: typing.AnyStr, encoding: str = None) -> bytes: return value.encode(encoding or "ascii") +def str_query_param(value: typing.Union[str, int, float, bool, type(None)]) -> str: + """ + Coerce a primitive data type into a string value for query params. + + Note that we prefer JSON-style 'true'/'false' for boolean values here. + """ + if value is True: + return "true" + elif value is False: + return "false" + elif value is None: + return "" + return str(value) + + def is_known_encoding(encoding: str) -> bool: """ Return `True` if `encoding` is a known codec. diff --git a/tests/models/test_queryparams.py b/tests/models/test_queryparams.py index 983b09fb..fbb559fb 100644 --- a/tests/models/test_queryparams.py +++ b/tests/models/test_queryparams.py @@ -31,3 +31,23 @@ def test_queryparams(): q = QueryParams([("a", "123"), ("a", "456")]) assert QueryParams(q) == q + + +def test_queryparam_types(): + q = QueryParams({"a": True}) + assert str(q) == "a=true" + + q = QueryParams({"a": False}) + assert str(q) == "a=false" + + q = QueryParams({"a": ""}) + assert str(q) == "a=" + + q = QueryParams({"a": None}) + assert str(q) == "a=" + + q = QueryParams({"a": 1.23}) + assert str(q) == "a=1.23" + + q = QueryParams({"a": 123}) + assert str(q) == "a=123"