19
|
1 # -*- coding: utf-8 -*-
|
|
2
|
|
3 """
|
|
4 data models
|
|
5 """
|
|
6
|
21
|
7 from collections import OrderedDict
|
|
8
|
|
9 __all__ = ['Rows', 'Columns']
|
|
10
|
|
11
|
|
12 class ColumnNumberException(Exception):
|
|
13 """
|
|
14 wrong number of columns: {given} given; {expected} expected
|
|
15 """
|
|
16 def __init__(self, given, expected):
|
|
17 self.given = given
|
|
18 self.expected = expected
|
23
|
19 Exception.__init__(self.__doc__.format(**self.__dict__).strip())
|
|
20
|
|
21
|
|
22 class ColumnLengthException(ColumnNumberException):
|
|
23 """
|
|
24 wrong length of column: {given} given; {expected} expected
|
|
25 """
|
|
26 # XXX should share ABC, not inherit from ColumnNumberException
|
21
|
27
|
|
28
|
|
29 class Rows(object):
|
|
30 """
|
|
31 row-based data
|
|
32 """
|
|
33
|
|
34 array = OrderedDict
|
19
|
35
|
21
|
36 def __init__(self, columns, *rows):
|
|
37 """
|
|
38 columns -- column labels
|
|
39 """
|
|
40 self.column_names = columns
|
|
41 self.rows = []
|
|
42
|
|
43 for row in rows:
|
|
44 self += row
|
|
45
|
|
46 def __iadd__(self, row):
|
|
47 """add a labeled row"""
|
|
48 if len(row) != len(self.columns_names):
|
|
49 raise ColumnNumberException(len(row), len(self.columns_names))
|
|
50 self.rows.append(self.array(zip(self.columns_names, row)))
|
|
51
|
|
52 def __len__(self):
|
|
53 return len(self.rows)
|
|
54
|
|
55 def __getitem__(self, item):
|
|
56 return self.rows[item]
|
22
|
57
|
|
58
|
|
59 class Columns(object):
|
|
60 """
|
|
61 column-oriented data
|
|
62 """
|
|
63
|
|
64 def __init__(self, *columns):
|
|
65 self.columns = OrderedDict() # this should be ordered
|
23
|
66 for name, values in columns:
|
|
67 self += (name, values)
|
|
68
|
|
69 def __iadd__(self, item):
|
|
70 column_name, values = item
|
|
71 assert column_name not in self.columns
|
|
72
|
|
73 return self
|