comparison sat_frontends/bridge/pb.py @ 2624:56f94936df1e

code style reformatting using black
author Goffi <goffi@goffi.org>
date Wed, 27 Jun 2018 20:14:46 +0200
parents 973d4551ffae
children 779351da2c13
comparison
equal deleted inserted replaced
2623:49533de4540b 2624:56f94936df1e
1 #!/usr/bin/env python2 1 #!/usr/bin/env python2
2 #-*- coding: utf-8 -*- 2 # -*- coding: utf-8 -*-
3 3
4 # SAT communication bridge 4 # SAT communication bridge
5 # Copyright (C) 2009-2018 Jérôme Poisson (goffi@goffi.org) 5 # Copyright (C) 2009-2018 Jérôme Poisson (goffi@goffi.org)
6 6
7 # This program is free software: you can redistribute it and/or modify 7 # This program is free software: you can redistribute it and/or modify
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 19
20 from sat.core.log import getLogger 20 from sat.core.log import getLogger
21
21 log = getLogger(__name__) 22 log = getLogger(__name__)
22 from sat.core import exceptions 23 from sat.core import exceptions
23 from twisted.spread import pb 24 from twisted.spread import pb
24 from twisted.internet import reactor 25 from twisted.internet import reactor
25 26
26 27
27 class SignalsHandler(pb.Referenceable): 28 class SignalsHandler(pb.Referenceable):
28
29 def __getattr__(self, name): 29 def __getattr__(self, name):
30 if name.startswith("remote_"): 30 if name.startswith("remote_"):
31 log.debug(u"calling an unregistered signal: {name}".format( 31 log.debug(u"calling an unregistered signal: {name}".format(name=name[7:]))
32 name = name[7:]))
33 return lambda *args, **kwargs: None 32 return lambda *args, **kwargs: None
34 33
35 else: 34 else:
36 raise AttributeError(name) 35 raise AttributeError(name)
37 36
41 try: 40 try:
42 self.__getattribute__(self, method_name) 41 self.__getattribute__(self, method_name)
43 except AttributeError: 42 except AttributeError:
44 pass 43 pass
45 else: 44 else:
46 raise exceptions.InternalError(u"{name} signal handler has been registered twice".format( 45 raise exceptions.InternalError(
47 name = method_name)) 46 u"{name} signal handler has been registered twice".format(
47 name=method_name
48 )
49 )
48 setattr(self, method_name, handler) 50 setattr(self, method_name, handler)
49 51
50 52
51 class Bridge(object): 53 class Bridge(object):
52
53 def __init__(self): 54 def __init__(self):
54 self.signals_handler = SignalsHandler() 55 self.signals_handler = SignalsHandler()
55 56
56 def __getattr__(self, name): 57 def __getattr__(self, name):
57 return lambda *args, **kwargs: self.call(name, args, kwargs) 58 return lambda *args, **kwargs: self.call(name, args, kwargs)
79 may contain callback and errback 80 may contain callback and errback
80 """ 81 """
81 callback = errback = None 82 callback = errback = None
82 if kwargs: 83 if kwargs:
83 try: 84 try:
84 callback = kwargs.pop('callback') 85 callback = kwargs.pop("callback")
85 except KeyError: 86 except KeyError:
86 pass 87 pass
87 try: 88 try:
88 errback = kwargs.pop('errback') 89 errback = kwargs.pop("errback")
89 except KeyError: 90 except KeyError:
90 pass 91 pass
91 elif len(args) >= 2 and callable(args[-1]) and callable(args[-2]): 92 elif len(args) >= 2 and callable(args[-1]) and callable(args[-2]):
92 errback = args.pop() 93 errback = args.pop()
93 callback = args.pop() 94 callback = args.pop()
130 d.addCallback(callback) 131 d.addCallback(callback)
131 if errback is None: 132 if errback is None:
132 errback = self._generic_errback 133 errback = self._generic_errback
133 d.addErrback(errback) 134 d.addErrback(errback)
134 135
135 def addContact(self, entity_jid, profile_key="@DEFAULT@", callback=None, errback=None): 136 def addContact(
137 self, entity_jid, profile_key="@DEFAULT@", callback=None, errback=None
138 ):
136 d = self.root.callRemote("addContact", entity_jid, profile_key) 139 d = self.root.callRemote("addContact", entity_jid, profile_key)
137 if callback is not None: 140 if callback is not None:
138 d.addCallback(lambda dummy: callback()) 141 d.addCallback(lambda dummy: callback())
139 if errback is None: 142 if errback is None:
140 errback = self._generic_errback 143 errback = self._generic_errback
146 d.addCallback(lambda dummy: callback()) 149 d.addCallback(lambda dummy: callback())
147 if errback is None: 150 if errback is None:
148 errback = self._generic_errback 151 errback = self._generic_errback
149 d.addErrback(errback) 152 d.addErrback(errback)
150 153
151 def asyncGetParamA(self, name, category, attribute="value", security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None): 154 def asyncGetParamA(
152 d = self.root.callRemote("asyncGetParamA", name, category, attribute, security_limit, profile_key) 155 self,
153 if callback is not None: 156 name,
154 d.addCallback(callback) 157 category,
155 if errback is None: 158 attribute="value",
156 errback = self._generic_errback 159 security_limit=-1,
157 d.addErrback(errback) 160 profile_key="@DEFAULT@",
158 161 callback=None,
159 def asyncGetParamsValuesFromCategory(self, category, security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None): 162 errback=None,
160 d = self.root.callRemote("asyncGetParamsValuesFromCategory", category, security_limit, profile_key) 163 ):
161 if callback is not None: 164 d = self.root.callRemote(
162 d.addCallback(callback) 165 "asyncGetParamA", name, category, attribute, security_limit, profile_key
163 if errback is None: 166 )
164 errback = self._generic_errback 167 if callback is not None:
165 d.addErrback(errback) 168 d.addCallback(callback)
166 169 if errback is None:
167 def connect(self, profile_key="@DEFAULT@", password='', options={}, callback=None, errback=None): 170 errback = self._generic_errback
171 d.addErrback(errback)
172
173 def asyncGetParamsValuesFromCategory(
174 self,
175 category,
176 security_limit=-1,
177 profile_key="@DEFAULT@",
178 callback=None,
179 errback=None,
180 ):
181 d = self.root.callRemote(
182 "asyncGetParamsValuesFromCategory", category, security_limit, profile_key
183 )
184 if callback is not None:
185 d.addCallback(callback)
186 if errback is None:
187 errback = self._generic_errback
188 d.addErrback(errback)
189
190 def connect(
191 self,
192 profile_key="@DEFAULT@",
193 password="",
194 options={},
195 callback=None,
196 errback=None,
197 ):
168 d = self.root.callRemote("connect", profile_key, password, options) 198 d = self.root.callRemote("connect", profile_key, password, options)
169 if callback is not None: 199 if callback is not None:
170 d.addCallback(callback) 200 d.addCallback(callback)
171 if errback is None: 201 if errback is None:
172 errback = self._generic_errback 202 errback = self._generic_errback
173 d.addErrback(errback) 203 d.addErrback(errback)
174 204
175 def delContact(self, entity_jid, profile_key="@DEFAULT@", callback=None, errback=None): 205 def delContact(
206 self, entity_jid, profile_key="@DEFAULT@", callback=None, errback=None
207 ):
176 d = self.root.callRemote("delContact", entity_jid, profile_key) 208 d = self.root.callRemote("delContact", entity_jid, profile_key)
177 if callback is not None: 209 if callback is not None:
178 d.addCallback(lambda dummy: callback()) 210 d.addCallback(lambda dummy: callback())
179 if errback is None: 211 if errback is None:
180 errback = self._generic_errback 212 errback = self._generic_errback
181 d.addErrback(errback) 213 d.addErrback(errback)
182 214
183 def discoFindByFeatures(self, namespaces, identities, bare_jid=False, service=True, roster=True, own_jid=True, local_device=False, profile_key=u"@DEFAULT@", callback=None, errback=None): 215 def discoFindByFeatures(
184 d = self.root.callRemote("discoFindByFeatures", namespaces, identities, bare_jid, service, roster, own_jid, local_device, profile_key) 216 self,
185 if callback is not None: 217 namespaces,
186 d.addCallback(callback) 218 identities,
187 if errback is None: 219 bare_jid=False,
188 errback = self._generic_errback 220 service=True,
189 d.addErrback(errback) 221 roster=True,
190 222 own_jid=True,
191 def discoInfos(self, entity_jid, node=u'', use_cache=True, profile_key=u"@DEFAULT@", callback=None, errback=None): 223 local_device=False,
224 profile_key=u"@DEFAULT@",
225 callback=None,
226 errback=None,
227 ):
228 d = self.root.callRemote(
229 "discoFindByFeatures",
230 namespaces,
231 identities,
232 bare_jid,
233 service,
234 roster,
235 own_jid,
236 local_device,
237 profile_key,
238 )
239 if callback is not None:
240 d.addCallback(callback)
241 if errback is None:
242 errback = self._generic_errback
243 d.addErrback(errback)
244
245 def discoInfos(
246 self,
247 entity_jid,
248 node=u"",
249 use_cache=True,
250 profile_key=u"@DEFAULT@",
251 callback=None,
252 errback=None,
253 ):
192 d = self.root.callRemote("discoInfos", entity_jid, node, use_cache, profile_key) 254 d = self.root.callRemote("discoInfos", entity_jid, node, use_cache, profile_key)
193 if callback is not None: 255 if callback is not None:
194 d.addCallback(callback) 256 d.addCallback(callback)
195 if errback is None: 257 if errback is None:
196 errback = self._generic_errback 258 errback = self._generic_errback
197 d.addErrback(errback) 259 d.addErrback(errback)
198 260
199 def discoItems(self, entity_jid, node=u'', use_cache=True, profile_key=u"@DEFAULT@", callback=None, errback=None): 261 def discoItems(
262 self,
263 entity_jid,
264 node=u"",
265 use_cache=True,
266 profile_key=u"@DEFAULT@",
267 callback=None,
268 errback=None,
269 ):
200 d = self.root.callRemote("discoItems", entity_jid, node, use_cache, profile_key) 270 d = self.root.callRemote("discoItems", entity_jid, node, use_cache, profile_key)
201 if callback is not None: 271 if callback is not None:
202 d.addCallback(callback) 272 d.addCallback(callback)
203 if errback is None: 273 if errback is None:
204 errback = self._generic_errback 274 errback = self._generic_errback
226 d.addCallback(callback) 296 d.addCallback(callback)
227 if errback is None: 297 if errback is None:
228 errback = self._generic_errback 298 errback = self._generic_errback
229 d.addErrback(errback) 299 d.addErrback(errback)
230 300
231 def getContactsFromGroup(self, group, profile_key="@DEFAULT@", callback=None, errback=None): 301 def getContactsFromGroup(
302 self, group, profile_key="@DEFAULT@", callback=None, errback=None
303 ):
232 d = self.root.callRemote("getContactsFromGroup", group, profile_key) 304 d = self.root.callRemote("getContactsFromGroup", group, profile_key)
233 if callback is not None: 305 if callback is not None:
234 d.addCallback(callback) 306 d.addCallback(callback)
235 if errback is None: 307 if errback is None:
236 errback = self._generic_errback 308 errback = self._generic_errback
258 d.addCallback(callback) 330 d.addCallback(callback)
259 if errback is None: 331 if errback is None:
260 errback = self._generic_errback 332 errback = self._generic_errback
261 d.addErrback(errback) 333 d.addErrback(errback)
262 334
263 def getMainResource(self, contact_jid, profile_key="@DEFAULT@", callback=None, errback=None): 335 def getMainResource(
336 self, contact_jid, profile_key="@DEFAULT@", callback=None, errback=None
337 ):
264 d = self.root.callRemote("getMainResource", contact_jid, profile_key) 338 d = self.root.callRemote("getMainResource", contact_jid, profile_key)
265 if callback is not None: 339 if callback is not None:
266 d.addCallback(callback) 340 d.addCallback(callback)
267 if errback is None: 341 if errback is None:
268 errback = self._generic_errback 342 errback = self._generic_errback
269 d.addErrback(errback) 343 d.addErrback(errback)
270 344
271 def getParamA(self, name, category, attribute="value", profile_key="@DEFAULT@", callback=None, errback=None): 345 def getParamA(
346 self,
347 name,
348 category,
349 attribute="value",
350 profile_key="@DEFAULT@",
351 callback=None,
352 errback=None,
353 ):
272 d = self.root.callRemote("getParamA", name, category, attribute, profile_key) 354 d = self.root.callRemote("getParamA", name, category, attribute, profile_key)
273 if callback is not None: 355 if callback is not None:
274 d.addCallback(callback) 356 d.addCallback(callback)
275 if errback is None: 357 if errback is None:
276 errback = self._generic_errback 358 errback = self._generic_errback
282 d.addCallback(callback) 364 d.addCallback(callback)
283 if errback is None: 365 if errback is None:
284 errback = self._generic_errback 366 errback = self._generic_errback
285 d.addErrback(errback) 367 d.addErrback(errback)
286 368
287 def getParamsUI(self, security_limit=-1, app='', profile_key="@DEFAULT@", callback=None, errback=None): 369 def getParamsUI(
370 self,
371 security_limit=-1,
372 app="",
373 profile_key="@DEFAULT@",
374 callback=None,
375 errback=None,
376 ):
288 d = self.root.callRemote("getParamsUI", security_limit, app, profile_key) 377 d = self.root.callRemote("getParamsUI", security_limit, app, profile_key)
289 if callback is not None: 378 if callback is not None:
290 d.addCallback(callback) 379 d.addCallback(callback)
291 if errback is None: 380 if errback is None:
292 errback = self._generic_errback 381 errback = self._generic_errback
322 d.addCallback(callback) 411 d.addCallback(callback)
323 if errback is None: 412 if errback is None:
324 errback = self._generic_errback 413 errback = self._generic_errback
325 d.addErrback(errback) 414 d.addErrback(errback)
326 415
327 def historyGet(self, from_jid, to_jid, limit, between=True, filters='', profile="@NONE@", callback=None, errback=None): 416 def historyGet(
328 d = self.root.callRemote("historyGet", from_jid, to_jid, limit, between, filters, profile) 417 self,
418 from_jid,
419 to_jid,
420 limit,
421 between=True,
422 filters="",
423 profile="@NONE@",
424 callback=None,
425 errback=None,
426 ):
427 d = self.root.callRemote(
428 "historyGet", from_jid, to_jid, limit, between, filters, profile
429 )
329 if callback is not None: 430 if callback is not None:
330 d.addCallback(callback) 431 d.addCallback(callback)
331 if errback is None: 432 if errback is None:
332 errback = self._generic_errback 433 errback = self._generic_errback
333 d.addErrback(errback) 434 d.addErrback(errback)
338 d.addCallback(callback) 439 d.addCallback(callback)
339 if errback is None: 440 if errback is None:
340 errback = self._generic_errback 441 errback = self._generic_errback
341 d.addErrback(errback) 442 d.addErrback(errback)
342 443
343 def launchAction(self, callback_id, data, profile_key="@DEFAULT@", callback=None, errback=None): 444 def launchAction(
445 self, callback_id, data, profile_key="@DEFAULT@", callback=None, errback=None
446 ):
344 d = self.root.callRemote("launchAction", callback_id, data, profile_key) 447 d = self.root.callRemote("launchAction", callback_id, data, profile_key)
345 if callback is not None: 448 if callback is not None:
346 d.addCallback(callback) 449 d.addCallback(callback)
347 if errback is None: 450 if errback is None:
348 errback = self._generic_errback 451 errback = self._generic_errback
362 d.addCallback(callback) 465 d.addCallback(callback)
363 if errback is None: 466 if errback is None:
364 errback = self._generic_errback 467 errback = self._generic_errback
365 d.addErrback(errback) 468 d.addErrback(errback)
366 469
367 def menuLaunch(self, menu_type, path, data, security_limit, profile_key, callback=None, errback=None): 470 def menuLaunch(
368 d = self.root.callRemote("menuLaunch", menu_type, path, data, security_limit, profile_key) 471 self,
472 menu_type,
473 path,
474 data,
475 security_limit,
476 profile_key,
477 callback=None,
478 errback=None,
479 ):
480 d = self.root.callRemote(
481 "menuLaunch", menu_type, path, data, security_limit, profile_key
482 )
369 if callback is not None: 483 if callback is not None:
370 d.addCallback(callback) 484 d.addCallback(callback)
371 if errback is None: 485 if errback is None:
372 errback = self._generic_errback 486 errback = self._generic_errback
373 d.addErrback(errback) 487 d.addErrback(errback)
378 d.addCallback(callback) 492 d.addCallback(callback)
379 if errback is None: 493 if errback is None:
380 errback = self._generic_errback 494 errback = self._generic_errback
381 d.addErrback(errback) 495 d.addErrback(errback)
382 496
383 def messageSend(self, to_jid, message, subject={}, mess_type="auto", extra={}, profile_key="@NONE@", callback=None, errback=None): 497 def messageSend(
384 d = self.root.callRemote("messageSend", to_jid, message, subject, mess_type, extra, profile_key) 498 self,
499 to_jid,
500 message,
501 subject={},
502 mess_type="auto",
503 extra={},
504 profile_key="@NONE@",
505 callback=None,
506 errback=None,
507 ):
508 d = self.root.callRemote(
509 "messageSend", to_jid, message, subject, mess_type, extra, profile_key
510 )
385 if callback is not None: 511 if callback is not None:
386 d.addCallback(lambda dummy: callback()) 512 d.addCallback(lambda dummy: callback())
387 if errback is None: 513 if errback is None:
388 errback = self._generic_errback 514 errback = self._generic_errback
389 d.addErrback(errback) 515 d.addErrback(errback)
394 d.addCallback(callback) 520 d.addCallback(callback)
395 if errback is None: 521 if errback is None:
396 errback = self._generic_errback 522 errback = self._generic_errback
397 d.addErrback(errback) 523 d.addErrback(errback)
398 524
399 def paramsRegisterApp(self, xml, security_limit=-1, app='', callback=None, errback=None): 525 def paramsRegisterApp(
526 self, xml, security_limit=-1, app="", callback=None, errback=None
527 ):
400 d = self.root.callRemote("paramsRegisterApp", xml, security_limit, app) 528 d = self.root.callRemote("paramsRegisterApp", xml, security_limit, app)
401 if callback is not None: 529 if callback is not None:
402 d.addCallback(lambda dummy: callback()) 530 d.addCallback(lambda dummy: callback())
403 if errback is None: 531 if errback is None:
404 errback = self._generic_errback 532 errback = self._generic_errback
405 d.addErrback(errback) 533 d.addErrback(errback)
406 534
407 def profileCreate(self, profile, password='', component='', callback=None, errback=None): 535 def profileCreate(
536 self, profile, password="", component="", callback=None, errback=None
537 ):
408 d = self.root.callRemote("profileCreate", profile, password, component) 538 d = self.root.callRemote("profileCreate", profile, password, component)
409 if callback is not None: 539 if callback is not None:
410 d.addCallback(lambda dummy: callback()) 540 d.addCallback(lambda dummy: callback())
411 if errback is None: 541 if errback is None:
412 errback = self._generic_errback 542 errback = self._generic_errback
413 d.addErrback(errback) 543 d.addErrback(errback)
414 544
415 def profileIsSessionStarted(self, profile_key="@DEFAULT@", callback=None, errback=None): 545 def profileIsSessionStarted(
546 self, profile_key="@DEFAULT@", callback=None, errback=None
547 ):
416 d = self.root.callRemote("profileIsSessionStarted", profile_key) 548 d = self.root.callRemote("profileIsSessionStarted", profile_key)
417 if callback is not None: 549 if callback is not None:
418 d.addCallback(callback) 550 d.addCallback(callback)
419 if errback is None: 551 if errback is None:
420 errback = self._generic_errback 552 errback = self._generic_errback
434 d.addCallback(lambda dummy: callback()) 566 d.addCallback(lambda dummy: callback())
435 if errback is None: 567 if errback is None:
436 errback = self._generic_errback 568 errback = self._generic_errback
437 d.addErrback(errback) 569 d.addErrback(errback)
438 570
439 def profileStartSession(self, password='', profile_key="@DEFAULT@", callback=None, errback=None): 571 def profileStartSession(
572 self, password="", profile_key="@DEFAULT@", callback=None, errback=None
573 ):
440 d = self.root.callRemote("profileStartSession", password, profile_key) 574 d = self.root.callRemote("profileStartSession", password, profile_key)
441 if callback is not None: 575 if callback is not None:
442 d.addCallback(callback) 576 d.addCallback(callback)
443 if errback is None: 577 if errback is None:
444 errback = self._generic_errback 578 errback = self._generic_errback
445 d.addErrback(errback) 579 d.addErrback(errback)
446 580
447 def profilesListGet(self, clients=True, components=False, callback=None, errback=None): 581 def profilesListGet(
582 self, clients=True, components=False, callback=None, errback=None
583 ):
448 d = self.root.callRemote("profilesListGet", clients, components) 584 d = self.root.callRemote("profilesListGet", clients, components)
449 if callback is not None: 585 if callback is not None:
450 d.addCallback(callback) 586 d.addCallback(callback)
451 if errback is None: 587 if errback is None:
452 errback = self._generic_errback 588 errback = self._generic_errback
490 d.addCallback(callback) 626 d.addCallback(callback)
491 if errback is None: 627 if errback is None:
492 errback = self._generic_errback 628 errback = self._generic_errback
493 d.addErrback(errback) 629 d.addErrback(errback)
494 630
495 def setParam(self, name, value, category, security_limit=-1, profile_key="@DEFAULT@", callback=None, errback=None): 631 def setParam(
496 d = self.root.callRemote("setParam", name, value, category, security_limit, profile_key) 632 self,
497 if callback is not None: 633 name,
498 d.addCallback(lambda dummy: callback()) 634 value,
499 if errback is None: 635 category,
500 errback = self._generic_errback 636 security_limit=-1,
501 d.addErrback(errback) 637 profile_key="@DEFAULT@",
502 638 callback=None,
503 def setPresence(self, to_jid='', show='', statuses={}, profile_key="@DEFAULT@", callback=None, errback=None): 639 errback=None,
640 ):
641 d = self.root.callRemote(
642 "setParam", name, value, category, security_limit, profile_key
643 )
644 if callback is not None:
645 d.addCallback(lambda dummy: callback())
646 if errback is None:
647 errback = self._generic_errback
648 d.addErrback(errback)
649
650 def setPresence(
651 self,
652 to_jid="",
653 show="",
654 statuses={},
655 profile_key="@DEFAULT@",
656 callback=None,
657 errback=None,
658 ):
504 d = self.root.callRemote("setPresence", to_jid, show, statuses, profile_key) 659 d = self.root.callRemote("setPresence", to_jid, show, statuses, profile_key)
505 if callback is not None: 660 if callback is not None:
506 d.addCallback(lambda dummy: callback()) 661 d.addCallback(lambda dummy: callback())
507 if errback is None: 662 if errback is None:
508 errback = self._generic_errback 663 errback = self._generic_errback
509 d.addErrback(errback) 664 d.addErrback(errback)
510 665
511 def subscription(self, sub_type, entity, profile_key="@DEFAULT@", callback=None, errback=None): 666 def subscription(
667 self, sub_type, entity, profile_key="@DEFAULT@", callback=None, errback=None
668 ):
512 d = self.root.callRemote("subscription", sub_type, entity, profile_key) 669 d = self.root.callRemote("subscription", sub_type, entity, profile_key)
513 if callback is not None: 670 if callback is not None:
514 d.addCallback(lambda dummy: callback()) 671 d.addCallback(lambda dummy: callback())
515 if errback is None: 672 if errback is None:
516 errback = self._generic_errback 673 errback = self._generic_errback
517 d.addErrback(errback) 674 d.addErrback(errback)
518 675
519 def updateContact(self, entity_jid, name, groups, profile_key="@DEFAULT@", callback=None, errback=None): 676 def updateContact(
677 self,
678 entity_jid,
679 name,
680 groups,
681 profile_key="@DEFAULT@",
682 callback=None,
683 errback=None,
684 ):
520 d = self.root.callRemote("updateContact", entity_jid, name, groups, profile_key) 685 d = self.root.callRemote("updateContact", entity_jid, name, groups, profile_key)
521 if callback is not None: 686 if callback is not None:
522 d.addCallback(lambda dummy: callback()) 687 d.addCallback(lambda dummy: callback())
523 if errback is None: 688 if errback is None:
524 errback = self._generic_errback 689 errback = self._generic_errback