Mercurial > libervia-web
comparison src/server/utils.py @ 1063:4b69f69c6ffd
server: new ProgressHandler helper class, to handle progressing actions
author | Goffi <goffi@goffi.org> |
---|---|
date | Sun, 11 Mar 2018 19:30:37 +0100 |
parents | f2170536ba23 |
children | 808ec98de8b3 |
comparison
equal
deleted
inserted
replaced
1062:c80649cdadd5 | 1063:4b69f69c6ffd |
---|---|
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 # GNU Affero General Public License for more details. | 15 # GNU Affero General Public License for more details. |
16 | 16 |
17 # You should have received a copy of the GNU Affero General Public License | 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/>. | 18 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
19 from sat.core.i18n import _ | |
20 from twisted.internet import reactor | |
21 from twisted.internet import defer | |
22 from sat.core import exceptions | |
23 from sat.core.log import getLogger | |
19 import urllib | 24 import urllib |
25 log = getLogger(__name__) | |
20 | 26 |
21 | 27 |
22 def quote(value, safe='@'): | 28 def quote(value, safe='@'): |
23 """shortcut to quote an unicode value for URL""" | 29 """shortcut to quote an unicode value for URL""" |
24 return urllib.quote(value.encode('utf-8'), safe=safe) | 30 return urllib.quote(value.encode('utf-8'), safe=safe) |
31 | |
32 | |
33 class ProgressHandler(object): | |
34 """class to help the management of progressions""" | |
35 handlers = {} | |
36 | |
37 def __init__(self, host, progress_id, profile): | |
38 self.host = host | |
39 self.progress_id = progress_id | |
40 self.profile = profile | |
41 | |
42 @classmethod | |
43 def _signal(cls, name, progress_id, data, profile): | |
44 handlers = cls.handlers | |
45 if profile in handlers and progress_id in handlers[profile]: | |
46 handler_data = handlers[profile][progress_id] | |
47 timeout = handler_data[u'timeout'] | |
48 if timeout.active(): | |
49 timeout.cancel() | |
50 cb = handler_data[name] | |
51 if cb is not None: | |
52 cb(data) | |
53 if name == u'started': | |
54 pass | |
55 elif name == u'finished': | |
56 handler_data[u'deferred'].callback(data) | |
57 handler_data[u'instance'].unregister_handler() | |
58 elif name == u'error': | |
59 handler_data[u'deferred'].errback(Exception(data)) | |
60 handler_data[u'instance'].unregister_handler() | |
61 | |
62 def _timeout(self): | |
63 log.warning(_(u"No progress received, cancelling handler: {progress_id} [{profile}]").format( | |
64 progress_id = self.progress_id, profile = self.profile)) | |
65 | |
66 def unregister_handler(self): | |
67 """remove a previously registered handler""" | |
68 try: | |
69 del self.handlers[self.profile][self.progress_id] | |
70 except KeyError: | |
71 log.warning(_(u"Trying to remove unknown handler: {progress_id} [{profile}]").format( | |
72 progress_id = self.progress_id, profile = self.profile)) | |
73 else: | |
74 if not self.handlers[self.profile]: | |
75 self.handlers[self.profile] | |
76 | |
77 def register(self, started_cb=None, finished_cb=None, error_cb=None, timeout=30): | |
78 """register the signals to handle progression | |
79 | |
80 @param started_cb(callable, None): method to call when progressStarted signal is received | |
81 @param finished_cb(callable, None): method to call when progressFinished signal is received | |
82 @param error_cb(callable, None): method to call when progressError signal is received | |
83 @param timeout(int): progress time out | |
84 if nothing happen in this progression during this delay, | |
85 an exception is raised | |
86 @return (D(dict[unicode,unicode])): a deferred called when progression is finished | |
87 """ | |
88 handler_data = self.handlers.setdefault(self.profile, {}).setdefault(self.progress_id, {}) | |
89 if handler_data: | |
90 raise exceptions.ConflictError(u"There is already one handler for this progression") | |
91 handler_data[u'instance'] = self | |
92 deferred = handler_data[u'deferred'] = defer.Deferred() | |
93 handler_data[u'started'] = started_cb | |
94 handler_data[u'finished'] = finished_cb | |
95 handler_data[u'error'] = error_cb | |
96 handler_data[u'timeout'] = reactor.callLater(timeout, self._timeout) | |
97 return deferred |