From 6cb639645415b7e1288e9d5becb92c53e6f06b56 Mon Sep 17 00:00:00 2001 From: Aman Pandey Date: Tue, 20 Aug 2024 23:58:07 +0530 Subject: [PATCH 1/4] ASGI check approach with added test and docs --- debug_toolbar/toolbar.py | 15 +++++++++------ docs/architecture.rst | 2 +- tests/test_integration.py | 18 +++++++++++++++++- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/debug_toolbar/toolbar.py b/debug_toolbar/toolbar.py index 35d789a53..921546aaf 100644 --- a/debug_toolbar/toolbar.py +++ b/debug_toolbar/toolbar.py @@ -12,6 +12,7 @@ from django.apps import apps from django.conf import settings from django.core.exceptions import ImproperlyConfigured +from django.core.handlers.asgi import ASGIRequest from django.dispatch import Signal from django.template import TemplateSyntaxError from django.template.loader import render_to_string @@ -101,12 +102,14 @@ def should_render_panels(self): If False, the panels will be loaded via Ajax. """ if (render_panels := self.config["RENDER_PANELS"]) is None: - # If wsgi.multiprocess isn't in the headers, then it's likely - # being served by ASGI. This type of set up is most likely - # incompatible with the toolbar until - # https://github.com/jazzband/django-debug-toolbar/issues/1430 - # is resolved. - render_panels = self.request.META.get("wsgi.multiprocess", True) + # If wsgi.multiprocess is true then it is either being served + # from ASGI or multithreaded third-party WSGI server eg gunicorn. + # we need to make special handling for ASGI for supporting + # async context based requests. + if isinstance(self.request, ASGIRequest): + render_panels = False + else: + render_panels = self.request.META.get("wsgi.multiprocess", True) return render_panels # Handle storing toolbars in memory and fetching them later on diff --git a/docs/architecture.rst b/docs/architecture.rst index 0043f5153..cf5c54951 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``, - ``RequestPanel``, ``HistoryPanel`` 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 `_. diff --git a/tests/test_integration.py b/tests/test_integration.py index df276d90c..ca31a294c 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -11,7 +11,7 @@ from django.db import connection from django.http import HttpResponse from django.template.loader import get_template -from django.test import RequestFactory +from django.test import AsyncRequestFactory, RequestFactory from django.test.utils import override_settings from debug_toolbar.forms import SignedDataForm @@ -126,6 +126,22 @@ def test_should_render_panels_multiprocess(self): request.META.pop("wsgi.multiprocess") self.assertTrue(toolbar.should_render_panels()) + def test_should_render_panels_asgi(self): + """ + The toolbar not should render the panels on each request when wsgi.multiprocess + is True or missing in case of async context rather than multithreaded + wsgi. + """ + async_request = AsyncRequestFactory().get("/") + # by default ASGIRequest will have wsgi.multiprocess set to True + # but we are still assigning this to true cause this could change + # and we specifically need to check that method returns false even with + # wsgi.multiprocess set to true + async_request.META["wsgi.multiprocess"] = True + toolbar = DebugToolbar(async_request, self.get_response) + toolbar.config["RENDER_PANELS"] = None + self.assertFalse(toolbar.should_render_panels()) + def _resolve_stats(self, path): # takes stats from Request panel request = rf.get(path) From 830c9641d1b4b9b196198d53eca8accee8d3e319 Mon Sep 17 00:00:00 2001 From: Aman Pandey Date: Wed, 21 Aug 2024 00:02:52 +0530 Subject: [PATCH 2/4] revert changes --- debug_toolbar/toolbar.py | 15 ++++++--------- docs/architecture.rst | 2 +- tests/test_integration.py | 18 +----------------- 3 files changed, 8 insertions(+), 27 deletions(-) diff --git a/debug_toolbar/toolbar.py b/debug_toolbar/toolbar.py index 921546aaf..35d789a53 100644 --- a/debug_toolbar/toolbar.py +++ b/debug_toolbar/toolbar.py @@ -12,7 +12,6 @@ from django.apps import apps from django.conf import settings from django.core.exceptions import ImproperlyConfigured -from django.core.handlers.asgi import ASGIRequest from django.dispatch import Signal from django.template import TemplateSyntaxError from django.template.loader import render_to_string @@ -102,14 +101,12 @@ def should_render_panels(self): If False, the panels will be loaded via Ajax. """ if (render_panels := self.config["RENDER_PANELS"]) is None: - # If wsgi.multiprocess is true then it is either being served - # from ASGI or multithreaded third-party WSGI server eg gunicorn. - # we need to make special handling for ASGI for supporting - # async context based requests. - if isinstance(self.request, ASGIRequest): - render_panels = False - else: - render_panels = self.request.META.get("wsgi.multiprocess", True) + # If wsgi.multiprocess isn't in the headers, then it's likely + # being served by ASGI. This type of set up is most likely + # incompatible with the toolbar until + # https://github.com/jazzband/django-debug-toolbar/issues/1430 + # is resolved. + render_panels = self.request.META.get("wsgi.multiprocess", True) return render_panels # Handle storing toolbars in memory and fetching them later on diff --git a/docs/architecture.rst b/docs/architecture.rst index cf5c54951..0043f5153 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``, - ``RequestPanel`` and ``ProfilingPanel`` aren't fully + ``RequestPanel``, ``HistoryPanel`` 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 `_. diff --git a/tests/test_integration.py b/tests/test_integration.py index ca31a294c..df276d90c 100644 --- a/tests/test_integration.py +++ b/tests/test_integration.py @@ -11,7 +11,7 @@ from django.db import connection from django.http import HttpResponse from django.template.loader import get_template -from django.test import AsyncRequestFactory, RequestFactory +from django.test import RequestFactory from django.test.utils import override_settings from debug_toolbar.forms import SignedDataForm @@ -126,22 +126,6 @@ def test_should_render_panels_multiprocess(self): request.META.pop("wsgi.multiprocess") self.assertTrue(toolbar.should_render_panels()) - def test_should_render_panels_asgi(self): - """ - The toolbar not should render the panels on each request when wsgi.multiprocess - is True or missing in case of async context rather than multithreaded - wsgi. - """ - async_request = AsyncRequestFactory().get("/") - # by default ASGIRequest will have wsgi.multiprocess set to True - # but we are still assigning this to true cause this could change - # and we specifically need to check that method returns false even with - # wsgi.multiprocess set to true - async_request.META["wsgi.multiprocess"] = True - toolbar = DebugToolbar(async_request, self.get_response) - toolbar.config["RENDER_PANELS"] = None - self.assertFalse(toolbar.should_render_panels()) - def _resolve_stats(self, path): # takes stats from Request panel request = rf.get(path) From 04b3aace5a1448df05348a8d1913cca90093781f Mon Sep 17 00:00:00 2001 From: Aman Pandey Date: Thu, 24 Oct 2024 23:28:50 +0530 Subject: [PATCH 3/4] Update warning at installation doc --- docs/installation.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/installation.rst b/docs/installation.rst index 6e301cb8b..5b371fba7 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -9,7 +9,8 @@ fully functional. .. warning:: - The Debug Toolbar does not currently support `Django's asynchronous views `_. + The Debug Toolbar now supports `Django's asynchronous views `_ and ASGI enviroment, but + still lacks the capability for handling concurrent requests. 1. Install the Package ^^^^^^^^^^^^^^^^^^^^^^ From 96912507f9870cc35bcd4e873cb853d1764f264c Mon Sep 17 00:00:00 2001 From: Aman Pandey Date: Fri, 25 Oct 2024 01:15:49 +0530 Subject: [PATCH 4/4] fix typo --- docs/installation.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.rst b/docs/installation.rst index 5b371fba7..ebe95bf3c 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -9,7 +9,7 @@ fully functional. .. warning:: - The Debug Toolbar now supports `Django's asynchronous views `_ and ASGI enviroment, but + The Debug Toolbar now supports `Django's asynchronous views `_ and ASGI environment, but still lacks the capability for handling concurrent requests. 1. Install the Package