Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async compatible debug-toolbar middleware #1938

Merged
merged 1 commit into from
Jul 16, 2024

Conversation

salty-ivy
Copy link
Member

@salty-ivy salty-ivy commented Jun 24, 2024

Description

GSoC 2024

This PR aims to add async compatibility in django-debug-toolbar middleware

Fixes # (issue)

Checklist:

  • I have added the relevant tests for this change.
  • I have added an item to the Pending section of docs/changes.rst.

Copy link
Member

@matthiask matthiask left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

debug_toolbar/middleware.py Outdated Show resolved Hide resolved
debug_toolbar/middleware.py Outdated Show resolved Hide resolved
@salty-ivy salty-ivy requested a review from matthiask June 26, 2024 15:00
Copy link
Member

@matthiask matthiask left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. I wonder how the panels can differentiate in process_request between the sync and async version. Also, awaiting def process_request (NOT async def process_request) looks a bit strange, but seems fine to me after thinking about it a bit.

@salty-ivy
Copy link
Member Author

salty-ivy commented Jun 26, 2024

LGTM. I wonder how the panels can differentiate in process_request between the sync and async version.

panels would receive either WSGIRequest or ASGIRequest ( not async ) instance which are subclasses of HttpRequest.

Also, awaiting def process_request (NOT async def process_request) looks a bit strange, but seems fine to me after thinking about it a bit.

process_request call of panels would ultimately reach down to view via chain of calls of both panels and then middlewares, the response will always be adapted to async by adapt_method_mode that has to be awaited.

https://github.com/django/django/blob/e56a32b89bb7fadffdfaa2cdf12b4863ccd5af9b/django/core/handlers/base.py#L104

it even adapts the view if its not async def the response will be adapted to async coroutines if the receiving middleware is async and we are running in async context ( if both conditions are true ).

https://github.com/django/django/blob/e56a32b89bb7fadffdfaa2cdf12b4863ccd5af9b/django/core/handlers/base.py#L54

this is my overall understanding so far.

Copy link
Contributor

@tim-schilling tim-schilling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is coming along nicely! Thank you for all your work. I have a few comments on particular aspects. We also need to document the new panel API before this can be merged in.

tests/panels/test_async_panel_compatibility.py Outdated Show resolved Hide resolved
tests/test_middleware_compatibility.py Show resolved Hide resolved
tests/test_middleware_compatibility.py Outdated Show resolved Hide resolved
tests/test_middleware_compatibility.py Outdated Show resolved Hide resolved
tests/panels/test_async_panel_compatibility.py Outdated Show resolved Hide resolved
@salty-ivy
Copy link
Member Author

I have changed the approach to test async panel compatibility tests.

Copy link
Contributor

@tim-schilling tim-schilling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code-wise, this is great! Thank you Aman. I think we need to update the docs in two areas:

  1. Change Panel.is_async to a @property method with a doc string, then update https://github.com/jazzband/django-debug-toolbar/blob/main/docs/panels.rst?plain=1#L332 to include that attribute in the documentation.
  2. Update the architecture document here:
    - Support for async and multi-threading: This is currently unsupported, but
    is being implemented as per the
    `Async compatible toolbar project <https://github.com/orgs/jazzband/projects/9>`_.

@salty-ivy
Copy link
Member Author

  1. Change Panel.is_async to a @property method with a doc string, then update https://github.com/jazzband/django-debug-toolbar/blob/main/docs/panels.rst?plain=1#L332 to

Sorry for the nit pick question but should we use @classproperty or @property with class level private attribute _is_async? my main idea is that is should be class level we might need to access it in future directly via class and makes subclassing easy

@tim-schilling
Copy link
Contributor

Not a nitpick at all. It's a good question @salty-ivy! My instinct is to go with @property to be consistent with the others. @matthiask thoughts?

@matthiask
Copy link
Member

Autogenerating documentation from code is always a workaround for lazyness (I like it a lot!) but I'm not sure we should uglify the code just for that.

I thought that adding a #: comment above a property would also act as a docstring by the way, so that we could keep the attribute?

@tim-schilling
Copy link
Contributor

TIL, then let's go with what Matthias suggested. Thank you for pointing that out

@matthiask
Copy link
Member

If you search this page for #: you'll find examples:
https://www.sphinx-doc.org/en/master/usage/extensions/autodoc.html#directive-autoproperty

So, if the autodoc support is the only reason for converting the attribute to a property I think I'm -0 on it. No strong opposition certainly, I just don't see the need for it.

@tim-schilling
Copy link
Contributor

I wanted the autodoc and then thought it would bring consistency to the API. Though you and @salty-ivy both questioning it is enough for me to agree to having it as an attribute.

@salty-ivy
Copy link
Member Author

  1. Update the architecture document here:
    - Support for async and multi-threading: This is currently unsupported, but
    is being implemented as per the
    `Async compatible toolbar project <https://github.com/orgs/jazzband/projects/9>`_.

So we are left with this only while keeping is_async a class level attribute for now.

@tim-schilling
Copy link
Contributor

Sounds good.

@salty-ivy
Copy link
Member Author

Not sure, may be something related to sphinx missing in the updated docs to throw the lint error?

@tim-schilling
Copy link
Contributor

@salty-ivy it can be hard to read the docs failures:

architecture.rst:84: : Spell check: ASGI: are disabled by default when running in async/ASGI enviroment..
architecture.rst:84: : Spell check: enviroment: are disabled by default when running in async/ASGI enviroment..

You need to change enviroment to environment

@salty-ivy
Copy link
Member Author

You need to change enviroment to environment

ahh, how can I miss this, thank you so much. Interestingly It even fails on ASGI keyword.

@salty-ivy salty-ivy marked this pull request as ready for review July 15, 2024 19:08
@tim-schilling
Copy link
Contributor

See! I didn't even catch that other one. I thought it was two lines because the word was used twice on that line 😁

extract redudant code in _postprocess

disable non async capable panels

add middleware sync and async compatible test case

rename file

add panel async compatibility tests/

added panel async compatibility tests/

marked erreneous panels as non async

refactor panel test

Add function docstrings

update async panel compatibility tests

revert middleware back to __call__ and __acall__ approach

update architecture.rst documentation

fix typo in docs

remove ASGI keyword from docs
@tim-schilling
Copy link
Contributor

I squashed the commits down to one, cleaned up the commit message, and rebased on main. After tests pass, I'll merge it in

@tim-schilling tim-schilling merged commit 25656ee into jazzband:main Jul 16, 2024
25 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants