1 """DAP variables.
2
3 This module is a Python implementation of the DAP data model.
4 """
5
6 __author__ = "Roberto De Almeida <rob@pydap.org>"
7
8 import copy
9 import itertools
10
11 from dap.lib import quote
12 from dap.util.ordereddict import odict
13 from dap.util.filter import get_filters
14
15 __all__ = ['StructureType', 'SequenceType', 'DatasetType', 'GridType', 'ArrayType', 'BaseType',
16 'Float', 'Float0', 'Float8', 'Float16', 'Float32', 'Float64', 'Int', 'Int0', 'Int8',
17 'Int16', 'Int32', 'Int64', 'UInt16', 'UInt32', 'UInt64', 'Byte', 'String', 'Url']
18
19 _basetypes = ['Float32', 'Float64', 'Int16', 'Int32', 'UInt16', 'UInt32', 'Byte', 'String', 'Url']
20 _constructors = ['StructureType', 'SequenceType', 'DatasetType', 'GridType', 'ArrayType']
21
22
23 Float = 'Float64'
24 Float0 = 'Float64'
25 Float8 = 'Float32'
26 Float16 = 'Float32'
27 Float32 = 'Float32'
28 Float64 = 'Float64'
29 Int = 'Int32'
30 Int0 = 'Int32'
31 Int8 = 'Byte'
32 Int16 = 'Int16'
33 Int32 = 'Int32'
34 Int64 = 'Int32'
35 UInt16 = 'UInt16'
36 UInt32 = 'UInt32'
37 UInt64 = 'UInt32'
38 UInt8 = 'Byte'
39 Byte = 'Byte'
40 String = 'String'
41 Url = 'Url'
42
43 typemap = {
44
45 'd': Float64,
46 'f': Float32,
47 'l': Int32,
48 'b': Byte,
49 'h': Int16,
50 'q': Int32,
51 'H': UInt16,
52 'L': UInt32,
53 'Q': UInt32,
54 'B': Byte,
55 'S': String,
56 }
57
58
60 """Structure contructor.
61
62 A structure is a dict-like object, which can hold other DAP variables.
63 Structures have a 'data' attribute that combines the data from the
64 stored variables when read, and propagates the data to the variables
65 when set.
66
67 This behaviour can be bypassed by setting the '_data' attribute; in
68 this case, no data is propagated, and further reads do not combine the
69 data from the stored variables.
70 """
71
72 - def __init__(self, name='', attributes=None):
73 odict.__init__(self)
74 self.name = quote(name)
75 self.attributes = attributes or {}
76
77 self._id = name
78 self._filters = []
79 self._data = None
80
84
85 walk = __iter__
86
88
89 try:
90 return self[attr]
91 except KeyError:
92
93 try: return self.attributes[attr]
94 except KeyError: raise AttributeError
95
97
98 self._dict.__setitem__(key, item)
99 if key not in self._keys: self._keys.append(key)
100
101
102 item._set_id(self._id)
103
105 if self._data is not None:
106 return self._data
107 else:
108 return [var.data for var in self.values()]
109
111
112 for data_, var in itertools.izip(data, self.values()):
113 var.data = data_
114
115 data = property(_get_data, _set_data)
116
118 return self._id
119
121 if parent:
122 self._id = '%s.%s' % (parent, self.name)
123 else:
124 self._id = self.name
125
126
127 for var in self.values(): var._set_id(self._id)
128
129 id = property(_get_id)
130
132 return self._filters
133
139
140 filters = property(_get_filters, _set_filters)
141
143 out = self.__class__(name=self.name, attributes=self.attributes.copy())
144 out._id = self._id
145 out._filters = self._filters[:]
146 out._data = self._data
147
148
149 for k, v in self.items():
150 out[k] = v
151 return out
152
154 out = self.__class__(name=self.name, attributes=self.attributes.copy())
155 out._id = self._id
156 out._filters = self._filters[:]
157
158 out._data = self._data
159
160
161 for k, v in self.items():
162 out[k] = copy.deepcopy(v)
163 return out
164
165
167 """Dataset constructor.
168
169 A dataset is very similar to a structure -- the main difference is that
170 its name is not used when composing the fully qualified name of stored
171 variables.
172 """
173
175 self._dict.__setitem__(key, item)
176 if key not in self._keys: self._keys.append(key)
177
178
179
180 item._set_id(None)
181
183 self._id = self.name
184
185
186 for var in self.values(): var._set_id(None)
187
188
190 """Sequence constructor.
191
192 A sequence contains ordered data, corresponding to the records in
193 a sequence of structures with the same stored variables.
194 """
195
196 level = 1
197
199
200 self._dict.__setitem__(key, item)
201 if key not in self._keys: self._keys.append(key)
202
203
204 item._set_id(self._id)
205
206
207 def set_level(seq, level):
208 if isinstance(seq, SequenceType):
209 seq.level = level
210 for child in seq.walk(): set_level(child, level+1)
211 set_level(item, self.level+1)
212
216
218
219
220
221 if self._data is not None:
222 return self._data
223 else:
224 return _build_data(self.level, *[var.data for var in self.values()])
225
229
230 data = property(_get_data, _set_data)
231
258
267
268
270 """Grid constructor.
271
272 A grid is a constructor holding an 'array' variable. The array has its
273 dimensions mapped to 'maps' stored in the grid (lat, lon, time, etc.).
274 Most of the requests are simply passed onto the stored array.
275 """
276
277 - def __init__(self, name='', array=None, maps=None, attributes=None):
278 self.name = quote(name)
279 self.array = array
280 self.maps = maps or odict()
281 self.attributes = attributes or {}
282
283 self._id = name
284 self._filters = []
285
287 return self.array.shape[0]
288
290
291 yield self.array
292 for map_ in self.maps.values(): yield map_
293
294 walk = __iter__
295
297
298 try:
299 return self.attributes[attr]
300 except KeyError:
301 raise AttributeError
302
304
305 return self.array.