]> git.ipfire.org Git - thirdparty/httpx.git/commitdiff
Tweak query param types (#175)
authorTom Christie <tom@tomchristie.com>
Tue, 30 Jul 2019 23:27:20 +0000 (00:27 +0100)
committerGitHub <noreply@github.com>
Tue, 30 Jul 2019 23:27:20 +0000 (00:27 +0100)
* Tweak query param types

* Handle primitive data types for queryparams

* QueryParam keys as str-only, not PrimitiveData

httpx/models.py
httpx/utils.py
tests/models/test_queryparams.py

index f98447cdf57cb2a921ab05172f8b75cfdfe98742..df5d071589e7a864014986705bc411f3fe407388 100644 (file)
@@ -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]
index 3d0d6607d6645b50a37b03ca47c6c575e56426b0..e96335f5471a28649e21f190d4ba54aa0fd1425a 100644 (file)
@@ -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.
index 983b09fb810681e3f316b7804a5536d6f3615a5c..fbb559fb629e3d7df0c9f76d204e90e7ab741ba0 100644 (file)
@@ -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"