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:
parent
20787b5c29
commit
197b187810
@ -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
|
||||||
|
@ -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."
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
||||||
|
@ -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'):
|
||||||
|
@ -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."
|
||||||
|
@ -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'
|
||||||
|
@ -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()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user