Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-pytest-httpx for
openSUSE:Factory checked in at 2023-01-17 17:35:27
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pytest-httpx (Old)
and /work/SRC/openSUSE:Factory/.python-pytest-httpx.new.32243 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pytest-httpx"
Tue Jan 17 17:35:27 2023 rev:4 rq:1058836 version:0.21.2
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pytest-httpx/python-pytest-httpx.changes
2022-08-08 10:02:33.362376869 +0200
+++
/work/SRC/openSUSE:Factory/.python-pytest-httpx.new.32243/python-pytest-httpx.changes
2023-01-17 17:35:41.517312709 +0100
@@ -1,0 +2,10 @@
+Mon Jan 16 16:21:19 UTC 2023 - Daniel Garcia <[email protected]>
+
+- Update to 0.21.2
+ * URL containing non ASCII characters in query can now be matched.
+ * Requests are now cleared when calling httpx_mock.reset.
+- 0.21.1
+ * httpx_mock.add_callback now handles async callbacks.
+- Unpin httpx and pytest in python metadata
+
+-------------------------------------------------------------------
Old:
----
pytest_httpx-0.21.0-gh.tar.gz
New:
----
pytest_httpx-0.21.2-gh.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-pytest-httpx.spec ++++++
--- /var/tmp/diff_new_pack.qiI9eS/_old 2023-01-17 17:35:42.069315911 +0100
+++ /var/tmp/diff_new_pack.qiI9eS/_new 2023-01-17 17:35:42.073315935 +0100
@@ -1,7 +1,7 @@
#
# spec file for package python-pytest-httpx
#
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
#
# All modifications and additions to the file contributed by third parties
# remain the property of their copyright owners, unless otherwise agreed
@@ -17,7 +17,7 @@
Name: python-pytest-httpx
-Version: 0.21.0
+Version: 0.21.2
Release: 0
Summary: Send responses to httpx
License: MIT
@@ -29,7 +29,7 @@
# SECTION test requirements
BuildRequires: %{python_module httpx >= 0.23.0}
BuildRequires: %{python_module pytest >= 6.0}
-BuildRequires: %{python_module pytest-asyncio >= 0.14.0}
+BuildRequires: %{python_module pytest-asyncio >= 0.20.0}
# /SECTION
BuildRequires: fdupes
Requires: python-httpx >= 0.23.0
@@ -43,7 +43,8 @@
%prep
%setup -q -n pytest_httpx-%{version}
# unpin exact version
-sed -i '/install_requires/ s/httpx==0./httpx>=0./' setup.py
+sed -i '/install_requires/ s/httpx==0.23.\*/httpx/' setup.py
+sed -i '/install_requires/ s/pytest>=6.*,<8.\*/pytest/' setup.py
%build
%python_build
++++++ pytest_httpx-0.21.0-gh.tar.gz -> pytest_httpx-0.21.2-gh.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest_httpx-0.21.0/.pre-commit-config.yaml
new/pytest_httpx-0.21.2/.pre-commit-config.yaml
--- old/pytest_httpx-0.21.0/.pre-commit-config.yaml 2022-05-24
18:29:06.000000000 +0200
+++ new/pytest_httpx-0.21.2/.pre-commit-config.yaml 2022-11-03
22:03:01.000000000 +0100
@@ -1,5 +1,5 @@
repos:
- repo: https://github.com/psf/black
- rev: 22.3.0
+ rev: 22.10.0
hooks:
- id: black
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest_httpx-0.21.0/CHANGELOG.md
new/pytest_httpx-0.21.2/CHANGELOG.md
--- old/pytest_httpx-0.21.0/CHANGELOG.md 2022-05-24 18:29:06.000000000
+0200
+++ new/pytest_httpx-0.21.2/CHANGELOG.md 2022-11-03 22:03:01.000000000
+0100
@@ -6,6 +6,15 @@
## [Unreleased]
+## [0.21.2] - 2022-11-03
+### Fixed
+- URL containing non ASCII characters in query can now be matched.
+- Requests are now cleared when calling `httpx_mock.reset`.
+
+## [0.21.1] - 2022-10-20
+### Fixed
+- `httpx_mock.add_callback` now handles async callbacks.
+
## [0.21.0] - 2022-05-24
### Changed
- Requires [`httpx`](https://www.python-httpx.org)==0.23.\*
@@ -223,7 +232,9 @@
### Added
- First release, should be considered as unstable for now as design might
change.
-[Unreleased]: https://github.com/Colin-b/pytest_httpx/compare/v0.21.0...HEAD
+[Unreleased]: https://github.com/Colin-b/pytest_httpx/compare/v0.21.2...HEAD
+[0.21.2]: https://github.com/Colin-b/pytest_httpx/compare/v0.21.1...v0.21.2
+[0.21.1]: https://github.com/Colin-b/pytest_httpx/compare/v0.21.0...v0.21.1
[0.21.0]: https://github.com/Colin-b/pytest_httpx/compare/v0.20.0...v0.21.0
[0.20.0]: https://github.com/Colin-b/pytest_httpx/compare/v0.19.0...v0.20.0
[0.19.0]: https://github.com/Colin-b/pytest_httpx/compare/v0.18.0...v0.19.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest_httpx-0.21.0/CONTRIBUTING.md
new/pytest_httpx-0.21.2/CONTRIBUTING.md
--- old/pytest_httpx-0.21.0/CONTRIBUTING.md 2022-05-24 18:29:06.000000000
+0200
+++ new/pytest_httpx-0.21.2/CONTRIBUTING.md 2022-11-03 22:03:01.000000000
+0100
@@ -56,7 +56,7 @@
1) Go to the *Pull requests* tab and click on the *New pull request* button.
2) *base* should always be set to `develop` and it should be compared to your
branch.
3) Title should be a small sentence describing the request.
-3) The comment should contain as much information as possible
+4) The comment should contain as much information as possible
* Actual behavior (before the new code)
* Expected behavior (with the new code)
* Steps to reproduce (with and without the new code to see the difference)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest_httpx-0.21.0/README.md
new/pytest_httpx-0.21.2/README.md
--- old/pytest_httpx-0.21.0/README.md 2022-05-24 18:29:06.000000000 +0200
+++ new/pytest_httpx-0.21.2/README.md 2022-11-03 22:03:01.000000000 +0100
@@ -5,7 +5,7 @@
<a href="https://github.com/Colin-b/pytest_httpx/actions"><img alt="Build
status"
src="https://github.com/Colin-b/pytest_httpx/workflows/Release/badge.svg"></a>
<a href="https://github.com/Colin-b/pytest_httpx/actions"><img alt="Coverage"
src="https://img.shields.io/badge/coverage-100%25-brightgreen"></a>
<a href="https://github.com/psf/black"><img alt="Code style: black"
src="https://img.shields.io/badge/code%20style-black-000000.svg"></a>
-<a href="https://github.com/Colin-b/pytest_httpx/actions"><img alt="Number of
tests" src="https://img.shields.io/badge/tests-153 passed-blue"></a>
+<a href="https://github.com/Colin-b/pytest_httpx/actions"><img alt="Number of
tests" src="https://img.shields.io/badge/tests-168 passed-blue"></a>
<a href="https://pypi.org/project/pytest-httpx/"><img alt="Number of
downloads" src="https://img.shields.io/pypi/dm/pytest_httpx"></a>
</p>
@@ -444,6 +444,38 @@
```
+Alternatively, callbacks can also be asynchronous.
+
+As in the following sample simulating network latency on some responses only.
+
+```python
+import asyncio
+import httpx
+import pytest
+from pytest_httpx import HTTPXMock
+
+
[email protected]
+async def test_dynamic_async_response(httpx_mock: HTTPXMock):
+ async def simulate_network_latency(request: httpx.Request):
+ await asyncio.sleep(1)
+ return httpx.Response(
+ status_code=200, json={"url": str(request.url)},
+ )
+
+ httpx_mock.add_callback(simulate_network_latency)
+ httpx_mock.add_response()
+
+ async with httpx.AsyncClient() as client:
+ responses = await asyncio.gather(
+ # Response will be received after one second
+ client.get("https://test_url"),
+ # Response will instantly be received (1 second before the first
request)
+ client.get("https://test_url")
+ )
+
+```
+
### Raising exceptions
You can simulate HTTPX exception throwing by raising an exception in your
callback or use `httpx_mock.add_exception` with the exception instance.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest_httpx-0.21.0/pytest_httpx/_httpx_mock.py
new/pytest_httpx-0.21.2/pytest_httpx/_httpx_mock.py
--- old/pytest_httpx-0.21.0/pytest_httpx/_httpx_mock.py 2022-05-24
18:29:06.000000000 +0200
+++ new/pytest_httpx-0.21.2/pytest_httpx/_httpx_mock.py 2022-11-03
22:03:01.000000000 +0100
@@ -1,14 +1,11 @@
+import inspect
import re
-from typing import List, Union, Optional, Callable, Tuple, Pattern, Any, Dict
-from urllib.parse import parse_qs
+from typing import List, Union, Optional, Callable, Tuple, Pattern, Any, Dict,
Awaitable
import httpx
from pytest_httpx import _httpx_internals
-# re.Pattern was introduced in Python 3.7
-pattern_type = re._pattern_type if hasattr(re, "_pattern_type") else re.Pattern
-
class _RequestMatcher:
def __init__(
@@ -36,18 +33,18 @@
if not self.url:
return True
- if isinstance(self.url, pattern_type):
+ if isinstance(self.url, re.Pattern):
return self.url.match(str(request.url)) is not None
# Compare query parameters apart as order of parameters should not
matter
- request_qs = parse_qs(request.url.query)
- qs = parse_qs(self.url.query)
+ request_params = dict(request.url.params)
+ params = dict(self.url.params)
# Remove the query parameters from the original URL to compare
everything besides query parameters
request_url = request.url.copy_with(query=None)
url = self.url.copy_with(query=None)
- return (request_qs == qs) and (url == request_url)
+ return (request_params == params) and (url == request_url)
def _method_match(self, request: httpx.Request) -> bool:
if not self.method:
@@ -89,7 +86,12 @@
self._callbacks: List[
Tuple[
_RequestMatcher,
- Callable[[httpx.Request], Optional[httpx.Response]],
+ Callable[
+ [httpx.Request],
+ Union[
+ Optional[httpx.Response],
Awaitable[Optional[httpx.Response]]
+ ],
+ ],
]
] = []
@@ -135,7 +137,12 @@
self.add_callback(lambda request: response, **matchers)
def add_callback(
- self, callback: Callable[[httpx.Request], Optional[httpx.Response]],
**matchers
+ self,
+ callback: Callable[
+ [httpx.Request],
+ Union[Optional[httpx.Response],
Awaitable[Optional[httpx.Response]]],
+ ],
+ **matchers,
) -> None:
"""
Mock the action that will take place if a request match.
@@ -180,12 +187,26 @@
response = callback(request)
if response:
- # Allow to read the response on client side
- response.is_stream_consumed = False
- response.is_closed = False
- if hasattr(response, "_content"):
- del response._content
- return response
+ return _unread(response)
+
+ raise httpx.TimeoutException(
+ self._explain_that_no_response_was_found(request), request=request
+ )
+
+ async def _handle_async_request(
+ self,
+ request: httpx.Request,
+ ) -> httpx.Response:
+ self._requests.append(request)
+
+ callback = self._get_callback(request)
+ if callback:
+ response = callback(request)
+
+ if response:
+ if inspect.isawaitable(response):
+ response = await response
+ return _unread(response)
raise httpx.TimeoutException(
self._explain_that_no_response_was_found(request), request=request
@@ -221,7 +242,12 @@
def _get_callback(
self, request: httpx.Request
- ) -> Optional[Callable[[httpx.Request], Optional[httpx.Response]]]:
+ ) -> Optional[
+ Callable[
+ [httpx.Request],
+ Union[Optional[httpx.Response],
Awaitable[Optional[httpx.Response]]],
+ ]
+ ]:
callbacks = [
(matcher, callback)
for matcher, callback in self._callbacks
@@ -274,6 +300,7 @@
return requests[0] if requests else None
def reset(self, assert_all_responses_were_requested: bool) -> None:
+ self._requests.clear()
not_called = self._reset_callbacks()
if assert_all_responses_were_requested:
@@ -304,4 +331,13 @@
self.mock = mock
async def handle_async_request(self, *args, **kwargs) -> httpx.Response:
- return self.mock._handle_request(*args, **kwargs)
+ return await self.mock._handle_async_request(*args, **kwargs)
+
+
+def _unread(response: httpx.Response) -> httpx.Response:
+ # Allow to read the response on client side
+ response.is_stream_consumed = False
+ response.is_closed = False
+ if hasattr(response, "_content"):
+ del response._content
+ return response
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest_httpx-0.21.0/pytest_httpx/version.py
new/pytest_httpx-0.21.2/pytest_httpx/version.py
--- old/pytest_httpx-0.21.0/pytest_httpx/version.py 2022-05-24
18:29:06.000000000 +0200
+++ new/pytest_httpx-0.21.2/pytest_httpx/version.py 2022-11-03
22:03:01.000000000 +0100
@@ -3,4 +3,4 @@
# Major should be incremented in case there is a breaking change. (eg: 2.5.8
-> 3.0.0)
# Minor should be incremented in case there is an enhancement. (eg: 2.5.8 ->
2.6.0)
# Patch should be incremented in case there is a bug fix. (eg: 2.5.8 -> 2.5.9)
-__version__ = "0.21.0"
+__version__ = "0.21.2"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest_httpx-0.21.0/setup.py
new/pytest_httpx-0.21.2/setup.py
--- old/pytest_httpx-0.21.0/setup.py 2022-05-24 18:29:06.000000000 +0200
+++ new/pytest_httpx-0.21.2/setup.py 2022-11-03 22:03:01.000000000 +0100
@@ -44,9 +44,9 @@
extras_require={
"testing": [
# Used to run async test functions
- "pytest-asyncio==0.17.*",
+ "pytest-asyncio==0.20.*",
# Used to check coverage
- "pytest-cov==3.*",
+ "pytest-cov==4.*",
]
},
python_requires=">=3.7",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest_httpx-0.21.0/tests/test_httpx_async.py
new/pytest_httpx-0.21.2/tests/test_httpx_async.py
--- old/pytest_httpx-0.21.0/tests/test_httpx_async.py 2022-05-24
18:29:06.000000000 +0200
+++ new/pytest_httpx-0.21.2/tests/test_httpx_async.py 2022-11-03
22:03:01.000000000 +0100
@@ -1,4 +1,7 @@
+import asyncio
+import math
import re
+import time
import httpx
import pytest
@@ -166,7 +169,7 @@
# Assert that stream still behaves the proper way (can only be
consumed once per request)
with pytest.raises(httpx.StreamConsumed):
async for part in response.aiter_raw():
- pass
+ pass # pragma: no cover
async with client.stream(method="GET", url="https://test_url") as
response:
assert [part async for part in response.aiter_raw()] == [
@@ -176,7 +179,7 @@
# Assert that stream still behaves the proper way (can only be
consumed once per request)
with pytest.raises(httpx.StreamConsumed):
async for part in response.aiter_raw():
- pass
+ pass # pragma: no cover
@pytest.mark.asyncio
@@ -194,7 +197,7 @@
# Assert that stream still behaves the proper way (can only be
consumed once per request)
with pytest.raises(httpx.StreamConsumed):
async for part in response.aiter_raw():
- pass
+ pass # pragma: no cover
async with client.stream(method="GET", url="https://test_url") as
response:
assert [part async for part in response.aiter_raw()] == [
@@ -203,7 +206,7 @@
# Assert that stream still behaves the proper way (can only be
consumed once per request)
with pytest.raises(httpx.StreamConsumed):
async for part in response.aiter_raw():
- pass
+ pass # pragma: no cover
@pytest.mark.asyncio
@@ -221,7 +224,7 @@
# Assert that stream still behaves the proper way (can only be
consumed once per request)
with pytest.raises(httpx.StreamConsumed):
async for part in response.aiter_raw():
- pass
+ pass # pragma: no cover
async with client.stream(method="GET", url="https://test_url") as
response:
assert [part async for part in response.aiter_raw()] == [
@@ -230,7 +233,7 @@
# Assert that stream still behaves the proper way (can only be
consumed once per request)
with pytest.raises(httpx.StreamConsumed):
async for part in response.aiter_raw():
- pass
+ pass # pragma: no cover
@pytest.mark.asyncio
@@ -243,14 +246,14 @@
# Assert that stream still behaves the proper way (can only be
consumed once per request)
with pytest.raises(httpx.StreamConsumed):
async for part in response.aiter_raw():
- pass
+ pass # pragma: no cover
async with client.stream(method="GET", url="https://test_url") as
response:
assert [part async for part in response.aiter_raw()] == []
# Assert that stream still behaves the proper way (can only be
consumed once per request)
with pytest.raises(httpx.StreamConsumed):
async for part in response.aiter_raw():
- pass
+ pass # pragma: no cover
@pytest.mark.asyncio
@@ -488,6 +491,66 @@
@pytest.mark.asyncio
+async def test_async_callback_with_await_statement(httpx_mock: HTTPXMock) ->
None:
+ async def simulate_network_latency(request: httpx.Request):
+ await asyncio.sleep(1)
+ return httpx.Response(
+ status_code=200,
+ json={"url": str(request.url), "time": time.time()},
+ )
+
+ def instant_response(request: httpx.Request) -> httpx.Response:
+ return httpx.Response(
+ status_code=200, json={"url": str(request.url), "time":
time.time()}
+ )
+
+ httpx_mock.add_callback(simulate_network_latency)
+ httpx_mock.add_callback(instant_response)
+ httpx_mock.add_response(json={"url": "not a callback"})
+
+ async with httpx.AsyncClient() as client:
+ responses = await asyncio.gather(
+ client.get("https://slow"),
+ client.get("https://fast_with_callback"),
+ client.get("https://fast_with_response"),
+ )
+ slow_response = responses[0].json()
+ assert slow_response["url"] == "https://slow"
+
+ fast_callback_response = responses[1].json()
+ assert fast_callback_response["url"] == "https://fast_with_callback"
+
+ fast_response = responses[2].json()
+ assert fast_response["url"] == "not a callback"
+
+ # Ensure slow request was properly awaited (did not block subsequent
async queries)
+ assert math.isclose(slow_response["time"],
fast_callback_response["time"] + 1)
+
+
[email protected]
+async def test_async_callback_with_pattern_in_url(httpx_mock: HTTPXMock) ->
None:
+ async def custom_response(request: httpx.Request) -> httpx.Response:
+ return httpx.Response(status_code=200, json={"url": str(request.url)})
+
+ async def custom_response2(request: httpx.Request) -> httpx.Response:
+ return httpx.Response(
+ status_code=200,
+ extensions={"http_version": b"HTTP/2.0"},
+ json={"url": str(request.url)},
+ )
+
+ httpx_mock.add_callback(custom_response, url=re.compile(".*test.*"))
+ httpx_mock.add_callback(custom_response2, url="https://unmatched")
+
+ async with httpx.AsyncClient() as client:
+ response = await client.get("https://unmatched")
+ assert response.http_version == "HTTP/2.0"
+
+ response = await client.get("https://test_url")
+ assert response.http_version == "HTTP/1.1"
+
+
[email protected]
async def test_with_many_responses_urls_instances(httpx_mock: HTTPXMock) ->
None:
httpx_mock.add_response(
url=httpx.URL("https://test_url", params={"param1": "test"}),
@@ -763,6 +826,22 @@
@pytest.mark.asyncio
+async def test_async_callback_raising_exception(httpx_mock: HTTPXMock) -> None:
+ async def raise_timeout(request: httpx.Request) -> httpx.Response:
+ raise httpx.ReadTimeout(
+ f"Unable to read within {request.extensions['timeout']['read']}",
+ request=request,
+ )
+
+ httpx_mock.add_callback(raise_timeout, url="https://test_url")
+
+ async with httpx.AsyncClient() as client:
+ with pytest.raises(httpx.ReadTimeout) as exception_info:
+ await client.get("https://test_url")
+ assert str(exception_info.value) == "Unable to read within 5.0"
+
+
[email protected]
async def test_request_exception_raising(httpx_mock: HTTPXMock) -> None:
httpx_mock.add_exception(
httpx.ReadTimeout("Unable to read within 5.0"), url="https://test_url"
@@ -801,6 +880,19 @@
@pytest.mark.asyncio
+async def test_async_callback_returning_response(httpx_mock: HTTPXMock) ->
None:
+ async def custom_response(request: httpx.Request) -> httpx.Response:
+ return httpx.Response(status_code=200, json={"url": str(request.url)})
+
+ httpx_mock.add_callback(custom_response, url="https://test_url")
+
+ async with httpx.AsyncClient() as client:
+ response = await client.get("https://test_url")
+ assert response.json() == {"url": "https://test_url"}
+ assert response.headers["content-type"] == "application/json"
+
+
[email protected]
async def test_callback_executed_twice(httpx_mock: HTTPXMock) -> None:
def custom_response(request: httpx.Request) -> httpx.Response:
return httpx.Response(status_code=200, json=["content"])
@@ -818,6 +910,23 @@
@pytest.mark.asyncio
+async def test_async_callback_executed_twice(httpx_mock: HTTPXMock) -> None:
+ async def custom_response(request: httpx.Request) -> httpx.Response:
+ return httpx.Response(status_code=200, json=["content"])
+
+ httpx_mock.add_callback(custom_response)
+
+ async with httpx.AsyncClient() as client:
+ response = await client.get("https://test_url")
+ assert response.json() == ["content"]
+ assert response.headers["content-type"] == "application/json"
+
+ response = await client.post("https://test_url")
+ assert response.json() == ["content"]
+ assert response.headers["content-type"] == "application/json"
+
+
[email protected]
async def test_callback_registered_after_response(httpx_mock: HTTPXMock) ->
None:
def custom_response(request: httpx.Request) -> httpx.Response:
return httpx.Response(status_code=200, json=["content2"])
@@ -841,6 +950,29 @@
@pytest.mark.asyncio
+async def test_async_callback_registered_after_response(httpx_mock: HTTPXMock)
-> None:
+ async def custom_response(request: httpx.Request) -> httpx.Response:
+ return httpx.Response(status_code=200, json=["content2"])
+
+ httpx_mock.add_response(json=["content1"])
+ httpx_mock.add_callback(custom_response)
+
+ async with httpx.AsyncClient() as client:
+ response = await client.get("https://test_url")
+ assert response.json() == ["content1"]
+ assert response.headers["content-type"] == "application/json"
+
+ response = await client.post("https://test_url")
+ assert response.json() == ["content2"]
+ assert response.headers["content-type"] == "application/json"
+
+ # Assert that the last registered callback is sent again even if there
is a response
+ response = await client.post("https://test_url")
+ assert response.json() == ["content2"]
+ assert response.headers["content-type"] == "application/json"
+
+
[email protected]
async def test_response_registered_after_callback(httpx_mock: HTTPXMock) ->
None:
def custom_response(request: httpx.Request) -> httpx.Response:
return httpx.Response(status_code=200, json=["content1"])
@@ -864,6 +996,29 @@
@pytest.mark.asyncio
+async def test_response_registered_after_async_callback(httpx_mock: HTTPXMock)
-> None:
+ async def custom_response(request: httpx.Request) -> httpx.Response:
+ return httpx.Response(status_code=200, json=["content1"])
+
+ httpx_mock.add_callback(custom_response)
+ httpx_mock.add_response(json=["content2"])
+
+ async with httpx.AsyncClient() as client:
+ response = await client.get("https://test_url")
+ assert response.json() == ["content1"]
+ assert response.headers["content-type"] == "application/json"
+
+ response = await client.post("https://test_url")
+ assert response.json() == ["content2"]
+ assert response.headers["content-type"] == "application/json"
+
+ # Assert that the last registered response is sent again even if there
is a callback
+ response = await client.post("https://test_url")
+ assert response.json() == ["content2"]
+ assert response.headers["content-type"] == "application/json"
+
+
[email protected]
async def test_callback_matching_method(httpx_mock: HTTPXMock) -> None:
def custom_response(request: httpx.Request) -> httpx.Response:
return httpx.Response(status_code=200, json=["content"])
@@ -880,6 +1035,23 @@
assert response.headers["content-type"] == "application/json"
[email protected]
+async def test_async_callback_matching_method(httpx_mock: HTTPXMock) -> None:
+ async def custom_response(request: httpx.Request) -> httpx.Response:
+ return httpx.Response(status_code=200, json=["content"])
+
+ httpx_mock.add_callback(custom_response, method="GET")
+
+ async with httpx.AsyncClient() as client:
+ response = await client.get("https://test_url")
+ assert response.json() == ["content"]
+ assert response.headers["content-type"] == "application/json"
+
+ response = await client.get("https://test_url2")
+ assert response.json() == ["content"]
+ assert response.headers["content-type"] == "application/json"
+
+
def test_request_retrieval_with_more_than_one(testdir: Testdir) -> None:
"""
Single request cannot be returned if there is more than one matching.
@@ -1485,3 +1657,45 @@
async with httpx.AsyncClient() as client:
response = await client.get("https://test_url")
assert response.elapsed is not None
+
+
[email protected]
+async def test_elapsed_when_add_async_callback(httpx_mock: HTTPXMock) -> None:
+ async def custom_response(request: httpx.Request) -> httpx.Response:
+ return httpx.Response(status_code=200, json={"foo": "bar"})
+
+ httpx_mock.add_callback(custom_response)
+
+ async with httpx.AsyncClient() as client:
+ response = await client.get("https://test_url")
+ assert response.elapsed is not None
+
+
[email protected]
+async def test_non_ascii_url_response(httpx_mock: HTTPXMock) -> None:
+ httpx_mock.add_response(url="https://test_url?query_type=æ°æ®")
+
+ async with httpx.AsyncClient() as client:
+ response = await client.get("https://test_url?query_type=æ°æ®")
+ assert response.content == b""
+
+
[email protected]
+async def test_url_encoded_matching_response(httpx_mock: HTTPXMock) -> None:
+ httpx_mock.add_response(url="https://test_url?a=%E6%95%B0%E6%8D%AE")
+
+ async with httpx.AsyncClient() as client:
+ response = await client.get("https://test_url?a=æ°æ®")
+ assert response.content == b""
+
+
[email protected]
+async def test_reset_is_removing_requests(httpx_mock: HTTPXMock) -> None:
+ httpx_mock.add_response()
+ async with httpx.AsyncClient() as client:
+ await client.get("https://test_url")
+
+ assert len(httpx_mock.get_requests()) == 1
+
+ httpx_mock.reset(assert_all_responses_were_requested=False)
+ assert len(httpx_mock.get_requests()) == 0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/pytest_httpx-0.21.0/tests/test_httpx_sync.py
new/pytest_httpx-0.21.2/tests/test_httpx_sync.py
--- old/pytest_httpx-0.21.0/tests/test_httpx_sync.py 2022-05-24
18:29:06.000000000 +0200
+++ new/pytest_httpx-0.21.2/tests/test_httpx_sync.py 2022-11-03
22:03:01.000000000 +0100
@@ -1383,3 +1383,30 @@
with httpx.Client() as client:
response = client.get("https://test_url")
assert response.elapsed is not None
+
+
+def test_non_ascii_url_response(httpx_mock: HTTPXMock) -> None:
+ httpx_mock.add_response(url="https://test_url?query_type=æ°æ®")
+
+ with httpx.Client() as client:
+ response = client.get("https://test_url?query_type=æ°æ®")
+ assert response.content == b""
+
+
+def test_url_encoded_matching_response(httpx_mock: HTTPXMock) -> None:
+ httpx_mock.add_response(url="https://test_url?a=%E6%95%B0%E6%8D%AE")
+
+ with httpx.Client() as client:
+ response = client.get("https://test_url?a=æ°æ®")
+ assert response.content == b""
+
+
+def test_reset_is_removing_requests(httpx_mock: HTTPXMock) -> None:
+ httpx_mock.add_response()
+ with httpx.Client() as client:
+ client.get("https://test_url")
+
+ assert len(httpx_mock.get_requests()) == 1
+
+ httpx_mock.reset(assert_all_responses_were_requested=False)
+ assert len(httpx_mock.get_requests()) == 0