disco — Service discovery support (XEP-0030)

This module provides support for Service Discovery. For this, it provides a Service subclass which can be loaded into a client using Client.summon().

Services

The following services are provided by this subpackage and available directly from aioxmpp:

DiscoServer Answer Service Discovery (XEP-0030) requests sent to this client.
DiscoClient Provide cache-backed Service Discovery (XEP-0030) queries.

Changed in version 0.8: Prior to version 0.8, both services were provided by a single class (aioxmpp.disco.Service). This is not the case anymore, and there is no replacement.

If you need to write backwards compatible code, you could be doing something like this:

try:
    aioxmpp.DiscoServer
except AttributeError:
    aioxmpp.DiscoServer = aioxmpp.disco.Service
    aioxmpp.DiscoClient = aioxmpp.disco.Service

This should work, because the old Service class provided the features of both of the individual classes.

The detailed documentation of the classes follows:

class aioxmpp.DiscoServer(client, **kwargs)

Answer Service Discovery (XEP-0030) requests sent to this client.

This service implements handlers for …disco#info and …disco#items IQ requests. It provides methods to configure the contents of these responses.

See also

DiscoClient
for a service which provides methods to query Service Discovery information from other entities.

The DiscoServer inherits from Node to manage the identities and features of the client. The identities and features declared in the service using the Node interface on the DiscoServer instance are returned when a query is received for the JID with an empty or unset node attribute. For completeness, the relevant methods are listed here. Refer to the Node documentation for details.

Note

Upon construction, the DiscoServer adds a default identity with category "client" and type "bot" to the root disco.Node. This is to comply with XEP-0030, which specifies that at least one identity must always be returned. Otherwise, the service would be forced to send a malformed response or reply with <feature-not-implemented/>.

After having added another identity, that default identity can be removed.

Other Node instances can be registered with the service using the following methods:

mount_node(mountpoint, node)

Mount the Node node to be returned when a peer requests XEP-0030 information for the node mountpoint.

unmount_node(mountpoint)

Unmount the node mounted at mountpoint.

See also

mount_node()
for a way for mounting Node instances.
class aioxmpp.DiscoClient(client, **kwargs)

Provide cache-backed Service Discovery (XEP-0030) queries.

This service provides methods to query Service Discovery information from other entities in the XMPP network. The results are cached transparently.

See also

DiscoServer
for a service which answers Service Discovery queries sent to the client by other entities.
EntityCapsService
for a service which uses XEP-0115 to fill the cache of the DiscoClient with offline information.

Querying other entities’ service discovery information:

coroutine query_info(jid, *, node=None, require_fresh=False, timeout=None)

Query the features and identities of the specified entity. The entity is identified by the jid and the optional node.

Return the xso.InfoQuery instance returned by the peer.

The requests are cached. This means that only one request is ever fired for a given target (identified by the jid and the node). The request is re-used for all subsequent requests to that identity.

If require_fresh is set to true, the above does not hold and a fresh request is always created. The new request is the request which will be used as alias for subsequent requests to the same identity.

The visible effects of this are twofold:

  • Caching: Results of requests are implicitly cached
  • Aliasing: Two concurrent requests will be aliased to one request to save computing resources

Both can be turned off by using require_fresh. In general, you should not need to use require_fresh, as all requests are implicitly cancelled whenever the underlying session gets destroyed.

The timeout can be used to restrict the time to wait for a response. If the timeout triggers, TimeoutError is raised.

If send() raises an exception, all queries which were running simultanously for the same target re-raise that exception. The result is not cached though. If a new query is sent at a later point for the same target, a new query is actually sent, independent of the value chosen for require_fresh.

coroutine query_items(jid, *, node=None, require_fresh=False, timeout=None)

Send an items query to the given jid, querying for the items at the node. Return the ItemsQuery result.

The arguments have the same semantics as with query_info(), as does the caching and error handling.

To prime the cache with information, the following method can be used:

set_info_cache(jid, node, info)

This is a wrapper around set_info_future() which creates a future and immediately assigns info as its result.

New in version 0.5.

set_info_future(jid, node, fut)

Override the cache entry (if one exists) for query_info() of the jid and node combination with the given asyncio.Future fut.

The future must receive a dict compatible to the output of xso.InfoQuery.to_dict().

As usual, the cache can be bypassed and cleared by passing require_fresh to query_info().

See also

Module aioxmpp.entitycaps
XEP-0115 implementation which uses this method to prime the cache with information derived from Entity Capability announcements.

Note

If a future is set to exception state, it will still remain and make all queries for that target fail with that exception, until a query uses require_fresh.

New in version 0.5.

Usage example, assuming that you have a node.Client client:

import aioxmpp.disco as disco
# load service into node
sd = client.summon(aioxmpp.DiscoClient)

# retrieve server information
server_info = yield from sd.query_info(
    node.local_jid.replace(localpart=None, resource=None)
)

# retrieve resources
resources = yield from sd.query_items(
    node.local_jid.bare()
)

Entity information

class aioxmpp.disco.Node

A Node holds the information related to a specific node within the entity referred to by a JID, with respect to XEP-0030 semantics.

A Node always has at least one identity (or it will return as <item-not-found/>). It may have zero or more features beyond the XEP-0030 features which are statically included.

To manage the identities and the features of a node, use the following methods:

register_feature(var)

Register a feature with the namespace variable var.

If the feature is already registered or part of the default XEP-0030 features, a ValueError is raised.

unregister_feature(var)

Unregister a feature which has previously been registered using register_feature().

If the feature has not been registered previously, KeyError is raised.

Note

