From 2cf7a510b57c47d2f56ece659cf4796e0f5fb8f3 Mon Sep 17 00:00:00 2001 From: anton Date: Thu, 14 Dec 2023 20:37:53 +0300 Subject: [PATCH 1/3] Django5 db_default --- django-stubs/db/backends/base/schema.pyi | 2 ++ django-stubs/db/models/fields/__init__.pyi | 12 ++++++++++++ django-stubs/db/models/fields/files.pyi | 1 + django-stubs/db/models/fields/related.pyi | 5 +++++ scripts/stubtest/allowlist_todo_django50.txt | 1 - 5 files changed, 20 insertions(+), 1 deletion(-) diff --git a/django-stubs/db/backends/base/schema.pyi b/django-stubs/db/backends/base/schema.pyi index bf73444a2..8abf68484 100644 --- a/django-stubs/db/backends/base/schema.pyi +++ b/django-stubs/db/backends/base/schema.pyi @@ -10,6 +10,7 @@ from django.db.models.base import Model from django.db.models.constraints import BaseConstraint from django.db.models.fields import Field from django.db.models.indexes import Index +from django.db.models.sql.compiler import _AsSqlType from typing_extensions import Self logger: Logger @@ -76,6 +77,7 @@ class BaseDatabaseSchemaEditor(AbstractContextManager[Any]): def skip_default(self, field: Any) -> bool: ... def skip_default_on_alter(self, field: Any) -> bool: ... def prepare_default(self, value: Any) -> Any: ... + def db_default_sql(self, field: Field) -> _AsSqlType: ... def effective_default(self, field: Field) -> int | str: ... def quote_value(self, value: Any) -> str: ... def create_model(self, model: type[Model]) -> None: ... diff --git a/django-stubs/db/models/fields/__init__.pyi b/django-stubs/db/models/fields/__init__.pyi index 11ff30414..76d842791 100644 --- a/django-stubs/db/models/fields/__init__.pyi +++ b/django-stubs/db/models/fields/__init__.pyi @@ -142,6 +142,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]): choices: _ChoicesList | None db_column: str | None db_comment: str | None + db_default: Any column: str concrete: bool default: Any @@ -180,6 +181,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]): validators: Iterable[validators._ValidatorCallable] = ..., error_messages: _ErrorMessagesMapping | None = ..., db_comment: str | None = ..., + db_default: Any = ..., ) -> None: ... def __set__(self, instance: Any, value: _ST) -> None: ... # class access @@ -280,6 +282,7 @@ class DecimalField(Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -308,6 +311,7 @@ class CharField(Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -337,6 +341,7 @@ class SlugField(CharField[_ST, _GT]): blank: bool = ..., null: bool = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -372,6 +377,7 @@ class URLField(CharField[_ST, _GT]): db_index: bool = ..., rel: ForeignObjectRel | None = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., @@ -403,6 +409,7 @@ class TextField(Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -453,6 +460,7 @@ class GenericIPAddressField(Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -487,6 +495,7 @@ class DateField(DateTimeCheckMixin, Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -517,6 +526,7 @@ class TimeField(DateTimeCheckMixin, Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -551,6 +561,7 @@ class UUIDField(Field[_ST, _GT]): db_index: bool = ..., rel: ForeignObjectRel | None = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., @@ -589,6 +600,7 @@ class FilePathField(Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., diff --git a/django-stubs/db/models/fields/files.pyi b/django-stubs/db/models/fields/files.pyi index bcd2cca9d..097bc8514 100644 --- a/django-stubs/db/models/fields/files.pyi +++ b/django-stubs/db/models/fields/files.pyi @@ -56,6 +56,7 @@ class FileField(Field): null: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., diff --git a/django-stubs/db/models/fields/related.pyi b/django-stubs/db/models/fields/related.pyi index 2c60b595e..e588a948b 100644 --- a/django-stubs/db/models/fields/related.pyi +++ b/django-stubs/db/models/fields/related.pyi @@ -56,6 +56,7 @@ class RelatedField(FieldCacheMixin, Field[_ST, _GT]): db_index: bool = ..., rel: ForeignObjectRel | None = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., @@ -110,6 +111,7 @@ class ForeignObject(RelatedField[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -166,6 +168,7 @@ class ForeignKey(ForeignObject[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -207,6 +210,7 @@ class OneToOneField(ForeignKey[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -267,6 +271,7 @@ class ManyToManyField(RelatedField[Any, Any], Generic[_To, _Through]): blank: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: Any = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., diff --git a/scripts/stubtest/allowlist_todo_django50.txt b/scripts/stubtest/allowlist_todo_django50.txt index da17fabd3..4050bc428 100644 --- a/scripts/stubtest/allowlist_todo_django50.txt +++ b/scripts/stubtest/allowlist_todo_django50.txt @@ -139,7 +139,6 @@ django.db.backends.base.features.BaseDatabaseFeatures.supports_nulls_distinct_un django.db.backends.base.features.BaseDatabaseFeatures.supports_stored_generated_columns django.db.backends.base.features.BaseDatabaseFeatures.supports_virtual_generated_columns django.db.backends.base.operations.BaseDatabaseOperations.prepare_join_on_clause -django.db.backends.base.schema.BaseDatabaseSchemaEditor.db_default_sql django.db.backends.mysql.features.DatabaseFeatures.allows_group_by_selected_pks django.db.backends.mysql.features.DatabaseFeatures.delete_can_self_reference_subquery django.db.backends.mysql.features.DatabaseFeatures.has_native_uuid_field From 1b8b547f8492cb485634e2203a44f95ccc2d2daa Mon Sep 17 00:00:00 2001 From: anton Date: Fri, 15 Dec 2023 14:45:51 +0300 Subject: [PATCH 2/3] Narrow db_default possible types --- django-stubs/contrib/gis/db/models/fields.pyi | 6 +++-- .../contrib/postgres/fields/array.pyi | 5 ++-- django-stubs/db/models/fields/__init__.pyi | 26 +++++++++---------- django-stubs/db/models/fields/files.pyi | 8 ++++-- django-stubs/db/models/fields/related.pyi | 21 ++++++++++----- scripts/stubtest/allowlist_todo_django50.txt | 3 --- 6 files changed, 40 insertions(+), 29 deletions(-) diff --git a/django-stubs/contrib/gis/db/models/fields.pyi b/django-stubs/contrib/gis/db/models/fields.pyi index 30e061930..3272022f1 100644 --- a/django-stubs/contrib/gis/db/models/fields.pyi +++ b/django-stubs/contrib/gis/db/models/fields.pyi @@ -13,8 +13,8 @@ from django.contrib.gis.geos import ( Polygon, ) from django.core.validators import _ValidatorCallable -from django.db.models.expressions import Combinable -from django.db.models.fields import Field, _ErrorMessagesMapping, _FieldChoices +from django.db.models.expressions import Combinable, Expression +from django.db.models.fields import NOT_PROVIDED, Field, _ErrorMessagesMapping, _FieldChoices from django.utils.functional import _StrOrPromise # __set__ value type @@ -51,6 +51,7 @@ class BaseSpatialField(Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -95,6 +96,7 @@ class GeometryField(BaseSpatialField[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., diff --git a/django-stubs/contrib/postgres/fields/array.pyi b/django-stubs/contrib/postgres/fields/array.pyi index 2b34c7885..e7a0ea6a3 100644 --- a/django-stubs/contrib/postgres/fields/array.pyi +++ b/django-stubs/contrib/postgres/fields/array.pyi @@ -3,8 +3,8 @@ from typing import Any, TypeVar from django.core.validators import _ValidatorCallable from django.db.models import Field, Transform -from django.db.models.expressions import Combinable -from django.db.models.fields import _ErrorMessagesDict, _ErrorMessagesMapping, _FieldChoices +from django.db.models.expressions import Combinable, Expression +from django.db.models.fields import NOT_PROVIDED, _ErrorMessagesDict, _ErrorMessagesMapping, _FieldChoices from django.db.models.fields.mixins import CheckFieldDefaultMixin from django.utils.functional import _StrOrPromise @@ -37,6 +37,7 @@ class ArrayField(CheckFieldDefaultMixin, Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., diff --git a/django-stubs/db/models/fields/__init__.pyi b/django-stubs/db/models/fields/__init__.pyi index 76d842791..b539c9c36 100644 --- a/django-stubs/db/models/fields/__init__.pyi +++ b/django-stubs/db/models/fields/__init__.pyi @@ -11,7 +11,7 @@ from django.core.checks import CheckMessage from django.core.exceptions import FieldDoesNotExist as FieldDoesNotExist from django.db.backends.base.base import BaseDatabaseWrapper from django.db.models import Model -from django.db.models.expressions import Col, Combinable +from django.db.models.expressions import Col, Combinable, Expression from django.db.models.fields.reverse_related import ForeignObjectRel from django.db.models.query_utils import Q, RegisterLookupMixin from django.forms import Widget @@ -142,7 +142,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]): choices: _ChoicesList | None db_column: str | None db_comment: str | None - db_default: Any + db_default: type[NOT_PROVIDED] | Expression column: str concrete: bool default: Any @@ -181,7 +181,7 @@ class Field(RegisterLookupMixin, Generic[_ST, _GT]): validators: Iterable[validators._ValidatorCallable] = ..., error_messages: _ErrorMessagesMapping | None = ..., db_comment: str | None = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., ) -> None: ... def __set__(self, instance: Any, value: _ST) -> None: ... # class access @@ -282,7 +282,7 @@ class DecimalField(Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -311,7 +311,7 @@ class CharField(Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -341,7 +341,7 @@ class SlugField(CharField[_ST, _GT]): blank: bool = ..., null: bool = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -377,7 +377,7 @@ class URLField(CharField[_ST, _GT]): db_index: bool = ..., rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., @@ -409,7 +409,7 @@ class TextField(Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -460,7 +460,7 @@ class GenericIPAddressField(Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -495,7 +495,7 @@ class DateField(DateTimeCheckMixin, Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -526,7 +526,7 @@ class TimeField(DateTimeCheckMixin, Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -561,7 +561,7 @@ class UUIDField(Field[_ST, _GT]): db_index: bool = ..., rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., @@ -600,7 +600,7 @@ class FilePathField(Field[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., diff --git a/django-stubs/db/models/fields/files.pyi b/django-stubs/db/models/fields/files.pyi index 097bc8514..29bf65d47 100644 --- a/django-stubs/db/models/fields/files.pyi +++ b/django-stubs/db/models/fields/files.pyi @@ -6,12 +6,16 @@ from django.core.files.base import File from django.core.files.images import ImageFile from django.core.files.storage import Storage from django.db.models.base import Model -from django.db.models.fields import Field, _ErrorMessagesMapping, _FieldChoices +from django.db.models.expressions import Expression +from django.db.models.fields import NOT_PROVIDED, Field, _ErrorMessagesMapping, _FieldChoices from django.db.models.query_utils import DeferredAttribute from django.utils._os import _PathCompatible from django.utils.functional import _StrOrPromise from typing_extensions import Self +# __set__ value type +_ST = TypeVar("_ST") + class FieldFile(File): instance: Model field: FileField @@ -56,7 +60,7 @@ class FileField(Field): null: bool = ..., db_index: bool = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., diff --git a/django-stubs/db/models/fields/related.pyi b/django-stubs/db/models/fields/related.pyi index e588a948b..5111a357e 100644 --- a/django-stubs/db/models/fields/related.pyi +++ b/django-stubs/db/models/fields/related.pyi @@ -4,8 +4,15 @@ from uuid import UUID from django.core import validators # due to weird mypy.stubtest error from django.db.models.base import Model -from django.db.models.expressions import Combinable -from django.db.models.fields import Field, _AllLimitChoicesTo, _ErrorMessagesMapping, _FieldChoices, _LimitChoicesTo +from django.db.models.expressions import Combinable, Expression +from django.db.models.fields import ( + NOT_PROVIDED, + Field, + _AllLimitChoicesTo, + _ErrorMessagesMapping, + _FieldChoices, + _LimitChoicesTo, +) from django.db.models.fields.mixins import FieldCacheMixin from django.db.models.fields.related_descriptors import ForwardManyToOneDescriptor as ForwardManyToOneDescriptor from django.db.models.fields.related_descriptors import ForwardOneToOneDescriptor as ForwardOneToOneDescriptor @@ -56,7 +63,7 @@ class RelatedField(FieldCacheMixin, Field[_ST, _GT]): db_index: bool = ..., rel: ForeignObjectRel | None = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., serialize: bool = ..., unique_for_date: str | None = ..., @@ -111,7 +118,7 @@ class ForeignObject(RelatedField[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -168,7 +175,7 @@ class ForeignKey(ForeignObject[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -210,7 +217,7 @@ class OneToOneField(ForeignKey[_ST, _GT]): null: bool = ..., db_index: bool = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., @@ -271,7 +278,7 @@ class ManyToManyField(RelatedField[Any, Any], Generic[_To, _Through]): blank: bool = ..., db_index: bool = ..., default: Any = ..., - db_default: Any = ..., + db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., diff --git a/scripts/stubtest/allowlist_todo_django50.txt b/scripts/stubtest/allowlist_todo_django50.txt index 4050bc428..16af5bc98 100644 --- a/scripts/stubtest/allowlist_todo_django50.txt +++ b/scripts/stubtest/allowlist_todo_django50.txt @@ -60,7 +60,6 @@ django.contrib.gis.db.models.Case.allowed_default django.contrib.gis.db.models.CheckConstraint.__init__ django.contrib.gis.db.models.ExpressionWrapper.allowed_default django.contrib.gis.db.models.F.allowed_default -django.contrib.gis.db.models.Field.__init__ django.contrib.gis.db.models.Field._get_flatchoices django.contrib.gis.db.models.Field.generated django.contrib.gis.db.models.FilteredRelation.relabeled_clone @@ -174,7 +173,6 @@ django.db.models.Case.allowed_default django.db.models.CheckConstraint.__init__ django.db.models.ExpressionWrapper.allowed_default django.db.models.F.allowed_default -django.db.models.Field.__init__ django.db.models.Field._get_flatchoices django.db.models.Field.generated django.db.models.FilteredRelation.relabeled_clone @@ -206,7 +204,6 @@ django.db.models.expressions.OrderByList.allowed_default django.db.models.expressions.RawSQL.allowed_default django.db.models.expressions.Value.allowed_default django.db.models.expressions.When.allowed_default -django.db.models.fields.Field.__init__ django.db.models.fields.Field._get_flatchoices django.db.models.fields.Field.generated django.db.models.fields.generated From b95c1e6bad3586e661d42f425660520635a0c3a9 Mon Sep 17 00:00:00 2001 From: anton Date: Sat, 16 Dec 2023 16:54:24 +0300 Subject: [PATCH 3/3] Fix broken ManyToManyField(db_default) --- django-stubs/db/models/fields/files.pyi | 5 +---- django-stubs/db/models/fields/related.pyi | 1 - 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/django-stubs/db/models/fields/files.pyi b/django-stubs/db/models/fields/files.pyi index 29bf65d47..85839ff0e 100644 --- a/django-stubs/db/models/fields/files.pyi +++ b/django-stubs/db/models/fields/files.pyi @@ -13,9 +13,6 @@ from django.utils._os import _PathCompatible from django.utils.functional import _StrOrPromise from typing_extensions import Self -# __set__ value type -_ST = TypeVar("_ST") - class FieldFile(File): instance: Model field: FileField @@ -60,7 +57,7 @@ class FileField(Field): null: bool = ..., db_index: bool = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., + db_default: type[NOT_PROVIDED] | Expression | str = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ..., diff --git a/django-stubs/db/models/fields/related.pyi b/django-stubs/db/models/fields/related.pyi index 5111a357e..ead3e49af 100644 --- a/django-stubs/db/models/fields/related.pyi +++ b/django-stubs/db/models/fields/related.pyi @@ -278,7 +278,6 @@ class ManyToManyField(RelatedField[Any, Any], Generic[_To, _Through]): blank: bool = ..., db_index: bool = ..., default: Any = ..., - db_default: type[NOT_PROVIDED] | Expression | _ST = ..., editable: bool = ..., auto_created: bool = ..., serialize: bool = ...,