From 09c0087d0fd5f3fd28ea15ccbb785167f6ebea8d Mon Sep 17 00:00:00 2001 From: Aman Pandey Date: Wed, 31 Jul 2024 19:32:37 +0530 Subject: [PATCH 01/11] aprocess_request pattern in base panel class --- debug_toolbar/panels/__init__.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py index fd3312bc3..490dfcdf1 100644 --- a/debug_toolbar/panels/__init__.py +++ b/debug_toolbar/panels/__init__.py @@ -199,6 +199,18 @@ def get_server_timing_stats(self): # Standard middleware methods + async def aprocess_request(self, request): + """ + Asynchronous version of process_request. + + Additional asynchronous logic for Panels during the request/response + phase that could be needed to make the panel async capable. + + :param request: The current request as an ASGIRequest object. + + Return the existing response or overwrite it. + """ + def process_request(self, request): """ Like __call__ in Django's middleware. From 3b990c3c4ad52451753a11d1c41aac850a0c7e7a Mon Sep 17 00:00:00 2001 From: Aman Pandey Date: Wed, 31 Jul 2024 19:43:19 +0530 Subject: [PATCH 02/11] change doctstring --- debug_toolbar/panels/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py index 490dfcdf1..e3b1e2804 100644 --- a/debug_toolbar/panels/__init__.py +++ b/debug_toolbar/panels/__init__.py @@ -204,7 +204,7 @@ async def aprocess_request(self, request): Asynchronous version of process_request. Additional asynchronous logic for Panels during the request/response - phase that could be needed to make the panel async capable. + phase that could be needed to make the panel async compatible. :param request: The current request as an ASGIRequest object. From 8bc078439aa7792829e69748417234a2524da8f2 Mon Sep 17 00:00:00 2001 From: Aman Pandey Date: Wed, 31 Jul 2024 19:49:48 +0530 Subject: [PATCH 03/11] add docs --- debug_toolbar/panels/__init__.py | 3 +-- docs/panels.rst | 2 ++ 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py index e3b1e2804..3a135403e 100644 --- a/debug_toolbar/panels/__init__.py +++ b/debug_toolbar/panels/__init__.py @@ -203,8 +203,7 @@ async def aprocess_request(self, request): """ Asynchronous version of process_request. - Additional asynchronous logic for Panels during the request/response - phase that could be needed to make the panel async compatible. + Write panel logic related to async operations for async capable panels. :param request: The current request as an ASGIRequest object. diff --git a/docs/panels.rst b/docs/panels.rst index 7892dcf94..cfa5eddda 100644 --- a/docs/panels.rst +++ b/docs/panels.rst @@ -357,6 +357,8 @@ There is no public CSS API at this time. .. automethod:: debug_toolbar.panels.Panel.get_stats + .. automethod:: debug_toolbar.panels.Panel.aprocess_request + .. automethod:: debug_toolbar.panels.Panel.process_request .. automethod:: debug_toolbar.panels.Panel.generate_server_timing From b9218ca252a674308c61661c615cc52f527c2cde Mon Sep 17 00:00:00 2001 From: Aman Pandey Date: Wed, 31 Jul 2024 19:53:07 +0530 Subject: [PATCH 04/11] update docstring --- debug_toolbar/panels/__init__.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py index 3a135403e..f682bf5eb 100644 --- a/debug_toolbar/panels/__init__.py +++ b/debug_toolbar/panels/__init__.py @@ -203,7 +203,9 @@ async def aprocess_request(self, request): """ Asynchronous version of process_request. - Write panel logic related to async operations for async capable panels. + Write panel logic related to async operations like awaiting response + and perform logic over it when running in ASGI environment for async + capable panels. :param request: The current request as an ASGIRequest object. From 8d533112fa704cd8a0b8ceae87b25317931b9c3c Mon Sep 17 00:00:00 2001 From: Aman Pandey Date: Thu, 1 Aug 2024 21:22:54 +0530 Subject: [PATCH 05/11] make redirect panel async capable by using aprocess_request patterm --- debug_toolbar/panels/redirects.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/debug_toolbar/panels/redirects.py b/debug_toolbar/panels/redirects.py index 349564edb..5d4b3e6ed 100644 --- a/debug_toolbar/panels/redirects.py +++ b/debug_toolbar/panels/redirects.py @@ -1,3 +1,5 @@ +from inspect import iscoroutine + from django.template.response import SimpleTemplateResponse from django.utils.translation import gettext_lazy as _ @@ -9,13 +11,15 @@ class RedirectsPanel(Panel): Panel that intercepts redirects and displays a page with debug info. """ - is_async = False + is_async = True has_content = False nav_title = _("Intercept redirects") - def process_request(self, request): - response = super().process_request(request) + def _process_response(self, response): + """ + Common response processing logic. + """ if 300 <= response.status_code < 400: redirect_to = response.get("Location") if redirect_to: @@ -33,3 +37,13 @@ def process_request(self, request): response.cookies = cookies response.render() return response + + async def aprocess_request(self, request): + response = await super().process_request(request) + return self._process_response(response) + + def process_request(self, request): + response = super().process_request(request) + if iscoroutine(response): + return self.aprocess_request(request) + return self._process_response(response) From 003d70bec04eb4fe360bb2b23e532a85f1018a0e Mon Sep 17 00:00:00 2001 From: Aman Pandey Date: Sat, 3 Aug 2024 13:07:22 +0530 Subject: [PATCH 06/11] revert the base panel aprocess_request pattern --- debug_toolbar/panels/__init__.py | 13 ------------- docs/panels.rst | 2 -- 2 files changed, 15 deletions(-) diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py index f682bf5eb..fd3312bc3 100644 --- a/debug_toolbar/panels/__init__.py +++ b/debug_toolbar/panels/__init__.py @@ -199,19 +199,6 @@ def get_server_timing_stats(self): # Standard middleware methods - async def aprocess_request(self, request): - """ - Asynchronous version of process_request. - - Write panel logic related to async operations like awaiting response - and perform logic over it when running in ASGI environment for async - capable panels. - - :param request: The current request as an ASGIRequest object. - - Return the existing response or overwrite it. - """ - def process_request(self, request): """ Like __call__ in Django's middleware. diff --git a/docs/panels.rst b/docs/panels.rst index cfa5eddda..7892dcf94 100644 --- a/docs/panels.rst +++ b/docs/panels.rst @@ -357,8 +357,6 @@ There is no public CSS API at this time. .. automethod:: debug_toolbar.panels.Panel.get_stats - .. automethod:: debug_toolbar.panels.Panel.aprocess_request - .. automethod:: debug_toolbar.panels.Panel.process_request .. automethod:: debug_toolbar.panels.Panel.generate_server_timing From 1a2921f0226660e5b33d0d4f905f490c28926259 Mon Sep 17 00:00:00 2001 From: Aman Pandey Date: Sun, 4 Aug 2024 02:24:43 +0530 Subject: [PATCH 07/11] added async compability test for redirect panel --- tests/panels/test_redirects.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tests/panels/test_redirects.py b/tests/panels/test_redirects.py index 6b67e6f1d..2abed9fd0 100644 --- a/tests/panels/test_redirects.py +++ b/tests/panels/test_redirects.py @@ -2,6 +2,7 @@ from django.conf import settings from django.http import HttpResponse +from django.test import AsyncRequestFactory from ..base import BaseTestCase @@ -70,3 +71,17 @@ def test_insert_content(self): self.assertIsNotNone(response) response = self.panel.generate_stats(self.request, redirect) self.assertIsNone(response) + + async def test_async_compatibility(self): + redirect = HttpResponse(status=302) + + async def get_response(request): + return redirect + + await_response = await get_response(self.request) + self._get_response = get_response + + self.request = AsyncRequestFactory().get("/") + response = await self.panel.process_request(self.request) + self.assertIsInstance(response, HttpResponse) + self.assertTrue(response is await_response) From caa32d8a8ba820ea4a9c31617f6e497d8e8529b8 Mon Sep 17 00:00:00 2001 From: Aman Pandey Date: Sun, 4 Aug 2024 11:44:38 +0530 Subject: [PATCH 08/11] remove redundant call for super process_request --- debug_toolbar/panels/redirects.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/debug_toolbar/panels/redirects.py b/debug_toolbar/panels/redirects.py index 5d4b3e6ed..71c008f1b 100644 --- a/debug_toolbar/panels/redirects.py +++ b/debug_toolbar/panels/redirects.py @@ -38,12 +38,17 @@ def _process_response(self, response): response.render() return response - async def aprocess_request(self, request): - response = await super().process_request(request) + async def aprocess_request(self, request, response_coroutine): + """ + Async version of process_request. used for accessing the response + by awaiting it when running in ASGI. + """ + + response = await response_coroutine return self._process_response(response) def process_request(self, request): response = super().process_request(request) if iscoroutine(response): - return self.aprocess_request(request) + return self.aprocess_request(request, response) return self._process_response(response) From 5ca55d4d0e9f9234537c6f1e86526d409f1e2d40 Mon Sep 17 00:00:00 2001 From: Aman Pandey Date: Sun, 4 Aug 2024 11:52:30 +0530 Subject: [PATCH 09/11] added previous missing comment and modfied docs --- docs/architecture.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/architecture.rst b/docs/architecture.rst index 145676459..000e6345e 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -82,7 +82,7 @@ Problematic Parts - Support for async and multi-threading: ``debug_toolbar.middleware.DebugToolbarMiddleware`` is now async compatible and can process async requests. However certain panels such as ``SQLPanel``, ``TimerPanel``, ``StaticFilesPanel``, - ``RequestPanel``, ``RedirectsPanel`` and ``ProfilingPanel`` aren't fully + ``RequestPanel``and ``ProfilingPanel`` aren't fully compatible and currently being worked on. For now, these panels are disabled by default when running in async environment. follow the progress of this issue in `Async compatible toolbar project `_. From c9d34af6f5747b6ed174913a1d0ce4e983a7d253 Mon Sep 17 00:00:00 2001 From: Aman Pandey Date: Sun, 4 Aug 2024 11:54:07 +0530 Subject: [PATCH 10/11] add space in docs --- docs/architecture.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/architecture.rst b/docs/architecture.rst index 000e6345e..c49bfef0f 100644 --- a/docs/architecture.rst +++ b/docs/architecture.rst @@ -82,7 +82,7 @@ Problematic Parts - Support for async and multi-threading: ``debug_toolbar.middleware.DebugToolbarMiddleware`` is now async compatible and can process async requests. However certain panels such as ``SQLPanel``, ``TimerPanel``, ``StaticFilesPanel``, - ``RequestPanel``and ``ProfilingPanel`` aren't fully + ``RequestPanel`` and ``ProfilingPanel`` aren't fully compatible and currently being worked on. For now, these panels are disabled by default when running in async environment. follow the progress of this issue in `Async compatible toolbar project `_. From 60b742c4fd102d4ac8de9d73b1c999bb60a4844e Mon Sep 17 00:00:00 2001 From: Tim Schilling Date: Tue, 6 Aug 2024 07:03:41 -0500 Subject: [PATCH 11/11] Add change log. --- docs/changes.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/changes.rst b/docs/changes.rst index d867b7d80..d4a81ffca 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -8,6 +8,7 @@ Pending * Fixed internal toolbar requests being instrumented if the Django setting ``FORCE_SCRIPT_NAME`` was set. * Increase opacity of show Debug Toolbar handle to improve accessibility. +* Changed the ``RedirectsPanel`` to be async compatible. 4.4.6 (2024-07-10) ------------------