separate baseoption and option
[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-2017 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         #(('path1',), (index1,), (value1,), ('owner1'))
30         self._values = (tuple(), tuple(), tuple(), tuple())
31         self._informations = {}
32         # should init cache too
33         super(Values, self).__init__(storage)
34
35     def commit(self):
36         pass
37
38     def getsession(self):
39         pass
40
41     def _setvalue_info(self, nb, idx, value, values, index, vidx):
42         lst = list(self._values[nb])
43         if idx is None:
44             if index is None or nb == 0:
45                 lst.append(value)
46             else:
47                 lst.append((value,))
48         else:
49             if index is None or nb == 0:
50                 lst[idx] = value
51             else:
52                 if nb == 1:
53                     if index in lst[idx]:
54                         vidx = lst[idx].index(index)
55                     else:
56                         vidx = None
57                 if vidx is None:
58                     tval = list(lst[idx])
59                     tval.append(value)
60                     lst[idx] = tuple(tval)
61                 elif nb != 1:
62                     tval = list(lst[idx])
63                     tval[vidx] = value
64                     lst[idx] = tuple(tval)
65                 lst[idx] = tuple(lst[idx])
66         values.append(tuple(lst))
67         return vidx
68     # value
69     def setvalue(self, path, value, owner, index, session, commit):
70         """set value for a path
71         a specified value must be associated to an owner
72         """
73         values = []
74         vidx = None
75
76         if path in self._values[0]:
77             idx = self._values[0].index(path)
78         else:
79             idx = None
80         vidx = self._setvalue_info(0, idx, path, values, index, vidx)
81         vidx = self._setvalue_info(1, idx, index, values, index, vidx)
82         if isinstance(value, list):
83             value = tuple(value)
84         vidx = self._setvalue_info(2, idx, value, values, index, vidx)
85         self._setvalue_info(3, idx, owner, values, index, vidx)
86         self._values = tuple(values)
87
88     def hasvalue(self, path, index=None):
89         """if path has a value
90         return: boolean
91         """
92         return path in self._values[0]
93
94     def resetvalue(self, path, session, commit):
95         """remove value means delete value in storage
96         """
97         def _resetvalue(nb):
98             lst = list(self._values[nb])
99             lst.pop(idx)
100             values.append(tuple(lst))
101         values = []
102         if path in self._values[0]:
103             idx = self._values[0].index(path)
104             _resetvalue(0)
105             _resetvalue(1)
106             _resetvalue(2)
107             _resetvalue(3)
108             self._values = tuple(values)
109
110     def get_modified_values(self):
111         """return all values in a dictionary
112         example: {'path1': (owner, 'value1'), 'path2': (owner, 'value2')}
113         """
114         values = {}
115         for idx, path in enumerate(self._values[0]):
116             indexes = self._values[1][idx]
117             value = self._values[2][idx]
118             owner = self._values[3][idx]
119             if indexes is not None:
120                 val = {}
121                 own = {}
122                 for cpt, index in enumerate(indexes):
123                     val[str(index)] = value[cpt]
124                     own[str(index)] = owner[cpt]
125                 value = val
126                 owner = own
127             values[path] = (owner, value)
128         return values
129
130     # owner
131     def setowner(self, path, owner, session, index=None):
132         """change owner for a path
133         """
134         idx = self._values[0].index(path)
135         if index is None:
136             vidx = None
137         else:
138             vidx = self._values[1][idx].index(index)
139         values = []
140         self._setvalue_info(3, idx, owner, values, index, vidx)
141         lst = list(self._values)
142         lst[3] = tuple(values[0])
143         self._values = tuple(lst)
144
145     def get_max_length(self, path, session):
146         if path in self._values[0]:
147             idx = self._values[0].index(path)
148         else:
149             return 0
150         return max(self._values[1][idx]) + 1
151
152     def getowner(self, path, default, session, index=None, only_default=False,
153                  with_value=False):
154         """get owner for a path
155         return: owner object
156         """
157         if index is None:
158             if only_default:
159                 if path in self._values[0]:
160                     owner = undefined
161                 else:
162                     owner = default
163             else:
164                 owner = self._getvalue(path, 3, index)
165                 if owner is undefined:
166                     owner = default
167         else:
168             owner = self._getvalue(path, 3, index)
169             if owner is undefined:
170                 owner = default
171         if with_value:
172             return owner, self._getvalue(path, 2, index)
173         else:
174             return owner
175
176     def _getvalue(self, path, nb, index):
177         """
178         _values == ((path1, path2), ((idx1_1, idx1_2), None), ((value1_1, value1_2), value2), ((owner1_1, owner1_2), owner2))
179         """
180         if path in self._values[0]:
181             path_idx = self._values[0].index(path)
182             indexes = self._values[1][path_idx]
183             if indexes is None:
184                 if index is not None:  # pragma: no cover
185                     raise ValueError('index is forbidden for {}'.format(path))
186                 value = self._values[nb][path_idx]
187             else:
188                 if index is None:  # pragma: no cover
189                     raise ValueError('index is mandatory for {}'.format(path))
190                 if index in indexes:
191                     subidx = indexes.index(index)
192                     value = self._values[nb][path_idx][subidx]
193                 else:
194                     value = undefined
195         else:
196             value = undefined
197         if isinstance(value, tuple):
198             value = list(value)
199         return value
200
201     def set_information(self, key, value):
202         """updates the information's attribute
203         (which is a dictionary)
204
205         :param key: information's key (ex: "help", "doc"
206         :param value: information's value (ex: "the help string")
207         """
208         self._informations[key] = value
209
210     def get_information(self, key, default):
211         """retrieves one information's item
212
213         :param key: the item string (ex: "help")
214         """
215         value = self._informations.get(key, default)
216         if value is undefined:
217             raise ValueError(_("information's item"
218                                " not found: {0}").format(key))
219         return value
220
221     def del_information(self, key, raises):
222         if key in self._informations:
223             del(self._informations[key])
224         else:
225             if raises:
226                 raise ValueError(_("information's item not found {0}").format(key))
227
228     def exportation(self, session, fake=False):
229         return self._values
230
231     def importation(self, export):
232         self._values = export
233
234 def delete_session(session_id, session):
235     raise ValueError(_('a dictionary cannot be persistent'))