Fixed #27557 -- Casted GEOSGeometry only when necessary

Thanks Pete Flugstad for the report, and Tim Graham for the review.
This commit is contained in:
Claude Paroz 2016-11-30 12:33:58 +01:00
parent 4464b9b9ad
commit cc9e429701
2 changed files with 39 additions and 18 deletions

View File

@ -95,24 +95,26 @@ class GEOSGeometry(GEOSBase, ListMixin):
self.srid = srid self.srid = srid
# Setting the class type (e.g., Point, Polygon, etc.) # Setting the class type (e.g., Point, Polygon, etc.)
if GEOSGeometry._GEOS_CLASSES is None: if type(self) == GEOSGeometry:
# Lazy-loaded variable to avoid import conflicts with GEOSGeometry. if GEOSGeometry._GEOS_CLASSES is None:
from .linestring import LineString, LinearRing # Lazy-loaded variable to avoid import conflicts with GEOSGeometry.
from .point import Point from .linestring import LineString, LinearRing
from .polygon import Polygon from .point import Point
from .collections import ( from .polygon import Polygon
GeometryCollection, MultiPoint, MultiLineString, MultiPolygon) from .collections import (
GEOSGeometry._GEOS_CLASSES = { GeometryCollection, MultiPoint, MultiLineString, MultiPolygon,
0: Point, )
1: LineString, GEOSGeometry._GEOS_CLASSES = {
2: LinearRing, 0: Point,
3: Polygon, 1: LineString,
4: MultiPoint, 2: LinearRing,
5: MultiLineString, 3: Polygon,
6: MultiPolygon, 4: MultiPoint,
7: GeometryCollection, 5: MultiLineString,
} 6: MultiPolygon,
self.__class__ = GEOSGeometry._GEOS_CLASSES[self.geom_typeid] 7: GeometryCollection,
}
self.__class__ = GEOSGeometry._GEOS_CLASSES[self.geom_typeid]
# Setting the coordinate sequence for the geometry (will be None on # Setting the coordinate sequence for the geometry (will be None on
# geometries that do not have coordinate sequences) # geometries that do not have coordinate sequences)

View File

@ -1308,6 +1308,25 @@ class GEOSTest(SimpleTestCase, TestDataMixin):
self.assertEqual(args, (Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly)) self.assertEqual(args, (Point(0, 0), MultiPoint(Point(0, 0), Point(1, 1)), poly))
self.assertEqual(kwargs, {}) self.assertEqual(kwargs, {})
def test_subclassing(self):
"""
GEOSGeometry subclass may itself be subclassed without being forced-cast
to the parent class during `__init__`.
"""
class ExtendedPolygon(Polygon):
def __init__(self, *args, **kwargs):
data = kwargs.pop('data', 0)
super(ExtendedPolygon, self).__init__(*args, **kwargs)
self._data = data
def __str__(self):
return "EXT_POLYGON - data: %d - %s" % (self._data, self.wkt)
ext_poly = ExtendedPolygon(((0, 0), (0, 1), (1, 1), (0, 0)), data=3)
self.assertEqual(type(ext_poly), ExtendedPolygon)
# ExtendedPolygon.__str__ should be called (instead of Polygon.__str__).
self.assertEqual(str(ext_poly), "EXT_POLYGON - data: 3 - POLYGON ((0 0, 0 1, 1 1, 0 0))")
def test_geos_version(self): def test_geos_version(self):
"""Testing the GEOS version regular expression.""" """Testing the GEOS version regular expression."""
from django.contrib.gis.geos.libgeos import version_regex from django.contrib.gis.geos.libgeos import version_regex