Skip to content

Commit

Permalink
Improvements to django.contrib.auth (#246)
Browse files Browse the repository at this point in the history
The highlight of this PR is changing `get_user_model()` to return `type[AbstractUser]`, which much more useful than `type[AbstractBaseUser]`.

See commits for details and commentary.
  • Loading branch information
noelleleigh authored Jun 1, 2024
1 parent 1cf947f commit f889fc4
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 23 deletions.
14 changes: 9 additions & 5 deletions django-stubs/contrib/auth/__init__.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ from typing import Any

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.models import AnonymousUser
from django.contrib.auth.models import AbstractUser, AnonymousUser
from django.db.models.options import Options
from django.http.request import HttpRequest
from django.test.client import Client
Expand All @@ -18,21 +18,25 @@ REDIRECT_FIELD_NAME: str

def load_backend(path: str) -> ModelBackend: ...
def get_backends() -> list[ModelBackend]: ...
def authenticate(request: HttpRequest = ..., **credentials: Any) -> AbstractBaseUser | None: ...
def authenticate(
request: HttpRequest | None = ..., **credentials: Any
) -> AbstractUser | None: ...
def login(
request: HttpRequest,
user: AbstractBaseUser | None,
backend: type[ModelBackend] | str | None = ...,
) -> None: ...
def logout(request: HttpRequest) -> None: ...
async def aauthenticate(request: HttpRequest = ..., **credentials: Any) -> AbstractBaseUser | None: ...
async def aauthenticate(
request: HttpRequest = ..., **credentials: Any
) -> AbstractBaseUser | None: ...
async def alogin(
request: HttpRequest,
user: AbstractBaseUser | None,
backend: type[ModelBackend] | str | None = ...,
) -> None: ...
def get_user_model() -> type[AbstractBaseUser]: ...
def get_user(request: HttpRequest | Client) -> AbstractBaseUser | AnonymousUser: ...
def get_user_model() -> type[AbstractUser]: ...
def get_user(request: HttpRequest | Client) -> AbstractUser | AnonymousUser: ...
def get_permission_codename(action: str, opts: Options[Any]) -> str: ...
def update_session_auth_hash(request: HttpRequest, user: AbstractBaseUser) -> None: ...

Expand Down
2 changes: 1 addition & 1 deletion django-stubs/contrib/auth/base_user.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class BaseUserManager(models.Manager[_ModelT]):
def make_random_password(
self, length: int = ..., allowed_chars: str = ...
) -> str: ...
def get_by_natural_key(self, username: str | None) -> _ModelT: ...
def get_by_natural_key(self, username: str) -> _ModelT: ...

class AbstractBaseUser(models.Model):
REQUIRED_FIELDS: list[str] = ...
Expand Down
36 changes: 19 additions & 17 deletions django-stubs/contrib/auth/models.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from collections.abc import Collection
from collections.abc import Iterable
from typing import Any, ClassVar, TypeVar
from typing_extensions import Literal, Self
from typing_extensions import Literal, Never, Self

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth.base_user import AbstractBaseUser as AbstractBaseUser
Expand All @@ -11,7 +11,7 @@ from django.db import models
from django.db.models.base import Model
from django.db.models.manager import EmptyManager, ManyToManyRelatedManager

_AnyUser = Model | AnonymousUser
_AnyUser = AbstractUser | AnonymousUser

_T = TypeVar("_T", bound=Model)

Expand Down Expand Up @@ -46,10 +46,11 @@ class Group(models.Model):

name = models.CharField(max_length=150)
permissions = models.ManyToManyField[Permission, Any](Permission)
def natural_key(self) -> tuple[str, ...]: ...
def natural_key(self) -> tuple[str]: ...
user_set = ManyToManyRelatedManager["PermissionsMixin", "Group"]()

class UserManager(BaseUserManager[_T]):
use_in_migrations: bool = ...
def create_user(
self,
username: str,
Expand All @@ -71,7 +72,7 @@ class UserManager(BaseUserManager[_T]):
include_superusers: bool = ...,
backend: type[ModelBackend] | str | None = ...,
obj: Model | None = ...,
) -> Any: ...
) -> Self | UserManager[_T]: ...

class PermissionsMixin(models.Model):
is_superuser = models.BooleanField()
Expand All @@ -82,15 +83,15 @@ class PermissionsMixin(models.Model):
def get_all_permissions(self, obj: _AnyUser | None = ...) -> set[str]: ...
def has_perm(self, perm: str, obj: _AnyUser | None = ...) -> bool: ...
def has_perms(
self, perm_list: Collection[str], obj: _AnyUser | None = ...
self, perm_list: Iterable[str], obj: _AnyUser | None = ...
) -> bool: ...
def has_module_perms(self, app_label: str) -> bool: ...

class AbstractUser(AbstractBaseUser, PermissionsMixin):
username_validator: UnicodeUsernameValidator = ...

username = models.CharField(max_length=150)
first_name = models.CharField(max_length=30, blank=True)
first_name = models.CharField(max_length=150, blank=True)
last_name = models.CharField(max_length=150, blank=True)
email = models.EmailField(blank=True)
is_staff = models.BooleanField()
Expand All @@ -102,33 +103,34 @@ class AbstractUser(AbstractBaseUser, PermissionsMixin):
def get_full_name(self) -> str: ...
def get_short_name(self) -> str: ...
def email_user(
self, subject: str, message: str, from_email: str = ..., **kwargs: Any
self, subject: str, message: str, from_email: str | None = ..., **kwargs: Any
) -> None: ...

class User(AbstractUser):
objects: ClassVar[UserManager[Self]] # type: ignore[assignment]

class User(AbstractUser): ...

class AnonymousUser:
id: Any = ...
pk: Any = ...
id: None = ...
pk: None = ...
username: str = ...
is_staff: bool = ...
is_active: bool = ...
is_superuser: bool = ...
def save(self) -> Any: ...
def delete(self) -> Any: ...
def set_password(self, raw_password: str) -> Any: ...
def check_password(self, raw_password: str) -> Any: ...
def save(self) -> Never: ...
def delete(self) -> Never: ...
def set_password(self, raw_password: str) -> Never: ...
def check_password(self, raw_password: str) -> Never: ...
@property
def groups(self) -> EmptyManager[Group]: ...
@property
def user_permissions(self) -> EmptyManager[Permission]: ...
def get_user_permissions(self, obj: _AnyUser | None = ...) -> set[str]: ...
def get_group_permissions(self, obj: _AnyUser | None = ...) -> set[Any]: ...
def get_group_permissions(self, obj: _AnyUser | None = ...) -> set[str]: ...
def get_all_permissions(self, obj: _AnyUser | None = ...) -> set[str]: ...
def has_perm(self, perm: str, obj: _AnyUser | None = ...) -> bool: ...
def has_perms(
self, perm_list: Collection[str], obj: _AnyUser | None = ...
self, perm_list: Iterable[str], obj: _AnyUser | None = ...
) -> bool: ...
def has_module_perms(self, module: str) -> bool: ...
@property
Expand Down

0 comments on commit f889fc4

Please sign in to comment.