Add Django-1.2.1
[frozenviper.git] / Django-1.2.1 / django / contrib / gis / gdal / datasource.py
blob7db5fd9ce3e730ddbf7d62835f648c156bf3721b
1 """
2 DataSource is a wrapper for the OGR Data Source object, which provides
3 an interface for reading vector geometry data from many different file
4 formats (including ESRI shapefiles).
6 When instantiating a DataSource object, use the filename of a
7 GDAL-supported data source. For example, a SHP file or a
8 TIGER/Line file from the government.
10 The ds_driver keyword is used internally when a ctypes pointer
11 is passed in directly.
13 Example:
14 ds = DataSource('/home/foo/bar.shp')
15 for layer in ds:
16 for feature in layer:
17 # Getting the geometry for the feature.
18 g = feature.geom
20 # Getting the 'description' field for the feature.
21 desc = feature['description']
23 # We can also increment through all of the fields
24 # attached to this feature.
25 for field in feature:
26 # Get the name of the field (e.g. 'description')
27 nm = field.name
29 # Get the type (integer) of the field, e.g. 0 => OFTInteger
30 t = field.type
32 # Returns the value the field; OFTIntegers return ints,
33 # OFTReal returns floats, all else returns string.
34 val = field.value
35 """
36 # ctypes prerequisites.
37 from ctypes import byref, c_void_p
39 # The GDAL C library, OGR exceptions, and the Layer object.
40 from django.contrib.gis.gdal.base import GDALBase
41 from django.contrib.gis.gdal.driver import Driver
42 from django.contrib.gis.gdal.error import OGRException, OGRIndexError
43 from django.contrib.gis.gdal.layer import Layer
45 # Getting the ctypes prototypes for the DataSource.
46 from django.contrib.gis.gdal.prototypes import ds as capi
48 # For more information, see the OGR C API source code:
49 # http://www.gdal.org/ogr/ogr__api_8h.html
51 # The OGR_DS_* routines are relevant here.
52 class DataSource(GDALBase):
53 "Wraps an OGR Data Source object."
55 #### Python 'magic' routines ####
56 def __init__(self, ds_input, ds_driver=False, write=False):
57 # The write flag.
58 if write:
59 self._write = 1
60 else:
61 self._write = 0
63 # Registering all the drivers, this needs to be done
64 # _before_ we try to open up a data source.
65 if not capi.get_driver_count():
66 capi.register_all()
68 if isinstance(ds_input, basestring):
69 # The data source driver is a void pointer.
70 ds_driver = Driver.ptr_type()
71 try:
72 # OGROpen will auto-detect the data source type.
73 ds = capi.open_ds(ds_input, self._write, byref(ds_driver))
74 except OGRException:
75 # Making the error message more clear rather than something
76 # like "Invalid pointer returned from OGROpen".
77 raise OGRException('Could not open the datasource at "%s"' % ds_input)
78 elif isinstance(ds_input, self.ptr_type) and isinstance(ds_driver, Driver.ptr_type):
79 ds = ds_input
80 else:
81 raise OGRException('Invalid data source input type: %s' % type(ds_input))
83 if bool(ds):
84 self.ptr = ds
85 self.driver = Driver(ds_driver)
86 else:
87 # Raise an exception if the returned pointer is NULL
88 raise OGRException('Invalid data source file "%s"' % ds_input)
90 def __del__(self):
91 "Destroys this DataStructure object."
92 if self._ptr: capi.destroy_ds(self._ptr)
94 def __iter__(self):
95 "Allows for iteration over the layers in a data source."
96 for i in xrange(self.layer_count):
97 yield self[i]
99 def __getitem__(self, index):
100 "Allows use of the index [] operator to get a layer at the index."
101 if isinstance(index, basestring):
102 l = capi.get_layer_by_name(self.ptr, index)
103 if not l: raise OGRIndexError('invalid OGR Layer name given: "%s"' % index)
104 elif isinstance(index, int):
105 if index < 0 or index >= self.layer_count:
106 raise OGRIndexError('index out of range')
107 l = capi.get_layer(self._ptr, index)
108 else:
109 raise TypeError('Invalid index type: %s' % type(index))
110 return Layer(l, self)
112 def __len__(self):
113 "Returns the number of layers within the data source."
114 return self.layer_count
116 def __str__(self):
117 "Returns OGR GetName and Driver for the Data Source."
118 return '%s (%s)' % (self.name, str(self.driver))
120 @property
121 def layer_count(self):
122 "Returns the number of layers in the data source."
123 return capi.get_layer_count(self._ptr)
125 @property
126 def name(self):
127 "Returns the name of the data source."
128 return capi.get_ds_name(self._ptr)