summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Fedoseev <fedoseev.sergey@gmail.com>2017-07-25 14:11:43 +0500
committerTim Graham <timograham@gmail.com>2017-07-26 09:42:02 -0400
commit5ccbcc5bf61c746a1d5ec2b3d2e0dc56c1a63fe0 (patch)
treea8dcb1374b2a0fde03839bb3ed337420967da527
parentc362228556bedb4a8a3cdaf91b9e456e459ecda1 (diff)
Fixed #28433 -- Made GEOSGeometry.__eq__() work correctly with non-canonical EWKT string.
-rw-r--r--django/contrib/gis/geos/geometry.py36
-rw-r--r--tests/gis_tests/geos_tests/test_geos.py19
2 files changed, 47 insertions, 8 deletions
diff --git a/django/contrib/gis/geos/geometry.py b/django/contrib/gis/geos/geometry.py
index 15c7369b49..9a8f8ed71f 100644
--- a/django/contrib/gis/geos/geometry.py
+++ b/django/contrib/gis/geos/geometry.py
@@ -2,6 +2,7 @@
This module contains the 'base' GEOSGeometry object -- all GEOS Geometries
inherit from this object.
"""
+import re
from ctypes import addressof, byref, c_double
from django.contrib.gis import gdal
@@ -54,7 +55,7 @@ class GEOSGeometry(GEOSBase, ListMixin):
# Handling WKT input.
if wkt_m.group('srid'):
input_srid = int(wkt_m.group('srid'))
- g = wkt_r().read(force_bytes(wkt_m.group('wkt')))
+ g = self._from_wkt(force_bytes(wkt_m.group('wkt')))
elif hex_regex.match(geo_input):
# Handling HEXEWKB input.
g = wkb_r().read(force_bytes(geo_input))
@@ -163,6 +164,27 @@ class GEOSGeometry(GEOSBase, ListMixin):
def _from_wkb(cls, wkb):
return wkb_r().read(wkb)
+ @staticmethod
+ def from_ewkt(ewkt):
+ ewkt = force_bytes(ewkt)
+ srid = None
+ parts = ewkt.split(b';', 1)
+ if len(parts) == 2:
+ srid_part, wkt = parts
+ match = re.match(b'SRID=(?P<srid>\-?\d+)', srid_part)
+ if not match:
+ raise ValueError('EWKT has invalid SRID part.')
+ srid = int(match.group('srid'))
+ else:
+ wkt = ewkt
+ if not wkt:
+ raise ValueError('Expected WKT but got an empty string.')
+ return GEOSGeometry(GEOSGeometry._from_wkt(wkt), srid=srid)
+
+ @staticmethod
+ def _from_wkt(wkt):
+ return wkt_r().read(wkt)
+
@classmethod
def from_gml(cls, gml_string):
return gdal.OGRGeometry.from_gml(gml_string).geos
@@ -174,13 +196,11 @@ class GEOSGeometry(GEOSBase, ListMixin):
or an EWKT representation.
"""
if isinstance(other, str):
- if other.startswith('SRID=0;'):
- return self.ewkt == other[7:] # Test only WKT part of other
- return self.ewkt == other
- elif isinstance(other, GEOSGeometry):
- return self.srid == other.srid and self.equals_exact(other)
- else:
- return False
+ try:
+ other = GEOSGeometry.from_ewkt(other)
+ except (ValueError, GEOSException):
+ return False
+ return isinstance(other, GEOSGeometry) and self.srid == other.srid and self.equals_exact(other)
# ### Geometry set-like operations ###
# Thanks to Sean Gillies for inspiration:
diff --git a/tests/gis_tests/geos_tests/test_geos.py b/tests/gis_tests/geos_tests/test_geos.py
index 2c94cc165f..35c06a5105 100644
--- a/tests/gis_tests/geos_tests/test_geos.py
+++ b/tests/gis_tests/geos_tests/test_geos.py
@@ -179,6 +179,7 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
ls = fromstr('LINESTRING(0 0, 1 1, 5 5)')
self.assertEqual(ls, ls.wkt)
self.assertNotEqual(p, 'bar')
+ self.assertEqual(p, 'POINT(5.0 23.0)')
# Error shouldn't be raise on equivalence testing with
# an invalid type.
for g in (p, ls):
@@ -1322,6 +1323,24 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
),
)
+ def test_from_ewkt(self):
+ self.assertEqual(GEOSGeometry.from_ewkt('SRID=1;POINT(1 1)'), Point(1, 1, srid=1))
+ self.assertEqual(GEOSGeometry.from_ewkt('POINT(1 1)'), Point(1, 1))
+
+ def test_from_ewkt_empty_string(self):
+ msg = 'Expected WKT but got an empty string.'
+ with self.assertRaisesMessage(ValueError, msg):
+ GEOSGeometry.from_ewkt('')
+ with self.assertRaisesMessage(ValueError, msg):
+ GEOSGeometry.from_ewkt('SRID=1;')
+
+ def test_from_ewkt_invalid_srid(self):
+ msg = 'EWKT has invalid SRID part.'
+ with self.assertRaisesMessage(ValueError, msg):
+ GEOSGeometry.from_ewkt('SRUD=1;POINT(1 1)')
+ with self.assertRaisesMessage(ValueError, msg):
+ GEOSGeometry.from_ewkt('SRID=WGS84;POINT(1 1)')
+
def test_normalize(self):
g = MultiPoint(Point(0, 0), Point(2, 2), Point(1, 1))
self.assertIsNone(g.normalize())