From af96ce8a4f00441c3aeb532d739c1175b2096a2a Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Mon, 24 Apr 2023 12:25:20 +0200 Subject: [PATCH 1/4] feat: integer repeat --- AUTHORS.rst | 2 +- README.rst | 6 ++++-- aioresponses/core.py | 8 ++++++-- tests/test_aioresponses.py | 9 +++++++++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/AUTHORS.rst b/AUTHORS.rst index 3b1fc8e..2d7fbcd 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -10,4 +10,4 @@ Development Lead Contributors ------------ -None yet. Why not be the first? +* Felix Claessen diff --git a/README.rst b/README.rst index 77b6687..bd1bdcf 100644 --- a/README.rst +++ b/README.rst @@ -152,14 +152,16 @@ E.g. for cases you want to test retrying mechanisms def test_multiple_responses(m): loop = asyncio.get_event_loop() session = aiohttp.ClientSession() - m.get('http://example.com', status=500, repeat=True) - m.get('http://example.com', status=200) # will not take effect + m.get('http://example.com', status=500, repeat=2) + m.get('http://example.com', status=200) # will take effect after two preceding calls resp1 = loop.run_until_complete(session.get('http://example.com')) resp2 = loop.run_until_complete(session.get('http://example.com')) + resp3 = loop.run_until_complete(session.get('http://example.com')) assert resp1.status == 500 assert resp2.status == 500 + assert resp3.status == 200 **match URLs with regular expressions** diff --git a/aioresponses/core.py b/aioresponses/core.py index 6eafff3..7f1f11c 100644 --- a/aioresponses/core.py +++ b/aioresponses/core.py @@ -78,7 +78,7 @@ def __init__(self, url: Union[URL, str, Pattern], content_type: str = 'application/json', response_class: Optional[Type[ClientResponse]] = None, timeout: bool = False, - repeat: bool = False, + repeat: Union[bool, int] = False, reason: Optional[str] = None, callback: Optional[Callable] = None): if isinstance(url, Pattern): @@ -313,7 +313,7 @@ def add(self, url: 'Union[URL, str, Pattern]', method: str = hdrs.METH_GET, payload: Optional[Dict] = None, headers: Optional[Dict] = None, response_class: Optional[Type[ClientResponse]] = None, - repeat: bool = False, + repeat: Union[bool, int] = False, timeout: bool = False, reason: Optional[str] = None, callback: Optional[Callable] = None) -> None: @@ -471,6 +471,10 @@ async def match( if matcher.repeat is False: del self._matches[key] + elif matcher.repeat == 2: + matcher.repeat = False + elif isinstance(matcher.repeat, int): + matcher.repeat -= 1 if self.is_exception(response_or_exc): raise response_or_exc diff --git a/tests/test_aioresponses.py b/tests/test_aioresponses.py index d0b150c..0d37ef7 100644 --- a/tests/test_aioresponses.py +++ b/tests/test_aioresponses.py @@ -581,6 +581,15 @@ async def test_assert_called_twice(self, m: aioresponses): with self.assertRaises(AssertionError): m.assert_called_once() + @aioresponses() + async def test_integer_repeat(self, m: aioresponses): + m.get(self.url, repeat=2) + m.assert_not_called() + await self.session.get(self.url) + await self.session.get(self.url) + with self.assertRaises(ClientConnectionError): + await self.session.get(self.url) + @aioresponses() async def test_assert_any_call(self, m: aioresponses): http_bin_url = "http://httpbin.org" From 7f611b5fceb53799579af6867959f612da46c7aa Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Fri, 8 Sep 2023 20:58:00 +0200 Subject: [PATCH 2/4] fix: case repeat=1 Signed-off-by: F.N. Claessen --- aioresponses/core.py | 2 +- tests/test_aioresponses.py | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/aioresponses/core.py b/aioresponses/core.py index 7f1f11c..fdc3d6a 100644 --- a/aioresponses/core.py +++ b/aioresponses/core.py @@ -469,7 +469,7 @@ async def match( else: return None - if matcher.repeat is False: + if matcher.repeat in (False, 1): del self._matches[key] elif matcher.repeat == 2: matcher.repeat = False diff --git a/tests/test_aioresponses.py b/tests/test_aioresponses.py index 0d37ef7..2a3a86b 100644 --- a/tests/test_aioresponses.py +++ b/tests/test_aioresponses.py @@ -582,7 +582,15 @@ async def test_assert_called_twice(self, m: aioresponses): m.assert_called_once() @aioresponses() - async def test_integer_repeat(self, m: aioresponses): + async def test_integer_repeat_once(self, m: aioresponses): + m.get(self.url, repeat=1) + m.assert_not_called() + await self.session.get(self.url) + with self.assertRaises(ClientConnectionError): + await self.session.get(self.url) + + @aioresponses() + async def test_integer_repeat_twice(self, m: aioresponses): m.get(self.url, repeat=2) m.assert_not_called() await self.session.get(self.url) From 149a8339607316b83b78f823233b5ad00f2232e2 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Fri, 8 Sep 2023 21:09:18 +0200 Subject: [PATCH 3/4] docs: elaborate on meaning in documentation of repeat argument Signed-off-by: F.N. Claessen --- README.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.rst b/README.rst index bd1bdcf..be8aa75 100644 --- a/README.rst +++ b/README.rst @@ -140,7 +140,11 @@ for convenience use *payload* argument to mock out json response. Example below. **Repeat response for the same url** -E.g. for cases you want to test retrying mechanisms +E.g. for cases where you want to test retrying mechanisms. + +- By default, ``repeat=False`` means the response is not repeated (``repeat=1`` does the same). +- Use ``repeat=n`` to repeat a response n times. +- Use ``repeat=True`` to repeat a response indefinitely. .. code:: python From 9b0f325b5c1d6645f269e95c118a833fb18f6260 Mon Sep 17 00:00:00 2001 From: "F.N. Claessen" Date: Fri, 10 May 2024 11:16:31 +0200 Subject: [PATCH 4/4] fix: review suggestion --- aioresponses/core.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/aioresponses/core.py b/aioresponses/core.py index fdc3d6a..1d5f6fd 100644 --- a/aioresponses/core.py +++ b/aioresponses/core.py @@ -469,11 +469,12 @@ async def match( else: return None - if matcher.repeat in (False, 1): - del self._matches[key] - elif matcher.repeat == 2: - matcher.repeat = False - elif isinstance(matcher.repeat, int): + if isinstance(matcher.repeat, bool): + if not matcher.repeat: + del self._matches[key] + else: + if matcher.repeat == 1: + del self._matches[key] matcher.repeat -= 1 if self.is_exception(response_or_exc):