mirror of
https://github.com/django/django.git
synced 2025-07-04 09:49:12 +00:00
gis: gdal: Features may now be fetched from OGR layers that do not support random access reading, but no more negative indexes are allowed; cleaned up OGRGeomType
; moved test vector data into its own directory.
git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@8034 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
7011fc6d3c
commit
825d6edd69
@ -25,6 +25,7 @@ OGRERR_DICT = { 1 : (OGRException, 'Not enough data.'),
|
|||||||
5 : (OGRException, 'Corrupt data.'),
|
5 : (OGRException, 'Corrupt data.'),
|
||||||
6 : (OGRException, 'OGR failure.'),
|
6 : (OGRException, 'OGR failure.'),
|
||||||
7 : (SRSException, 'Unsupported SRS.'),
|
7 : (SRSException, 'Unsupported SRS.'),
|
||||||
|
8 : (OGRException, 'Invalid handle.'),
|
||||||
}
|
}
|
||||||
OGRERR_NONE = 0
|
OGRERR_NONE = 0
|
||||||
|
|
||||||
|
@ -201,7 +201,13 @@ class OGRGeometry(object):
|
|||||||
@property
|
@property
|
||||||
def geom_type(self):
|
def geom_type(self):
|
||||||
"Returns the Type for this Geometry."
|
"Returns the Type for this Geometry."
|
||||||
|
try:
|
||||||
return OGRGeomType(get_geom_type(self._ptr))
|
return OGRGeomType(get_geom_type(self._ptr))
|
||||||
|
except OGRException:
|
||||||
|
# VRT datasources return an invalid geometry type
|
||||||
|
# number, but a valid name -- we'll try that instead.
|
||||||
|
# See: http://trac.osgeo.org/gdal/ticket/2491
|
||||||
|
return OGRGeomType(get_geom_name(self._ptr))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def geom_name(self):
|
def geom_name(self):
|
||||||
|
@ -4,31 +4,42 @@ from django.contrib.gis.gdal.error import OGRException
|
|||||||
class OGRGeomType(object):
|
class OGRGeomType(object):
|
||||||
"Encapulates OGR Geometry Types."
|
"Encapulates OGR Geometry Types."
|
||||||
|
|
||||||
# Ordered array of acceptable strings and their corresponding OGRwkbGeometryType
|
# Dictionary of acceptable OGRwkbGeometryType s and their string names.
|
||||||
__ogr_str = ['Unknown', 'Point', 'LineString', 'Polygon', 'MultiPoint',
|
_types = {0 : 'Unknown',
|
||||||
'MultiLineString', 'MultiPolygon', 'GeometryCollection',
|
1 : 'Point',
|
||||||
'LinearRing']
|
2 : 'LineString',
|
||||||
__ogr_int = [0, 1, 2, 3, 4, 5, 6, 7, 101]
|
3 : 'Polygon',
|
||||||
|
4 : 'MultiPoint',
|
||||||
|
5 : 'MultiLineString',
|
||||||
|
6 : 'MultiPolygon',
|
||||||
|
7 : 'GeometryCollection',
|
||||||
|
100 : 'None',
|
||||||
|
101 : 'LinearRing',
|
||||||
|
}
|
||||||
|
# Reverse type dictionary, keyed by lower-case of the name.
|
||||||
|
_str_types = dict([(v.lower(), k) for k, v in _types.items()])
|
||||||
|
|
||||||
def __init__(self, type_input):
|
def __init__(self, type_input):
|
||||||
"Figures out the correct OGR Type based upon the input."
|
"Figures out the correct OGR Type based upon the input."
|
||||||
if isinstance(type_input, OGRGeomType):
|
if isinstance(type_input, OGRGeomType):
|
||||||
self._index = type_input._index
|
num = type_input.num
|
||||||
elif isinstance(type_input, basestring):
|
elif isinstance(type_input, basestring):
|
||||||
idx = self._has_str(self.__ogr_str, type_input)
|
num = self._str_types.get(type_input.lower(), None)
|
||||||
if idx == None:
|
if num is None:
|
||||||
raise OGRException('Invalid OGR String Type "%s"' % type_input)
|
raise OGRException('Invalid OGR String Type "%s"' % type_input)
|
||||||
self._index = idx
|
|
||||||
elif isinstance(type_input, int):
|
elif isinstance(type_input, int):
|
||||||
if not type_input in self.__ogr_int:
|
if not type_input in self._types:
|
||||||
raise OGRException('Invalid OGR Integer Type: %d' % type_input)
|
raise OGRException('Invalid OGR Integer Type: %d' % type_input)
|
||||||
self._index = self.__ogr_int.index(type_input)
|
num = type_input
|
||||||
else:
|
else:
|
||||||
raise TypeError('Invalid OGR input type given.')
|
raise TypeError('Invalid OGR input type given.')
|
||||||
|
|
||||||
|
# Setting the OGR geometry type number.
|
||||||
|
self.num = num
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
"Returns a short-hand string form of the OGR Geometry type."
|
"Returns the value of the name property."
|
||||||
return self.__ogr_str[self._index]
|
return self.name
|
||||||
|
|
||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
"""
|
"""
|
||||||
@ -36,37 +47,27 @@ class OGRGeomType(object):
|
|||||||
other OGRGeomType, the short-hand string, or the integer.
|
other OGRGeomType, the short-hand string, or the integer.
|
||||||
"""
|
"""
|
||||||
if isinstance(other, OGRGeomType):
|
if isinstance(other, OGRGeomType):
|
||||||
return self._index == other._index
|
return self.num == other.num
|
||||||
elif isinstance(other, basestring):
|
elif isinstance(other, basestring):
|
||||||
idx = self._has_str(self.__ogr_str, other)
|
return self.name.lower() == other.lower()
|
||||||
if not (idx == None): return self._index == idx
|
|
||||||
return False
|
|
||||||
elif isinstance(other, int):
|
elif isinstance(other, int):
|
||||||
if not other in self.__ogr_int: return False
|
return self.num == other
|
||||||
return self.__ogr_int.index(other) == self._index
|
|
||||||
else:
|
else:
|
||||||
raise TypeError('Cannot compare with type: %s' % str(type(other)))
|
return False
|
||||||
|
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return not (self == other)
|
return not (self == other)
|
||||||
|
|
||||||
def _has_str(self, arr, s):
|
@property
|
||||||
"Case-insensitive search of the string array for the given pattern."
|
def name(self):
|
||||||
s_low = s.lower()
|
"Returns a short-hand string form of the OGR Geometry type."
|
||||||
for i in xrange(len(arr)):
|
return self._types[self.num]
|
||||||
if s_low == arr[i].lower(): return i
|
|
||||||
return None
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def django(self):
|
def django(self):
|
||||||
"Returns the Django GeometryField for this OGR Type."
|
"Returns the Django GeometryField for this OGR Type."
|
||||||
s = self.__ogr_str[self._index]
|
s = self.name
|
||||||
if s in ('Unknown', 'LinearRing'):
|
if s in ('Unknown', 'LinearRing', 'None'):
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return s + 'Field'
|
return s + 'Field'
|
||||||
|
|
||||||
@property
|
|
||||||
def num(self):
|
|
||||||
"Returns the OGRwkbGeometryType number for the OGR Type."
|
|
||||||
return self.__ogr_int[self._index]
|
|
||||||
|
@ -14,7 +14,7 @@ from django.contrib.gis.gdal.prototypes.ds import \
|
|||||||
get_extent, get_fd_geom_type, get_fd_name, get_feature, get_feature_count, \
|
get_extent, get_fd_geom_type, get_fd_name, get_feature, get_feature_count, \
|
||||||
get_field_count, get_field_defn, get_field_name, get_field_precision, \
|
get_field_count, get_field_defn, get_field_name, get_field_precision, \
|
||||||
get_field_width, get_field_type, get_layer_defn, get_layer_srs, \
|
get_field_width, get_field_type, get_layer_defn, get_layer_srs, \
|
||||||
get_next_feature, reset_reading
|
get_next_feature, reset_reading, test_capability
|
||||||
from django.contrib.gis.gdal.prototypes.srs import clone_srs
|
from django.contrib.gis.gdal.prototypes.srs import clone_srs
|
||||||
|
|
||||||
# For more information, see the OGR C API source code:
|
# For more information, see the OGR C API source code:
|
||||||
@ -32,29 +32,29 @@ class Layer(object):
|
|||||||
raise OGRException('Cannot create Layer, invalid pointer given')
|
raise OGRException('Cannot create Layer, invalid pointer given')
|
||||||
self._ptr = layer_ptr
|
self._ptr = layer_ptr
|
||||||
self._ldefn = get_layer_defn(self._ptr)
|
self._ldefn = get_layer_defn(self._ptr)
|
||||||
|
# Does the Layer support random reading?
|
||||||
|
self._random_read = self.test_capability('RandomRead')
|
||||||
|
|
||||||
def __getitem__(self, index):
|
def __getitem__(self, index):
|
||||||
"Gets the Feature at the specified index."
|
"Gets the Feature at the specified index."
|
||||||
if not isinstance(index, (slice, int)):
|
if isinstance(index, (int, long)):
|
||||||
raise TypeError
|
# An integer index was given -- we cannot do a check based on the
|
||||||
end = self.num_feat
|
# number of features because the beginning and ending feature IDs
|
||||||
if isinstance(index,int):
|
# are not guaranteed to be 0 and len(layer)-1, respectively.
|
||||||
# An integer index was given
|
if index < 0: raise OGRIndexError('Negative indices are not allowed on OGR Layers.')
|
||||||
if index < 0:
|
|
||||||
index = end - index
|
|
||||||
if index < 0 or index >= self.num_feat:
|
|
||||||
raise OGRIndexError('index out of range')
|
|
||||||
return self._make_feature(index)
|
return self._make_feature(index)
|
||||||
else:
|
elif isinstance(index, slice):
|
||||||
# A slice was given
|
# A slice was given
|
||||||
start, stop, stride = index.indices(end)
|
start, stop, stride = index.indices(self.num_feat)
|
||||||
return [self._make_feature(offset) for offset in range(start,stop,stride)]
|
return [self._make_feature(fid) for fid in xrange(start, stop, stride)]
|
||||||
|
else:
|
||||||
|
raise TypeError('Integers and slices may only be used when indexing OGR Layers.')
|
||||||
|
|
||||||
def __iter__(self):
|
def __iter__(self):
|
||||||
"Iterates over each Feature in the Layer."
|
"Iterates over each Feature in the Layer."
|
||||||
# ResetReading() must be called before iteration is to begin.
|
# ResetReading() must be called before iteration is to begin.
|
||||||
reset_reading(self._ptr)
|
reset_reading(self._ptr)
|
||||||
for i in range(self.num_feat):
|
for i in xrange(self.num_feat):
|
||||||
yield Feature(get_next_feature(self._ptr), self._ldefn)
|
yield Feature(get_next_feature(self._ptr), self._ldefn)
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
@ -65,9 +65,26 @@ class Layer(object):
|
|||||||
"The string name of the layer."
|
"The string name of the layer."
|
||||||
return self.name
|
return self.name
|
||||||
|
|
||||||
def _make_feature(self, offset):
|
def _make_feature(self, feat_id):
|
||||||
"Helper routine for __getitem__ that makes a feature from an offset."
|
"""
|
||||||
return Feature(get_feature(self._ptr, offset), self._ldefn)
|
Helper routine for __getitem__ that constructs a Feature from the given
|
||||||
|
Feature ID. If the OGR Layer does not support random-access reading,
|
||||||
|
then each feature of the layer will be incremented through until the
|
||||||
|
a Feature is found matching the given feature ID.
|
||||||
|
"""
|
||||||
|
if self._random_read:
|
||||||
|
# If the Layer supports random reading, return.
|
||||||
|
try:
|
||||||
|
return Feature(get_feature(self._ptr, feat_id), self._ldefn)
|
||||||
|
except OGRException:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
# Random access isn't supported, have to increment through
|
||||||
|
# each feature until the given feature ID is encountered.
|
||||||
|
for feat in self:
|
||||||
|
if feat.fid == feat_id: return feat
|
||||||
|
# Should have returned a Feature, raise an OGRIndexError.
|
||||||
|
raise OGRIndexError('Invalid feature id: %s.' % feat_id)
|
||||||
|
|
||||||
#### Layer properties ####
|
#### Layer properties ####
|
||||||
@property
|
@property
|
||||||
@ -158,3 +175,13 @@ class Layer(object):
|
|||||||
return [GEOSGeometry(feat.geom.wkb) for feat in self]
|
return [GEOSGeometry(feat.geom.wkb) for feat in self]
|
||||||
else:
|
else:
|
||||||
return [feat.geom for feat in self]
|
return [feat.geom for feat in self]
|
||||||
|
|
||||||
|
def test_capability(self, capability):
|
||||||
|
"""
|
||||||
|
Returns a bool indicating whether the this Layer supports the given
|
||||||
|
capability (a string). Valid capability strings include:
|
||||||
|
'RandomRead', 'SequentialWrite', 'RandomWrite', 'FastSpatialFilter',
|
||||||
|
'FastFeatureCount', 'FastGetExtent', 'CreateField', 'Transactions',
|
||||||
|
'DeleteFeature', and 'FastSetNextByIndex'.
|
||||||
|
"""
|
||||||
|
return bool(test_capability(self._ptr, capability))
|
||||||
|
@ -37,6 +37,7 @@ get_layer_defn = voidptr_output(lgdal.OGR_L_GetLayerDefn, [c_void_p])
|
|||||||
get_layer_srs = srs_output(lgdal.OGR_L_GetSpatialRef, [c_void_p])
|
get_layer_srs = srs_output(lgdal.OGR_L_GetSpatialRef, [c_void_p])
|
||||||
get_next_feature = voidptr_output(lgdal.OGR_L_GetNextFeature, [c_void_p])
|
get_next_feature = voidptr_output(lgdal.OGR_L_GetNextFeature, [c_void_p])
|
||||||
reset_reading = void_output(lgdal.OGR_L_ResetReading, [c_void_p], errcheck=False)
|
reset_reading = void_output(lgdal.OGR_L_ResetReading, [c_void_p], errcheck=False)
|
||||||
|
test_capability = int_output(lgdal.OGR_L_TestCapability, [c_void_p, c_char_p])
|
||||||
|
|
||||||
### Feature Definition Routines ###
|
### Feature Definition Routines ###
|
||||||
get_fd_geom_type = int_output(lgdal.OGR_FD_GetGeomType, [c_void_p])
|
get_fd_geom_type = int_output(lgdal.OGR_FD_GetGeomType, [c_void_p])
|
||||||
|
4
django/contrib/gis/tests/data/test_vrt/test_vrt.csv
Normal file
4
django/contrib/gis/tests/data/test_vrt/test_vrt.csv
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
POINT_X,POINT_Y,NUM
|
||||||
|
1.0,2.0,5
|
||||||
|
5.0,23.0,17
|
||||||
|
100.0,523.5,23
|
|
7
django/contrib/gis/tests/data/test_vrt/test_vrt.vrt
Normal file
7
django/contrib/gis/tests/data/test_vrt/test_vrt.vrt
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<OGRVRTDataSource>
|
||||||
|
<OGRVRTLayer name="test_vrt">
|
||||||
|
<SrcDataSource relativeToVRT="1">test_vrt.csv</SrcDataSource>
|
||||||
|
<GeometryType>wkbPoint</GeometryType>
|
||||||
|
<GeometryField encoding="PointFromColumns" x="POINT_X" y="POINT_Y" z="NUM"/>
|
||||||
|
</OGRVRTLayer>
|
||||||
|
</OGRVRTDataSource>
|
@ -3,27 +3,38 @@ from django.contrib.gis.gdal import DataSource, Envelope, OGRException, OGRIndex
|
|||||||
from django.contrib.gis.gdal.field import OFTReal, OFTInteger, OFTString
|
from django.contrib.gis.gdal.field import OFTReal, OFTInteger, OFTString
|
||||||
|
|
||||||
# Path for SHP files
|
# Path for SHP files
|
||||||
shp_path = os.path.dirname(__file__)
|
data_path = os.path.join(os.path.dirname(__file__), 'data')
|
||||||
def get_shp(name):
|
def get_ds_file(name, ext):
|
||||||
return shp_path + os.sep + name + os.sep + name + '.shp'
|
return os.sep.join([data_path, name, name + '.%s' % ext])
|
||||||
|
|
||||||
# Test SHP data source object
|
# Test SHP data source object
|
||||||
class TestSHP:
|
class TestDS:
|
||||||
def __init__(self, shp, **kwargs):
|
def __init__(self, name, **kwargs):
|
||||||
self.ds = get_shp(shp)
|
ext = kwargs.pop('ext', 'shp')
|
||||||
|
self.ds = get_ds_file(name, ext)
|
||||||
for key, value in kwargs.items():
|
for key, value in kwargs.items():
|
||||||
setattr(self, key, value)
|
setattr(self, key, value)
|
||||||
|
|
||||||
# List of acceptable data sources.
|
# List of acceptable data sources.
|
||||||
ds_list = (TestSHP('test_point', nfeat=5, nfld=3, geom='POINT', gtype=1, fields={'dbl' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,},
|
ds_list = (TestDS('test_point', nfeat=5, nfld=3, geom='POINT', gtype=1, driver='ESRI Shapefile',
|
||||||
|
fields={'dbl' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,},
|
||||||
extent=(-1.35011,0.166623,-0.524093,0.824508), # Got extent from QGIS
|
extent=(-1.35011,0.166623,-0.524093,0.824508), # Got extent from QGIS
|
||||||
srs_wkt='GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]'),
|
srs_wkt='GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]',
|
||||||
TestSHP('test_poly', nfeat=3, nfld=3, geom='POLYGON', gtype=3, fields={'float' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,},
|
field_values={'dbl' : [float(i) for i in range(1, 6)], 'int' : range(1, 6), 'str' : [str(i) for i in range(1, 6)]},
|
||||||
|
fids=range(5)),
|
||||||
|
TestDS('test_vrt', ext='vrt', nfeat=3, nfld=3, geom='POINT', gtype=1, driver='VRT',
|
||||||
|
fields={'POINT_X' : OFTString, 'POINT_Y' : OFTString, 'NUM' : OFTString}, # VRT uses CSV, which all types are OFTString.
|
||||||
|
extent=(1.0, 2.0, 100.0, 523.5), # Min/Max from CSV
|
||||||
|
field_values={'POINT_X' : ['1.0', '5.0', '100.0'], 'POINT_Y' : ['2.0', '23.0', '523.5'], 'NUM' : ['5', '17', '23']},
|
||||||
|
fids=range(1,4)),
|
||||||
|
TestDS('test_poly', nfeat=3, nfld=3, geom='POLYGON', gtype=3,
|
||||||
|
driver='ESRI Shapefile',
|
||||||
|
fields={'float' : OFTReal, 'int' : OFTInteger, 'str' : OFTString,},
|
||||||
extent=(-1.01513,-0.558245,0.161876,0.839637), # Got extent from QGIS
|
extent=(-1.01513,-0.558245,0.161876,0.839637), # Got extent from QGIS
|
||||||
srs_wkt='GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]'),
|
srs_wkt='GEOGCS["GCS_WGS_1984",DATUM["WGS_1984",SPHEROID["WGS_1984",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]'),
|
||||||
)
|
)
|
||||||
|
|
||||||
bad_ds = (TestSHP('foo'),
|
bad_ds = (TestDS('foo'),
|
||||||
)
|
)
|
||||||
|
|
||||||
class DataSourceTest(unittest.TestCase):
|
class DataSourceTest(unittest.TestCase):
|
||||||
@ -42,7 +53,7 @@ class DataSourceTest(unittest.TestCase):
|
|||||||
self.assertEqual(source.ds, ds.name)
|
self.assertEqual(source.ds, ds.name)
|
||||||
|
|
||||||
# Making sure the driver name matches up
|
# Making sure the driver name matches up
|
||||||
self.assertEqual('ESRI Shapefile', str(ds.driver))
|
self.assertEqual(source.driver, str(ds.driver))
|
||||||
|
|
||||||
# Making sure indexing works
|
# Making sure indexing works
|
||||||
try:
|
try:
|
||||||
@ -57,20 +68,17 @@ class DataSourceTest(unittest.TestCase):
|
|||||||
for source in bad_ds:
|
for source in bad_ds:
|
||||||
self.assertRaises(OGRException, DataSource, source.ds)
|
self.assertRaises(OGRException, DataSource, source.ds)
|
||||||
|
|
||||||
def test03_layers(self):
|
def test03a_layers(self):
|
||||||
"Testing Data Source Layers."
|
"Testing Data Source Layers."
|
||||||
|
print "\nBEGIN - expecting out of range feature id error; safe to ignore.\n"
|
||||||
for source in ds_list:
|
for source in ds_list:
|
||||||
ds = DataSource(source.ds)
|
ds = DataSource(source.ds)
|
||||||
|
|
||||||
# Incrementing through each layer, this tests __iter__
|
# Incrementing through each layer, this tests DataSource.__iter__
|
||||||
for layer in ds:
|
for layer in ds:
|
||||||
# Making sure we get the number of features we expect
|
# Making sure we get the number of features we expect
|
||||||
self.assertEqual(len(layer), source.nfeat)
|
self.assertEqual(len(layer), source.nfeat)
|
||||||
|
|
||||||
layer[0] #can index
|
|
||||||
layer[:1] #can slice
|
|
||||||
|
|
||||||
# Making sure we get the number of fields we expect
|
# Making sure we get the number of fields we expect
|
||||||
self.assertEqual(source.nfld, layer.num_fields)
|
self.assertEqual(source.nfld, layer.num_fields)
|
||||||
self.assertEqual(source.nfld, len(layer.fields))
|
self.assertEqual(source.nfld, len(layer.fields))
|
||||||
@ -86,6 +94,42 @@ class DataSourceTest(unittest.TestCase):
|
|||||||
flds = layer.fields
|
flds = layer.fields
|
||||||
for f in flds: self.assertEqual(True, f in source.fields)
|
for f in flds: self.assertEqual(True, f in source.fields)
|
||||||
|
|
||||||
|
# Negative FIDs are not allowed.
|
||||||
|
self.assertRaises(OGRIndexError, layer.__getitem__, -1)
|
||||||
|
self.assertRaises(OGRIndexError, layer.__getitem__, 50000)
|
||||||
|
|
||||||
|
if hasattr(source, 'field_values'):
|
||||||
|
fld_names = source.field_values.keys()
|
||||||
|
|
||||||
|
# Testing `Layer.get_fields` (which uses Layer.__iter__)
|
||||||
|
for fld_name in fld_names:
|
||||||
|
self.assertEqual(source.field_values[fld_name], layer.get_fields(fld_name))
|
||||||
|
|
||||||
|
# Testing `Layer.__getitem__`.
|
||||||
|
for i, fid in enumerate(source.fids):
|
||||||
|
feat = layer[fid]
|
||||||
|
self.assertEqual(fid, feat.fid)
|
||||||
|
# Maybe this should be in the test below, but we might as well test
|
||||||
|
# the feature values here while in this loop.
|
||||||
|
for fld_name in fld_names:
|
||||||
|
self.assertEqual(source.field_values[fld_name][i], feat.get(fld_name))
|
||||||
|
print "\nEND - expecting out of range feature id error; safe to ignore."
|
||||||
|
|
||||||
|
def test03b_layer_slice(self):
|
||||||
|
"Test indexing and slicing on Layers."
|
||||||
|
# Using the first data-source because the same slice
|
||||||
|
# can be used for both the layer and the control values.
|
||||||
|
source = ds_list[0]
|
||||||
|
ds = DataSource(source.ds)
|
||||||
|
|
||||||
|
sl = slice(1, 3)
|
||||||
|
feats = ds[0][sl]
|
||||||
|
|
||||||
|
for fld_name in ds[0].fields:
|
||||||
|
test_vals = [feat.get(fld_name) for feat in feats]
|
||||||
|
control_vals = source.field_values[fld_name][sl]
|
||||||
|
self.assertEqual(control_vals, test_vals)
|
||||||
|
|
||||||
def test04_features(self):
|
def test04_features(self):
|
||||||
"Testing Data Source Features."
|
"Testing Data Source Features."
|
||||||
for source in ds_list:
|
for source in ds_list:
|
||||||
@ -95,7 +139,8 @@ class DataSourceTest(unittest.TestCase):
|
|||||||
for layer in ds:
|
for layer in ds:
|
||||||
# Incrementing through each feature in the layer
|
# Incrementing through each feature in the layer
|
||||||
for feat in layer:
|
for feat in layer:
|
||||||
# Making sure the number of fields is what's expected.
|
# Making sure the number of fields, and the geometry type
|
||||||
|
# are what's expected.
|
||||||
self.assertEqual(source.nfld, len(list(feat)))
|
self.assertEqual(source.nfld, len(list(feat)))
|
||||||
self.assertEqual(source.gtype, feat.geom_type)
|
self.assertEqual(source.gtype, feat.geom_type)
|
||||||
|
|
||||||
@ -105,7 +150,7 @@ class DataSourceTest(unittest.TestCase):
|
|||||||
# a string value index for the feature.
|
# a string value index for the feature.
|
||||||
self.assertEqual(True, isinstance(feat[k], v))
|
self.assertEqual(True, isinstance(feat[k], v))
|
||||||
|
|
||||||
# Testing __iter__ on the Feature
|
# Testing Feature.__iter__
|
||||||
for fld in feat: self.assertEqual(True, fld.name in source.fields.keys())
|
for fld in feat: self.assertEqual(True, fld.name in source.fields.keys())
|
||||||
|
|
||||||
def test05_geometries(self):
|
def test05_geometries(self):
|
||||||
@ -123,8 +168,10 @@ class DataSourceTest(unittest.TestCase):
|
|||||||
self.assertEqual(source.gtype, g.geom_type)
|
self.assertEqual(source.gtype, g.geom_type)
|
||||||
|
|
||||||
# Making sure the SpatialReference is as expected.
|
# Making sure the SpatialReference is as expected.
|
||||||
|
if hasattr(source, 'srs_wkt'):
|
||||||
self.assertEqual(source.srs_wkt, g.srs.wkt)
|
self.assertEqual(source.srs_wkt, g.srs.wkt)
|
||||||
|
|
||||||
|
|
||||||
def suite():
|
def suite():
|
||||||
s = unittest.TestSuite()
|
s = unittest.TestSuite()
|
||||||
s.addTest(unittest.makeSuite(DataSourceTest))
|
s.addTest(unittest.makeSuite(DataSourceTest))
|
||||||
|
@ -36,6 +36,11 @@ class OGRGeomTest(unittest.TestCase):
|
|||||||
self.assertEqual(False, OGRGeomType(1) != OGRGeomType('point'))
|
self.assertEqual(False, OGRGeomType(1) != OGRGeomType('point'))
|
||||||
self.assertEqual(True, OGRGeomType('POINT') != OGRGeomType(6))
|
self.assertEqual(True, OGRGeomType('POINT') != OGRGeomType(6))
|
||||||
|
|
||||||
|
# Testing the Django field name equivalent property.
|
||||||
|
self.assertEqual('PointField', OGRGeomType('Point').django)
|
||||||
|
self.assertEqual(None, OGRGeomType('Unknown').django)
|
||||||
|
self.assertEqual(None, OGRGeomType('none').django)
|
||||||
|
|
||||||
def test01a_wkt(self):
|
def test01a_wkt(self):
|
||||||
"Testing WKT output."
|
"Testing WKT output."
|
||||||
for g in wkt_out:
|
for g in wkt_out:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user