PEP8 formatting updates.
This commit is contained in:
parent
f7a74d960e
commit
d92aa05b5c
@ -16,24 +16,24 @@ class APIWrapper(object):
|
||||
elif attr == 'settings':
|
||||
return self.api.settings[self.name]
|
||||
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)
|
||||
return register(handler, self.name, op, jid, node, default)
|
||||
return curried_handler
|
||||
return partial
|
||||
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 curried_handler
|
||||
return partial
|
||||
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 curried_handler
|
||||
return partial
|
||||
return None
|
||||
|
||||
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 curried_handler
|
||||
return partial
|
||||
|
||||
|
||||
class APIRegistry(object):
|
||||
@ -42,7 +42,7 @@ class APIRegistry(object):
|
||||
self._handlers = {}
|
||||
self._handler_defaults = {}
|
||||
self.xmpp = xmpp
|
||||
self.settings = {}
|
||||
self.settings = {}
|
||||
|
||||
def _setup(self, ctype, op):
|
||||
"""Initialize the API callback dictionaries.
|
||||
@ -138,8 +138,8 @@ class APIRegistry(object):
|
||||
"""Register an API callback, with JID+node specificity.
|
||||
|
||||
The API callback can later be executed based on the
|
||||
specificity of the provided JID+node combination.
|
||||
|
||||
specificity of the provided JID+node combination.
|
||||
|
||||
See :meth:`~ApiRegistry.run` for more details.
|
||||
|
||||
:param string ctype: The name of the API to use.
|
||||
|
@ -67,7 +67,7 @@ class BaseXMPP(XMLStream):
|
||||
#: An identifier for the stream as given by the server.
|
||||
self.stream_id = None
|
||||
|
||||
#: The JabberID (JID) used by this connection.
|
||||
#: The JabberID (JID) used by this connection.
|
||||
self.boundjid = JID(jid)
|
||||
self._expected_server_name = self.boundjid.host
|
||||
|
||||
@ -103,7 +103,7 @@ class BaseXMPP(XMLStream):
|
||||
#: The API registry is a way to process callbacks based on
|
||||
#: JID+node combinations. Each callback in the registry is
|
||||
#: marked with:
|
||||
#:
|
||||
#:
|
||||
#: - An API name, e.g. xep_0030
|
||||
#: - The name of an action, e.g. get_info
|
||||
#: - The JID that will be affected
|
||||
@ -202,7 +202,7 @@ class BaseXMPP(XMLStream):
|
||||
Defaults to ``True``. This does **not** mean that no
|
||||
threads are used at all if ``threaded=False``.
|
||||
|
||||
Regardless of these threading options, these threads will
|
||||
Regardless of these threading options, these threads will
|
||||
always exist:
|
||||
|
||||
- The event queue processor
|
||||
@ -294,11 +294,11 @@ class BaseXMPP(XMLStream):
|
||||
|
||||
:param id: An ideally unique ID value for this stanza thread.
|
||||
Defaults to 0.
|
||||
:param ifrom: The from :class:`~sleekxmpp.xmlstream.jid.JID`
|
||||
:param ifrom: The from :class:`~sleekxmpp.xmlstream.jid.JID`
|
||||
to use for this stanza.
|
||||
:param ito: The destination :class:`~sleekxmpp.xmlstream.jid.JID`
|
||||
for this stanza.
|
||||
:param itype: The :class:`~sleekxmpp.stanza.iq.Iq`'s type,
|
||||
:param itype: The :class:`~sleekxmpp.stanza.iq.Iq`'s type,
|
||||
one of: ``'get'``, ``'set'``, ``'result'``,
|
||||
or ``'error'``.
|
||||
:param iquery: Optional namespace for adding a query element.
|
||||
@ -336,7 +336,7 @@ class BaseXMPP(XMLStream):
|
||||
|
||||
def make_iq_result(self, id=None, ito=None, ifrom=None, iq=None):
|
||||
"""
|
||||
Create an :class:`~sleekxmpp.stanza.iq.Iq` stanza of type
|
||||
Create an :class:`~sleekxmpp.stanza.iq.Iq` stanza of type
|
||||
``'result'`` with the given ID value.
|
||||
|
||||
:param id: An ideally unique ID value. May use :meth:`new_id()`.
|
||||
@ -366,10 +366,10 @@ class BaseXMPP(XMLStream):
|
||||
Optionally, a substanza may be given to use as the
|
||||
stanza's payload.
|
||||
|
||||
:param sub: Either an
|
||||
:param sub: Either an
|
||||
:class:`~sleekxmpp.xmlstream.stanzabase.ElementBase`
|
||||
stanza object or an
|
||||
:class:`~xml.etree.ElementTree.Element` XML object
|
||||
:class:`~xml.etree.ElementTree.Element` XML object
|
||||
to use as the :class:`~sleekxmpp.stanza.iq.Iq`'s payload.
|
||||
:param ito: The destination :class:`~sleekxmpp.xmlstream.jid.JID`
|
||||
for this stanza.
|
||||
@ -396,9 +396,9 @@ class BaseXMPP(XMLStream):
|
||||
Create an :class:`~sleekxmpp.stanza.iq.Iq` stanza of type ``'error'``.
|
||||
|
||||
:param id: An ideally unique ID value. May use :meth:`new_id()`.
|
||||
:param type: The type of the error, such as ``'cancel'`` or
|
||||
:param type: The type of the error, such as ``'cancel'`` or
|
||||
``'modify'``. Defaults to ``'cancel'``.
|
||||
:param condition: The error condition. Defaults to
|
||||
:param condition: The error condition. Defaults to
|
||||
``'feature-not-implemented'``.
|
||||
:param text: A message describing the cause of the error.
|
||||
:param ito: The destination :class:`~sleekxmpp.xmlstream.jid.JID`
|
||||
@ -422,7 +422,7 @@ class BaseXMPP(XMLStream):
|
||||
|
||||
def make_iq_query(self, iq=None, xmlns='', ito=None, ifrom=None):
|
||||
"""
|
||||
Create or modify an :class:`~sleekxmpp.stanza.iq.Iq` stanza
|
||||
Create or modify an :class:`~sleekxmpp.stanza.iq.Iq` stanza
|
||||
to use the given query namespace.
|
||||
|
||||
:param iq: Optionally use an existing stanza instead
|
||||
@ -455,7 +455,7 @@ class BaseXMPP(XMLStream):
|
||||
def make_message(self, mto, mbody=None, msubject=None, mtype=None,
|
||||
mhtml=None, mfrom=None, mnick=None):
|
||||
"""
|
||||
Create and initialize a new
|
||||
Create and initialize a new
|
||||
:class:`~sleekxmpp.stanza.message.Message` stanza.
|
||||
|
||||
:param mto: The recipient of the message.
|
||||
@ -481,7 +481,7 @@ class BaseXMPP(XMLStream):
|
||||
def make_presence(self, pshow=None, pstatus=None, ppriority=None,
|
||||
pto=None, ptype=None, pfrom=None, pnick=None):
|
||||
"""
|
||||
Create and initialize a new
|
||||
Create and initialize a new
|
||||
:class:`~sleekxmpp.stanza.presence.Presence` stanza.
|
||||
|
||||
:param pshow: The presence's show value.
|
||||
@ -505,7 +505,7 @@ class BaseXMPP(XMLStream):
|
||||
def send_message(self, mto, mbody, msubject=None, mtype=None,
|
||||
mhtml=None, mfrom=None, mnick=None):
|
||||
"""
|
||||
Create, initialize, and send a new
|
||||
Create, initialize, and send a new
|
||||
:class:`~sleekxmpp.stanza.message.Message` stanza.
|
||||
|
||||
:param mto: The recipient of the message.
|
||||
@ -525,7 +525,7 @@ class BaseXMPP(XMLStream):
|
||||
def send_presence(self, pshow=None, pstatus=None, ppriority=None,
|
||||
pto=None, pfrom=None, ptype=None, pnick=None):
|
||||
"""
|
||||
Create, initialize, and send a new
|
||||
Create, initialize, and send a new
|
||||
:class:`~sleekxmpp.stanza.presence.Presence` stanza.
|
||||
|
||||
:param pshow: The presence's show value.
|
||||
@ -536,13 +536,13 @@ class BaseXMPP(XMLStream):
|
||||
:param pfrom: The sender of the presence.
|
||||
:param pnick: Optional nickname of the presence's sender.
|
||||
"""
|
||||
self.make_presence(pshow, pstatus, ppriority, pto,
|
||||
self.make_presence(pshow, pstatus, ppriority, pto,
|
||||
ptype, pfrom, pnick).send()
|
||||
|
||||
def send_presence_subscription(self, pto, pfrom=None,
|
||||
ptype='subscribe', pnick=None):
|
||||
"""
|
||||
Create, initialize, and send a new
|
||||
Create, initialize, and send a new
|
||||
:class:`~sleekxmpp.stanza.presence.Presence` stanza of
|
||||
type ``'subscribe'``.
|
||||
|
||||
@ -743,7 +743,7 @@ class BaseXMPP(XMLStream):
|
||||
return
|
||||
|
||||
def exception(self, exception):
|
||||
"""Process any uncaught exceptions, notably
|
||||
"""Process any uncaught exceptions, notably
|
||||
:class:`~sleekxmpp.exceptions.IqError` and
|
||||
:class:`~sleekxmpp.exceptions.IqTimeout` exceptions.
|
||||
|
||||
|
@ -54,13 +54,13 @@ class ClientXMPP(BaseXMPP):
|
||||
:param password: The password for the XMPP user account.
|
||||
:param ssl: **Deprecated.**
|
||||
:param plugin_config: A dictionary of plugin configurations.
|
||||
:param plugin_whitelist: A list of approved plugins that
|
||||
will be loaded when calling
|
||||
:param plugin_whitelist: A list of approved plugins that
|
||||
will be loaded when calling
|
||||
:meth:`~sleekxmpp.basexmpp.BaseXMPP.register_plugins()`.
|
||||
:param escape_quotes: **Deprecated.**
|
||||
"""
|
||||
|
||||
def __init__(self, jid, password, plugin_config={}, plugin_whitelist=[],
|
||||
def __init__(self, jid, password, plugin_config={}, plugin_whitelist=[],
|
||||
escape_quotes=True, sasl_mech=None, lang='en'):
|
||||
BaseXMPP.__init__(self, jid, 'jabber:client')
|
||||
|
||||
@ -189,7 +189,7 @@ class ClientXMPP(BaseXMPP):
|
||||
occurs. Defaults to ``True``.
|
||||
:param timeout: The length of time (in seconds) to wait
|
||||
for a response before continuing if blocking
|
||||
is used. Defaults to
|
||||
is used. Defaults to
|
||||
:attr:`~sleekxmpp.xmlstream.xmlstream.XMLStream.response_timeout`.
|
||||
:param callback: Optional reference to a stream handler function.
|
||||
Will be executed when the roster is received.
|
||||
@ -200,7 +200,7 @@ class ClientXMPP(BaseXMPP):
|
||||
|
||||
def del_roster_item(self, jid):
|
||||
"""Remove an item from the roster.
|
||||
|
||||
|
||||
This is done by setting its subscription status to ``'remove'``.
|
||||
|
||||
:param jid: The JID of the item to remove.
|
||||
@ -215,7 +215,7 @@ class ClientXMPP(BaseXMPP):
|
||||
Defaults to ``True``.
|
||||
:param timeout: The length of time (in seconds) to wait for a response
|
||||
before continuing if blocking is used.
|
||||
Defaults to
|
||||
Defaults to
|
||||
:attr:`~sleekxmpp.xmlstream.xmlstream.XMLStream.response_timeout`.
|
||||
:param callback: Optional reference to a stream handler function. Will
|
||||
be executed when the roster is received.
|
||||
@ -233,7 +233,7 @@ class ClientXMPP(BaseXMPP):
|
||||
response = iq.send(block, timeout, callback)
|
||||
self.event('roster_received', response)
|
||||
|
||||
if block:
|
||||
if block:
|
||||
self._handle_roster(response)
|
||||
return response
|
||||
|
||||
@ -279,7 +279,7 @@ class ClientXMPP(BaseXMPP):
|
||||
roster[jid]['pending_out'] = (item['ask'] == 'subscribe')
|
||||
|
||||
roster[jid].save(remove=(item['subscription'] == 'remove'))
|
||||
|
||||
|
||||
self.event("roster_update", iq)
|
||||
if iq['type'] == 'set':
|
||||
resp = self.Iq(stype='result',
|
||||
|
@ -40,8 +40,8 @@ class ComponentXMPP(BaseXMPP):
|
||||
:param host: The server accepting the component.
|
||||
:param port: The port used to connect to the server.
|
||||
:param plugin_config: A dictionary of plugin configurations.
|
||||
:param plugin_whitelist: A list of approved plugins that
|
||||
will be loaded when calling
|
||||
:param plugin_whitelist: A list of approved plugins that
|
||||
will be loaded when calling
|
||||
:meth:`~sleekxmpp.basexmpp.BaseXMPP.register_plugins()`.
|
||||
:param use_jc_ns: Indicates if the ``'jabber:client'`` namespace
|
||||
should be used instead of the standard
|
||||
@ -78,7 +78,7 @@ class ComponentXMPP(BaseXMPP):
|
||||
self.add_event_handler('presence_probe',
|
||||
self._handle_probe)
|
||||
|
||||
def connect(self, host=None, port=None, use_ssl=False,
|
||||
def connect(self, host=None, port=None, use_ssl=False,
|
||||
use_tls=False, reattempt=True):
|
||||
"""Connect to the server.
|
||||
|
||||
|
@ -69,10 +69,11 @@ class IqTimeout(XMPPError):
|
||||
condition='remote-server-timeout',
|
||||
etype='cancel')
|
||||
|
||||
#: The :class:`~sleekxmpp.stanza.iq.Iq` stanza whose response
|
||||
#: The :class:`~sleekxmpp.stanza.iq.Iq` stanza whose response
|
||||
#: did not arrive before the timeout expired.
|
||||
self.iq = iq
|
||||
|
||||
|
||||
class IqError(XMPPError):
|
||||
|
||||
"""
|
||||
|
@ -7,9 +7,9 @@
|
||||
"""
|
||||
|
||||
__all__ = [
|
||||
'feature_starttls',
|
||||
'feature_mechanisms',
|
||||
'feature_bind',
|
||||
'feature_starttls',
|
||||
'feature_mechanisms',
|
||||
'feature_bind',
|
||||
'feature_session',
|
||||
'feature_rosterver'
|
||||
]
|
||||
|
@ -23,7 +23,7 @@ class Auth(StanzaBase):
|
||||
interfaces = set(('mechanism', 'value'))
|
||||
plugin_attrib = name
|
||||
|
||||
#: Some SASL mechs require sending values as is,
|
||||
#: Some SASL mechs require sending values as is,
|
||||
#: without converting base64.
|
||||
plain_mechs = set(['X-MESSENGER-OAUTH2'])
|
||||
|
||||
|
@ -31,10 +31,10 @@ log = logging.getLogger(__name__)
|
||||
PLUGIN_REGISTRY = {}
|
||||
|
||||
#: In order to do cascading plugin disabling, reverse dependencies
|
||||
#: must be tracked.
|
||||
#: must be tracked.
|
||||
PLUGIN_DEPENDENTS = {}
|
||||
|
||||
#: Only allow one thread to manipulate the plugin registry at a time.
|
||||
#: Only allow one thread to manipulate the plugin registry at a time.
|
||||
REGISTRY_LOCK = threading.RLock()
|
||||
|
||||
|
||||
@ -75,7 +75,7 @@ def load_plugin(name, module=None):
|
||||
plugins are in packages matching their name,
|
||||
even though the plugin class name does not
|
||||
have to match.
|
||||
:param str module: The name of the base module to search
|
||||
:param str module: The name of the base module to search
|
||||
for the plugin.
|
||||
"""
|
||||
try:
|
||||
@ -107,7 +107,7 @@ def load_plugin(name, module=None):
|
||||
log.exception("Unable to load plugin: %s", name)
|
||||
|
||||
|
||||
class PluginManager(object):
|
||||
class PluginManager(object):
|
||||
def __init__(self, xmpp, config=None):
|
||||
#: We will track all enabled plugins in a set so that we
|
||||
#: can enable plugins in batches and pull in dependencies
|
||||
@ -181,7 +181,7 @@ class PluginManager(object):
|
||||
|
||||
def enable_all(self, names=None, config=None):
|
||||
"""Enable all registered plugins.
|
||||
|
||||
|
||||
:param list names: A list of plugin names to enable. If
|
||||
none are provided, all registered plugins
|
||||
will be enabled.
|
||||
@ -292,7 +292,7 @@ class BasePlugin(object):
|
||||
|
||||
def post_init(self):
|
||||
"""Initialize any cross-plugin state.
|
||||
|
||||
|
||||
Only needed if the plugin has circular dependencies.
|
||||
"""
|
||||
pass
|
||||
|
@ -81,7 +81,8 @@ class XEP_0027(BasePlugin):
|
||||
|
||||
def _sign_presence(self, stanza):
|
||||
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']
|
||||
return stanza
|
||||
|
||||
|
@ -51,6 +51,3 @@ class Encrypted(ElementBase):
|
||||
if self.xml.text:
|
||||
return xmpp['xep_0027'].decrypt(self.xml.text, parent['to'])
|
||||
return None
|
||||
|
||||
|
||||
|
||||
|
@ -339,8 +339,8 @@ class XEP_0030(BasePlugin):
|
||||
if local:
|
||||
log.debug("Looking up local disco#info data " + \
|
||||
"for %s, node %s.", jid, node)
|
||||
info = self.api['get_info'](jid, node,
|
||||
kwargs.get('ifrom', None),
|
||||
info = self.api['get_info'](jid, node,
|
||||
kwargs.get('ifrom', None),
|
||||
kwargs)
|
||||
info = self._fix_default_info(info)
|
||||
return self._wrap(kwargs.get('ifrom', None), jid, info)
|
||||
@ -348,8 +348,8 @@ class XEP_0030(BasePlugin):
|
||||
if cached:
|
||||
log.debug("Looking up cached disco#info data " + \
|
||||
"for %s, node %s.", jid, node)
|
||||
info = self.api['get_cached_info'](jid, node,
|
||||
kwargs.get('ifrom', None),
|
||||
info = self.api['get_cached_info'](jid, node,
|
||||
kwargs.get('ifrom', None),
|
||||
kwargs)
|
||||
if info is not None:
|
||||
return self._wrap(kwargs.get('ifrom', None), jid, info)
|
||||
@ -405,8 +405,8 @@ class XEP_0030(BasePlugin):
|
||||
Otherwise the parameter is ignored.
|
||||
"""
|
||||
if local or jid is None:
|
||||
items = self.api['get_items'](jid, node,
|
||||
kwargs.get('ifrom', None),
|
||||
items = self.api['get_items'](jid, node,
|
||||
kwargs.get('ifrom', None),
|
||||
kwargs)
|
||||
return self._wrap(kwargs.get('ifrom', None), jid, items)
|
||||
|
||||
|
@ -16,7 +16,7 @@ class Addresses(ElementBase):
|
||||
plugin_attrib = 'addresses'
|
||||
interfaces = set()
|
||||
|
||||
def add_address(self, atype='to', jid='', node='', uri='',
|
||||
def add_address(self, atype='to', jid='', node='', uri='',
|
||||
desc='', delivered=False):
|
||||
addr = Address(parent=self)
|
||||
addr['type'] = atype
|
||||
@ -116,7 +116,7 @@ for atype in ('all', 'bcc', 'cc', 'noreply', 'replyroom', 'replyto', 'to'):
|
||||
setattr(Addresses, "get_%s" % atype, get_multi)
|
||||
setattr(Addresses, "set_%s" % atype, set_multi)
|
||||
setattr(Addresses, "del_%s" % atype, del_multi)
|
||||
|
||||
|
||||
# To retain backwards compatibility:
|
||||
setattr(Addresses, "get%s" % atype.title(), get_multi)
|
||||
setattr(Addresses, "set%s" % atype.title(), set_multi)
|
||||
|
@ -106,8 +106,8 @@ class Address(ElementBase):
|
||||
namespace = 'vcard-temp'
|
||||
plugin_attrib = name
|
||||
plugin_multi_attrib = 'addresses'
|
||||
interfaces = set(['HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM', 'INTL',
|
||||
'PREF', 'POBOX', 'EXTADD', 'STREET', 'LOCALITY',
|
||||
interfaces = set(['HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM', 'INTL',
|
||||
'PREF', 'POBOX', 'EXTADD', 'STREET', 'LOCALITY',
|
||||
'REGION', 'PCODE', 'CTRY'])
|
||||
sub_interfaces = set(['POBOX', 'EXTADD', 'STREET', 'LOCALITY',
|
||||
'REGION', 'PCODE', 'CTRY'])
|
||||
@ -123,8 +123,8 @@ class Telephone(ElementBase):
|
||||
'CELL', 'VIDEO', 'BBS', 'MODEM', 'ISDN', 'PCS',
|
||||
'PREF', 'NUMBER'])
|
||||
sub_interfaces = set(['NUMBER'])
|
||||
bool_interfaces = set(['HOME', 'WORK', 'VOICE', 'FAX', 'PAGER',
|
||||
'MSG', 'CELL', 'VIDEO', 'BBS', 'MODEM',
|
||||
bool_interfaces = set(['HOME', 'WORK', 'VOICE', 'FAX', 'PAGER',
|
||||
'MSG', 'CELL', 'VIDEO', 'BBS', 'MODEM',
|
||||
'ISDN', 'PCS', 'PREF'])
|
||||
|
||||
def setup(self, xml=None):
|
||||
@ -145,7 +145,7 @@ class Label(ElementBase):
|
||||
plugin_multi_attrib = 'labels'
|
||||
interfaces = set(['HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM', 'INT',
|
||||
'PREF', 'lines'])
|
||||
bool_interfaces = set(['HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM',
|
||||
bool_interfaces = set(['HOME', 'WORK', 'POSTAL', 'PARCEL', 'DOM',
|
||||
'INT', 'PREF'])
|
||||
|
||||
def add_line(self, value):
|
||||
@ -515,7 +515,7 @@ class TimeZone(ElementBase):
|
||||
is_extension = True
|
||||
|
||||
def set_tz(self, value):
|
||||
time = xep_0082.time(offset=value)
|
||||
time = xep_0082.time(offset=value)
|
||||
if time[-1] == 'Z':
|
||||
self.xml.text = 'Z'
|
||||
else:
|
||||
|
@ -53,7 +53,7 @@ class XEP_0054(BasePlugin):
|
||||
def make_vcard(self):
|
||||
return VCardTemp()
|
||||
|
||||
def get_vcard(self, jid=None, ifrom=None, local=False, cached=False,
|
||||
def get_vcard(self, jid=None, ifrom=None, local=False, cached=False,
|
||||
block=True, callback=None, timeout=None):
|
||||
if self.xmpp.is_component and jid.domain == self.xmpp.boundjid.domain:
|
||||
local = True
|
||||
@ -84,12 +84,12 @@ class XEP_0054(BasePlugin):
|
||||
iq.enable('vcard_temp')
|
||||
|
||||
vcard = iq.send(block=block, callback=callback, timeout=timeout)
|
||||
|
||||
|
||||
if block:
|
||||
self.api['set_vcard'](vcard['from'], args=vcard['vcard_temp'])
|
||||
return vcard
|
||||
|
||||
def publish_vcard(self, vcard=None, jid=None, block=True, ifrom=None,
|
||||
def publish_vcard(self, vcard=None, jid=None, block=True, ifrom=None,
|
||||
callback=None, timeout=None):
|
||||
if self.xmpp.is_component:
|
||||
self.api['set_vcard'](jid, None, ifrom, vcard)
|
||||
|
@ -39,5 +39,3 @@ class AuthFeature(ElementBase):
|
||||
interfaces = set()
|
||||
plugin_tag_map = {}
|
||||
plugin_attrib_map = {}
|
||||
|
||||
|
||||
|
@ -40,33 +40,33 @@ class XEP_0080(BasePlugin):
|
||||
accuracy -- Horizontal GPS error in meters.
|
||||
alt -- Altitude in meters above or below sea level.
|
||||
area -- A named area such as a campus or neighborhood.
|
||||
bearing -- GPS bearing (direction in which the entity is
|
||||
heading to reach its next waypoint), measured in
|
||||
bearing -- GPS bearing (direction in which the entity is
|
||||
heading to reach its next waypoint), measured in
|
||||
decimal degrees relative to true north.
|
||||
building -- A specific building on a street or in an area.
|
||||
country -- The nation where the user is located.
|
||||
countrycode -- The ISO 3166 two-letter country code.
|
||||
datum -- GPS datum.
|
||||
description -- A natural-language name for or description of
|
||||
description -- A natural-language name for or description of
|
||||
the location.
|
||||
error -- Horizontal GPS error in arc minutes. Obsoleted by
|
||||
the accuracy parameter.
|
||||
floor -- A particular floor in a building.
|
||||
lat -- Latitude in decimal degrees North.
|
||||
locality -- A locality within the administrative region, such
|
||||
locality -- A locality within the administrative region, such
|
||||
as a town or city.
|
||||
lon -- Longitude in decimal degrees East.
|
||||
postalcode -- A code used for postal delivery.
|
||||
region -- An administrative region of the nation, such
|
||||
region -- An administrative region of the nation, such
|
||||
as a state or province.
|
||||
room -- A particular room in a building.
|
||||
speed -- The speed at which the entity is moving,
|
||||
speed -- The speed at which the entity is moving,
|
||||
in meters per second.
|
||||
street -- A thoroughfare within the locality, or a crossing
|
||||
of two thoroughfares.
|
||||
text -- A catch-all element that captures any other
|
||||
text -- A catch-all element that captures any other
|
||||
information about the location.
|
||||
timestamp -- UTC timestamp specifying the moment when the
|
||||
timestamp -- UTC timestamp specifying the moment when the
|
||||
reading was taken.
|
||||
uri -- A URI or URL pointing to information about
|
||||
the location.
|
||||
@ -115,7 +115,7 @@ class XEP_0080(BasePlugin):
|
||||
be executed when a reply stanza is received.
|
||||
"""
|
||||
geoloc = Geoloc()
|
||||
return self.xmpp['xep_0163'].publish(geoloc,
|
||||
return self.xmpp['xep_0163'].publish(geoloc,
|
||||
ifrom=ifrom,
|
||||
block=block,
|
||||
callback=callback,
|
||||
|
@ -31,33 +31,33 @@ class Geoloc(ElementBase):
|
||||
accuracy -- Horizontal GPS error in meters.
|
||||
alt -- Altitude in meters above or below sea level.
|
||||
area -- A named area such as a campus or neighborhood.
|
||||
bearing -- GPS bearing (direction in which the entity is
|
||||
heading to reach its next waypoint), measured in
|
||||
bearing -- GPS bearing (direction in which the entity is
|
||||
heading to reach its next waypoint), measured in
|
||||
decimal degrees relative to true north.
|
||||
building -- A specific building on a street or in an area.
|
||||
country -- The nation where the user is located.
|
||||
countrycode -- The ISO 3166 two-letter country code.
|
||||
datum -- GPS datum.
|
||||
description -- A natural-language name for or description of
|
||||
description -- A natural-language name for or description of
|
||||
the location.
|
||||
error -- Horizontal GPS error in arc minutes. Obsoleted by
|
||||
the accuracy parameter.
|
||||
floor -- A particular floor in a building.
|
||||
lat -- Latitude in decimal degrees North.
|
||||
locality -- A locality within the administrative region, such
|
||||
locality -- A locality within the administrative region, such
|
||||
as a town or city.
|
||||
lon -- Longitude in decimal degrees East.
|
||||
postalcode -- A code used for postal delivery.
|
||||
region -- An administrative region of the nation, such
|
||||
region -- An administrative region of the nation, such
|
||||
as a state or province.
|
||||
room -- A particular room in a building.
|
||||
speed -- The speed at which the entity is moving,
|
||||
speed -- The speed at which the entity is moving,
|
||||
in meters per second.
|
||||
street -- A thoroughfare within the locality, or a crossing
|
||||
of two thoroughfares.
|
||||
text -- A catch-all element that captures any other
|
||||
text -- A catch-all element that captures any other
|
||||
information about the location.
|
||||
timestamp -- UTC timestamp specifying the moment when the
|
||||
timestamp -- UTC timestamp specifying the moment when the
|
||||
reading was taken.
|
||||
uri -- A URI or URL pointing to information about
|
||||
the location.
|
||||
@ -65,10 +65,10 @@ class Geoloc(ElementBase):
|
||||
|
||||
namespace = 'http://jabber.org/protocol/geoloc'
|
||||
name = 'geoloc'
|
||||
interfaces = set(('accuracy', 'alt', 'area', 'bearing', 'building',
|
||||
'country', 'countrycode', 'datum', 'dscription',
|
||||
'error', 'floor', 'lat', 'locality', 'lon',
|
||||
'postalcode', 'region', 'room', 'speed', 'street',
|
||||
interfaces = set(('accuracy', 'alt', 'area', 'bearing', 'building',
|
||||
'country', 'countrycode', 'datum', 'dscription',
|
||||
'error', 'floor', 'lat', 'locality', 'lon',
|
||||
'postalcode', 'region', 'room', 'speed', 'street',
|
||||
'text', 'timestamp', 'uri'))
|
||||
sub_interfaces = interfaces
|
||||
plugin_attrib = name
|
||||
@ -88,7 +88,7 @@ class Geoloc(ElementBase):
|
||||
"""
|
||||
self._set_sub_text('accuracy', text=str(accuracy))
|
||||
return self
|
||||
|
||||
|
||||
def get_accuracy(self):
|
||||
"""
|
||||
Return the value of the <accuracy> element as an integer.
|
||||
@ -111,7 +111,7 @@ class Geoloc(ElementBase):
|
||||
"""
|
||||
self._set_sub_text('alt', text=str(alt))
|
||||
return self
|
||||
|
||||
|
||||
def get_alt(self):
|
||||
"""
|
||||
Return the value of the <alt> element as an integer.
|
||||
@ -130,8 +130,8 @@ class Geoloc(ElementBase):
|
||||
Set the value of the <bearing> element.
|
||||
|
||||
Arguments:
|
||||
bearing -- GPS bearing (direction in which the entity is heading
|
||||
to reach its next waypoint), measured in decimal
|
||||
bearing -- GPS bearing (direction in which the entity is heading
|
||||
to reach its next waypoint), measured in decimal
|
||||
degrees relative to true north
|
||||
"""
|
||||
self._set_sub_text('bearing', text=str(bearing))
|
||||
@ -155,7 +155,7 @@ class Geoloc(ElementBase):
|
||||
Set the value of the <error> element.
|
||||
|
||||
Arguments:
|
||||
error -- Horizontal GPS error in arc minutes; this
|
||||
error -- Horizontal GPS error in arc minutes; this
|
||||
element is deprecated in favor of <accuracy/>
|
||||
"""
|
||||
self._set_sub_text('error', text=str(error))
|
||||
@ -183,7 +183,7 @@ class Geoloc(ElementBase):
|
||||
"""
|
||||
self._set_sub_text('lat', text=str(lat))
|
||||
return self
|
||||
|
||||
|
||||
def get_lat(self):
|
||||
"""
|
||||
Return the value of the <lat> element as a float.
|
||||
@ -196,7 +196,7 @@ class Geoloc(ElementBase):
|
||||
return float(p)
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
|
||||
def set_lon(self, lon):
|
||||
"""
|
||||
Set the value of the <lon> element.
|
||||
@ -225,12 +225,12 @@ class Geoloc(ElementBase):
|
||||
Set the value of the <speed> element.
|
||||
|
||||
Arguments:
|
||||
speed -- The speed at which the entity is moving,
|
||||
speed -- The speed at which the entity is moving,
|
||||
in meters per second
|
||||
"""
|
||||
self._set_sub_text('speed', text=str(speed))
|
||||
return self
|
||||
|
||||
|
||||
def get_speed(self):
|
||||
"""
|
||||
Return the value of the <speed> element as a float.
|
||||
|
@ -42,6 +42,7 @@ def format_date(time_obj):
|
||||
time_obj = time_obj.date()
|
||||
return time_obj.isoformat()
|
||||
|
||||
|
||||
def format_time(time_obj):
|
||||
"""
|
||||
Return a formatted string version of a time object.
|
||||
@ -60,6 +61,7 @@ def format_time(time_obj):
|
||||
return '%sZ' % timestamp
|
||||
return timestamp
|
||||
|
||||
|
||||
def format_datetime(time_obj):
|
||||
"""
|
||||
Return a formatted string version of a datetime object.
|
||||
@ -76,6 +78,7 @@ def format_datetime(time_obj):
|
||||
return '%sZ' % timestamp
|
||||
return timestamp
|
||||
|
||||
|
||||
def date(year=None, month=None, day=None, obj=False):
|
||||
"""
|
||||
Create a date only timestamp for the given instant.
|
||||
@ -98,9 +101,10 @@ def date(year=None, month=None, day=None, obj=False):
|
||||
day = today.day
|
||||
value = dt.date(year, month, day)
|
||||
if obj:
|
||||
return value
|
||||
return value
|
||||
return format_date(value)
|
||||
|
||||
|
||||
def time(hour=None, min=None, sec=None, micro=None, offset=None, obj=False):
|
||||
"""
|
||||
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 format_time(value)
|
||||
|
||||
|
||||
def datetime(year=None, month=None, day=None, hour=None,
|
||||
min=None, sec=None, micro=None, offset=None,
|
||||
separators=True, obj=False):
|
||||
@ -181,7 +186,7 @@ def datetime(year=None, month=None, day=None, hour=None,
|
||||
value = dt.datetime(year, month, day, hour,
|
||||
min, sec, micro, offset)
|
||||
if obj:
|
||||
return value
|
||||
return value
|
||||
return format_datetime(value)
|
||||
|
||||
|
||||
|
@ -14,5 +14,3 @@ from sleekxmpp.plugins.xep_0084.avatar import XEP_0084
|
||||
|
||||
|
||||
register_plugin(XEP_0084)
|
||||
|
||||
|
||||
|
@ -38,7 +38,7 @@ class XEP_0084(BasePlugin):
|
||||
|
||||
def retrieve_avatar(self, jid, id, url=None, ifrom=None, block=True,
|
||||
callback=None, timeout=None):
|
||||
return self.xmpp['xep_0060'].get_item(jid, Data.namespace, id,
|
||||
return self.xmpp['xep_0060'].get_item(jid, Data.namespace, id,
|
||||
ifrom=ifrom,
|
||||
block=block,
|
||||
callback=callback,
|
||||
|
@ -47,28 +47,28 @@ class LegacyError(ElementBase):
|
||||
interfaces = set(('condition',))
|
||||
overrides = ['set_condition']
|
||||
|
||||
error_map = {'bad-request': ('modify','400'),
|
||||
'conflict': ('cancel','409'),
|
||||
'feature-not-implemented': ('cancel','501'),
|
||||
'forbidden': ('auth','403'),
|
||||
'gone': ('modify','302'),
|
||||
'internal-server-error': ('wait','500'),
|
||||
'item-not-found': ('cancel','404'),
|
||||
'jid-malformed': ('modify','400'),
|
||||
'not-acceptable': ('modify','406'),
|
||||
'not-allowed': ('cancel','405'),
|
||||
'not-authorized': ('auth','401'),
|
||||
'payment-required': ('auth','402'),
|
||||
'recipient-unavailable': ('wait','404'),
|
||||
'redirect': ('modify','302'),
|
||||
'registration-required': ('auth','407'),
|
||||
'remote-server-not-found': ('cancel','404'),
|
||||
'remote-server-timeout': ('wait','504'),
|
||||
'resource-constraint': ('wait','500'),
|
||||
'service-unavailable': ('cancel','503'),
|
||||
'subscription-required': ('auth','407'),
|
||||
'undefined-condition': (None,'500'),
|
||||
'unexpected-request': ('wait','400')}
|
||||
error_map = {'bad-request': ('modify', '400'),
|
||||
'conflict': ('cancel', '409'),
|
||||
'feature-not-implemented': ('cancel', '501'),
|
||||
'forbidden': ('auth', '403'),
|
||||
'gone': ('modify', '302'),
|
||||
'internal-server-error': ('wait', '500'),
|
||||
'item-not-found': ('cancel', '404'),
|
||||
'jid-malformed': ('modify', '400'),
|
||||
'not-acceptable': ('modify', '406'),
|
||||
'not-allowed': ('cancel', '405'),
|
||||
'not-authorized': ('auth', '401'),
|
||||
'payment-required': ('auth', '402'),
|
||||
'recipient-unavailable': ('wait', '404'),
|
||||
'redirect': ('modify', '302'),
|
||||
'registration-required': ('auth', '407'),
|
||||
'remote-server-not-found': ('cancel', '404'),
|
||||
'remote-server-timeout': ('wait', '504'),
|
||||
'resource-constraint': ('wait', '500'),
|
||||
'service-unavailable': ('cancel', '503'),
|
||||
'subscription-required': ('auth', '407'),
|
||||
'undefined-condition': (None, '500'),
|
||||
'unexpected-request': ('wait', '400')}
|
||||
|
||||
def setup(self, xml):
|
||||
"""Don't create XML for the plugin."""
|
||||
|
@ -34,7 +34,7 @@ class XEP_0107(BasePlugin):
|
||||
register_stanza_plugin(Message, UserMood)
|
||||
self.xmpp['xep_0163'].register_pep('user_mood', UserMood)
|
||||
|
||||
def publish_mood(self, value=None, text=None, options=None,
|
||||
def publish_mood(self, value=None, text=None, options=None,
|
||||
ifrom=None, block=True, callback=None, timeout=None):
|
||||
"""
|
||||
Publish the user's current mood.
|
||||
@ -79,7 +79,7 @@ class XEP_0107(BasePlugin):
|
||||
be executed when a reply stanza is received.
|
||||
"""
|
||||
mood = UserMood()
|
||||
return self.xmpp['xep_0163'].publish(mood,
|
||||
return self.xmpp['xep_0163'].publish(mood,
|
||||
node=UserMood.namespace,
|
||||
ifrom=ifrom,
|
||||
block=block,
|
||||
|
@ -21,7 +21,7 @@ class UserActivity(ElementBase):
|
||||
'talking', 'traveling', 'undefined', 'working'])
|
||||
specific = set(['at_the_spa', 'brushing_teeth', 'buying_groceries',
|
||||
'cleaning', 'coding', 'commuting', 'cooking', 'cycling',
|
||||
'dancing', 'day_off', 'doing_maintenance',
|
||||
'dancing', 'day_off', 'doing_maintenance',
|
||||
'doing_the_dishes', 'doing_the_laundry', 'driving',
|
||||
'fishing', 'gaming', 'gardening', 'getting_a_haircut',
|
||||
'going_out', 'hanging_out', 'having_a_beer',
|
||||
@ -31,11 +31,11 @@ class UserActivity(ElementBase):
|
||||
'jogging', 'on_a_bus', 'on_a_plane', 'on_a_train',
|
||||
'on_a_trip', 'on_the_phone', 'on_vacation',
|
||||
'on_video_phone', 'other', 'partying', 'playing_sports',
|
||||
'praying', 'reading', 'rehearsing', 'running',
|
||||
'praying', 'reading', 'rehearsing', 'running',
|
||||
'running_an_errand', 'scheduled_holiday', 'shaving',
|
||||
'shopping', 'skiing', 'sleeping', 'smoking',
|
||||
'socializing', 'studying', 'sunbathing', 'swimming',
|
||||
'taking_a_bath', 'taking_a_shower', 'thinking',
|
||||
'taking_a_bath', 'taking_a_shower', 'thinking',
|
||||
'walking', 'walking_the_dog', 'watching_a_movie',
|
||||
'watching_tv', 'working_out', 'writing'])
|
||||
|
||||
@ -46,7 +46,7 @@ class UserActivity(ElementBase):
|
||||
if isinstance(value, tuple) or isinstance(value, list):
|
||||
general = value[0]
|
||||
specific = value[1]
|
||||
|
||||
|
||||
if general in self.general:
|
||||
gen_xml = ET.Element('{%s}%s' % (self.namespace, general))
|
||||
if specific:
|
||||
|
@ -29,7 +29,7 @@ class XEP_0108(BasePlugin):
|
||||
def plugin_init(self):
|
||||
self.xmpp['xep_0163'].register_pep('user_activity', UserActivity)
|
||||
|
||||
def publish_activity(self, general, specific=None, text=None, options=None,
|
||||
def publish_activity(self, general, specific=None, text=None, options=None,
|
||||
ifrom=None, block=True, callback=None, timeout=None):
|
||||
"""
|
||||
Publish the user's current activity.
|
||||
@ -76,7 +76,7 @@ class XEP_0108(BasePlugin):
|
||||
be executed when a reply stanza is received.
|
||||
"""
|
||||
activity = UserActivity()
|
||||
return self.xmpp['xep_0163'].publish(activity,
|
||||
return self.xmpp['xep_0163'].publish(activity,
|
||||
node=UserActivity.namespace,
|
||||
ifrom=ifrom,
|
||||
block=block,
|
||||
|
@ -35,7 +35,7 @@ class XEP_0115(BasePlugin):
|
||||
stanza = stanza
|
||||
|
||||
def plugin_init(self):
|
||||
self.hashes = {'sha-1': hashlib.sha1,
|
||||
self.hashes = {'sha-1': hashlib.sha1,
|
||||
'sha1': hashlib.sha1,
|
||||
'md5': hashlib.md5}
|
||||
|
||||
@ -124,7 +124,7 @@ class XEP_0115(BasePlugin):
|
||||
existing_verstring = self.get_verstring(pres['from'].full)
|
||||
if str(existing_verstring) == str(pres['caps']['ver']):
|
||||
return
|
||||
|
||||
|
||||
if pres['caps']['hash'] not in self.hashes:
|
||||
try:
|
||||
log.debug("Unknown caps hash: %s", pres['caps']['hash'])
|
||||
@ -132,7 +132,7 @@ class XEP_0115(BasePlugin):
|
||||
return
|
||||
except XMPPError:
|
||||
return
|
||||
|
||||
|
||||
log.debug("New caps verification string: %s", pres['caps']['ver'])
|
||||
try:
|
||||
node = '%s#%s' % (pres['caps']['node'], pres['caps']['ver'])
|
||||
@ -140,7 +140,7 @@ class XEP_0115(BasePlugin):
|
||||
|
||||
if isinstance(caps, Iq):
|
||||
caps = caps['disco_info']
|
||||
|
||||
|
||||
if self._validate_caps(caps, pres['caps']['hash'],
|
||||
pres['caps']['ver']):
|
||||
self.assign_verstring(pres['from'], pres['caps']['ver'])
|
||||
@ -173,7 +173,8 @@ class XEP_0115(BasePlugin):
|
||||
form_types.append(f_type)
|
||||
deduped_form_types.add(f_type)
|
||||
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
|
||||
|
||||
if len(f_type) > 1:
|
||||
@ -183,7 +184,8 @@ class XEP_0115(BasePlugin):
|
||||
return False
|
||||
|
||||
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)
|
||||
else:
|
||||
log.debug("No FORM_TYPE found, ignoring form for caps")
|
||||
@ -212,7 +214,7 @@ class XEP_0115(BasePlugin):
|
||||
|
||||
identities = sorted(('/'.join(i) for i in identities))
|
||||
features = sorted(info['features'])
|
||||
|
||||
|
||||
S += '<'.join(identities) + '<'
|
||||
S += '<'.join(features) + '<'
|
||||
|
||||
@ -254,7 +256,7 @@ class XEP_0115(BasePlugin):
|
||||
info = info['disco_info']
|
||||
ver = self.generate_verstring(info, self.hash)
|
||||
self.xmpp['xep_0030'].set_info(
|
||||
jid=jid,
|
||||
jid=jid,
|
||||
node='%s#%s' % (self.caps_node, ver),
|
||||
info=info)
|
||||
self.cache_caps(ver, info)
|
||||
|
@ -69,7 +69,7 @@ class StaticCaps(object):
|
||||
return True
|
||||
|
||||
try:
|
||||
info = self.disco.get_info(jid=jid, node=node,
|
||||
info = self.disco.get_info(jid=jid, node=node,
|
||||
ifrom=ifrom, **data)
|
||||
info = self.disco._wrap(ifrom, jid, info, True)
|
||||
return feature in info['disco_info']['features']
|
||||
@ -99,7 +99,7 @@ class StaticCaps(object):
|
||||
be skipped, even if a result has already been
|
||||
cached. Defaults to false.
|
||||
"""
|
||||
identity = (data.get('category', None),
|
||||
identity = (data.get('category', None),
|
||||
data.get('itype', None),
|
||||
data.get('lang', None))
|
||||
|
||||
@ -114,7 +114,7 @@ class StaticCaps(object):
|
||||
return True
|
||||
|
||||
try:
|
||||
info = self.disco.get_info(jid=jid, node=node,
|
||||
info = self.disco.get_info(jid=jid, node=node,
|
||||
ifrom=ifrom, **data)
|
||||
info = self.disco._wrap(ifrom, jid, info, True)
|
||||
return identity in map(trunc, info['disco_info']['identities'])
|
||||
|
@ -14,7 +14,7 @@ class UserTune(ElementBase):
|
||||
name = 'tune'
|
||||
namespace = 'http://jabber.org/protocol/tune'
|
||||
plugin_attrib = 'tune'
|
||||
interfaces = set(['artist', 'length', 'rating', 'source',
|
||||
interfaces = set(['artist', 'length', 'rating', 'source',
|
||||
'title', 'track', 'uri'])
|
||||
sub_interfaces = interfaces
|
||||
|
||||
|
@ -30,7 +30,7 @@ class XEP_0118(BasePlugin):
|
||||
self.xmpp['xep_0163'].register_pep('user_tune', UserTune)
|
||||
|
||||
def publish_tune(self, artist=None, length=None, rating=None, source=None,
|
||||
title=None, track=None, uri=None, options=None,
|
||||
title=None, track=None, uri=None, options=None,
|
||||
ifrom=None, block=True, callback=None, timeout=None):
|
||||
"""
|
||||
Publish the user's current tune.
|
||||
@ -61,7 +61,7 @@ class XEP_0118(BasePlugin):
|
||||
tune['title'] = title
|
||||
tune['track'] = track
|
||||
tune['uri'] = uri
|
||||
return self.xmpp['xep_0163'].publish(tune,
|
||||
return self.xmpp['xep_0163'].publish(tune,
|
||||
node=UserTune.namespace,
|
||||
options=options,
|
||||
ifrom=ifrom,
|
||||
@ -84,7 +84,7 @@ class XEP_0118(BasePlugin):
|
||||
be executed when a reply stanza is received.
|
||||
"""
|
||||
tune = UserTune()
|
||||
return self.xmpp['xep_0163'].publish(tune,
|
||||
return self.xmpp['xep_0163'].publish(tune,
|
||||
node=UserTune.namespace,
|
||||
ifrom=ifrom,
|
||||
block=block,
|
||||
|
@ -45,7 +45,7 @@ class XEP_0153(BasePlugin):
|
||||
self.api.register(self._set_hash, 'set_hash', default=True)
|
||||
self.api.register(self._get_hash, 'get_hash', default=True)
|
||||
|
||||
def set_avatar(self, jid=None, avatar=None, mtype=None, block=True,
|
||||
def set_avatar(self, jid=None, avatar=None, mtype=None, block=True,
|
||||
timeout=None, callback=None):
|
||||
vcard = self.xmpp['xep_0054'].get_vcard(jid, cached=True)
|
||||
vcard = vcard['vcard_temp']
|
||||
@ -69,7 +69,7 @@ class XEP_0153(BasePlugin):
|
||||
own_jid = (jid.bare == self.xmpp.boundjid.bare)
|
||||
if self.xmpp.is_component:
|
||||
own_jid = (jid.domain == self.xmpp.boundjid.domain)
|
||||
|
||||
|
||||
if jid is not None:
|
||||
jid = jid.bare
|
||||
self.api['set_hash'](jid, args=None)
|
||||
@ -77,7 +77,7 @@ class XEP_0153(BasePlugin):
|
||||
self.xmpp.roster[jid].send_last_presence()
|
||||
|
||||
iq = self.xmpp['xep_0054'].get_vcard(
|
||||
jid=jid,
|
||||
jid=jid,
|
||||
ifrom=self.xmpp.boundjid)
|
||||
data = iq['vcard_temp']['PHOTO']['BINVAL']
|
||||
if not data:
|
||||
|
@ -56,7 +56,7 @@ class XEP_0163(BasePlugin):
|
||||
jid -- Optionally specify the JID.
|
||||
"""
|
||||
if not isinstance(namespace, set) and not isinstance(namespace, list):
|
||||
namespace = [namespace]
|
||||
namespace = [namespace]
|
||||
|
||||
for ns in namespace:
|
||||
self.xmpp['xep_0030'].add_feature('%s+notify' % ns,
|
||||
@ -75,7 +75,7 @@ class XEP_0163(BasePlugin):
|
||||
jid -- Optionally specify the JID.
|
||||
"""
|
||||
if not isinstance(namespace, set) and not isinstance(namespace, list):
|
||||
namespace = [namespace]
|
||||
namespace = [namespace]
|
||||
|
||||
for ns in namespace:
|
||||
self.xmpp['xep_0030'].del_feature(jid=jid,
|
||||
|
@ -78,7 +78,7 @@ class XEP_0172(BasePlugin):
|
||||
be executed when a reply stanza is received.
|
||||
"""
|
||||
nick = UserNick()
|
||||
return self.xmpp['xep_0163'].publish(nick,
|
||||
return self.xmpp['xep_0163'].publish(nick,
|
||||
node=UserNick.namespace,
|
||||
ifrom=ifrom,
|
||||
block=block,
|
||||
|
@ -100,13 +100,13 @@ class XEP_0184(BasePlugin):
|
||||
|
||||
if not isinstance(stanza, Message):
|
||||
return stanza
|
||||
|
||||
|
||||
if stanza['request_receipt']:
|
||||
return stanza
|
||||
|
||||
if not stanza['type'] in self.ack_types:
|
||||
return stanza
|
||||
|
||||
|
||||
if stanza['receipt']:
|
||||
return stanza
|
||||
|
||||
|
@ -82,7 +82,6 @@ class Resumed(StanzaBase):
|
||||
self._set_attr('h', str(val))
|
||||
|
||||
|
||||
|
||||
class Failed(StanzaBase, Error):
|
||||
name = 'failed'
|
||||
namespace = 'urn:xmpp:sm:3'
|
||||
@ -106,7 +105,7 @@ class StreamManagement(ElementBase):
|
||||
self.del_required()
|
||||
if val:
|
||||
self._set_sub_text('required', '', keep=True)
|
||||
|
||||
|
||||
def del_required(self):
|
||||
self._del_sub('required')
|
||||
|
||||
@ -117,7 +116,7 @@ class StreamManagement(ElementBase):
|
||||
self.del_optional()
|
||||
if val:
|
||||
self._set_sub_text('optional', '', keep=True)
|
||||
|
||||
|
||||
def del_optional(self):
|
||||
self._del_sub('optional')
|
||||
|
||||
|
@ -21,7 +21,7 @@ from sleekxmpp.plugins.xep_0198 import stanza
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
MAX_SEQ = 2**32
|
||||
MAX_SEQ = 2 ** 32
|
||||
|
||||
|
||||
class XEP_0198(BasePlugin):
|
||||
@ -69,7 +69,7 @@ class XEP_0198(BasePlugin):
|
||||
|
||||
self.enabled = threading.Event()
|
||||
self.unacked_queue = collections.deque()
|
||||
|
||||
|
||||
self.seq_lock = threading.Lock()
|
||||
self.handled_lock = threading.Lock()
|
||||
self.ack_lock = threading.Lock()
|
||||
@ -197,7 +197,7 @@ class XEP_0198(BasePlugin):
|
||||
|
||||
def _handle_enabled(self, stanza):
|
||||
"""Save the SM-ID, if provided.
|
||||
|
||||
|
||||
Raises an :term:`sm_enabled` event.
|
||||
"""
|
||||
self.xmpp.features.add('stream_management')
|
||||
@ -231,7 +231,7 @@ class XEP_0198(BasePlugin):
|
||||
|
||||
def _handle_ack(self, ack):
|
||||
"""Process a server ack by freeing acked stanzas from the queue.
|
||||
|
||||
|
||||
Raises a :term:`stanza_acked` event for each acked stanza.
|
||||
"""
|
||||
if ack['h'] == self.last_ack:
|
||||
@ -243,10 +243,10 @@ class XEP_0198(BasePlugin):
|
||||
log.debug("Ack: %s, Last Ack: %s, " + \
|
||||
"Unacked: %s, Num Acked: %s, " + \
|
||||
"Remaining: %s",
|
||||
ack['h'],
|
||||
self.last_ack,
|
||||
ack['h'],
|
||||
self.last_ack,
|
||||
num_unacked,
|
||||
num_acked,
|
||||
num_acked,
|
||||
num_unacked - num_acked)
|
||||
for x in range(num_acked):
|
||||
seq, stanza = self.unacked_queue.popleft()
|
||||
|
@ -40,8 +40,12 @@ class XEP_0202(BasePlugin):
|
||||
# custom function can be supplied which accepts
|
||||
# the JID of the entity to query for the time.
|
||||
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:
|
||||
self.local_time = lambda x: xep_0082.datetime(offset=self.tz_offset)
|
||||
self.local_time = default_local_time
|
||||
|
||||
self.xmpp.registerHandler(
|
||||
Callback('Entity Time',
|
||||
|
@ -13,9 +13,7 @@ from sleekxmpp.plugins.xep_0203.stanza import Delay
|
||||
from sleekxmpp.plugins.xep_0203.delay import XEP_0203
|
||||
|
||||
|
||||
|
||||
register_plugin(XEP_0203)
|
||||
|
||||
|
||||
# Retain some backwards compatibility
|
||||
xep_0203 = XEP_0203
|
||||
|
@ -18,13 +18,13 @@ log = logging.getLogger(__name__)
|
||||
class XEP_0222(BasePlugin):
|
||||
|
||||
"""
|
||||
XEP-0222: Persistent Storage of Public Data via PubSub
|
||||
XEP-0222: Persistent Storage of Public Data via PubSub
|
||||
"""
|
||||
|
||||
name = 'xep_0222'
|
||||
description = 'XEP-0222: Persistent Storage of Private Data via PubSub'
|
||||
dependencies = set(['xep_0163', 'xep_0060', 'xep_0004'])
|
||||
|
||||
|
||||
profile = {'pubsub#persist_items': True,
|
||||
'pubsub#send_last_published_item': 'never'}
|
||||
|
||||
@ -72,8 +72,8 @@ class XEP_0222(BasePlugin):
|
||||
options = self.xmpp['xep_0004'].stanza.Form()
|
||||
options['type'] = 'submit'
|
||||
options.add_field(
|
||||
var='FORM_TYPE',
|
||||
ftype='hidden',
|
||||
var='FORM_TYPE',
|
||||
ftype='hidden',
|
||||
value='http://jabber.org/protocol/pubsub#publish-options')
|
||||
|
||||
for field, value in self.profile.items():
|
||||
|
@ -18,7 +18,7 @@ log = logging.getLogger(__name__)
|
||||
class XEP_0223(BasePlugin):
|
||||
|
||||
"""
|
||||
XEP-0223: Persistent Storage of Private Data via PubSub
|
||||
XEP-0223: Persistent Storage of Private Data via PubSub
|
||||
"""
|
||||
|
||||
name = 'xep_0223'
|
||||
@ -72,8 +72,8 @@ class XEP_0223(BasePlugin):
|
||||
options = self.xmpp['xep_0004'].stanza.Form()
|
||||
options['type'] = 'submit'
|
||||
options.add_field(
|
||||
var='FORM_TYPE',
|
||||
ftype='hidden',
|
||||
var='FORM_TYPE',
|
||||
ftype='hidden',
|
||||
value='http://jabber.org/protocol/pubsub#publish-options')
|
||||
|
||||
for field, value in self.profile.items():
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""
|
||||
SleekXMPP: The Sleek XMPP Library
|
||||
Copyright (C) 2012 Nathanael C. Fritz,
|
||||
Copyright (C) 2012 Nathanael C. Fritz,
|
||||
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
|
||||
This file is part of SleekXMPP.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""
|
||||
SleekXMPP: The Sleek XMPP Library
|
||||
Copyright (C) 2012 Nathanael C. Fritz,
|
||||
Copyright (C) 2012 Nathanael C. Fritz,
|
||||
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
|
||||
This file is part of SleekXMPP.
|
||||
|
||||
@ -58,7 +58,6 @@ class XEP_0231(BasePlugin):
|
||||
self.api.register(self._set_bob, 'set_bob', default=True)
|
||||
self.api.register(self._del_bob, 'del_bob', default=True)
|
||||
|
||||
|
||||
def set_bob(self, data, mtype, cid=None, max_age=None):
|
||||
if cid is None:
|
||||
cid = 'sha1+%s@bob.xmpp.org' % hashlib.sha1(data).hexdigest()
|
||||
@ -73,7 +72,7 @@ class XEP_0231(BasePlugin):
|
||||
|
||||
return cid
|
||||
|
||||
def get_bob(self, jid=None, cid=None, cached=True, ifrom=None,
|
||||
def get_bob(self, jid=None, cid=None, cached=True, ifrom=None,
|
||||
block=True, timeout=None, callback=None):
|
||||
if cached:
|
||||
data = self.api['get_bob'](None, None, ifrom, args=cid)
|
||||
@ -112,7 +111,7 @@ class XEP_0231(BasePlugin):
|
||||
iq.send()
|
||||
|
||||
def _handle_bob(self, stanza):
|
||||
self.api['set_bob'](stanza['from'], None,
|
||||
self.api['set_bob'](stanza['from'], None,
|
||||
stanza['to'], args=stanza['bob'])
|
||||
self.xmpp.event('bob', stanza)
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
"""
|
||||
SleekXMPP: The Sleek XMPP Library
|
||||
Copyright (C) 2012 Nathanael C. Fritz,
|
||||
Copyright (C) 2012 Nathanael C. Fritz,
|
||||
Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
|
||||
This file is part of SleekXMPP.
|
||||
|
||||
|
@ -30,7 +30,7 @@ class XEP_0258(BasePlugin):
|
||||
register_stanza_plugin(Message, SecurityLabel)
|
||||
register_stanza_plugin(Iq, Catalog)
|
||||
|
||||
def get_catalog(self, jid, ifrom=None, block=True,
|
||||
def get_catalog(self, jid, ifrom=None, block=True,
|
||||
callback=None, timeout=None):
|
||||
iq = self.xmpp.Iq()
|
||||
iq['to'] = jid
|
||||
|
@ -33,7 +33,7 @@ class Label(ElementBase):
|
||||
class DisplayMarking(ElementBase):
|
||||
name = 'displaymarking'
|
||||
namespace = 'urn:xmpp:sec-label:0'
|
||||
plugin_attrib = 'display_marking'
|
||||
plugin_attrib = 'display_marking'
|
||||
interfaces = set(['fgcolor', 'bgcolor', 'value'])
|
||||
|
||||
def get_fgcolor(self):
|
||||
|
@ -307,7 +307,7 @@ class RosterItem(object):
|
||||
p['from'] = self.owner
|
||||
p.send()
|
||||
|
||||
def send_presence(self, **kwargs):
|
||||
def send_presence(self, **kwargs):
|
||||
"""
|
||||
Create, initialize, and send a Presence stanza.
|
||||
|
||||
|
@ -150,7 +150,7 @@ class Roster(object):
|
||||
for node in self:
|
||||
self[node].reset()
|
||||
|
||||
def send_presence(self, **kwargs):
|
||||
def send_presence(self, **kwargs):
|
||||
"""
|
||||
Create, initialize, and send a Presence stanza.
|
||||
|
||||
|
@ -68,7 +68,7 @@ class RosterNode(object):
|
||||
self._version = self.db.version(self.jid)
|
||||
for jid in self.db.entries(self.jid):
|
||||
self.add(jid)
|
||||
|
||||
|
||||
@property
|
||||
def version(self):
|
||||
"""Retrieve the roster's version ID."""
|
||||
@ -149,7 +149,7 @@ class RosterNode(object):
|
||||
self.db = db
|
||||
existing_entries = set(self._jids)
|
||||
new_entries = set(self.db.entries(self.jid, {}))
|
||||
|
||||
|
||||
for jid in existing_entries:
|
||||
self._jids[jid].set_backend(db, save)
|
||||
for jid in new_entries - existing_entries:
|
||||
@ -294,7 +294,7 @@ class RosterNode(object):
|
||||
for jid in self:
|
||||
self[jid].reset()
|
||||
|
||||
def send_presence(self, **kwargs):
|
||||
def send_presence(self, **kwargs):
|
||||
"""
|
||||
Create, initialize, and send a Presence stanza.
|
||||
|
||||
|
@ -51,7 +51,7 @@ class Error(ElementBase):
|
||||
namespace = 'jabber:client'
|
||||
name = 'error'
|
||||
plugin_attrib = 'error'
|
||||
interfaces = set(('code', 'condition', 'text', 'type',
|
||||
interfaces = set(('code', 'condition', 'text', 'type',
|
||||
'gone', 'redirect'))
|
||||
sub_interfaces = set(('text',))
|
||||
plugin_attrib_map = {}
|
||||
|
@ -78,7 +78,8 @@ class RootStanza(StanzaBase):
|
||||
self['error']['type'] = 'cancel'
|
||||
self.send()
|
||||
# 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
|
||||
self.stream.exception(e)
|
||||
|
||||
|
@ -47,7 +47,7 @@ class Roster(ElementBase):
|
||||
roster versioning.
|
||||
"""
|
||||
return self.xml.attrib.get('ver', None)
|
||||
|
||||
|
||||
def set_ver(self, ver):
|
||||
"""
|
||||
Ensure handling an empty ver attribute propery.
|
||||
@ -101,7 +101,7 @@ class Roster(ElementBase):
|
||||
items[item['jid']] = item.values
|
||||
# Remove extra JID reference to keep everything
|
||||
# backward compatible
|
||||
del items[item['jid']]['jid']
|
||||
del items[item['jid']]['jid']
|
||||
del items[item['jid']]['lang']
|
||||
return items
|
||||
|
||||
|
@ -79,4 +79,3 @@ class StreamError(Error, StanzaBase):
|
||||
|
||||
def del_see_other_host(self):
|
||||
self._del_sub('{%s}see-other-host' % self.condition_ns)
|
||||
|
||||
|
@ -336,7 +336,6 @@ class SleekTest(unittest.TestCase):
|
||||
self.xmpp.default_lang = None
|
||||
self.xmpp.peer_default_lang = None
|
||||
|
||||
|
||||
# We will use this to wait for the session_start event
|
||||
# for live connections.
|
||||
skip_queue = queue.Queue()
|
||||
|
@ -7,11 +7,12 @@ try:
|
||||
from pyasn1.type.univ import Any, ObjectIdentifier, OctetString
|
||||
from pyasn1.type.char import BMPString, IA5String, UTF8String
|
||||
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_at_commonName as COMMON_NAME
|
||||
|
||||
|
||||
XMPP_ADDR = ObjectIdentifier('1.3.6.1.5.5.7.8.5')
|
||||
SRV_NAME = ObjectIdentifier('1.3.6.1.5.5.7.8.7')
|
||||
|
||||
@ -149,7 +150,7 @@ def verify(expected, raw_cert):
|
||||
expected_wild = expected[expected.index('.'):]
|
||||
expected_srv = '_xmpp-client.%s' % expected
|
||||
|
||||
for name in cert_names['XMPPAddr']:
|
||||
for name in cert_names['XMPPAddr']:
|
||||
if name == expected:
|
||||
return True
|
||||
for name in cert_names['SRV']:
|
||||
|
@ -49,7 +49,7 @@ class BaseHandler(object):
|
||||
def match(self, xml):
|
||||
"""Compare a stanza or XML object with the handler's matcher.
|
||||
|
||||
:param xml: An XML or
|
||||
:param xml: An XML or
|
||||
:class:`~sleekxmpp.xmlstream.stanzabase.ElementBase` object
|
||||
"""
|
||||
return self._matcher.match(xml)
|
||||
@ -73,7 +73,7 @@ class BaseHandler(object):
|
||||
self._payload = payload
|
||||
|
||||
def check_delete(self):
|
||||
"""Check if the handler should be removed from the list
|
||||
"""Check if the handler should be removed from the list
|
||||
of stream handlers.
|
||||
"""
|
||||
return self._destroy
|
||||
|
@ -33,7 +33,7 @@ class Callback(BaseHandler):
|
||||
:param matcher: A :class:`~sleekxmpp.xmlstream.matcher.base.MatcherBase`
|
||||
derived object for matching stanza objects.
|
||||
:param pointer: The function to execute during callback.
|
||||
:param bool thread: **DEPRECATED.** Remains only for
|
||||
:param bool thread: **DEPRECATED.** Remains only for
|
||||
backwards compatibility.
|
||||
:param bool once: Indicates if the handler should be used only
|
||||
once. Defaults to False.
|
||||
|
@ -34,9 +34,9 @@ class MatchXMLMask(MatcherBase):
|
||||
|
||||
<message xmlns="jabber:client"><body /></message>
|
||||
|
||||
Use of XMLMask is discouraged, and
|
||||
:class:`~sleekxmpp.xmlstream.matcher.xpath.MatchXPath` or
|
||||
:class:`~sleekxmpp.xmlstream.matcher.stanzapath.StanzaPath`
|
||||
Use of XMLMask is discouraged, and
|
||||
:class:`~sleekxmpp.xmlstream.matcher.xpath.MatchXPath` or
|
||||
:class:`~sleekxmpp.xmlstream.matcher.stanzapath.StanzaPath`
|
||||
should be used instead.
|
||||
|
||||
The use of namespaces in the mask comparison is controlled by
|
||||
|
@ -57,7 +57,7 @@ class Task(object):
|
||||
|
||||
#: The keyword arguments to pass to :attr:`callback`.
|
||||
self.kwargs = kwargs or {}
|
||||
|
||||
|
||||
#: Indicates if the task should repeat after executing,
|
||||
#: using the same :attr:`seconds` delay.
|
||||
self.repeat = repeat
|
||||
@ -103,7 +103,7 @@ class Scheduler(object):
|
||||
def __init__(self, parentstop=None):
|
||||
#: A queue for storing tasks
|
||||
self.addq = queue.Queue()
|
||||
|
||||
|
||||
#: A list of tasks in order of execution time.
|
||||
self.schedule = []
|
||||
|
||||
|
@ -45,7 +45,7 @@ def register_stanza_plugin(stanza, plugin, iterable=False, overrides=False):
|
||||
substanzas for the parent, using ``parent['substanzas']``. If the
|
||||
attribute ``plugin_multi_attrib`` was defined for the plugin, then
|
||||
the substanza set can be filtered to only instances of the plugin
|
||||
class. For example, given a plugin class ``Foo`` with
|
||||
class. For example, given a plugin class ``Foo`` with
|
||||
``plugin_multi_attrib = 'foos'`` then::
|
||||
|
||||
parent['foos']
|
||||
@ -99,6 +99,14 @@ def multifactory(stanza, plugin_attrib):
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
Template class for multifactory
|
||||
@ -109,9 +117,9 @@ def multifactory(stanza, plugin_attrib):
|
||||
def get_multi(self, lang=None):
|
||||
parent = self.parent()
|
||||
if not lang or lang == '*':
|
||||
res = filter(lambda sub: isinstance(sub, self._multistanza), parent)
|
||||
res = filter(plugin_filter(self), parent)
|
||||
else:
|
||||
res = filter(lambda sub: isinstance(sub, self._multistanza) and sub['lang'] == lang, parent)
|
||||
res = filter(plugin_filter(self, lang), parent)
|
||||
return list(res)
|
||||
|
||||
def set_multi(self, val, lang=None):
|
||||
@ -124,9 +132,9 @@ def multifactory(stanza, plugin_attrib):
|
||||
def del_multi(self, lang=None):
|
||||
parent = self.parent()
|
||||
if not lang or lang == '*':
|
||||
res = filter(lambda sub: isinstance(sub, self._multistanza), parent)
|
||||
res = filter(plugin_filter(self), parent)
|
||||
else:
|
||||
res = filter(lambda sub: isinstance(sub, self._multistanza) and sub['lang'] == lang, parent)
|
||||
res = filter(plugin_filter(self, lang), parent)
|
||||
res = list(res)
|
||||
if not res:
|
||||
del parent.plugins[(plugin_attrib, None)]
|
||||
@ -253,8 +261,10 @@ class ElementBase(object):
|
||||
directly from the parent stanza, as shown below, but retrieving
|
||||
information will require all interfaces to be used, as so::
|
||||
|
||||
>>> message['custom'] = 'bar' # Same as using message['custom']['custom']
|
||||
>>> message['custom']['custom'] # Must use all interfaces
|
||||
>>> # Same as using message['custom']['custom']
|
||||
>>> message['custom'] = 'bar'
|
||||
>>> # Must use all interfaces
|
||||
>>> message['custom']['custom']
|
||||
'bar'
|
||||
|
||||
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
|
||||
#: prefixes. For example, an :class:`ElementBase` object for ``<message />``
|
||||
#: would use ``name = 'message'``.
|
||||
#: prefixes. For example, an :class:`ElementBase` object for
|
||||
#: ``<message />`` would use ``name = 'message'``.
|
||||
name = 'stanza'
|
||||
|
||||
#: The XML namespace for the element. Given ``<foo xmlns="bar" />``,
|
||||
@ -522,8 +532,10 @@ class ElementBase(object):
|
||||
|
||||
if existing_xml is None:
|
||||
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:
|
||||
existing_xml = None
|
||||
|
||||
if existing_xml is not None:
|
||||
if existing_xml.attrib.get('{%s}lang' % XML_NS, '') != lang:
|
||||
existing_xml = None
|
||||
|
||||
plugin = plugin_class(parent=self, xml=existing_xml)
|
||||
|
||||
@ -761,13 +773,20 @@ class ElementBase(object):
|
||||
else:
|
||||
if attrib in self.sub_interfaces:
|
||||
if lang == '*':
|
||||
return self._set_all_sub_text(attrib, value, lang='*')
|
||||
return self._set_sub_text(attrib, text=value, lang=lang)
|
||||
return self._set_all_sub_text(attrib,
|
||||
value,
|
||||
lang='*')
|
||||
return self._set_sub_text(attrib, text=value,
|
||||
lang=lang)
|
||||
elif attrib in self.bool_interfaces:
|
||||
if value:
|
||||
return self._set_sub_text(attrib, '', keep=True, lang=lang)
|
||||
return self._set_sub_text(attrib, '',
|
||||
keep=True,
|
||||
lang=lang)
|
||||
else:
|
||||
return self._set_sub_text(attrib, '', keep=False, lang=lang)
|
||||
return self._set_sub_text(attrib, '',
|
||||
keep=False,
|
||||
lang=lang)
|
||||
else:
|
||||
self._set_attr(attrib, value)
|
||||
else:
|
||||
@ -932,7 +951,8 @@ class ElementBase(object):
|
||||
stanzas = self.xml.findall(name)
|
||||
if 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:
|
||||
results[stanza_lang] = stanza.text
|
||||
return results
|
||||
@ -996,7 +1016,9 @@ class ElementBase(object):
|
||||
self._del_sub(name, lang)
|
||||
for value_lang, value in values.items():
|
||||
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):
|
||||
"""Remove sub elements that match the given name or XPath.
|
||||
@ -1032,7 +1054,9 @@ class ElementBase(object):
|
||||
not element.getchildren():
|
||||
# Only delete the originally requested elements, and
|
||||
# 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)
|
||||
if not all:
|
||||
# If we don't want to delete elements up the tree, stop
|
||||
@ -1272,8 +1296,8 @@ class ElementBase(object):
|
||||
return self
|
||||
|
||||
def _fix_ns(self, xpath, split=False, propagate_ns=True):
|
||||
return fix_ns(xpath, split=split,
|
||||
propagate_ns=propagate_ns,
|
||||
return fix_ns(xpath, split=split,
|
||||
propagate_ns=propagate_ns,
|
||||
default_ns=self.namespace)
|
||||
|
||||
def __eq__(self, other):
|
||||
|
@ -55,7 +55,7 @@ RESPONSE_TIMEOUT = 30
|
||||
WAIT_TIMEOUT = 0.1
|
||||
|
||||
#: The number of threads to use to handle XML stream events. This is not the
|
||||
#: same as the number of custom event handling threads.
|
||||
#: same as the number of custom event handling threads.
|
||||
#: :data:`HANDLER_THREADS` must be at least 1. For Python implementations
|
||||
#: with a GIL, this should be left at 1, but for implemetnations without
|
||||
#: a GIL increasing this value can provide better performance.
|
||||
@ -124,7 +124,7 @@ class XMLStream(object):
|
||||
self.ssl_support = SSL_SUPPORT
|
||||
|
||||
#: Most XMPP servers support TLSv1, but OpenFire in particular
|
||||
#: does not work well with it. For OpenFire, set
|
||||
#: does not work well with it. For OpenFire, set
|
||||
#: :attr:`ssl_version` to use ``SSLv23``::
|
||||
#:
|
||||
#: import ssl
|
||||
@ -134,30 +134,30 @@ class XMLStream(object):
|
||||
#: Path to a file containing certificates for verifying the
|
||||
#: server SSL certificate. A non-``None`` value will trigger
|
||||
#: certificate checking.
|
||||
#:
|
||||
#:
|
||||
#: .. note::
|
||||
#:
|
||||
#: On Mac OS X, certificates in the system keyring will
|
||||
#: be consulted, even if they are not in the provided file.
|
||||
self.ca_certs = None
|
||||
|
||||
#: The time in seconds to wait for events from the event queue,
|
||||
#: The time in seconds to wait for events from the event queue,
|
||||
#: and also the time between checks for the process stop signal.
|
||||
self.wait_timeout = WAIT_TIMEOUT
|
||||
|
||||
#: The time in seconds to wait before timing out waiting
|
||||
#: The time in seconds to wait before timing out waiting
|
||||
#: for response stanzas.
|
||||
self.response_timeout = RESPONSE_TIMEOUT
|
||||
|
||||
#: The current amount to time to delay attempting to reconnect.
|
||||
#: The current amount to time to delay attempting to reconnect.
|
||||
#: This value doubles (with some jitter) with each failed
|
||||
#: connection attempt up to :attr:`reconnect_max_delay` seconds.
|
||||
self.reconnect_delay = None
|
||||
|
||||
|
||||
#: Maximum time to delay between connection attempts is one hour.
|
||||
self.reconnect_max_delay = RECONNECT_MAX_DELAY
|
||||
|
||||
#: Maximum number of attempts to connect to the server before
|
||||
#: Maximum number of attempts to connect to the server before
|
||||
#: quitting and raising a 'connect_failed' event. Setting to
|
||||
#: ``None`` allows infinite reattempts, while setting it to ``0``
|
||||
#: will disable reconnection attempts. Defaults to ``None``.
|
||||
@ -178,16 +178,16 @@ class XMLStream(object):
|
||||
|
||||
#: The default port to return when querying DNS records.
|
||||
self.default_port = int(port)
|
||||
|
||||
#: The domain to try when querying DNS records.
|
||||
|
||||
#: The domain to try when querying DNS records.
|
||||
self.default_domain = ''
|
||||
|
||||
#: The expected name of the server, for validation.
|
||||
self._expected_server_name = ''
|
||||
|
||||
|
||||
#: The desired, or actual, address of the connected server.
|
||||
self.address = (host, int(port))
|
||||
|
||||
|
||||
#: A file-like wrapper for the socket for use with the
|
||||
#: :mod:`~xml.etree.ElementTree` module.
|
||||
self.filesocket = None
|
||||
@ -258,7 +258,7 @@ class XMLStream(object):
|
||||
#: and data is sent immediately over the wire.
|
||||
self.session_started_event = threading.Event()
|
||||
|
||||
#: The default time in seconds to wait for a session to start
|
||||
#: The default time in seconds to wait for a session to start
|
||||
#: after connecting before reconnecting and trying again.
|
||||
self.session_timeout = 45
|
||||
|
||||
@ -417,12 +417,12 @@ class XMLStream(object):
|
||||
if use_tls is not None:
|
||||
self.use_tls = use_tls
|
||||
|
||||
|
||||
# Repeatedly attempt to connect until a successful connection
|
||||
# is established.
|
||||
attempts = self.reconnect_max_attempts
|
||||
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():
|
||||
connected = self.state.transition('disconnected', 'connected',
|
||||
func=self._connect)
|
||||
@ -437,7 +437,7 @@ class XMLStream(object):
|
||||
def _connect(self, reattempt=True):
|
||||
self.scheduler.remove('Session timeout check')
|
||||
self.stop.clear()
|
||||
|
||||
|
||||
if self.reconnect_delay is None or not reattempt:
|
||||
delay = 1.0
|
||||
else:
|
||||
@ -483,7 +483,7 @@ class XMLStream(object):
|
||||
if self.use_proxy:
|
||||
connected = self._connect_proxy()
|
||||
if not connected:
|
||||
if reattempt:
|
||||
if reattempt:
|
||||
self.reconnect_delay = delay
|
||||
return False
|
||||
|
||||
@ -520,7 +520,8 @@ class XMLStream(object):
|
||||
except (Socket.error, ssl.SSLError):
|
||||
log.error('CERT: Invalid certificate trust 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:
|
||||
self.event('ssl_invalid_chain', direct=True)
|
||||
return False
|
||||
@ -528,7 +529,7 @@ class XMLStream(object):
|
||||
self._der_cert = self.socket.getpeercert(binary_form=True)
|
||||
pem_cert = ssl.DER_cert_to_PEM_cert(self._der_cert)
|
||||
log.debug('CERT: %s', pem_cert)
|
||||
|
||||
|
||||
self.event('ssl_cert', pem_cert, direct=True)
|
||||
try:
|
||||
cert.verify(self._expected_server_name, self._der_cert)
|
||||
@ -537,7 +538,9 @@ class XMLStream(object):
|
||||
if not self.event_handled('ssl_invalid_cert'):
|
||||
self.disconnect(send_close=False)
|
||||
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)
|
||||
#this event is where you should set your application state
|
||||
@ -630,7 +633,7 @@ class XMLStream(object):
|
||||
|
||||
If the disconnect should take place after all items
|
||||
in the send queue have been sent, use ``wait=True``.
|
||||
|
||||
|
||||
.. warning::
|
||||
|
||||
If you are constantly adding items to the queue
|
||||
@ -651,7 +654,7 @@ class XMLStream(object):
|
||||
"""
|
||||
self.state.transition('connected', 'disconnected',
|
||||
wait=2.0,
|
||||
func=self._disconnect,
|
||||
func=self._disconnect,
|
||||
args=(reconnect, wait, send_close))
|
||||
|
||||
def _disconnect(self, reconnect=False, wait=None, send_close=True):
|
||||
@ -705,16 +708,18 @@ class XMLStream(object):
|
||||
"""Reset the stream's state and reconnect to the server."""
|
||||
log.debug("reconnecting...")
|
||||
if self.state.ensure('connected'):
|
||||
self.state.transition('connected', 'disconnected',
|
||||
self.state.transition('connected', 'disconnected',
|
||||
wait=2.0,
|
||||
func=self._disconnect,
|
||||
func=self._disconnect,
|
||||
args=(True, wait, send_close))
|
||||
|
||||
attempts = self.reconnect_max_attempts
|
||||
|
||||
log.debug("connecting...")
|
||||
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():
|
||||
connected = self.state.transition('disconnected', 'connected',
|
||||
wait=2.0, func=self._connect)
|
||||
@ -762,8 +767,8 @@ class XMLStream(object):
|
||||
"""
|
||||
Configure and set options for a :class:`~dns.resolver.Resolver`
|
||||
instance, and other DNS related tasks. For example, you
|
||||
can also check :meth:`~socket.socket.getaddrinfo` to see
|
||||
if you need to call out to ``libresolv.so.2`` to
|
||||
can also check :meth:`~socket.socket.getaddrinfo` to see
|
||||
if you need to call out to ``libresolv.so.2`` to
|
||||
run ``res_init()``.
|
||||
|
||||
Meant to be overridden.
|
||||
@ -817,7 +822,7 @@ class XMLStream(object):
|
||||
log.debug('CERT: %s', pem_cert)
|
||||
self.event('ssl_cert', pem_cert, direct=True)
|
||||
|
||||
try:
|
||||
try:
|
||||
cert.verify(self._expected_server_name, self._der_cert)
|
||||
except cert.CertificateError as err:
|
||||
log.error(err.message)
|
||||
@ -877,8 +882,8 @@ class XMLStream(object):
|
||||
self.schedule('Whitespace Keepalive',
|
||||
self.whitespace_keepalive_interval,
|
||||
self.send_raw,
|
||||
args = (' ',),
|
||||
kwargs = {'now': True},
|
||||
args=(' ',),
|
||||
kwargs={'now': True},
|
||||
repeat=True)
|
||||
|
||||
def _remove_schedules(self, event):
|
||||
@ -887,7 +892,7 @@ class XMLStream(object):
|
||||
self.scheduler.remove('Certificate Expiration')
|
||||
|
||||
def start_stream_handler(self, xml):
|
||||
"""Perform any initialization actions, such as handshakes,
|
||||
"""Perform any initialization actions, such as handshakes,
|
||||
once the stream header has been sent.
|
||||
|
||||
Meant to be overridden.
|
||||
@ -895,8 +900,8 @@ class XMLStream(object):
|
||||
pass
|
||||
|
||||
def register_stanza(self, stanza_class):
|
||||
"""Add a stanza object class as a known root stanza.
|
||||
|
||||
"""Add a stanza object class as a known root stanza.
|
||||
|
||||
A root stanza is one that appears as a direct child of the stream's
|
||||
root element.
|
||||
|
||||
@ -913,8 +918,8 @@ class XMLStream(object):
|
||||
self.__root_stanza.append(stanza_class)
|
||||
|
||||
def remove_stanza(self, stanza_class):
|
||||
"""Remove a stanza from being a known root stanza.
|
||||
|
||||
"""Remove a stanza from being a known root stanza.
|
||||
|
||||
A root stanza is one that appears as a direct child of the stream's
|
||||
root element.
|
||||
|
||||
@ -979,8 +984,9 @@ class XMLStream(object):
|
||||
"""Add a stream event handler that will be executed when a matching
|
||||
stanza is received.
|
||||
|
||||
:param handler: The :class:`~sleekxmpp.xmlstream.handler.base.BaseHandler`
|
||||
derived object to execute.
|
||||
:param handler:
|
||||
The :class:`~sleekxmpp.xmlstream.handler.base.BaseHandler`
|
||||
derived object to execute.
|
||||
"""
|
||||
if handler.stream is None:
|
||||
self.__handlers.append(handler)
|
||||
@ -1007,11 +1013,12 @@ class XMLStream(object):
|
||||
"""
|
||||
if port is None:
|
||||
port = self.default_port
|
||||
|
||||
|
||||
resolver = default_resolver()
|
||||
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):
|
||||
"""Pick a server and port from DNS answers.
|
||||
@ -1029,7 +1036,7 @@ class XMLStream(object):
|
||||
return self.dns_answers.next()
|
||||
else:
|
||||
return next(self.dns_answers)
|
||||
|
||||
|
||||
def add_event_handler(self, name, pointer,
|
||||
threaded=False, disposable=False):
|
||||
"""Add a custom event handler that will be executed whenever
|
||||
@ -1144,9 +1151,9 @@ class XMLStream(object):
|
||||
|
||||
May optionally block until an expected response is received.
|
||||
|
||||
:param data: The :class:`~sleekxmpp.xmlstream.stanzabase.ElementBase`
|
||||
:param data: The :class:`~sleekxmpp.xmlstream.stanzabase.ElementBase`
|
||||
stanza to send on the stream.
|
||||
:param mask: **DEPRECATED**
|
||||
:param mask: **DEPRECATED**
|
||||
An XML string snippet matching the structure
|
||||
of the expected response. Execution will block
|
||||
in this thread until the response is received
|
||||
@ -1198,9 +1205,9 @@ class XMLStream(object):
|
||||
"""Send an XML object on the stream, and optionally wait
|
||||
for a response.
|
||||
|
||||
:param data: The :class:`~xml.etree.ElementTree.Element` XML object
|
||||
:param data: The :class:`~xml.etree.ElementTree.Element` XML object
|
||||
to send on the stream.
|
||||
:param mask: **DEPRECATED**
|
||||
:param mask: **DEPRECATED**
|
||||
An XML string snippet matching the structure
|
||||
of the expected response. Execution will block
|
||||
in this thread until the response is received
|
||||
@ -1240,14 +1247,15 @@ class XMLStream(object):
|
||||
count += 1
|
||||
except ssl.SSLError as serr:
|
||||
if tries >= self.ssl_retry_max:
|
||||
log.debug('SSL error - max retries reached')
|
||||
log.debug('SSL error: max retries reached')
|
||||
self.exception(serr)
|
||||
log.warning("Failed to send %s", data)
|
||||
if reconnect is None:
|
||||
reconnect = self.auto_reconnect
|
||||
if not self.stop.is_set():
|
||||
self.disconnect(reconnect, send_close=False)
|
||||
log.warning('SSL write error - reattempting')
|
||||
self.disconnect(reconnect,
|
||||
send_close=False)
|
||||
log.warning('SSL write error: retrying')
|
||||
if not self.stop.is_set():
|
||||
time.sleep(self.ssl_retry_delay)
|
||||
tries += 1
|
||||
@ -1302,7 +1310,7 @@ class XMLStream(object):
|
||||
def _wait_for_threads(self):
|
||||
with self.__thread_cond:
|
||||
if self.__thread_count != 0:
|
||||
log.debug("Waiting for %s threads to exit." %
|
||||
log.debug("Waiting for %s threads to exit." %
|
||||
self.__thread_count)
|
||||
name = threading.current_thread().name
|
||||
if name in self.__thread:
|
||||
@ -1334,7 +1342,7 @@ class XMLStream(object):
|
||||
Defaults to ``True``. This does **not** mean that no
|
||||
threads are used at all if ``threaded=False``.
|
||||
|
||||
Regardless of these threading options, these threads will
|
||||
Regardless of these threading options, these threads will
|
||||
always exist:
|
||||
|
||||
- The event queue processor
|
||||
@ -1424,7 +1432,7 @@ class XMLStream(object):
|
||||
|
||||
def __read_xml(self):
|
||||
"""Parse the incoming XML stream
|
||||
|
||||
|
||||
Stream events are raised for each received stanza.
|
||||
"""
|
||||
depth = 0
|
||||
@ -1435,8 +1443,8 @@ class XMLStream(object):
|
||||
# We have received the start of the root element.
|
||||
root = xml
|
||||
log.debug('RECV: %s', tostring(root, xmlns=self.default_ns,
|
||||
stream=self,
|
||||
top_level=True,
|
||||
stream=self,
|
||||
top_level=True,
|
||||
open_only=True))
|
||||
# Perform any stream initialization actions, such
|
||||
# as handshakes.
|
||||
@ -1468,10 +1476,10 @@ class XMLStream(object):
|
||||
"""Create a stanza object from a given XML object.
|
||||
|
||||
If a specialized stanza type is not found for the XML, then
|
||||
a generic :class:`~sleekxmpp.xmlstream.stanzabase.StanzaBase`
|
||||
a generic :class:`~sleekxmpp.xmlstream.stanzabase.StanzaBase`
|
||||
stanza will be returned.
|
||||
|
||||
:param xml: The :class:`~xml.etree.ElementTree.Element` XML object
|
||||
:param xml: The :class:`~xml.etree.ElementTree.Element` XML object
|
||||
to convert into a stanza object.
|
||||
:param default_ns: Optional default namespace to use instead of the
|
||||
stream's current default namespace.
|
||||
@ -1656,12 +1664,13 @@ class XMLStream(object):
|
||||
count += 1
|
||||
except ssl.SSLError as serr:
|
||||
if tries >= self.ssl_retry_max:
|
||||
log.debug('SSL error - max retries reached')
|
||||
log.debug('SSL error: max retries reached')
|
||||
self.exception(serr)
|
||||
log.warning("Failed to send %s", data)
|
||||
if not self.stop.is_set():
|
||||
self.disconnect(self.auto_reconnect, send_close=False)
|
||||
log.warning('SSL write error - reattempting')
|
||||
self.disconnect(self.auto_reconnect,
|
||||
send_close=False)
|
||||
log.warning('SSL write error: retrying')
|
||||
if not self.stop.is_set():
|
||||
time.sleep(self.ssl_retry_delay)
|
||||
tries += 1
|
||||
|
Loading…
Reference in New Issue
Block a user