The features which are mandatory per XEP-0030 are always registered and cannot be unregistered. For the purpose of unregistration, they behave as if they had never been registered; for the purpose of registration, they behave as if they had been registered before.

register_identity(category, type_, *, names={})

Register an identity with the given category and type_.

If there is already a registered identity with the same category and type_, ValueError is raised.

names may be a mapping which maps structs.LanguageTag instances to strings. This mapping will be used to produce <identity/> declarations with the respective xml:lang and name attributes.

unregister_identity(category, type_)

Unregister an identity previously registered using register_identity().

If no identity with the given category and type_ has been registered before, KeyError is raised.

If the identity to remove is the last identity of the Node, ValueError is raised; a node must always have at least one identity.

To access the declared features and identities, use:

iter_features(stanza)

Return an iterator which yields the features of the node.

Parameters:stanza (IQ) – The IQ request stanza
Return type:iterable of str
Returns:XEP-0030 features of this node

stanza is the aioxmpp.IQ stanza of the request. This can be used to filter the list according to who is asking (not recommended).

The features are returned as strings. The features demanded by XEP-0030 are always returned.

iter_identities(stanza)

Return an iterator of tuples describing the identities of the node.

Parameters:stanza (IQ) – The IQ request stanza
Return type:iterable of (str, str, str or None, str or None) tuples
Returns:XEP-0030 identities of this node

stanza is the aioxmpp.IQ stanza of the request. This can be used to hide a node depending on who is asking. If the returned iterable is empty, the DiscoServer returns an <item-not-found/> error.

Return an iterator which yields tuples consisting of the category, the type, the language code and the name of each identity declared in this Node.

Both the language code and the name may be None, if no names or a name without language code have been declared.

To access items, use:

iter_items(stanza)

Return an iterator which yields the items of the node.

Parameters:stanza (IQ) – The IQ request stanza
Return type:iterable of Item
Returns:Items of the node

stanza is the aioxmpp.IQ stanza of the request. This can be used to localize the list to the language of the stanza or filter it according to who is asking.

A bare Node cannot hold any items and will thus return an iterator which does not yield any element.

Signals provide information about changes:

signal on_info_changed()

This signal emits when a feature or identity is registered or unregistered.

As mentioned, bare Node objects have no items; there are subclasses of Node which support items:

StaticNode Support for a list of xso.Item instances
DiscoServer Support for “mountpoints” for node subtrees
class aioxmpp.disco.StaticNode

A StaticNode is a Node with a non-dynamic set of items.

items

A list of xso.Item instances. These items will be returned when the node is queried for it’s XEP-0030 items.

It is the responsibility of the user to ensure that the set of items is valid. This includes avoiding duplicate items.

class aioxmpp.disco.mount_as_node(mountpoint)

Service descriptor which mounts the Service as DiscoServer node.

Parameters:mountpoint (str) – The mountpoint at which to mount the node.

New in version 0.8.

When the service is instaniated, it is mounted as Node at the given mountpoint; it must thus also inherit from Node or implement a compatible interface.

mountpoint

The mountpoint at which the node is mounted.

class aioxmpp.disco.register_feature(feature)

Service descriptor which registers a service discovery feature.

Parameters:feature (str) – The feature to register.

New in version 0.8.

When the service is instaniated, the feature is registered at the DiscoServer.

feature

The feature which is registered.

disco.xso — IQ payloads

The submodule aioxmpp.disco.xso contains the XSO classes which describe the IQ payloads used by this subpackage.

You will encounter some of these in return values, but there should never be a need to construct them by yourself; the Service handles it all.

Information queries

class aioxmpp.disco.xso.InfoQuery(*[, identities][, features][, node])[source]

A query for features and identities of an entity. The keyword arguments to the constructor can be used to initialize the attributes. Note that identities and features must be iterables of Identity and Feature, respectively; these iterables are evaluated and the items are stored in the respective attributes.

node

The node at which the query is directed.

identities

The identities of the entity, as Identity instances. Each entity has at least one identity.

features

The features of the entity, as a set of strings. Each string represents a Feature instance with the corresponding var attribute.

captured_events

If the object was created by parsing an XML stream, this attribute holds a list of events which were used when parsing it.

Otherwise, this is None.

New in version 0.5.

to_dict()[source]

Convert the query result to a normalized JSON-like representation.

The format is a subset of the format used by the capsdb. Obviously, the node name and hash type are not included; otherwise, the format is identical.

class aioxmpp.disco.xso.Feature(*[, var])[source]

A feature declaration. The keyword argument to the constructor can be used to initialize the attribute of the Feature instance.

var

The namespace which identifies the feature.

class aioxmpp.disco.xso.Identity(*[, category][, type_][, name][, lang])[source]

An identity declaration. The keyword arguments to the constructor can be used to initialize attributes of the Identity instance.

category

The category of the identity. The value is not validated against the values in the registry.

type_

The type of the identity. The value is not validated against the values in the registry.

name

The optional human-readable name of the identity. See also the lang attribute.

lang

The language of the name. This may be not None even if name is not set due to xml:lang propagation.

Item queries

class aioxmpp.disco.xso.ItemsQuery(*[, node][, items])[source]

A query for items at a specific entity. The keyword arguments to the constructor can be used to initialize the attributes of the ItemsQuery. Note that items must be an iterable of Item instances. The iterable will be evaluated and the items will be stored in the items attribute.

node

Node at which the query is directed

items

The items at the addressed entity.

class aioxmpp.disco.xso.Item(*[, jid][, name][, node])[source]

An item declaration. The keyword arguments to the constructor can be used to initialize the attributes of the Item instance.

jid

JID of the entity represented by the item.

node

Node of the item

name

Name of the item