diff --git a/sleekxmpp/clientxmpp.py b/sleekxmpp/clientxmpp.py index 3778ccf..20012b5 100644 --- a/sleekxmpp/clientxmpp.py +++ b/sleekxmpp/clientxmpp.py @@ -1,9 +1,15 @@ +# -*- coding: utf-8 -*- """ - SleekXMPP: The Sleek XMPP Library - Copyright (C) 2010 Nathanael C. Fritz - This file is part of SleekXMPP. + sleekxmpp.clientxmpp + ~~~~~~~~~~~~~~~~~~~~ - See the file LICENSE for copying permission. + This module provides XMPP functionality that + is specific to client connections. + + Part of SleekXMPP: The Sleek XMPP Library + + :copyright: (c) 2011 Nathanael C. Fritz + :license: MIT, see LICENSE for more details """ from __future__ import absolute_import, unicode_literals @@ -41,37 +47,30 @@ log = logging.getLogger(__name__) class ClientXMPP(BaseXMPP): """ - SleekXMPP's client class. ( Use only for good, not for evil.) + SleekXMPP's client class. (Use only for good, not for evil.) - Typical Use: - xmpp = ClientXMPP('user@server.tld/resource', 'password') - xmpp.process(block=False) // when block is True, it blocks the current - // thread. False by default. + Typical use pattern: - Attributes: + .. code-block:: python - Methods: - connect -- Overrides XMLStream.connect. - del_roster_item -- Delete a roster item. - get_roster -- Retrieve the roster from the server. - register_feature -- Register a stream feature. - update_roster -- Update a roster item. + xmpp = ClientXMPP('user@server.tld/resource', 'password') + # ... Register plugins and event handlers ... + xmpp.connect() + xmpp.process(block=False) # block=True will block the current + # thread. By default, block=False + + :param jid: The JID of the XMPP user account. + :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 + :meth:`~sleekxmpp.basexmpp.BaseXMPP.register_plugins()`. + :param escape_quotes: **Deprecated.** """ def __init__(self, jid, password, ssl=False, plugin_config={}, plugin_whitelist=[], escape_quotes=True, sasl_mech=None): - """ - Create a new SleekXMPP client. - - Arguments: - jid -- The JID of the XMPP user account. - password -- The password for the XMPP user account. - ssl -- Deprecated. - plugin_config -- A dictionary of plugin configurations. - plugin_whitelist -- A list of approved plugins that will be loaded - when calling register_plugins. - escape_quotes -- Deprecated. - """ BaseXMPP.__init__(self, jid, 'jabber:client') self.set_jid(jid) @@ -121,21 +120,19 @@ class ClientXMPP(BaseXMPP): def connect(self, address=tuple(), reattempt=True, use_tls=True, use_ssl=False): - """ - Connect to the XMPP server. + """Connect to the XMPP server. When no address is given, a SRV lookup for the server will be attempted. If that fails, the server user in the JID will be used. - Arguments: - address -- A tuple containing the server's host and port. - reattempt -- If True, reattempt the connection if an - error occurs. Defaults to True. - use_tls -- Indicates if TLS should be used for the - connection. Defaults to True. - use_ssl -- Indicates if the older SSL connection method - should be used. Defaults to False. + :param address -- A tuple containing the server's host and port. + :param reattempt: If ``True``, repeat attempting to connect if an + error occurs. Defaults to ``True``. + :param use_tls: Indicates if TLS should be used for the + connection. Defaults to ``True``. + :param use_ssl: Indicates if the older SSL connection method + should be used. Defaults to ``False``. """ self.session_started_event.clear() if not address: @@ -146,13 +143,10 @@ class ClientXMPP(BaseXMPP): reattempt=reattempt) def get_dns_records(self, domain, port=None): - """ - Get the DNS records for a domain. - Overriddes XMLStream.get_dns_records to use SRV. + """Get the DNS records for a domain, including SRV records. - Arguments: - domain -- The domain in question. - port -- If the results don't include a port, use this one. + :param domain: The domain in question. + :param port: If the results don't include a port, use this one. """ if port is None: port = self.default_port @@ -177,17 +171,15 @@ class ClientXMPP(BaseXMPP): return [((domain, port), 0, 0)] def register_feature(self, name, handler, restart=False, order=5000): - """ - Register a stream feature. + """Register a stream feature handler. - Arguments: - name -- The name of the stream feature. - handler -- The function to execute if the feature is received. - restart -- Indicates if feature processing should halt with - this feature. Defaults to False. - order -- The relative ordering in which the feature should - be negotiated. Lower values will be attempted - earlier when available. + :param name: The name of the stream feature. + :param handler: The function to execute if the feature is received. + :param restart: Indicates if feature processing should halt with + this feature. Defaults to ``False``. + :param order: The relative ordering in which the feature should + be negotiated. Lower values will be attempted + earlier when available. """ self._stream_feature_handlers[name] = (handler, restart) self._stream_feature_order.append((order, name)) @@ -195,53 +187,51 @@ class ClientXMPP(BaseXMPP): def update_roster(self, jid, name=None, subscription=None, groups=[], block=True, timeout=None, callback=None): - """ - Add or change a roster item. + """Add or change a roster item. - Arguments: - jid -- The JID of the entry to modify. - name -- The user's nickname for this JID. - subscription -- The subscription status. May be one of - 'to', 'from', 'both', or 'none'. If set - to 'remove', the entry will be deleted. - groups -- The roster groups that contain this item. - block -- Specify if the roster request will block - until a response is received, or a timeout - occurs. Defaults to True. - timeout -- The length of time (in seconds) to wait - for a response before continuing if blocking - is used. Defaults to self.response_timeout. - callback -- Optional reference to a stream handler function. - Will be executed when the roster is received. - Implies block=False. + :param jid: The JID of the entry to modify. + :param name: The user's nickname for this JID. + :param subscription: The subscription status. May be one of + ``'to'``, ``'from'``, ``'both'``, or + ``'none'``. If set to ``'remove'``, + the entry will be deleted. + :param groups: The roster groups that contain this item. + :param block: Specify if the roster request will block + until a response is received, or a timeout + 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 + :attr:`~sleekxmpp.xmlstream.xmlstream.XMLStream.response_timeout`. + :param callback: Optional reference to a stream handler function. + Will be executed when the roster is received. + Implies ``block=False``. """ return self.client_roster.update(jid, name, subscription, groups, block, timeout, callback) def del_roster_item(self, jid): - """ - Remove an item from the roster by setting its subscription - status to 'remove'. + """Remove an item from the roster. + + This is done by setting its subscription status to ``'remove'``. - Arguments: - jid -- The JID of the item to remove. + :param jid: The JID of the item to remove. """ return self.client_roster.remove(jid) def get_roster(self, block=True, timeout=None, callback=None): - """ - Request the roster from the server. + """Request the roster from the server. - Arguments: - block -- Specify if the roster request will block until a - response is received, or a timeout occurs. - Defaults to True. - timeout -- The length of time (in seconds) to wait for a response + :param block: Specify if the roster request will block until a + response is received, or a timeout 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 self.response_timeout. - callback -- Optional reference to a stream handler function. Will - be executed when the roster is received. - Implies block=False. + 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. + Implies ``block=False``. """ iq = self.Iq() iq['type'] = 'get' @@ -260,11 +250,9 @@ class ClientXMPP(BaseXMPP): self.features = set() def _handle_stream_features(self, features): - """ - Process the received stream features. + """Process the received stream features. - Arguments: - features -- The features stanza. + :param features: The features stanza. """ for order, name in self._stream_feature_order: if name in features['features']: @@ -275,13 +263,12 @@ class ClientXMPP(BaseXMPP): return True def _handle_roster(self, iq, request=False): - """ - Update the roster after receiving a roster stanza. + """Update the roster after receiving a roster stanza. - Arguments: - iq -- The roster stanza. - request -- Indicates if this stanza is a response - to a request for the roster. + :param iq: The roster stanza. + :param request: Indicates if this stanza is a response + to a request for the roster, and not an + empty acknowledgement from the server. """ if iq['type'] == 'set' or (iq['type'] == 'result' and request): for jid in iq['roster']['items']: diff --git a/sleekxmpp/componentxmpp.py b/sleekxmpp/componentxmpp.py index e98ad50..5b16c5e 100644 --- a/sleekxmpp/componentxmpp.py +++ b/sleekxmpp/componentxmpp.py @@ -1,9 +1,15 @@ +# -*- coding: utf-8 -*- """ - SleekXMPP: The Sleek XMPP Library - Copyright (C) 2010 Nathanael C. Fritz - This file is part of SleekXMPP. + sleekxmpp.clientxmpp + ~~~~~~~~~~~~~~~~~~~~ - See the file LICENSE for copying permission. + This module provides XMPP functionality that + is specific to external server component connections. + + Part of SleekXMPP: The Sleek XMPP Library + + :copyright: (c) 2011 Nathanael C. Fritz + :license: MIT, see LICENSE for more details """ from __future__ import absolute_import @@ -32,28 +38,22 @@ class ComponentXMPP(BaseXMPP): Use only for good, not for evil. - Methods: - connect -- Overrides XMLStream.connect. - incoming_filter -- Overrides XMLStream.incoming_filter. - start_stream_handler -- Overrides XMLStream.start_stream_handler. + :param jid: The JID of the component. + :param secret: The secret or password for the component. + :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 + :meth:`~sleekxmpp.basexmpp.BaseXMPP.register_plugins()`. + :param use_jc_ns: Indicates if the ``'jabber:client'`` namespace + should be used instead of the standard + ``'jabber:component:accept'`` namespace. + Defaults to ``False``. """ - def __init__(self, jid, secret, host, port, + def __init__(self, jid, secret, host=None, port=None, plugin_config={}, plugin_whitelist=[], use_jc_ns=False): - """ - Arguments: - jid -- The JID of the component. - secret -- The secret or password for the component. - host -- The server accepting the component. - port -- The port used to connect to the server. - plugin_config -- A dictionary of plugin configurations. - plugin_whitelist -- A list of desired plugins to load - when using register_plugins. - use_js_ns -- Indicates if the 'jabber:client' namespace - should be used instead of the standard - 'jabber:component:accept' namespace. - Defaults to False. - """ if use_jc_ns: default_ns = 'jabber:client' else: @@ -81,26 +81,42 @@ class ComponentXMPP(BaseXMPP): self.add_event_handler('presence_probe', self._handle_probe) - def connect(self): - """ - Connect to the server. + def connect(self, host=None, port=None, use_ssl=False, + use_tls=True, reattempt=True): + """Connect to the server. - Overrides XMLStream.connect. + Setting ``reattempt`` to ``True`` will cause connection attempts to + be made every second until a successful connection is established. + + :param host: The name of the desired server for the connection. + Defaults to :attr:`server_host`. + :param port: Port to connect to on the server. + Defauts to :attr:`server_port`. + :param use_ssl: Flag indicating if SSL should be used by connecting + directly to a port using SSL. + :param use_tls: Flag indicating if TLS should be used, allowing for + connecting to a port without using SSL immediately and + later upgrading the connection. + :param reattempt: Flag indicating if the socket should reconnect + after disconnections. """ - log.debug("Connecting to %s:%s", self.server_host, - self.server_port) - return XMLStream.connect(self, self.server_host, - self.server_port) + if host is None: + host = self.server_host + if port is None: + port = self.server_port + log.debug("Connecting to %s:%s", host, port) + return XMLStream.connect(self, host=host, port=port, + use_ssl=use_ssl, + use_tls=use_tls, + reattempt=reattempt) def incoming_filter(self, xml): """ - Pre-process incoming XML stanzas by converting any 'jabber:client' - namespaced elements to the component's default namespace. + Pre-process incoming XML stanzas by converting any + ``'jabber:client'`` namespaced elements to the component's + default namespace. - Overrides XMLStream.incoming_filter. - - Arguments: - xml -- The XML stanza to pre-process. + :param xml: The XML stanza to pre-process. """ if xml.tag.startswith('{jabber:client}'): xml.tag = xml.tag.replace('jabber:client', self.default_ns) @@ -117,10 +133,7 @@ class ComponentXMPP(BaseXMPP): Once the streams are established, attempt to handshake with the server to be accepted as a component. - Overrides BaseXMPP.start_stream_handler. - - Arguments: - xml -- The incoming stream's root element. + :param xml: The incoming stream's root element. """ BaseXMPP.start_stream_handler(self, xml) @@ -136,11 +149,9 @@ class ComponentXMPP(BaseXMPP): self.send_xml(handshake, now=True) def _handle_handshake(self, xml): - """ - The handshake has been accepted. + """The handshake has been accepted. - Arguments: - xml -- The reply handshake stanza. + :param xml: The reply handshake stanza. """ self.session_started_event.set() self.event("session_start")