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 gdalsupported data source for example a shp file or a tigerline file from the government the dsdriver keyword is used internally when a ctypes pointer is passed in directly example ds datasource homefoobar 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 for more information see the ogr c api documentation https gdal orgapivectorcapi html the ogrds routines are relevant here the write flag see also https gdal orgdevelopmentrfcrfc23ogrunicode html the data source driver is a void pointer ogropen will autodetect the data source type making the error message more clear rather than something like invalid pointer returned from ogropen raise an exception if the returned pointer is null for more information see the ogr c api documentation https gdal org api vector_c_api html the ogr_ds_ routines are relevant here the write flag see also https gdal org development rfc rfc23_ogr_unicode html the data source driver is a void pointer ogropen will auto detect the data source type making the error message more clear rather than something like invalid pointer returned from ogropen raise an exception if the returned pointer is null
from ctypes import byref
from pathlib import Path

from django.contrib.gis.gdal.base import GDALBase
from django.contrib.gis.gdal.driver import Driver
from django.contrib.gis.gdal.error import GDALException
from django.contrib.gis.gdal.layer import Layer
from django.contrib.gis.gdal.prototypes import ds as capi
from django.utils.encoding import force_bytes, force_str






class DataSource(GDALBase):
    "Wraps an OGR Data Source object."
    destructor = capi.destroy_ds

    def __init__(self, ds_input, ds_driver=False, write=False, encoding="utf-8"):
        
        if write:
            self._write = 1
        else:
            self._write = 0
        
        self.encoding = encoding

        Driver.ensure_registered()

        if isinstance(ds_input, (str, Path)):
            
            ds_driver = Driver.ptr_type()
            try:
                
                ds = capi.open_ds(force_bytes(ds_input), self._write, byref(ds_driver))
            except GDALException:
                
                
                raise GDALException('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 GDALException("Invalid data source input type: %s" % type(ds_input))

        if ds:
            self.ptr = ds
            self.driver = Driver(ds_driver)
        else:
            
            raise GDALException('Invalid data source file "%s"' % ds_input)

    def __getitem__(self, index):
        "Allows use of the index [] operator to get a layer at the index."
        if isinstance(index, str):
            try:
                layer = capi.get_layer_by_name(self.ptr, force_bytes(index))
            except GDALException:
                raise IndexError("Invalid OGR layer name given: %s." % index)
        elif isinstance(index, int):
            if 0 <= index < self.layer_count:
                layer = capi.get_layer(self._ptr, index)
            else:
                raise IndexError(
                    "Index out of range when accessing layers in a datasource: %s."
                    % index
                )
        else:
            raise TypeError("Invalid index type: %s" % type(index))
        return Layer(layer, self)

    def __len__(self):
        "Return the number of layers within the data source."
        return self.layer_count

    def __str__(self):
        "Return OGR GetName and Driver for the Data Source."
        return "%s (%s)" % (self.name, self.driver)

    @property
    def layer_count(self):
        "Return the number of layers in the data source."
        return capi.get_layer_count(self._ptr)

    @property
    def name(self):
        "Return the name of the data source."
        name = capi.get_ds_name(self._ptr)
        return force_str(name, self.encoding, strings_only=True)