From 054cdd43ed509340972b07de736bfea3d41654b9 Mon Sep 17 00:00:00 2001 From: Jon Janzen Date: Fri, 8 Dec 2023 04:00:31 -0800 Subject: [PATCH] [5.0] Added many new a-prefixed asynchronous methods (#1741) * Asyncify auth funcs + methods in test Client https://github.com/django/django/commit/5e98959d9242c57a55c65847758781f82d386fa4 * Fixed #34565 -- Added support for async checking of user passwords. https://github.com/django/django/commit/674c23999cb6982a9d447fedec4d72e135201fee * Fixed #34714 -- Added aget_object_or_404()/aget_list_or_404() shortcuts. https://github.com/django/django/commit/b9473cac65190822e7c94f695f1f7b4d5b49502a * Fixed #34331 -- Added QuerySet.aiterator() support for prefetch_related(). https://github.com/django/django/commit/fff14736f1cc594f79ea0e2656b8375d837b7aca * Update stubtest ignores --------- Co-authored-by: Marti Raudsepp --- django-stubs/contrib/auth/__init__.pyi | 7 +++++++ django-stubs/contrib/auth/base_user.pyi | 1 + django-stubs/contrib/auth/hashers.pyi | 3 +++ django-stubs/db/models/query.pyi | 1 + django-stubs/shortcuts.pyi | 2 ++ django-stubs/test/client.pyi | 4 ++++ scripts/stubtest/allowlist_todo_django50.txt | 15 --------------- 7 files changed, 18 insertions(+), 15 deletions(-) diff --git a/django-stubs/contrib/auth/__init__.pyi b/django-stubs/contrib/auth/__init__.pyi index 0d24bb9b0..cd37c03ad 100644 --- a/django-stubs/contrib/auth/__init__.pyi +++ b/django-stubs/contrib/auth/__init__.pyi @@ -19,13 +19,20 @@ REDIRECT_FIELD_NAME: str def load_backend(path: str) -> ModelBackend: ... def get_backends() -> list[ModelBackend]: ... def authenticate(request: HttpRequest | None = ..., **credentials: Any) -> AbstractBaseUser | None: ... +async def aauthenticate(request: HttpRequest | None = ..., **credentials: Any) -> AbstractBaseUser | None: ... def login( request: HttpRequest, user: AbstractBaseUser | None, backend: type[ModelBackend] | str | None = ... ) -> None: ... +async def alogin( + request: HttpRequest, user: AbstractBaseUser | None, backend: type[ModelBackend] | str | None = ... +) -> None: ... def logout(request: HttpRequest) -> None: ... +async def alogout(request: HttpRequest) -> None: ... def get_user_model() -> type[AbstractBaseUser]: ... def get_user(request: HttpRequest | Client) -> AbstractBaseUser | AnonymousUser: ... +async def aget_user(request: HttpRequest | Client) -> AbstractBaseUser | AnonymousUser: ... def get_permission_codename(action: str, opts: Options) -> str: ... def update_session_auth_hash(request: HttpRequest, user: AbstractBaseUser) -> None: ... +async def aupdate_session_auth_hash(request: HttpRequest, user: AbstractBaseUser) -> None: ... default_app_config: str diff --git a/django-stubs/contrib/auth/base_user.pyi b/django-stubs/contrib/auth/base_user.pyi index 5bf256329..b137e51f9 100644 --- a/django-stubs/contrib/auth/base_user.pyi +++ b/django-stubs/contrib/auth/base_user.pyi @@ -30,6 +30,7 @@ class AbstractBaseUser(models.Model): def is_authenticated(self) -> Literal[True]: ... def set_password(self, raw_password: str | None) -> None: ... def check_password(self, raw_password: str) -> bool: ... + async def acheck_password(self, raw_password: str) -> bool: ... def set_unusable_password(self) -> None: ... def has_usable_password(self) -> bool: ... def get_session_auth_hash(self) -> str: ... diff --git a/django-stubs/contrib/auth/hashers.pyi b/django-stubs/contrib/auth/hashers.pyi index 3942d6f5b..7ea9aa9b0 100644 --- a/django-stubs/contrib/auth/hashers.pyi +++ b/django-stubs/contrib/auth/hashers.pyi @@ -6,6 +6,9 @@ UNUSABLE_PASSWORD_SUFFIX_LENGTH: int def is_password_usable(encoded: str | None) -> bool: ... def check_password(password: str | None, encoded: str, setter: Callable | None = ..., preferred: str = ...) -> bool: ... +async def acheck_password( + password: str | None, encoded: str, setter: Callable | None = ..., preferred: str = ... +) -> bool: ... def make_password(password: str | None, salt: str | None = ..., hasher: str | BasePasswordHasher = ...) -> str: ... def get_hashers() -> list[BasePasswordHasher]: ... def get_hashers_by_algorithm() -> dict[str, BasePasswordHasher]: ... diff --git a/django-stubs/db/models/query.pyi b/django-stubs/db/models/query.pyi index 1202e049c..6f449bf77 100644 --- a/django-stubs/db/models/query.pyi +++ b/django-stubs/db/models/query.pyi @@ -234,6 +234,7 @@ class Prefetch: def get_current_queryset(self, level: int) -> QuerySet | None: ... def prefetch_related_objects(model_instances: Iterable[_T], *related_lookups: str | Prefetch) -> None: ... +async def aprefetch_related_objects(model_instances: Iterable[_T], *related_lookups: str | Prefetch) -> None: ... def get_prefetcher(instance: Model, through_attr: str, to_attr: str) -> tuple[Any, Any, bool, bool]: ... class InstanceCheckMeta(type): ... diff --git a/django-stubs/shortcuts.pyi b/django-stubs/shortcuts.pyi index 376fbac75..1e352e86b 100644 --- a/django-stubs/shortcuts.pyi +++ b/django-stubs/shortcuts.pyi @@ -34,5 +34,7 @@ def redirect( _T = TypeVar("_T", bound=Model) def get_object_or_404(klass: type[_T] | Manager[_T] | QuerySet[_T], *args: Any, **kwargs: Any) -> _T: ... +async def aget_object_or_404(klass: type[_T] | Manager[_T] | QuerySet[_T], *args: Any, **kwargs: Any) -> _T: ... def get_list_or_404(klass: type[_T] | Manager[_T] | QuerySet[_T], *args: Any, **kwargs: Any) -> list[_T]: ... +async def aget_list_or_404(klass: type[_T] | Manager[_T] | QuerySet[_T], *args: Any, **kwargs: Any) -> list[_T]: ... def resolve_url(to: Callable | Model | str, *args: Any, **kwargs: Any) -> str: ... diff --git a/django-stubs/test/client.pyi b/django-stubs/test/client.pyi index eb65d3468..e8fa729b8 100644 --- a/django-stubs/test/client.pyi +++ b/django-stubs/test/client.pyi @@ -180,9 +180,13 @@ class ClientMixin: def check_exception(self, response: HttpResponseBase) -> NoReturn: ... @property def session(self) -> SessionBase: ... + async def asession(self) -> SessionBase: ... def login(self, **credentials: Any) -> bool: ... + async def alogin(self, **credentials: Any) -> bool: ... def force_login(self, user: AbstractBaseUser, backend: str | None = ...) -> None: ... + async def aforce_login(self, user: AbstractBaseUser, backend: str | None = ...) -> None: ... def logout(self) -> None: ... + async def alogout(self) -> None: ... class Client(ClientMixin, _RequestFactory[_MonkeyPatchedWSGIResponse]): handler: ClientHandler diff --git a/scripts/stubtest/allowlist_todo_django50.txt b/scripts/stubtest/allowlist_todo_django50.txt index 5b9c0b7c5..da17fabd3 100644 --- a/scripts/stubtest/allowlist_todo_django50.txt +++ b/scripts/stubtest/allowlist_todo_django50.txt @@ -40,18 +40,10 @@ django.contrib.admin.sites.AdminSite.get_model_admin django.contrib.admin.utils.build_q_object_from_lookup_parameters django.contrib.admin.utils.get_last_value_from_parameters django.contrib.admin.views.main.ChangeList.get_queryset -django.contrib.auth.aauthenticate django.contrib.auth.admin.UserAdmin.lookup_allowed -django.contrib.auth.aget_user -django.contrib.auth.alogin -django.contrib.auth.alogout -django.contrib.auth.aupdate_session_auth_hash -django.contrib.auth.base_user.AbstractBaseUser.acheck_password django.contrib.auth.hashers.CryptPasswordHasher -django.contrib.auth.hashers.acheck_password django.contrib.auth.hashers.verify_password django.contrib.auth.middleware.auser -django.contrib.auth.models.AbstractBaseUser.acheck_password django.contrib.contenttypes.fields.GenericForeignKey.get_content_type django.contrib.contenttypes.fields.GenericForeignKey.get_prefetch_querysets django.contrib.contenttypes.prefetch @@ -242,7 +234,6 @@ django.db.models.lookups.Lookup.allowed_default django.db.models.query.Prefetch.get_current_querysets django.db.models.query.QuerySet.aupdate_or_create django.db.models.query.QuerySet.update_or_create -django.db.models.query.aprefetch_related_objects django.db.models.query_utils.FilteredRelation.relabeled_clone django.db.models.query_utils.FilteredRelation.resolve_expression django.db.models.query_utils.Q.identity @@ -278,8 +269,6 @@ django.forms.renderers.BaseRenderer.field_template_name django.forms.renderers.Jinja2DivFormRenderer.__init__ django.forms.utils.RenderableFieldMixin django.forms.widgets.ClearableFileInput.checked -django.shortcuts.aget_list_or_404 -django.shortcuts.aget_object_or_404 django.template.Template.__iter__ django.template.autoreload django.template.base.Template.__iter__ @@ -300,10 +289,6 @@ django.test.client.AsyncClient.patch django.test.client.AsyncClient.post django.test.client.AsyncClient.put django.test.client.AsyncClient.trace -django.test.client.ClientMixin.aforce_login -django.test.client.ClientMixin.alogin -django.test.client.ClientMixin.alogout -django.test.client.ClientMixin.asession django.test.runner.DiscoverRunner.__init__ django.test.runner.DiscoverRunner.run_tests django.test.runner.RemoteTestResult.addDuration