Fixed #28558 -- Simplified code to remove OGRIndexError.

The test is a regression for refs #4740 to show that the original fix of
OGRIndexError is no longer needed.

This is similar to the removal of GEOSIndexError in
197b187810.
This commit is contained in:
Nick Pope 2017-09-04 02:19:37 +01:00 committed by Tim Graham
parent feb1a0a692
commit 9397d3add4
8 changed files with 34 additions and 65 deletions

View File

@ -29,7 +29,7 @@ from django.contrib.gis.gdal.datasource import DataSource
from django.contrib.gis.gdal.driver import Driver from django.contrib.gis.gdal.driver import Driver
from django.contrib.gis.gdal.envelope import Envelope from django.contrib.gis.gdal.envelope import Envelope
from django.contrib.gis.gdal.error import ( from django.contrib.gis.gdal.error import (
GDALException, OGRIndexError, SRSException, check_err, GDALException, SRSException, check_err,
) )
from django.contrib.gis.gdal.geometries import OGRGeometry from django.contrib.gis.gdal.geometries import OGRGeometry
from django.contrib.gis.gdal.geomtype import OGRGeomType from django.contrib.gis.gdal.geomtype import OGRGeomType
@ -42,6 +42,6 @@ from django.contrib.gis.gdal.srs import CoordTransform, SpatialReference
__all__ = ( __all__ = (
'Driver', 'DataSource', 'CoordTransform', 'Envelope', 'GDALException', 'Driver', 'DataSource', 'CoordTransform', 'Envelope', 'GDALException',
'GDALRaster', 'GDAL_VERSION', 'OGRGeometry', 'OGRGeomType', 'GDALRaster', 'GDAL_VERSION', 'OGRGeometry', 'OGRGeomType',
'OGRIndexError', 'SpatialReference', 'SRSException', 'check_err', 'SpatialReference', 'SRSException', 'check_err', 'gdal_version',
'gdal_version', 'gdal_full_version', 'gdal_full_version',
) )

View File

@ -37,7 +37,7 @@ from ctypes import byref
from django.contrib.gis.gdal.base import GDALBase from django.contrib.gis.gdal.base import GDALBase
from django.contrib.gis.gdal.driver import Driver from django.contrib.gis.gdal.driver import Driver
from django.contrib.gis.gdal.error import GDALException, OGRIndexError from django.contrib.gis.gdal.error import GDALException
from django.contrib.gis.gdal.layer import Layer from django.contrib.gis.gdal.layer import Layer
from django.contrib.gis.gdal.prototypes import ds as capi from django.contrib.gis.gdal.prototypes import ds as capi
from django.utils.encoding import force_bytes, force_text from django.utils.encoding import force_bytes, force_text
@ -84,22 +84,17 @@ class DataSource(GDALBase):
# Raise an exception if the returned pointer is NULL # Raise an exception if the returned pointer is NULL
raise GDALException('Invalid data source file "%s"' % ds_input) raise GDALException('Invalid data source file "%s"' % ds_input)
def __iter__(self):
"Allows for iteration over the layers in a data source."
for i in range(self.layer_count):
yield self[i]
def __getitem__(self, index): def __getitem__(self, index):
"Allows use of the index [] operator to get a layer at the index." "Allows use of the index [] operator to get a layer at the index."
if isinstance(index, str): if isinstance(index, str):
layer = capi.get_layer_by_name(self.ptr, force_bytes(index)) layer = capi.get_layer_by_name(self.ptr, force_bytes(index))
if not layer: if not layer:
raise OGRIndexError('invalid OGR Layer name given: "%s"' % index) raise IndexError('invalid OGR Layer name given: "%s"' % index)
elif isinstance(index, int): elif isinstance(index, int):
if 0 <= index < self.layer_count: if 0 <= index < self.layer_count:
layer = capi.get_layer(self._ptr, index) layer = capi.get_layer(self._ptr, index)
else: else:
raise OGRIndexError('index out of range') raise IndexError('index out of range')
else: else:
raise TypeError('Invalid index type: %s' % type(index)) raise TypeError('Invalid index type: %s' % type(index))
return Layer(layer, self) return Layer(layer, self)

View File

@ -14,16 +14,6 @@ class SRSException(Exception):
pass pass
class OGRIndexError(GDALException, 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.
"""
silent_variable_failure = True
# #### GDAL/OGR error checking codes and routine #### # #### GDAL/OGR error checking codes and routine ####
# OGR Error Codes # OGR Error Codes

View File

@ -1,5 +1,5 @@
from django.contrib.gis.gdal.base import GDALBase from django.contrib.gis.gdal.base import GDALBase
from django.contrib.gis.gdal.error import GDALException, OGRIndexError from django.contrib.gis.gdal.error import GDALException
from django.contrib.gis.gdal.field import Field from django.contrib.gis.gdal.field import Field
from django.contrib.gis.gdal.geometries import OGRGeometry, OGRGeomType from django.contrib.gis.gdal.geometries import OGRGeometry, OGRGeomType
from django.contrib.gis.gdal.prototypes import ds as capi, geom as geom_api from django.contrib.gis.gdal.prototypes import ds as capi, geom as geom_api
@ -38,14 +38,9 @@ class Feature(GDALBase):
elif 0 <= index < self.num_fields: elif 0 <= index < self.num_fields:
i = index i = index
else: else:
raise OGRIndexError('index out of range') raise IndexError('index out of range')
return Field(self, i) return Field(self, i)
def __iter__(self):
"Iterate over each field in the Feature."
for i in range(self.num_fields):
yield self[i]
def __len__(self): def __len__(self):
"Return the count of fields in this feature." "Return the count of fields in this feature."
return self.num_fields return self.num_fields
@ -116,5 +111,5 @@ class Feature(GDALBase):
"Return the index of the given field name." "Return the index of the given field name."
i = capi.get_field_index(self.ptr, force_bytes(field_name)) i = capi.get_field_index(self.ptr, force_bytes(field_name))
if i < 0: if i < 0:
raise OGRIndexError('invalid OFT field name given: "%s"' % field_name) raise IndexError('invalid OFT field name given: "%s"' % field_name)
return i return i

View File

@ -44,9 +44,7 @@ from ctypes import byref, c_char_p, c_double, c_ubyte, c_void_p, string_at
from django.contrib.gis.gdal.base import GDALBase from django.contrib.gis.gdal.base import GDALBase
from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope
from django.contrib.gis.gdal.error import ( from django.contrib.gis.gdal.error import GDALException, SRSException
GDALException, OGRIndexError, SRSException,
)
from django.contrib.gis.gdal.geomtype import OGRGeomType from django.contrib.gis.gdal.geomtype import OGRGeomType
from django.contrib.gis.gdal.libgdal import GDAL_VERSION from django.contrib.gis.gdal.libgdal import GDAL_VERSION
from django.contrib.gis.gdal.prototypes import geom as capi, srs as srs_api from django.contrib.gis.gdal.prototypes import geom as capi, srs as srs_api
@ -566,12 +564,7 @@ class LineString(OGRGeometry):
elif dim == 3: elif dim == 3:
return (x.value, y.value, z.value) return (x.value, y.value, z.value)
else: else:
raise OGRIndexError('index out of range: %s' % index) raise IndexError('index out of range: %s' % index)
def __iter__(self):
"Iterate over each point in the LineString."
for i in range(self.point_count):
yield self[i]
def __len__(self): def __len__(self):
"Return the number of points in the LineString." "Return the number of points in the LineString."
@ -618,17 +611,12 @@ class Polygon(OGRGeometry):
"Return the number of interior rings in this Polygon." "Return the number of interior rings in this Polygon."
return self.geom_count return self.geom_count
def __iter__(self):
"Iterate through each ring in the Polygon."
for i in range(self.geom_count):
yield self[i]
def __getitem__(self, index): def __getitem__(self, index):
"Get the ring at the specified index." "Get the ring at the specified index."
if 0 <= index < self.geom_count: if 0 <= index < self.geom_count:
return OGRGeometry(capi.clone_geom(capi.get_geom_ref(self.ptr, index)), self.srs) return OGRGeometry(capi.clone_geom(capi.get_geom_ref(self.ptr, index)), self.srs)
else: else:
raise OGRIndexError('index out of range: %s' % index) raise IndexError('index out of range: %s' % index)
# Polygon Properties # Polygon Properties
@property @property
@ -667,12 +655,7 @@ class GeometryCollection(OGRGeometry):
if 0 <= index < self.geom_count: if 0 <= index < self.geom_count:
return OGRGeometry(capi.clone_geom(capi.get_geom_ref(self.ptr, index)), self.srs) return OGRGeometry(capi.clone_geom(capi.get_geom_ref(self.ptr, index)), self.srs)
else: else:
raise OGRIndexError('index out of range: %s' % index) raise IndexError('index out of range: %s' % index)
def __iter__(self):
"Iterate over each Geometry."
for i in range(self.geom_count):
yield self[i]
def __len__(self): def __len__(self):
"Return the number of geometries in this Geometry Collection." "Return the number of geometries in this Geometry Collection."

View File

@ -3,9 +3,7 @@ from ctypes import byref, c_double
from django.contrib.gis.gdal.base import GDALBase from django.contrib.gis.gdal.base import GDALBase
from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope from django.contrib.gis.gdal.envelope import Envelope, OGREnvelope
from django.contrib.gis.gdal.error import ( from django.contrib.gis.gdal.error import GDALException, SRSException
GDALException, OGRIndexError, SRSException,
)
from django.contrib.gis.gdal.feature import Feature from django.contrib.gis.gdal.feature import Feature
from django.contrib.gis.gdal.field import OGRFieldTypes from django.contrib.gis.gdal.field import OGRFieldTypes
from django.contrib.gis.gdal.geometries import OGRGeometry from django.contrib.gis.gdal.geometries import OGRGeometry
@ -46,7 +44,7 @@ class Layer(GDALBase):
# number of features because the beginning and ending feature IDs # number of features because the beginning and ending feature IDs
# are not guaranteed to be 0 and len(layer)-1, respectively. # are not guaranteed to be 0 and len(layer)-1, respectively.
if index < 0: if index < 0:
raise OGRIndexError('Negative indices are not allowed on OGR Layers.') raise IndexError('Negative indices are not allowed on OGR Layers.')
return self._make_feature(index) return self._make_feature(index)
elif isinstance(index, slice): elif isinstance(index, slice):
# A slice was given # A slice was given
@ -87,8 +85,8 @@ class Layer(GDALBase):
for feat in self: for feat in self:
if feat.fid == feat_id: if feat.fid == feat_id:
return feat return feat
# Should have returned a Feature, raise an OGRIndexError. # Should have returned a Feature, raise an IndexError.
raise OGRIndexError('Invalid feature id: %s.' % feat_id) raise IndexError('Invalid feature id: %s.' % feat_id)
# #### Layer properties #### # #### Layer properties ####
@property @property

View File

@ -4,7 +4,6 @@ import unittest
from django.contrib.gis.gdal import ( from django.contrib.gis.gdal import (
GDAL_VERSION, DataSource, Envelope, GDALException, OGRGeometry, GDAL_VERSION, DataSource, Envelope, GDALException, OGRGeometry,
OGRIndexError,
) )
from django.contrib.gis.gdal.field import OFTInteger, OFTReal, OFTString from django.contrib.gis.gdal.field import OFTInteger, OFTReal, OFTString
@ -84,7 +83,7 @@ class DataSourceTest(unittest.TestCase):
self.assertEqual(source.driver, str(ds.driver)) self.assertEqual(source.driver, str(ds.driver))
# Making sure indexing works # Making sure indexing works
with self.assertRaises(OGRIndexError): with self.assertRaises(IndexError):
ds[len(ds)] ds[len(ds)]
def test02_invalid_shp(self): def test02_invalid_shp(self):
@ -120,9 +119,9 @@ class DataSourceTest(unittest.TestCase):
self.assertIn(f, source.fields) self.assertIn(f, source.fields)
# Negative FIDs are not allowed. # Negative FIDs are not allowed.
with self.assertRaises(OGRIndexError): with self.assertRaises(IndexError):
layer.__getitem__(-1) layer.__getitem__(-1)
with self.assertRaises(OGRIndexError): with self.assertRaises(IndexError):
layer.__getitem__(50000) layer.__getitem__(50000)
if hasattr(source, 'field_values'): if hasattr(source, 'field_values'):

View File

@ -4,9 +4,10 @@ import unittest
from binascii import b2a_hex from binascii import b2a_hex
from django.contrib.gis.gdal import ( from django.contrib.gis.gdal import (
CoordTransform, GDALException, OGRGeometry, OGRGeomType, OGRIndexError, CoordTransform, GDALException, OGRGeometry, OGRGeomType, SpatialReference,
SpatialReference,
) )
from django.template import Context
from django.template.engine import Engine
from ..test_data import TestDataMixin from ..test_data import TestDataMixin
@ -157,7 +158,7 @@ class OGRGeomTest(unittest.TestCase, TestDataMixin):
self.assertEqual(ls.coords, linestr.tuple) self.assertEqual(ls.coords, linestr.tuple)
self.assertEqual(linestr, OGRGeometry(ls.wkt)) self.assertEqual(linestr, OGRGeometry(ls.wkt))
self.assertNotEqual(linestr, prev) self.assertNotEqual(linestr, prev)
with self.assertRaises(OGRIndexError): with self.assertRaises(IndexError):
linestr.__getitem__(len(linestr)) linestr.__getitem__(len(linestr))
prev = linestr prev = linestr
@ -182,7 +183,7 @@ class OGRGeomTest(unittest.TestCase, TestDataMixin):
for ls in mlinestr: for ls in mlinestr:
self.assertEqual(2, ls.geom_type) self.assertEqual(2, ls.geom_type)
self.assertEqual('LINESTRING', ls.geom_name) self.assertEqual('LINESTRING', ls.geom_name)
with self.assertRaises(OGRIndexError): with self.assertRaises(IndexError):
mlinestr.__getitem__(len(mlinestr)) mlinestr.__getitem__(len(mlinestr))
def test_linearring(self): def test_linearring(self):
@ -232,6 +233,14 @@ class OGRGeomTest(unittest.TestCase, TestDataMixin):
for r in poly: for r in poly:
self.assertEqual('LINEARRING', r.geom_name) self.assertEqual('LINEARRING', r.geom_name)
def test_polygons_templates(self):
# Accessing Polygon attributes in templates should work.
engine = Engine()
template = engine.from_string('{{ polygons.0.wkt }}')
polygons = [OGRGeometry(p.wkt) for p in self.geometries.multipolygons[:2]]
content = template.render(Context({'polygons': polygons}))
self.assertIn('MULTIPOLYGON (((100', content)
def test_closepolygons(self): def test_closepolygons(self):
"Testing closing Polygon objects." "Testing closing Polygon objects."
# Both rings in this geometry are not closed. # Both rings in this geometry are not closed.
@ -254,7 +263,7 @@ class OGRGeomTest(unittest.TestCase, TestDataMixin):
if mp.valid: if mp.valid:
self.assertEqual(mp.n_p, mpoly.point_count) self.assertEqual(mp.n_p, mpoly.point_count)
self.assertEqual(mp.num_geom, len(mpoly)) self.assertEqual(mp.num_geom, len(mpoly))
with self.assertRaises(OGRIndexError): with self.assertRaises(IndexError):
mpoly.__getitem__(len(mpoly)) mpoly.__getitem__(len(mpoly))
for p in mpoly: for p in mpoly:
self.assertEqual('POLYGON', p.geom_name) self.assertEqual('POLYGON', p.geom_name)