From 4ed7d99df7aa0ac5d49b08998e513bdc55e3adb9 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Thu, 4 Mar 2021 13:48:20 +0000 Subject: [PATCH 01/19] Update unittest docs --- docs/testing.rst | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/docs/testing.rst b/docs/testing.rst index d722f3aef39..ffdd31c955d 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -243,7 +243,7 @@ Unittest To test applications with the standard library's unittest or unittest-based functionality, the AioHTTPTestCase is provided:: - from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop + from aiohttp.test_utils import AioHTTPTestCase from aiohttp import web class MyAppTestCase(AioHTTPTestCase): @@ -259,26 +259,11 @@ functionality, the AioHTTPTestCase is provided:: app.router.add_get('/', hello) return app - # the unittest_run_loop decorator can be used in tandem with - # the AioHTTPTestCase to simplify running - # tests that are asynchronous - @unittest_run_loop async def test_example(self): - resp = await self.client.request("GET", "/") - assert resp.status == 200 - text = await resp.text() - assert "Hello, world" in text - - # a vanilla example - def test_example_vanilla(self): - async def test_get_route(): - url = "/" - resp = await self.client.request("GET", url) + async with self.client.request("GET", "/") as resp: assert resp.status == 200 text = await resp.text() - assert "Hello, world" in text - - self.loop.run_until_complete(test_get_route()) + assert "Hello, world" in text .. class:: AioHTTPTestCase @@ -361,16 +346,14 @@ functionality, the AioHTTPTestCase is provided:: .. note:: The ``TestClient``'s methods are asynchronous: you have to - execute function on the test client using asynchronous methods. - - A basic test class wraps every test method by - :func:`unittest_run_loop` decorator:: + execute functions on the test client using asynchronous methods. class TestA(AioHTTPTestCase): @unittest_run_loop async def test_f(self): - resp = await self.client.get('/') + async with self.client.get('/') as resp: + body = await resp.text() .. decorator:: unittest_run_loop: @@ -381,6 +364,10 @@ functionality, the AioHTTPTestCase is provided:: Handles executing an asynchronous function, using the :attr:`AioHTTPTestCase.loop` of the :class:`AioHTTPTestCase`. + .. deprecated:: 3.8 + In 3.8+ :class:`AioHTTPTestCase` inherits from :class:`unittest.IsolatedAsyncioTestCase` + making this decorator unneeded. + Faking request object --------------------- From 92ca9bee5f267e881a554c68f6dc7044ac38ef58 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Thu, 4 Mar 2021 13:53:33 +0000 Subject: [PATCH 02/19] Deprecate decorator code --- aiohttp/test_utils.py | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py index 20abe2c8088..7ee3e5f4496 100644 --- a/aiohttp/test_utils.py +++ b/aiohttp/test_utils.py @@ -8,6 +8,7 @@ import os import socket import sys +import warnings from abc import ABC, abstractmethod from types import TracebackType from typing import ( @@ -472,17 +473,12 @@ async def get_client(self, server: TestServer) -> TestClient: def unittest_run_loop(func: Any, *args: Any, **kwargs: Any) -> Any: """A decorator dedicated to use with asynchronous methods of an - AioHTTPTestCase. - - Handles executing an asynchronous function, using - the self.loop of the AioHTTPTestCase. + AioHTTPTestCase in aiohttp <3.7. + + In 3.8+, this does nothing. """ - - @functools.wraps(func, *args, **kwargs) - def new_func(self: Any, *inner_args: Any, **inner_kwargs: Any) -> Any: - return self.loop.run_until_complete(func(self, *inner_args, **inner_kwargs)) - - return new_func + warnings.warn("Decorator no longer needed in 3.8+", DeprecationWarning) + return func _LOOP_FACTORY = Callable[[], asyncio.AbstractEventLoop] From fdea1ccfcc910ce53e5624fcfdaff0848876e5b0 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Thu, 4 Mar 2021 13:54:39 +0000 Subject: [PATCH 03/19] Create 5515.misc --- CHANGES/5515.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 CHANGES/5515.misc diff --git a/CHANGES/5515.misc b/CHANGES/5515.misc new file mode 100644 index 00000000000..5f5aed29978 --- /dev/null +++ b/CHANGES/5515.misc @@ -0,0 +1 @@ +Deprecate @unittest_run_loop. This behaviour is now the default. From 7f791c2a28507d6d82825f12825190683d1064d4 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Thu, 4 Mar 2021 13:56:25 +0000 Subject: [PATCH 04/19] Update test_utils.py --- aiohttp/test_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py index 7ee3e5f4496..978198e12a4 100644 --- a/aiohttp/test_utils.py +++ b/aiohttp/test_utils.py @@ -473,7 +473,7 @@ async def get_client(self, server: TestServer) -> TestClient: def unittest_run_loop(func: Any, *args: Any, **kwargs: Any) -> Any: """A decorator dedicated to use with asynchronous methods of an - AioHTTPTestCase in aiohttp <3.7. + AioHTTPTestCase in aiohttp <3.8. In 3.8+, this does nothing. """ From d621e2a93bf9df4fc92cf617cc8aa489005a8f64 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Thu, 4 Mar 2021 13:59:20 +0000 Subject: [PATCH 05/19] Whitespace --- aiohttp/test_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py index 978198e12a4..0f3994e859f 100644 --- a/aiohttp/test_utils.py +++ b/aiohttp/test_utils.py @@ -474,7 +474,7 @@ async def get_client(self, server: TestServer) -> TestClient: def unittest_run_loop(func: Any, *args: Any, **kwargs: Any) -> Any: """A decorator dedicated to use with asynchronous methods of an AioHTTPTestCase in aiohttp <3.8. - + In 3.8+, this does nothing. """ warnings.warn("Decorator no longer needed in 3.8+", DeprecationWarning) From 8ce05e13bca430f20547b7266e4e3179a9f3eb36 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Thu, 4 Mar 2021 14:06:16 +0000 Subject: [PATCH 06/19] Redundant import --- aiohttp/test_utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py index 0f3994e859f..c48dc94df05 100644 --- a/aiohttp/test_utils.py +++ b/aiohttp/test_utils.py @@ -2,7 +2,6 @@ import asyncio import contextlib -import functools import gc import inspect import os From 451231df878e5b9def69ce14adcc37209e7063a1 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Thu, 4 Mar 2021 14:13:39 +0000 Subject: [PATCH 07/19] Update testing.rst --- docs/testing.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/testing.rst b/docs/testing.rst index ffdd31c955d..077e5e887d7 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -350,7 +350,6 @@ functionality, the AioHTTPTestCase is provided:: class TestA(AioHTTPTestCase): - @unittest_run_loop async def test_f(self): async with self.client.get('/') as resp: body = await resp.text() From f94b6599ee8cc6ec60f51f3191c5d3fe1cb1c4ea Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Thu, 4 Mar 2021 14:18:39 +0000 Subject: [PATCH 08/19] Use correct unittest methods. --- docs/testing.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/testing.rst b/docs/testing.rst index 077e5e887d7..6ac6270bea1 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -261,9 +261,9 @@ functionality, the AioHTTPTestCase is provided:: async def test_example(self): async with self.client.request("GET", "/") as resp: - assert resp.status == 200 + self.assertEqual(resp.status, 200) text = await resp.text() - assert "Hello, world" in text + self.assertIn("Hello, world", text) .. class:: AioHTTPTestCase From 1d19e71b69f3fc42bd79f4d2660111be679fe2e8 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Thu, 4 Mar 2021 14:23:24 +0000 Subject: [PATCH 09/19] Update testing.rst --- docs/testing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/testing.rst b/docs/testing.rst index 6ac6270bea1..a0fff9e6e0c 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -346,7 +346,7 @@ functionality, the AioHTTPTestCase is provided:: .. note:: The ``TestClient``'s methods are asynchronous: you have to - execute functions on the test client using asynchronous methods. + execute functions on the test client using asynchronous methods.:: class TestA(AioHTTPTestCase): From a2f26e511f9f2d607c0edcedd51dc9e94c9cb9d1 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Thu, 4 Mar 2021 14:33:29 +0000 Subject: [PATCH 10/19] Update test_loop.py --- tests/test_loop.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_loop.py b/tests/test_loop.py index 24c979ebd55..914b8f1fc4d 100644 --- a/tests/test_loop.py +++ b/tests/test_loop.py @@ -5,7 +5,7 @@ import pytest from aiohttp import web -from aiohttp.test_utils import AioHTTPTestCase, unittest_run_loop +from aiohttp.test_utils import AioHTTPTestCase @pytest.mark.skipif( @@ -31,7 +31,6 @@ async def get_application(self): async def on_startup_hook(self, app): self.on_startup_called = True - @unittest_run_loop async def test_on_startup_hook(self) -> None: self.assertTrue(self.on_startup_called) From 0616fc8a3a69480c884f1f1efcd58b9399c8da91 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Thu, 4 Mar 2021 15:34:01 +0000 Subject: [PATCH 11/19] Adjust stacklevel --- aiohttp/test_utils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py index c48dc94df05..4f794dafe0a 100644 --- a/aiohttp/test_utils.py +++ b/aiohttp/test_utils.py @@ -476,7 +476,9 @@ def unittest_run_loop(func: Any, *args: Any, **kwargs: Any) -> Any: In 3.8+, this does nothing. """ - warnings.warn("Decorator no longer needed in 3.8+", DeprecationWarning) + warnings.warn( + "Decorator no longer needed in 3.8+", DeprecationWarning, stacklever=2 + ) return func From 62f91fef1cb8f502f6320bcac8d95086b279f519 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Thu, 4 Mar 2021 15:39:15 +0000 Subject: [PATCH 12/19] Update test_utils.py --- aiohttp/test_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py index 4f794dafe0a..df80a9498e0 100644 --- a/aiohttp/test_utils.py +++ b/aiohttp/test_utils.py @@ -477,7 +477,7 @@ def unittest_run_loop(func: Any, *args: Any, **kwargs: Any) -> Any: In 3.8+, this does nothing. """ warnings.warn( - "Decorator no longer needed in 3.8+", DeprecationWarning, stacklever=2 + "Decorator no longer needed in 3.8+", DeprecationWarning, stacklevel=2 ) return func From f05401e1519e6a721f2ce6779ecec6758416c867 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Thu, 4 Mar 2021 16:55:41 +0000 Subject: [PATCH 13/19] Test deprecation warning. --- tests/test_test_utils.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/test_test_utils.py b/tests/test_test_utils.py index c268e71073f..ab2a37e7b10 100644 --- a/tests/test_test_utils.py +++ b/tests/test_test_utils.py @@ -102,7 +102,6 @@ class TestAioHTTPTestCase(AioHTTPTestCase): def get_app(self): return _create_example_app() - @unittest_run_loop async def test_example_with_loop(self) -> None: request = await self.client.request("GET", "/") assert request.status == 200 @@ -134,6 +133,13 @@ async def test_get_route() -> None: await test_get_route() +def test_unittest_run_loop() -> None: + with pytest.warns(DeprecationWarning): + @unittest_run_loop + def foo(): + pass + + def test_get_route(loop, test_client) -> None: async def test_get_route() -> None: resp = await test_client.request("GET", "/") From 7d321ab98c7d8d3c8119d80c5d790a1e72a0d119 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Thu, 4 Mar 2021 16:57:49 +0000 Subject: [PATCH 14/19] Update test_test_utils.py --- tests/test_test_utils.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_test_utils.py b/tests/test_test_utils.py index ab2a37e7b10..198a84222ab 100644 --- a/tests/test_test_utils.py +++ b/tests/test_test_utils.py @@ -135,6 +135,7 @@ async def test_get_route() -> None: def test_unittest_run_loop() -> None: with pytest.warns(DeprecationWarning): + @unittest_run_loop def foo(): pass From c1ecdaad94922b4db7dc5bdc42d060c18a72f972 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Fri, 5 Mar 2021 00:59:25 +0100 Subject: [PATCH 15/19] Mark `@unittest_run_loop` as code in changelog --- CHANGES/5515.misc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES/5515.misc b/CHANGES/5515.misc index 5f5aed29978..e3d810b17f6 100644 --- a/CHANGES/5515.misc +++ b/CHANGES/5515.misc @@ -1 +1 @@ -Deprecate @unittest_run_loop. This behaviour is now the default. +Deprecate ``@unittest_run_loop``. This behaviour is now the default. From e50bbcd2d0e305911949786b7120cbbd13c3a5a6 Mon Sep 17 00:00:00 2001 From: Sam Bull Date: Fri, 5 Mar 2021 10:50:02 +0000 Subject: [PATCH 16/19] Update tests/test_test_utils.py Co-authored-by: Sviatoslav Sydorenko --- tests/test_test_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_test_utils.py b/tests/test_test_utils.py index 198a84222ab..12c34394d00 100644 --- a/tests/test_test_utils.py +++ b/tests/test_test_utils.py @@ -134,7 +134,7 @@ async def test_get_route() -> None: def test_unittest_run_loop() -> None: - with pytest.warns(DeprecationWarning): + with pytest.warns(DeprecationWarning, match=r"Decorator no longer needed in 3\.8\+"): @unittest_run_loop def foo(): From c30fe360f8bef7a51b7f86b8e37969785f92676e Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Fri, 5 Mar 2021 14:56:27 +0100 Subject: [PATCH 17/19] Make `@unittest_run_loop` deprecation message more specific --- aiohttp/test_utils.py | 3 ++- tests/test_test_utils.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py index df80a9498e0..514f1dd0344 100644 --- a/aiohttp/test_utils.py +++ b/aiohttp/test_utils.py @@ -477,7 +477,8 @@ def unittest_run_loop(func: Any, *args: Any, **kwargs: Any) -> Any: In 3.8+, this does nothing. """ warnings.warn( - "Decorator no longer needed in 3.8+", DeprecationWarning, stacklevel=2 + "Decorator `@unittest_run_loop` is no longer needed in aiohttp 3.8+", DeprecationWarning, + stacklevel=2, ) return func diff --git a/tests/test_test_utils.py b/tests/test_test_utils.py index 12c34394d00..2e9b5c9e86d 100644 --- a/tests/test_test_utils.py +++ b/tests/test_test_utils.py @@ -134,7 +134,7 @@ async def test_get_route() -> None: def test_unittest_run_loop() -> None: - with pytest.warns(DeprecationWarning, match=r"Decorator no longer needed in 3\.8\+"): + with pytest.warns(DeprecationWarning, match=r"Decorator `@unittest_run_loop` is no longer needed in aiohttp 3\.8\+"): @unittest_run_loop def foo(): From 011de7efd51ccb7795db8415ecac243864929e27 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Fri, 5 Mar 2021 14:58:01 +0100 Subject: [PATCH 18/19] Document that the `@unittest_run_loop` decorator is no-op --- docs/testing.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/testing.rst b/docs/testing.rst index a0fff9e6e0c..1cf316a3965 100644 --- a/docs/testing.rst +++ b/docs/testing.rst @@ -365,7 +365,7 @@ functionality, the AioHTTPTestCase is provided:: .. deprecated:: 3.8 In 3.8+ :class:`AioHTTPTestCase` inherits from :class:`unittest.IsolatedAsyncioTestCase` - making this decorator unneeded. + making this decorator unneeded. It is now a no-op. Faking request object From 223fe697c815c547d19b723cbe12a958aebf14d3 Mon Sep 17 00:00:00 2001 From: Sviatoslav Sydorenko Date: Fri, 5 Mar 2021 14:59:52 +0100 Subject: [PATCH 19/19] Format the lines to be shorter --- aiohttp/test_utils.py | 3 ++- tests/test_test_utils.py | 5 ++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py index 514f1dd0344..4cb70c8cb22 100644 --- a/aiohttp/test_utils.py +++ b/aiohttp/test_utils.py @@ -477,7 +477,8 @@ def unittest_run_loop(func: Any, *args: Any, **kwargs: Any) -> Any: In 3.8+, this does nothing. """ warnings.warn( - "Decorator `@unittest_run_loop` is no longer needed in aiohttp 3.8+", DeprecationWarning, + "Decorator `@unittest_run_loop` is no longer needed in aiohttp 3.8+", + DeprecationWarning, stacklevel=2, ) return func diff --git a/tests/test_test_utils.py b/tests/test_test_utils.py index 2e9b5c9e86d..d393834927f 100644 --- a/tests/test_test_utils.py +++ b/tests/test_test_utils.py @@ -134,7 +134,10 @@ async def test_get_route() -> None: def test_unittest_run_loop() -> None: - with pytest.warns(DeprecationWarning, match=r"Decorator `@unittest_run_loop` is no longer needed in aiohttp 3\.8\+"): + with pytest.warns( + DeprecationWarning, + match=r"Decorator `@unittest_run_loop` is no longer needed in aiohttp 3\.8\+", + ): @unittest_run_loop def foo():