From 0b6d214f481e5412da0edb6c940db86e520b04c3 Mon Sep 17 00:00:00 2001 From: Justin Bronn Date: Sun, 26 Oct 2008 22:24:21 +0000 Subject: [PATCH] Fixed #9448 -- `Layer` objects now carry a reference to their parent `DataSource`. Thanks, Matthew D. Hancher for the bug report. git-svn-id: http://code.djangoproject.com/svn/django/trunk@9284 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/gis/gdal/datasource.py | 2 +- django/contrib/gis/gdal/layer.py | 10 ++++++++-- django/contrib/gis/tests/test_gdal_ds.py | 17 +++++++++++++++++ 3 files changed, 26 insertions(+), 3 deletions(-) diff --git a/django/contrib/gis/gdal/datasource.py b/django/contrib/gis/gdal/datasource.py index 02363a075b..1eace25bef 100644 --- a/django/contrib/gis/gdal/datasource.py +++ b/django/contrib/gis/gdal/datasource.py @@ -111,7 +111,7 @@ class DataSource(object): l = get_layer(self._ptr, index) else: raise TypeError('Invalid index type: %s' % type(index)) - return Layer(l) + return Layer(l, self) def __len__(self): "Returns the number of layers within the data source." diff --git a/django/contrib/gis/gdal/layer.py b/django/contrib/gis/gdal/layer.py index d60e2cb7f6..45e823dedc 100644 --- a/django/contrib/gis/gdal/layer.py +++ b/django/contrib/gis/gdal/layer.py @@ -25,12 +25,18 @@ class Layer(object): "A class that wraps an OGR Layer, needs to be instantiated from a DataSource object." #### Python 'magic' routines #### - def __init__(self, layer_ptr): - "Needs a C pointer (Python/ctypes integer) in order to initialize." + def __init__(self, layer_ptr, ds): + """ + Initializes on an OGR C pointer to the Layer and the `DataSource` object + that owns this layer. The `DataSource` object is required so that a + reference to it is kept with this Layer. This prevents garbage + collection of the `DataSource` while this Layer is still active. + """ self._ptr = None # Initially NULL if not layer_ptr: raise OGRException('Cannot create Layer, invalid pointer given') self._ptr = layer_ptr + self._ds = ds self._ldefn = get_layer_defn(self._ptr) # Does the Layer support random reading? self._random_read = self.test_capability('RandomRead') diff --git a/django/contrib/gis/tests/test_gdal_ds.py b/django/contrib/gis/tests/test_gdal_ds.py index 9b826859f9..0be0984ff5 100644 --- a/django/contrib/gis/tests/test_gdal_ds.py +++ b/django/contrib/gis/tests/test_gdal_ds.py @@ -130,6 +130,23 @@ class DataSourceTest(unittest.TestCase): control_vals = source.field_values[fld_name][sl] self.assertEqual(control_vals, test_vals) + def test03c_layer_references(self): + "Test to make sure Layer access is still available without the DataSource." + source = ds_list[0] + + # See ticket #9448. + def get_layer(): + # This DataSource object is not accessible outside this + # scope. However, a reference should still be kept alive + # on the `Layer` returned. + ds = DataSource(source.ds) + return ds[0] + + # Making sure we can call OGR routines on the Layer returned. + lyr = get_layer() + self.assertEqual(source.nfeat, len(lyr)) + self.assertEqual(source.gtype, lyr.geom_type.num) + def test04_features(self): "Testing Data Source Features." for source in ds_list: