1 '''
2
3 '''
4
5 from itertools import imap,count,chain
6
7 from itertools import imap,count,chain
8
10 """
11 Tables are list of rows of the same model
12 """
13 - def __init__(self, headers=None,
14 types=None,
15 colcount=None,
16 rowFactory=None,
17 subrowFactory=None):
18 '''
19
20 @param headers: the list of column header.
21
22 if this parametter is C{None}, C{colcount}
23 parametter must be set.
24
25 @type headers: C{list}, C{tuple} or and iterable object
26
27 @param types: the list of data type associated to each column.
28
29 If this parametter is specified its length must be
30 equal to the C{headers} length or to C{colcount}.
31
32 @type types: C{list}, C{tuple} or and iterable object
33
34 @param colcount: number of column in the created table.
35
36 If C{headers} parametter is not C{None} this
37 parametter is ignored
38
39 @type colcount: int
40 '''
41
42 assert headers is not None or colcount is not None,\
43 'headers or colcount parametter must be not None value'
44
45 if headers is None:
46 headers = tuple('Col_%d' % x for x in xrange(colcount))
47
48 self.headers = headers
49 self.types = types
50 self.colcount= len(self.headers)
51
52 if rowFactory is None:
53 self.rowFactory=TableRow
54 else:
55 self.rowFactory=rowFactory
56
57 if subrowFactory is None:
58 self.subrowFactory=TableRow
59 else:
60 self.subrowFactory=rowFactory
61
62
63 self.likedTo=set()
64
65
66
74
76 '''
77
78 @param key:
79 @type key: C{int}, C{slice} or C{str}
80 @param value:
81 @type value:
82 '''
83
84 if isintance(key,int):
85 if not isinstance(value, TableRow):
86 value = self.rowFactory(self,value)
87 else:
88 assert self.isCompatible(value)
89 list.__setitem__(self,key,value.row)
90
91 elif isinstance(key,slice):
92 indices = xrange(key.indices(len(self)))
93 for i,d in imap(None,indices,value):
94 self[i]=d
95
96 else:
97 raise TypeError, "Key must be an int or slice value"
98
100 '''
101 this function has different comportements depending
102 of the data type of C{key} and the table used.
103
104 @param key: description of the table part to return
105 @type key: C{int} or C{slice}
106
107 @return: return a TableRow (if key is C{int})
108 or a subpart of the table (if key is C{slice}).
109 '''
110 if isinstance(key,int):
111 return self.rowFactory(self,
112 list.__getitem__(self,key))
113
114 if isinstance(key,slice):
115 newtable=Table(self.headers,self.types)
116 indices = xrange(key.indices(len(self)))
117 for i in indices:
118 list.append(newtable,list.__getitem__(self,i))
119 self.likedTo.add(newtable)
120 return newtable
121
122 raise TypeError
123
124
127
130
133
136
138 if types is not None and not isinstance(type,tuple):
139 types = tuple(x for x in types)
140
141 assert types is None or len(types)==len(self._headers)
142
143 self._types = types
144
145 if types is not None:
146 for row in self:
147 row.castRow()
148
151
152 types = property(_getTypes,_setTypes)
153
156
164
165 headers=property(_getHeaders,_setHeaders)
166
173
174
175
178 if data is None:
179 list.__init__(self,(None for x in xrange(size)))
180 else:
181 list.__init__(self,data)
182 assert len(self)==size, \
183 "Size of data is not correct (%d instead of %d)" % (len(self),size)
184
186 raise NotImplementedError, \
187 "Rows cannot change of size"
188
189 - def pop(self,key=None):
190 raise NotImplementedError, \
191 "Rows cannot change of size"
192
194 raise NotImplementedError, \
195 "Rows cannot change of size"
196
197
198
199
201 '''
202
203 '''
204 - def __init__(self, table,
205 data=None,
206 ):
215
218
221
224
227
228 types = property(getType,None,None,
229 "List of types associated to this row")
230 headers= property(getHeaders,None,None,
231 "List of headers associated to this row")
232
233 _hindex= property(getHIndex,None,None)
234 _colcount = property(getColCount,None,None)
235
237 '''
238 Cast a value to a specified type, with exception of
239 C{None} values that are returned without cast.
240
241 @param t: the destination type
242 @type t: C{type}
243 @param x: the value to cast
244
245 @return: the casted value or C{None}
246
247 '''
248 if x is None or t is None:
249 return x
250 else:
251 return t(x)
252
253 _castValue=staticmethod(_castValue)
254
256
257 if not isinstance(data, (list,dict)):
258 data=[x for x in data]
259
260 if isinstance(data,list):
261 assert len(data)==self._colcount, \
262 'values has not good length'
263 if self.types is not None:
264 data=[TableRow._castValue(t, x)
265 for t,x in imap(None,self.types,data)]
266
267 elif isinstance(data,dict):
268 lvalue = [None] * len(self.header)
269
270 for k,v in data.items():
271 try:
272 hindex = self._hindex[k]
273 if self.types is not None:
274 lvalue[hindex]=TableRow._castValue(self.types[hindex], v)
275 else:
276 lvalue[hindex]=v
277 except KeyError:
278 info('%s is not a table column' % k)
279
280 data=lvalue
281 else:
282 raise TypeError
283
284 return data
285
287 '''
288
289 @param key:
290 @type key:
291 '''
292
293 if isinstance(key,(int,slice)):
294 return self.row[key]
295
296 if isinstance(key,str):
297 i = self._hindex[key]
298 return self.row[i]
299
300 raise TypeError, "Key must be an int, slice or str value"
301
303 '''
304
305 @param key:
306 @type key:
307 @param value:
308 @type value:
309 '''
310
311 if isinstance(key,str):
312 key = self._hindex[key]
313
314 elif isinstance(key,int):
315 if self.types is not None:
316 value = TableRow._castValue(self.types[key], value)
317 self.row[key]=value
318
319 elif isinstance(key,slice):
320 indices = xrange(key.indices(len(self.row)))
321 for i,v in imap(None,indices,value):
322 self[i]=v
323 else:
324 raise TypeError, "Key must be an int, slice or str value"
325
326
327
329 '''
330
331 '''
332 return iter(self.row)
333
335 raise NotImplementedError, \
336 "Rows cannot change of size"
337
338 - def pop(self,key=None):
339 raise NotImplementedError, \
340 "Rows cannot change of size"
341
343 raise NotImplementedError, \
344 "Rows cannot change of size"
345
348
350 return repr(self.row)
351
354
357
358
360
363
366
369
372
375
378
379 headers = property(_getHeaders,None,None)
380 types = property(_getTypes,None,None)
381 rowFactory = property(_getRowFactory,None,None)
382 subrowFactory = property(_getSubrowFactory,None,None)
383 colcount = property(_getColcount,None,None)
384
386 if isinstance(name,str):
387 return self._reference.headers.index(name)
388 elif isinstance(name,int):
389 lh = len(self._reference.headers)
390 if name < lh and name >=0:
391 return name
392 elif name < 0 and name >= -lh:
393 return lh - name
394 raise IndexError
395 raise TypeError
396
399
400
402
404 if not isinstance(table,Table):
405 raise TypeError
406
407 self._reftable=table
408 self._i=0
409
412
414 return self._reftable.types
415
418
421
423 if isinstance(name,str):
424 return self._reftable._hindex[name]
425 elif isinstance(name,int):
426 lh = len(self._reftable._headers)
427 if name < lh and name >=0:
428 return name
429 elif name < 0 and name >= -lh:
430 return lh - name
431 raise IndexError
432 raise TypeError
433
434
437
439 if self._i < len(self._reftable):
440 rep=self._reftable[self._i]
441 self._i+=1
442 return rep
443 else:
444 raise StopIteration
445
446 headers = property(_getHeaders,None,None)
447 types = property(_getTypes,None,None)
448 rowFactory = property(_getRowFactory,None,None)
449 subrowFactory = property(_getSubrowFactory,None,None)
450
451
453
454 - def __init__(self,tableiterator,*cols):
455 self._reference = iter(tableiterator)
456
457 assert isinstance(self._reference, iTableIterator)
458
459 self._selected = tuple(self._reference.columnIndex(x)
460 for x in cols)
461 self._headers = tuple(self._reference.headers[x]
462 for x in self._selected)
463
464 if self._reference.types is not None:
465 self._types= tuple(self._reference.types[x]
466 for x in self._selected)
467 else:
468 self._types=None
469
472
475
478
481
482 headers = property(_getHeaders,None,None)
483 types = property(_getTypes,None,None)
484 rowFactory = property(_getRowFactory,None,None)
485 subrowFactory = property(_getSubrowFactory,None,None)
486
491
493 - def __init__(self,tableiterator,**conditions):
494 self._reference = iter(tableiterator)
495
496 assert isinstance(self._reference, iTableIterator)
497
498 self._conditions=dict((self._reference.columnIndex(i),c)
499 for i,c in conditions.iteritems())
500
502 return reduce(lambda x,y : x and y,
503 (bool(self._conditions[i](row[i]))
504 for i in self._conditions),
505 True)
506
509
512
515
517 return self._reference.types
518
520 row = self._reference.next()
521 while not self._checkCondition(row):
522 row = self._reference.next()
523 return row
524
525
526 headers = property(_getHeaders,None,None)
527 types = property(_getTypes,None,None)
528 rowFactory = property(_getRowFactory,None,None)
529 subrowFactory = property(_getSubrowFactory,None,None)
530
531
534 self._itables=[iter(x) for x in itables]
535 self._types = self._itables[0].types
536 self._headers = self._itables[0].headers
537
538 assert reduce(lambda x,y: x and y,
539 ( isinstance(z,iTableIterator)
540 and len(z.headers)==len(self._headers)
541 for z in self._itables),
542 True)
543
544 self._iterator = chain(*self._itables)
545
548
551
554
557
561
562 headers = property(_getHeaders,None,None)
563 types = property(_getTypes,None,None)
564 rowFactory = property(_getRowFactory,None,None)
565 subrowFactory = property(_getSubrowFactory,None,None)
566
567
568
582
585
586 -def subTable(tableiterator,**conditions):
588
590 '''
591 Concatene severals tables.
592
593 concatenation is done using the L{UnionIterator<UnionIterator>}
594
595 @type itables: iTableIterator or Table
596
597 @return: a new Table
598 @rtype: c{Table}
599
600 @see: L{UnionIterator<UnionIterator>}
601 '''
602 return tableFactory(UnionIterator(*itables))
603
605
607 self._reference = iter(tableiterator)
608
609 assert isinstance(self._reference, iTableIterator)
610
611 self._headers = self._reference.headers
612 self._types = self._reference.types
613 if self._types is not None:
614 self._types = dict((n,t)
615 for n,t in imap(None,self._headers,self._types))
616
619
621 value = self._reference.next()
622 return dict((n,t)
623 for n,t in imap(None,self._headers,value))
624
627
630
631 headers = property(_getHeaders,None,None)
632 types = property(_getTypes,None,None)
633