From: Tom Christie Date: Wed, 8 May 2019 11:43:06 +0000 (+0100) Subject: Add query_params support X-Git-Tag: 0.3.0~38^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=faededae59b95bd46bdbb063f2b3d3ae5b45ee55;p=thirdparty%2Fhttpx.git Add query_params support --- diff --git a/README.md b/README.md index 3768baeb..c3c35be0 100644 --- a/README.md +++ b/README.md @@ -87,14 +87,14 @@ Additionally, credit is due to for `urllib3` for plenty of design inspiration. ``` * `def __init__([ssl], [timeout], [pool_limits], [max_redirects])` -* `async def .request(method, url, [content], [headers], [stream], [allow_redirects], [ssl], [timeout])` -* `async def .get(url, [headers], [stream], [allow_redirects], [ssl], [timeout])` -* `async def .options(url, [headers], [stream], [allow_redirects], [ssl], [timeout])` -* `async def .head(url, [headers], [stream], [allow_redirects], [ssl], [timeout])` -* `async def .post(url, [content], [headers], [stream], [allow_redirects], [ssl], [timeout])` -* `async def .put(url, [content], [headers], [stream], [allow_redirects], [ssl], [timeout])` -* `async def .patch(url, [content], [headers], [stream], [allow_redirects], [ssl], [timeout])` -* `async def .delete(url, [content], [headers], [stream], [allow_redirects], [ssl], [timeout])` +* `async def .request(method, url, [content], [query_params], [headers], [stream], [allow_redirects], [ssl], [timeout])` +* `async def .get(url, [query_params], [headers], [stream], [allow_redirects], [ssl], [timeout])` +* `async def .options(url, [query_params], [headers], [stream], [allow_redirects], [ssl], [timeout])` +* `async def .head(url, [query_params], [headers], [stream], [allow_redirects], [ssl], [timeout])` +* `async def .post(url, [content], [query_params], [headers], [stream], [allow_redirects], [ssl], [timeout])` +* `async def .put(url, [content], [query_params], [headers], [stream], [allow_redirects], [ssl], [timeout])` +* `async def .patch(url, [content], [query_params], [headers], [stream], [allow_redirects], [ssl], [timeout])` +* `async def .delete(url, [content], [query_params], [headers], [stream], [allow_redirects], [ssl], [timeout])` * `def .prepare_request(request)` * `async def .send(request, [stream], [allow_redirects], [ssl], [timeout])` * `async def .close()` diff --git a/httpcore/client.py b/httpcore/client.py index 58a10740..a3e31f1d 100644 --- a/httpcore/client.py +++ b/httpcore/client.py @@ -15,7 +15,15 @@ from .config import ( TimeoutConfig, ) from .dispatch.connection_pool import ConnectionPool -from .models import URL, ByteOrByteStream, HeaderTypes, Request, Response, URLTypes +from .models import ( + URL, + ByteOrByteStream, + HeaderTypes, + QueryParamTypes, + Request, + Response, + URLTypes, +) class Client: @@ -42,13 +50,16 @@ class Client: url: URLTypes, *, content: ByteOrByteStream = b"", + query_params: QueryParamTypes = None, headers: HeaderTypes = None, stream: bool = False, allow_redirects: bool = True, ssl: SSLConfig = None, timeout: TimeoutConfig = None, ) -> Response: - request = Request(method, url, headers=headers, content=content) + request = Request( + method, url, query_params=query_params, headers=headers, content=content + ) self.prepare_request(request) response = await self.send( request, @@ -63,6 +74,7 @@ class Client: self, url: URLTypes, *, + query_params: QueryParamTypes = None, headers: HeaderTypes = None, stream: bool = False, allow_redirects: bool = True, @@ -72,6 +84,7 @@ class Client: return await self.request( "GET", url, + query_params=query_params, headers=headers, stream=stream, allow_redirects=allow_redirects, @@ -83,6 +96,7 @@ class Client: self, url: URLTypes, *, + query_params: QueryParamTypes = None, headers: HeaderTypes = None, stream: bool = False, allow_redirects: bool = True, @@ -92,6 +106,7 @@ class Client: return await self.request( "OPTIONS", url, + query_params=query_params, headers=headers, stream=stream, allow_redirects=allow_redirects, @@ -103,6 +118,7 @@ class Client: self, url: URLTypes, *, + query_params: QueryParamTypes = None, headers: HeaderTypes = None, stream: bool = False, allow_redirects: bool = False, #  Note: Differs to usual default. @@ -112,6 +128,7 @@ class Client: return await self.request( "HEAD", url, + query_params=query_params, headers=headers, stream=stream, allow_redirects=allow_redirects, @@ -124,6 +141,7 @@ class Client: url: URLTypes, *, content: ByteOrByteStream = b"", + query_params: QueryParamTypes = None, headers: HeaderTypes = None, stream: bool = False, allow_redirects: bool = True, @@ -134,6 +152,7 @@ class Client: "POST", url, content=content, + query_params=query_params, headers=headers, stream=stream, allow_redirects=allow_redirects, @@ -146,6 +165,7 @@ class Client: url: URLTypes, *, content: ByteOrByteStream = b"", + query_params: QueryParamTypes = None, headers: HeaderTypes = None, stream: bool = False, allow_redirects: bool = True, @@ -156,6 +176,7 @@ class Client: "PUT", url, content=content, + query_params=query_params, headers=headers, stream=stream, allow_redirects=allow_redirects, @@ -168,6 +189,7 @@ class Client: url: URLTypes, *, content: ByteOrByteStream = b"", + query_params: QueryParamTypes = None, headers: HeaderTypes = None, stream: bool = False, allow_redirects: bool = True, @@ -178,6 +200,7 @@ class Client: "PATCH", url, content=content, + query_params=query_params, headers=headers, stream=stream, allow_redirects=allow_redirects, @@ -190,6 +213,7 @@ class Client: url: URLTypes, *, content: ByteOrByteStream = b"", + query_params: QueryParamTypes = None, headers: HeaderTypes = None, stream: bool = False, allow_redirects: bool = True, @@ -200,6 +224,7 @@ class Client: "DELETE", url, content=content, + query_params=query_params, headers=headers, stream=stream, allow_redirects=allow_redirects, diff --git a/httpcore/models.py b/httpcore/models.py index 495d6f82..ca98bc8c 100644 --- a/httpcore/models.py +++ b/httpcore/models.py @@ -49,7 +49,10 @@ ByteOrByteStream = typing.Union[bytes, typing.AsyncIterator[bytes]] class URL: def __init__( - self, url: URLTypes, allow_relative: bool = False, params: QueryParamTypes = None + self, + url: URLTypes, + allow_relative: bool = False, + query_params: QueryParamTypes = None, ) -> None: if isinstance(url, rfc3986.uri.URIReference): self.components = url @@ -67,6 +70,11 @@ class URL: # Normalize scheme and domain name. self.components = self.components.normalize() + # Add any query parameters. + if query_params: + query_string = str(QueryParams(query_params)) + self.components = self.components.copy_with(query=query_string) + # Enforce absolute URLs by default. if not allow_relative: if not self.scheme: @@ -444,11 +452,12 @@ class Request: method: str, url: typing.Union[str, URL], *, + query_params: QueryParamTypes = None, headers: HeaderTypes = None, content: ByteOrByteStream = b"", ): self.method = method.upper() - self.url = URL(url) if isinstance(url, str) else url + self.url = URL(url, query_params=query_params) if isinstance(content, bytes): self.is_streaming = False self.content = content diff --git a/tests/models/test_url.py b/tests/models/test_url.py index cf69a6fa..9ed96f6d 100644 --- a/tests/models/test_url.py +++ b/tests/models/test_url.py @@ -23,3 +23,13 @@ def test_url(): new = url.copy_with(scheme="http") assert new == URL("http://example.org:123/path/to/somewhere?abc=123#anchor") assert new.scheme == "http" + + +def test_url_query_params(): + url = URL("https://example.org:123/path/to/somewhere", query_params={"a": "123"}) + assert str(url) == "https://example.org:123/path/to/somewhere?a=123" + + url = URL( + "https://example.org:123/path/to/somewhere?b=456", query_params={"a": "123"} + ) + assert str(url) == "https://example.org:123/path/to/somewhere?a=123"