PEP8 formatting updates.

This commit is contained in:
Lance Stout 2012-06-19 01:29:48 -07:00
parent f7a74d960e
commit d92aa05b5c
58 changed files with 324 additions and 289 deletions

View File

@ -16,24 +16,24 @@ class APIWrapper(object):
elif attr == 'settings': elif attr == 'settings':
return self.api.settings[self.name] return self.api.settings[self.name]
elif attr == 'register': elif attr == 'register':
def curried_handler(handler, op, jid=None, node=None, default=False): def partial(handler, op, jid=None, node=None, default=False):
register = getattr(self.api, attr) register = getattr(self.api, attr)
return register(handler, self.name, op, jid, node, default) return register(handler, self.name, op, jid, node, default)
return curried_handler return partial
elif attr == 'register_default': elif attr == 'register_default':
def curried_handler(handler, op, jid=None, node=None): def partial(handler, op, jid=None, node=None):
return getattr(self.api, attr)(handler, self.name, op) return getattr(self.api, attr)(handler, self.name, op)
return curried_handler return partial
elif attr in ('run', 'restore_default', 'unregister'): elif attr in ('run', 'restore_default', 'unregister'):
def curried_handler(*args, **kwargs): def partial(*args, **kwargs):
return getattr(self.api, attr)(self.name, *args, **kwargs) return getattr(self.api, attr)(self.name, *args, **kwargs)
return curried_handler return partial
return None return None
def __getitem__(self, attr): def __getitem__(self, attr):
def curried_handler(jid=None, node=None, ifrom=None, args=None): def partial(jid=None, node=None, ifrom=None, args=None):
return self.api.run(self.name, attr, jid, node, ifrom, args) return self.api.run(self.name, attr, jid, node, ifrom, args)
return curried_handler return partial
class APIRegistry(object): class APIRegistry(object):

View File

@ -73,6 +73,7 @@ class IqTimeout(XMPPError):
#: did not arrive before the timeout expired. #: did not arrive before the timeout expired.
self.iq = iq self.iq = iq
class IqError(XMPPError): class IqError(XMPPError):
""" """

View File

@ -81,7 +81,8 @@ class XEP_0027(BasePlugin):
def _sign_presence(self, stanza): def _sign_presence(self, stanza):
if isinstance(stanza, Presence): if isinstance(stanza, Presence):
if stanza['type'] == 'available' or stanza['type'] in Presence.showtypes: if stanza['type'] == 'available' or \
stanza['type'] in Presence.showtypes:
stanza['signed'] = stanza['status'] stanza['signed'] = stanza['status']
return stanza return stanza

View File

@ -51,6 +51,3 @@ class Encrypted(ElementBase):
if self.xml.text: if self.xml.text:
return xmpp['xep_0027'].decrypt(self.xml.text, parent['to']) return xmpp['xep_0027'].decrypt(self.xml.text, parent['to'])
return None return None

View File

@ -39,5 +39,3 @@ class AuthFeature(ElementBase):
interfaces = set() interfaces = set()
plugin_tag_map = {} plugin_tag_map = {}
plugin_attrib_map = {} plugin_attrib_map = {}

View File

@ -42,6 +42,7 @@ def format_date(time_obj):
time_obj = time_obj.date() time_obj = time_obj.date()
return time_obj.isoformat() return time_obj.isoformat()
def format_time(time_obj): def format_time(time_obj):
""" """
Return a formatted string version of a time object. Return a formatted string version of a time object.
@ -60,6 +61,7 @@ def format_time(time_obj):
return '%sZ' % timestamp return '%sZ' % timestamp
return timestamp return timestamp
def format_datetime(time_obj): def format_datetime(time_obj):
""" """
Return a formatted string version of a datetime object. Return a formatted string version of a datetime object.
@ -76,6 +78,7 @@ def format_datetime(time_obj):
return '%sZ' % timestamp return '%sZ' % timestamp
return timestamp return timestamp
def date(year=None, month=None, day=None, obj=False): def date(year=None, month=None, day=None, obj=False):
""" """
Create a date only timestamp for the given instant. Create a date only timestamp for the given instant.
@ -101,6 +104,7 @@ def date(year=None, month=None, day=None, obj=False):
return value return value
return format_date(value) return format_date(value)
def time(hour=None, min=None, sec=None, micro=None, offset=None, obj=False): def time(hour=None, min=None, sec=None, micro=None, offset=None, obj=False):
""" """
Create a time only timestamp for the given instant. Create a time only timestamp for the given instant.
@ -136,6 +140,7 @@ def time(hour=None, min=None, sec=None, micro=None, offset=None, obj=False):
return value return value
return format_time(value) return format_time(value)
def datetime(year=None, month=None, day=None, hour=None, def datetime(year=None, month=None, day=None, hour=None,
min=None, sec=None, micro=None, offset=None, min=None, sec=None, micro=None, offset=None,
separators=True, obj=False): separators=True, obj=False):

