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