Changeset 8034
- Timestamp:
- 07/21/08 20:10:59 (5 months ago)
- Files:
-
- django/branches/gis/django/contrib/gis/gdal/error.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/gdal/geometries.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/gdal/geomtype.py (modified) (2 diffs)
- django/branches/gis/django/contrib/gis/gdal/layer.py (modified) (5 diffs)
- django/branches/gis/django/contrib/gis/gdal/prototypes/ds.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/tests/data (added)
- django/branches/gis/django/contrib/gis/tests/data/test_point (moved) (moved from django/branches/gis/django/contrib/gis/tests/test_point)
- django/branches/gis/django/contrib/gis/tests/data/test_poly (moved) (moved from django/branches/gis/django/contrib/gis/tests/test_poly)
- django/branches/gis/django/contrib/gis/tests/data/test_vrt (added)
- django/branches/gis/django/contrib/gis/tests/data/test_vrt/test_vrt.csv (added)
- django/branches/gis/django/contrib/gis/tests/data/test_vrt/test_vrt.vrt (added)
- django/branches/gis/django/contrib/gis/tests/test_gdal_ds.py (modified) (7 diffs)
- django/branches/gis/django/contrib/gis/tests/test_gdal_geom.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/gis/django/contrib/gis/gdal/error.py
r6686 r8034 26 26 6 : (OGRException, 'OGR failure.'), 27 27 7 : (SRSException, 'Unsupported SRS.'), 28 8 : (OGRException, 'Invalid handle.'), 28 29 } 29 30 OGRERR_NONE = 0 django/branches/gis/django/contrib/gis/gdal/geometries.py
r7767 r8034 202 202 def geom_type(self): 203 203 "Returns the Type for this Geometry." 204 return OGRGeomType(get_geom_type(self._ptr)) 204 try: 205 return OGRGeomType(get_geom_type(self._ptr)) 206 except OGRException: 207 # VRT datasources return an invalid geometry type 208 # number, but a valid name -- we'll try that instead. 209 # See: http://trac.osgeo.org/gdal/ticket/2491 210 return OGRGeomType(get_geom_name(self._ptr)) 205 211 206 212 @property django/branches/gis/django/contrib/gis/gdal/geomtype.py
r7665 r8034 5 5 "Encapulates OGR Geometry Types." 6 6 7 # Ordered array of acceptable strings and their corresponding OGRwkbGeometryType 8 __ogr_str = ['Unknown', 'Point', 'LineString', 'Polygon', 'MultiPoint', 9 'MultiLineString', 'MultiPolygon', 'GeometryCollection', 10 'LinearRing'] 11 __ogr_int = [0, 1, 2, 3, 4, 5, 6, 7, 101] 7 # Dictionary of acceptable OGRwkbGeometryType s and their string names. 8 _types = {0 : 'Unknown', 9 1 : 'Point', 10 2 : 'LineString', 11 3 : 'Polygon', 12 4 : 'MultiPoint', 13 5 : 'MultiLineString', 14 6 : 'MultiPolygon', 15 7 : 'GeometryCollection', 16 100 : 'None', 17 101 : 'LinearRing', 18 } 19 # Reverse type dictionary, keyed by lower-case of the name. 20 _str_types = dict([(v.lower(), k) for k, v in _types.items()]) 12 21 13 22 def __init__(self, type_input): 14 23 "Figures out the correct OGR Type based upon the input." 15 24 if isinstance(type_input, OGRGeomType): 16 self._index = type_input._index25 num = type_input.num 17 26 elif isinstance(type_input, basestring): 18 idx = self._has_str(self.__ogr_str, type_input)19 if idx ==None:27 num = self._str_types.get(type_input.lower(), None) 28 if num is None: 20 29 raise OGRException('Invalid OGR String Type "%s"' % type_input) 21 self._index = idx22 30 elif isinstance(type_input, int): 23 if not type_input in self._ _ogr_int:31 if not type_input in self._types: 24 32 raise OGRException('Invalid OGR Integer Type: %d' % type_input) 25 self._index = self.__ogr_int.index(type_input)33 num = type_input 26 34 else: 27 35 raise TypeError('Invalid OGR input type given.') 36 37 # Setting the OGR geometry type number. 38 self.num = num 28 39 29 40 def __str__(self): 30 "Returns a short-hand string form of the OGR Geometry type."31 return self. __ogr_str[self._index]41 "Returns the value of the name property." 42 return self.name 32 43 33 44 def __eq__(self, other): … … 37 48 """ 38 49 if isinstance(other, OGRGeomType): 39 return self. _index == other._index50 return self.num == other.num 40 51 elif isinstance(other, basestring): 41 idx = self._has_str(self.__ogr_str, other) 42 if not (idx == None): return self._index == idx 52 return self.name.lower() == other.lower() 53 elif isinstance(other, int): 54 return self.num == other 55 else: 43 56 return False 44 elif isinstance(other, int):45 if not other in self.__ogr_int: return False46 return self.__ogr_int.index(other) == self._index47 else:48 raise TypeError('Cannot compare with type: %s' % str(type(other)))49 57 50 58 def __ne__(self, other): 51 59 return not (self == other) 52 60 53 def _has_str(self, arr, s): 54 "Case-insensitive search of the string array for the given pattern." 55 s_low = s.lower() 56 for i in xrange(len(arr)): 57 if s_low == arr[i].lower(): return i 58 return None 61 @property 62 def name(self): 63 "Returns a short-hand string form of the OGR Geometry type." 64 return self._types[self.num] 59 65 60 66 @property 61 67 def django(self): 62 68 "Returns the Django GeometryField for this OGR Type." 63 s = self. __ogr_str[self._index]64 if s in ('Unknown', 'LinearRing' ):69 s = self.name 70 if s in ('Unknown', 'LinearRing', 'None'): 65 71 return None 66 72 else: 67 73 return s + 'Field' 68 69 @property70 def num(self):71 "Returns the OGRwkbGeometryType number for the OGR Type."72 return self.__ogr_int[self._index]django/branches/gis/django/contrib/gis/gdal/layer.py
r6992 r8034 15 15 get_field_count, get_field_defn, get_field_name, get_field_precision, \ 16 16 get_field_width, get_field_type, get_layer_defn, get_layer_srs, \ 17 get_next_feature, reset_reading 17 get_next_feature, reset_reading, test_capability 18 18 from django.contrib.gis.gdal.prototypes.srs import clone_srs 19 19 … … 33 33 self._ptr = layer_ptr 34 34 self._ldefn = get_layer_defn(self._ptr) 35 # Does the Layer support random reading? 36 self._random_read = self.test_capability('RandomRead') 35 37 36 38 def __getitem__(self, index): 37 39 "Gets the Feature at the specified index." 38 if not isinstance(index, (slice, int)): 39 raise TypeError 40 end = self.num_feat 41 if isinstance(index,int): 42 # An integer index was given 43 if index < 0: 44 index = end - index 45 if index < 0 or index >= self.num_feat: 46 raise OGRIndexError('index out of range') 40 if isinstance(index, (int, long)): 41 # An integer index was given -- we cannot do a check based on the 42 # number of features because the beginning and ending feature IDs 43 # are not guaranteed to be 0 and len(layer)-1, respectively. 44 if index < 0: raise OGRIndexError('Negative indices are not allowed on OGR Layers.') 47 45 return self._make_feature(index) 48 el se:46 elif isinstance(index, slice): 49 47 # A slice was given 50 start, stop, stride = index.indices(end) 51 return [self._make_feature(offset) for offset in range(start,stop,stride)] 48 start, stop, stride = index.indices(self.num_feat) 49 return [self._make_feature(fid) for fid in xrange(start, stop, stride)] 50 else: 51 raise TypeError('Integers and slices may only be used when indexing OGR Layers.') 52 52 53 53 def __iter__(self): … … 55 55 # ResetReading() must be called before iteration is to begin. 56 56 reset_reading(self._ptr) 57 for i in range(self.num_feat):57 for i in xrange(self.num_feat): 58 58 yield Feature(get_next_feature(self._ptr), self._ldefn) 59 59 … … 66 66 return self.name 67 67 68 def _make_feature(self, offset): 69 "Helper routine for __getitem__ that makes a feature from an offset." 70 return Feature(get_feature(self._ptr, offset), self._ldefn) 68 def _make_feature(self, feat_id): 69 """ 70 Helper routine for __getitem__ that constructs a Feature from the given 71 Feature ID. If the OGR Layer does not support random-access reading, 72 then each feature of the layer will be incremented through until the 73 a Feature is found matching the given feature ID. 74 """ 75 if self._random_read: 76 # If the Layer supports random reading, return. 77 try: 78 return Feature(get_feature(self._ptr, feat_id), self._ldefn) 79 except OGRException: 80 pass 81 else: 82 # Random access isn't supported, have to increment through 83 # each feature until the given feature ID is encountered. 84 for feat in self: 85 if feat.fid == feat_id: return feat 86 # Should have returned a Feature, raise an OGRIndexError. 87 raise OGRIndexError('Invalid feature id: %s.' % feat_id) 71 88 72 89 #### Layer properties #### … … 159 176 else: 160 177 return [feat.geom for feat in self] 178 179 def test_capability(self, capability): 180 """ 181 Returns a bool indicating whether the this Layer supports the given 182 capability (a string). Valid capability strings include: 183 'RandomRead', 'SequentialWrite', 'RandomWrite', 'FastSpatialFilter', 184 'FastFeatureCount', 'FastGetExtent', 'CreateField', 'Transactions', 185 'DeleteFeature', and 'FastSetNextByIndex'. 186 """ 187 return bool(test_capability(self._ptr, capability)) django/branches/gis/django/contrib/gis/gdal/prototypes/ds.py
r6914 r8034 38 38 get_next_feature = voidptr_output(lgdal.OGR_L_GetNextFeature, [c_void_p]) 39 39 reset_reading = void_output(lgdal.OGR_L_ResetReading, [c_void_p], errcheck=False) 40 test_capability = int_output(lgdal.OGR_L_TestCapability, [c_void_p, c_char_p]) 40 41 41 42 ### Feature Definition Routines ### django/branches/gis/django/contrib/gis/tests/test_gdal_ds.py
r6686 r8034 4 4 5 5 # Path for SHP files 6 shp_path = os.path.dirname(__file__)7 def get_ shp(name):8 return shp_path + os.sep + name + os.sep + name + '.shp'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]) 9 9 10 10 # Test SHP data source object 11 class TestSHP: 12 def __init__(self, shp, **kwargs): 13 self.ds = get_shp(shp) 11 class TestDS: 12 def __init__(self, name, **kwargs): 13 ext = kwargs.pop('ext', 'shp') 14 self.ds = get_ds_file(name, ext) 14 15 for key, value in kwargs.items(): 15 16 setattr(self, key, value) 16 17 17 18 # List of acceptable data sources. 18 ds_list = (TestSHP('test_point', nfeat=5, nfld=3, geom='POINT', gtype=1, fields={'dbl' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,}, 19 extent=(-1.35011,0.166623,-0.524093,0.824508), # Got extent from QGIS 20 srs_wkt='GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]'), 21 TestSHP('test_poly', nfeat=3, nfld=3, geom='POLYGON', gtype=3, 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]]'), 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)]}, 24 fids=range(5)), 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']}, 29 fids=range(1,4)), 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]]'), 24 35 ) 25 36 26 bad_ds = (Test SHP('foo'),37 bad_ds = (TestDS('foo'), 27 38 ) 28 39 … … 43 54 44 55 # Making sure the driver name matches up 45 self.assertEqual( 'ESRI Shapefile', str(ds.driver))56 self.assertEqual(source.driver, str(ds.driver)) 46 57 47 58 # Making sure indexing works … … 58 69 self.assertRaises(OGRException, DataSource, source.ds) 59 70 60 def test03 _layers(self):71 def test03a_layers(self): 61 72 "Testing Data Source Layers." 62 73 print "\nBEGIN - expecting out of range feature id error; safe to ignore.\n" 63 74 for source in ds_list: 64 75 ds = DataSource(source.ds) 65 76 66 # Incrementing through each layer, this tests __iter__77 # Incrementing through each layer, this tests DataSource.__iter__ 67 78 for layer in ds: 68 79 # Making sure we get the number of features we expect 69 80 self.assertEqual(len(layer), source.nfeat) 70 71 layer[0] #can index72 layer[:1] #can slice73 81 74 82 # Making sure we get the number of fields we expect … … 86 94 flds = layer.fields 87 95 for f in flds: self.assertEqual(True, f in source.fields) 96 97 # Negative FIDs are not allowed. 98 self.assertRaises(OGRIndexError, layer.__getitem__, -1) 99 self.assertRaises(OGRIndexError, layer.__getitem__, 50000) 100 101 if hasattr(source, 'field_values'): 102 fld_names = source.field_values.keys() 103 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)) 107 108 # Testing `Layer.__getitem__`. 109 for i, fid in enumerate(source.fids): 110 feat = layer[fid] 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." 117 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. 122 source = ds_list[0] 123 ds = DataSource(source.ds) 124 125 sl = slice(1, 3) 126 feats = ds[0][sl] 127 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) 88 132 89 133 def test04_features(self): … … 96 140 # Incrementing through each feature in the layer 97 141 for feat in layer: 98 # Making sure the number of fields is what's expected. 142 # Making sure the number of fields, and the geometry type 143 # are what's expected. 99 144 self.assertEqual(source.nfld, len(list(feat))) 100 145 self.assertEqual(source.gtype, feat.geom_type) … … 106 151 self.assertEqual(True, isinstance(feat[k], v)) 107 152 108 # Testing __iter__ on the Feature153 # Testing Feature.__iter__ 109 154 for fld in feat: self.assertEqual(True, fld.name in source.fields.keys()) 110 155 … … 124 169 125 170 # Making sure the SpatialReference is as expected. 126 self.assertEqual(source.srs_wkt, g.srs.wkt) 127 171 if hasattr(source, 'srs_wkt'): 172 self.assertEqual(source.srs_wkt, g.srs.wkt) 173 174 128 175 def suite(): 129 176 s = unittest.TestSuite() django/branches/gis/django/contrib/gis/tests/test_gdal_geom.py
r7665 r8034 36 36 self.assertEqual(False, OGRGeomType(1) != OGRGeomType('point')) 37 37 self.assertEqual(True, OGRGeomType('POINT') != OGRGeomType(6)) 38 39 # Testing the Django field name equivalent property. 40 self.assertEqual('PointField', OGRGeomType('Point').django) 41 self.assertEqual(None, OGRGeomType('Unknown').django) 42 self.assertEqual(None, OGRGeomType('none').django) 38 43 39 44 def test01a_wkt(self):
