Fixed #18640 -- Allowed access to GDAL Feature without Datasource

Thanks Justin Bronn for improving my initial patch.
This commit is contained in:
Claude Paroz 2012-10-07 16:20:29 +02:00
parent 35e8dc5169
commit cb9f71dd99
4 changed files with 36 additions and 20 deletions

View File

@ -16,15 +16,21 @@ from django.utils.six.moves import xrange
#
# The OGR_F_* routines are relevant here.
class Feature(GDALBase):
"A class that wraps an OGR Feature, needs to be instantiated from a Layer object."
"""
This class that wraps an OGR Feature, needs to be instantiated
from a Layer object.
"""
#### Python 'magic' routines ####
def __init__(self, feat, fdefn):
"Initializes on the pointers for the feature and the layer definition."
if not feat or not fdefn:
def __init__(self, feat, layer):
"""
Initializes on the feature pointers for the feature and the layer
definition, as well as the Layer.
"""
if not feat:
raise OGRException('Cannot create OGR Feature, invalid pointer given.')
self.ptr = feat
self._fdefn = fdefn
self._layer = layer
def __del__(self):
"Releases a reference to this object."
@ -43,7 +49,7 @@ class Feature(GDALBase):
if index < 0 or index > self.num_fields:
raise OGRIndexError('index out of range')
i = index
return Field(self.ptr, i)
return Field(self, i)
def __iter__(self):
"Iterates over each field in the Feature."
@ -71,7 +77,7 @@ class Feature(GDALBase):
@property
def layer_name(self):
"Returns the name of the layer for the feature."
return capi.get_feat_name(self._fdefn)
return capi.get_feat_name(self._layer._ldefn)
@property
def num_fields(self):
@ -81,7 +87,7 @@ class Feature(GDALBase):
@property
def fields(self):
"Returns a list of fields in the Feature."
return [capi.get_field_name(capi.get_field_defn(self._fdefn, i))
return [capi.get_field_name(capi.get_field_defn(self._layer._ldefn, i))
for i in xrange(self.num_fields)]
@property
@ -94,7 +100,7 @@ class Feature(GDALBase):
@property
def geom_type(self):
"Returns the OGR Geometry Type for this Feture."
return OGRGeomType(capi.get_fd_geom_type(self._fdefn))
return OGRGeomType(capi.get_fd_geom_type(self._layer._ldefn))
#### Feature Methods ####
def get(self, field):

View File

@ -9,12 +9,15 @@ from django.contrib.gis.gdal.prototypes import ds as capi
#
# The OGR_Fld_* routines are relevant here.
class Field(GDALBase):
"A class that wraps an OGR Field, needs to be instantiated from a Feature object."
"""
This class wraps an OGR Field, and needs to be instantiated
from a Feature object.
"""
#### Python 'magic' routines ####
def __init__(self, feat, index):
"""
Initializes on the feature pointer and the integer index of
Initializes on the feature object and the integer index of
the field within the feature.
"""
# Setting the feature pointer and index.
@ -22,7 +25,7 @@ class Field(GDALBase):
self._index = index
# Getting the pointer for this field.
fld_ptr = capi.get_feat_field_defn(feat, index)
fld_ptr = capi.get_feat_field_defn(feat.ptr, index)
if not fld_ptr:
raise OGRException('Cannot create OGR Field, invalid pointer given.')
self.ptr = fld_ptr
@ -42,21 +45,22 @@ class Field(GDALBase):
#### Field Methods ####
def as_double(self):
"Retrieves the Field's value as a double (float)."
return capi.get_field_as_double(self._feat, self._index)
return capi.get_field_as_double(self._feat.ptr, self._index)
def as_int(self):
"Retrieves the Field's value as an integer."
return capi.get_field_as_integer(self._feat, self._index)
return capi.get_field_as_integer(self._feat.ptr, self._index)
def as_string(self):
"Retrieves the Field's value as a string."
return capi.get_field_as_string(self._feat, self._index)
return capi.get_field_as_string(self._feat.ptr, self._index)
def as_datetime(self):
"Retrieves the Field's value as a tuple of date & time components."
yy, mm, dd, hh, mn, ss, tz = [c_int() for i in range(7)]
status = capi.get_field_as_datetime(self._feat, self._index, byref(yy), byref(mm), byref(dd),
byref(hh), byref(mn), byref(ss), byref(tz))
status = capi.get_field_as_datetime(
self._feat.ptr, self._index, byref(yy), byref(mm), byref(dd),
byref(hh), byref(mn), byref(ss), byref(tz))
if status:
return (yy, mm, dd, hh, mn, ss, tz)
else:

View File

@ -61,7 +61,7 @@ class Layer(GDALBase):
# ResetReading() must be called before iteration is to begin.
capi.reset_reading(self._ptr)
for i in xrange(self.num_feat):
yield Feature(capi.get_next_feature(self._ptr), self._ldefn)
yield Feature(capi.get_next_feature(self._ptr), self)
def __len__(self):
"The length is the number of features."
@ -81,7 +81,7 @@ class Layer(GDALBase):
if self._random_read:
# If the Layer supports random reading, return.
try:
return Feature(capi.get_feature(self.ptr, feat_id), self._ldefn)
return Feature(capi.get_feature(self.ptr, feat_id), self)
except OGRException:
pass
else:

View File

@ -125,7 +125,10 @@ class DataSourceTest(unittest.TestCase):
self.assertEqual(control_vals, test_vals)
def test03c_layer_references(self):
"Test to make sure Layer access is still available without the DataSource."
"""
Test to make sure Layer/Feature access is still available without
the DataSource/Feature.
"""
source = ds_list[0]
# See ticket #9448.
@ -141,6 +144,9 @@ class DataSourceTest(unittest.TestCase):
self.assertEqual(source.nfeat, len(lyr))
self.assertEqual(source.gtype, lyr.geom_type.num)
# Same issue for Feature/Field objects, see #18640
self.assertEqual(str(lyr[0]['str']), "1")
def test04_features(self):
"Testing Data Source Features."
for source in ds_list: