many improvment
[tiramisu.git] / tiramisu / storage / sqlite3 / 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
19 from .sqlite3db import Sqlite3DB
20 from .storage import delete_session
21 from ...setting import undefined, owners
22 from ...i18n import _
23
24
25 class Values(Sqlite3DB):
26     __slots__ = ('__weakref__',)
27
28     def __init__(self, storage):
29         """init plugin means create values storage
30         """
31         super(Values, self).__init__(storage)
32
33     def getsession(self):
34         pass
35
36     # sqlite
37     def _sqlite_select(self, path, index):
38         request = "SELECT value FROM value WHERE path = ? AND session_id = ? "
39         params = (path, self._session_id)
40         if index is not None:
41             request += "and idx = ? "
42             params = (path, self._session_id, index)
43         request += "LIMIT 1"
44         return self._storage.select(request, params)
45
46     # value
47     def setvalue(self, path, value, owner, index, session):
48         """set value for an option
49         a specified value must be associated to an owner
50         """
51         path = self._sqlite_encode_path(path)
52         if index is not None:
53             self._storage.execute("DELETE FROM value WHERE path = ? AND idx = ? AND "
54                                   "session_id = ?", (path, index, self._session_id),
55                                   commit=False)
56             self._storage.execute("INSERT INTO value(path, value, owner, idx, session_id) VALUES "
57                                   "(?, ?, ?, ?, ?)", (path, self._sqlite_encode(value),
58                                                       str(owner),
59                                                       index,
60                                                       self._session_id),
61                                   commit=True)
62         else:
63             self._storage.execute("DELETE FROM value WHERE path = ? AND session_id = ?",
64                                   (path, self._session_id),
65                                   commit=False)
66             self._storage.execute("INSERT INTO value(path, value, owner, session_id) VALUES "
67                                   "(?, ?, ?, ?)", (path, self._sqlite_encode(value),
68                                                    str(owner),
69                                                    self._session_id),
70                                   commit=True)
71
72     def getvalue(self, path, session, index=None):
73         """get value for an option
74         return: only value, not the owner
75         """
76         path = self._sqlite_encode_path(path)
77         values = self._sqlite_select(path, index)
78         if values is None:
79             return values
80         return self._sqlite_decode(values[0])
81
82     def hasvalue(self, path, index=None):
83         """if opt has a value
84         return: boolean
85         """
86         path = self._sqlite_encode_path(path)
87         return self._sqlite_select(path, index) is not None
88
89     def resetvalue(self, path, session):
90         """remove value means delete value in storage
91         """
92         path = self._sqlite_encode_path(path)
93         self._storage.execute("DELETE FROM value WHERE path = ? AND session_id = ?", (path, self._session_id))
94
95     def get_modified_values(self):
96         """return all values in a dictionary
97         example: {option1: (owner, 'value1'), option2: (owner, 'value2')}
98         """
99         ret = {}
100         for path, value, owner, index, _ in self._storage.select("SELECT * FROM value WHERE "
101                                                                  "session_id = ?",
102                                                                  (self._session_id,),
103                                                                  only_one=False):
104             path = self._sqlite_decode_path(path)
105             owner = getattr(owners, owner)
106
107             value = self._sqlite_decode(value)
108             if isinstance(value, list):
109                 value = tuple(value)
110             if index is None:
111                 ret[path] = (owner, value)
112             else:
113                 if path in ret:
114                     ret[path][0][str(index)] = owner
115                     ret[path][1][str(index)] = value
116                 else:
117                     ret[path] = ({str(index): owner}, {str(index): value})
118         return ret
119
120     # owner
121     def setowner(self, path, owner, session, index=None):
122         """change owner for an option
123         """
124         path = self._sqlite_encode_path(path)
125         if index is None:
126             self._storage.execute("UPDATE value SET owner = ? WHERE path = ? AND session_id = ?",
127                                  (str(owner), path, self._session_id))
128         else:
129             self._storage.execute("UPDATE value SET owner = ? WHERE path = ? and idx = ? AND session_id = ?",
130                                  (str(owner), path, index, self._session_id))
131
132     def getowner(self, path, default, session, index=None, only_default=False, with_value=False):
133         """get owner for an option
134         return: owner object
135         """
136         path = self._sqlite_encode_path(path)
137         request = "SELECT owner, value FROM value WHERE path = ? AND session_id = ?"
138         if index is not None:
139             request += " AND idx = ?"
140             params = (path, self._session_id, index)
141         else:
142             params = (path, self._session_id)
143         request += ' LIMIT 1'
144         owner = self._storage.select(request, params)
145         if owner is None:
146             if not with_value:
147                 return default
148             else:
149                 return default, None
150         else:
151             # autocreate owners
152             try:
153                 nowner = getattr(owners, owner[0])
154             except AttributeError:
155                 owners.addowner(towner)
156                 nowner = getattr(owners, owner[0])
157             if not with_value:
158                 return nowner
159             else:
160                 value = self._sqlite_decode(owner[1])
161                 return nowner, value
162
163     def set_information(self, key, value):
164         """updates the information's attribute
165         (which is a dictionary)
166
167         :param key: information's key (ex: "help", "doc"
168         :param value: information's value (ex: "the help string")
169         """
170         self._storage.execute("DELETE FROM information WHERE key = ? AND session_id = ?",
171                              (key, self._session_id),
172                              False)
173         self._storage.execute("INSERT INTO information(key, value, session_id) VALUES "
174                              "(?, ?, ?)", (key, self._sqlite_encode(value), self._session_id))
175
176     def get_information(self, key, default):
177         """retrieves one information's item
178
179         :param key: the item string (ex: "help")
180         """
181         value = self._storage.select("SELECT value FROM information WHERE key = ? AND "
182                                      "session_id = ?",
183                                     (key, self._session_id))
184         if value is None:
185             if default is undefined:
186                 raise ValueError(_("information's item"
187                                    " not found: {0}").format(key))
188             return default
189         else:
190             return self._sqlite_decode(value[0])
191
192     def del_information(self, key, raises):
193         if raises and self._storage.select("SELECT value FROM information WHERE key = ? "
194                                            "AND session_id = ?",
195                                            (key, self._session_id)) is None:
196             raise ValueError(_("information's item not found {0}").format(key))
197         self._storage.execute("DELETE FROM information WHERE key = ? AND session_id = ?",
198                               (key, self._session_id))
199
200     def exportation(self, session, fake=False):
201         rows = self._storage.select("SELECT path, value, owner, idx FROM value WHERE "
202                                     "session_id = ?;", (self._session_id,), only_one=False)
203         ret = [[], [], [], []]
204         for row in rows:
205             path = row[0]
206             value = self._sqlite_decode(row[1])
207             owner = row[2]
208             index = row[3]
209             if index is None:
210                 ret[0].append(path)
211                 ret[1].append(index)
212                 ret[2].append(value)
213                 ret[3].append(owner)
214             else:
215                 if path in ret[0]:
216                     path_idx = ret[0].index(path)
217                     ret[1][path_idx].append(index)
218                     ret[2][path_idx].append(value)
219                 else:
220                     ret[0].append(path)
221                     ret[1].append([index])
222                     ret[2].append([value])
223                     ret[3].append(owner)
224
225         return ret
226
227     def importation(self, export):
228         self._storage.execute("DELETE FROM value WHERE session_id = ?", (self._session_id,),
229                               commit=False)
230         for idx, path in enumerate(export[0]):
231             index = export[1][idx]
232             value = export[2][idx]
233             owner = export[3][idx]
234             self._storage.execute("INSERT INTO value(path, value, owner, idx, session_id) VALUES "
235                                   "(?, ?, ?, ?, ?)", (path, self._sqlite_encode(value),
236                                                       str(owner), index,
237                                                       self._session_id))
238         self._storage._conn.commit()
239
240     def get_max_length(self, path, session):
241         val_max = self._storage.select("SELECT max(idx) FROM value WHERE path = ? AND session_id = ?",
242                                        (path, self._session_id), False)
243         if val_max[0][0] is None:
244             return 0
245         return val_max[0][0] + 1