cb7baf15be0942e44b9e04cbecf872b97df023ae
[tiramisu.git] / tiramisu / storage / dictionary / value.py
1 # -*- coding: utf-8 -*-
2 "default plugin for value: set it in a simple dictionary"
3 # Copyright (C) 2013-2014 Team tiramisu (see AUTHORS for all contributors)
4 #
5 # This program is free software: you can redistribute it and/or modify it
6 # under the terms of the GNU Lesser General Public License as published by the
7 # Free Software Foundation, either version 3 of the License, or (at your
8 # option) any later version.
9 #
10 # This program is distributed in the hope that it will be useful, but WITHOUT
11 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12 # FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more
13 # details.
14 #
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 # ____________________________________________________________
18 from ..util import Cache
19 from ...setting import undefined
20 from ...i18n import _
21
22
23 class Values(Cache):
24     __slots__ = ('_values', '_informations', '__weakref__')
25
26     def __init__(self, storage):
27         """init plugin means create values storage
28         """
29         self._values = (tuple(), tuple(), tuple(), tuple())
30         self._informations = {}
31         # should init cache too
32         super(Values, self).__init__(storage)
33
34     def _setvalue_info(self, nb, idx, value, values, index, vidx):
35         lst = list(self._values[nb])
36         if idx is None:
37             if index is None or nb == 0:
38                 lst.append(value)
39             else:
40                 lst.append((value,))
41         else:
42             if index is None or nb == 0:
43                 lst[idx] = value
44             else:
45                 if nb == 1:
46                     if index in lst[idx]:
47                         vidx = lst[idx].index(index)
48                     else:
49                         vidx = None
50                 if vidx is None:
51                     tval = list(lst[idx])
52                     tval.append(value)
53                     lst[idx] = tuple(tval)
54                 elif nb != 1:
55                     tval = list(lst[idx])
56                     tval[vidx] = value
57                     lst[idx] = tuple(tval)
58                 lst[idx] = tuple(lst[idx])
59         for ls in lst:
60             if isinstance(ls, list):
61                 raise Exception('pouet')
62         values.append(tuple(lst))
63         return vidx
64     # value
65     def setvalue(self, path, value, owner, index):
66         """set value for a path
67         a specified value must be associated to an owner
68         """
69         values = []
70         vidx = None
71
72         if path in self._values[0]:
73             idx = self._values[0].index(path)
74         else:
75             idx = None
76         vidx = self._setvalue_info(0, idx, path, values, index, vidx)
77         vidx = self._setvalue_info(1, idx, index, values, index, vidx)
78         if isinstance(value, list):
79             value = tuple(value)
80         vidx = self._setvalue_info(2, idx, value, values, index, vidx)
81         if isinstance(value, list):
82             value = tuple(value)
83         self._setvalue_info(3, idx, owner, values, index, vidx)
84         self._values = tuple(values)
85
86     def getvalue(self, path, index=None):
87         """get value for a path
88         return: only value, not the owner
89         """
90         return self._getvalue(path, 2, index)
91
92     def hasvalue(self, path, index=None):
93         """if path has a value
94         return: boolean
95         """
96         return path in self._values[0]
97
98     def resetvalue(self, path):
99         """remove value means delete value in storage
100         """
101         def _resetvalue(nb):
102             lst = list(self._values[nb])
103             lst.pop(idx)
104             values.append(tuple(lst))
105         values = []
106         if path in self._values[0]:
107             idx = self._values[0].index(path)
108             _resetvalue(0)
109             _resetvalue(1)
110             _resetvalue(2)
111             _resetvalue(3)
112             self._values = tuple(values)
113
114     def get_modified_values(self):
115         """return all values in a dictionary
116         example: {'path1': (owner, 'value1'), 'path2': (owner, 'value2')}
117         """
118         values = {}
119         for idx, path in enumerate(self._values[0]):
120             indexes = self._values[1][idx]
121             value = self._values[2][idx]
122             owner = self._values[3][idx]
123             if indexes is not None:
124                 val = {}
125                 own = {}
126                 for cpt, index in enumerate(indexes):
127                     val[str(index)] = value[cpt]
128                     own[str(index)] = owner[cpt]
129                 value = val
130                 owner = own
131             values[path] = (owner, value)
132         return values
133
134     # owner
135     def setowner(self, path, owner, index=None):
136         """change owner for a path
137         """
138         idx = self._values[0].index(path)
139         if index is None:
140             vidx = None
141         else:
142             vidx = self._values[1][idx].index(index)
143         values = []
144         self._setvalue_info(3, idx, owner, values, index, vidx)
145         lst = list(self._values)
146         lst[3] = tuple(values[0])
147         self._values = tuple(lst)
148
149     def get_max_length(self, path):
150         if path in self._values[0]:
151             idx = self._values[0].index(path)
152         else:
153             return 0
154         return max(self._values[1][idx]) + 1
155
156     def getowner(self, path, default, index=None, only_default=False):
157         """get owner for a path
158         return: owner object
159         """
160         if index is None:
161             if only_default:
162                 if path in self._values[0]:
163                     return None
164                 else:
165                     return default
166             val = self._getvalue(path, 3, index)
167             if val is None:
168                 return default
169             return val
170         else:
171             value = self._getvalue(path, 3, index)
172             if value is None:
173                 return default
174             else:
175                 return value
176
177     def _getvalue(self, path, nb, index):
178         """
179         _values == ((path1, path2), ((idx1_1, idx1_2), None), ((value1_1, value1_2), value2), ((owner1_1, owner1_2), owner2))
180         """
181         if path in self._values[0]:
182             idx = self._values[0].index(path)
183             if isinstance(self._values[1][idx], tuple):
184                 if index is None:
185                     raise ValueError('index is mandatory')
186             elif index is not None:
187                 raise ValueError('index is forbidden')
188
189             if self._values[1][idx] is None:
190                 if index is None:
191                     value = self._values[nb][idx]
192                 else:
193                     value = self._values[nb][idx][index]
194             else:
195                 if index is not None:
196                     if index in self._values[1][idx]:
197                         subidx = self._values[1][idx].index(index)
198                         value = self._values[nb][idx][subidx]
199                     else:
200                         value = None
201                 else:
202                     value = []
203                     for i in xrange(0, max(self._values[1][idx])):
204                         if i in self._values[1][idx]:
205                             value.append(self._values[nb][idx][self._values[1][idx].index(i)])
206                         else:
207                             value.append(undefined)
208         else:
209             value = None
210         if isinstance(value, tuple):
211             value = list(value)
212         return value
213
214     def set_information(self, key, value):
215         """updates the information's attribute
216         (which is a dictionary)
217
218         :param key: information's key (ex: "help", "doc"
219         :param value: information's value (ex: "the help string")
220         """
221         self._informations[key] = value
222
223     def get_information(self, key, default):
224         """retrieves one information's item
225
226         :param key: the item string (ex: "help")
227         """
228         value = self._informations.get(key, default)
229         if value is undefined:
230             raise ValueError(_("information's item"
231                                " not found: {0}").format(key))
232         return value