From a925a3afe29922c0817fb9e4ae9bef7dc24b1cac Mon Sep 17 00:00:00 2001 From: Jeremy Dunck Date: Wed, 4 Jul 2007 06:55:32 +0000 Subject: [PATCH] gis: Added utils.inspect_data.sample, which allows a shows a convenient bit of the supplied data_source Added support for feature slicing and negative indices. Handled missing Feature field values. git-svn-id: http://code.djangoproject.com/svn/django/branches/gis@5605 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/gis/gdal/Field.py | 14 ++++++++++-- django/contrib/gis/gdal/Layer.py | 28 ++++++++++++++---------- django/contrib/gis/tests/test_gdal_ds.py | 7 ++++-- django/contrib/gis/utils/inspect_data.py | 27 +++++++++++++++++++++++ 4 files changed, 61 insertions(+), 15 deletions(-) create mode 100644 django/contrib/gis/utils/inspect_data.py diff --git a/django/contrib/gis/gdal/Field.py b/django/contrib/gis/gdal/Field.py index 340c9bfa1b..858d7512ff 100644 --- a/django/contrib/gis/gdal/Field.py +++ b/django/contrib/gis/gdal/Field.py @@ -48,14 +48,24 @@ class OFTInteger(Field): @property def value(self): "Returns an integer contained in this field." - return int(self._val) + try: + return int(self._val) + except ValueError: + return 0 class OFTIntegerList(Field): pass class OFTReal(Field): @property def value(self): "Returns a float contained in this field." - return float(self._val) + + try: + return float(self._val) + except ValueError: + #FIXME: 0? None? + return 0 + + class OFTRealList(Field): pass class OFTString(Field): pass diff --git a/django/contrib/gis/gdal/Layer.py b/django/contrib/gis/gdal/Layer.py index 2f6b07905d..7194d6fbf7 100644 --- a/django/contrib/gis/gdal/Layer.py +++ b/django/contrib/gis/gdal/Layer.py @@ -35,20 +35,26 @@ class Layer(object): def __getitem__(self, index): "Gets the Feature at the specified index." - if index < 0 or index >= self.num_feat: - raise IndexError, 'index out of range' - return Feature(lgdal.OGR_L_GetFeature(self._layer, c_long(index))) + def make_feature(offset): + return Feature(lgdal.OGR_L_GetFeature(self._layer, + c_long(offset))) + end = self.num_feat + if not isinstance(index, (slice, int)): + raise TypeError + if isinstance(index,int): + if index < 0: + index = end - index + if index < 0 or index >= self.num_feat: + raise IndexError, 'index out of range' + yield make_feature(index) + else: #isinstance(index,slice) + start, stop, stride = index.indices(end) + for offset in xrange(start,stop,stride): + yield make_feature(offset) def __iter__(self): "Iterates over each Feature in the Layer." - - # Resetting the Layer before beginning iteration - lgdal.OGR_L_ResetReading(self._layer) - - # Incrementing over each feature in the layer, and yielding - # to the caller of the function. - for i in xrange(self.num_feat): - yield self.__getitem__(i) + return self.__getitem__(slice(self.num_feat)) def __len__(self): "The length is the number of features." diff --git a/django/contrib/gis/tests/test_gdal_ds.py b/django/contrib/gis/tests/test_gdal_ds.py index 00a4e4b752..19dc74534a 100644 --- a/django/contrib/gis/tests/test_gdal_ds.py +++ b/django/contrib/gis/tests/test_gdal_ds.py @@ -65,10 +65,13 @@ class DataSourceTest(unittest.TestCase): ds = DataSource(source.ds) # Incrementing through each layer, this tests __iter__ - for layer in ds: + for layer in ds: # Making sure we get the number of features we expect self.assertEqual(len(layer), source.nfeat) + layer[0] #can index + layer[:1] #can slice + # Making sure we get the number of fields we expect self.assertEqual(source.nfld, layer.num_fields) self.assertEqual(source.nfld, len(layer.fields)) @@ -94,7 +97,7 @@ class DataSourceTest(unittest.TestCase): # Incrementing through each feature in the layer for feat in layer: # Making sure the number of fields is what's expected. - self.assertEqual(source.nfld, len(feat)) + self.assertEqual(source.nfld, len(list(feat))) self.assertEqual(source.gtype, feat.geom_type) # Making sure the fields match to an appropriate OFT type. diff --git a/django/contrib/gis/utils/inspect_data.py b/django/contrib/gis/utils/inspect_data.py new file mode 100644 index 0000000000..71b327bcf5 --- /dev/null +++ b/django/contrib/gis/utils/inspect_data.py @@ -0,0 +1,27 @@ +""" +This module includes some utility functions for inspecting the layout +of a gdal.DataSource. +""" + +from django.contrib.gis.gdal.OGRGeometry import GEO_CLASSES + +def sample(data_source, num_features=10, gcs_file=None): + """ + Walks the available layers in the supplied ``data_source``, displaying + the fields for the first ``num_features`` features. + """ + + for i, layer in enumerate(data_source): + print "data source : %s" % data_source.name + print "==== layer %s" % i + print " shape type: %s" % GEO_CLASSES[layer.geom_type.num].__name__ + print " # features: %s" % len(layer) + print " srs: %s" % layer.srs + print "Showing first %s features ========" % num_features + + width = max(*map(len,layer.fields)) + fmt = " %%%ss:%%s" % width + for i, feature in enumerate(layer[:num_features]): + print "======== Feature %s" % i + for field in layer.fields: + print fmt % (field, feature.get(field))