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

Make managers in django.contrib generic #190

Merged
merged 1 commit into from
Sep 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 21 additions & 15 deletions django-stubs/contrib/admin/models.pyi
Original file line number Diff line number Diff line change
@@ -1,37 +1,43 @@
from typing import Any, ClassVar
import datetime as dt
from typing import Any, ClassVar, TypeVar
from typing_extensions import Self
from uuid import UUID

from django.contrib.contenttypes.models import ContentType
from django.db import models
from django.db.models.base import Model

ADDITION: int
CHANGE: int
DELETION: int
ACTION_FLAG_CHOICES: Any
ACTION_FLAG_CHOICES: list[tuple[int, str]]

class LogEntryManager(models.Manager[LogEntry]):
_LogEntryT = TypeVar("_LogEntryT", bound=LogEntry)

class LogEntryManager(models.Manager[_LogEntryT]):
def log_action(
self,
user_id: int,
content_type_id: int,
object_id: int | str | UUID,
object_repr: str,
action_flag: int,
change_message: Any = ...,
) -> LogEntry: ...
change_message: str | list[Any] = ...,
) -> _LogEntryT: ...

class LogEntry(models.Model):
action_time: models.DateTimeField[Any] = ...
user: models.ForeignKey[Any] = ...
content_type: models.ForeignKey[Any] = ...
object_id: models.TextField[Any] = ...
object_repr: models.CharField[Any] = ...
action_flag: models.PositiveSmallIntegerField[Any] = ...
change_message: models.TextField[Any] = ...
objects: ClassVar[LogEntryManager] = ...
objects: ClassVar[LogEntryManager[Self]] # type: ignore[assignment]

action_time: models.DateTimeField[dt.datetime]
user: models.ForeignKey[Any]
content_type: models.ForeignKey[ContentType | None]
object_id: models.TextField[str | None]
object_repr: models.CharField[str]
action_flag: models.PositiveSmallIntegerField[int]
change_message: models.TextField[str]

def is_addition(self) -> bool: ...
def is_change(self) -> bool: ...
def is_deletion(self) -> bool: ...
def get_change_message(self) -> str: ...
def get_edited_object(self) -> Model: ...
def get_edited_object(self) -> models.Model: ...
def get_admin_url(self) -> str | None: ...
15 changes: 6 additions & 9 deletions django-stubs/contrib/auth/base_user.pyi
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
from typing import Any, TypeVar, overload
from typing import Any, TypeVar
from typing_extensions import Literal

from django.db import models
from django.db.models.base import Model
from django.db.models.fields import BooleanField

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

class BaseUserManager(models.Manager[_T]):
class BaseUserManager(models.Manager[_ModelT]):
@classmethod
def normalize_email(cls, email: str | None) -> str: ...
def make_random_password(
self, length: int = ..., allowed_chars: str = ...
) -> str: ...
def get_by_natural_key(self, username: str | None) -> _T: ...
def get_by_natural_key(self, username: str | None) -> _ModelT: ...

class AbstractBaseUser(models.Model):
REQUIRED_FIELDS: list[str] = ...
Expand All @@ -35,8 +36,4 @@ class AbstractBaseUser(models.Model):
@classmethod
def get_email_field_name(cls) -> str: ...
@classmethod
@overload
def normalize_username(cls, username: str) -> str: ...
@classmethod
@overload
def normalize_username(cls, username: Any) -> Any: ...
def normalize_username(cls, username: _T) -> _T: ...
26 changes: 15 additions & 11 deletions django-stubs/contrib/auth/models.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,39 @@ from django.db.models.manager import EmptyManager

_AnyUser = Model | AnonymousUser

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

def update_last_login(
sender: type[AbstractBaseUser], user: AbstractBaseUser, **kwargs: Any
) -> None: ...

class PermissionManager(models.Manager[Permission]):
_PermissionT = TypeVar("_PermissionT", bound=Permission)

class PermissionManager(models.Manager[_PermissionT]):
def get_by_natural_key(
self, codename: str, app_label: str, model: str
) -> Permission: ...
) -> _PermissionT: ...

class Permission(models.Model):
content_type_id: int
objects: ClassVar[PermissionManager]
objects: ClassVar[PermissionManager[Self]] # type: ignore[assignment]

name = models.CharField(max_length=255)
content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
codename = models.CharField(max_length=100)
def natural_key(self) -> tuple[str, str, str]: ...

class GroupManager(models.Manager[Group]):
def get_by_natural_key(self, name: str) -> Group: ...
_GroupT = TypeVar("_GroupT", bound=Group)

class GroupManager(models.Manager[_GroupT]):
def get_by_natural_key(self, name: str) -> _GroupT: ...

