1
import os, os.path, unittest
2
from django.contrib.gis.gdal import DataSource, Envelope, OGRException, OGRIndexError
3
from django.contrib.gis.gdal.field import OFTReal, OFTInteger, OFTString
6
data_path = os.path.join(os.path.dirname(__file__), 'data')
7
def get_ds_file(name, ext):
8
return os.sep.join([data_path, name, name + '.%s' % ext])
10
# Test SHP data source object
12
def __init__(self, name, **kwargs):
13
ext = kwargs.pop('ext', 'shp')
14
self.ds = get_ds_file(name, ext)
15
for key, value in kwargs.items():
16
setattr(self, key, value)
18
# List of acceptable data sources.
19
ds_list = (TestDS('test_point', nfeat=5, nfld=3, geom='POINT', gtype=1, driver='ESRI Shapefile',
20
fields={'dbl' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,},
21
extent=(-1.35011,0.166623,-0.524093,0.824508), # 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
field_values={'dbl' : [float(i) for i in range(1, 6)], 'int' : range(1, 6), 'str' : [str(i) for i in range(1, 6)]},
25
TestDS('test_vrt', ext='vrt', nfeat=3, nfld=3, geom='POINT', gtype=1, driver='VRT',
26
fields={'POINT_X' : OFTString, 'POINT_Y' : OFTString, 'NUM' : OFTString}, # VRT uses CSV, which all types are OFTString.
27
extent=(1.0, 2.0, 100.0, 523.5), # Min/Max from CSV
28
field_values={'POINT_X' : ['1.0', '5.0', '100.0'], 'POINT_Y' : ['2.0', '23.0', '523.5'], 'NUM' : ['5', '17', '23']},
30
TestDS('test_poly', nfeat=3, nfld=3, geom='POLYGON', gtype=3,
31
driver='ESRI Shapefile',
32
fields={'float' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,},
33
extent=(-1.01513,-0.558245,0.161876,0.839637), # Got extent from QGIS
34
srs_wkt='GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]'),
37
bad_ds = (TestDS('foo'),
40
class DataSourceTest(unittest.TestCase):
42
def test01_valid_shp(self):
43
"Testing valid SHP Data Source files."
45
for source in ds_list:
46
# Loading up the data source
47
ds = DataSource(source.ds)
49
# Making sure the layer count is what's expected (only 1 layer in a SHP file)
50
self.assertEqual(1, len(ds))
52
# Making sure GetName works
53
self.assertEqual(source.ds, ds.name)
55
# Making sure the driver name matches up
56
self.assertEqual(source.driver, str(ds.driver))
58
# Making sure indexing works
64
self.fail('Expected an IndexError!')
66
def test02_invalid_shp(self):
67
"Testing invalid SHP files for the Data Source."
69
self.assertRaises(OGRException, DataSource, source.ds)
71
def test03a_layers(self):
72
"Testing Data Source Layers."
73
print "\nBEGIN - expecting out of range feature id error; safe to ignore.\n"
74
for source in ds_list:
75
ds = DataSource(source.ds)
77
# Incrementing through each layer, this tests DataSource.__iter__
79
# Making sure we get the number of features we expect
80
self.assertEqual(len(layer), source.nfeat)
82
# Making sure we get the number of fields we expect
83
self.assertEqual(source.nfld, layer.num_fields)
84
self.assertEqual(source.nfld, len(layer.fields))
86
# Testing the layer's extent (an Envelope), and it's properties
87
self.assertEqual(True, isinstance(layer.extent, Envelope))
88
self.assertAlmostEqual(source.extent[0], layer.extent.min_x, 5)
89
self.assertAlmostEqual(source.extent[1], layer.extent.min_y, 5)
90
self.assertAlmostEqual(source.extent[2], layer.extent.max_x, 5)
91
self.assertAlmostEqual(source.extent[3], layer.extent.max_y, 5)
93
# Now checking the field names.
95
for f in flds: self.assertEqual(True, f in source.fields)
97
# Negative FIDs are not allowed.
98
self.assertRaises(OGRIndexError, layer.__getitem__, -1)
99
self.assertRaises(OGRIndexError, layer.__getitem__, 50000)
101
if hasattr(source, 'field_values'):
102
fld_names = source.field_values.keys()
104
# Testing `Layer.get_fields` (which uses Layer.__iter__)
105
for fld_name in fld_names:
106
self.assertEqual(source.field_values[fld_name], layer.get_fields(fld_name))
108
# Testing `Layer.__getitem__`.
109
for i, fid in enumerate(source.fids):
111
self.assertEqual(fid, feat.fid)
112
# Maybe this should be in the test below, but we might as well test
113
# the feature values here while in this loop.
114
for fld_name in fld_names:
115
self.assertEqual(source.field_values[fld_name][i], feat.get(fld_name))
116
print "\nEND - expecting out of range feature id error; safe to ignore."
118
def test03b_layer_slice(self):
119
"Test indexing and slicing on Layers."
120
# Using the first data-source because the same slice
121
# can be used for both the layer and the control values.
123
ds = DataSource(source.ds)
128
for fld_name in ds[0].fields:
129
test_vals = [feat.get(fld_name) for feat in feats]
130
control_vals = source.field_values[fld_name][sl]
131
self.assertEqual(control_vals, test_vals)
133
def test03c_layer_references(self):
134
"Test to make sure Layer access is still available without the DataSource."
139
# This DataSource object is not accessible outside this
140
# scope. However, a reference should still be kept alive
141
# on the `Layer` returned.
142
ds = DataSource(source.ds)
145
# Making sure we can call OGR routines on the Layer returned.
147
self.assertEqual(source.nfeat, len(lyr))
148
self.assertEqual(source.gtype, lyr.geom_type.num)
150
def test04_features(self):
151
"Testing Data Source Features."
152
for source in ds_list:
153
ds = DataSource(source.ds)
155
# Incrementing through each layer
157
# Incrementing through each feature in the layer
159
# Making sure the number of fields, and the geometry type
160
# are what's expected.
161
self.assertEqual(source.nfld, len(list(feat)))
162
self.assertEqual(source.gtype, feat.geom_type)
164
# Making sure the fields match to an appropriate OFT type.
165
for k, v in source.fields.items():
166
# Making sure we get the proper OGR Field instance, using
167
# a string value index for the feature.
168
self.assertEqual(True, isinstance(feat[k], v))
170
# Testing Feature.__iter__
171
for fld in feat: self.assertEqual(True, fld.name in source.fields.keys())
173
def test05_geometries(self):
174
"Testing Geometries from Data Source Features."
175
for source in ds_list:
176
ds = DataSource(source.ds)
178
# Incrementing through each layer and feature.
183
# Making sure we get the right Geometry name & type
184
self.assertEqual(source.geom, g.geom_name)
185
self.assertEqual(source.gtype, g.geom_type)
187
# Making sure the SpatialReference is as expected.
188
if hasattr(source, 'srs_wkt'):
189
self.assertEqual(source.srs_wkt, g.srs.wkt)
193
s = unittest.TestSuite()
194
s.addTest(unittest.makeSuite(DataSourceTest))
197
def run(verbosity=2):
198
unittest.TextTestRunner(verbosity=verbosity).run(suite())