Repository: encode/httpx

Issue:
Support passing bytes keys/values in `params=...`
``` python
>>> httpx.get('https://example.org', params={b'testparam': b'testvalue'}).url
URL('https://example.org?b%27testparam%27=b%27testvalue%27')
```

I don't think this is intentional, as there is an isinstance check for bytes in the ``flatten_queryparams`` function, I'd expect anyone involved to have raised an exception instead of letting it go through like that, and that would be an undocumented divergence from requests compatibility.

I have tested with ``httpx==0.7.8`` as well as ``httpx==0.11.0``.

Discussion:

Patch:
diff --git a/httpx/_utils.py b/httpx/_utils.py
index 1f64dee..1e1570e 100644
--- a/httpx/_utils.py
+++ b/httpx/_utils.py
@@ -67,7 +67,11 @@ def primitive_value_to_str(value: "PrimitiveData") -> str:
         return "false"
     elif value is None:
         return ""
-    return str(value)
+    elif isinstance(value, (str, float, int)):
+        return str(value)
+    raise TypeError(
+        f"Expected str, int, float, bool, or None. Got {type(value).__name__!r}."
+    )
 
 
 def is_known_encoding(encoding: str) -> bool:


Test patch:
diff --git a/tests/models/test_queryparams.py b/tests/models/test_queryparams.py
index 29b2ca6..cbb487b 100644
--- a/tests/models/test_queryparams.py
+++ b/tests/models/test_queryparams.py
@@ -87,6 +87,13 @@ def test_empty_query_params():
     assert str(q) == "a="
 
 
+def test_invalid_query_params():
+    with pytest.raises(
+        TypeError, match=r"Expected str, int, float, bool, or None. Got 'bytes'."
+    ):
+        httpx.QueryParams({"a": b"bytes"})
+
+
 def test_queryparam_update_is_hard_deprecated():
     q = httpx.QueryParams("a=123")
     with pytest.raises(RuntimeError):