diff --git a/django-stubs/contrib/auth/models.pyi b/django-stubs/contrib/auth/models.pyi index 78702f1e7..d2064fa14 100644 --- a/django-stubs/contrib/auth/models.pyi +++ b/django-stubs/contrib/auth/models.pyi @@ -8,6 +8,7 @@ from django.contrib.contenttypes.models import ContentType from django.db import models from django.db.models import QuerySet from django.db.models.base import Model +from django.db.models.expressions import Combinable from django.db.models.manager import EmptyManager from django.utils.functional import _StrOrPromise from typing_extensions import Self, TypeAlias @@ -23,9 +24,9 @@ class Permission(models.Model): content_type_id: int objects: ClassVar[PermissionManager] - name = models.CharField(max_length=255) - content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE) - codename = models.CharField(max_length=100) + name: models.CharField[str | int | Combinable, str] + content_type: models.ForeignKey[ContentType | Combinable, ContentType] + codename: models.CharField[str | int | Combinable, str] def natural_key(self) -> tuple[str, str, str]: ... class GroupManager(models.Manager[Group]): @@ -34,7 +35,7 @@ class GroupManager(models.Manager[Group]): class Group(models.Model): objects: ClassVar[GroupManager] - name = models.CharField(max_length=150) + name: models.CharField[str | int | Combinable, str] permissions = models.ManyToManyField(Permission) def natural_key(self) -> tuple[str]: ... diff --git a/django-stubs/db/models/fields/__init__.pyi b/django-stubs/db/models/fields/__init__.pyi index 39b1a2a07..147429278 100644 --- a/django-stubs/db/models/fields/__init__.pyi +++ b/django-stubs/db/models/fields/__init__.pyi @@ -103,9 +103,28 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]): Notice, that this is not magic. This is how descriptors work with ``mypy``. - We also need ``_pyi_private_set_type`` attributes - and friends to help inside our plugin. - It is required to enhance parts like ``filter`` queries. + Each field class defines three "type-only" attributes: + - ``_pyi_lookup_exact_type``: Used for ``filter`` queries and friends. + - ``_pyi_private_get/set_type``: Used to parametrize the field class + on instantiation. Additional logic is also applied if the field is nullable, + a primary key or has a default. + + To improve support with other type checkers, subclasses define overloads on the + ``__init__`` method to automatically parametrize the field class: + + .. code:: python + + class Example(Model): + count = IntField(null=True) + my_pk = IntField(primary_key=True, default=def_gen) + + example = Example() + reveal_type(example.count) # Revealed type is "builtins.int | None", even without the plugin + + example.my_pk = None # No error with the mypy plugin, error in "vanilla" type checking + + Plugin logic is still kept as these overloads only support field nullability, as shown + in the example. """ _pyi_private_set_type: Any @@ -160,6 +179,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]): max_length: int | None = ..., unique: bool = ..., blank: bool = ..., + *, null: bool = ..., db_index: bool = ..., rel: ForeignObjectRel | None = ..., @@ -240,76 +260,51 @@ class IntegerField(Field[_ST, _GT]): _pyi_private_set_type: float | int | str | Combinable _pyi_private_get_type: int _pyi_lookup_exact_type: str | int - -class PositiveIntegerRelDbTypeMixin: - def rel_db_type(self, connection: BaseDatabaseWrapper) -> str: ... - -class SmallIntegerField(IntegerField[_ST, _GT]): ... - -class BigIntegerField(IntegerField[_ST, _GT]): - MAX_BIGINT: ClassVar[int] - -class PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField[_ST, _GT]): ... -class PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, SmallIntegerField[_ST, _GT]): ... -class PositiveBigIntegerField(PositiveIntegerRelDbTypeMixin, BigIntegerField[_ST, _GT]): ... - -class FloatField(Field[_ST, _GT]): - _pyi_private_set_type: float | int | str | Combinable - _pyi_private_get_type: float - _pyi_lookup_exact_type: float - -class DecimalField(Field[_ST, _GT]): - _pyi_private_set_type: str | float | decimal.Decimal | Combinable - _pyi_private_get_type: decimal.Decimal - _pyi_lookup_exact_type: str | decimal.Decimal - # attributes - max_digits: int - decimal_places: int + @overload def __init__( - self, + self: IntegerField[float | int | str | Combinable | None, int | None], verbose_name: _StrOrPromise | None = ..., name: str | None = ..., - max_digits: int | None = ..., - decimal_places: int | None = ..., - *, primary_key: bool = ..., + max_length: int | None = ..., unique: bool = ..., blank: bool = ..., - null: bool = ..., + *, + null: Literal[True], db_index: bool = ..., + rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str | None = ..., editable: bool = ..., - auto_created: bool = ..., serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., - db_comment: str | None = ..., db_tablespace: str | None = ..., + auto_created: bool = ..., validators: Iterable[validators._ValidatorCallable] = ..., error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., ) -> None: ... - -class CharField(Field[_ST, _GT]): - _pyi_private_set_type: str | int | Combinable - _pyi_private_get_type: str - # objects are converted to string before comparison - _pyi_lookup_exact_type: Any + @overload def __init__( - self, + self: IntegerField[float | int | str | Combinable, int], verbose_name: _StrOrPromise | None = ..., name: str | None = ..., primary_key: bool = ..., max_length: int | None = ..., unique: bool = ..., blank: bool = ..., - null: bool = ..., + *, + null: Literal[False] = ..., db_index: bool = ..., + rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str = ..., editable: bool = ..., - auto_created: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., unique_for_month: str | None = ..., @@ -317,29 +312,33 @@ class CharField(Field[_ST, _GT]): choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., - db_comment: str | None = ..., db_tablespace: str | None = ..., + auto_created: bool = ..., validators: Iterable[validators._ValidatorCallable] = ..., error_messages: _ErrorMessagesMapping | None = ..., - *, - db_collation: str | None = ..., + db_comment: str | None = ..., ) -> None: ... -class CommaSeparatedIntegerField(CharField[_ST, _GT]): ... +class PositiveIntegerRelDbTypeMixin: + def rel_db_type(self, connection: BaseDatabaseWrapper) -> str: ... -class SlugField(CharField[_ST, _GT]): +class SmallIntegerField(IntegerField[_ST, _GT]): + @overload def __init__( - self, + self: SmallIntegerField[float | int | str | Combinable | None, int | None], verbose_name: _StrOrPromise | None = ..., name: str | None = ..., primary_key: bool = ..., + max_length: int | None = ..., unique: bool = ..., blank: bool = ..., - null: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str | None = ..., editable: bool = ..., - auto_created: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., unique_for_month: str | None = ..., @@ -347,33 +346,27 @@ class SlugField(CharField[_ST, _GT]): choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., - db_comment: str | None = ..., db_tablespace: str | None = ..., + auto_created: bool = ..., validators: Iterable[validators._ValidatorCallable] = ..., error_messages: _ErrorMessagesMapping | None = ..., - *, - max_length: int | None = ..., - db_index: bool = ..., - allow_unicode: bool = ..., + db_comment: str | None = ..., ) -> None: ... - -class EmailField(CharField[_ST, _GT]): ... - -class URLField(CharField[_ST, _GT]): + @overload def __init__( - self, + self: SmallIntegerField[float | int | str | Combinable, int], verbose_name: _StrOrPromise | None = ..., name: str | None = ..., - *, primary_key: bool = ..., max_length: int | None = ..., unique: bool = ..., blank: bool = ..., - null: bool = ..., + *, + null: Literal[False] = ..., db_index: bool = ..., rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str = ..., editable: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., @@ -382,32 +375,31 @@ class URLField(CharField[_ST, _GT]): choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., - db_comment: str | None = ..., db_tablespace: str | None = ..., auto_created: bool = ..., validators: Iterable[validators._ValidatorCallable] = ..., error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., ) -> None: ... -class TextField(Field[_ST, _GT]): - _pyi_private_set_type: str | Combinable - _pyi_private_get_type: str - # objects are converted to string before comparison - _pyi_lookup_exact_type: Any +class BigIntegerField(IntegerField[_ST, _GT]): + MAX_BIGINT: ClassVar[int] + @overload def __init__( - self, + self: BigIntegerField[float | int | str | Combinable | None, int | None], verbose_name: _StrOrPromise | None = ..., name: str | None = ..., primary_key: bool = ..., max_length: int | None = ..., unique: bool = ..., blank: bool = ..., - null: bool = ..., + *, + null: Literal[True], db_index: bool = ..., + rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str | None = ..., editable: bool = ..., - auto_created: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., unique_for_month: str | None = ..., @@ -415,149 +407,118 @@ class TextField(Field[_ST, _GT]): choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., - db_comment: str | None = ..., db_tablespace: str | None = ..., + auto_created: bool = ..., validators: Iterable[validators._ValidatorCallable] = ..., error_messages: _ErrorMessagesMapping | None = ..., - *, - db_collation: str | None = ..., + db_comment: str | None = ..., ) -> None: ... - -class BooleanField(Field[_ST, _GT]): - _pyi_private_set_type: bool | Combinable - _pyi_private_get_type: bool - _pyi_lookup_exact_type: bool - -class NullBooleanField(BooleanField[_ST, _GT]): - _pyi_private_set_type: bool | Combinable | None # type: ignore[assignment] - _pyi_private_get_type: bool | None # type: ignore[assignment] - _pyi_lookup_exact_type: bool | None # type: ignore[assignment] - -class IPAddressField(Field[_ST, _GT]): - _pyi_private_set_type: str | Combinable - _pyi_private_get_type: str - -class GenericIPAddressField(Field[_ST, _GT]): - _pyi_private_set_type: str | int | Callable[..., Any] | Combinable - _pyi_private_get_type: str - - default_error_messages: _ErrorMessagesDict - unpack_ipv4: bool - protocol: str + @overload def __init__( - self, + self: BigIntegerField[float | int | str | Combinable, int], verbose_name: _StrOrPromise | None = ..., - name: Any | None = ..., - protocol: str = ..., - unpack_ipv4: bool = ..., + name: str | None = ..., primary_key: bool = ..., + max_length: int | None = ..., unique: bool = ..., blank: bool = ..., - null: bool = ..., + *, + null: Literal[False] = ..., db_index: bool = ..., + rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str = ..., editable: bool = ..., - auto_created: bool = ..., serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., - db_comment: str | None = ..., db_tablespace: str | None = ..., + auto_created: bool = ..., validators: Iterable[validators._ValidatorCallable] = ..., error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., ) -> None: ... -class DateTimeCheckMixin: ... - -class DateField(DateTimeCheckMixin, Field[_ST, _GT]): - _pyi_private_set_type: str | date | Combinable - _pyi_private_get_type: date - _pyi_lookup_exact_type: str | date - auto_now: bool - auto_now_add: bool +class PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField[_ST, _GT]): + @overload def __init__( - self, + self: PositiveIntegerField[float | int | str | Combinable | None, int | None], verbose_name: _StrOrPromise | None = ..., name: str | None = ..., - auto_now: bool = ..., - auto_now_add: bool = ..., - *, primary_key: bool = ..., max_length: int | None = ..., unique: bool = ..., blank: bool = ..., - null: bool = ..., + *, + null: Literal[True], db_index: bool = ..., + rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str | None = ..., editable: bool = ..., - auto_created: bool = ..., serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., - db_comment: str | None = ..., db_tablespace: str | None = ..., + auto_created: bool = ..., validators: Iterable[validators._ValidatorCallable] = ..., error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., ) -> None: ... - -class TimeField(DateTimeCheckMixin, Field[_ST, _GT]): - _pyi_private_set_type: str | time | real_datetime | Combinable - _pyi_private_get_type: time - auto_now: bool - auto_now_add: bool + @overload def __init__( - self, + self: PositiveIntegerField[float | int | str | Combinable, int], verbose_name: _StrOrPromise | None = ..., name: str | None = ..., - auto_now: bool = ..., - auto_now_add: bool = ..., - *, primary_key: bool = ..., + max_length: int | None = ..., unique: bool = ..., blank: bool = ..., - null: bool = ..., + *, + null: Literal[False] = ..., db_index: bool = ..., + rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str = ..., editable: bool = ..., - auto_created: bool = ..., serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., - db_comment: str | None = ..., db_tablespace: str | None = ..., + auto_created: bool = ..., validators: Iterable[validators._ValidatorCallable] = ..., error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., ) -> None: ... -class DateTimeField(DateField[_ST, _GT]): - _pyi_private_set_type: str | real_datetime | date | Combinable - _pyi_private_get_type: real_datetime - _pyi_lookup_exact_type: str | real_datetime - -class UUIDField(Field[_ST, _GT]): - _pyi_private_set_type: str | uuid.UUID - _pyi_private_get_type: uuid.UUID - _pyi_lookup_exact_type: uuid.UUID | str +class PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, SmallIntegerField[_ST, _GT]): + @overload def __init__( - self, + self: PositiveSmallIntegerField[float | int | str | Combinable | None, int | None], verbose_name: _StrOrPromise | None = ..., - *, name: str | None = ..., primary_key: bool = ..., max_length: int | None = ..., unique: bool = ..., blank: bool = ..., - null: bool = ..., + *, + null: Literal[True], db_index: bool = ..., rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str | None = ..., editable: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., @@ -566,65 +527,1369 @@ class UUIDField(Field[_ST, _GT]): choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., - db_comment: str | None = ..., db_tablespace: str | None = ..., auto_created: bool = ..., validators: Iterable[validators._ValidatorCallable] = ..., error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., ) -> None: ... - -class FilePathField(Field[_ST, _GT]): - path: Any - match: str | None - recursive: bool - allow_files: bool - allow_folders: bool + @overload def __init__( - self, + self: PositiveSmallIntegerField[float | int | str | Combinable, int], verbose_name: _StrOrPromise | None = ..., name: str | None = ..., - path: str | Callable[..., str] = ..., - match: str | None = ..., - recursive: bool = ..., - allow_files: bool = ..., - allow_folders: bool = ..., - *, primary_key: bool = ..., - max_length: int = ..., + max_length: int | None = ..., unique: bool = ..., blank: bool = ..., - null: bool = ..., + *, + null: Literal[False] = ..., db_index: bool = ..., + rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str = ..., editable: bool = ..., - auto_created: bool = ..., serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., - db_comment: str | None = ..., db_tablespace: str | None = ..., + auto_created: bool = ..., validators: Iterable[validators._ValidatorCallable] = ..., error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., ) -> None: ... -class BinaryField(Field[_ST, _GT]): - _pyi_private_get_type: bytes | memoryview - -class DurationField(Field[_ST, _GT]): - _pyi_private_get_type: timedelta - -class AutoFieldMixin: - db_returning: bool - def deconstruct(self) -> tuple[str, str, Sequence[Any], dict[str, Any]]: ... - +class PositiveBigIntegerField(PositiveIntegerRelDbTypeMixin, BigIntegerField[_ST, _GT]): + @overload + def __init__( + self: PositiveBigIntegerField[float | int | str | Combinable | None, int | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str | None = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + @overload + def __init__( + self: PositiveBigIntegerField[float | int | str | Combinable, int], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + +class FloatField(Field[_ST, _GT]): + _pyi_private_set_type: float | int | str | Combinable + _pyi_private_get_type: float + _pyi_lookup_exact_type: float + @overload + def __init__( + self: FloatField[float | int | str | Combinable | None, float | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str | None = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + @overload + def __init__( + self: FloatField[float | int | str | Combinable, float], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + +class DecimalField(Field[_ST, _GT]): + _pyi_private_set_type: str | float | decimal.Decimal | Combinable + _pyi_private_get_type: decimal.Decimal + _pyi_lookup_exact_type: str | decimal.Decimal + # attributes + max_digits: int + decimal_places: int + @overload + def __init__( + self: DecimalField[str | float | decimal.Decimal | Combinable | None, decimal.Decimal | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + max_digits: int | None = ..., + decimal_places: int | None = ..., + *, + primary_key: bool = ..., + unique: bool = ..., + blank: bool = ..., + null: Literal[True], + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | float | decimal.Decimal | None = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + @overload + def __init__( + self: DecimalField[str | float | decimal.Decimal | Combinable, decimal.Decimal], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + max_digits: int | None = ..., + decimal_places: int | None = ..., + *, + primary_key: bool = ..., + unique: bool = ..., + blank: bool = ..., + null: Literal[False] = ..., + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | float | decimal.Decimal = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + +class CharField(Field[_ST, _GT]): + _pyi_private_set_type: str | int | Combinable + _pyi_private_get_type: str + # objects are converted to string before comparison + _pyi_lookup_exact_type: Any + @overload + def __init__( + self: CharField[str | int | Combinable | None, str | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int | None = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_collation: str | None = ..., + ) -> None: ... + @overload + def __init__( + self: CharField[str | int | Combinable, str], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_collation: str | None = ..., + ) -> None: ... + +class CommaSeparatedIntegerField(CharField[_ST, _GT]): + @overload + def __init__( + self: CommaSeparatedIntegerField[str | int | Combinable | None, str | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int | None = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_collation: str | None = ..., + ) -> None: ... + @overload + def __init__( + self: CommaSeparatedIntegerField[str | int | Combinable, str], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_collation: str | None = ..., + ) -> None: ... + +class SlugField(CharField[_ST, _GT]): + @overload + def __init__( + self: SlugField[str | int | Combinable | None, str | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int | None = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + max_length: int | None = ..., + db_index: bool = ..., + allow_unicode: bool = ..., + ) -> None: ... + @overload + def __init__( + self: SlugField[str | int | Combinable, str], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + max_length: int | None = ..., + db_index: bool = ..., + allow_unicode: bool = ..., + ) -> None: ... + +class EmailField(CharField[_ST, _GT]): + @overload + def __init__( + self: EmailField[str | int | Combinable | None, str | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int | None = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_collation: str | None = ..., + ) -> None: ... + @overload + def __init__( + self: EmailField[str | int | Combinable, str], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_collation: str | None = ..., + ) -> None: ... + +class URLField(CharField[_ST, _GT]): + @overload + def __init__( + self: URLField[str | int | Combinable | None, str | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + *, + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + null: Literal[True], + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int | None = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + @overload + def __init__( + self: URLField[str | int | Combinable, str], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + *, + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + null: Literal[False] = ..., + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + +class TextField(Field[_ST, _GT]): + _pyi_private_set_type: str | Combinable + _pyi_private_get_type: str + # objects are converted to string before comparison + _pyi_lookup_exact_type: Any + @overload + def __init__( + self: TextField[str | Combinable | None, str | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | None = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_collation: str | None = ..., + ) -> None: ... + @overload + def __init__( + self: TextField[str | Combinable, str], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_collation: str | None = ..., + ) -> None: ... + +class BooleanField(Field[_ST, _GT]): + _pyi_private_set_type: bool | Combinable + _pyi_private_get_type: bool + _pyi_lookup_exact_type: bool + @overload + def __init__( + self: BooleanField[bool | Combinable | None, bool | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | bool | None = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + @overload + def __init__( + self: BooleanField[bool | Combinable, bool], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | bool = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + +class NullBooleanField(BooleanField[bool | Combinable | None, bool | None]): + _pyi_private_set_type: bool | Combinable | None # type: ignore[assignment] + _pyi_private_get_type: bool | None # type: ignore[assignment] + _pyi_lookup_exact_type: bool | None # type: ignore[assignment] + +class IPAddressField(Field[_ST, _GT]): + _pyi_private_set_type: str | Combinable + _pyi_private_get_type: str + @overload + def __init__( + self: IPAddressField[str | Combinable | None, str | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | None = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + @overload + def __init__( + self: IPAddressField[str | Combinable, str], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + +class GenericIPAddressField(Field[_ST, _GT]): + _pyi_private_set_type: str | int | Callable[..., Any] | Combinable + _pyi_private_get_type: str + + default_error_messages: _ErrorMessagesDict + unpack_ipv4: bool + protocol: str + @overload + def __init__( + self: GenericIPAddressField[str | int | Callable[..., Any] | Combinable | None, str | None], + verbose_name: _StrOrPromise | None = ..., + name: Any | None = ..., + protocol: str = ..., + unpack_ipv4: bool = ..., + primary_key: bool = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int | Callable[..., Any] | None = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + @overload + def __init__( + self: GenericIPAddressField[str | int | Callable[..., Any] | Combinable, str], + verbose_name: _StrOrPromise | None = ..., + name: Any | None = ..., + protocol: str = ..., + unpack_ipv4: bool = ..., + primary_key: bool = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int | Callable[..., Any] = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + +class DateTimeCheckMixin: ... + +class DateField(DateTimeCheckMixin, Field[_ST, _GT]): + _pyi_private_set_type: str | date | Combinable + _pyi_private_get_type: date + _pyi_lookup_exact_type: str | date + auto_now: bool + auto_now_add: bool + @overload + def __init__( + self: DateField[str | date | Combinable | None, date | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + auto_now: bool = ..., + auto_now_add: bool = ..., + *, + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + null: Literal[True], + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | date | None = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + @overload + def __init__( + self: DateField[str | date | Combinable, date], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + auto_now: bool = ..., + auto_now_add: bool = ..., + *, + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + null: Literal[False] = ..., + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | date = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + +class TimeField(DateTimeCheckMixin, Field[_ST, _GT]): + _pyi_private_set_type: str | time | real_datetime | Combinable + _pyi_private_get_type: time + auto_now: bool + auto_now_add: bool + @overload + def __init__( + self: TimeField[str | time | real_datetime | Combinable | None, time | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + auto_now: bool = ..., + auto_now_add: bool = ..., + *, + primary_key: bool = ..., + unique: bool = ..., + blank: bool = ..., + null: Literal[True], + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | time | real_datetime | None = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + @overload + def __init__( + self: TimeField[str | time | real_datetime | Combinable, time], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + auto_now: bool = ..., + auto_now_add: bool = ..., + *, + primary_key: bool = ..., + unique: bool = ..., + blank: bool = ..., + null: Literal[False] = ..., + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | time | real_datetime = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + +class DateTimeField(DateField[_ST, _GT]): + _pyi_private_set_type: str | real_datetime | date | Combinable + _pyi_private_get_type: real_datetime + _pyi_lookup_exact_type: str | real_datetime + @overload + def __init__( + self: DateTimeField[str | real_datetime | date | Combinable | None, real_datetime | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + auto_now: bool = ..., + auto_now_add: bool = ..., + *, + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + null: Literal[True], + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | real_datetime | date | None = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + @overload + def __init__( + self: DateTimeField[str | real_datetime | date | Combinable, real_datetime], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + auto_now: bool = ..., + auto_now_add: bool = ..., + *, + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + null: Literal[False] = ..., + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | real_datetime | date = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + +class UUIDField(Field[_ST, _GT]): + _pyi_private_set_type: str | uuid.UUID + _pyi_private_get_type: uuid.UUID + _pyi_lookup_exact_type: uuid.UUID | str + @overload + def __init__( + self: UUIDField[str | uuid.UUID | None, uuid.UUID | None], + verbose_name: _StrOrPromise | None = ..., + *, + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + null: Literal[True], + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | uuid.UUID | None = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + @overload + def __init__( + self: UUIDField[str | uuid.UUID, uuid.UUID], + verbose_name: _StrOrPromise | None = ..., + *, + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + null: Literal[False] = ..., + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | str | uuid.UUID = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + +class FilePathField(Field[_ST, _GT]): + path: Any + match: str | None + recursive: bool + allow_files: bool + allow_folders: bool + def __init__( + self, + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + path: str | Callable[..., str] = ..., + match: str | None = ..., + recursive: bool = ..., + allow_files: bool = ..., + allow_folders: bool = ..., + *, + primary_key: bool = ..., + max_length: int = ..., + unique: bool = ..., + blank: bool = ..., + null: bool = ..., + db_index: bool = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_comment: str | None = ..., + db_tablespace: str | None = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + ) -> None: ... + +class BinaryField(Field[_ST, _GT]): + _pyi_private_get_type: bytes | memoryview + @overload + def __init__( + self: BinaryField[Any | None, bytes | memoryview | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | Any | None = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + @overload + def __init__( + self: BinaryField[Any, bytes | memoryview], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | Any = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + +class DurationField(Field[_ST, _GT]): + _pyi_private_get_type: timedelta + @overload + def __init__( + self: DurationField[Any | None, timedelta | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | Any | None = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + @overload + def __init__( + self: DurationField[Any, timedelta], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | Any = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + +class AutoFieldMixin: + db_returning: bool + def deconstruct(self) -> tuple[str, str, Sequence[Any], dict[str, Any]]: ... + class AutoFieldMeta(type): ... class AutoField(AutoFieldMixin, IntegerField[_ST, _GT], metaclass=AutoFieldMeta): _pyi_private_set_type: Combinable | int | str _pyi_private_get_type: int _pyi_lookup_exact_type: str | int + @overload + def __init__( + self: AutoField[Combinable | int | str | None, int | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | int | str | None = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + @overload + def __init__( + self: AutoField[Combinable | int | str, int], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | int | str = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + +class BigAutoField(AutoFieldMixin, BigIntegerField[_ST, _GT]): + @overload + def __init__( + self: BigAutoField[float | int | str | Combinable | None, int | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str | None = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + @overload + def __init__( + self: BigAutoField[float | int | str | Combinable, int], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... -class BigAutoField(AutoFieldMixin, BigIntegerField[_ST, _GT]): ... -class SmallAutoField(AutoFieldMixin, SmallIntegerField[_ST, _GT]): ... +class SmallAutoField(AutoFieldMixin, SmallIntegerField[_ST, _GT]): + @overload + def __init__( + self: SmallAutoField[float | int | str | Combinable | None, int | None], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[True], + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str | None = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... + @overload + def __init__( + self: SmallAutoField[float | int | str | Combinable, int], + verbose_name: _StrOrPromise | None = ..., + name: str | None = ..., + primary_key: bool = ..., + max_length: int | None = ..., + unique: bool = ..., + blank: bool = ..., + *, + null: Literal[False] = ..., + db_index: bool = ..., + rel: ForeignObjectRel | None = ..., + default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | float | int | str = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _Choices | None = ..., + help_text: _StrOrPromise = ..., + db_column: str | None = ..., + db_tablespace: str | None = ..., + auto_created: bool = ..., + validators: Iterable[validators._ValidatorCallable] = ..., + error_messages: _ErrorMessagesMapping | None = ..., + db_comment: str | None = ..., + ) -> None: ... diff --git a/django-stubs/db/models/fields/json.pyi b/django-stubs/db/models/fields/json.pyi index 3da0f590b..a44f6e02f 100644 --- a/django-stubs/db/models/fields/json.pyi +++ b/django-stubs/db/models/fields/json.pyi @@ -1,6 +1,6 @@ import json from collections.abc import Callable -from typing import Any, ClassVar, TypeVar +from typing import Any, ClassVar from django.db.backends.base.base import BaseDatabaseWrapper from django.db.models import lookups @@ -9,7 +9,7 @@ from django.db.models.fields import TextField from django.db.models.lookups import PostgresOperatorLookup, Transform from django.db.models.sql.compiler import SQLCompiler from django.utils.functional import _StrOrPromise -from typing_extensions import Self +from typing_extensions import Self, TypeVar from . import Field from .mixins import CheckFieldDefaultMixin diff --git a/mypy_django_plugin/transformers/fields.py b/mypy_django_plugin/transformers/fields.py index 731a102b5..17c0f348e 100644 --- a/mypy_django_plugin/transformers/fields.py +++ b/mypy_django_plugin/transformers/fields.py @@ -7,13 +7,13 @@ from mypy.maptype import map_instance_to_supertype from mypy.nodes import AssignmentStmt, NameExpr, TypeInfo from mypy.plugin import FunctionContext -from mypy.types import AnyType, Instance, NoneType, ProperType, TypeOfAny, UninhabitedType, UnionType +from mypy.types import AnyType, Instance, ProperType, TypeOfAny, UninhabitedType, UnionType from mypy.types import Type as MypyType from mypy_django_plugin.django.context import DjangoContext from mypy_django_plugin.exceptions import UnregisteredModelError from mypy_django_plugin.lib import fullnames, helpers -from mypy_django_plugin.lib.helpers import parse_bool +from mypy_django_plugin.lib.helpers import make_optional, parse_bool from mypy_django_plugin.transformers import manytomany if TYPE_CHECKING: @@ -140,35 +140,27 @@ def set_descriptor_types_for_field( null_expr = helpers.get_call_argument_by_name(ctx, "null") if null_expr is not None: is_nullable = parse_bool(null_expr) or False + # Allow setting field value to `None` when a field is primary key and has a default that can produce a value default_expr = helpers.get_call_argument_by_name(ctx, "default") primary_key_expr = helpers.get_call_argument_by_name(ctx, "primary_key") if default_expr is not None and primary_key_expr is not None: is_set_nullable = parse_bool(primary_key_expr) or False - set_type, get_type = get_field_descriptor_types( - default_return_type.type, - is_set_nullable=is_set_nullable or is_nullable, - is_get_nullable=is_get_nullable or is_nullable, - ) - - # reconcile set and get types with the base field class base_field_type = next(base for base in default_return_type.type.mro if base.fullname == fullnames.FIELD_FULLNAME) mapped_instance = map_instance_to_supertype(default_return_type, base_field_type) - mapped_set_type, mapped_get_type = mapped_instance.args - - # bail if either mapped_set_type or mapped_get_type have type Never - if not (isinstance(mapped_set_type, UninhabitedType) or isinstance(mapped_get_type, UninhabitedType)): - # always replace set_type and get_type with (non-Any) mapped types - set_type = helpers.convert_any_to_type(mapped_set_type, set_type) - get_type = helpers.convert_any_to_type(mapped_get_type, get_type) - - # the get_type must be optional if the field is nullable - if (is_get_nullable or is_nullable) and not (isinstance(get_type, NoneType) or helpers.is_optional(get_type)): - ctx.api.fail( - f"{default_return_type.type.name} is nullable but its generic get type parameter is not optional", - ctx.context, - ) + set_type, get_type = mapped_instance.args + + # If the base class wasn't explicitly parametrized, assume `Any`: + if isinstance(set_type, UninhabitedType): + set_type = AnyType(TypeOfAny.from_omitted_generics) + if isinstance(get_type, UninhabitedType): + get_type = AnyType(TypeOfAny.from_omitted_generics) + + if is_set_nullable or is_nullable: + set_type = make_optional(set_type) + if is_get_nullable or is_nullable: + get_type = make_optional(get_type) return helpers.reparametrize_instance(default_return_type, [set_type, get_type]) diff --git a/scripts/stubtest/allowlist.txt b/scripts/stubtest/allowlist.txt index ef6a09219..608d0afa3 100644 --- a/scripts/stubtest/allowlist.txt +++ b/scripts/stubtest/allowlist.txt @@ -411,3 +411,8 @@ django.contrib.sessions.base_session.AbstractBaseSession.Meta # Custom __str__ that we don't want to overcomplicate: django.forms.utils.RenderableMixin.__str__ django.forms.utils.RenderableMixin.__html__ + +# Keyword only in stubs +django.db.models.(\w*)Field.__init__ +django.db.models.fields.(\w*)Field.__init__ +django.contrib.gis.db.models.(\w*)Field.__init__ diff --git a/tests/typecheck/fields/test_base.yml b/tests/typecheck/fields/test_base.yml index 4c65dc54b..eb225f49a 100644 --- a/tests/typecheck/fields/test_base.yml +++ b/tests/typecheck/fields/test_base.yml @@ -1,4 +1,15 @@ - case: test_model_fields_classes_present_as_primitives + parametrized: + - mypy_section: | + [mypy] + plugins = + mypy_django_plugin.main + - mypy_section: | + [mypy] + disable_error_code = var-annotated + plugins = + mypy_config: | + {{ mypy_section }} main: | from myapp.models import User user = User(small_int=1, name='user', slug='user', text='user') @@ -75,6 +86,17 @@ my_pk = models.IntegerField(primary_key=True) - case: blank_and_null_char_field_allows_none + parametrized: + - mypy_section: | + [mypy] + plugins = + mypy_django_plugin.main + - mypy_section: | + [mypy] + disable_error_code = var-annotated + plugins = + mypy_config: | + {{ mypy_section }} main: | from myapp.models import MyModel MyModel(nulltext="") diff --git a/tests/typecheck/fields/test_custom_fields.yml b/tests/typecheck/fields/test_custom_fields.yml index 14d175348..44344a703 100644 --- a/tests/typecheck/fields/test_custom_fields.yml +++ b/tests/typecheck/fields/test_custom_fields.yml @@ -7,17 +7,15 @@ reveal_type(user.my_custom_field2) # N: Revealed type is "myapp.models.CustomFieldValue" reveal_type(user.my_custom_field3) # N: Revealed type is "builtins.bool" reveal_type(user.my_custom_field4) # N: Revealed type is "myapp.models.CustomFieldValue" - reveal_type(user.my_custom_field5) # N: Revealed type is "myapp.models.CustomFieldValue" - reveal_type(user.my_custom_field6) # N: Revealed type is "myapp.models.CustomFieldValue" - reveal_type(user.my_custom_field7) # N: Revealed type is "builtins.bool" - reveal_type(user.my_custom_field8) # N: Revealed type is "myapp.models.CustomFieldValue" - reveal_type(user.my_custom_field9) # N: Revealed type is "myapp.models.CustomFieldValue" - reveal_type(user.my_custom_field10) # N: Revealed type is "builtins.bool" - reveal_type(user.my_custom_field11) # N: Revealed type is "builtins.bool" - reveal_type(user.my_custom_field12) # N: Revealed type is "Union[myapp.models.CustomFieldValue, None]" - reveal_type(user.my_custom_field13) # N: Revealed type is "Union[myapp.models.CustomFieldValue, None]" - reveal_type(user.my_custom_field14) # N: Revealed type is "Union[builtins.bool, None]" - reveal_type(user.my_custom_field15) # N: Revealed type is "None" + reveal_type(user.my_custom_field5) # N: Revealed type is "Union[myapp.models.CustomFieldValue, None]" + reveal_type(user.my_custom_field6) # N: Revealed type is "Union[myapp.models.CustomFieldValue, None]" + reveal_type(user.my_custom_field7) # N: Revealed type is "Union[builtins.bool, None]" + reveal_type(user.my_custom_field8) # N: Revealed type is "Union[myapp.models.CustomFieldValue, None]" + reveal_type(user.my_custom_field9) # N: Revealed type is "Union[myapp.models.CustomFieldValue, None]" + reveal_type(user.my_custom_field10) # N: Revealed type is "Union[myapp.models.CustomFieldValue, None]" + reveal_type(user.my_custom_field11) # N: Revealed type is "Union[myapp.models.CustomFieldValue, None]" + reveal_type(user.my_custom_field12) # N: Revealed type is "Union[builtins.bool, None]" + reveal_type(user.my_custom_field13) # N: Revealed type is "None" monkeypatch: true out: | myapp/models:31: error: GenericField is nullable but its generic get type parameter is not optional [misc] @@ -67,12 +65,8 @@ my_custom_field8 = AdditionalTypeVarField[Union[CustomFieldValue, int], CustomFieldValue, bool](null=True) my_custom_field9 = fields.Field[Union[CustomFieldValue, int], CustomFieldValue](null=True) - # test overriding fields that set _pyi_private_set_type or _pyi_private_get_type - my_custom_field10 = fields.SmallIntegerField[bool, bool]() - my_custom_field11 = CustomSmallIntegerField[bool, bool]() - # test null=True on fields with non-optional generic types throw no errors - my_custom_field12 = fields.Field[Union[CustomFieldValue, int], Union[CustomFieldValue, None]](null=True) - my_custom_field13 = GenericField[Union[CustomFieldValue, int], Union[CustomFieldValue, None]](null=True) - my_custom_field14 = SingleTypeField[Union[bool, None]](null=True) - my_custom_field15 = fields.Field[None, None](null=True) + my_custom_field10 = fields.Field[Union[CustomFieldValue, int], Union[CustomFieldValue, None]](null=True) + my_custom_field11 = GenericField[Union[CustomFieldValue, int], Union[CustomFieldValue, None]](null=True) + my_custom_field12 = SingleTypeField[Union[bool, None]](null=True) + my_custom_field13 = fields.Field[None, None](null=True)