class Group(models.Model):
objects: ClassVar[GroupManager]
objects: ClassVar[GroupManager[Self]] # type: ignore[assignment]

name = models.CharField(max_length=150)
permissions = models.ManyToManyField[Permission, Any](Permission)
def natural_key(self) -> Any: ...

_T = TypeVar("_T", bound=Model)
def natural_key(self) -> tuple[str, ...]: ...

class UserManager(BaseUserManager[_T]):
def create_user(
Expand Down Expand Up @@ -114,9 +118,9 @@ class AnonymousUser:
def set_password(self, raw_password: str) -> Any: ...
def check_password(self, raw_password: str) -> Any: ...
@property
def groups(self) -> EmptyManager: ...
def groups(self) -> EmptyManager[Group]: ...
@property
def user_permissions(self) -> EmptyManager: ...
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_all_permissions(self, obj: _AnyUser | None = ...) -> set[str]: ...
Expand Down
19 changes: 12 additions & 7 deletions django-stubs/contrib/sessions/base_session.pyi
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
from datetime import datetime
from typing import Any, ClassVar
from typing import ClassVar, TypeVar
from typing_extensions import Self

from django.contrib.sessions.backends.base import SessionBase
from django.db import models

class BaseSessionManager(models.Manager[Any]):
_SessionT = TypeVar("_SessionT", bound=AbstractBaseSession)

class BaseSessionManager(models.Manager[_SessionT]):
def encode(self, session_dict: dict[str, int]) -> str: ...
def save(
self, session_key: str, session_dict: dict[str, int], expire_date: datetime
) -> AbstractBaseSession: ...
) -> _SessionT: ...

class AbstractBaseSession(models.Model):
expire_date: datetime
session_data: str
session_key: str
objects: ClassVar[BaseSessionManager] = ...
objects: ClassVar[BaseSessionManager[Self]] # type: ignore[assignment]

session_key: models.CharField[str]
session_data: models.TextField[str]
expire_date: models.DateTimeField[datetime]

@classmethod
def get_session_store_class(cls) -> type[SessionBase] | None: ...
def get_decoded(self) -> dict[str, int]: ...
15 changes: 13 additions & 2 deletions django-stubs/contrib/sessions/models.pyi
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
from typing import ClassVar, TypeVar
from typing_extensions import Self

from django.contrib.sessions.backends.db import SessionStore
from django.contrib.sessions.base_session import AbstractBaseSession, BaseSessionManager

class SessionManager(BaseSessionManager): ...
class Session(AbstractBaseSession): ...
_T = TypeVar("_T", bound=AbstractBaseSession)

class SessionManager(BaseSessionManager[_T]): ...

class Session(AbstractBaseSession):
objects: ClassVar[SessionManager[Self]] # type: ignore[assignment]

@classmethod
def get_session_store_class(cls) -> type[SessionStore]: ...
6 changes: 4 additions & 2 deletions django-stubs/contrib/sites/managers.pyi
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from typing import Any
from typing import TypeVar

from django.db import models

class CurrentSiteManager(models.Manager[Any]):
_T = TypeVar("_T", bound=models.Model)

class CurrentSiteManager(models.Manager[_T]):
def __init__(self, field_name: str | None = ...) -> None: ...
15 changes: 9 additions & 6 deletions django-stubs/contrib/sites/models.pyi
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
from typing import Any, ClassVar
from typing import Any, ClassVar, TypeVar
from typing_extensions import Self

from django.db import models
from django.http.request import HttpRequest

SITE_CACHE: Any
SITE_CACHE: dict[Any, Site]

class SiteManager(models.Manager[Site]):
def get_current(self, request: HttpRequest | None = ...) -> Site: ...
_SiteT = TypeVar("_SiteT", bound=Site)

class SiteManager(models.Manager[_SiteT]):
def get_current(self, request: HttpRequest | None = ...) -> _SiteT: ...
def clear_cache(self) -> None: ...
def get_by_natural_key(self, domain: str) -> Site: ...
def get_by_natural_key(self, domain: str) -> _SiteT: ...

class Site(models.Model):
objects: ClassVar[SiteManager]
objects: ClassVar[SiteManager[Self]] # type: ignore[assignment]

domain = models.CharField(max_length=100)
name = models.CharField(max_length=50)
Expand Down
4 changes: 2 additions & 2 deletions django-stubs/db/models/manager.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,5 @@ class ManagerDescriptor:
self, instance: Model | None, cls: type[Model] = ...
) -> Manager[Any]: ...

class EmptyManager(Manager[Any]):
def __init__(self, model: type[Model]) -> None: ...
class EmptyManager(Manager[_T]):
def __init__(self, model: type[_T]) -> None: ...