View File

@ -14,5 +14,3 @@ from sleekxmpp.plugins.xep_0084.avatar import XEP_0084
register_plugin(XEP_0084) register_plugin(XEP_0084)

View File

@ -47,28 +47,28 @@ class LegacyError(ElementBase):
interfaces = set(('condition',)) interfaces = set(('condition',))
overrides = ['set_condition'] overrides = ['set_condition']
error_map = {'bad-request': ('modify','400'), error_map = {'bad-request': ('modify', '400'),
'conflict': ('cancel','409'), 'conflict': ('cancel', '409'),
'feature-not-implemented': ('cancel','501'), 'feature-not-implemented': ('cancel', '501'),
'forbidden': ('auth','403'), 'forbidden': ('auth', '403'),
'gone': ('modify','302'), 'gone': ('modify', '302'),
'internal-server-error': ('wait','500'), 'internal-server-error': ('wait', '500'),
'item-not-found': ('cancel','404'), 'item-not-found': ('cancel', '404'),
'jid-malformed': ('modify','400'), 'jid-malformed': ('modify', '400'),
'not-acceptable': ('modify','406'), 'not-acceptable': ('modify', '406'),
'not-allowed': ('cancel','405'), 'not-allowed': ('cancel', '405'),
'not-authorized': ('auth','401'), 'not-authorized': ('auth', '401'),
'payment-required': ('auth','402'), 'payment-required': ('auth', '402'),
'recipient-unavailable': ('wait','404'), 'recipient-unavailable': ('wait', '404'),
'redirect': ('modify','302'), 'redirect': ('modify', '302'),
'registration-required': ('auth','407'), 'registration-required': ('auth', '407'),
'remote-server-not-found': ('cancel','404'), 'remote-server-not-found': ('cancel', '404'),
'remote-server-timeout': ('wait','504'), 'remote-server-timeout': ('wait', '504'),
'resource-constraint': ('wait','500'), 'resource-constraint': ('wait', '500'),
'service-unavailable': ('cancel','503'), 'service-unavailable': ('cancel', '503'),
'subscription-required': ('auth','407'), 'subscription-required': ('auth', '407'),
'undefined-condition': (None,'500'), 'undefined-condition': (None, '500'),
'unexpected-request': ('wait','400')} 'unexpected-request': ('wait', '400')}
def setup(self, xml): def setup(self, xml):
"""Don't create XML for the plugin.""" """Don't create XML for the plugin."""

View File

@ -173,7 +173,8 @@ class XEP_0115(BasePlugin):
form_types.append(f_type) form_types.append(f_type)
deduped_form_types.add(f_type) deduped_form_types.add(f_type)
if len(form_types) != len(deduped_form_types): if len(form_types) != len(deduped_form_types):
log.debug("Duplicated FORM_TYPE values, invalid for caps") log.debug("Duplicated FORM_TYPE values, " + \
"invalid for caps")
return False return False
if len(f_type) > 1: if len(f_type) > 1:
@ -183,7 +184,8 @@ class XEP_0115(BasePlugin):
return False return False
if stanza['fields']['FORM_TYPE']['type'] != 'hidden': if stanza['fields']['FORM_TYPE']['type'] != 'hidden':
log.debug("Field FORM_TYPE type not 'hidden', ignoring form for caps") log.debug("Field FORM_TYPE type not 'hidden', " + \
"ignoring form for caps")
caps.xml.remove(stanza.xml) caps.xml.remove(stanza.xml)
else: else:
log.debug("No FORM_TYPE found, ignoring form for caps") log.debug("No FORM_TYPE found, ignoring form for caps")

View File

@ -82,7 +82,6 @@ class Resumed(StanzaBase):
self._set_attr('h', str(val)) self._set_attr('h', str(val))
class Failed(StanzaBase, Error): class Failed(StanzaBase, Error):
name = 'failed' name = 'failed'
namespace = 'urn:xmpp:sm:3' namespace = 'urn:xmpp:sm:3'

