diff --git a/django/contrib/gis/gdal/field.py b/django/contrib/gis/gdal/field.py index 46dbc869b7..2b831b5516 100644 --- a/django/contrib/gis/gdal/field.py +++ b/django/contrib/gis/gdal/field.py @@ -20,7 +20,7 @@ class Field(GDALBase): # Setting the feature pointer and index. self._feat = feat self._index = index - + # Getting the pointer for this field. fld_ptr = capi.get_feat_field_defn(feat, index) if not fld_ptr: @@ -33,6 +33,7 @@ class Field(GDALBase): # OFTReal with no precision should be an OFTInteger. if isinstance(self, OFTReal) and self.precision == 0: self.__class__ = OFTInteger + self._double = True def __str__(self): "Returns the string representation of the Field." @@ -95,10 +96,17 @@ class Field(GDALBase): ### The Field sub-classes for each OGR Field type. ### class OFTInteger(Field): + _double = False + @property def value(self): "Returns an integer contained in this field." - return self.as_int() + if self._double: + # If this is really from an OFTReal field with no precision, + # read as a double and cast as Python int (to prevent overflow). + return int(self.as_double()) + else: + return self.as_int() @property def type(self): @@ -137,7 +145,7 @@ class OFTDateTime(Field): "Returns a Python `datetime` object for this OFTDateTime field." # TODO: Adapt timezone information. # See http://lists.maptools.org/pipermail/gdal-dev/2006-February/007990.html - # The `tz` variable has values of: 0=unknown, 1=localtime (ambiguous), + # The `tz` variable has values of: 0=unknown, 1=localtime (ambiguous), # 100=GMT, 104=GMT+1, 80=GMT-5, etc. try: yy, mm, dd, hh, mn, ss, tz = self.as_datetime() diff --git a/django/contrib/gis/gdal/tests/test_ds.py b/django/contrib/gis/gdal/tests/test_ds.py index e1083b2a35..16d6e8603b 100644 --- a/django/contrib/gis/gdal/tests/test_ds.py +++ b/django/contrib/gis/gdal/tests/test_ds.py @@ -1,7 +1,8 @@ -import os, os.path, unittest +import os +import unittest from django.contrib.gis.gdal import DataSource, Envelope, OGRGeometry, OGRException, OGRIndexError, GDAL_VERSION from django.contrib.gis.gdal.field import OFTReal, OFTInteger, OFTString -from django.contrib.gis.geometry.test_data import get_ds_file, TestDS +from django.contrib.gis.geometry.test_data import get_ds_file, TestDS, TEST_DATA # List of acceptable data sources. ds_list = (TestDS('test_point', nfeat=5, nfld=3, geom='POINT', gtype=1, driver='ESRI Shapefile', @@ -72,7 +73,7 @@ class DataSourceTest(unittest.TestCase): self.assertEqual(source.nfld, len(layer.fields)) # Testing the layer's extent (an Envelope), and it's properties - if source.driver == 'VRT' and (GDAL_VERSION > (1, 7, 0) and GDAL_VERSION < (1, 7, 3)): + if source.driver == 'VRT' and (GDAL_VERSION >= (1, 7, 0) and GDAL_VERSION < (1, 7, 3)): # There's a known GDAL regression with retrieving the extent # of a VRT layer in versions 1.7.0-1.7.2: # http://trac.osgeo.org/gdal/ticket/3783 @@ -217,6 +218,16 @@ class DataSourceTest(unittest.TestCase): lyr.spatial_filter = None self.assertEqual(3, len(lyr)) + def test07_integer_overflow(self): + "Testing that OFTReal fields, treated as OFTInteger, do not overflow." + # Using *.dbf from Census 2010 TIGER Shapefile for Texas, + # which has land area ('ALAND10') stored in a Real field + # with no precision. + ds = DataSource(os.path.join(TEST_DATA, 'texas.dbf')) + feat = ds[0][0] + # Reference value obtained using `ogrinfo`. + self.assertEqual(676586997978, feat.get('ALAND10')) + def suite(): s = unittest.TestSuite() s.addTest(unittest.makeSuite(DataSourceTest)) diff --git a/django/contrib/gis/tests/data/texas.dbf b/django/contrib/gis/tests/data/texas.dbf new file mode 100755 index 0000000000..827c065071 Binary files /dev/null and b/django/contrib/gis/tests/data/texas.dbf differ