PageRenderTime 27ms CodeModel.GetById 6ms app.highlight 17ms RepoModel.GetById 1ms app.codeStats 0ms

/django/contrib/gis/gdal/tests/test_ds.py

https://code.google.com/p/mango-py/
Python | 237 lines | 146 code | 42 blank | 49 comment | 51 complexity | a89f4c74c94b4b6dced9973a48f180d1 MD5 | raw file
  1import os
  2import unittest
  3from django.contrib.gis.gdal import DataSource, Envelope, OGRGeometry, OGRException, OGRIndexError, GDAL_VERSION
  4from django.contrib.gis.gdal.field import OFTReal, OFTInteger, OFTString
  5from django.contrib.gis.geometry.test_data import get_ds_file, TestDS, TEST_DATA
  6
  7# List of acceptable data sources.
  8ds_list = (TestDS('test_point', nfeat=5, nfld=3, geom='POINT', gtype=1, driver='ESRI Shapefile',
  9                  fields={'dbl' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,},
 10                  extent=(-1.35011,0.166623,-0.524093,0.824508), # Got extent from QGIS
 11                  srs_wkt='GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]',
 12                  field_values={'dbl' : [float(i) for i in range(1, 6)], 'int' : range(1, 6), 'str' : [str(i) for i in range(1, 6)]},
 13                  fids=range(5)),
 14           TestDS('test_vrt', ext='vrt', nfeat=3, nfld=3, geom='POINT', gtype='Point25D', driver='VRT',
 15                  fields={'POINT_X' : OFTString, 'POINT_Y' : OFTString, 'NUM' : OFTString}, # VRT uses CSV, which all types are OFTString.
 16                  extent=(1.0, 2.0, 100.0, 523.5), # Min/Max from CSV
 17                  field_values={'POINT_X' : ['1.0', '5.0', '100.0'], 'POINT_Y' : ['2.0', '23.0', '523.5'], 'NUM' : ['5', '17', '23']},
 18                  fids=range(1,4)),
 19           TestDS('test_poly', nfeat=3, nfld=3, geom='POLYGON', gtype=3,
 20                  driver='ESRI Shapefile',
 21                  fields={'float' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,},
 22                  extent=(-1.01513,-0.558245,0.161876,0.839637), # Got extent from QGIS
 23                  srs_wkt='GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]'),
 24           )
 25
 26bad_ds = (TestDS('foo'),
 27          )
 28
 29class DataSourceTest(unittest.TestCase):
 30
 31    def test01_valid_shp(self):
 32        "Testing valid SHP Data Source files."
 33
 34        for source in ds_list:
 35            # Loading up the data source
 36            ds = DataSource(source.ds)
 37
 38            # Making sure the layer count is what's expected (only 1 layer in a SHP file)
 39            self.assertEqual(1, len(ds))
 40
 41            # Making sure GetName works
 42            self.assertEqual(source.ds, ds.name)
 43
 44            # Making sure the driver name matches up
 45            self.assertEqual(source.driver, str(ds.driver))
 46
 47            # Making sure indexing works
 48            try:
 49                ds[len(ds)]
 50            except OGRIndexError:
 51                pass
 52            else:
 53                self.fail('Expected an IndexError!')
 54
 55    def test02_invalid_shp(self):
 56        "Testing invalid SHP files for the Data Source."
 57        for source in bad_ds:
 58            self.assertRaises(OGRException, DataSource, source.ds)
 59
 60    def test03a_layers(self):
 61        "Testing Data Source Layers."
 62        print "\nBEGIN - expecting out of range feature id error; safe to ignore.\n"
 63        for source in ds_list:
 64            ds = DataSource(source.ds)
 65
 66            # Incrementing through each layer, this tests DataSource.__iter__
 67            for layer in ds:
 68                # Making sure we get the number of features we expect
 69                self.assertEqual(len(layer), source.nfeat)
 70
 71                # Making sure we get the number of fields we expect
 72                self.assertEqual(source.nfld, layer.num_fields)
 73                self.assertEqual(source.nfld, len(layer.fields))
 74
 75                # Testing the layer's extent (an Envelope), and it's properties
 76                if source.driver == 'VRT' and (GDAL_VERSION >= (1, 7, 0) and GDAL_VERSION < (1, 7, 3)):
 77                    # There's a known GDAL regression with retrieving the extent
 78                    # of a VRT layer in versions 1.7.0-1.7.2:
 79                    #  http://trac.osgeo.org/gdal/ticket/3783
 80                    pass
 81                else:
 82                    self.assertEqual(True, isinstance(layer.extent, Envelope))
 83                    self.assertAlmostEqual(source.extent[0], layer.extent.min_x, 5)
 84                    self.assertAlmostEqual(source.extent[1], layer.extent.min_y, 5)
 85                    self.assertAlmostEqual(source.extent[2], layer.extent.max_x, 5)
 86                    self.assertAlmostEqual(source.extent[3], layer.extent.max_y, 5)
 87
 88                # Now checking the field names.
 89                flds = layer.fields
 90                for f in flds: self.assertEqual(True, f in source.fields)
 91
 92                # Negative FIDs are not allowed.
 93                self.assertRaises(OGRIndexError, layer.__getitem__, -1)
 94                self.assertRaises(OGRIndexError, layer.__getitem__, 50000)
 95
 96                if hasattr(source, 'field_values'):
 97                    fld_names = source.field_values.keys()
 98
 99                    # Testing `Layer.get_fields` (which uses Layer.__iter__)
100                    for fld_name in fld_names:
101                        self.assertEqual(source.field_values[fld_name], layer.get_fields(fld_name))
102
103                    # Testing `Layer.__getitem__`.
104                    for i, fid in enumerate(source.fids):
105                        feat = layer[fid]
106                        self.assertEqual(fid, feat.fid)
107                        # Maybe this should be in the test below, but we might as well test
108                        # the feature values here while in this loop.
109                        for fld_name in fld_names:
110                            self.assertEqual(source.field_values[fld_name][i], feat.get(fld_name))
111        print "\nEND - expecting out of range feature id error; safe to ignore."
112
113    def test03b_layer_slice(self):
114        "Test indexing and slicing on Layers."
115        # Using the first data-source because the same slice
116        # can be used for both the layer and the control values.
117        source = ds_list[0]
118        ds = DataSource(source.ds)
119
120        sl = slice(1, 3)
121        feats = ds[0][sl]
122
123        for fld_name in ds[0].fields:
124            test_vals = [feat.get(fld_name) for feat in feats]
125            control_vals = source.field_values[fld_name][sl]
126            self.assertEqual(control_vals, test_vals)
127
128    def test03c_layer_references(self):
129        "Test to make sure Layer access is still available without the DataSource."
130        source = ds_list[0]
131
132        # See ticket #9448.
133        def get_layer():
134            # This DataSource object is not accessible outside this
135            # scope.  However, a reference should still be kept alive
136            # on the `Layer` returned.
137            ds = DataSource(source.ds)
138            return ds[0]
139
140        # Making sure we can call OGR routines on the Layer returned.
141        lyr = get_layer()
142        self.assertEqual(source.nfeat, len(lyr))
143        self.assertEqual(source.gtype, lyr.geom_type.num)
144
145    def test04_features(self):
146        "Testing Data Source Features."
147        for source in ds_list:
148            ds = DataSource(source.ds)
149
150            # Incrementing through each layer
151            for layer in ds:
152                # Incrementing through each feature in the layer
153                for feat in layer:
154                    # Making sure the number of fields, and the geometry type
155                    # are what's expected.
156                    self.assertEqual(source.nfld, len(list(feat)))
157                    self.assertEqual(source.gtype, feat.geom_type)
158
159                    # Making sure the fields match to an appropriate OFT type.
160                    for k, v in source.fields.items():
161                        # Making sure we get the proper OGR Field instance, using
162                        # a string value index for the feature.
163                        self.assertEqual(True, isinstance(feat[k], v))
164
165                    # Testing Feature.__iter__
166                    for fld in feat: self.assertEqual(True, fld.name in source.fields.keys())
167
168    def test05_geometries(self):
169        "Testing Geometries from Data Source Features."
170        for source in ds_list:
171            ds = DataSource(source.ds)
172
173            # Incrementing through each layer and feature.
174            for layer in ds:
175                for feat in layer:
176                    g = feat.geom
177
178                    # Making sure we get the right Geometry name & type
179                    self.assertEqual(source.geom, g.geom_name)
180                    self.assertEqual(source.gtype, g.geom_type)
181
182                    # Making sure the SpatialReference is as expected.
183                    if hasattr(source, 'srs_wkt'):
184                        self.assertEqual(source.srs_wkt, g.srs.wkt)
185
186    def test06_spatial_filter(self):
187        "Testing the Layer.spatial_filter property."
188        ds = DataSource(get_ds_file('cities', 'shp'))
189        lyr = ds[0]
190
191        # When not set, it should be None.
192        self.assertEqual(None, lyr.spatial_filter)
193
194        # Must be set a/an OGRGeometry or 4-tuple.
195        self.assertRaises(TypeError, lyr._set_spatial_filter, 'foo')
196
197        # Setting the spatial filter with a tuple/list with the extent of
198        # a buffer centering around Pueblo.
199        self.assertRaises(ValueError, lyr._set_spatial_filter, range(5))
200        filter_extent = (-105.609252, 37.255001, -103.609252, 39.255001)
201        lyr.spatial_filter = (-105.609252, 37.255001, -103.609252, 39.255001)
202        self.assertEqual(OGRGeometry.from_bbox(filter_extent), lyr.spatial_filter)
203        feats = [feat for feat in lyr]
204        self.assertEqual(1, len(feats))
205        self.assertEqual('Pueblo', feats[0].get('Name'))
206
207        # Setting the spatial filter with an OGRGeometry for buffer centering
208        # around Houston.
209        filter_geom = OGRGeometry('POLYGON((-96.363151 28.763374,-94.363151 28.763374,-94.363151 30.763374,-96.363151 30.763374,-96.363151 28.763374))')
210        lyr.spatial_filter = filter_geom
211        self.assertEqual(filter_geom, lyr.spatial_filter)
212        feats = [feat for feat in lyr]
213        self.assertEqual(1, len(feats))
214        self.assertEqual('Houston', feats[0].get('Name'))
215
216        # Clearing the spatial filter by setting it to None.  Now
217        # should indicate that there are 3 features in the Layer.
218        lyr.spatial_filter = None
219        self.assertEqual(3, len(lyr))
220
221    def test07_integer_overflow(self):
222        "Testing that OFTReal fields, treated as OFTInteger, do not overflow."
223        # Using *.dbf from Census 2010 TIGER Shapefile for Texas,
224        # which has land area ('ALAND10') stored in a Real field
225        # with no precision.
226        ds = DataSource(os.path.join(TEST_DATA, 'texas.dbf'))
227        feat = ds[0][0]
228        # Reference value obtained using `ogrinfo`.
229        self.assertEqual(676586997978, feat.get('ALAND10'))
230
231def suite():
232    s = unittest.TestSuite()
233    s.addTest(unittest.makeSuite(DataSourceTest))
234    return s
235
236def run(verbosity=2):
237    unittest.TextTestRunner(verbosity=verbosity).run(suite())