View File

@ -21,7 +21,7 @@ from sleekxmpp.plugins.xep_0198 import stanza
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
MAX_SEQ = 2**32 MAX_SEQ = 2 ** 32
class XEP_0198(BasePlugin): class XEP_0198(BasePlugin):

View File

@ -40,8 +40,12 @@ class XEP_0202(BasePlugin):
# custom function can be supplied which accepts # custom function can be supplied which accepts
# the JID of the entity to query for the time. # the JID of the entity to query for the time.
self.local_time = self.config.get('local_time', None) self.local_time = self.config.get('local_time', None)
def default_local_time(jid):
return xep_0082.datetime(offset=self.tz_offset)
if not self.local_time: if not self.local_time:
self.local_time = lambda x: xep_0082.datetime(offset=self.tz_offset) self.local_time = default_local_time
self.xmpp.registerHandler( self.xmpp.registerHandler(
Callback('Entity Time', Callback('Entity Time',

View File

@ -13,9 +13,7 @@ from sleekxmpp.plugins.xep_0203.stanza import Delay
from sleekxmpp.plugins.xep_0203.delay import XEP_0203 from sleekxmpp.plugins.xep_0203.delay import XEP_0203
register_plugin(XEP_0203) register_plugin(XEP_0203)
# Retain some backwards compatibility # Retain some backwards compatibility
xep_0203 = XEP_0203 xep_0203 = XEP_0203

View File

@ -58,7 +58,6 @@ class XEP_0231(BasePlugin):
self.api.register(self._set_bob, 'set_bob', default=True) self.api.register(self._set_bob, 'set_bob', default=True)
self.api.register(self._del_bob, 'del_bob', default=True) self.api.register(self._del_bob, 'del_bob', default=True)
def set_bob(self, data, mtype, cid=None, max_age=None): def set_bob(self, data, mtype, cid=None, max_age=None):
if cid is None: if cid is None:
cid = 'sha1+%s@bob.xmpp.org' % hashlib.sha1(data).hexdigest() cid = 'sha1+%s@bob.xmpp.org' % hashlib.sha1(data).hexdigest()

View File

@ -78,7 +78,8 @@ class RootStanza(StanzaBase):
self['error']['type'] = 'cancel' self['error']['type'] = 'cancel'
self.send() self.send()
# log the error # log the error
log.exception('Error handling {%s}%s stanza' , self.namespace, self.name) log.exception('Error handling {%s}%s stanza',
self.namespace, self.name)
# Finally raise the exception to a global exception handler # Finally raise the exception to a global exception handler
self.stream.exception(e) self.stream.exception(e)

View File

@ -79,4 +79,3 @@ class StreamError(Error, StanzaBase):
def del_see_other_host(self): def del_see_other_host(self):
self._del_sub('{%s}see-other-host' % self.condition_ns) self._del_sub('{%s}see-other-host' % self.condition_ns)

View File

@ -336,7 +336,6 @@ class SleekTest(unittest.TestCase):
self.xmpp.default_lang = None self.xmpp.default_lang = None
self.xmpp.peer_default_lang = None self.xmpp.peer_default_lang = None
# We will use this to wait for the session_start event # We will use this to wait for the session_start event
# for live connections. # for live connections.
skip_queue = queue.Queue() skip_queue = queue.Queue()

View File

@ -7,11 +7,12 @@ try:
from pyasn1.type.univ import Any, ObjectIdentifier, OctetString from pyasn1.type.univ import Any, ObjectIdentifier, OctetString
from pyasn1.type.char import BMPString, IA5String, UTF8String from pyasn1.type.char import BMPString, IA5String, UTF8String
from pyasn1.type.useful import GeneralizedTime from pyasn1.type.useful import GeneralizedTime
from pyasn1_modules.rfc2459 import Certificate, DirectoryString, SubjectAltName, GeneralNames, GeneralName from pyasn1_modules.rfc2459 import (Certificate, DirectoryString,
SubjectAltName, GeneralNames,
GeneralName)
from pyasn1_modules.rfc2459 import id_ce_subjectAltName as SUBJECT_ALT_NAME from pyasn1_modules.rfc2459 import id_ce_subjectAltName as SUBJECT_ALT_NAME
from pyasn1_modules.rfc2459 import id_at_commonName as COMMON_NAME from pyasn1_modules.rfc2459 import id_at_commonName as COMMON_NAME
XMPP_ADDR = ObjectIdentifier('1.3.6.1.5.5.7.8.5') XMPP_ADDR = ObjectIdentifier('1.3.6.1.5.5.7.8.5')
SRV_NAME = ObjectIdentifier('1.3.6.1.5.5.7.8.7') SRV_NAME = ObjectIdentifier('1.3.6.1.5.5.7.8.7')

View File

@ -99,6 +99,14 @@ def multifactory(stanza, plugin_attrib):
""" """
Returns a ElementBase class for handling reoccuring child stanzas Returns a ElementBase class for handling reoccuring child stanzas
""" """
def plugin_filter(self):
return lambda x: isinstance(x, self._multistanza)
def plugin_lang_filter(self, lang):
return lambda x: isinstance(x, self._multistanza) and \
x['lang'] == lang
class Multi(ElementBase): class Multi(ElementBase):
""" """
Template class for multifactory Template class for multifactory
@ -109,9 +117,9 @@ def multifactory(stanza, plugin_attrib):
def get_multi(self, lang=None): def get_multi(self, lang=None):
parent = self.parent() parent = self.parent()
if not lang or lang == '*': if not lang or lang == '*':
res = filter(lambda sub: isinstance(sub, self._multistanza), parent) res = filter(plugin_filter(self), parent)
else: else:
res = filter(lambda sub: isinstance(sub, self._multistanza) and sub['lang'] == lang, parent) res = filter(plugin_filter(self, lang), parent)
return list(res) return list(res)
def set_multi(self, val, lang=None): def set_multi(self, val, lang=None):
@ -124,9 +132,9 @@ def multifactory(stanza, plugin_attrib):
def del_multi(self, lang=None): def del_multi(self, lang=None):
parent = self.parent() parent = self.parent()
if not lang or lang == '*': if not lang or lang == '*':
res = filter(lambda sub: isinstance(sub, self._multistanza), parent) res = filter(plugin_filter(self), parent)
else: else:
res = filter(lambda sub: isinstance(sub, self._multistanza) and sub['lang'] == lang, parent) res = filter(plugin_filter(self, lang), parent)
res = list(res) res = list(res)
if not res: if not res:
del parent.plugins[(plugin_attrib, None)] del parent.plugins[(plugin_attrib, None)]
@ -253,8 +261,10 @@ class ElementBase(object):
directly from the parent stanza, as shown below, but retrieving directly from the parent stanza, as shown below, but retrieving
information will require all interfaces to be used, as so:: information will require all interfaces to be used, as so::
>>> message['custom'] = 'bar' # Same as using message['custom']['custom'] >>> # Same as using message['custom']['custom']
>>> message['custom']['custom'] # Must use all interfaces >>> message['custom'] = 'bar'
>>> # Must use all interfaces
>>> message['custom']['custom']
'bar' 'bar'
If the plugin sets :attr:`is_extension` to ``True``, then both setting If the plugin sets :attr:`is_extension` to ``True``, then both setting
@ -272,8 +282,8 @@ class ElementBase(object):
""" """
#: The XML tag name of the element, not including any namespace #: The XML tag name of the element, not including any namespace
#: prefixes. For example, an :class:`ElementBase` object for ``<message />`` #: prefixes. For example, an :class:`ElementBase` object for
#: would use ``name = 'message'``. #: ``<message />`` would use ``name = 'message'``.
name = 'stanza' name = 'stanza'
#: The XML namespace for the element. Given ``<foo xmlns="bar" />``, #: The XML namespace for the element. Given ``<foo xmlns="bar" />``,
@ -522,7 +532,9 @@ class ElementBase(object):
if existing_xml is None: if existing_xml is None:
existing_xml = self.xml.find(plugin_class.tag_name()) existing_xml = self.xml.find(plugin_class.tag_name())
if existing_xml is not None and existing_xml.attrib.get('{%s}lang' % XML_NS, '') != lang:
if existing_xml is not None:
if existing_xml.attrib.get('{%s}lang' % XML_NS, '') != lang:
existing_xml = None existing_xml = None
plugin = plugin_class(parent=self, xml=existing_xml) plugin = plugin_class(parent=self, xml=existing_xml)
@ -761,13 +773,20 @@ class ElementBase(object):
else: else:
if attrib in self.sub_interfaces: if attrib in self.sub_interfaces:
if lang == '*': if lang == '*':
return self._set_all_sub_text(attrib, value, lang='*') return self._set_all_sub_text(attrib,
return self._set_sub_text(attrib, text=value, lang=lang) value,
lang='*')
return self._set_sub_text(attrib, text=value,
lang=lang)
elif attrib in self.bool_interfaces: elif attrib in self.bool_interfaces:
if value: if value:
return self._set_sub_text(attrib, '', keep=True, lang=lang) return self._set_sub_text(attrib, '',
keep=True,
lang=lang)
else: else:
return self._set_sub_text(attrib, '', keep=False, lang=lang) return self._set_sub_text(attrib, '',
keep=False,
lang=lang)
else: else:
self._set_attr(attrib, value) self._set_attr(attrib, value)
else: else:
@ -932,7 +951,8 @@ class ElementBase(object):
stanzas = self.xml.findall(name) stanzas = self.xml.findall(name)
if stanzas: if stanzas:
for stanza in stanzas: for stanza in stanzas:
stanza_lang = stanza.attrib.get('{%s}lang' % XML_NS, default_lang) stanza_lang = stanza.attrib.get('{%s}lang' % XML_NS,
default_lang)
if not lang or lang == '*' or stanza_lang == lang: if not lang or lang == '*' or stanza_lang == lang:
results[stanza_lang] = stanza.text results[stanza_lang] = stanza.text
return results return results
@ -996,7 +1016,9 @@ class ElementBase(object):
self._del_sub(name, lang) self._del_sub(name, lang)
for value_lang, value in values.items(): for value_lang, value in values.items():
if not lang or lang == '*' or value_lang == lang: if not lang or lang == '*' or value_lang == lang:
self._set_sub_text(name, text=value, keep=keep, lang=value_lang) self._set_sub_text(name, text=value,
keep=keep,
lang=value_lang)
def _del_sub(self, name, all=False, lang=None): def _del_sub(self, name, all=False, lang=None):
"""Remove sub elements that match the given name or XPath. """Remove sub elements that match the given name or XPath.
@ -1032,7 +1054,9 @@ class ElementBase(object):
not element.getchildren(): not element.getchildren():
# Only delete the originally requested elements, and # Only delete the originally requested elements, and
# any parent elements that have become empty. # any parent elements that have become empty.
if lang == '*' or element.attrib.get('{%s}lang' % XML_NS, default_lang) == lang: elem_lang = element.attrib.get('{%s}lang' % XML_NS,
default_lang)
if lang == '*' or elem_lang == lang:
parent.remove(element) parent.remove(element)
if not all: if not all:
# If we don't want to delete elements up the tree, stop # If we don't want to delete elements up the tree, stop

View File

@ -417,12 +417,12 @@ class XMLStream(object):
if use_tls is not None: if use_tls is not None:
self.use_tls = use_tls self.use_tls = use_tls
# Repeatedly attempt to connect until a successful connection # Repeatedly attempt to connect until a successful connection
# is established. # is established.
attempts = self.reconnect_max_attempts attempts = self.reconnect_max_attempts
connected = self.state.transition('disconnected', 'connected', connected = self.state.transition('disconnected', 'connected',
func=self._connect, args=(reattempt,)) func=self._connect,
args=(reattempt,))
while reattempt and not connected and not self.stop.is_set(): while reattempt and not connected and not self.stop.is_set():
connected = self.state.transition('disconnected', 'connected', connected = self.state.transition('disconnected', 'connected',
func=self._connect) func=self._connect)
@ -520,7 +520,8 @@ class XMLStream(object):
except (Socket.error, ssl.SSLError): except (Socket.error, ssl.SSLError):
log.error('CERT: Invalid certificate trust chain.') log.error('CERT: Invalid certificate trust chain.')
if not self.event_handled('ssl_invalid_chain'): if not self.event_handled('ssl_invalid_chain'):
self.disconnect(self.auto_reconnect, send_close=False) self.disconnect(self.auto_reconnect,
send_close=False)
else: else:
self.event('ssl_invalid_chain', direct=True) self.event('ssl_invalid_chain', direct=True)
return False return False
@ -537,7 +538,9 @@ class XMLStream(object):
if not self.event_handled('ssl_invalid_cert'): if not self.event_handled('ssl_invalid_cert'):
self.disconnect(send_close=False) self.disconnect(send_close=False)
else: else:
self.event('ssl_invalid_cert', pem_cert, direct=True) self.event('ssl_invalid_cert',
pem_cert,
direct=True)
self.set_socket(self.socket, ignore=True) self.set_socket(self.socket, ignore=True)
#this event is where you should set your application state #this event is where you should set your application state
@ -714,7 +717,9 @@ class XMLStream(object):
log.debug("connecting...") log.debug("connecting...")
connected = self.state.transition('disconnected', 'connected', connected = self.state.transition('disconnected', 'connected',
wait=2.0, func=self._connect, args=(reattempt,)) wait=2.0,
func=self._connect,
args=(reattempt,))
while reattempt and not connected and not self.stop.is_set(): while reattempt and not connected and not self.stop.is_set():
connected = self.state.transition('disconnected', 'connected', connected = self.state.transition('disconnected', 'connected',
wait=2.0, func=self._connect) wait=2.0, func=self._connect)
@ -877,8 +882,8 @@ class XMLStream(object):
self.schedule('Whitespace Keepalive', self.schedule('Whitespace Keepalive',
self.whitespace_keepalive_interval, self.whitespace_keepalive_interval,
self.send_raw, self.send_raw,
args = (' ',), args=(' ',),
kwargs = {'now': True}, kwargs={'now': True},
repeat=True) repeat=True)
def _remove_schedules(self, event): def _remove_schedules(self, event):
@ -979,7 +984,8 @@ class XMLStream(object):
"""Add a stream event handler that will be executed when a matching """Add a stream event handler that will be executed when a matching
stanza is received. stanza is received.
:param handler: The :class:`~sleekxmpp.xmlstream.handler.base.BaseHandler` :param handler:
The :class:`~sleekxmpp.xmlstream.handler.base.BaseHandler`
derived object to execute. derived object to execute.
""" """
if handler.stream is None: if handler.stream is None:
@ -1011,7 +1017,8 @@ class XMLStream(object):
resolver = default_resolver() resolver = default_resolver()
self.configure_dns(resolver, domain=domain, port=port) self.configure_dns(resolver, domain=domain, port=port)
return resolve(domain, port, service=self.dns_service, resolver=resolver) return resolve(domain, port, service=self.dns_service,
resolver=resolver)
def pick_dns_answer(self, domain, port=None): def pick_dns_answer(self, domain, port=None):
"""Pick a server and port from DNS answers. """Pick a server and port from DNS answers.
@ -1240,14 +1247,15 @@ class XMLStream(object):
count += 1 count += 1
except ssl.SSLError as serr: except ssl.SSLError as serr:
if tries >= self.ssl_retry_max: if tries >= self.ssl_retry_max:
log.debug('SSL error - max retries reached') log.debug('SSL error: max retries reached')
self.exception(serr) self.exception(serr)
log.warning("Failed to send %s", data) log.warning("Failed to send %s", data)
if reconnect is None: if reconnect is None:
reconnect = self.auto_reconnect reconnect = self.auto_reconnect
if not self.stop.is_set(): if not self.stop.is_set():
self.disconnect(reconnect, send_close=False) self.disconnect(reconnect,
log.warning('SSL write error - reattempting') send_close=False)
log.warning('SSL write error: retrying')
if not self.stop.is_set(): if not self.stop.is_set():
time.sleep(self.ssl_retry_delay) time.sleep(self.ssl_retry_delay)
tries += 1 tries += 1
@ -1656,12 +1664,13 @@ class XMLStream(object):
count += 1 count += 1
except ssl.SSLError as serr: except ssl.SSLError as serr:
if tries >= self.ssl_retry_max: if tries >= self.ssl_retry_max:
log.debug('SSL error - max retries reached') log.debug('SSL error: max retries reached')
self.exception(serr) self.exception(serr)
log.warning("Failed to send %s", data) log.warning("Failed to send %s", data)
if not self.stop.is_set(): if not self.stop.is_set():
self.disconnect(self.auto_reconnect, send_close=False) self.disconnect(self.auto_reconnect,
log.warning('SSL write error - reattempting') send_close=False)
log.warning('SSL write error: retrying')
if not self.stop.is_set(): if not self.stop.is_set():
time.sleep(self.ssl_retry_delay) time.sleep(self.ssl_retry_delay)
tries += 1 tries += 1