diff --git a/django/contrib/gis/db/backends/base/operations.py b/django/contrib/gis/db/backends/base/operations.py index 1b786f7897b..860748cc9d1 100644 --- a/django/contrib/gis/db/backends/base/operations.py +++ b/django/contrib/gis/db/backends/base/operations.py @@ -40,10 +40,10 @@ class BaseSpatialOperations: unsupported_functions = { 'Area', 'AsGeoJSON', 'AsGML', 'AsKML', 'AsSVG', 'Azimuth', 'BoundingCircle', 'Centroid', 'Difference', 'Distance', 'Envelope', - 'ForceRHR', 'GeoHash', 'Intersection', 'IsValid', 'Length', - 'LineLocatePoint', 'MakeValid', 'MemSize', 'NumGeometries', - 'NumPoints', 'Perimeter', 'PointOnSurface', 'Reverse', 'Scale', - 'SnapToGrid', 'SymDifference', 'Transform', 'Translate', 'Union', + 'GeoHash', 'Intersection', 'IsValid', 'Length', 'LineLocatePoint', + 'MakeValid', 'MemSize', 'NumGeometries', 'NumPoints', 'Perimeter', + 'PointOnSurface', 'Reverse', 'Scale', 'SnapToGrid', 'SymDifference', + 'Transform', 'Translate', 'Union', } # Constructors diff --git a/django/contrib/gis/db/backends/mysql/operations.py b/django/contrib/gis/db/backends/mysql/operations.py index 138b5a3c9f2..d55e9f49376 100644 --- a/django/contrib/gis/db/backends/mysql/operations.py +++ b/django/contrib/gis/db/backends/mysql/operations.py @@ -56,9 +56,9 @@ class MySQLOperations(BaseSpatialOperations, DatabaseOperations): def unsupported_functions(self): unsupported = { 'AsGML', 'AsKML', 'AsSVG', 'Azimuth', 'BoundingCircle', - 'ForcePolygonCW', 'ForceRHR', 'LineLocatePoint', 'MakeValid', - 'MemSize', 'Perimeter', 'PointOnSurface', 'Reverse', 'Scale', - 'SnapToGrid', 'Transform', 'Translate', + 'ForcePolygonCW', 'LineLocatePoint', 'MakeValid', 'MemSize', + 'Perimeter', 'PointOnSurface', 'Reverse', 'Scale', 'SnapToGrid', + 'Transform', 'Translate', } if self.connection.mysql_is_mariadb: unsupported.update({'GeoHash', 'IsValid'}) diff --git a/django/contrib/gis/db/backends/oracle/operations.py b/django/contrib/gis/db/backends/oracle/operations.py index d2db7f84984..df052d74fcb 100644 --- a/django/contrib/gis/db/backends/oracle/operations.py +++ b/django/contrib/gis/db/backends/oracle/operations.py @@ -106,9 +106,9 @@ class OracleOperations(BaseSpatialOperations, DatabaseOperations): } unsupported_functions = { - 'AsGeoJSON', 'AsKML', 'AsSVG', 'Azimuth', - 'ForcePolygonCW', 'ForceRHR', 'GeoHash', 'LineLocatePoint', - 'MakeValid', 'MemSize', 'Scale', 'SnapToGrid', 'Translate', + 'AsGeoJSON', 'AsKML', 'AsSVG', 'Azimuth', 'ForcePolygonCW', 'GeoHash', + 'LineLocatePoint', 'MakeValid', 'MemSize', 'Scale', 'SnapToGrid', + 'Translate', } def geo_quote_name(self, name): diff --git a/django/contrib/gis/db/backends/spatialite/operations.py b/django/contrib/gis/db/backends/spatialite/operations.py index 52096480984..78dfa5cfb46 100644 --- a/django/contrib/gis/db/backends/spatialite/operations.py +++ b/django/contrib/gis/db/backends/spatialite/operations.py @@ -81,7 +81,7 @@ class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations): @cached_property def unsupported_functions(self): - unsupported = {'BoundingCircle', 'ForceRHR', 'MemSize'} + unsupported = {'BoundingCircle', 'MemSize'} if not self.lwgeom_version(): unsupported |= {'Azimuth', 'GeoHash', 'IsValid', 'MakeValid'} return unsupported diff --git a/django/contrib/gis/db/models/functions.py b/django/contrib/gis/db/models/functions.py index 710e7c5d3d9..c1ae4ae4459 100644 --- a/django/contrib/gis/db/models/functions.py +++ b/django/contrib/gis/db/models/functions.py @@ -1,4 +1,3 @@ -import warnings from decimal import Decimal from django.contrib.gis.db.models.fields import BaseSpatialField, GeometryField @@ -11,7 +10,6 @@ from django.db.models import ( from django.db.models.expressions import Func, Value from django.db.models.functions import Cast from django.db.utils import NotSupportedError -from django.utils.deprecation import RemovedInDjango30Warning from django.utils.functional import cached_property NUMERIC_TYPES = (int, float, Decimal) @@ -284,17 +282,6 @@ class ForcePolygonCW(GeomOutputGeoFunc): arity = 1 -class ForceRHR(GeomOutputGeoFunc): - arity = 1 - - def __init__(self, *args, **kwargs): - warnings.warn( - 'ForceRHR is deprecated in favor of ForcePolygonCW.', - RemovedInDjango30Warning, stacklevel=2, - ) - super().__init__(*args, **kwargs) - - class GeoHash(GeoFunc): output_field = TextField() diff --git a/docs/ref/contrib/gis/db-api.txt b/docs/ref/contrib/gis/db-api.txt index b70ae11067c..9b88ff78612 100644 --- a/docs/ref/contrib/gis/db-api.txt +++ b/docs/ref/contrib/gis/db-api.txt @@ -383,7 +383,6 @@ Function PostGIS Oracle MySQL Spat :class:`Distance` X X X X :class:`Envelope` X X X X :class:`ForcePolygonCW` X X -:class:`ForceRHR` X :class:`GeoHash` X X (≥ 5.7.5) X (LWGEOM) :class:`Intersection` X X X X :class:`IsValid` X X X (≥ 5.7.5) X (LWGEOM) diff --git a/docs/ref/contrib/gis/functions.txt b/docs/ref/contrib/gis/functions.txt index 453c1385d5d..03e8411c25c 100644 --- a/docs/ref/contrib/gis/functions.txt +++ b/docs/ref/contrib/gis/functions.txt @@ -24,12 +24,11 @@ Function's summary: Measurement Relationships Operations Editors Output format Miscellaneous ================== ======================== ====================== ======================= ================== ===================== :class:`Area` :class:`Azimuth` :class:`Difference` :class:`ForcePolygonCW` :class:`AsGeoJSON` :class:`IsValid` -:class:`Distance` :class:`BoundingCircle` :class:`Intersection` :class:`ForceRHR` :class:`AsGML` :class:`MemSize` -:class:`Length` :class:`Centroid` :class:`SymDifference` :class:`MakeValid` :class:`AsKML` :class:`NumGeometries` -:class:`Perimeter` :class:`Envelope` :class:`Union` :class:`Reverse` :class:`AsSVG` :class:`NumPoints` -.. :class:`LineLocatePoint` :class:`Scale` :class:`GeoHash` -.. :class:`PointOnSurface` :class:`SnapToGrid` -.. :class:`Transform` +:class:`Distance` :class:`BoundingCircle` :class:`Intersection` :class:`MakeValid` :class:`AsGML` :class:`MemSize` +:class:`Length` :class:`Centroid` :class:`SymDifference` :class:`Reverse` :class:`AsKML` :class:`NumGeometries` +:class:`Perimeter` :class:`Envelope` :class:`Union` :class:`Scale` :class:`AsSVG` :class:`NumPoints` +.. :class:`LineLocatePoint` :class:`SnapToGrid` :class:`GeoHash` +.. :class:`PointOnSurface` :class:`Transform` .. :class:`Translate` ================== ======================== ====================== ======================= ================== ===================== @@ -291,21 +290,6 @@ of the polygon/multipolygon in which all exterior rings are oriented clockwise and all interior rings are oriented counterclockwise. Non-polygonal geometries are returned unchanged. -``ForceRHR`` -============ - -.. class:: ForceRHR(expression, **extra) - -.. deprecated:: 2.1 - - Use :class:`ForcePolygonCW` instead. - -*Availability*: `PostGIS `__ - -Accepts a single geographic field or expression and returns a modified version -of the polygon/multipolygon in which all of the vertices follow the -right-hand rule. - ``GeoHash`` =========== diff --git a/docs/releases/3.0.txt b/docs/releases/3.0.txt index 7699603dea3..ac7c3d06380 100644 --- a/docs/releases/3.0.txt +++ b/docs/releases/3.0.txt @@ -253,4 +253,4 @@ to remove usage of these features. See :ref:`deprecated-features-2.1` for details on these changes, including how to remove usage of these features. -* ... +* The ``ForceRHR`` GIS function is removed. diff --git a/tests/gis_tests/geoapp/test_functions.py b/tests/gis_tests/geoapp/test_functions.py index e7eec26dd6f..817e0b26116 100644 --- a/tests/gis_tests/geoapp/test_functions.py +++ b/tests/gis_tests/geoapp/test_functions.py @@ -10,8 +10,7 @@ from django.contrib.gis.geos import ( from django.contrib.gis.measure import Area from django.db import NotSupportedError, connection from django.db.models import Sum -from django.test import TestCase, ignore_warnings, skipUnlessDBFeature -from django.utils.deprecation import RemovedInDjango30Warning +from django.test import TestCase, skipUnlessDBFeature from ..utils import FuncTestMixin, mysql, oracle, postgis, spatialite from .models import City, Country, CountryWebMercator, State, Track @@ -230,21 +229,6 @@ class GISFunctionsTests(FuncTestMixin, TestCase): st = State.objects.annotate(force_polygon_cw=functions.ForcePolygonCW('poly')).get(name='Foo') self.assertEqual(rhr_rings, st.force_polygon_cw.coords) - @skipUnlessDBFeature("has_ForceRHR_function") - @ignore_warnings(category=RemovedInDjango30Warning) - def test_force_rhr(self): - rings = ( - ((0, 0), (5, 0), (0, 5), (0, 0)), - ((1, 1), (1, 3), (3, 1), (1, 1)), - ) - rhr_rings = ( - ((0, 0), (0, 5), (5, 0), (0, 0)), - ((1, 1), (3, 1), (1, 3), (1, 1)), - ) - State.objects.create(name='Foo', poly=Polygon(*rings)) - st = State.objects.annotate(force_rhr=functions.ForceRHR('poly')).get(name='Foo') - self.assertEqual(rhr_rings, st.force_rhr.coords) - @skipUnlessDBFeature("has_GeoHash_function") def test_geohash(self): # Reference query: