/django/contrib/gis/gdal/datasource.py
Python | 128 lines | 115 code | 0 blank | 13 comment | 0 complexity | c739981dc53340c46959989ca87aa484 MD5 | raw file
Possible License(s): BSD-3-Clause
- """
- DataSource is a wrapper for the OGR Data Source object, which provides
- an interface for reading vector geometry data from many different file
- formats (including ESRI shapefiles).
- When instantiating a DataSource object, use the filename of a
- GDAL-supported data source. For example, a SHP file or a
- TIGER/Line file from the government.
- The ds_driver keyword is used internally when a ctypes pointer
- is passed in directly.
- Example:
- ds = DataSource('/home/foo/bar.shp')
- for layer in ds:
- for feature in layer:
- # Getting the geometry for the feature.
- g = feature.geom
- # Getting the 'description' field for the feature.
- desc = feature['description']
- # We can also increment through all of the fields
- # attached to this feature.
- for field in feature:
- # Get the name of the field (e.g. 'description')
- nm = field.name
- # Get the type (integer) of the field, e.g. 0 => OFTInteger
- t = field.type
- # Returns the value the field; OFTIntegers return ints,
- # OFTReal returns floats, all else returns string.
- val = field.value
- """
- # ctypes prerequisites.
- from ctypes import byref, c_void_p
- # The GDAL C library, OGR exceptions, and the Layer object.
- from django.contrib.gis.gdal.base import GDALBase
- from django.contrib.gis.gdal.driver import Driver
- from django.contrib.gis.gdal.error import OGRException, OGRIndexError
- from django.contrib.gis.gdal.layer import Layer
- # Getting the ctypes prototypes for the DataSource.
- from django.contrib.gis.gdal.prototypes import ds as capi
- # For more information, see the OGR C API source code:
- # http://www.gdal.org/ogr/ogr__api_8h.html
- #
- # The OGR_DS_* routines are relevant here.
- class DataSource(GDALBase):
- "Wraps an OGR Data Source object."
- #### Python 'magic' routines ####
- def __init__(self, ds_input, ds_driver=False, write=False):
- # The write flag.
- if write:
- self._write = 1
- else:
- self._write = 0
- # Registering all the drivers, this needs to be done
- # _before_ we try to open up a data source.
- if not capi.get_driver_count():
- capi.register_all()
- if isinstance(ds_input, basestring):
- # The data source driver is a void pointer.
- ds_driver = Driver.ptr_type()
- try:
- # OGROpen will auto-detect the data source type.
- ds = capi.open_ds(ds_input, self._write, byref(ds_driver))
- except OGRException:
- # Making the error message more clear rather than something
- # like "Invalid pointer returned from OGROpen".
- raise OGRException('Could not open the datasource at "%s"' % ds_input)
- elif isinstance(ds_input, self.ptr_type) and isinstance(ds_driver, Driver.ptr_type):
- ds = ds_input
- else:
- raise OGRException('Invalid data source input type: %s' % type(ds_input))
- if bool(ds):
- self.ptr = ds
- self.driver = Driver(ds_driver)
- else:
- # Raise an exception if the returned pointer is NULL
- raise OGRException('Invalid data source file "%s"' % ds_input)
- def __del__(self):
- "Destroys this DataStructure object."
- if self._ptr: capi.destroy_ds(self._ptr)
- def __iter__(self):
- "Allows for iteration over the layers in a data source."
- for i in xrange(self.layer_count):
- yield self[i]
- def __getitem__(self, index):
- "Allows use of the index [] operator to get a layer at the index."
- if isinstance(index, basestring):
- l = capi.get_layer_by_name(self.ptr, index)
- if not l: raise OGRIndexError('invalid OGR Layer name given: "%s"' % index)
- elif isinstance(index, int):
- if index < 0 or index >= self.layer_count:
- raise OGRIndexError('index out of range')
- l = capi.get_layer(self._ptr, index)
- else:
- raise TypeError('Invalid index type: %s' % type(index))
- return Layer(l, self)
-
- def __len__(self):
- "Returns the number of layers within the data source."
- return self.layer_count
- def __str__(self):
- "Returns OGR GetName and Driver for the Data Source."
- return '%s (%s)' % (self.name, str(self.driver))
- @property
- def layer_count(self):
- "Returns the number of layers in the data source."
- return capi.get_layer_count(self._ptr)
- @property
- def name(self):
- "Returns the name of the data source."
- return capi.get_ds_name(self._ptr)