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

#658: fix for async Auth #756

Closed
wants to merge 8 commits into from

Conversation

skokado
Copy link
Contributor

@skokado skokado commented Apr 29, 2023

Fix #658 the async-auth behavior
Fix the behavior not to be completed the auth callback.

see below
#658 (comment)

@skokado

This comment was marked as outdated.

@skokado

This comment was marked as outdated.

@skokado skokado closed this May 1, 2023
@skokado skokado reopened this May 1, 2023
@skokado
Copy link
Contributor Author

skokado commented May 1, 2023

I've checked it again, so re-open this PR.
#658 (comment)

@skokado
Copy link
Contributor Author

skokado commented May 1, 2023

Hi mantainers,
This PR is ready for preview so please check and give me some feedbacks

Copy link

@legioz legioz left a comment

Choose a reason for hiding this comment

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

I was using the decorator to workaround this issue:

def await_auth(f):
    @functools.wraps(f)
    async def decorator(*args, **kwargs):
        auth = await args[0].auth
        if not auth :
            raise AuthenticationError()
        args[0].auth = auth
        return await f(*args, **kwargs)
    return decorator

But it seems these PR fix this async auth issue, nice work!

@legioz
Copy link

legioz commented May 2, 2023

@vitalik Are there any async auth fix foreseen for the next release?

@SmileyChris
Copy link
Contributor

This looks like it makes #735 obsolete, but that pr has some docs you might want to steal :)
This also fixes #44

Comment on lines 153 to 158
if asyncio.iscoroutinefunction(callback):
result = async_to_sync(callback)(request)
elif isinstance(callback, AuthBase) and asyncio.iscoroutinefunction(callback.authenticate):
result = async_to_sync(callback)(request)
else:
result = callback(request)
Copy link
Contributor

Choose a reason for hiding this comment

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

use asgiref.iscoroutinefunction :)

It provides a backport of this functionality

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@baseplate-admin
you mean asgiref.sync.iscoroutinefunction ?

Copy link
Contributor

@baseplate-admin baseplate-admin May 3, 2023

Choose a reason for hiding this comment

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

Yes correct

@skokado
Copy link
Contributor Author

skokado commented May 3, 2023

#756 (comment)

@SmileyChris Thank you!
I will update the document about this to steal from PR you mentioned 😎

@skokado
Copy link
Contributor Author

skokado commented May 5, 2023

Thank you reviewers !
I hope this PR will be merged and reflected in next release.

@vitalik
Copy link
Owner

vitalik commented May 5, 2023

@skokado

to check for async - use signature.utils.is_async which should be compatible with 3.7

@baseplate-admin
Copy link
Contributor

baseplate-admin commented May 5, 2023

to check for async - use signature.utils.is_async which should be compatible with 3.7

Is it not better to use a asgiref function ?

well it break tests :)

btw - check #735 as well - this seems already all tests covered

@baseplate-admin
Copy link
Contributor

baseplate-admin commented May 5, 2023

Besides @vitalik, your function is deprecated. Check : python/cpython#94912 ( maybe we should switch to asgiref one everywhere ? )

@skokado
Copy link
Contributor Author

skokado commented May 5, 2023

@baseplate-admin @vitalik
How about switch function dynamically like this ?

try:
    import asgiref
    iscoroutinefunction = asgiref.sync.iscoroutinefunction
except ModuleNotFoundError:
    # For Django 2.x
    import asyncio
    iscoroutinefunction = asyncio.iscoroutinefunction

@vitalik
Copy link
Owner

vitalik commented May 5, 2023

Besides @vitalik, your function is deprecated. Check : python/cpython#94912 ( maybe we should switch to asgiref one everywhere ? )

well utils.is_async should be then adapted anyway - as this function is used in multiple places it just good practice to reuse the same code

@baseplate-admin
Copy link
Contributor

How about switch function dynamically like this ?

Thats exactly what asgiref is doing. Except it imports from inspect.

well utils.is_async should be then adapted anyway

Would you like a PR to remove asyncio.iscoroutinefunction?

@skokado
Copy link
Contributor Author

skokado commented May 5, 2023

So then it's better to use signature.utils.is_async here as in the rest of the code, right ?

@skokado
Copy link
Contributor Author

skokado commented May 5, 2023

Oops, didn't notice this #756 (comment)

@baseplate-admin
Copy link
Contributor

So then it's better to use signature.utils.is_async here as in the rest of the code, right ?

Right

@skokado
Copy link
Contributor Author

skokado commented May 5, 2023

updated 15274a0

@legioz
Copy link

legioz commented May 6, 2023

@skokado looks ninja.pagination is broken

class PaginationBase contains a queryset sync method called _items_count()
Maybe the best pratice would be to rewrite a @async_paginate()

Any sugestions?

@skokado
Copy link
Contributor Author

skokado commented May 6, 2023

#756 (comment)

looks ninja.pagination is broken

@luizfelipevbll How can I see the behavior of that?
I ran unit tests locally and all cases have succeeded

pytest

$ pytest tests/
================================================================================= test session starts ==================================================================================
platform linux -- Python 3.11.2, pytest-7.3.1, pluggy-1.0.0
rootdir: /home/skokado/workspace/django-ninja/tests
configfile: pytest.ini
plugins: anyio-3.6.2, django-4.5.2, cov-4.0.0, asyncio-0.21.0
asyncio: mode=Mode.STRICT
collected 476 items                                                                                                                                                                    

tests/test_django_models.py .                                                                                                                                                    [  0%]
tests/test_orm_schemas.py .                                                                                                                                                      [  0%]
tests/test_docs/test_auth.py .                                                                                                                                                   [  0%]
tests/test_alias.py .                                                                                                                                                            [  0%]
tests/test_api_instance.py ..                                                                                                                                                    [  1%]
tests/test_app.py ............                                                                                                                                                   [  3%]
tests/test_async.py .                                                                                                                                                            [  3%]
tests/test_auth.py ...................................                                                                                                                           [ 11%]
tests/test_auth_global.py ..                                                                                                                                                     [ 11%]
tests/test_auth_inheritance_routers.py ............                                                                                                                              [ 14%]
tests/test_auth_routers.py ........                                                                                                                                              [ 15%]
tests/test_body.py ..                                                                                                                                                            [ 16%]
tests/test_conf.py .                                                                                                                                                             [ 16%]
tests/test_csrf.py ...                                                                                                                                                           [ 17%]
tests/test_django_models.py ..                                                                                                                                                   [ 17%]
tests/test_enum.py ..                                                                                                                                                            [ 18%]
tests/test_exceptions.py .....                                                                                                                                                   [ 19%]
tests/test_export_openapi_schema.py .....                                                                                                                                        [ 20%]
tests/test_files.py ...                                                                                                                                                          [ 20%]
tests/test_filter_schema.py ..............                                                                                                                                       [ 23%]
tests/test_forms.py ...                                                                                                                                                          [ 24%]
tests/test_forms_and_files.py .                                                                                                                                                  [ 24%]
tests/test_inheritance_routers.py ........                                                                                                                                       [ 26%]
tests/test_lists.py ..........                                                                                                                                                   [ 28%]
tests/test_misc.py .....                                                                                                                                                         [ 29%]
tests/test_models.py ..........                                                                                                                                                  [ 31%]
tests/test_openapi_params.py ..                                                                                                                                                  [ 31%]
tests/test_openapi_schema.py .........................                                                                                                                           [ 37%]
tests/test_orm_metaclass.py .....                                                                                                                                                [ 38%]
tests/test_orm_relations.py .                                                                                                                                                    [ 38%]
tests/test_orm_schemas.py ............                                                                                                                                           [ 40%]
tests/test_pagination.py ..........                                                                                                                                              [ 43%]
tests/test_pagination_router.py ..                                                                                                                                               [ 43%]
tests/test_parser.py .                                                                                                                                                           [ 43%]
tests/test_path.py ......................................................................................................                                                        [ 65%]
tests/test_query.py .........................                                                                                                                                    [ 70%]
tests/test_query_schema.py ....                                                                                                                                                  [ 71%]
tests/test_renderer.py ...                                                                                                                                                       [ 71%]
tests/test_request.py .......                                                                                                                                                    [ 73%]
tests/test_response.py ...........                                                                                                                                               [ 75%]
tests/test_response_cookies.py .                                                                                                                                                 [ 75%]
tests/test_response_multiple.py ..................                                                                                                                               [ 79%]
tests/test_response_params.py .                                                                                                                                                  [ 79%]
tests/test_reverse.py ...                                                                                                                                                        [ 80%]
tests/test_router_path_params.py .................                                                                                                                               [ 84%]
tests/test_schema.py ......                                                                                                                                                      [ 85%]
tests/test_server.py ...                                                                                                                                                         [ 85%]
tests/test_signature_details.py ............                                                                                                                                     [ 88%]
tests/test_test_client.py ........                                                                                                                                               [ 90%]
tests/test_union.py .                                                                                                                                                            [ 90%]
tests/test_utils.py ......                                                                                                                                                       [ 91%]
tests/test_wraps.py ........                                                                                                                                                     [ 93%]
tests/test_docs/test_auth.py ..                                                                                                                                                  [ 93%]
tests/test_docs/test_body.py .                                                                                                                                                   [ 93%]
tests/test_docs/test_form.py .                                                                                                                                                   [ 94%]
tests/test_docs/test_index.py .                                                                                                                                                  [ 94%]
tests/test_docs/test_path.py .                                                                                                                                                   [ 94%]
tests/test_docs/test_query.py .                                                                                                                                                  [ 94%]
tests/test_with_django/test_multi_param_parsing.py .........................                                                                                                     [100%]

=================================================================================== warnings summary ===================================================================================
test_auth.py::test_auth[/async_apikeyquery-kwargs11-401-expected_body11]
test_auth.py::test_auth[/async_apikeyquery?key=keyquerysecret-kwargs12-200-expected_body12]
test_auth.py::test_auth[/async_apikeyheader-kwargs15-401-expected_body15]
test_auth.py::test_auth[/async_apikeyheader-kwargs16-200-expected_body16]
test_auth.py::test_auth[/async_apikeycookie-kwargs19-401-expected_body19]
test_auth.py::test_auth[/async_apikeycookie-kwargs20-200-expected_body20]
test_auth.py::test_auth[/async_customexception-kwargs31-401-expected_body31]
test_auth.py::test_auth[/async_customexception-kwargs32-200-expected_body32]
  /home/skokado/workspace/django-ninja/ninja/operation.py:155: UserWarning: async_to_sync was passed a non-async-marked callable
    result = async_to_sync(callback)(request)

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================================================================== 476 passed, 8 warnings in 1.71s ============================================================================

@skokado
Copy link
Contributor Author

skokado commented May 6, 2023

Hi reviewers, on second thought, this update may be fundamentally misguided :(

https://github.com/vitalik/django-ninja/actions/runs/4894118600/jobs/8750675243?pr=756#step:6:30

it's used import asgiref at the beginning of the module ninja.operation, which is incompatible with the Django2.x case.
https://github.com/skokado/django-ninja/blob/dd181d96bd17dc293a7adbcc3f7ec1b663f4c317/ninja/operation.py#L15

Should I wait for Django 2 to drop? #744

@baseplate-admin
Copy link
Contributor

Should I wait for Django 2 to drop? #744

I thought of this too when i closed my own PR. see #719 (comment) and i then made my own middleware package to extend django-ninja

@vitalik
Copy link
Owner

vitalik commented May 27, 2023

Hi, thank you for contribution, but another PR with async auth merged, please test with latest master branch

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.

Async Auth is broken
5 participants