From a2c10f53316362933230d113031351bdc9aa6fb2 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Fri, 2 Feb 2024 08:46:12 +0100 Subject: [PATCH 1/8] Add explicit overloads to each field class This allows type checkers other than mypy to infer correctly the `__set/get__` type variables, without the need for the plugin. The plugin logic to solve these type variables is kept, as some special casing is implemented to handle primary key fields with a default. The `Field` docstring was updated with an example reflecting this --- django-stubs/db/models/fields/__init__.pyi | 1594 +++++++++++++++++--- django-stubs/db/models/fields/json.pyi | 4 +- 2 files changed, 1410 insertions(+), 188 deletions(-) diff --git a/django-stubs/db/models/fields/__init__.pyi b/django-stubs/db/models/fields/__init__.pyi index 39b1a2a07..0aa66aa54 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,370 +260,1291 @@ 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 = ..., editable: bool = ..., - auto_created: bool = ..., serialize: bool = ..., - choices: _Choices | None = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., 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 = ..., + choices: _FieldChoices | 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 = ..., 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 = ..., + choices: _FieldChoices | 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 = ..., editable: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., unique_for_month: str | None = ..., unique_for_year: str | None = ..., - choices: _Choices | None = ..., + choices: _FieldChoices | 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 = ..., 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 = ..., + choices: _FieldChoices | 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 = ..., editable: bool = ..., - auto_created: bool = ..., serialize: bool = ..., - choices: _Choices | None = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., editable: bool = ..., - auto_created: bool = ..., serialize: bool = ..., - choices: _Choices | None = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., editable: bool = ..., - auto_created: bool = ..., serialize: bool = ..., - choices: _Choices | None = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., editable: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., unique_for_month: str | None = ..., unique_for_year: str | None = ..., - choices: _Choices | None = ..., + choices: _FieldChoices | 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 = ..., editable: bool = ..., - auto_created: bool = ..., serialize: bool = ..., - choices: _Choices | None = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _FieldChoices | 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 | _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 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 | _ST = ..., + 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 | _ST = ..., + 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 = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 | _ST = ..., + 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 | _ST = ..., + 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 = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _FieldChoices | 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 | _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 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 = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _FieldChoices | 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 | _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 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 = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _FieldChoices | 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 | _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 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 = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + auto_created: bool = ..., + serialize: bool = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 | _ST = ..., + 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 = ..., @@ -611,9 +1552,121 @@ class FilePathField(Field[_ST, _GT]): 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 @@ -625,6 +1678,175 @@ 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 = ..., + editable: bool = ..., + serialize: bool = ..., + unique_for_date: str | None = ..., + unique_for_month: str | None = ..., + unique_for_year: str | None = ..., + choices: _FieldChoices | 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 From e31a5c6f58ef42e7c88b2dca2ee25e2362972dfb Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Fri, 2 Feb 2024 08:48:59 +0100 Subject: [PATCH 2/8] Explicitly annotate some fields in the auth module This is required to run mypy without the plugin, as it would complain about these fields requiring an annotation. Using `follow_imports = silent` did not work in this case Also feels more natural than doing an assignment in a stub file --- django-stubs/contrib/auth/models.pyi | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) 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]: ... From 9cafb9d7f852a787469bf33c6f20cb452895bb22 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Fri, 2 Feb 2024 08:52:42 +0100 Subject: [PATCH 3/8] Add tests to ensure this is working without the plugin A bit of a hacky solution for now, maybe CI could be improved to add this kind of tests more easily. `var-annotated` is still an ignored error code as I wasn't able to change the assignment to an annotation for `ManyToManyField`s in my previous commit --- tests/typecheck/fields/test_base.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) 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="") From 3dda6c80e656e6a0fb28ce5777f98a3e4027f358 Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Fri, 2 Feb 2024 18:05:20 +0100 Subject: [PATCH 4/8] Add fields __init__ to allowlist Really not ideal, so open to alternatives --- scripts/stubtest/allowlist.txt | 5 +++++ 1 file changed, 5 insertions(+) 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__ From 3a7887120bbb28a88c57b6bb7662bd6c0cd34fdf Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Wed, 22 May 2024 18:41:17 +0200 Subject: [PATCH 5/8] Incorporate latest changes `db_default` is added on all overloads. `_ST` is replaced by the same set type set on `self` --- django-stubs/db/models/fields/__init__.pyi | 147 +++++++++++++-------- 1 file changed, 95 insertions(+), 52 deletions(-) diff --git a/django-stubs/db/models/fields/__init__.pyi b/django-stubs/db/models/fields/__init__.pyi index 0aa66aa54..147429278 100644 --- a/django-stubs/db/models/fields/__init__.pyi +++ b/django-stubs/db/models/fields/__init__.pyi @@ -274,12 +274,13 @@ class IntegerField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -302,12 +303,13 @@ class IntegerField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -335,12 +337,13 @@ class SmallIntegerField(IntegerField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -363,12 +366,13 @@ class SmallIntegerField(IntegerField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -394,12 +398,13 @@ class BigIntegerField(IntegerField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -422,12 +427,13 @@ class BigIntegerField(IntegerField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -452,12 +458,13 @@ class PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField[_ST, _GT] 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -480,12 +487,13 @@ class PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField[_ST, _GT] 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -510,12 +518,13 @@ class PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, SmallIntegerField 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -538,12 +547,13 @@ class PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, SmallIntegerField 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -568,12 +578,13 @@ class PositiveBigIntegerField(PositiveIntegerRelDbTypeMixin, BigIntegerField[_ST 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -596,12 +607,13 @@ class PositiveBigIntegerField(PositiveIntegerRelDbTypeMixin, BigIntegerField[_ST 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -629,12 +641,13 @@ class FloatField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -657,12 +670,13 @@ class FloatField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -693,10 +707,11 @@ class DecimalField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -718,7 +733,7 @@ class DecimalField(Field[_ST, _GT]): null: Literal[False] = ..., db_index: bool = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | str | float | decimal.Decimal = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -749,7 +764,7 @@ class CharField(Field[_ST, _GT]): null: Literal[True], db_index: bool = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int | None = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -778,7 +793,7 @@ class CharField(Field[_ST, _GT]): null: Literal[False] = ..., db_index: bool = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -809,13 +824,14 @@ class CommaSeparatedIntegerField(CharField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -837,13 +853,14 @@ class CommaSeparatedIntegerField(CharField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -865,13 +882,14 @@ class SlugField(CharField[_ST, _GT]): *, 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -893,13 +911,14 @@ class SlugField(CharField[_ST, _GT]): *, 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -925,13 +944,14 @@ class EmailField(CharField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -953,13 +973,14 @@ class EmailField(CharField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -984,12 +1005,13 @@ class URLField(CharField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -1012,7 +1034,7 @@ class URLField(CharField[_ST, _GT]): db_index: bool = ..., rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int = ..., editable: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., @@ -1046,7 +1068,7 @@ class TextField(Field[_ST, _GT]): null: Literal[True], db_index: bool = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | str | None = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -1075,13 +1097,14 @@ class TextField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -1109,12 +1132,13 @@ class BooleanField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -1137,12 +1161,13 @@ class BooleanField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -1174,12 +1199,13 @@ class IPAddressField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -1202,12 +1228,13 @@ class IPAddressField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -1238,10 +1265,11 @@ class GenericIPAddressField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -1263,7 +1291,7 @@ class GenericIPAddressField(Field[_ST, _GT]): null: Literal[False] = ..., db_index: bool = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | str | int | Callable[..., Any] = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -1299,10 +1327,11 @@ class DateField(DateTimeCheckMixin, Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -1325,7 +1354,7 @@ class DateField(DateTimeCheckMixin, Field[_ST, _GT]): null: Literal[False] = ..., db_index: bool = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | str | date = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -1357,10 +1386,11 @@ class TimeField(DateTimeCheckMixin, Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -1382,7 +1412,7 @@ class TimeField(DateTimeCheckMixin, Field[_ST, _GT]): null: Literal[False] = ..., db_index: bool = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | str | time | real_datetime = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -1414,10 +1444,11 @@ class DateTimeField(DateField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -1440,10 +1471,11 @@ class DateTimeField(DateField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -1470,12 +1502,13 @@ class UUIDField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_comment: str | None = ..., @@ -1498,7 +1531,7 @@ class UUIDField(Field[_ST, _GT]): db_index: bool = ..., rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | str | uuid.UUID = ..., editable: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., @@ -1566,12 +1599,13 @@ class BinaryField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -1594,12 +1628,13 @@ class BinaryField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -1625,12 +1660,13 @@ class DurationField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -1653,12 +1689,13 @@ class DurationField(Field[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -1692,12 +1729,13 @@ class AutoField(AutoFieldMixin, IntegerField[_ST, _GT], metaclass=AutoFieldMeta) 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -1720,12 +1758,13 @@ class AutoField(AutoFieldMixin, IntegerField[_ST, _GT], metaclass=AutoFieldMeta) 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -1750,12 +1789,13 @@ class BigAutoField(AutoFieldMixin, BigIntegerField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -1778,12 +1818,13 @@ class BigAutoField(AutoFieldMixin, BigIntegerField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -1808,12 +1849,13 @@ class SmallAutoField(AutoFieldMixin, SmallIntegerField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., @@ -1836,12 +1878,13 @@ class SmallAutoField(AutoFieldMixin, SmallIntegerField[_ST, _GT]): 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: _FieldChoices | None = ..., + choices: _Choices | None = ..., help_text: _StrOrPromise = ..., db_column: str | None = ..., db_tablespace: str | None = ..., From ec4f339ebb71051fdd3b94c7fd337a89af94273e Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Wed, 22 May 2024 19:04:18 +0200 Subject: [PATCH 6/8] Fix newly added tests --- tests/typecheck/fields/test_custom_fields.yml | 22 +++++++------------ 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/tests/typecheck/fields/test_custom_fields.yml b/tests/typecheck/fields/test_custom_fields.yml index 14d175348..02fe4ed20 100644 --- a/tests/typecheck/fields/test_custom_fields.yml +++ b/tests/typecheck/fields/test_custom_fields.yml @@ -12,12 +12,10 @@ 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_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) From b1e8662e5f5bd21aec687037385b3dcc41868d9a Mon Sep 17 00:00:00 2001 From: Viicos <65306057+Viicos@users.noreply.github.com> Date: Thu, 23 May 2024 10:22:02 +0200 Subject: [PATCH 7/8] wip: Do not infer types from `_pyi_private_*_type` --- mypy_django_plugin/transformers/fields.py | 36 ++++++++----------- tests/typecheck/fields/test_custom_fields.yml | 10 +++--- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/mypy_django_plugin/transformers/fields.py b/mypy_django_plugin/transformers/fields.py index 731a102b5..2a5711ed1 100644 --- a/mypy_django_plugin/transformers/fields.py +++ b/mypy_django_plugin/transformers/fields.py @@ -13,7 +13,7 @@ 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 parse_bool, make_optional 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/tests/typecheck/fields/test_custom_fields.yml b/tests/typecheck/fields/test_custom_fields.yml index 02fe4ed20..44344a703 100644 --- a/tests/typecheck/fields/test_custom_fields.yml +++ b/tests/typecheck/fields/test_custom_fields.yml @@ -7,11 +7,11 @@ 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_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]" From 9512835a2145649409d578fa120ff1e6a528030d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 23 May 2024 08:22:17 +0000 Subject: [PATCH 8/8] [pre-commit.ci] auto fixes from pre-commit.com hooks --- mypy_django_plugin/transformers/fields.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mypy_django_plugin/transformers/fields.py b/mypy_django_plugin/transformers/fields.py index 2a5711ed1..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, make_optional +from mypy_django_plugin.lib.helpers import make_optional, parse_bool from mypy_django_plugin.transformers import manytomany if TYPE_CHECKING: