1
0
mirror of https://github.com/django/django.git synced 2025-01-18 22:33:44 +00:00

Fixed #25225 -- Simplified code to remove GEOSIndexError

The test is a regression for refs #4740 to show that the original
fix of GEOSIndexError is no longer needed.
This commit is contained in:
Tim Graham 2015-08-12 08:42:01 -04:00
parent 20787b5c29
commit 197b187810
8 changed files with 34 additions and 59 deletions

View File

@ -5,7 +5,7 @@ for more details: https://docs.djangoproject.com/en/dev/ref/contrib/gis/geos/
from .collections import ( # NOQA from .collections import ( # NOQA
GeometryCollection, MultiLineString, MultiPoint, MultiPolygon, GeometryCollection, MultiLineString, MultiPoint, MultiPolygon,
) )
from .error import GEOSException, GEOSIndexError # NOQA from .error import GEOSException # NOQA
from .factory import fromfile, fromstr # NOQA from .factory import fromfile, fromstr # NOQA
from .geometry import GEOSGeometry, hex_regex, wkt_regex # NOQA from .geometry import GEOSGeometry, hex_regex, wkt_regex # NOQA
from .io import WKBReader, WKBWriter, WKTReader, WKTWriter # NOQA from .io import WKBReader, WKBWriter, WKTReader, WKTWriter # NOQA

View File

@ -7,7 +7,7 @@ from ctypes import byref, 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, GEOSIndexError from django.contrib.gis.geos.error import GEOSException
from django.contrib.gis.geos.libgeos import CS_PTR from django.contrib.gis.geos.libgeos import CS_PTR
from django.contrib.gis.shortcuts import numpy from django.contrib.gis.shortcuts import numpy
from django.utils.six.moves import range from django.utils.six.moves import range
@ -74,7 +74,7 @@ class GEOSCoordSeq(GEOSBase):
"Checks the given index." "Checks the given index."
sz = self.size sz = self.size
if (sz < 1) or (index < 0) or (index >= sz): if (sz < 1) or (index < 0) or (index >= sz):
raise GEOSIndexError('invalid GEOS Geometry index: %s' % str(index)) raise IndexError('invalid GEOS Geometry index: %s' % str(index))
def _checkdim(self, dim): def _checkdim(self, dim):
"Checks the given dimension." "Checks the given dimension."

View File

@ -1,22 +1,3 @@
"""
This module houses the GEOS exceptions, specifically, GEOSException and
GEOSGeometryIndexError.
"""
class GEOSException(Exception): class GEOSException(Exception):
"The base GEOS exception, indicates a GEOS-related error." "The base GEOS exception, indicates a GEOS-related error."
pass pass
class GEOSIndexError(GEOSException, KeyError):
"""
This exception is raised when an invalid index is encountered, and has
the 'silent_variable_feature' attribute set to true. This ensures that
django's templates proceed to use the next lookup type gracefully when
an Exception is raised. Fixes ticket #4740.
"""
# "If, during the method lookup, a method raises an exception, the exception
# will be propagated, unless the exception has an attribute
# `silent_variable_failure` whose value is True." -- Django template docs.
silent_variable_failure = True

View File

@ -12,7 +12,7 @@ from django.contrib.gis.geometry.regex import hex_regex, json_regex, wkt_regex
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.coordseq import GEOSCoordSeq from django.contrib.gis.geos.coordseq import GEOSCoordSeq
from django.contrib.gis.geos.error import GEOSException, GEOSIndexError from django.contrib.gis.geos.error import GEOSException
from django.contrib.gis.geos.libgeos import GEOM_PTR 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
@ -26,9 +26,6 @@ from django.utils.encoding import force_bytes, force_text
class GEOSGeometry(GEOSBase, ListMixin): class GEOSGeometry(GEOSBase, ListMixin):
"A class that, generally, encapsulates a GEOS geometry." "A class that, generally, encapsulates a GEOS geometry."
# Raise GEOSIndexError instead of plain IndexError
# (see ticket #4740 and GEOSIndexError docstring)
_IndexError = GEOSIndexError
_GEOS_CLASSES = None _GEOS_CLASSES = None
ptr_type = GEOM_PTR ptr_type = GEOM_PTR

View File

@ -4,7 +4,7 @@
This module contains a base type which provides list-style mutations This module contains a base type which provides list-style mutations
without specific data storage methods. without specific data storage methods.
See also http://www.aryehleib.com/MutableLists.html See also http://static.aryehleib.com/oldsite/MutableLists.html
Author: Aryeh Leib Taurog. Author: Aryeh Leib Taurog.
""" """
@ -55,14 +55,10 @@ class ListMixin(object):
type or tuple _allowed: type or tuple _allowed:
A type or tuple of allowed item types [Optional] A type or tuple of allowed item types [Optional]
class _IndexError:
The type of exception to be raise on invalid index [Optional]
""" """
_minlength = 0 _minlength = 0
_maxlength = None _maxlength = None
_IndexError = IndexError
# ### Python initialization and special list interface methods ### # ### Python initialization and special list interface methods ###
@ -113,11 +109,6 @@ class ListMixin(object):
self._check_allowed((val,)) self._check_allowed((val,))
self._set_single(index, val) self._set_single(index, val)
def __iter__(self):
"Iterate over the items in the list"
for i in range(len(self)):
yield self[i]
# ### Special methods for arithmetic operations ### # ### Special methods for arithmetic operations ###
def __add__(self, other): def __add__(self, other):
'add another list-like object' 'add another list-like object'
@ -155,7 +146,7 @@ class ListMixin(object):
for i in range(olen): for i in range(olen):
try: try:
c = self[i] == other[i] c = self[i] == other[i]
except self._IndexError: except IndexError:
# self must be shorter # self must be shorter
return False return False
if not c: if not c:
@ -167,7 +158,7 @@ class ListMixin(object):
for i in range(olen): for i in range(olen):
try: try:
c = self[i] < other[i] c = self[i] < other[i]
except self._IndexError: except IndexError:
# self must be shorter # self must be shorter
return True return True
if c: if c:
@ -254,7 +245,7 @@ class ListMixin(object):
return index return index
if correct and -length <= index < 0: if correct and -length <= index < 0:
return index + length return index + length
raise self._IndexError('invalid index: %s' % str(index)) raise IndexError('invalid index: %s' % str(index))
def _check_allowed(self, items): def _check_allowed(self, items):
if hasattr(self, '_allowed'): if hasattr(self, '_allowed'):

View File

@ -11,12 +11,14 @@ from unittest import skipUnless
from django.contrib.gis import gdal from django.contrib.gis import gdal
from django.contrib.gis.gdal import HAS_GDAL from django.contrib.gis.gdal import HAS_GDAL
from django.contrib.gis.geos import ( from django.contrib.gis.geos import (
HAS_GEOS, GeometryCollection, GEOSException, GEOSGeometry, GEOSIndexError, HAS_GEOS, GeometryCollection, GEOSException, GEOSGeometry, LinearRing,
LinearRing, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, LineString, MultiLineString, MultiPoint, MultiPolygon, Point, Polygon,
Polygon, fromfile, fromstr, geos_version_info, fromfile, fromstr, geos_version_info,
) )
from django.contrib.gis.geos.base import GEOSBase from django.contrib.gis.geos.base import GEOSBase
from django.contrib.gis.shortcuts import numpy from django.contrib.gis.shortcuts import numpy
from django.template import Context
from django.template.engine import Engine
from django.test import mock from django.test import mock
from django.utils import six from django.utils import six
from django.utils.encoding import force_bytes from django.utils.encoding import force_bytes
@ -283,7 +285,7 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
self.assertAlmostEqual(mp.centroid[0], mpnt.centroid.tuple[0], 9) self.assertAlmostEqual(mp.centroid[0], mpnt.centroid.tuple[0], 9)
self.assertAlmostEqual(mp.centroid[1], mpnt.centroid.tuple[1], 9) self.assertAlmostEqual(mp.centroid[1], mpnt.centroid.tuple[1], 9)
self.assertRaises(GEOSIndexError, mpnt.__getitem__, len(mpnt)) self.assertRaises(IndexError, mpnt.__getitem__, len(mpnt))
self.assertEqual(mp.centroid, mpnt.centroid.tuple) self.assertEqual(mp.centroid, mpnt.centroid.tuple)
self.assertEqual(mp.coords, tuple(m.tuple for m in mpnt)) self.assertEqual(mp.coords, tuple(m.tuple for m in mpnt))
for p in mpnt: for p in mpnt:
@ -308,7 +310,7 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
self.assertEqual(ls, fromstr(l.wkt)) self.assertEqual(ls, fromstr(l.wkt))
self.assertEqual(False, ls == prev) # Use assertEqual to test __eq__ self.assertEqual(False, ls == prev) # Use assertEqual to test __eq__
self.assertRaises(GEOSIndexError, ls.__getitem__, len(ls)) self.assertRaises(IndexError, ls.__getitem__, len(ls))
prev = ls prev = ls
# Creating a LineString from a tuple, list, and numpy array # Creating a LineString from a tuple, list, and numpy array
@ -340,7 +342,7 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
self.assertEqual(ls.geom_typeid, 1) self.assertEqual(ls.geom_typeid, 1)
self.assertEqual(ls.empty, False) self.assertEqual(ls.empty, False)
self.assertRaises(GEOSIndexError, ml.__getitem__, len(ml)) self.assertRaises(IndexError, ml.__getitem__, len(ml))
self.assertEqual(ml.wkt, MultiLineString(*tuple(s.clone() for s in ml)).wkt) self.assertEqual(ml.wkt, MultiLineString(*tuple(s.clone() for s in ml)).wkt)
self.assertEqual(ml, MultiLineString(*tuple(LineString(s.tuple) for s in ml))) self.assertEqual(ml, MultiLineString(*tuple(LineString(s.tuple) for s in ml)))
@ -409,9 +411,9 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
self.assertEqual(p.ext_ring_cs, poly[0].tuple) # Testing __getitem__ self.assertEqual(p.ext_ring_cs, poly[0].tuple) # Testing __getitem__
# Testing __getitem__ and __setitem__ on invalid indices # Testing __getitem__ and __setitem__ on invalid indices
self.assertRaises(GEOSIndexError, poly.__getitem__, len(poly)) self.assertRaises(IndexError, poly.__getitem__, len(poly))
self.assertRaises(GEOSIndexError, poly.__setitem__, len(poly), False) self.assertRaises(IndexError, poly.__setitem__, len(poly), False)
self.assertRaises(GEOSIndexError, poly.__getitem__, -1 * len(poly) - 1) self.assertRaises(IndexError, poly.__getitem__, -1 * len(poly) - 1)
# Testing __iter__ # Testing __iter__
for r in poly: for r in poly:
@ -434,6 +436,14 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
self.assertEqual(poly.wkt, Polygon(*tuple(r for r in poly)).wkt) self.assertEqual(poly.wkt, Polygon(*tuple(r for r in poly)).wkt)
self.assertEqual(poly.wkt, Polygon(*tuple(LinearRing(r.tuple) for r in poly)).wkt) self.assertEqual(poly.wkt, Polygon(*tuple(LinearRing(r.tuple) for r in poly)).wkt)
def test_polygons_templates(self):
# Accessing Polygon attributes in templates should work.
engine = Engine()
template = engine.from_string('{{ polygons.0.wkt }}')
polygons = [fromstr(p.wkt) for p in self.geometries.multipolygons[:2]]
content = template.render(Context({'polygons': polygons}))
self.assertIn('MULTIPOLYGON (((100', content)
def test_polygon_comparison(self): def test_polygon_comparison(self):
p1 = Polygon(((0, 0), (0, 1), (1, 1), (1, 0), (0, 0))) p1 = Polygon(((0, 0), (0, 1), (1, 1), (1, 0), (0, 0)))
p2 = Polygon(((0, 0), (0, 1), (1, 0), (0, 0))) p2 = Polygon(((0, 0), (0, 1), (1, 0), (0, 0)))
@ -458,7 +468,7 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
self.assertEqual(mp.num_geom, mpoly.num_geom) self.assertEqual(mp.num_geom, mpoly.num_geom)
self.assertEqual(mp.n_p, mpoly.num_coords) self.assertEqual(mp.n_p, mpoly.num_coords)
self.assertEqual(mp.num_geom, len(mpoly)) self.assertEqual(mp.num_geom, len(mpoly))
self.assertRaises(GEOSIndexError, mpoly.__getitem__, len(mpoly)) self.assertRaises(IndexError, mpoly.__getitem__, len(mpoly))
for p in mpoly: for p in mpoly:
self.assertEqual(p.geom_type, 'Polygon') self.assertEqual(p.geom_type, 'Polygon')
self.assertEqual(p.geom_typeid, 3) self.assertEqual(p.geom_typeid, 3)
@ -806,15 +816,15 @@ class GEOSTest(unittest.TestCase, TestDataMixin):
# Testing __getitem__ (doesn't work on Point or Polygon) # Testing __getitem__ (doesn't work on Point or Polygon)
if isinstance(g, Point): if isinstance(g, Point):
self.assertRaises(GEOSIndexError, g.get_x) self.assertRaises(IndexError, g.get_x)
elif isinstance(g, Polygon): elif isinstance(g, Polygon):
lr = g.shell lr = g.shell
self.assertEqual('LINEARRING EMPTY', lr.wkt) self.assertEqual('LINEARRING EMPTY', lr.wkt)
self.assertEqual(0, len(lr)) self.assertEqual(0, len(lr))
self.assertEqual(True, lr.empty) self.assertEqual(True, lr.empty)
self.assertRaises(GEOSIndexError, lr.__getitem__, 0) self.assertRaises(IndexError, lr.__getitem__, 0)
else: else:
self.assertRaises(GEOSIndexError, g.__getitem__, 0) self.assertRaises(IndexError, g.__getitem__, 0)
def test_collections_of_collections(self): def test_collections_of_collections(self):
"Testing GeometryCollection handling of other collections." "Testing GeometryCollection handling of other collections."

View File

@ -8,7 +8,6 @@ from unittest import skipUnless
from django.contrib.gis.geos import ( from django.contrib.gis.geos import (
HAS_GEOS, LinearRing, LineString, MultiPoint, Point, Polygon, fromstr, HAS_GEOS, LinearRing, LineString, MultiPoint, Point, Polygon, fromstr,
) )
from django.contrib.gis.geos.error import GEOSIndexError
def api_get_distance(x): def api_get_distance(x):
@ -79,12 +78,12 @@ class GEOSMutationTest(unittest.TestCase):
""" """
def test00_GEOSIndexException(self): def test00_GEOSIndexException(self):
'Testing Geometry GEOSIndexError' 'Testing Geometry IndexError'
p = Point(1, 2) p = Point(1, 2)
for i in range(-2, 2): for i in range(-2, 2):
p._checkindex(i) p._checkindex(i)
self.assertRaises(GEOSIndexError, p._checkindex, 2) self.assertRaises(IndexError, p._checkindex, 2)
self.assertRaises(GEOSIndexError, p._checkindex, -3) self.assertRaises(IndexError, p._checkindex, -3)
def test01_PointMutations(self): def test01_PointMutations(self):
'Testing Point mutations' 'Testing Point mutations'

View File

@ -337,9 +337,6 @@ class ListMixinTest(unittest.TestCase):
for i in (-self.limit - 1, self.limit): for i in (-self.limit - 1, self.limit):
self.assertRaises(IndexError, ul._checkindex, i) self.assertRaises(IndexError, ul._checkindex, i)
ul._IndexError = TypeError
self.assertRaises(TypeError, ul._checkindex, -self.limit - 1)
def test_11_sorting(self): def test_11_sorting(self):
'Sorting' 'Sorting'
pl, ul = self.lists_of_len() pl, ul = self.lists_of_len()