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:
parent
35e8dc5169
commit
cb9f71dd99
@ -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):
|
||||||
|
@ -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:
|
||||||
|
@ -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:
|
||||||
|
@ -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:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user