1
0
mirror of https://github.com/django/django.git synced 2025-06-03 10:39:12 +00:00

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. # The OGR_F_* routines are relevant here.
class Feature(GDALBase): 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 #### #### Python 'magic' routines ####
def __init__(self, feat, fdefn): def __init__(self, feat, layer):
"Initializes on the pointers for the feature and the layer definition." """
if not feat or not fdefn: 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.') raise OGRException('Cannot create OGR Feature, invalid pointer given.')
self.ptr = feat self.ptr = feat
self._fdefn = fdefn self._layer = layer
def __del__(self): def __del__(self):
"Releases a reference to this object." "Releases a reference to this object."
@ -43,7 +49,7 @@ class Feature(GDALBase):
if index < 0 or index > self.num_fields: if index < 0 or index > self.num_fields:
raise OGRIndexError('index out of range') raise OGRIndexError('index out of range')
i = index i = index
return Field(self.ptr, i) return Field(self, i)
def __iter__(self): def __iter__(self):
"Iterates over each field in the Feature." "Iterates over each field in the Feature."
@ -71,7 +77,7 @@ class Feature(GDALBase):
@property @property
def layer_name(self): def layer_name(self):
"Returns the name of the layer for the feature." "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 @property
def num_fields(self): def num_fields(self):
@ -81,7 +87,7 @@ class Feature(GDALBase):
@property @property
def fields(self): def fields(self):
"Returns a list of fields in the Feature." "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)] for i in xrange(self.num_fields)]
@property @property
@ -94,7 +100,7 @@ class Feature(GDALBase):
@property @property
def geom_type(self): def geom_type(self):
"Returns the OGR Geometry Type for this Feture." "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 #### #### Feature Methods ####
def get(self, field): 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. # The OGR_Fld_* routines are relevant here.
class Field(GDALBase): 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 #### #### Python 'magic' routines ####
def __init__(self, feat, index): 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. the field within the feature.
""" """
# Setting the feature pointer and index. # Setting the feature pointer and index.
@ -22,7 +25,7 @@ class Field(GDALBase):
self._index = index self._index = index
# Getting the pointer for this field. # 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: if not fld_ptr:
raise OGRException('Cannot create OGR Field, invalid pointer given.') raise OGRException('Cannot create OGR Field, invalid pointer given.')
self.ptr = fld_ptr self.ptr = fld_ptr
@ -42,21 +45,22 @@ class Field(GDALBase):
#### Field Methods #### #### Field Methods ####
def as_double(self): def as_double(self):
"Retrieves the Field's value as a double (float)." "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): def as_int(self):
"Retrieves the Field's value as an integer." "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): def as_string(self):
"Retrieves the Field's value as a string." "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): def as_datetime(self):
"Retrieves the Field's value as a tuple of date & time components." "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)] 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), status = capi.get_field_as_datetime(
byref(hh), byref(mn), byref(ss), byref(tz)) self._feat.ptr, self._index, byref(yy), byref(mm), byref(dd),
byref(hh), byref(mn), byref(ss), byref(tz))
if status: if status:
return (yy, mm, dd, hh, mn, ss, tz) return (yy, mm, dd, hh, mn, ss, tz)
else: else:

View File

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

View File

@ -125,7 +125,10 @@ class DataSourceTest(unittest.TestCase):
self.assertEqual(control_vals, test_vals) self.assertEqual(control_vals, test_vals)
def test03c_layer_references(self): 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] source = ds_list[0]
# See ticket #9448. # See ticket #9448.
@ -141,6 +144,9 @@ class DataSourceTest(unittest.TestCase):
self.assertEqual(source.nfeat, len(lyr)) self.assertEqual(source.nfeat, len(lyr))
self.assertEqual(source.gtype, lyr.geom_type.num) 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): def test04_features(self):
"Testing Data Source Features." "Testing Data Source Features."
for source in ds_list: for source in ds_list: