diff --git a/django/contrib/gis/gdal/feature.py b/django/contrib/gis/gdal/feature.py
index 2920048..db40357 100644
a
|
b
|
from django.utils.six.moves import xrange
|
15 | 15 | # |
16 | 16 | # The OGR_F_* routines are relevant here. |
17 | 17 | class Feature(GDALBase): |
18 | | "A class that wraps an OGR Feature, needs to be instantiated from a Layer object." |
| 18 | """ |
| 19 | This class that wraps an OGR Feature, needs to be instantiated |
| 20 | from a Layer object. |
| 21 | """ |
19 | 22 | |
20 | 23 | #### Python 'magic' routines #### |
21 | | def __init__(self, feat, fdefn): |
22 | | "Initializes on the pointers for the feature and the layer definition." |
23 | | if not feat or not fdefn: |
| 24 | def __init__(self, feat, layer): |
| 25 | """ |
| 26 | Initializes on the feature pointers for the feature and the layer |
| 27 | definition, as well as the Layer |
| 28 | """ |
| 29 | if not feat or not layer: |
24 | 30 | raise OGRException('Cannot create OGR Feature, invalid pointer given.') |
25 | 31 | self.ptr = feat |
26 | | self._fdefn = fdefn |
| 32 | self._layer = layer |
27 | 33 | |
28 | 34 | def __del__(self): |
29 | 35 | "Releases a reference to this object." |
… |
… |
class Feature(GDALBase):
|
42 | 48 | if index < 0 or index > self.num_fields: |
43 | 49 | raise OGRIndexError('index out of range') |
44 | 50 | i = index |
45 | | return Field(self.ptr, i) |
| 51 | return Field(self, i) |
46 | 52 | |
47 | 53 | def __iter__(self): |
48 | 54 | "Iterates over each field in the Feature." |
… |
… |
class Feature(GDALBase):
|
70 | 76 | @property |
71 | 77 | def layer_name(self): |
72 | 78 | "Returns the name of the layer for the feature." |
73 | | return capi.get_feat_name(self._fdefn) |
| 79 | return capi.get_feat_name(self._layer._ldefn) |
74 | 80 | |
75 | 81 | @property |
76 | 82 | def num_fields(self): |
… |
… |
class Feature(GDALBase):
|
80 | 86 | @property |
81 | 87 | def fields(self): |
82 | 88 | "Returns a list of fields in the Feature." |
83 | | return [capi.get_field_name(capi.get_field_defn(self._fdefn, i)) |
| 89 | return [capi.get_field_name(capi.get_field_defn(self._layer._ldefn, i)) |
84 | 90 | for i in xrange(self.num_fields)] |
85 | 91 | |
86 | 92 | @property |
… |
… |
class Feature(GDALBase):
|
93 | 99 | @property |
94 | 100 | def geom_type(self): |
95 | 101 | "Returns the OGR Geometry Type for this Feture." |
96 | | return OGRGeomType(capi.get_fd_geom_type(self._fdefn)) |
| 102 | return OGRGeomType(capi.get_fd_geom_type(self._layer._ldefn)) |
97 | 103 | |
98 | 104 | #### Feature Methods #### |
99 | 105 | def get(self, field): |
diff --git a/django/contrib/gis/gdal/field.py b/django/contrib/gis/gdal/field.py
index 12dc8b9..16230af 100644
a
|
b
|
from django.contrib.gis.gdal.prototypes import ds as capi
|
9 | 9 | # |
10 | 10 | # The OGR_Fld_* routines are relevant here. |
11 | 11 | class Field(GDALBase): |
12 | | "A class that wraps an OGR Field, needs to be instantiated from a Feature object." |
| 12 | """ |
| 13 | This class wraps an OGR Field, and needs to be instantiated |
| 14 | from a Feature object. |
| 15 | """ |
13 | 16 | |
14 | 17 | #### Python 'magic' routines #### |
15 | 18 | def __init__(self, feat, index): |
16 | 19 | """ |
17 | | Initializes on the feature pointer and the integer index of |
| 20 | Initializes on the feature object and the integer index of |
18 | 21 | the field within the feature. |
19 | 22 | """ |
20 | 23 | # Setting the feature pointer and index. |
… |
… |
class Field(GDALBase):
|
22 | 25 | self._index = index |
23 | 26 | |
24 | 27 | # Getting the pointer for this field. |
25 | | fld_ptr = capi.get_feat_field_defn(feat, index) |
| 28 | fld_ptr = capi.get_feat_field_defn(feat.ptr, index) |
26 | 29 | if not fld_ptr: |
27 | 30 | raise OGRException('Cannot create OGR Field, invalid pointer given.') |
28 | 31 | self.ptr = fld_ptr |
… |
… |
class Field(GDALBase):
|
42 | 45 | #### Field Methods #### |
43 | 46 | def as_double(self): |
44 | 47 | "Retrieves the Field's value as a double (float)." |
45 | | return capi.get_field_as_double(self._feat, self._index) |
| 48 | return capi.get_field_as_double(self._feat.ptr, self._index) |
46 | 49 | |
47 | 50 | def as_int(self): |
48 | 51 | "Retrieves the Field's value as an integer." |
49 | | return capi.get_field_as_integer(self._feat, self._index) |
| 52 | return capi.get_field_as_integer(self._feat.ptr, self._index) |
50 | 53 | |
51 | 54 | def as_string(self): |
52 | 55 | "Retrieves the Field's value as a string." |
53 | | return capi.get_field_as_string(self._feat, self._index) |
| 56 | return capi.get_field_as_string(self._feat.ptr, self._index) |
54 | 57 | |
55 | 58 | def as_datetime(self): |
56 | 59 | "Retrieves the Field's value as a tuple of date & time components." |
57 | 60 | yy, mm, dd, hh, mn, ss, tz = [c_int() for i in range(7)] |
58 | | status = capi.get_field_as_datetime(self._feat, self._index, byref(yy), byref(mm), byref(dd), |
59 | | byref(hh), byref(mn), byref(ss), byref(tz)) |
| 61 | status = capi.get_field_as_datetime( |
| 62 | self._feat.ptr, self._index, byref(yy), byref(mm), byref(dd), |
| 63 | byref(hh), byref(mn), byref(ss), byref(tz)) |
60 | 64 | if status: |
61 | 65 | return (yy, mm, dd, hh, mn, ss, tz) |
62 | 66 | else: |
diff --git a/django/contrib/gis/gdal/layer.py b/django/contrib/gis/gdal/layer.py
index 2357fbb..8c53831 100644
a
|
b
|
from django.utils.six.moves import xrange
|
22 | 22 | # |
23 | 23 | # The OGR_L_* routines are relevant here. |
24 | 24 | class Layer(GDALBase): |
25 | | "A class that wraps an OGR Layer, needs to be instantiated from a DataSource object." |
| 25 | """ |
| 26 | This class wraps an OGR Layer, and needs to be instantiated |
| 27 | from a DataSource object. |
| 28 | """ |
26 | 29 | |
27 | 30 | #### Python 'magic' routines #### |
28 | 31 | def __init__(self, layer_ptr, ds): |
… |
… |
class Layer(GDALBase):
|
60 | 63 | # ResetReading() must be called before iteration is to begin. |
61 | 64 | capi.reset_reading(self._ptr) |
62 | 65 | for i in xrange(self.num_feat): |
63 | | yield Feature(capi.get_next_feature(self._ptr), self._ldefn) |
| 66 | yield Feature(capi.get_next_feature(self._ptr), self) |
64 | 67 | |
65 | 68 | def __len__(self): |
66 | 69 | "The length is the number of features." |
… |
… |
class Layer(GDALBase):
|
80 | 83 | if self._random_read: |
81 | 84 | # If the Layer supports random reading, return. |
82 | 85 | try: |
83 | | return Feature(capi.get_feature(self.ptr, feat_id), self._ldefn) |
| 86 | return Feature(capi.get_feature(self.ptr, feat_id), self) |
84 | 87 | except OGRException: |
85 | 88 | pass |
86 | 89 | else: |
diff --git a/django/contrib/gis/gdal/tests/test_ds.py b/django/contrib/gis/gdal/tests/test_ds.py
index 71d22a0..4d7d075 100644
a
|
b
|
class DataSourceTest(unittest.TestCase):
|
126 | 126 | self.assertEqual(control_vals, test_vals) |
127 | 127 | |
128 | 128 | def test03c_layer_references(self): |
129 | | "Test to make sure Layer access is still available without the DataSource." |
| 129 | """ |
| 130 | Test to make sure Layer/Feature access is still available without |
| 131 | the DataSource/Feature. |
| 132 | """ |
130 | 133 | source = ds_list[0] |
131 | 134 | |
132 | 135 | # See ticket #9448. |
… |
… |
class DataSourceTest(unittest.TestCase):
|
142 | 145 | self.assertEqual(source.nfeat, len(lyr)) |
143 | 146 | self.assertEqual(source.gtype, lyr.geom_type.num) |
144 | 147 | |
| 148 | # Same issue for Feature/Field objects, see #18640 |
| 149 | self.assertEqual(str(lyr[0]['str']), "1") |
| 150 | |
145 | 151 | def test04_features(self): |
146 | 152 | "Testing Data Source Features." |
147 | 153 | for source in ds_list: |