1
0
mirror of https://github.com/django/django.git synced 2024-12-22 17:16:24 +00:00

Fixed #34685 -- Dropped support for GEOS 3.6 and 3.7.

This commit is contained in:
Mariusz Felisiak 2023-06-29 21:45:36 +02:00 committed by GitHub
parent ce204bed7f
commit 601ffb0da3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 7 additions and 46 deletions

View File

@ -8,7 +8,7 @@ from ctypes import byref, c_byte, c_double, c_uint
from django.contrib.gis.geos import prototypes as capi from django.contrib.gis.geos import prototypes as capi
from django.contrib.gis.geos.base import GEOSBase from django.contrib.gis.geos.base import GEOSBase
from django.contrib.gis.geos.error import GEOSException from django.contrib.gis.geos.error import GEOSException
from django.contrib.gis.geos.libgeos import CS_PTR, geos_version_tuple from django.contrib.gis.geos.libgeos import CS_PTR
from django.contrib.gis.shortcuts import numpy from django.contrib.gis.shortcuts import numpy
@ -202,16 +202,6 @@ class GEOSCoordSeq(GEOSBase):
@property @property
def is_counterclockwise(self): def is_counterclockwise(self):
"""Return whether this coordinate sequence is counterclockwise.""" """Return whether this coordinate sequence is counterclockwise."""
if geos_version_tuple() < (3, 7):
# A modified shoelace algorithm to determine polygon orientation.
# See https://en.wikipedia.org/wiki/Shoelace_formula.
area = 0.0
n = len(self)
for i in range(n):
j = (i + 1) % n
area += self[i][0] * self[j][1]
area -= self[j][0] * self[i][1]
return area > 0.0
ret = c_byte() ret = c_byte()
if not capi.cs_is_ccw(self.ptr, byref(ret)): if not capi.cs_is_ccw(self.ptr, byref(ret)):
raise GEOSException( raise GEOSException(

View File

@ -11,7 +11,7 @@ from django.contrib.gis.geos import prototypes as capi
from django.contrib.gis.geos.base import GEOSBase from django.contrib.gis.geos.base import GEOSBase
from django.contrib.gis.geos.coordseq import GEOSCoordSeq from django.contrib.gis.geos.coordseq import GEOSCoordSeq
from django.contrib.gis.geos.error import GEOSException from django.contrib.gis.geos.error import GEOSException
from django.contrib.gis.geos.libgeos import GEOM_PTR, geos_version_tuple from django.contrib.gis.geos.libgeos import GEOM_PTR
from django.contrib.gis.geos.mutable_list import ListMixin from django.contrib.gis.geos.mutable_list import ListMixin
from django.contrib.gis.geos.prepared import PreparedGeometry from django.contrib.gis.geos.prepared import PreparedGeometry
from django.contrib.gis.geos.prototypes.io import ewkb_w, wkb_r, wkb_w, wkt_r, wkt_w from django.contrib.gis.geos.prototypes.io import ewkb_w, wkb_r, wkb_w, wkt_r, wkt_w
@ -238,8 +238,6 @@ class GEOSGeometryBase(GEOSBase):
Attempt to create a valid representation of a given invalid geometry Attempt to create a valid representation of a given invalid geometry
without losing any of the input vertices. without losing any of the input vertices.
""" """
if geos_version_tuple() < (3, 8):
raise GEOSException("GEOSGeometry.make_valid() requires GEOS >= 3.8.0.")
return GEOSGeometry(capi.geos_makevalid(self.ptr), srid=self.srid) return GEOSGeometry(capi.geos_makevalid(self.ptr), srid=self.srid)
# #### Unary predicates #### # #### Unary predicates ####

View File

@ -259,24 +259,14 @@ class WKBWriter(IOBase):
def write(self, geom): def write(self, geom):
"Return the WKB representation of the given geometry." "Return the WKB representation of the given geometry."
from django.contrib.gis.geos import Polygon
geom = self._handle_empty_point(geom) geom = self._handle_empty_point(geom)
wkb = wkb_writer_write(self.ptr, geom.ptr, byref(c_size_t())) wkb = wkb_writer_write(self.ptr, geom.ptr, byref(c_size_t()))
if self.geos_version < (3, 6, 1) and isinstance(geom, Polygon) and geom.empty:
# Fix GEOS output for empty polygon.
# See https://trac.osgeo.org/geos/ticket/680.
wkb = wkb[:-8] + b"\0" * 4
return memoryview(wkb) return memoryview(wkb)
def write_hex(self, geom): def write_hex(self, geom):
"Return the HEXEWKB representation of the given geometry." "Return the HEXEWKB representation of the given geometry."
from django.contrib.gis.geos.polygon import Polygon
geom = self._handle_empty_point(geom) geom = self._handle_empty_point(geom)
wkb = wkb_writer_write_hex(self.ptr, geom.ptr, byref(c_size_t())) wkb = wkb_writer_write_hex(self.ptr, geom.ptr, byref(c_size_t()))
if self.geos_version < (3, 6, 1) and isinstance(geom, Polygon) and geom.empty:
wkb = wkb[:-16] + b"0" * 8
return wkb return wkb
# ### WKBWriter Properties ### # ### WKBWriter Properties ###

View File

@ -8,7 +8,7 @@ geospatial libraries:
======================== ==================================== ================================ ====================================== ======================== ==================================== ================================ ======================================
Program Description Required Supported Versions Program Description Required Supported Versions
======================== ==================================== ================================ ====================================== ======================== ==================================== ================================ ======================================
:doc:`GEOS <../geos>` Geometry Engine Open Source Yes 3.11, 3.10, 3.9, 3.8, 3.7, 3.6 :doc:`GEOS <../geos>` Geometry Engine Open Source Yes 3.11, 3.10, 3.9, 3.8
`PROJ`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 9.x, 8.x, 7.x, 6.x, 5.x `PROJ`_ Cartographic Projections library Yes (PostgreSQL and SQLite only) 9.x, 8.x, 7.x, 6.x, 5.x
:doc:`GDAL <../gdal>` Geospatial Data Abstraction Library Yes 3.6, 3.5, 3.4, 3.3, 3.2, 3.1, 3.0, 2.4 :doc:`GDAL <../gdal>` Geospatial Data Abstraction Library Yes 3.6, 3.5, 3.4, 3.3, 3.2, 3.1, 3.0, 2.4
:doc:`GeoIP <../geoip2>` IP-based geolocation library No 2 :doc:`GeoIP <../geoip2>` IP-based geolocation library No 2
@ -21,8 +21,6 @@ totally fine with GeoDjango. Your mileage may vary.
.. ..
Libs release dates: Libs release dates:
GEOS 3.6.0 2016-10-25
GEOS 3.7.0 2018-09-10
GEOS 3.8.0 2019-10-10 GEOS 3.8.0 2019-10-10
GEOS 3.9.0 2020-12-14 GEOS 3.9.0 2020-12-14
GEOS 3.10.0 2021-10-20 GEOS 3.10.0 2021-10-20

View File

@ -422,6 +422,8 @@ backends.
* Support for GDAL 2.2 and 2.3 is removed. * Support for GDAL 2.2 and 2.3 is removed.
* Support for GEOS 3.6 and 3.7 is removed.
Using ``create_defaults__exact`` may now be required with ``QuerySet.update_or_create()`` Using ``create_defaults__exact`` may now be required with ``QuerySet.update_or_create()``
----------------------------------------------------------------------------------------- -----------------------------------------------------------------------------------------

View File

@ -5,7 +5,7 @@ import pickle
import random import random
from binascii import a2b_hex from binascii import a2b_hex
from io import BytesIO from io import BytesIO
from unittest import mock, skipIf from unittest import mock
from django.contrib.gis import gdal from django.contrib.gis import gdal
from django.contrib.gis.geos import ( from django.contrib.gis.geos import (
@ -393,7 +393,7 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
line.ewkt, "SRID=4326;LINESTRING (151.2607 -33.887, 144.963 -37.8143)" line.ewkt, "SRID=4326;LINESTRING (151.2607 -33.887, 144.963 -37.8143)"
) )
def _test_is_counterclockwise(self): def test_is_counterclockwise(self):
lr = LinearRing((0, 0), (1, 0), (0, 1), (0, 0)) lr = LinearRing((0, 0), (1, 0), (0, 1), (0, 0))
self.assertIs(lr.is_counterclockwise, True) self.assertIs(lr.is_counterclockwise, True)
lr.reverse() lr.reverse()
@ -402,11 +402,6 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
with self.assertRaisesMessage(ValueError, msg): with self.assertRaisesMessage(ValueError, msg):
LinearRing().is_counterclockwise LinearRing().is_counterclockwise
@skipIf(geos_version_tuple() < (3, 7), "GEOS >= 3.7.0 is required")
def test_is_counterclockwise(self):
self._test_is_counterclockwise()
@skipIf(geos_version_tuple() < (3, 7), "GEOS >= 3.7.0 is required")
def test_is_counterclockwise_geos_error(self): def test_is_counterclockwise_geos_error(self):
with mock.patch("django.contrib.gis.geos.prototypes.cs_is_ccw") as mocked: with mock.patch("django.contrib.gis.geos.prototypes.cs_is_ccw") as mocked:
mocked.return_value = 0 mocked.return_value = 0
@ -415,10 +410,6 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
with self.assertRaisesMessage(GEOSException, msg): with self.assertRaisesMessage(GEOSException, msg):
LinearRing((0, 0), (1, 0), (0, 1), (0, 0)).is_counterclockwise LinearRing((0, 0), (1, 0), (0, 1), (0, 0)).is_counterclockwise
@mock.patch("django.contrib.gis.geos.libgeos.geos_version", lambda: b"3.6.9")
def test_is_counterclockwise_fallback(self):
self._test_is_counterclockwise()
def test_multilinestring(self): def test_multilinestring(self):
"Testing MultiLineString objects." "Testing MultiLineString objects."
prev = fromstr("POINT(0 0)") prev = fromstr("POINT(0 0)")
@ -1543,7 +1534,6 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
self.assertEqual(multipoint_2, normalized) self.assertEqual(multipoint_2, normalized)
self.assertNotEqual(multipoint, normalized) self.assertNotEqual(multipoint, normalized)
@skipIf(geos_version_tuple() < (3, 8), "GEOS >= 3.8.0 is required")
def test_make_valid(self): def test_make_valid(self):
poly = GEOSGeometry("POLYGON((0 0, 0 23, 23 0, 23 23, 0 0))") poly = GEOSGeometry("POLYGON((0 0, 0 23, 23 0, 23 23, 0 0))")
self.assertIs(poly.valid, False) self.assertIs(poly.valid, False)
@ -1555,13 +1545,6 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
self.assertIs(valid_poly2.valid, True) self.assertIs(valid_poly2.valid, True)
self.assertEqual(valid_poly, valid_poly2) self.assertEqual(valid_poly, valid_poly2)
@mock.patch("django.contrib.gis.geos.libgeos.geos_version", lambda: b"3.7.3")
def test_make_valid_geos_version(self):
msg = "GEOSGeometry.make_valid() requires GEOS >= 3.8.0."
poly = GEOSGeometry("POLYGON((0 0, 0 23, 23 0, 23 23, 0 0))")
with self.assertRaisesMessage(GEOSException, msg):
poly.make_valid()
def test_empty_point(self): def test_empty_point(self):
p = Point(srid=4326) p = Point(srid=4326)
self.assertEqual(p.ogr.ewkt, p.ewkt) self.assertEqual(p.ogr.ewkt, p.ewkt)