diff --git a/django-stubs/contrib/gis/db/backends/postgis/operations.pyi b/django-stubs/contrib/gis/db/backends/postgis/operations.pyi index adeb6ca00..eee045678 100644 --- a/django-stubs/contrib/gis/db/backends/postgis/operations.pyi +++ b/django-stubs/contrib/gis/db/backends/postgis/operations.pyi @@ -2,8 +2,10 @@ from typing import Any, Literal from django.contrib.gis.db.backends.base.operations import BaseSpatialOperations from django.contrib.gis.db.backends.utils import SpatialOperator +from django.contrib.gis.db.models.fields import GeometryField from django.db.backends.postgresql.operations import DatabaseOperations from django.db.models import Func +from django.utils.functional import cached_property BILATERAL: Literal["bilateral"] @@ -16,8 +18,8 @@ class PostGISOperator(SpatialOperator): class ST_Polygon(Func): function: str def __init__(self, expr: Any) -> None: ... - @property - def output_field(self) -> Any: ... + @cached_property + def output_field(self) -> GeometryField: ... class PostGISOperations(BaseSpatialOperations, DatabaseOperations): name: str diff --git a/django-stubs/contrib/gis/db/models/functions.pyi b/django-stubs/contrib/gis/db/models/functions.pyi index 508b953e8..2a4f380ca 100644 --- a/django-stubs/contrib/gis/db/models/functions.pyi +++ b/django-stubs/contrib/gis/db/models/functions.pyi @@ -1,9 +1,12 @@ -from typing import Any +from typing import Any, ClassVar +from django.contrib.gis.db.models.fields import GeometryField +from django.contrib.gis.db.models.sql.conversion import AreaField, DistanceField from django.db.backends.base.base import BaseDatabaseWrapper -from django.db.models import Func +from django.db.models import BinaryField, BooleanField, FloatField, Func, IntegerField, TextField from django.db.models import Transform as StandardTransform from django.db.models.sql.compiler import SQLCompiler, _AsSqlType +from django.utils.functional import cached_property NUMERIC_TYPES: Any @@ -15,8 +18,8 @@ class GeoFuncMixin: class GeoFunc(GeoFuncMixin, Func): ... class GeomOutputGeoFunc(GeoFunc): - @property - def output_field(self) -> Any: ... + @cached_property + def output_field(self) -> GeometryField: ... class SQLiteDecimalToFloatMixin: def as_sqlite(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... @@ -27,17 +30,17 @@ class OracleToleranceMixin: class Area(OracleToleranceMixin, GeoFunc): arity: int - @property - def output_field(self) -> Any: ... + @cached_property + def output_field(self) -> AreaField: ... def as_sqlite(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... class Azimuth(GeoFunc): - output_field: Any + output_field: ClassVar[FloatField] arity: int geom_param_pos: Any class AsGeoJSON(GeoFunc): - output_field: Any + output_field: ClassVar[TextField] def __init__( self, expression: Any, bbox: bool = ..., crs: bool = ..., precision: int = ..., **extra: Any ) -> None: ... @@ -45,24 +48,24 @@ class AsGeoJSON(GeoFunc): class AsGML(GeoFunc): geom_param_pos: Any - output_field: Any + output_field: ClassVar[TextField] def __init__(self, expression: Any, version: int = ..., precision: int = ..., **extra: Any) -> None: ... def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... class AsKML(GeoFunc): - output_field: Any + output_field: ClassVar[TextField] def __init__(self, expression: Any, precision: int = ..., **extra: Any) -> None: ... class AsSVG(GeoFunc): - output_field: Any + output_field: ClassVar[TextField] def __init__(self, expression: Any, relative: bool = ..., precision: int = ..., **extra: Any) -> None: ... class AsWKB(GeoFunc): - output_field: Any + output_field: ClassVar[BinaryField] arity: int class AsWKT(GeoFunc): - output_field: Any + output_field: ClassVar[TextField] arity: int class BoundingCircle(OracleToleranceMixin, GeomOutputGeoFunc): @@ -77,8 +80,8 @@ class Difference(OracleToleranceMixin, GeomOutputGeoFunc): geom_param_pos: Any class DistanceResultMixin: - @property - def output_field(self) -> Any: ... + @cached_property + def output_field(self) -> DistanceField: ... def source_is_geography(self) -> Any: ... class Distance(DistanceResultMixin, OracleToleranceMixin, GeoFunc): @@ -97,20 +100,20 @@ class ForcePolygonCW(GeomOutputGeoFunc): arity: int class FromWKB(GeoFunc): - output_field: Any + output_field: ClassVar[GeometryField] arity: int class FromWKT(GeoFunc): - output_field: Any + output_field: ClassVar[GeometryField] arity: int class GeoHash(GeoFunc): - output_field: Any + output_field: ClassVar[TextField] def __init__(self, expression: Any, precision: Any | None = ..., **extra: Any) -> None: ... def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... class GeometryDistance(GeoFunc): - output_field: Any + output_field: ClassVar[FloatField] arity: int function: str arg_joiner: str @@ -122,11 +125,11 @@ class Intersection(OracleToleranceMixin, GeomOutputGeoFunc): class IsEmpty(GeoFuncMixin, StandardTransform): lookup_name: str - output_field: Any + output_field: ClassVar[BooleanField] class IsValid(OracleToleranceMixin, GeoFuncMixin, StandardTransform): lookup_name: str - output_field: Any + output_field: ClassVar[BooleanField] def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... class Length(DistanceResultMixin, OracleToleranceMixin, GeoFunc): @@ -138,22 +141,22 @@ class Length(DistanceResultMixin, OracleToleranceMixin, GeoFunc): def as_sqlite(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... class LineLocatePoint(GeoFunc): - output_field: Any + output_field: ClassVar[FloatField] arity: int geom_param_pos: Any class MakeValid(GeomOutputGeoFunc): ... class MemSize(GeoFunc): - output_field: Any + output_field: ClassVar[IntegerField] arity: int class NumGeometries(GeoFunc): - output_field: Any + output_field: ClassVar[IntegerField] arity: int class NumPoints(GeoFunc): - output_field: Any + output_field: ClassVar[IntegerField] arity: int class Perimeter(DistanceResultMixin, OracleToleranceMixin, GeoFunc): diff --git a/django-stubs/contrib/postgres/aggregates/general.pyi b/django-stubs/contrib/postgres/aggregates/general.pyi index b38f30789..f42e82b8c 100644 --- a/django-stubs/contrib/postgres/aggregates/general.pyi +++ b/django-stubs/contrib/postgres/aggregates/general.pyi @@ -1,11 +1,25 @@ -from django.db.models.aggregates import Aggregate +from typing import ClassVar + +from django.contrib.postgres.fields import ArrayField +from django.db.models import Aggregate, BooleanField, JSONField, TextField from .mixins import OrderableAggMixin -class ArrayAgg(OrderableAggMixin, Aggregate): ... +class ArrayAgg(OrderableAggMixin, Aggregate): + @property + def output_field(self) -> ArrayField: ... + class BitAnd(Aggregate): ... class BitOr(Aggregate): ... -class BoolAnd(Aggregate): ... -class BoolOr(Aggregate): ... -class JSONBAgg(OrderableAggMixin, Aggregate): ... -class StringAgg(OrderableAggMixin, Aggregate): ... + +class BoolAnd(Aggregate): + output_field: ClassVar[BooleanField] + +class BoolOr(Aggregate): + output_field: ClassVar[BooleanField] + +class JSONBAgg(OrderableAggMixin, Aggregate): + output_field: ClassVar[JSONField] + +class StringAgg(OrderableAggMixin, Aggregate): + output_field: ClassVar[TextField] diff --git a/django-stubs/contrib/postgres/aggregates/statistics.pyi b/django-stubs/contrib/postgres/aggregates/statistics.pyi index 9e7d1380c..986736af9 100644 --- a/django-stubs/contrib/postgres/aggregates/statistics.pyi +++ b/django-stubs/contrib/postgres/aggregates/statistics.pyi @@ -1,11 +1,18 @@ -from django.db.models.aggregates import Aggregate +from typing import ClassVar + +from django.db.models import Aggregate, FloatField, IntegerField + +class StatAggregate(Aggregate): + output_field: ClassVar[FloatField] -class StatAggregate(Aggregate): ... class Corr(StatAggregate): ... class CovarPop(StatAggregate): ... class RegrAvgX(StatAggregate): ... class RegrAvgY(StatAggregate): ... -class RegrCount(StatAggregate): ... + +class RegrCount(StatAggregate): + output_field: ClassVar[IntegerField] # type: ignore[assignment] + class RegrIntercept(StatAggregate): ... class RegrR2(StatAggregate): ... class RegrSlope(StatAggregate): ... diff --git a/django-stubs/contrib/postgres/fields/hstore.pyi b/django-stubs/contrib/postgres/fields/hstore.pyi index 207f79037..179722afa 100644 --- a/django-stubs/contrib/postgres/fields/hstore.pyi +++ b/django-stubs/contrib/postgres/fields/hstore.pyi @@ -1,17 +1,23 @@ -from typing import Any +from typing import Any, ClassVar -from django.db.models import Field, Transform +from django.contrib.postgres.fields.array import ArrayField +from django.db.models import Field, TextField, Transform from django.db.models.fields.mixins import CheckFieldDefaultMixin class HStoreField(CheckFieldDefaultMixin, Field): def get_transform(self, name: str) -> Any: ... class KeyTransform(Transform): + output_field: ClassVar[TextField] + def __init__(self, key_name: str, *args: Any, **kwargs: Any) -> None: ... class KeyTransformFactory: def __init__(self, key_name: str) -> None: ... def __call__(self, *args: Any, **kwargs: Any) -> KeyTransform: ... -class KeysTransform(Transform): ... -class ValuesTransform(Transform): ... +class KeysTransform(Transform): + output_field: ClassVar[ArrayField] + +class ValuesTransform(Transform): + output_field: ClassVar[ArrayField] diff --git a/django-stubs/contrib/postgres/fields/ranges.pyi b/django-stubs/contrib/postgres/fields/ranges.pyi index 7600d864f..006695691 100644 --- a/django-stubs/contrib/postgres/fields/ranges.pyi +++ b/django-stubs/contrib/postgres/fields/ranges.pyi @@ -1,4 +1,4 @@ -from typing import Any, Literal +from typing import Any, ClassVar, Literal from django.db import models from django.db.models.lookups import PostgresOperatorLookup @@ -43,68 +43,36 @@ class DateTimeRangeField(RangeField): class DateRangeField(RangeField): def __get__(self, instance: Any, owner: Any) -> DateRange: ... -class DateTimeRangeContains(PostgresOperatorLookup): - lookup_name: str - postgres_operator: str +class DateTimeRangeContains(PostgresOperatorLookup): ... class RangeContainedBy(PostgresOperatorLookup): - lookup_name: str type_mapping: dict[str, str] - postgres_operator: str -class FullyLessThan(PostgresOperatorLookup): - lookup_name: str - postgres_operator: str - -class FullGreaterThan(PostgresOperatorLookup): - lookup_name: str - postgres_operator: str - -class NotLessThan(PostgresOperatorLookup): - lookup_name: str - postgres_operator: str - -class NotGreaterThan(PostgresOperatorLookup): - lookup_name: str - postgres_operator: str - -class AdjacentToLookup(PostgresOperatorLookup): - lookup_name: str - postgres_operator: str +class FullyLessThan(PostgresOperatorLookup): ... +class FullGreaterThan(PostgresOperatorLookup): ... +class NotLessThan(PostgresOperatorLookup): ... +class NotGreaterThan(PostgresOperatorLookup): ... +class AdjacentToLookup(PostgresOperatorLookup): ... class RangeStartsWith(models.Transform): - lookup_name: str - function: str @property def output_field(self) -> models.Field: ... class RangeEndsWith(models.Transform): - lookup_name: str - function: str @property def output_field(self) -> models.Field: ... class IsEmpty(models.Transform): - lookup_name: str - function: str - output_field: models.BooleanField + output_field: ClassVar[models.BooleanField] class LowerInclusive(models.Transform): - lookup_name: str - function: str - output_field: models.BooleanField + output_field: ClassVar[models.BooleanField] class LowerInfinite(models.Transform): - lookup_name: str - function: str - output_field: models.BooleanField + output_field: ClassVar[models.BooleanField] class UpperInclusive(models.Transform): - lookup_name: str - function: str - output_field: models.BooleanField + output_field: ClassVar[models.BooleanField] class UpperInfinite(models.Transform): - lookup_name: str - function: str - output_field: models.BooleanField + output_field: ClassVar[models.BooleanField] diff --git a/django-stubs/contrib/postgres/functions.pyi b/django-stubs/contrib/postgres/functions.pyi index 414a0998a..2d957735d 100644 --- a/django-stubs/contrib/postgres/functions.pyi +++ b/django-stubs/contrib/postgres/functions.pyi @@ -1,4 +1,9 @@ -from django.db.models import Func +from typing import ClassVar -class RandomUUID(Func): ... -class TransactionNow(Func): ... +from django.db.models import DateTimeField, Func, UUIDField + +class RandomUUID(Func): + output_field: ClassVar[UUIDField] + +class TransactionNow(Func): + output_field: ClassVar[DateTimeField] diff --git a/django-stubs/contrib/postgres/search.pyi b/django-stubs/contrib/postgres/search.pyi index f3e0dcc5f..1687a8a09 100644 --- a/django-stubs/contrib/postgres/search.pyi +++ b/django-stubs/contrib/postgres/search.pyi @@ -1,6 +1,6 @@ -from typing import Any +from typing import Any, ClassVar -from django.db.models import Expression, Field +from django.db.models import Expression, Field, FloatField, TextField from django.db.models.expressions import Combinable, CombinedExpression, Func from django.db.models.lookups import Lookup from typing_extensions import Self, TypeAlias @@ -24,7 +24,7 @@ class SearchVector(SearchVectorCombinable, Func): config: _Expression | None function: str arg_joiner: str - output_field: Field + output_field: ClassVar[SearchVectorField] def __init__( self, *expressions: _Expression, config: _Expression | None = ..., weight: Any | None = ... ) -> None: ... @@ -48,6 +48,7 @@ class SearchQueryCombinable: def __rand__(self, other: SearchQueryCombinable) -> Self: ... class SearchQuery(SearchQueryCombinable, Func): # type: ignore[misc] + output_field: ClassVar[SearchQueryField] SEARCH_TYPES: dict[str, str] def __init__( self, @@ -71,6 +72,7 @@ class CombinedSearchQuery(SearchQueryCombinable, CombinedExpression): # type: i ) -> None: ... class SearchRank(Func): + output_field: ClassVar[FloatField] def __init__( self, vector: SearchVector | _Expression, @@ -83,7 +85,7 @@ class SearchRank(Func): class SearchHeadline(Func): function: str template: str - output_field: Field + output_field: ClassVar[TextField] def __init__( self, expression: _Expression, @@ -101,9 +103,11 @@ class SearchHeadline(Func): ) -> None: ... class TrigramBase(Func): + output_field: ClassVar[FloatField] def __init__(self, expression: _Expression, string: str, **extra: Any) -> None: ... class TrigramWordBase(Func): + output_field: ClassVar[FloatField] def __init__(self, string: str, expression: _Expression, **extra: Any) -> None: ... class TrigramSimilarity(TrigramBase): ... diff --git a/django-stubs/db/models/aggregates.pyi b/django-stubs/db/models/aggregates.pyi index e712f937d..2e00bca4a 100644 --- a/django-stubs/db/models/aggregates.pyi +++ b/django-stubs/db/models/aggregates.pyi @@ -1,6 +1,7 @@ -from typing import Any +from typing import Any, ClassVar from django.db.models.expressions import Func +from django.db.models.fields import IntegerField from django.db.models.functions.mixins import FixDurationInputMixin, NumericOutputFieldMixin class Aggregate(Func): @@ -10,7 +11,10 @@ class Aggregate(Func): def __init__(self, *expressions: Any, distinct: bool = ..., filter: Any | None = ..., **extra: Any) -> None: ... class Avg(FixDurationInputMixin, NumericOutputFieldMixin, Aggregate): ... -class Count(Aggregate): ... + +class Count(Aggregate): + output_field: ClassVar[IntegerField] + class Max(Aggregate): ... class Min(Aggregate): ... class StdDev(NumericOutputFieldMixin, Aggregate): ... diff --git a/django-stubs/db/models/expressions.pyi b/django-stubs/db/models/expressions.pyi index 4ff89770e..cbb55ab98 100644 --- a/django-stubs/db/models/expressions.pyi +++ b/django-stubs/db/models/expressions.pyi @@ -4,7 +4,7 @@ from decimal import Decimal from typing import Any, ClassVar, Generic, Literal, TypeVar from django.db.backends.base.base import BaseDatabaseWrapper -from django.db.models import Q +from django.db.models import Q, fields from django.db.models.fields import Field from django.db.models.lookups import Lookup, Transform from django.db.models.query import QuerySet @@ -85,7 +85,7 @@ class BaseExpression: def conditional(self) -> bool: ... @property def field(self) -> Field: ... - @property + @cached_property def output_field(self) -> Field: ... @cached_property def convert_value(self) -> Callable: ... @@ -124,6 +124,7 @@ class DurationExpression(CombinedExpression): def compile(self, side: Combinable, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ... class TemporalSubtraction(CombinedExpression): + output_field: ClassVar[fields.DurationField] def __init__(self, lhs: Combinable, rhs: Combinable) -> None: ... class F(_Deconstructible, Combinable): @@ -241,6 +242,7 @@ class Subquery(BaseExpression, Combinable): def __init__(self, queryset: Query | QuerySet, output_field: Field | None = ..., **extra: Any) -> None: ... class Exists(Subquery): + output_field: ClassVar[fields.BooleanField] def __init__(self, queryset: Query | QuerySet, **kwargs: Any) -> None: ... class OrderBy(Expression): diff --git a/django-stubs/db/models/fields/json.pyi b/django-stubs/db/models/fields/json.pyi index 4ab220f11..544fb03ea 100644 --- a/django-stubs/db/models/fields/json.pyi +++ b/django-stubs/db/models/fields/json.pyi @@ -1,9 +1,10 @@ import json from collections.abc import Callable -from typing import Any +from typing import Any, ClassVar from django.db.backends.base.base import BaseDatabaseWrapper from django.db.models import lookups +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 @@ -57,6 +58,7 @@ class KeyTransform(Transform): class KeyTextTransform(KeyTransform): postgres_operator: str postgres_nested_operator: str + output_field: ClassVar[TextField] @classmethod def from_lookup(cls, lookup: str) -> Self: ... diff --git a/django-stubs/db/models/functions/comparison.pyi b/django-stubs/db/models/functions/comparison.pyi index fb1a63385..50590a9dc 100644 --- a/django-stubs/db/models/functions/comparison.pyi +++ b/django-stubs/db/models/functions/comparison.pyi @@ -1,4 +1,4 @@ -from typing import Any +from typing import Any, ClassVar from django.db.models import Func from django.db.models.fields import Field @@ -16,7 +16,7 @@ class Greatest(Func): ... class JSONObject(Func): def __init__(self, **fields: Any) -> None: ... - output_field: JSONField + output_field: ClassVar[JSONField] class Least(Func): ... class NullIf(Func): ... diff --git a/django-stubs/db/models/functions/datetime.pyi b/django-stubs/db/models/functions/datetime.pyi index e5ce958ae..b2469e33e 100644 --- a/django-stubs/db/models/functions/datetime.pyi +++ b/django-stubs/db/models/functions/datetime.pyi @@ -1,4 +1,4 @@ -from typing import Any +from typing import Any, ClassVar from django.db import models from django.db.models import Func, Transform @@ -9,7 +9,7 @@ class TimezoneMixin: class Extract(TimezoneMixin, Transform): lookup_name: str - output_field: models.IntegerField + output_field: ClassVar[models.IntegerField] def __init__( self, expression: Any, lookup_name: str | None = ..., tzinfo: Any | None = ..., **extra: Any ) -> None: ... @@ -27,7 +27,7 @@ class ExtractMinute(Extract): ... class ExtractSecond(Extract): ... class Now(Func): - output_field: models.DateTimeField + output_field: ClassVar[models.DateTimeField] class TruncBase(TimezoneMixin, Transform): kind: str @@ -41,10 +41,10 @@ class TruncWeek(TruncBase): ... class TruncDay(TruncBase): ... class TruncDate(TruncBase): - output_field: models.DateField + output_field: ClassVar[models.DateField] class TruncTime(TruncBase): - output_field: models.TimeField + output_field: ClassVar[models.TimeField] class TruncHour(TruncBase): ... class TruncMinute(TruncBase): ... diff --git a/django-stubs/db/models/functions/text.pyi b/django-stubs/db/models/functions/text.pyi index e71cbf571..0be24be07 100644 --- a/django-stubs/db/models/functions/text.pyi +++ b/django-stubs/db/models/functions/text.pyi @@ -1,4 +1,4 @@ -from typing import Any +from typing import Any, ClassVar from django.db import models from django.db.backends.base.base import BaseDatabaseWrapper @@ -31,20 +31,20 @@ class Concat(Func): def __init__(self, *expressions: Any, **extra: Any) -> None: ... class Left(Func): - output_field: models.CharField + output_field: ClassVar[models.CharField] def __init__(self, expression: Expression | str, length: Expression | int, **extra: Any) -> None: ... def get_substr(self) -> Substr: ... def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... def as_sqlite(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... class Length(Transform): - output_field: models.IntegerField + output_field: ClassVar[models.IntegerField] def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... class Lower(Transform): ... class LPad(Func): - output_field: models.CharField + output_field: ClassVar[models.CharField] def __init__( self, expression: Expression | str, length: Expression | int | None, fill_text: Expression = ..., **extra: Any ) -> None: ... @@ -52,12 +52,12 @@ class LPad(Func): class LTrim(Transform): ... class Ord(Transform): - output_field: models.IntegerField + output_field: ClassVar[models.IntegerField] def as_sqlite(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... def as_mysql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... class Repeat(Func): - output_field: models.CharField + output_field: ClassVar[models.CharField] def __init__(self, expression: Expression | str, number: Expression | int | None, **extra: Any) -> None: ... def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... @@ -82,13 +82,13 @@ class SHA384(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): .. class SHA512(MySQLSHA2Mixin, OracleHashMixin, PostgreSQLSHAMixin, Transform): ... class StrIndex(Func): - output_field: models.IntegerField + output_field: ClassVar[models.IntegerField] def as_postgresql( self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any ) -> _AsSqlType: ... class Substr(Func): - output_field: models.CharField + output_field: ClassVar[models.CharField] def __init__( self, expression: Expression | str, pos: Expression | int, length: Expression | int | None = ..., **extra: Any ) -> None: ... diff --git a/django-stubs/db/models/functions/window.pyi b/django-stubs/db/models/functions/window.pyi index 7de622d19..59152c395 100644 --- a/django-stubs/db/models/functions/window.pyi +++ b/django-stubs/db/models/functions/window.pyi @@ -1,13 +1,13 @@ -from typing import Any +from typing import Any, ClassVar from django.db import models from django.db.models.expressions import Func class CumeDist(Func): - output_field: models.FloatField + output_field: ClassVar[models.FloatField] class DenseRank(Func): - output_field: models.IntegerField + output_field: ClassVar[models.IntegerField] class FirstValue(Func): ... @@ -23,13 +23,13 @@ class NthValue(Func): class Ntile(Func): def __init__(self, num_buckets: int = ..., **extra: Any) -> None: ... - output_field: models.IntegerField + output_field: ClassVar[models.IntegerField] class PercentRank(Func): - output_field: models.FloatField + output_field: ClassVar[models.FloatField] class Rank(Func): - output_field: models.IntegerField + output_field: ClassVar[models.IntegerField] class RowNumber(Func): - output_field: models.IntegerField + output_field: ClassVar[models.IntegerField] diff --git a/django-stubs/db/models/lookups.pyi b/django-stubs/db/models/lookups.pyi index c97b3b22b..1ce6dccb4 100644 --- a/django-stubs/db/models/lookups.pyi +++ b/django-stubs/db/models/lookups.pyi @@ -1,6 +1,7 @@ from collections.abc import Iterable, Mapping from typing import Any, Generic, Literal, TypeVar +from db.models import BooleanField from django.db.backends.base.base import BaseDatabaseWrapper from django.db.models.expressions import Expression, Func from django.db.models.query_utils import RegisterLookupMixin @@ -37,6 +38,8 @@ class Lookup(Generic[_T]): def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ... def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ... @cached_property + def output_field(self) -> BooleanField: ... + @cached_property def contains_aggregate(self) -> bool: ... @cached_property def contains_over_clause(self) -> bool: ... diff --git a/django-stubs/db/models/sql/where.pyi b/django-stubs/db/models/sql/where.pyi index 32d00bba9..537133974 100644 --- a/django-stubs/db/models/sql/where.pyi +++ b/django-stubs/db/models/sql/where.pyi @@ -1,6 +1,7 @@ from collections.abc import Sequence from typing import Any +from db.models import BooleanField from django.db.backends.base.base import BaseDatabaseWrapper from django.db.models.expressions import Expression from django.db.models.sql.compiler import SQLCompiler, _AsSqlType @@ -25,6 +26,8 @@ class WhereNode(tree.Node): def relabeled_clone(self, change_map: dict[str | None, str]) -> WhereNode: ... def resolve_expression(self, *args: Any, **kwargs: Any) -> WhereNode: ... @cached_property + def output_field(self) -> BooleanField: ... + @cached_property def contains_aggregate(self) -> bool: ... @cached_property def contains_over_clause(self) -> bool: ... diff --git a/scripts/stubtest/allowlist.txt b/scripts/stubtest/allowlist.txt index b6373fdd7..40376cb50 100644 --- a/scripts/stubtest/allowlist.txt +++ b/scripts/stubtest/allowlist.txt @@ -172,6 +172,7 @@ django.contrib.gis.db.backends.mysql.operations.MySQLOperations.mariadb django.contrib.gis.db.backends.mysql.operations.MySQLOperations.mysql django.contrib.gis.db.backends.mysql.operations.MySQLOperations.select django.contrib.gis.db.backends.mysql.operations.MySQLOperations.unsupported_functions +django.contrib.gis.db.backends.postgis.operations.ST_Polygon.output_field django.contrib.gis.db.backends.spatialite.features.DatabaseFeatures.supports_area_geodetic django.contrib.gis.db.backends.spatialite.operations.SpatiaLiteOperations.unsupported_functions django.contrib.gis.db.models.DecimalField.validators @@ -191,6 +192,10 @@ django.contrib.gis.db.models.ForeignObjectRel.related_model django.contrib.gis.db.models.IntegerField.validators django.contrib.gis.db.models.Lookup.contains_aggregate django.contrib.gis.db.models.Lookup.contains_over_clause +django.contrib.gis.db.models.aggregates.GeoAggregate.output_field +django.contrib.gis.db.models.functions.Area.output_field +django.contrib.gis.db.models.functions.DistanceResultMixin.output_field +django.contrib.gis.db.models.functions.GeomOutputGeoFunc.output_field django.contrib.gis.forms.BaseForm.changed_data django.contrib.gis.forms.BaseFormSet.forms django.contrib.gis.forms.BaseFormSet.management_form @@ -305,9 +310,10 @@ django.db.models.Lookup.contains_aggregate django.db.models.Lookup.contains_over_clause django.db.models.expressions.BaseExpression.contains_aggregate django.db.models.expressions.BaseExpression.contains_column_references -django.db.models.expressions.BaseExpression.contains_subquery django.db.models.expressions.BaseExpression.contains_over_clause +django.db.models.expressions.BaseExpression.contains_subquery django.db.models.expressions.BaseExpression.convert_value +django.db.models.expressions.BaseExpression.output_field django.db.models.fields.DecimalField.validators django.db.models.fields.Field.cached_col django.db.models.fields.Field.validators diff --git a/scripts/stubtest/allowlist_todo.txt b/scripts/stubtest/allowlist_todo.txt index 495e88301..79f4e005f 100644 --- a/scripts/stubtest/allowlist_todo.txt +++ b/scripts/stubtest/allowlist_todo.txt @@ -415,7 +415,6 @@ django.contrib.gis.db.models.JSONField.from_db_value django.contrib.gis.db.models.JSONField.get_transform django.contrib.gis.db.models.Lookup.get_prep_lhs django.contrib.gis.db.models.Lookup.lookup_name -django.contrib.gis.db.models.Lookup.output_field django.contrib.gis.db.models.Lookup.relabeled_clone django.contrib.gis.db.models.Lookup.resolve_expression django.contrib.gis.db.models.Lookup.select_format @@ -491,7 +490,6 @@ django.contrib.gis.db.models.aggregates.Extent.is_extent django.contrib.gis.db.models.aggregates.Extent3D.is_extent django.contrib.gis.db.models.aggregates.GeoAggregate.as_sql django.contrib.gis.db.models.aggregates.GeoAggregate.function -django.contrib.gis.db.models.aggregates.GeoAggregate.output_field django.contrib.gis.db.models.fields.BaseSpatialField.class_lookups django.contrib.gis.db.models.fields.GeometryField.contribute_to_class django.contrib.gis.db.models.fields.RasterField.contribute_to_class @@ -1069,7 +1067,6 @@ django.db.models.JSONField.from_db_value django.db.models.JSONField.get_transform django.db.models.Lookup.get_prep_lhs django.db.models.Lookup.lookup_name -django.db.models.Lookup.output_field django.db.models.Lookup.relabeled_clone django.db.models.Lookup.resolve_expression django.db.models.Lookup.select_format @@ -1169,7 +1166,6 @@ django.db.models.constraints.UniqueConstraint.contains_expressions django.db.models.constraints.UniqueConstraint.validate django.db.models.expressions.BaseExpression.empty_result_set_value django.db.models.expressions.BaseExpression.get_refs -django.db.models.expressions.BaseExpression.output_field django.db.models.expressions.BaseExpression.prefix_references django.db.models.expressions.BaseExpression.replace_expressions django.db.models.expressions.BaseExpression.select_format @@ -1440,7 +1436,6 @@ django.db.models.lookups.FieldGetDbPrepValueIterableMixin.process_rhs django.db.models.lookups.IExact.process_rhs django.db.models.lookups.Lookup.get_prep_lhs django.db.models.lookups.Lookup.lookup_name -django.db.models.lookups.Lookup.output_field django.db.models.lookups.Lookup.relabeled_clone django.db.models.lookups.Lookup.resolve_expression django.db.models.lookups.Lookup.select_format @@ -1624,7 +1619,6 @@ django.db.models.sql.where.WhereNode.get_lookup django.db.models.sql.where.WhereNode.get_refs django.db.models.sql.where.WhereNode.get_source_expressions django.db.models.sql.where.WhereNode.leaves -django.db.models.sql.where.WhereNode.output_field django.db.models.sql.where.WhereNode.replace_expressions django.db.models.sql.where.WhereNode.select_format django.db.models.sql.where.WhereNode.set_source_expressions