Mercurial > libervia-backend
comparison sat/memory/persistent.py @ 2562:26edcf3a30eb
core, setup: huge cleaning:
- moved directories from src and frontends/src to sat and sat_frontends, which is the recommanded naming convention
- move twisted directory to root
- removed all hacks from setup.py, and added missing dependencies, it is now clean
- use https URL for website in setup.py
- removed "Environment :: X11 Applications :: GTK", as wix is deprecated and removed
- renamed sat.sh to sat and fixed its installation
- added python_requires to specify Python version needed
- replaced glib2reactor which use deprecated code by gtk3reactor
sat can now be installed directly from virtualenv without using --system-site-packages anymore \o/
author | Goffi <goffi@goffi.org> |
---|---|
date | Mon, 02 Apr 2018 19:44:50 +0200 |
parents | src/memory/persistent.py@0046283a285d |
children | e107089d6640 |
comparison
equal
deleted
inserted
replaced
2561:bd30dc3ffe5a | 2562:26edcf3a30eb |
---|---|
1 #!/usr/bin/env python2 | |
2 # -*- coding: utf-8 -*- | |
3 | |
4 # SAT: a jabber client | |
5 # Copyright (C) 2009-2018 Jérôme Poisson (goffi@goffi.org) | |
6 | |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 | |
17 # You should have received a copy of the GNU Affero General Public License | |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 from sat.core.i18n import _ | |
21 from sat.core.log import getLogger | |
22 log = getLogger(__name__) | |
23 | |
24 | |
25 class MemoryNotInitializedError(Exception): | |
26 pass | |
27 | |
28 | |
29 class PersistentDict(object): | |
30 r"""A dictionary which save persistently each value assigned | |
31 | |
32 /!\ be careful, each assignment means a database write | |
33 /!\ Memory must be initialised before loading/setting value with instances of this class""" | |
34 storage = None | |
35 binary = False | |
36 | |
37 def __init__(self, namespace, profile=None): | |
38 """ | |
39 | |
40 @param namespace: unique namespace for this dictionary | |
41 @param profile(unicode, None): profile which *MUST* exists, or None for general values | |
42 """ | |
43 if not self.storage: | |
44 log.error(_("PersistentDict can't be used before memory initialisation")) | |
45 raise MemoryNotInitializedError | |
46 self._cache = None | |
47 self.namespace = namespace | |
48 self.profile = profile | |
49 | |
50 def _setCache(self, data): | |
51 self._cache = data | |
52 | |
53 def load(self): | |
54 """Load persistent data from storage. | |
55 | |
56 need to be called before any other operation | |
57 @return: defers the PersistentDict instance itself | |
58 """ | |
59 d = self.storage.getPrivates(self.namespace, binary=self.binary, profile=self.profile) | |
60 d.addCallback(self._setCache) | |
61 d.addCallback(lambda dummy: self) | |
62 return d | |
63 | |
64 def iteritems(self): | |
65 return self._cache.iteritems() | |
66 | |
67 def items(self): | |
68 return self._cache.items() | |
69 | |
70 def __repr__(self): | |
71 return self._cache.__repr__() | |
72 | |
73 def __str__(self): | |
74 return self._cache.__str__() | |
75 | |
76 def __lt__(self, other): | |
77 return self._cache.__lt__(other) | |
78 | |
79 def __le__(self, other): | |
80 return self._cache.__le__(other) | |
81 | |
82 def __eq__(self, other): | |
83 return self._cache.__eq__(other) | |
84 | |
85 def __ne__(self, other): | |
86 return self._cache.__ne__(other) | |
87 | |
88 def __gt__(self, other): | |
89 return self._cache.__gt__(other) | |
90 | |
91 def __ge__(self, other): | |
92 return self._cache.__ge__(other) | |
93 | |
94 def __cmp__(self, other): | |
95 return self._cache.__cmp__(other) | |
96 | |
97 def __hash__(self): | |
98 return self._cache.__hash__() | |
99 | |
100 def __nonzero__(self): | |
101 return self._cache.__len__() | |
102 | |
103 def __contains__(self, key): | |
104 return self._cache.__contains__(key) | |
105 | |
106 def __iter__(self): | |
107 return self._cache.__iter__() | |
108 | |
109 def __getitem__(self, key): | |
110 return self._cache.__getitem__(key) | |
111 | |
112 def __setitem__(self, key, value): | |
113 self.storage.setPrivateValue(self.namespace, key, value, self.binary, self.profile) | |
114 return self._cache.__setitem__(key, value) | |
115 | |
116 def __delitem__(self, key): | |
117 self.storage.delPrivateValue(self.namespace, key, self.binary, self.profile) | |
118 return self._cache.__delitem__(key) | |
119 | |
120 def get(self, key, default=None): | |
121 return self._cache.get(key, default) | |
122 | |
123 def setdefault(self, key, default): | |
124 try: | |
125 return self._cache[key] | |
126 except: | |
127 self.__setitem__(key, default) | |
128 return default | |
129 | |
130 def force(self, name): | |
131 """Force saving of an attribute to storage | |
132 | |
133 @return: deferred fired when data is actually saved | |
134 """ | |
135 return self.storage.setPrivateValue(self.namespace, name, self._cache[name], self.binary, self.profile) | |
136 | |
137 | |
138 class PersistentBinaryDict(PersistentDict): | |
139 """Persistent dict where value can be any python data (instead of string only)""" | |
140 binary = True | |
141 | |
142 | |
143 class LazyPersistentBinaryDict(PersistentBinaryDict): | |
144 ur"""PersistentBinaryDict which get key/value when needed | |
145 | |
146 This Persistent need more database access, it is suitable for largest data, | |
147 to save memory. | |
148 /!\ most of methods return a Deferred | |
149 """ | |
150 # TODO: missing methods should be implemented using database access | |
151 # TODO: a cache would be useful (which is deleted after a timeout) | |
152 | |
153 def load(self): | |
154 # we show a warning as calling load on LazyPersistentBinaryDict sounds like a code mistake | |
155 log.warning(_(u"Calling load on LazyPersistentBinaryDict while it's not needed")) | |
156 | |
157 def iteritems(self): | |
158 raise NotImplementedError | |
159 | |
160 def items(self): | |
161 return self.storage.getPrivates(self.namespace, binary=self.binary, profile=self.profile) | |
162 | |
163 def __repr__(self): | |
164 raise NotImplementedError | |
165 | |
166 def __str__(self): | |
167 return "LazyPersistentBinaryDict (namespace: {})".format(self.namespace) | |
168 | |
169 def __lt__(self, other): | |
170 raise NotImplementedError | |
171 | |
172 def __le__(self, other): | |
173 raise NotImplementedError | |
174 | |
175 def __eq__(self, other): | |
176 raise NotImplementedError | |
177 | |
178 def __ne__(self, other): | |
179 raise NotImplementedError | |
180 | |
181 def __gt__(self, other): | |
182 raise NotImplementedError | |
183 | |
184 def __ge__(self, other): | |
185 raise NotImplementedError | |
186 | |
187 def __cmp__(self, other): | |
188 raise NotImplementedError | |
189 | |
190 def __hash__(self): | |
191 return hash(unicode(self.__class__) + self.namespace + (self.profile or u'')) | |
192 | |
193 def __nonzero__(self): | |
194 raise NotImplementedError | |
195 | |
196 def __contains__(self, key): | |
197 raise NotImplementedError | |
198 | |
199 def __iter__(self): | |
200 raise NotImplementedError | |
201 | |
202 def __getitem__(self, key): | |
203 """get the value as a Deferred""" | |
204 d = self.storage.getPrivates(self.namespace, keys=[key], binary=self.binary, profile=self.profile) | |
205 d.addCallback(lambda data: data[key]) | |
206 return d | |
207 | |
208 def __setitem__(self, key, value): | |
209 self.storage.setPrivateValue(self.namespace, key, value, self.binary, self.profile) | |
210 | |
211 def __delitem__(self, key): | |
212 self.storage.delPrivateValue(self.namespace, key, self.binary, self.profile) | |
213 | |
214 def _valueOrDefault(self, value, default): | |
215 if value is None: | |
216 return default | |
217 return value | |
218 | |
219 def get(self, key, default=None): | |
220 d = self.__getitem__(key) | |
221 d.addCallback(self._valueOrDefault) | |
222 return d | |
223 | |
224 def setdefault(self, key, default): | |
225 raise NotImplementedError | |
226 | |
227 def force(self, name, value): | |
228 """Force saving of an attribute to storage | |
229 | |
230 @param value(object): value is needed for LazyPersistentBinaryDict | |
231 @return: deferred fired when data is actually saved | |
232 """ | |
233 return self.storage.setPrivateValue(self.namespace, name, value, self.binary, self.profile) |