mirror of
https://github.com/correl/SleekXMPP.git
synced 2024-11-23 19:19:53 +00:00
Update the API docs for XMLStream
This commit is contained in:
parent
a85891c611
commit
8922e2050a
5 changed files with 389 additions and 383 deletions
|
@ -1,13 +0,0 @@
|
||||||
=========
|
|
||||||
xmlstream
|
|
||||||
=========
|
|
||||||
|
|
||||||
.. module:: sleekxmpp.xmlstream
|
|
||||||
|
|
||||||
.. autoclass:: XMLStream
|
|
||||||
:members:
|
|
||||||
|
|
||||||
.. toctree::
|
|
||||||
|
|
||||||
stanzabase
|
|
||||||
tostring
|
|
10
docs/api/xmlstream/xmlstream.rst
Normal file
10
docs/api/xmlstream/xmlstream.rst
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
==========
|
||||||
|
XML Stream
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. module:: sleekxmpp.xmlstream.xmlstream
|
||||||
|
|
||||||
|
.. autoexception:: RestartStream
|
||||||
|
|
||||||
|
.. autoclass:: XMLStream
|
||||||
|
:members:
|
|
@ -116,10 +116,29 @@ API Reference
|
||||||
api/xmlstream/stanzabase
|
api/xmlstream/stanzabase
|
||||||
api/xmlstream/handler
|
api/xmlstream/handler
|
||||||
api/xmlstream/matcher
|
api/xmlstream/matcher
|
||||||
|
api/xmlstream/xmlstream
|
||||||
api/xmlstream/scheduler
|
api/xmlstream/scheduler
|
||||||
api/xmlstream/tostring
|
api/xmlstream/tostring
|
||||||
api/xmlstream/filesocket
|
api/xmlstream/filesocket
|
||||||
|
|
||||||
|
Core Stanzas
|
||||||
|
~~~~~~~~~~~~
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
api/stanza/rootstanza
|
||||||
|
api/stanza/message
|
||||||
|
api/stanza/presence
|
||||||
|
api/stanza/iq
|
||||||
|
api/stanza/error
|
||||||
|
api/stanza/stream_error
|
||||||
|
|
||||||
|
Plugins
|
||||||
|
~~~~~~~
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
|
||||||
Additional Info
|
Additional Info
|
||||||
---------------
|
---------------
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
|
|
@ -30,66 +30,59 @@ class MatchXMLMask(MatcherBase):
|
||||||
XML pattern, or mask. For example, message stanzas with body elements
|
XML pattern, or mask. For example, message stanzas with body elements
|
||||||
could be matched using the mask:
|
could be matched using the mask:
|
||||||
|
|
||||||
|
.. code-block:: xml
|
||||||
|
|
||||||
<message xmlns="jabber:client"><body /></message>
|
<message xmlns="jabber:client"><body /></message>
|
||||||
|
|
||||||
Use of XMLMask is discouraged, and XPath or StanzaPath should be used
|
Use of XMLMask is discouraged, and
|
||||||
instead.
|
: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
|
The use of namespaces in the mask comparison is controlled by
|
||||||
IGNORE_NS. Setting IGNORE_NS to True will disable namespace based matching
|
``IGNORE_NS``. Setting ``IGNORE_NS`` to ``True`` will disable namespace
|
||||||
for ALL XMLMask matchers.
|
based matching for ALL XMLMask matchers.
|
||||||
|
|
||||||
Methods:
|
:param criteria: Either an :class:`~xml.etree.ElementTree.Element` XML
|
||||||
match -- Overrides MatcherBase.match.
|
object or XML string to use as a mask.
|
||||||
setDefaultNS -- Set the default namespace for the mask.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, criteria):
|
def __init__(self, criteria):
|
||||||
"""
|
|
||||||
Create a new XMLMask matcher.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
criteria -- Either an XML object or XML string to use as a mask.
|
|
||||||
"""
|
|
||||||
MatcherBase.__init__(self, criteria)
|
MatcherBase.__init__(self, criteria)
|
||||||
if isinstance(criteria, str):
|
if isinstance(criteria, str):
|
||||||
self._criteria = ET.fromstring(self._criteria)
|
self._criteria = ET.fromstring(self._criteria)
|
||||||
self.default_ns = 'jabber:client'
|
self.default_ns = 'jabber:client'
|
||||||
|
|
||||||
def setDefaultNS(self, ns):
|
def setDefaultNS(self, ns):
|
||||||
"""
|
"""Set the default namespace to use during comparisons.
|
||||||
Set the default namespace to use during comparisons.
|
|
||||||
|
|
||||||
Arguments:
|
:param ns: The new namespace to use as the default.
|
||||||
ns -- The new namespace to use as the default.
|
|
||||||
"""
|
"""
|
||||||
self.default_ns = ns
|
self.default_ns = ns
|
||||||
|
|
||||||
def match(self, xml):
|
def match(self, xml):
|
||||||
"""
|
"""Compare a stanza object or XML object against the stored XML mask.
|
||||||
Compare a stanza object or XML object against the stored XML mask.
|
|
||||||
|
|
||||||
Overrides MatcherBase.match.
|
Overrides MatcherBase.match.
|
||||||
|
|
||||||
Arguments:
|
:param xml: The stanza object or XML object to compare against.
|
||||||
xml -- The stanza object or XML object to compare against.
|
|
||||||
"""
|
"""
|
||||||
if hasattr(xml, 'xml'):
|
if hasattr(xml, 'xml'):
|
||||||
xml = xml.xml
|
xml = xml.xml
|
||||||
return self._mask_cmp(xml, self._criteria, True)
|
return self._mask_cmp(xml, self._criteria, True)
|
||||||
|
|
||||||
def _mask_cmp(self, source, mask, use_ns=False, default_ns='__no_ns__'):
|
def _mask_cmp(self, source, mask, use_ns=False, default_ns='__no_ns__'):
|
||||||
"""
|
"""Compare an XML object against an XML mask.
|
||||||
Compare an XML object against an XML mask.
|
|
||||||
|
|
||||||
Arguments:
|
:param source: The :class:`~xml.etree.ElementTree.Element` XML object
|
||||||
source -- The XML object to compare against the mask.
|
to compare against the mask.
|
||||||
mask -- The XML object serving as the mask.
|
:param mask: The :class:`~xml.etree.ElementTree.Element` XML object
|
||||||
use_ns -- Indicates if namespaces should be respected during
|
serving as the mask.
|
||||||
|
:param use_ns: Indicates if namespaces should be respected during
|
||||||
the comparison.
|
the comparison.
|
||||||
default_ns -- The default namespace to apply to elements that
|
:default_ns: The default namespace to apply to elements that
|
||||||
do not have a specified namespace.
|
do not have a specified namespace.
|
||||||
Defaults to "__no_ns__".
|
Defaults to ``"__no_ns__"``.
|
||||||
"""
|
"""
|
||||||
use_ns = not IGNORE_NS
|
use_ns = not IGNORE_NS
|
||||||
|
|
||||||
|
@ -148,14 +141,13 @@ class MatchXMLMask(MatcherBase):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _get_child(self, xml, tag):
|
def _get_child(self, xml, tag):
|
||||||
"""
|
"""Return a child element given its tag, ignoring namespace values.
|
||||||
Return a child element given its tag, ignoring namespace values.
|
|
||||||
|
|
||||||
Returns None if the child was not found.
|
Returns ``None`` if the child was not found.
|
||||||
|
|
||||||
Arguments:
|
:param xml: The :class:`~xml.etree.ElementTree.Element` XML object
|
||||||
xml -- The XML object to search for the given child tag.
|
to search for the given child tag.
|
||||||
tag -- The name of the subelement to find.
|
:param tag: The name of the subelement to find.
|
||||||
"""
|
"""
|
||||||
tag = tag.split('}')[-1]
|
tag = tag.split('}')[-1]
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,9 +1,16 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
"""
|
"""
|
||||||
SleekXMPP: The Sleek XMPP Library
|
sleekxmpp.xmlstream.xmlstream
|
||||||
Copyright (C) 2010 Nathanael C. Fritz
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
This file is part of SleekXMPP.
|
|
||||||
|
|
||||||
See the file LICENSE for copying permission.
|
This module provides the module for creating and
|
||||||
|
interacting with generic XML streams, along with
|
||||||
|
the necessary eventing infrastructure.
|
||||||
|
|
||||||
|
Part of SleekXMPP: The Sleek XMPP Library
|
||||||
|
|
||||||
|
:copyright: (c) 2011 Nathanael C. Fritz
|
||||||
|
:license: MIT, see LICENSE for more details
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import with_statement, unicode_literals
|
from __future__ import with_statement, unicode_literals
|
||||||
|
@ -45,32 +52,35 @@ else:
|
||||||
DNSPYTHON = True
|
DNSPYTHON = True
|
||||||
|
|
||||||
|
|
||||||
# The time in seconds to wait before timing out waiting for response stanzas.
|
#: The time in seconds to wait before timing out waiting for response stanzas.
|
||||||
RESPONSE_TIMEOUT = 30
|
RESPONSE_TIMEOUT = 30
|
||||||
|
|
||||||
# The time in seconds to wait for events from the event queue, and also the
|
#: The time in seconds to wait for events from the event queue, and also the
|
||||||
# time between checks for the process stop signal.
|
#: time between checks for the process stop signal.
|
||||||
WAIT_TIMEOUT = 1
|
WAIT_TIMEOUT = 1
|
||||||
|
|
||||||
# The number of threads to use to handle XML stream events. This is not the
|
#: The number of threads to use to handle XML stream events. This is not the
|
||||||
# same as the number of custom event handling threads. HANDLER_THREADS must
|
#: same as the number of custom event handling threads.
|
||||||
# be at least 1.
|
#: :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.
|
||||||
HANDLER_THREADS = 1
|
HANDLER_THREADS = 1
|
||||||
|
|
||||||
# Flag indicating if the SSL library is available for use.
|
#: Flag indicating if the SSL library is available for use.
|
||||||
SSL_SUPPORT = True
|
SSL_SUPPORT = True
|
||||||
|
|
||||||
# The time in seconds to delay between attempts to resend data
|
#: The time in seconds to delay between attempts to resend data
|
||||||
# after an SSL error.
|
#: after an SSL error.
|
||||||
SSL_RETRY_DELAY = 0.5
|
SSL_RETRY_DELAY = 0.5
|
||||||
|
|
||||||
# The maximum number of times to attempt resending data due to
|
#: The maximum number of times to attempt resending data due to
|
||||||
# an SSL error.
|
#: an SSL error.
|
||||||
SSL_RETRY_MAX = 10
|
SSL_RETRY_MAX = 10
|
||||||
|
|
||||||
# Maximum time to delay between connection attempts is one hour.
|
#: Maximum time to delay between connection attempts is one hour.
|
||||||
RECONNECT_MAX_DELAY = 600
|
RECONNECT_MAX_DELAY = 600
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -93,117 +103,83 @@ class XMLStream(object):
|
||||||
streams should be complete and valid XML documents.
|
streams should be complete and valid XML documents.
|
||||||
|
|
||||||
Three types of events are provided to manage the stream:
|
Three types of events are provided to manage the stream:
|
||||||
Stream -- Triggered based on received stanzas, similar in concept
|
:Stream: Triggered based on received stanzas, similar in concept
|
||||||
to events in a SAX XML parser.
|
to events in a SAX XML parser.
|
||||||
Custom -- Triggered manually.
|
:Custom: Triggered manually.
|
||||||
Scheduled -- Triggered based on time delays.
|
:Scheduled: Triggered based on time delays.
|
||||||
|
|
||||||
Typically, stanzas are first processed by a stream event handler which
|
Typically, stanzas are first processed by a stream event handler which
|
||||||
will then trigger custom events to continue further processing,
|
will then trigger custom events to continue further processing,
|
||||||
especially since custom event handlers may run in individual threads.
|
especially since custom event handlers may run in individual threads.
|
||||||
|
|
||||||
|
:param socket: Use an existing socket for the stream. Defaults to
|
||||||
Attributes:
|
``None`` to generate a new socket.
|
||||||
address -- The hostname and port of the server.
|
:param string host: The name of the target server.
|
||||||
default_ns -- The default XML namespace that will be applied
|
:param int port: The port to use for the connection. Defaults to 0.
|
||||||
to all non-namespaced stanzas.
|
|
||||||
event_queue -- A queue of stream, custom, and scheduled
|
|
||||||
events to be processed.
|
|
||||||
filesocket -- A filesocket created from the main connection socket.
|
|
||||||
Required for ElementTree.iterparse.
|
|
||||||
default_port -- Default port to connect to.
|
|
||||||
namespace_map -- Optional mapping of namespaces to namespace prefixes.
|
|
||||||
scheduler -- A scheduler object for triggering events
|
|
||||||
after a given period of time.
|
|
||||||
send_queue -- A queue of stanzas to be sent on the stream.
|
|
||||||
socket -- The connection to the server.
|
|
||||||
ssl_support -- Indicates if a SSL library is available for use.
|
|
||||||
ssl_version -- The version of the SSL protocol to use.
|
|
||||||
Defaults to ssl.PROTOCOL_TLSv1.
|
|
||||||
ca_certs -- File path to a CA certificate to verify the
|
|
||||||
server's identity.
|
|
||||||
state -- A state machine for managing the stream's
|
|
||||||
connection state.
|
|
||||||
stream_footer -- The start tag and any attributes for the stream's
|
|
||||||
root element.
|
|
||||||
stream_header -- The closing tag of the stream's root element.
|
|
||||||
use_ssl -- Flag indicating if SSL should be used.
|
|
||||||
use_tls -- Flag indicating if TLS should be used.
|
|
||||||
use_proxy -- Flag indicating that an HTTP Proxy should be used.
|
|
||||||
stop -- threading Event used to stop all threads.
|
|
||||||
proxy_config -- An optional dictionary with the following entries:
|
|
||||||
host -- The host offering proxy services.
|
|
||||||
port -- The port for the proxy service.
|
|
||||||
username -- Optional username for the proxy.
|
|
||||||
password -- Optional password for the proxy.
|
|
||||||
|
|
||||||
auto_reconnect -- Flag to determine whether we auto reconnect.
|
|
||||||
reconnect_max_delay -- Maximum time to delay between connection
|
|
||||||
attempts. Defaults to RECONNECT_MAX_DELAY,
|
|
||||||
which is one hour.
|
|
||||||
dns_answers -- List of dns answers not yet used to connect.
|
|
||||||
|
|
||||||
Methods:
|
|
||||||
add_event_handler -- Add a handler for a custom event.
|
|
||||||
add_handler -- Shortcut method for registerHandler.
|
|
||||||
connect -- Connect to the given server.
|
|
||||||
del_event_handler -- Remove a handler for a custom event.
|
|
||||||
disconnect -- Disconnect from the server and terminate
|
|
||||||
processing.
|
|
||||||
event -- Trigger a custom event.
|
|
||||||
get_id -- Return the current stream ID.
|
|
||||||
incoming_filter -- Optionally filter stanzas before processing.
|
|
||||||
new_id -- Generate a new, unique ID value.
|
|
||||||
process -- Read XML stanzas from the stream and apply
|
|
||||||
matching stream handlers.
|
|
||||||
reconnect -- Reestablish a connection to the server.
|
|
||||||
register_handler -- Add a handler for a stream event.
|
|
||||||
register_stanza -- Add a new stanza object type that may appear
|
|
||||||
as a direct child of the stream's root.
|
|
||||||
remove_handler -- Remove a stream handler.
|
|
||||||
remove_stanza -- Remove a stanza object type.
|
|
||||||
schedule -- Schedule an event handler to execute after a
|
|
||||||
given delay.
|
|
||||||
send -- Send a stanza object on the stream.
|
|
||||||
send_raw -- Send a raw string on the stream.
|
|
||||||
send_xml -- Send an XML string on the stream.
|
|
||||||
set_socket -- Set the stream's socket and generate a new
|
|
||||||
filesocket.
|
|
||||||
start_stream_handler -- Perform any stream initialization such
|
|
||||||
as handshakes.
|
|
||||||
start_tls -- Establish a TLS connection and restart
|
|
||||||
the stream.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, socket=None, host='', port=0):
|
def __init__(self, socket=None, host='', port=0):
|
||||||
"""
|
#: Flag indicating if the SSL library is available for use.
|
||||||
Establish a new XML stream.
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
socket -- Use an existing socket for the stream.
|
|
||||||
Defaults to None to generate a new socket.
|
|
||||||
host -- The name of the target server.
|
|
||||||
Defaults to the empty string.
|
|
||||||
port -- The port to use for the connection.
|
|
||||||
Defaults to 0.
|
|
||||||
"""
|
|
||||||
self.ssl_support = SSL_SUPPORT
|
self.ssl_support = SSL_SUPPORT
|
||||||
|
|
||||||
|
#: Most XMPP servers support TLSv1, but OpenFire in particular
|
||||||
|
#: does not work well with it. For OpenFire, set
|
||||||
|
#: :attr:`ssl_version` to use ``SSLv23``::
|
||||||
|
#:
|
||||||
|
#: import ssl
|
||||||
|
#: xmpp.ssl_version = ssl.PROTOCOL_SSLv23
|
||||||
self.ssl_version = ssl.PROTOCOL_TLSv1
|
self.ssl_version = ssl.PROTOCOL_TLSv1
|
||||||
|
|
||||||
|
#: 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
|
self.ca_certs = None
|
||||||
|
|
||||||
|
#: 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
|
self.wait_timeout = WAIT_TIMEOUT
|
||||||
|
|
||||||
|
#: The time in seconds to wait before timing out waiting
|
||||||
|
#: for response stanzas.
|
||||||
self.response_timeout = RESPONSE_TIMEOUT
|
self.response_timeout = RESPONSE_TIMEOUT
|
||||||
|
|
||||||
|
#: 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
|
self.reconnect_delay = None
|
||||||
|
|
||||||
|
#: Maximum time to delay between connection attempts is one hour.
|
||||||
self.reconnect_max_delay = RECONNECT_MAX_DELAY
|
self.reconnect_max_delay = RECONNECT_MAX_DELAY
|
||||||
|
|
||||||
|
#: The time in seconds to delay between attempts to resend data
|
||||||
|
#: after an SSL error.
|
||||||
self.ssl_retry_max = SSL_RETRY_MAX
|
self.ssl_retry_max = SSL_RETRY_MAX
|
||||||
|
|
||||||
|
#: The maximum number of times to attempt resending data due to
|
||||||
|
#: an SSL error.
|
||||||
self.ssl_retry_delay = SSL_RETRY_DELAY
|
self.ssl_retry_delay = SSL_RETRY_DELAY
|
||||||
|
|
||||||
|
#: The connection state machine tracks if the stream is
|
||||||
|
#: ``'connected'`` or ``'disconnected'``.
|
||||||
self.state = StateMachine(('disconnected', 'connected'))
|
self.state = StateMachine(('disconnected', 'connected'))
|
||||||
self.state._set_state('disconnected')
|
self.state._set_state('disconnected')
|
||||||
|
|
||||||
|
#: The default port to return when querying DNS records.
|
||||||
self.default_port = int(port)
|
self.default_port = int(port)
|
||||||
|
|
||||||
|
#: The domain to try when querying DNS records.
|
||||||
self.default_domain = ''
|
self.default_domain = ''
|
||||||
|
|
||||||
|
#: The desired, or actual, address of the connected server.
|
||||||
self.address = (host, int(port))
|
self.address = (host, int(port))
|
||||||
|
|
||||||
|
#: A file-like wrapper for the socket for use with the
|
||||||
|
#: :mod:`~xml.etree.ElementTree` module.
|
||||||
self.filesocket = None
|
self.filesocket = None
|
||||||
self.set_socket(socket)
|
self.set_socket(socket)
|
||||||
|
|
||||||
|
@ -212,31 +188,79 @@ class XMLStream(object):
|
||||||
else:
|
else:
|
||||||
self.socket_class = Socket.socket
|
self.socket_class = Socket.socket
|
||||||
|
|
||||||
|
#: Enable connecting to the server directly over SSL, in
|
||||||
|
#: particular when the service provides two ports: one for
|
||||||
|
#: non-SSL traffic and another for SSL traffic.
|
||||||
self.use_ssl = False
|
self.use_ssl = False
|
||||||
|
|
||||||
|
#: Enable connecting to the service without using SSL
|
||||||
|
#: immediately, but allow upgrading the connection later
|
||||||
|
#: to use SSL.
|
||||||
self.use_tls = False
|
self.use_tls = False
|
||||||
|
|
||||||
|
#: If set to ``True``, attempt to connect through an HTTP
|
||||||
|
#: proxy based on the settings in :attr:`proxy_config`.
|
||||||
self.use_proxy = False
|
self.use_proxy = False
|
||||||
|
|
||||||
|
#: An optional dictionary of proxy settings. It may provide:
|
||||||
|
#: :host: The host offering proxy services.
|
||||||
|
#: :port: The port for the proxy service.
|
||||||
|
#: :username: Optional username for accessing the proxy.
|
||||||
|
#: :password: Optional password for accessing the proxy.
|
||||||
self.proxy_config = {}
|
self.proxy_config = {}
|
||||||
|
|
||||||
|
#: The default namespace of the stream content, not of the
|
||||||
|
#: stream wrapper itself.
|
||||||
self.default_ns = ''
|
self.default_ns = ''
|
||||||
|
|
||||||
|
#: The namespace of the enveloping stream element.
|
||||||
self.stream_ns = ''
|
self.stream_ns = ''
|
||||||
|
|
||||||
|
#: The default opening tag for the stream element.
|
||||||
self.stream_header = "<stream>"
|
self.stream_header = "<stream>"
|
||||||
|
|
||||||
|
#: The default closing tag for the stream element.
|
||||||
self.stream_footer = "</stream>"
|
self.stream_footer = "</stream>"
|
||||||
|
|
||||||
|
#: If ``True``, periodically send a whitespace character over the
|
||||||
|
#: wire to keep the connection alive. Mainly useful for connections
|
||||||
|
#: traversing NAT.
|
||||||
self.whitespace_keepalive = True
|
self.whitespace_keepalive = True
|
||||||
|
|
||||||
|
#: The default interval between keepalive signals when
|
||||||
|
#: :attr:`whitespace_keepalive` is enabled.
|
||||||
self.whitespace_keepalive_interval = 300
|
self.whitespace_keepalive_interval = 300
|
||||||
|
|
||||||
|
#: An :class:`~threading.Event` to signal that the application
|
||||||
|
#: is stopping, and that all threads should shutdown.
|
||||||
self.stop = threading.Event()
|
self.stop = threading.Event()
|
||||||
|
|
||||||
|
#: An :class:`~threading.Event` to signal receiving a closing
|
||||||
|
#: stream tag from the server.
|
||||||
self.stream_end_event = threading.Event()
|
self.stream_end_event = threading.Event()
|
||||||
self.stream_end_event.set()
|
self.stream_end_event.set()
|
||||||
|
|
||||||
|
#: An :class:`~threading.Event` to signal the start of a stream
|
||||||
|
#: session. Until this event fires, the send queue is not used
|
||||||
|
#: and data is sent immediately over the wire.
|
||||||
self.session_started_event = threading.Event()
|
self.session_started_event = threading.Event()
|
||||||
|
|
||||||
|
#: The default time in seconds to wait for a session to start
|
||||||
|
#: after connecting before reconnecting and trying again.
|
||||||
self.session_timeout = 45
|
self.session_timeout = 45
|
||||||
|
|
||||||
|
#: A queue of stream, custom, and scheduled events to be processed.
|
||||||
self.event_queue = queue.Queue()
|
self.event_queue = queue.Queue()
|
||||||
self.send_queue = queue.Queue()
|
|
||||||
self.__failed_send_stanza = None
|
|
||||||
self.scheduler = Scheduler(self.stop)
|
|
||||||
|
|
||||||
|
#: A queue of string data to be sent over the stream.
|
||||||
|
self.send_queue = queue.Queue()
|
||||||
|
|
||||||
|
#: A :class:`~sleekxmpp.xmlstream.scheduler.Scheduler` instance for
|
||||||
|
#: executing callbacks in the future based on time delays.
|
||||||
|
self.scheduler = Scheduler(self.stop)
|
||||||
|
self.__failed_send_stanza = None
|
||||||
|
|
||||||
|
#: A mapping of XML namespaces to well-known prefixes.
|
||||||
self.namespace_map = {StanzaBase.xml_ns: 'xml'}
|
self.namespace_map = {StanzaBase.xml_ns: 'xml'}
|
||||||
|
|
||||||
self.__thread = {}
|
self.__thread = {}
|
||||||
|
@ -248,7 +272,11 @@ class XMLStream(object):
|
||||||
self._id = 0
|
self._id = 0
|
||||||
self._id_lock = threading.Lock()
|
self._id_lock = threading.Lock()
|
||||||
|
|
||||||
|
#: The :attr:`auto_reconnnect` setting controls whether or not
|
||||||
|
#: the stream will be restarted in the event of an error.
|
||||||
self.auto_reconnect = True
|
self.auto_reconnect = True
|
||||||
|
|
||||||
|
#: A list of DNS results that have not yet been tried.
|
||||||
self.dns_answers = []
|
self.dns_answers = []
|
||||||
|
|
||||||
self.add_event_handler('connected', self._handle_connected)
|
self.add_event_handler('connected', self._handle_connected)
|
||||||
|
@ -256,17 +284,16 @@ class XMLStream(object):
|
||||||
self.add_event_handler('session_end', self._end_keepalive)
|
self.add_event_handler('session_end', self._end_keepalive)
|
||||||
|
|
||||||
def use_signals(self, signals=None):
|
def use_signals(self, signals=None):
|
||||||
"""
|
"""Register signal handlers for ``SIGHUP`` and ``SIGTERM``.
|
||||||
Register signal handlers for SIGHUP and SIGTERM, if possible,
|
|
||||||
which will raise a "killed" event when the application is
|
By using signals, a ``'killed'`` event will be raised when the
|
||||||
terminated.
|
application is terminated.
|
||||||
|
|
||||||
If a signal handler already existed, it will be executed first,
|
If a signal handler already existed, it will be executed first,
|
||||||
before the "killed" event is raised.
|
before the ``'killed'`` event is raised.
|
||||||
|
|
||||||
Arguments:
|
:param list signals: A list of signal names to be monitored.
|
||||||
signals -- A list of signal names to be monitored.
|
Defaults to ``['SIGHUP', 'SIGTERM']``.
|
||||||
Defaults to ['SIGHUP', 'SIGTERM'].
|
|
||||||
"""
|
"""
|
||||||
if signals is None:
|
if signals is None:
|
||||||
signals = ['SIGHUP', 'SIGTERM']
|
signals = ['SIGHUP', 'SIGTERM']
|
||||||
|
@ -282,7 +309,7 @@ class XMLStream(object):
|
||||||
def handle_kill(signum, frame):
|
def handle_kill(signum, frame):
|
||||||
"""
|
"""
|
||||||
Capture kill event and disconnect cleanly after first
|
Capture kill event and disconnect cleanly after first
|
||||||
spawning the "killed" event.
|
spawning the ``'killed'`` event.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if signum in existing_handlers and \
|
if signum in existing_handlers and \
|
||||||
|
@ -303,8 +330,7 @@ class XMLStream(object):
|
||||||
"SleekXMPP is not running from a main thread.")
|
"SleekXMPP is not running from a main thread.")
|
||||||
|
|
||||||
def new_id(self):
|
def new_id(self):
|
||||||
"""
|
"""Generate and return a new stream ID in hexadecimal form.
|
||||||
Generate and return a new stream ID in hexadecimal form.
|
|
||||||
|
|
||||||
Many stanzas, handlers, or matchers may require unique
|
Many stanzas, handlers, or matchers may require unique
|
||||||
ID values. Using this method ensures that all new ID values
|
ID values. Using this method ensures that all new ID values
|
||||||
|
@ -315,25 +341,24 @@ class XMLStream(object):
|
||||||
return self.get_id()
|
return self.get_id()
|
||||||
|
|
||||||
def get_id(self):
|
def get_id(self):
|
||||||
"""
|
"""Return the current unique stream ID in hexadecimal form."""
|
||||||
Return the current unique stream ID in hexadecimal form.
|
|
||||||
"""
|
|
||||||
return "%X" % self._id
|
return "%X" % self._id
|
||||||
|
|
||||||
def connect(self, host='', port=0, use_ssl=False,
|
def connect(self, host='', port=0, use_ssl=False,
|
||||||
use_tls=True, reattempt=True):
|
use_tls=True, reattempt=True):
|
||||||
"""
|
"""Create a new socket and connect to the server.
|
||||||
Create a new socket and connect to the server.
|
|
||||||
|
|
||||||
Setting reattempt to True will cause connection attempts to be made
|
Setting ``reattempt`` to ``True`` will cause connection attempts to
|
||||||
every second until a successful connection is established.
|
be made every second until a successful connection is established.
|
||||||
|
|
||||||
Arguments:
|
:param host: The name of the desired server for the connection.
|
||||||
host -- The name of the desired server for the connection.
|
:param port: Port to connect to on the server.
|
||||||
port -- Port to connect to on the server.
|
:param use_ssl: Flag indicating if SSL should be used by connecting
|
||||||
use_ssl -- Flag indicating if SSL should be used.
|
directly to a port using SSL.
|
||||||
use_tls -- Flag indicating if TLS should be used.
|
:param use_tls: Flag indicating if TLS should be used, allowing for
|
||||||
reattempt -- Flag indicating if the socket should reconnect
|
connecting to a port without using SSL immediately and
|
||||||
|
later upgrading the connection.
|
||||||
|
:param reattempt: Flag indicating if the socket should reconnect
|
||||||
after disconnections.
|
after disconnections.
|
||||||
"""
|
"""
|
||||||
if host and port:
|
if host and port:
|
||||||
|
@ -486,23 +511,24 @@ class XMLStream(object):
|
||||||
_handle_session_timeout)
|
_handle_session_timeout)
|
||||||
|
|
||||||
def disconnect(self, reconnect=False, wait=False):
|
def disconnect(self, reconnect=False, wait=False):
|
||||||
"""
|
"""Terminate processing and close the XML streams.
|
||||||
Terminate processing and close the XML streams.
|
|
||||||
|
|
||||||
Optionally, the connection may be reconnected and
|
Optionally, the connection may be reconnected and
|
||||||
resume processing afterwards.
|
resume processing afterwards.
|
||||||
|
|
||||||
If the disconnect should take place after all items
|
If the disconnect should take place after all items
|
||||||
in the send queue have been sent, use wait=True. However,
|
in the send queue have been sent, use ``wait=True``.
|
||||||
take note: If you are constantly adding items to the queue
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
If you are constantly adding items to the queue
|
||||||
such that it is never empty, then the disconnect will
|
such that it is never empty, then the disconnect will
|
||||||
not occur and the call will continue to block.
|
not occur and the call will continue to block.
|
||||||
|
|
||||||
Arguments:
|
:param reconnect: Flag indicating if the connection
|
||||||
reconnect -- Flag indicating if the connection
|
|
||||||
and processing should be restarted.
|
and processing should be restarted.
|
||||||
Defaults to False.
|
Defaults to ``False``.
|
||||||
wait -- Flag indicating if the send queue should
|
:param wait: Flag indicating if the send queue should
|
||||||
be emptied before disconnecting.
|
be emptied before disconnecting.
|
||||||
"""
|
"""
|
||||||
self.state.transition('connected', 'disconnected',
|
self.state.transition('connected', 'disconnected',
|
||||||
|
@ -536,9 +562,7 @@ class XMLStream(object):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def reconnect(self, reattempt=True):
|
def reconnect(self, reattempt=True):
|
||||||
"""
|
"""Reset the stream's state and reconnect to the server."""
|
||||||
Reset the stream's state and reconnect to the server.
|
|
||||||
"""
|
|
||||||
log.debug("reconnecting...")
|
log.debug("reconnecting...")
|
||||||
if self.state.ensure('connected'):
|
if self.state.ensure('connected'):
|
||||||
self.state.transition('connected', 'disconnected', wait=2.0,
|
self.state.transition('connected', 'disconnected', wait=2.0,
|
||||||
|
@ -554,14 +578,13 @@ class XMLStream(object):
|
||||||
return connected
|
return connected
|
||||||
|
|
||||||
def set_socket(self, socket, ignore=False):
|
def set_socket(self, socket, ignore=False):
|
||||||
"""
|
"""Set the socket to use for the stream.
|
||||||
Set the socket to use for the stream.
|
|
||||||
|
|
||||||
The filesocket will be recreated as well.
|
The filesocket will be recreated as well.
|
||||||
|
|
||||||
Arguments:
|
:param socket: The new socket object to use.
|
||||||
socket -- The new socket to use.
|
:param bool ignore: If ``True``, don't set the connection
|
||||||
ignore -- don't set the state
|
state to ``'connected'``.
|
||||||
"""
|
"""
|
||||||
self.socket = socket
|
self.socket = socket
|
||||||
if socket is not None:
|
if socket is not None:
|
||||||
|
@ -579,8 +602,7 @@ class XMLStream(object):
|
||||||
self.state._set_state('connected')
|
self.state._set_state('connected')
|
||||||
|
|
||||||
def configure_socket(self):
|
def configure_socket(self):
|
||||||
"""
|
"""Set timeout and other options for self.socket.
|
||||||
Set timeout and other options for self.socket.
|
|
||||||
|
|
||||||
Meant to be overridden.
|
Meant to be overridden.
|
||||||
"""
|
"""
|
||||||
|
@ -588,24 +610,23 @@ class XMLStream(object):
|
||||||
|
|
||||||
def configure_dns(self, resolver, domain=None, port=None):
|
def configure_dns(self, resolver, domain=None, port=None):
|
||||||
"""
|
"""
|
||||||
Configure and set options for a dns.resolver.Resolver
|
Configure and set options for a :class:`~dns.resolver.Resolver`
|
||||||
instance, and other DNS related tasks. For example, you
|
instance, and other DNS related tasks. For example, you
|
||||||
can also check Socket.getaddrinfo to see if you need to
|
can also check :meth:`~socket.socket.getaddrinfo` to see
|
||||||
call out to libresolv.so.2 to run res_init().
|
if you need to call out to ``libresolv.so.2`` to
|
||||||
|
run ``res_init()``.
|
||||||
|
|
||||||
Meant to be overridden.
|
Meant to be overridden.
|
||||||
|
|
||||||
Arguments:
|
:param resolver: A :class:`~dns.resolver.Resolver` instance
|
||||||
resolver -- A dns.resolver.Resolver instance, or None
|
or ``None`` if ``dnspython`` is not installed.
|
||||||
if dnspython is not installed.
|
:param domain: The initial domain under consideration.
|
||||||
domain -- The initial domain under consideration.
|
:param port: The initial port under consideration.
|
||||||
port -- The initial port under consideration.
|
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def start_tls(self):
|
def start_tls(self):
|
||||||
"""
|
"""Perform handshakes for TLS.
|
||||||
Perform handshakes for TLS.
|
|
||||||
|
|
||||||
If the handshake is successful, the XML stream will need
|
If the handshake is successful, the XML stream will need
|
||||||
to be restarted.
|
to be restarted.
|
||||||
|
@ -638,13 +659,14 @@ class XMLStream(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _start_keepalive(self, event):
|
def _start_keepalive(self, event):
|
||||||
"""
|
"""Begin sending whitespace periodically to keep the connection alive.
|
||||||
Begin sending whitespace periodically to keep the connection alive.
|
|
||||||
|
May be disabled by setting::
|
||||||
|
|
||||||
May be disabled by setting:
|
|
||||||
self.whitespace_keepalive = False
|
self.whitespace_keepalive = False
|
||||||
|
|
||||||
The keepalive interval can be set using:
|
The keepalive interval can be set using::
|
||||||
|
|
||||||
self.whitespace_keepalive_interval = 300
|
self.whitespace_keepalive_interval = 300
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
@ -662,18 +684,18 @@ class XMLStream(object):
|
||||||
self.scheduler.remove('Whitespace Keepalive')
|
self.scheduler.remove('Whitespace Keepalive')
|
||||||
|
|
||||||
def start_stream_handler(self, xml):
|
def start_stream_handler(self, xml):
|
||||||
"""
|
"""Perform any initialization actions, such as handshakes,
|
||||||
Perform any initialization actions, such as handshakes, once the
|
once the stream header has been sent.
|
||||||
stream header has been sent.
|
|
||||||
|
|
||||||
Meant to be overridden.
|
Meant to be overridden.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def register_stanza(self, stanza_class):
|
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.
|
A root stanza is one that appears as a direct child of the stream's
|
||||||
|
root element.
|
||||||
|
|
||||||
Stanzas that appear as substanzas of a root stanza do not need to
|
Stanzas that appear as substanzas of a root stanza do not need to
|
||||||
be registered here. That is done using register_stanza_plugin() from
|
be registered here. That is done using register_stanza_plugin() from
|
||||||
|
@ -683,15 +705,15 @@ class XMLStream(object):
|
||||||
stanza objects, but may still be processed using handlers and
|
stanza objects, but may still be processed using handlers and
|
||||||
matchers.
|
matchers.
|
||||||
|
|
||||||
Arguments:
|
:param stanza_class: The top-level stanza object's class.
|
||||||
stanza_class -- The top-level stanza object's class.
|
|
||||||
"""
|
"""
|
||||||
self.__root_stanza.append(stanza_class)
|
self.__root_stanza.append(stanza_class)
|
||||||
|
|
||||||
def remove_stanza(self, 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.
|
A root stanza is one that appears as a direct child of the stream's
|
||||||
|
root element.
|
||||||
|
|
||||||
Stanzas that are not registered will not be converted into
|
Stanzas that are not registered will not be converted into
|
||||||
stanza objects, but may still be processed using handlers and
|
stanza objects, but may still be processed using handlers and
|
||||||
|
@ -701,20 +723,22 @@ class XMLStream(object):
|
||||||
|
|
||||||
def add_handler(self, mask, pointer, name=None, disposable=False,
|
def add_handler(self, mask, pointer, name=None, disposable=False,
|
||||||
threaded=False, filter=False, instream=False):
|
threaded=False, filter=False, instream=False):
|
||||||
"""
|
"""A shortcut method for registering a handler using XML masks.
|
||||||
A shortcut method for registering a handler using XML masks.
|
|
||||||
|
|
||||||
Arguments:
|
The use of :meth:`register_handler()` is preferred.
|
||||||
mask -- An XML snippet matching the structure of the
|
|
||||||
|
:param mask: An XML snippet matching the structure of the
|
||||||
stanzas that will be passed to this handler.
|
stanzas that will be passed to this handler.
|
||||||
pointer -- The handler function itself.
|
:param pointer: The handler function itself.
|
||||||
name -- A unique name for the handler. A name will
|
:parm name: A unique name for the handler. A name will
|
||||||
be generated if one is not provided.
|
be generated if one is not provided.
|
||||||
disposable -- Indicates if the handler should be discarded
|
:param disposable: Indicates if the handler should be discarded
|
||||||
after one use.
|
after one use.
|
||||||
threaded -- Deprecated. Remains for backwards compatibility.
|
:param threaded: **DEPRECATED**.
|
||||||
filter -- Deprecated. Remains for backwards compatibility.
|
Remains for backwards compatibility.
|
||||||
instream -- Indicates if the handler should execute during
|
:param filter: **DEPRECATED**.
|
||||||
|
Remains for backwards compatibility.
|
||||||
|
:param instream: Indicates if the handler should execute during
|
||||||
stream processing and not during normal event
|
stream processing and not during normal event
|
||||||
processing.
|
processing.
|
||||||
"""
|
"""
|
||||||
|
@ -727,23 +751,20 @@ class XMLStream(object):
|
||||||
once=disposable, instream=instream))
|
once=disposable, instream=instream))
|
||||||
|
|
||||||
def register_handler(self, handler, before=None, after=None):
|
def register_handler(self, handler, before=None, after=None):
|
||||||
"""
|
"""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.
|
||||||
|
|
||||||
Arguments:
|
:param handler: The :class:`~sleekxmpp.xmlstream.handler.base.BaseHandler`
|
||||||
handler -- The handler object to execute.
|
derived object to execute.
|
||||||
"""
|
"""
|
||||||
if handler.stream is None:
|
if handler.stream is None:
|
||||||
self.__handlers.append(handler)
|
self.__handlers.append(handler)
|
||||||
handler.stream = weakref.ref(self)
|
handler.stream = weakref.ref(self)
|
||||||
|
|
||||||
def remove_handler(self, name):
|
def remove_handler(self, name):
|
||||||
"""
|
"""Remove any stream event handlers with the given name.
|
||||||
Remove any stream event handlers with the given name.
|
|
||||||
|
|
||||||
Arguments:
|
:param name: The name of the handler.
|
||||||
name -- The name of the handler.
|
|
||||||
"""
|
"""
|
||||||
idx = 0
|
idx = 0
|
||||||
for handler in self.__handlers:
|
for handler in self.__handlers:
|
||||||
|
@ -754,12 +775,10 @@ class XMLStream(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_dns_records(self, domain, port=None):
|
def get_dns_records(self, domain, port=None):
|
||||||
"""
|
"""Get the DNS records for a domain.
|
||||||
Get the DNS records for a domain.
|
|
||||||
|
|
||||||
Arguments:
|
:param domain: The domain in question.
|
||||||
domain -- The domain in question.
|
:param port: If the results don't include a port, use this one.
|
||||||
port -- If the results don't include a port, use this one.
|
|
||||||
"""
|
"""
|
||||||
if port is None:
|
if port is None:
|
||||||
port = self.default_port
|
port = self.default_port
|
||||||
|
@ -785,14 +804,13 @@ class XMLStream(object):
|
||||||
return [((domain, port), 0, 0)]
|
return [((domain, port), 0, 0)]
|
||||||
|
|
||||||
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.
|
|
||||||
Gets DNS answers if none available.
|
Gets DNS answers if none available.
|
||||||
Removes used answer from available answers.
|
Removes used answer from available answers.
|
||||||
|
|
||||||
Arguments:
|
:param domain: The domain in question.
|
||||||
domain -- The domain in question.
|
:param port: If the results don't include a port, use this one.
|
||||||
port -- If the results don't include a port, use this one.
|
|
||||||
"""
|
"""
|
||||||
if not self.dns_answers:
|
if not self.dns_answers:
|
||||||
self.dns_answers = self.get_dns_records(domain, port)
|
self.dns_answers = self.get_dns_records(domain, port)
|
||||||
|
@ -824,30 +842,26 @@ class XMLStream(object):
|
||||||
|
|
||||||
def add_event_handler(self, name, pointer,
|
def add_event_handler(self, name, pointer,
|
||||||
threaded=False, disposable=False):
|
threaded=False, disposable=False):
|
||||||
"""
|
"""Add a custom event handler that will be executed whenever
|
||||||
Add a custom event handler that will be executed whenever
|
|
||||||
its event is manually triggered.
|
its event is manually triggered.
|
||||||
|
|
||||||
Arguments:
|
:param name: The name of the event that will trigger
|
||||||
name -- The name of the event that will trigger
|
|
||||||
this handler.
|
this handler.
|
||||||
pointer -- The function to execute.
|
:param pointer: The function to execute.
|
||||||
threaded -- If set to True, the handler will execute
|
:param threaded: If set to ``True``, the handler will execute
|
||||||
in its own thread. Defaults to False.
|
in its own thread. Defaults to ``False``.
|
||||||
disposable -- If set to True, the handler will be
|
:param disposable: If set to ``True``, the handler will be
|
||||||
discarded after one use. Defaults to False.
|
discarded after one use. Defaults to ``False``.
|
||||||
"""
|
"""
|
||||||
if not name in self.__event_handlers:
|
if not name in self.__event_handlers:
|
||||||
self.__event_handlers[name] = []
|
self.__event_handlers[name] = []
|
||||||
self.__event_handlers[name].append((pointer, threaded, disposable))
|
self.__event_handlers[name].append((pointer, threaded, disposable))
|
||||||
|
|
||||||
def del_event_handler(self, name, pointer):
|
def del_event_handler(self, name, pointer):
|
||||||
"""
|
"""Remove a function as a handler for an event.
|
||||||
Remove a function as a handler for an event.
|
|
||||||
|
|
||||||
Arguments:
|
:param name: The name of the event.
|
||||||
name -- The name of the event.
|
:param pointer: The function to remove as a handler.
|
||||||
pointer -- The function to remove as a handler.
|
|
||||||
"""
|
"""
|
||||||
if not name in self.__event_handlers:
|
if not name in self.__event_handlers:
|
||||||
return
|
return
|
||||||
|
@ -862,25 +876,20 @@ class XMLStream(object):
|
||||||
self.__event_handlers[name]))
|
self.__event_handlers[name]))
|
||||||
|
|
||||||
def event_handled(self, name):
|
def event_handled(self, name):
|
||||||
"""
|
"""Returns the number of registered handlers for an event.
|
||||||
Indicates if an event has any associated handlers.
|
|
||||||
|
|
||||||
Returns the number of registered handlers.
|
:param name: The name of the event to check.
|
||||||
|
|
||||||
Arguments:
|
|
||||||
name -- The name of the event to check.
|
|
||||||
"""
|
"""
|
||||||
return len(self.__event_handlers.get(name, []))
|
return len(self.__event_handlers.get(name, []))
|
||||||
|
|
||||||
def event(self, name, data={}, direct=False):
|
def event(self, name, data={}, direct=False):
|
||||||
"""
|
"""Manually trigger a custom event.
|
||||||
Manually trigger a custom event.
|
|
||||||
|
|
||||||
Arguments:
|
:param name: The name of the event to trigger.
|
||||||
name -- The name of the event to trigger.
|
:param data: Data that will be passed to each event handler.
|
||||||
data -- Data that will be passed to each event handler.
|
Defaults to an empty dictionary, but is usually
|
||||||
Defaults to an empty dictionary.
|
a stanza object.
|
||||||
direct -- Runs the event directly if True, skipping the
|
:param direct: Runs the event directly if True, skipping the
|
||||||
event queue. All event handlers will run in the
|
event queue. All event handlers will run in the
|
||||||
same thread.
|
same thread.
|
||||||
"""
|
"""
|
||||||
|
@ -916,25 +925,22 @@ class XMLStream(object):
|
||||||
|
|
||||||
def schedule(self, name, seconds, callback, args=None,
|
def schedule(self, name, seconds, callback, args=None,
|
||||||
kwargs=None, repeat=False):
|
kwargs=None, repeat=False):
|
||||||
"""
|
"""Schedule a callback function to execute after a given delay.
|
||||||
Schedule a callback function to execute after a given delay.
|
|
||||||
|
|
||||||
Arguments:
|
:param name: A unique name for the scheduled callback.
|
||||||
name -- A unique name for the scheduled callback.
|
:param seconds: The time in seconds to wait before executing.
|
||||||
seconds -- The time in seconds to wait before executing.
|
:param callback: A pointer to the function to execute.
|
||||||
callback -- A pointer to the function to execute.
|
:param args: A tuple of arguments to pass to the function.
|
||||||
args -- A tuple of arguments to pass to the function.
|
:param kwargs: A dictionary of keyword arguments to pass to
|
||||||
kwargs -- A dictionary of keyword arguments to pass to
|
|
||||||
the function.
|
the function.
|
||||||
repeat -- Flag indicating if the scheduled event should
|
:param repeat: Flag indicating if the scheduled event should
|
||||||
be reset and repeat after executing.
|
be reset and repeat after executing.
|
||||||
"""
|
"""
|
||||||
self.scheduler.add(name, seconds, callback, args, kwargs,
|
self.scheduler.add(name, seconds, callback, args, kwargs,
|
||||||
repeat, qpointer=self.event_queue)
|
repeat, qpointer=self.event_queue)
|
||||||
|
|
||||||
def incoming_filter(self, xml):
|
def incoming_filter(self, xml):
|
||||||
"""
|
"""Filter incoming XML objects before they are processed.
|
||||||
Filter incoming XML objects before they are processed.
|
|
||||||
|
|
||||||
Possible uses include remapping namespaces, or correcting elements
|
Possible uses include remapping namespaces, or correcting elements
|
||||||
from sources with incorrect behavior.
|
from sources with incorrect behavior.
|
||||||
|
@ -944,23 +950,23 @@ class XMLStream(object):
|
||||||
return xml
|
return xml
|
||||||
|
|
||||||
def send(self, data, mask=None, timeout=None, now=False):
|
def send(self, data, mask=None, timeout=None, now=False):
|
||||||
"""
|
"""A wrapper for :meth:`send_raw()` for sending stanza objects.
|
||||||
A wrapper for send_raw for sending stanza objects.
|
|
||||||
|
|
||||||
May optionally block until an expected response is received.
|
May optionally block until an expected response is received.
|
||||||
|
|
||||||
Arguments:
|
:param data: The :class:`~sleekxmpp.xmlstream.stanzabase.ElementBase`
|
||||||
data -- The stanza object to send on the stream.
|
stanza to send on the stream.
|
||||||
mask -- Deprecated. An XML snippet matching the structure
|
:param mask: **DEPRECATED**
|
||||||
|
An XML string snippet matching the structure
|
||||||
of the expected response. Execution will block
|
of the expected response. Execution will block
|
||||||
in this thread until the response is received
|
in this thread until the response is received
|
||||||
or a timeout occurs.
|
or a timeout occurs.
|
||||||
timeout -- Time in seconds to wait for a response before
|
:param int timeout: Time in seconds to wait for a response before
|
||||||
continuing. Defaults to RESPONSE_TIMEOUT.
|
continuing. Defaults to :attr:`response_timeout`.
|
||||||
now -- Indicates if the send queue should be skipped,
|
:param bool now: Indicates if the send queue should be skipped,
|
||||||
sending the stanza immediately. Useful mainly
|
sending the stanza immediately. Useful mainly
|
||||||
for stream initialization stanzas.
|
for stream initialization stanzas.
|
||||||
Defaults to False.
|
Defaults to ``False``.
|
||||||
"""
|
"""
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
timeout = self.response_timeout
|
timeout = self.response_timeout
|
||||||
|
@ -977,37 +983,35 @@ class XMLStream(object):
|
||||||
return wait_for.wait(timeout)
|
return wait_for.wait(timeout)
|
||||||
|
|
||||||
def send_xml(self, data, mask=None, timeout=None, now=False):
|
def send_xml(self, data, mask=None, timeout=None, now=False):
|
||||||
"""
|
"""Send an XML object on the stream, and optionally wait
|
||||||
Send an XML object on the stream, and optionally wait
|
|
||||||
for a response.
|
for a response.
|
||||||
|
|
||||||
Arguments:
|
:param data: The :class:`~xml.etree.ElementTree.Element` XML object
|
||||||
data -- The XML object to send on the stream.
|
to send on the stream.
|
||||||
mask -- Deprecated. An XML snippet matching the structure
|
:param mask: **DEPRECATED**
|
||||||
|
An XML string snippet matching the structure
|
||||||
of the expected response. Execution will block
|
of the expected response. Execution will block
|
||||||
in this thread until the response is received
|
in this thread until the response is received
|
||||||
or a timeout occurs.
|
or a timeout occurs.
|
||||||
timeout -- Time in seconds to wait for a response before
|
:param int timeout: Time in seconds to wait for a response before
|
||||||
continuing. Defaults to RESPONSE_TIMEOUT.
|
continuing. Defaults to :attr:`response_timeout`.
|
||||||
now -- Indicates if the send queue should be skipped,
|
:param bool now: Indicates if the send queue should be skipped,
|
||||||
sending the stanza immediately. Useful mainly
|
sending the stanza immediately. Useful mainly
|
||||||
for stream initialization stanzas.
|
for stream initialization stanzas.
|
||||||
Defaults to False.
|
Defaults to ``False``.
|
||||||
"""
|
"""
|
||||||
if timeout is None:
|
if timeout is None:
|
||||||
timeout = self.response_timeout
|
timeout = self.response_timeout
|
||||||
return self.send(tostring(data), mask, timeout, now)
|
return self.send(tostring(data), mask, timeout, now)
|
||||||
|
|
||||||
def send_raw(self, data, now=False, reconnect=None):
|
def send_raw(self, data, now=False, reconnect=None):
|
||||||
"""
|
"""Send raw data across the stream.
|
||||||
Send raw data across the stream.
|
|
||||||
|
|
||||||
Arguments:
|
:param string data: Any string value.
|
||||||
data -- Any string value.
|
:param bool reconnect: Indicates if the stream should be
|
||||||
reconnect -- Indicates if the stream should be
|
|
||||||
restarted if there is an error sending
|
restarted if there is an error sending
|
||||||
the stanza. Used mainly for testing.
|
the stanza. Used mainly for testing.
|
||||||
Defaults to self.auto_reconnect.
|
Defaults to :attr:`auto_reconnect`.
|
||||||
"""
|
"""
|
||||||
if now:
|
if now:
|
||||||
log.debug("SEND (IMMED): %s", data)
|
log.debug("SEND (IMMED): %s", data)
|
||||||
|
@ -1045,27 +1049,29 @@ class XMLStream(object):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def process(self, **kwargs):
|
def process(self, **kwargs):
|
||||||
"""
|
"""Initialize the XML streams and begin processing events.
|
||||||
Initialize the XML streams and begin processing events.
|
|
||||||
|
|
||||||
The number of threads used for processing stream events is determined
|
The number of threads used for processing stream events is determined
|
||||||
by HANDLER_THREADS.
|
by :data:`HANDLER_THREADS`.
|
||||||
|
|
||||||
Arguments:
|
:param bool block: If ``False``, then event dispatcher will run
|
||||||
block -- If block=False then event dispatcher will run
|
|
||||||
in a separate thread, allowing for the stream to be
|
in a separate thread, allowing for the stream to be
|
||||||
used in the background for another application.
|
used in the background for another application.
|
||||||
Otherwise, process(block=True) blocks the current thread.
|
Otherwise, ``process(block=True)`` blocks the current
|
||||||
Defaults to False.
|
thread. Defaults to ``False``.
|
||||||
|
:param bool threaded: **DEPRECATED**
|
||||||
**threaded is deprecated and included for API compatibility**
|
If ``True``, then event dispatcher will run
|
||||||
threaded -- If threaded=True then event dispatcher will run
|
|
||||||
in a separate thread, allowing for the stream to be
|
in a separate thread, allowing for the stream to be
|
||||||
used in the background for another application.
|
used in the background for another application.
|
||||||
Defaults to True.
|
Defaults to ``True``. This does **not** mean that no
|
||||||
|
threads are used at all if ``threaded=False``.
|
||||||
|
|
||||||
Event handlers and the send queue will be threaded
|
Regardless of these threading options, these threads will
|
||||||
regardless of these parameters.
|
always exist:
|
||||||
|
|
||||||
|
- The event queue processor
|
||||||
|
- The send queue processor
|
||||||
|
- The scheduler
|
||||||
"""
|
"""
|
||||||
if 'threaded' in kwargs and 'block' in kwargs:
|
if 'threaded' in kwargs and 'block' in kwargs:
|
||||||
raise ValueError("process() called with both " + \
|
raise ValueError("process() called with both " + \
|
||||||
|
@ -1094,8 +1100,7 @@ class XMLStream(object):
|
||||||
self._process()
|
self._process()
|
||||||
|
|
||||||
def _process(self):
|
def _process(self):
|
||||||
"""
|
"""Start processing the XML streams.
|
||||||
Start processing the XML streams.
|
|
||||||
|
|
||||||
Processing will continue after any recoverable errors
|
Processing will continue after any recoverable errors
|
||||||
if reconnections are allowed.
|
if reconnections are allowed.
|
||||||
|
@ -1147,9 +1152,9 @@ class XMLStream(object):
|
||||||
break
|
break
|
||||||
|
|
||||||
def __read_xml(self):
|
def __read_xml(self):
|
||||||
"""
|
"""Parse the incoming XML stream
|
||||||
Parse the incoming XML stream, raising stream events for
|
|
||||||
each received stanza.
|
Stream events are raised for each received stanza.
|
||||||
"""
|
"""
|
||||||
depth = 0
|
depth = 0
|
||||||
root = None
|
root = None
|
||||||
|
@ -1185,15 +1190,15 @@ class XMLStream(object):
|
||||||
log.debug("Ending read XML loop")
|
log.debug("Ending read XML loop")
|
||||||
|
|
||||||
def _build_stanza(self, xml, default_ns=None):
|
def _build_stanza(self, xml, default_ns=None):
|
||||||
"""
|
"""Create a stanza object from a given XML object.
|
||||||
Create a stanza object from a given XML object.
|
|
||||||
|
|
||||||
If a specialized stanza type is not found for the XML, then
|
If a specialized stanza type is not found for the XML, then
|
||||||
a generic StanzaBase stanza will be returned.
|
a generic :class:`~sleekxmpp.xmlstream.stanzabase.StanzaBase`
|
||||||
|
stanza will be returned.
|
||||||
|
|
||||||
Arguments:
|
:param xml: The :class:`~xml.etree.ElementTree.Element` XML object
|
||||||
xml -- The XML object to convert into a stanza object.
|
to convert into a stanza object.
|
||||||
default_ns -- Optional default namespace to use instead of the
|
:param default_ns: Optional default namespace to use instead of the
|
||||||
stream's current default namespace.
|
stream's current default namespace.
|
||||||
"""
|
"""
|
||||||
if default_ns is None:
|
if default_ns is None:
|
||||||
|
@ -1213,8 +1218,8 @@ class XMLStream(object):
|
||||||
objects if applicable and queue stream events to be processed
|
objects if applicable and queue stream events to be processed
|
||||||
by matching handlers.
|
by matching handlers.
|
||||||
|
|
||||||
Arguments:
|
:param xml: The :class:`~sleekxmpp.xmlstream.stanzabase.ElementBase`
|
||||||
xml -- The XML stanza to analyze.
|
stanza to analyze.
|
||||||
"""
|
"""
|
||||||
log.debug("RECV: %s", tostring(xml, xmlns=self.default_ns,
|
log.debug("RECV: %s", tostring(xml, xmlns=self.default_ns,
|
||||||
stream=self))
|
stream=self))
|
||||||
|
@ -1250,13 +1255,11 @@ class XMLStream(object):
|
||||||
stanza.unhandled()
|
stanza.unhandled()
|
||||||
|
|
||||||
def _threaded_event_wrapper(self, func, args):
|
def _threaded_event_wrapper(self, func, args):
|
||||||
"""
|
"""Capture exceptions for event handlers that run
|
||||||
Capture exceptions for event handlers that run
|
|
||||||
in individual threads.
|
in individual threads.
|
||||||
|
|
||||||
Arguments:
|
:param func: The event handler to execute.
|
||||||
func -- The event handler to execute.
|
:param args: Arguments to the event handler.
|
||||||
args -- Arguments to the event handler.
|
|
||||||
"""
|
"""
|
||||||
# this is always already copied before this is invoked
|
# this is always already copied before this is invoked
|
||||||
orig = args[0]
|
orig = args[0]
|
||||||
|
@ -1271,8 +1274,7 @@ class XMLStream(object):
|
||||||
self.exception(e)
|
self.exception(e)
|
||||||
|
|
||||||
def _event_runner(self):
|
def _event_runner(self):
|
||||||
"""
|
"""Process the event queue and execute handlers.
|
||||||
Process the event queue and execute handlers.
|
|
||||||
|
|
||||||
The number of event runner threads is controlled by HANDLER_THREADS.
|
The number of event runner threads is controlled by HANDLER_THREADS.
|
||||||
|
|
||||||
|
@ -1341,9 +1343,7 @@ class XMLStream(object):
|
||||||
return
|
return
|
||||||
|
|
||||||
def _send_thread(self):
|
def _send_thread(self):
|
||||||
"""
|
"""Extract stanzas from the send queue and send them on the stream."""
|
||||||
Extract stanzas from the send queue and send them on the stream.
|
|
||||||
"""
|
|
||||||
try:
|
try:
|
||||||
while not self.stop.is_set():
|
while not self.stop.is_set():
|
||||||
while not self.stop.is_set and \
|
while not self.stop.is_set and \
|
||||||
|
@ -1394,13 +1394,11 @@ class XMLStream(object):
|
||||||
self.disconnect(self.auto_reconnect)
|
self.disconnect(self.auto_reconnect)
|
||||||
|
|
||||||
def exception(self, exception):
|
def exception(self, exception):
|
||||||
"""
|
"""Process an unknown exception.
|
||||||
Process an unknown exception.
|
|
||||||
|
|
||||||
Meant to be overridden.
|
Meant to be overridden.
|
||||||
|
|
||||||
Arguments:
|
:param exception: An unhandled exception object.
|
||||||
exception -- An unhandled exception object.
|
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue