Mercurial > libervia-backend
comparison sat/plugins/plugin_misc_file.py @ 2624:56f94936df1e
code style reformatting using black
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 27 Jun 2018 20:14:46 +0200 |
parents | 26edcf3a30eb |
children | 003b8b4b56a7 |
comparison
equal
deleted
inserted
replaced
2623:49533de4540b | 2624:56f94936df1e |
---|---|
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 | 19 |
20 from sat.core.i18n import _, D_ | 20 from sat.core.i18n import _, D_ |
21 from sat.core.constants import Const as C | 21 from sat.core.constants import Const as C |
22 from sat.core.log import getLogger | 22 from sat.core.log import getLogger |
23 | |
23 log = getLogger(__name__) | 24 log = getLogger(__name__) |
24 from sat.core import exceptions | 25 from sat.core import exceptions |
25 from sat.tools import xml_tools | 26 from sat.tools import xml_tools |
26 from sat.tools import stream | 27 from sat.tools import stream |
27 from twisted.internet import defer | 28 from twisted.internet import defer |
35 C.PI_IMPORT_NAME: "FILE", | 36 C.PI_IMPORT_NAME: "FILE", |
36 C.PI_TYPE: C.PLUG_TYPE_MISC, | 37 C.PI_TYPE: C.PLUG_TYPE_MISC, |
37 C.PI_MODES: C.PLUG_MODE_BOTH, | 38 C.PI_MODES: C.PLUG_MODE_BOTH, |
38 C.PI_MAIN: "FilePlugin", | 39 C.PI_MAIN: "FilePlugin", |
39 C.PI_HANDLER: "no", | 40 C.PI_HANDLER: "no", |
40 C.PI_DESCRIPTION: _("""File Tansfer Management: | 41 C.PI_DESCRIPTION: _( |
41 This plugin manage the various ways of sending a file, and choose the best one.""") | 42 """File Tansfer Management: |
43 This plugin manage the various ways of sending a file, and choose the best one.""" | |
44 ), | |
42 } | 45 } |
43 | 46 |
44 | 47 |
45 SENDING = D_(u'Please select a file to send to {peer}') | 48 SENDING = D_(u"Please select a file to send to {peer}") |
46 SENDING_TITLE = D_(u'File sending') | 49 SENDING_TITLE = D_(u"File sending") |
47 CONFIRM = D_(u'{peer} wants to send the file "{name}" to you:\n{desc}\n\nThe file has a size of {size_human}\n\nDo you accept ?') | 50 CONFIRM = D_( |
48 CONFIRM_TITLE = D_(u'Confirm file transfer') | 51 u'{peer} wants to send the file "{name}" to you:\n{desc}\n\nThe file has a size of {size_human}\n\nDo you accept ?' |
49 CONFIRM_OVERWRITE = D_(u'File {} already exists, are you sure you want to overwrite ?') | 52 ) |
50 CONFIRM_OVERWRITE_TITLE = D_(u'File exists') | 53 CONFIRM_TITLE = D_(u"Confirm file transfer") |
54 CONFIRM_OVERWRITE = D_(u"File {} already exists, are you sure you want to overwrite ?") | |
55 CONFIRM_OVERWRITE_TITLE = D_(u"File exists") | |
51 SECURITY_LIMIT = 30 | 56 SECURITY_LIMIT = 30 |
52 | 57 |
53 PROGRESS_ID_KEY = 'progress_id' | 58 PROGRESS_ID_KEY = "progress_id" |
54 | 59 |
55 | 60 |
56 class FilePlugin(object): | 61 class FilePlugin(object): |
57 File=stream.SatFile | 62 File = stream.SatFile |
58 | 63 |
59 def __init__(self, host): | 64 def __init__(self, host): |
60 log.info(_("plugin File initialization")) | 65 log.info(_("plugin File initialization")) |
61 self.host = host | 66 self.host = host |
62 host.bridge.addMethod("fileSend", ".plugin", in_sign='ssssa{ss}s', out_sign='a{ss}', method=self._fileSend, async=True) | 67 host.bridge.addMethod( |
68 "fileSend", | |
69 ".plugin", | |
70 in_sign="ssssa{ss}s", | |
71 out_sign="a{ss}", | |
72 method=self._fileSend, | |
73 async=True, | |
74 ) | |
63 self._file_callbacks = [] | 75 self._file_callbacks = [] |
64 host.importMenu((D_("Action"), D_("send file")), self._fileSendMenu, security_limit=10, help_string=D_("Send a file"), type_=C.MENU_SINGLE) | 76 host.importMenu( |
65 | 77 (D_("Action"), D_("send file")), |
66 def _fileSend(self, peer_jid_s, filepath, name="", file_desc="", extra=None, profile=C.PROF_KEY_NONE): | 78 self._fileSendMenu, |
79 security_limit=10, | |
80 help_string=D_("Send a file"), | |
81 type_=C.MENU_SINGLE, | |
82 ) | |
83 | |
84 def _fileSend( | |
85 self, | |
86 peer_jid_s, | |
87 filepath, | |
88 name="", | |
89 file_desc="", | |
90 extra=None, | |
91 profile=C.PROF_KEY_NONE, | |
92 ): | |
67 client = self.host.getClient(profile) | 93 client = self.host.getClient(profile) |
68 return self.fileSend(client, jid.JID(peer_jid_s), filepath, name or None, file_desc or None, extra) | 94 return self.fileSend( |
95 client, jid.JID(peer_jid_s), filepath, name or None, file_desc or None, extra | |
96 ) | |
69 | 97 |
70 @defer.inlineCallbacks | 98 @defer.inlineCallbacks |
71 def fileSend(self, client, peer_jid, filepath, filename=None, file_desc=None, extra=None): | 99 def fileSend( |
100 self, client, peer_jid, filepath, filename=None, file_desc=None, extra=None | |
101 ): | |
72 """Send a file using best available method | 102 """Send a file using best available method |
73 | 103 |
74 @param peer_jid(jid.JID): jid of the destinee | 104 @param peer_jid(jid.JID): jid of the destinee |
75 @param filepath(str): absolute path to the file | 105 @param filepath(str): absolute path to the file |
76 @param filename(unicode, None): name to use, or None to find it from filepath | 106 @param filename(unicode, None): name to use, or None to find it from filepath |
79 @return (dict): action dictionary, with progress id in case of success, else xmlui message | 109 @return (dict): action dictionary, with progress id in case of success, else xmlui message |
80 """ | 110 """ |
81 if not os.path.isfile(filepath): | 111 if not os.path.isfile(filepath): |
82 raise exceptions.DataError(u"The given path doesn't link to a file") | 112 raise exceptions.DataError(u"The given path doesn't link to a file") |
83 if not filename: | 113 if not filename: |
84 filename = os.path.basename(filepath) or '_' | 114 filename = os.path.basename(filepath) or "_" |
85 for namespace, callback, priority, method_name in self._file_callbacks: | 115 for namespace, callback, priority, method_name in self._file_callbacks: |
86 has_feature = yield self.host.hasFeature(client, namespace, peer_jid) | 116 has_feature = yield self.host.hasFeature(client, namespace, peer_jid) |
87 if has_feature: | 117 if has_feature: |
88 log.info(u"{name} method will be used to send the file".format(name=method_name)) | 118 log.info( |
89 progress_id = yield callback(client, peer_jid, filepath, filename, file_desc, extra) | 119 u"{name} method will be used to send the file".format( |
90 defer.returnValue({'progress': progress_id}) | 120 name=method_name |
121 ) | |
122 ) | |
123 progress_id = yield callback( | |
124 client, peer_jid, filepath, filename, file_desc, extra | |
125 ) | |
126 defer.returnValue({"progress": progress_id}) | |
91 msg = u"Can't find any method to send file to {jid}".format(jid=peer_jid.full()) | 127 msg = u"Can't find any method to send file to {jid}".format(jid=peer_jid.full()) |
92 log.warning(msg) | 128 log.warning(msg) |
93 defer.returnValue({'xmlui': xml_tools.note(u"Can't transfer file", msg, C.XMLUI_DATA_LVL_WARNING).toXml()}) | 129 defer.returnValue( |
130 { | |
131 "xmlui": xml_tools.note( | |
132 u"Can't transfer file", msg, C.XMLUI_DATA_LVL_WARNING | |
133 ).toXml() | |
134 } | |
135 ) | |
94 | 136 |
95 def _onFileChoosed(self, client, peer_jid, data): | 137 def _onFileChoosed(self, client, peer_jid, data): |
96 cancelled = C.bool(data.get("cancelled", C.BOOL_FALSE)) | 138 cancelled = C.bool(data.get("cancelled", C.BOOL_FALSE)) |
97 if cancelled: | 139 if cancelled: |
98 return | 140 return |
99 path=data['path'] | 141 path = data["path"] |
100 return self.fileSend(client, peer_jid, path) | 142 return self.fileSend(client, peer_jid, path) |
101 | 143 |
102 def _fileSendMenu(self, data, profile): | 144 def _fileSendMenu(self, data, profile): |
103 """ XMLUI activated by menu: return file sending UI | 145 """ XMLUI activated by menu: return file sending UI |
104 | 146 |
105 @param profile: %(doc_profile)s | 147 @param profile: %(doc_profile)s |
106 """ | 148 """ |
107 try: | 149 try: |
108 jid_ = jid.JID(data['jid']) | 150 jid_ = jid.JID(data["jid"]) |
109 except RuntimeError: | 151 except RuntimeError: |
110 raise exceptions.DataError(_("Invalid JID")) | 152 raise exceptions.DataError(_("Invalid JID")) |
111 | 153 |
112 file_choosed_id = self.host.registerCallback(lambda data, profile: self._onFileChoosed(self.host.getClient(profile), jid_, data), with_data=True, one_shot=True) | 154 file_choosed_id = self.host.registerCallback( |
155 lambda data, profile: self._onFileChoosed( | |
156 self.host.getClient(profile), jid_, data | |
157 ), | |
158 with_data=True, | |
159 one_shot=True, | |
160 ) | |
113 xml_ui = xml_tools.XMLUI( | 161 xml_ui = xml_tools.XMLUI( |
114 C.XMLUI_DIALOG, | 162 C.XMLUI_DIALOG, |
115 dialog_opt = { | 163 dialog_opt={ |
116 C.XMLUI_DATA_TYPE: C.XMLUI_DIALOG_FILE, | 164 C.XMLUI_DATA_TYPE: C.XMLUI_DIALOG_FILE, |
117 C.XMLUI_DATA_MESS: _(SENDING).format(peer=jid_.full())}, | 165 C.XMLUI_DATA_MESS: _(SENDING).format(peer=jid_.full()), |
118 title = _(SENDING_TITLE), | 166 }, |
119 submit_id = file_choosed_id) | 167 title=_(SENDING_TITLE), |
120 | 168 submit_id=file_choosed_id, |
121 return {'xmlui': xml_ui.toXml()} | 169 ) |
170 | |
171 return {"xmlui": xml_ui.toXml()} | |
122 | 172 |
123 def register(self, namespace, callback, priority=0, method_name=None): | 173 def register(self, namespace, callback, priority=0, method_name=None): |
124 """Register a fileSending method | 174 """Register a fileSending method |
125 | 175 |
126 @param namespace(unicode): XEP namespace | 176 @param namespace(unicode): XEP namespace |
128 @param priority(int): pririoty of this method, the higher available will be used | 178 @param priority(int): pririoty of this method, the higher available will be used |
129 @param method_name(unicode): short name for the method, namespace will be used if None | 179 @param method_name(unicode): short name for the method, namespace will be used if None |
130 """ | 180 """ |
131 for data in self._file_callbacks: | 181 for data in self._file_callbacks: |
132 if namespace == data[0]: | 182 if namespace == data[0]: |
133 raise exceptions.ConflictError(u'A method with this namespace is already registered') | 183 raise exceptions.ConflictError( |
134 self._file_callbacks.append((namespace, callback, priority, method_name or namespace)) | 184 u"A method with this namespace is already registered" |
185 ) | |
186 self._file_callbacks.append( | |
187 (namespace, callback, priority, method_name or namespace) | |
188 ) | |
135 self._file_callbacks.sort(key=lambda data: data[2], reverse=True) | 189 self._file_callbacks.sort(key=lambda data: data[2], reverse=True) |
136 | 190 |
137 def unregister(self, namespace): | 191 def unregister(self, namespace): |
138 for idx, data in enumerate(self._file_callbacks): | 192 for idx, data in enumerate(self._file_callbacks): |
139 if data[0] == namespace: | 193 if data[0] == namespace: |
146 | 200 |
147 def openFileWrite(self, client, file_path, transfer_data, file_data, stream_object): | 201 def openFileWrite(self, client, file_path, transfer_data, file_data, stream_object): |
148 """create SatFile or FileStremaObject for the requested file and fill suitable data | 202 """create SatFile or FileStremaObject for the requested file and fill suitable data |
149 """ | 203 """ |
150 if stream_object: | 204 if stream_object: |
151 assert 'stream_object' not in transfer_data | 205 assert "stream_object" not in transfer_data |
152 transfer_data['stream_object'] = stream.FileStreamObject( | 206 transfer_data["stream_object"] = stream.FileStreamObject( |
153 self.host, | 207 self.host, |
154 client, | 208 client, |
155 file_path, | 209 file_path, |
156 mode='wb', | 210 mode="wb", |
157 uid=file_data[PROGRESS_ID_KEY], | 211 uid=file_data[PROGRESS_ID_KEY], |
158 size=file_data['size'], | 212 size=file_data["size"], |
159 data_cb = file_data.get('data_cb'), | 213 data_cb=file_data.get("data_cb"), |
160 ) | 214 ) |
161 else: | 215 else: |
162 assert 'file_obj' not in transfer_data | 216 assert "file_obj" not in transfer_data |
163 transfer_data['file_obj'] = stream.SatFile( | 217 transfer_data["file_obj"] = stream.SatFile( |
164 self.host, | 218 self.host, |
165 client, | 219 client, |
166 file_path, | 220 file_path, |
167 mode='wb', | 221 mode="wb", |
168 uid=file_data[PROGRESS_ID_KEY], | 222 uid=file_data[PROGRESS_ID_KEY], |
169 size=file_data['size'], | 223 size=file_data["size"], |
170 data_cb = file_data.get('data_cb'), | 224 data_cb=file_data.get("data_cb"), |
171 ) | 225 ) |
172 | 226 |
173 def _gotConfirmation(self, data, client, peer_jid, transfer_data, file_data, stream_object): | 227 def _gotConfirmation( |
228 self, data, client, peer_jid, transfer_data, file_data, stream_object | |
229 ): | |
174 """Called when the permission and dest path have been received | 230 """Called when the permission and dest path have been received |
175 | 231 |
176 @param peer_jid(jid.JID): jid of the file sender | 232 @param peer_jid(jid.JID): jid of the file sender |
177 @param transfer_data(dict): same as for [self.getDestDir] | 233 @param transfer_data(dict): same as for [self.getDestDir] |
178 @param file_data(dict): same as for [self.getDestDir] | 234 @param file_data(dict): same as for [self.getDestDir] |
179 @param stream_object(bool): same as for [self.getDestDir] | 235 @param stream_object(bool): same as for [self.getDestDir] |
180 return (bool): True if copy is wanted and OK | 236 return (bool): True if copy is wanted and OK |
181 False if user wants to cancel | 237 False if user wants to cancel |
182 if file exists ask confirmation and call again self._getDestDir if needed | 238 if file exists ask confirmation and call again self._getDestDir if needed |
183 """ | 239 """ |
184 if data.get('cancelled', False): | 240 if data.get("cancelled", False): |
185 return False | 241 return False |
186 path = data['path'] | 242 path = data["path"] |
187 file_data['file_path'] = file_path = os.path.join(path, file_data['name']) | 243 file_data["file_path"] = file_path = os.path.join(path, file_data["name"]) |
188 log.debug(u'destination file path set to {}'.format(file_path)) | 244 log.debug(u"destination file path set to {}".format(file_path)) |
189 | 245 |
190 # we manage case where file already exists | 246 # we manage case where file already exists |
191 if os.path.exists(file_path): | 247 if os.path.exists(file_path): |
248 | |
192 def check_overwrite(overwrite): | 249 def check_overwrite(overwrite): |
193 if overwrite: | 250 if overwrite: |
194 self.openFileWrite(client, file_path, transfer_data, file_data, stream_object) | 251 self.openFileWrite( |
252 client, file_path, transfer_data, file_data, stream_object | |
253 ) | |
195 return True | 254 return True |
196 else: | 255 else: |
197 return self.getDestDir(client, peer_jid, transfer_data, file_data) | 256 return self.getDestDir(client, peer_jid, transfer_data, file_data) |
198 | 257 |
199 exists_d = xml_tools.deferConfirm( | 258 exists_d = xml_tools.deferConfirm( |
200 self.host, | 259 self.host, |
201 _(CONFIRM_OVERWRITE).format(file_path), | 260 _(CONFIRM_OVERWRITE).format(file_path), |
202 _(CONFIRM_OVERWRITE_TITLE), | 261 _(CONFIRM_OVERWRITE_TITLE), |
203 action_extra={'meta_from_jid': peer_jid.full(), | 262 action_extra={ |
204 'meta_type': C.META_TYPE_OVERWRITE, | 263 "meta_from_jid": peer_jid.full(), |
205 'meta_progress_id': file_data[PROGRESS_ID_KEY] | 264 "meta_type": C.META_TYPE_OVERWRITE, |
206 }, | 265 "meta_progress_id": file_data[PROGRESS_ID_KEY], |
266 }, | |
207 security_limit=SECURITY_LIMIT, | 267 security_limit=SECURITY_LIMIT, |
208 profile=client.profile) | 268 profile=client.profile, |
269 ) | |
209 exists_d.addCallback(check_overwrite) | 270 exists_d.addCallback(check_overwrite) |
210 return exists_d | 271 return exists_d |
211 | 272 |
212 self.openFileWrite(client, file_path, transfer_data, file_data, stream_object) | 273 self.openFileWrite(client, file_path, transfer_data, file_data, stream_object) |
213 return True | 274 return True |
237 "size_human" will also be added with human readable file size | 298 "size_human" will also be added with human readable file size |
238 @param stream_object(bool): if True, a stream_object will be used instead of file_obj | 299 @param stream_object(bool): if True, a stream_object will be used instead of file_obj |
239 a stream.FileStreamObject will be used | 300 a stream.FileStreamObject will be used |
240 return (defer.Deferred): True if transfer is accepted | 301 return (defer.Deferred): True if transfer is accepted |
241 """ | 302 """ |
242 cont,ret_value = self.host.trigger.returnPoint("FILE_getDestDir", client, peer_jid, transfer_data, file_data, stream_object) | 303 cont, ret_value = self.host.trigger.returnPoint( |
304 "FILE_getDestDir", client, peer_jid, transfer_data, file_data, stream_object | |
305 ) | |
243 if not cont: | 306 if not cont: |
244 return ret_value | 307 return ret_value |
245 filename = file_data['name'] | 308 filename = file_data["name"] |
246 assert filename and not '/' in filename | 309 assert filename and not "/" in filename |
247 assert PROGRESS_ID_KEY in file_data | 310 assert PROGRESS_ID_KEY in file_data |
248 # human readable size | 311 # human readable size |
249 file_data['size_human'] = u'{:.6n} Mio'.format(float(file_data['size'])/(1024**2)) | 312 file_data["size_human"] = u"{:.6n} Mio".format( |
250 d = xml_tools.deferDialog(self.host, | 313 float(file_data["size"]) / (1024 ** 2) |
314 ) | |
315 d = xml_tools.deferDialog( | |
316 self.host, | |
251 _(CONFIRM).format(peer=peer_jid.full(), **file_data), | 317 _(CONFIRM).format(peer=peer_jid.full(), **file_data), |
252 _(CONFIRM_TITLE), | 318 _(CONFIRM_TITLE), |
253 type_=C.XMLUI_DIALOG_FILE, | 319 type_=C.XMLUI_DIALOG_FILE, |
254 options={C.XMLUI_DATA_FILETYPE: C.XMLUI_DATA_FILETYPE_DIR}, | 320 options={C.XMLUI_DATA_FILETYPE: C.XMLUI_DATA_FILETYPE_DIR}, |
255 action_extra={'meta_from_jid': peer_jid.full(), | 321 action_extra={ |
256 'meta_type': C.META_TYPE_FILE, | 322 "meta_from_jid": peer_jid.full(), |
257 'meta_progress_id': file_data[PROGRESS_ID_KEY] | 323 "meta_type": C.META_TYPE_FILE, |
258 }, | 324 "meta_progress_id": file_data[PROGRESS_ID_KEY], |
325 }, | |
259 security_limit=SECURITY_LIMIT, | 326 security_limit=SECURITY_LIMIT, |
260 profile=client.profile) | 327 profile=client.profile, |
261 d.addCallback(self._gotConfirmation, client, peer_jid, transfer_data, file_data, stream_object) | 328 ) |
329 d.addCallback( | |
330 self._gotConfirmation, | |
331 client, | |
332 peer_jid, | |
333 transfer_data, | |
334 file_data, | |
335 stream_object, | |
336 ) | |
262 return d | 337 return d |