From 48b48080eb317fcb012b24ce43145a16a53645c0 Mon Sep 17 00:00:00 2001 From: ahmedasar00 Date: Sun, 22 Mar 2026 09:48:19 +0200 Subject: [PATCH 1/3] Fix GIS as_sql stub signatures to match runtime --- .../contrib/gis/db/models/functions.pyi | 20 +++++++++++++++++++ .../contrib/gis/db/models/lookups.pyi | 6 +++++- scripts/stubtest/allowlist_todo.txt | 4 ---- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/django-stubs/contrib/gis/db/models/functions.pyi b/django-stubs/contrib/gis/db/models/functions.pyi index bee8e4076..d5b05e8c3 100644 --- a/django-stubs/contrib/gis/db/models/functions.pyi +++ b/django-stubs/contrib/gis/db/models/functions.pyi @@ -20,6 +20,18 @@ class GeoFuncMixin: def name(self) -> str: ... @cached_property def geo_field(self) -> Any: ... + # GeoFuncMixin.as_sql drops `template` and `arg_joiner` vs Func.as_sql, but forwards + # **extra_context to super().as_sql — so callers can still pass them and they work. + # We keep the full Func.as_sql-compatible signature here to avoid MRO conflicts. + def as_sql( + self, + compiler: SQLCompiler, + connection: BaseDatabaseWrapper, + function: str | None = None, + template: str | None = None, + arg_joiner: str | None = None, + **extra_context: Any, + ) -> _AsSqlType: ... def resolve_expression( self, *args: Any, @@ -46,6 +58,10 @@ class Area(OracleToleranceMixin, GeoFunc): @override def output_field(self) -> AreaField: ... @override + def as_sql( # type: ignore[override] + self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any + ) -> _AsSqlType: ... + @override def as_sqlite(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... class Azimuth(GeoFunc): @@ -160,6 +176,10 @@ class IsValid(OracleToleranceMixin, GeoFuncMixin, StandardTransform): class Length(DistanceResultMixin, OracleToleranceMixin, GeoFunc): spheroid: Any def __init__(self, expr1: Any, spheroid: bool = True, **extra: Any) -> None: ... + @override + def as_sql( # type: ignore[override] + self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any + ) -> _AsSqlType: ... def as_postgresql( self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any ) -> _AsSqlType: ... diff --git a/django-stubs/contrib/gis/db/models/lookups.pyi b/django-stubs/contrib/gis/db/models/lookups.pyi index 202559447..9c7b4a901 100644 --- a/django-stubs/contrib/gis/db/models/lookups.pyi +++ b/django-stubs/contrib/gis/db/models/lookups.pyi @@ -1,9 +1,13 @@ from typing import Any +from django.db.backends.base.base import BaseDatabaseWrapper from django.db.models import Lookup, Transform +from django.db.models.sql.compiler import SQLCompiler, _AsSqlType from typing_extensions import override -class RasterBandTransform(Transform): ... +class RasterBandTransform(Transform): + @override + def as_sql(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper) -> _AsSqlType: ... # type: ignore[override] class GISLookup(Lookup): sql_template: Any diff --git a/scripts/stubtest/allowlist_todo.txt b/scripts/stubtest/allowlist_todo.txt index ac5d27a21..3cb02bee7 100644 --- a/scripts/stubtest/allowlist_todo.txt +++ b/scripts/stubtest/allowlist_todo.txt @@ -79,10 +79,6 @@ django.contrib.gis.admin.site django.contrib.gis.db.backends.spatialite.base.DatabaseWrapper.ops django.contrib.gis.db.models.CharField.description django.contrib.gis.db.models.Field.description -django.contrib.gis.db.models.functions.Area.as_sql -django.contrib.gis.db.models.functions.GeoFuncMixin.as_sql -django.contrib.gis.db.models.functions.Length.as_sql -django.contrib.gis.db.models.lookups.RasterBandTransform.as_sql django.contrib.gis.forms.inlineformset_factory django.contrib.gis.forms.modelformset_factory django.contrib.redirects.models.Redirect.id From 7511a9f33e72142086549cbcabf517d0d82bc4e8 Mon Sep 17 00:00:00 2001 From: ahmedasar00 Date: Sun, 22 Mar 2026 21:35:01 +0200 Subject: [PATCH 2/3] Add missing as_sql for GIS function --- .../contrib/gis/db/models/functions.pyi | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/django-stubs/contrib/gis/db/models/functions.pyi b/django-stubs/contrib/gis/db/models/functions.pyi index d5b05e8c3..dd88b31f0 100644 --- a/django-stubs/contrib/gis/db/models/functions.pyi +++ b/django-stubs/contrib/gis/db/models/functions.pyi @@ -20,16 +20,11 @@ class GeoFuncMixin: def name(self) -> str: ... @cached_property def geo_field(self) -> Any: ... - # GeoFuncMixin.as_sql drops `template` and `arg_joiner` vs Func.as_sql, but forwards - # **extra_context to super().as_sql — so callers can still pass them and they work. - # We keep the full Func.as_sql-compatible signature here to avoid MRO conflicts. - def as_sql( + def as_sql( # type: ignore[override] self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, function: str | None = None, - template: str | None = None, - arg_joiner: str | None = None, **extra_context: Any, ) -> _AsSqlType: ... def resolve_expression( @@ -38,7 +33,8 @@ class GeoFuncMixin: **kwargs: Any, ) -> Any: ... -class GeoFunc(GeoFuncMixin, Func): ... +class GeoFunc(GeoFuncMixin, Func): # type: ignore[misc] + ... class GeomOutputGeoFunc(GeoFunc): @cached_property @@ -98,19 +94,19 @@ class AsWKT(GeoFunc): output_field: ClassVar[TextField] arity: int -class BoundingCircle(OracleToleranceMixin, GeomOutputGeoFunc): +class BoundingCircle(OracleToleranceMixin, GeomOutputGeoFunc): # type: ignore[misc] def __init__(self, expression: Any, num_seg: int = 48, **extra: Any) -> None: ... @override def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... -class Centroid(OracleToleranceMixin, GeomOutputGeoFunc): +class Centroid(OracleToleranceMixin, GeomOutputGeoFunc): # type: ignore[misc] arity: int -class ClosestPoint(GeomOutputGeoFunc): +class ClosestPoint(GeomOutputGeoFunc): # type: ignore[misc] arity: int geom_param_pos: tuple[int, int] -class Difference(OracleToleranceMixin, GeomOutputGeoFunc): +class Difference(OracleToleranceMixin, GeomOutputGeoFunc): # type: ignore[misc] arity: int geom_param_pos: Any @@ -119,7 +115,7 @@ class DistanceResultMixin: def output_field(self) -> DistanceField: ... def source_is_geography(self) -> Any: ... -class Distance(DistanceResultMixin, OracleToleranceMixin, GeoFunc): +class Distance(DistanceResultMixin, OracleToleranceMixin, GeoFunc): # type: ignore[misc] geom_param_pos: Any spheroid: Any def __init__(self, expr1: Any, expr2: Any, spheroid: Any | None = None, **extra: Any) -> None: ... @@ -154,26 +150,26 @@ class GeometryDistance(GeoFunc): arg_joiner: str geom_param_pos: Any -class Intersection(OracleToleranceMixin, GeomOutputGeoFunc): +class Intersection(OracleToleranceMixin, GeomOutputGeoFunc): # type: ignore[misc] arity: int geom_param_pos: Any -class GeometryType(GeoFuncMixin, StandardTransform): +class GeometryType(GeoFuncMixin, StandardTransform): # type: ignore[misc] lookup_name: str output_field: ClassVar[CharField] def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... -class IsEmpty(GeoFuncMixin, StandardTransform): +class IsEmpty(GeoFuncMixin, StandardTransform): # type: ignore[misc] lookup_name: str output_field: ClassVar[BooleanField] -class IsValid(OracleToleranceMixin, GeoFuncMixin, StandardTransform): +class IsValid(OracleToleranceMixin, GeoFuncMixin, StandardTransform): # type: ignore[misc] lookup_name: str output_field: ClassVar[BooleanField] @override def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... -class Length(DistanceResultMixin, OracleToleranceMixin, GeoFunc): +class Length(DistanceResultMixin, OracleToleranceMixin, GeoFunc): # type: ignore[misc] spheroid: Any def __init__(self, expr1: Any, spheroid: bool = True, **extra: Any) -> None: ... @override @@ -205,7 +201,7 @@ class NumPoints(GeoFunc): output_field: ClassVar[IntegerField] arity: int -class Perimeter(DistanceResultMixin, OracleToleranceMixin, GeoFunc): +class Perimeter(DistanceResultMixin, OracleToleranceMixin, GeoFunc): # type: ignore[misc] arity: int def as_postgresql( self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any @@ -213,22 +209,22 @@ class Perimeter(DistanceResultMixin, OracleToleranceMixin, GeoFunc): @override def as_sqlite(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... -class PointOnSurface(OracleToleranceMixin, GeomOutputGeoFunc): +class PointOnSurface(OracleToleranceMixin, GeomOutputGeoFunc): # type: ignore[misc] arity: int -class Reverse(GeoFunc): +class Reverse(GeoFunc): # type: ignore[misc] arity: int -class Rotate(GeomOutputGeoFunc): +class Rotate(GeomOutputGeoFunc): # type: ignore[misc] def __init__(self, expression: Any, angle: Any, origin: Any | None = None, **extra: Any) -> None: ... -class Scale(SQLiteDecimalToFloatMixin, GeomOutputGeoFunc): +class Scale(SQLiteDecimalToFloatMixin, GeomOutputGeoFunc): # type: ignore[misc] def __init__(self, expression: Any, x: Any, y: Any, z: float = 0.0, **extra: Any) -> None: ... -class SnapToGrid(SQLiteDecimalToFloatMixin, GeomOutputGeoFunc): +class SnapToGrid(SQLiteDecimalToFloatMixin, GeomOutputGeoFunc): # type: ignore[misc] def __init__(self, expression: Any, *args: Any, **extra: Any) -> None: ... -class SymDifference(OracleToleranceMixin, GeomOutputGeoFunc): +class SymDifference(OracleToleranceMixin, GeomOutputGeoFunc): # type: ignore[misc] arity: int geom_param_pos: Any @@ -239,6 +235,6 @@ class Translate(Scale): @override def as_sqlite(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... -class Union(OracleToleranceMixin, GeomOutputGeoFunc): +class Union(OracleToleranceMixin, GeomOutputGeoFunc): # type: ignore[misc] arity: int geom_param_pos: Any From 39b03a8b32af82c296c099dfbd668aaeb57e956d Mon Sep 17 00:00:00 2001 From: ahmedasar00 Date: Sun, 22 Mar 2026 21:48:36 +0200 Subject: [PATCH 3/3] Remove unused type: ignore comments in GIS function stubs --- django-stubs/contrib/gis/db/models/functions.pyi | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/django-stubs/contrib/gis/db/models/functions.pyi b/django-stubs/contrib/gis/db/models/functions.pyi index dd88b31f0..ff12bea3c 100644 --- a/django-stubs/contrib/gis/db/models/functions.pyi +++ b/django-stubs/contrib/gis/db/models/functions.pyi @@ -20,7 +20,7 @@ class GeoFuncMixin: def name(self) -> str: ... @cached_property def geo_field(self) -> Any: ... - def as_sql( # type: ignore[override] + def as_sql( self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, @@ -102,7 +102,7 @@ class BoundingCircle(OracleToleranceMixin, GeomOutputGeoFunc): # type: ignore[m class Centroid(OracleToleranceMixin, GeomOutputGeoFunc): # type: ignore[misc] arity: int -class ClosestPoint(GeomOutputGeoFunc): # type: ignore[misc] +class ClosestPoint(GeomOutputGeoFunc): arity: int geom_param_pos: tuple[int, int] @@ -169,7 +169,7 @@ class IsValid(OracleToleranceMixin, GeoFuncMixin, StandardTransform): # type: i @override def as_oracle(self, compiler: SQLCompiler, connection: BaseDatabaseWrapper, **extra_context: Any) -> _AsSqlType: ... -class Length(DistanceResultMixin, OracleToleranceMixin, GeoFunc): # type: ignore[misc] +class Length(DistanceResultMixin, OracleToleranceMixin, GeoFunc): spheroid: Any def __init__(self, expr1: Any, spheroid: bool = True, **extra: Any) -> None: ... @override @@ -212,10 +212,10 @@ class Perimeter(DistanceResultMixin, OracleToleranceMixin, GeoFunc): # type: ig class PointOnSurface(OracleToleranceMixin, GeomOutputGeoFunc): # type: ignore[misc] arity: int -class Reverse(GeoFunc): # type: ignore[misc] +class Reverse(GeoFunc): arity: int -class Rotate(GeomOutputGeoFunc): # type: ignore[misc] +class Rotate(GeomOutputGeoFunc): def __init__(self, expression: Any, angle: Any, origin: Any | None = None, **extra: Any) -> None: ... class Scale(SQLiteDecimalToFloatMixin, GeomOutputGeoFunc): # type: ignore[misc]