From 65a1f32319a0a58f8458060a61c7bab0fa12292e Mon Sep 17 00:00:00 2001 From: Sergey Fedoseev Date: Fri, 2 Dec 2016 08:22:04 +0500 Subject: [PATCH] Refs #27472 -- Fixed GEOSGeometry('POINT EMPTY').ogr crash. --- django/contrib/gis/gdal/geometries.py | 10 +++++++++- django/contrib/gis/geos/geometry.py | 10 ++++------ django/contrib/gis/geos/point.py | 4 ++++ tests/gis_tests/geos_tests/test_geos.py | 4 ++++ 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/django/contrib/gis/gdal/geometries.py b/django/contrib/gis/gdal/geometries.py index cab40aa751..5a9fc2796d 100644 --- a/django/contrib/gis/gdal/geometries.py +++ b/django/contrib/gis/gdal/geometries.py @@ -97,7 +97,7 @@ class OGRGeometry(GDALBase): g = capi.create_geom(OGRGeomType(geom_input).num) elif isinstance(geom_input, six.memoryview): # WKB was passed in - g = capi.from_wkb(bytes(geom_input), None, byref(c_void_p()), len(geom_input)) + g = self._from_wkb(geom_input) elif isinstance(geom_input, OGRGeomType): # OGRGeomType was passed in, an empty geometry will be created. g = capi.create_geom(geom_input.num) @@ -144,6 +144,10 @@ class OGRGeometry(GDALBase): self.ptr = ptr self.srs = srs + @classmethod + def _from_wkb(cls, geom_input): + return capi.from_wkb(bytes(geom_input), None, byref(c_void_p()), len(geom_input)) + @classmethod def from_bbox(cls, bbox): "Constructs a Polygon from a bounding box (4-tuple)." @@ -500,6 +504,10 @@ class OGRGeometry(GDALBase): # The subclasses for OGR Geometry. class Point(OGRGeometry): + @classmethod + def _create_empty(cls): + return capi.create_geom(OGRGeomType('point').num) + @property def x(self): "Returns the X coordinate for this Point." diff --git a/django/contrib/gis/geos/geometry.py b/django/contrib/gis/geos/geometry.py index 07a22cb751..ac16184469 100644 --- a/django/contrib/gis/geos/geometry.py +++ b/django/contrib/gis/geos/geometry.py @@ -479,15 +479,13 @@ class GEOSGeometry(GEOSBase, ListMixin): return PreparedGeometry(self) # #### GDAL-specific output routines #### + def _ogr_ptr(self): + return gdal.OGRGeometry._from_wkb(self.wkb) + @property def ogr(self): "Returns the OGR Geometry for this Geometry." - if self.srid: - try: - return gdal.OGRGeometry(self.wkb, self.srid) - except gdal.SRSException: - pass - return gdal.OGRGeometry(self.wkb) + return gdal.OGRGeometry(self._ogr_ptr(), self.srs) @property def srs(self): diff --git a/django/contrib/gis/geos/point.py b/django/contrib/gis/geos/point.py index 46972629d8..ccb292cecc 100644 --- a/django/contrib/gis/geos/point.py +++ b/django/contrib/gis/geos/point.py @@ -1,6 +1,7 @@ import warnings from ctypes import c_uint +from django.contrib.gis import gdal from django.contrib.gis.geos import prototypes as capi from django.contrib.gis.geos.error import GEOSException from django.contrib.gis.geos.geometry import GEOSGeometry @@ -43,6 +44,9 @@ class Point(GEOSGeometry): # createPoint factory. super(Point, self).__init__(point, srid=srid) + def _ogr_ptr(self): + return gdal.geometries.Point._create_empty() if self.empty else super(Point, self)._ogr_ptr() + def _create_point(self, ndim, coords): """ Create a coordinate sequence, set X, Y, [Z], and create point diff --git a/tests/gis_tests/geos_tests/test_geos.py b/tests/gis_tests/geos_tests/test_geos.py index 9bb55a1b4d..c70171e4c5 100644 --- a/tests/gis_tests/geos_tests/test_geos.py +++ b/tests/gis_tests/geos_tests/test_geos.py @@ -1355,6 +1355,10 @@ class GEOSTest(SimpleTestCase, TestDataMixin): self.assertIsNone(g.normalize()) self.assertTrue(g.equals_exact(MultiPoint(Point(2, 2), Point(1, 1), Point(0, 0)))) + def test_empty_point(self): + p = Point(srid=4326) + self.assertEqual(p.ogr.ewkt, p.ewkt) + @ignore_warnings(category=RemovedInDjango20Warning) def test_deprecated_srid_getters_setters(self): p = Point(1, 2, srid=123)