class UserExt(xso.XSO): TAG = (namespaces.xep0045_muc_user, "x") status_codes = xso.ChildValueList(StatusCodeList(), container_type=set) destroy = xso.Child([DestroyNotification]) decline = xso.Child([Decline]) invites = xso.ChildList([Invite]) items = xso.ChildList([UserItem]) password = xso.ChildText((namespaces.xep0045_muc_user, "password"), default=None) def __init__(self, status_codes=[], destroy=None, decline=None, invites=[], items=[], password=None): super().__init__() self.status_codes.update(status_codes) self.destroy = destroy self.decline = decline self.invites.extend(invites) self.items.extend(items) self.password = password
class Command(xso.XSO): TAG = (namespaces.xep0050_commands, "command") actions = xso.Child([Actions]) notes = xso.ChildList([Note]) action = xso.Attr( "action", type_=xso.EnumType(ActionType), default=ActionType.EXECUTE, ) status = xso.Attr( "status", type_=xso.EnumType(CommandStatus), default=None, ) sessionid = xso.Attr( "sessionid", default=None, ) node = xso.Attr( "node", ) payload = xso.ChildList([ aioxmpp.forms.Data, ]) def __init__(self, node, *, action=ActionType.EXECUTE, status=None, sessionid=None, payload=[], notes=[], actions=None): super().__init__() self.node = node self.action = action self.status = status self.sessionid = sessionid if not isinstance(payload, collections.abc.Iterable): self.payload[:] = [payload] else: self.payload[:] = payload self.notes[:] = notes self.actions = actions @property def first_payload(self): try: return self.payload[0] except IndexError: return
class EventItems(xso.XSO): TAG = (namespaces.xep0060_event, "items") node = xso.Attr("node", ) retracts = xso.ChildList([EventRetract]) items = xso.ChildList([EventItem]) def __init__(self, node, *, items=[], retracts=[]): super().__init__() self.items[:] = items self.retracts[:] = retracts self.node = node
class ItemsQuery(xso.XSO): """ A query for items at a specific entity. The keyword arguments to the constructor can be used to initialize the attributes of the :class:`ItemsQuery`. Note that `items` must be an iterable of :class:`Item` instances. The iterable will be evaluated and the items will be stored in the :attr:`items` attribute. .. attribute:: node Node at which the query is directed .. attribute:: items The items at the addressed entity. """ TAG = (namespaces.xep0030_items, "query") node = xso.Attr(tag="node", default=None) items = xso.ChildList([Item]) def __init__(self, *, node=None, items=()): super().__init__() self.items.extend(items) if node is not None: self.node = node
class Items(xso.XSO): TAG = (namespaces.xep0060, "items") max_items = xso.Attr( (None, "max_items"), type_=xso.Integer(), validator=xso.NumericRange(min_=1), default=None, ) node = xso.Attr( "node", ) subid = xso.Attr( "subid", default=None ) items = xso.ChildList( [Item] ) def __init__(self, node, subid=None, max_items=None): super().__init__() self.node = node self.subid = subid self.max_items = max_items
class Metadata(xso.XSO): """ A metadata node which used to publish and reveice avatar image metadata. .. attribute:: info A map from the MIME type to the corresponding :class:`Info` XSO. .. attribute:: pointer A list of the :class:`Pointer` children. """ TAG = (namespaces.xep0084_metadata, "metadata") info = xso.ChildMap([Info], key=lambda x: x.mime_type) pointer = xso.ChildList([Pointer]) def iter_info_nodes(self): """ Iterate over all :class:`Info` children. """ info_map = self.info for mime_type in info_map: for metadata_info_node in info_map[mime_type]: yield metadata_info_node
class Query(xso.XSO): """ A query which fetches data from the roster or sends new items to the roster. .. attribute:: ver The version of the roster, if any. See the RFC for the detailed semantics. .. attribute:: items The items in the roster query. """ TAG = (namespaces.rfc6121_roster, "query") ver = xso.Attr("ver", default=None) items = xso.ChildList([Item]) def __init__(self, *, ver=None, items=()): super().__init__() self.ver = ver self.items.extend(items)
class AdminQuery(xso.XSO): TAG = (namespaces.xep0045_muc_admin, "query") items = xso.ChildList([AdminItem]) def __init__(self, *, items=[]): super().__init__() self.items[:] = items
class Data(AbstractItem): TAG = (namespaces.xep0004_data, "x") type_ = xso.Attr( "type", validator=xso.RestrictToSet({ "form", "submit", "cancel", "result", }), validate=xso.ValidateMode.ALWAYS, ) title = xso.ChildList([Title]) instructions = xso.ChildList([Instructions]) items = xso.ChildList([Item]) reported = xso.Child([Reported], required=False) def _validate_result(self): if self.fields: raise ValueError("field in report result") fieldvars = {field.var for field in self.reported.fields} if not fieldvars: raise ValueError("empty report header") for item in self.items: itemvars = {field.var for field in item.fields} if itemvars != fieldvars: raise ValueError("field mismatch between row and header") def validate(self): super().validate() if (self.type_ != "result" and (self.reported is not None or self.items)): raise ValueError("report in non-result") if (self.type_ == "result" and (self.reported is not None or self.items)): self._validate_result()
class RootXSO(xso.XSO): TAG = (None, "root") children = xso.ChildList([ FooXSO, BarXSO, ]) attr = xso.Attr("attr")
class DeepRoot(xso.XSO): TAG = ("uri:test", "root") children = xso.ChildList([DeepLeaf, DeepNode]) def generate(self, rng): self.children[:] = [DeepNode() for i in range(3)] for child in self.children: child.generate(rng, 1)
class OwnerSubscriptions(xso.XSO): TAG = (namespaces.xep0060_owner, "subscriptions") node = xso.Attr("node", ) subscriptions = xso.ChildList([OwnerSubscription]) def __init__(self, node, *, subscriptions=[]): super().__init__() self.node = node self.subscriptions[:] = subscriptions
class Subscriptions(xso.XSO): TAG = (namespaces.xep0060, "subscriptions") node = xso.Attr("node", default=None) subscriptions = xso.ChildList([Subscription], ) def __init__(self, *, subscriptions=[], node=None): super().__init__() self.node = node self.subscriptions[:] = subscriptions
class OwnerAffiliations(xso.XSO): TAG = (namespaces.xep0060_owner, "affiliations") affiliations = xso.ChildList([OwnerAffiliation]) node = xso.Attr("node", ) def __init__(self, node, *, affiliations=[]): super().__init__() self.node = node self.affiliations[:] = affiliations
class Affiliations(xso.XSO): TAG = (namespaces.xep0060, "affiliations") node = xso.Attr("node", default=None) affiliations = xso.ChildList([Affiliation], ) def __init__(self, affiliations=[], node=None): super().__init__() self.affiliations[:] = affiliations self.node = node
class Storage(xso.XSO): """ The container for storing bookmarks. .. attribute:: bookmarks A :class:`~xso.XSOList` of bookmarks. """ TAG = (namespaces.xep0048, "storage") bookmarks = xso.ChildList([URL, Conference])
class DeepNode(xso.XSO): TAG = ("uri:test", "node") data = xso.Attr("attr") children = xso.ChildList([DeepLeaf]) def generate(self, rng, depth): self.data = "foo" * (2 * rng.randint(1, 10)) if depth >= 5: cls = DeepLeaf else: cls = DeepNode self.children.append(cls()) for i in range(rng.randint(2, 10)): if rng.randint(1, 10) == 1: item = DeepNode() else: item = DeepLeaf() self.children.append(item) for item in self.children: item.generate(rng, depth + 1)
class InfoQuery(xso.CapturingXSO): """ 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 :class:`Identity` and :class:`Feature`, respectively; these iterables are evaluated and the items are stored in the respective attributes. .. attribute:: node The node at which the query is directed. .. attribute:: identities The identities of the entity, as :class:`Identity` instances. Each entity has at least one identity. .. attribute:: features The features of the entity, as a set of strings. Each string represents a :class:`Feature` instance with the corresponding :attr:`~.Feature.var` attribute. .. 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 :data:`None`. .. versionadded:: 0.5 .. automethod:: to_dict """ __slots__ = ("captured_events", ) TAG = (namespaces.xep0030_info, "query") node = xso.Attr(tag="node", default=None) identities = xso.ChildList([Identity]) features = xso.ChildValueList(FeatureSet(), container_type=set) exts = xso.ChildList([forms_xso.Data]) def __init__(self, *, identities=(), features=(), node=None): super().__init__() self.captured_events = None self.identities.extend(identities) self.features.update(features) if node is not None: self.node = node def to_dict(self): """ 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. __ https://github.com/xnyhps/capsdb """ identities = [] for identity in self.identities: identity_dict = { "category": identity.category, "type": identity.type_, } if identity.lang is not None: identity_dict["lang"] = identity.lang.match_str if identity.name is not None: identity_dict["name"] = identity.name identities.append(identity_dict) features = sorted(self.features) forms = [] for form in self.exts: forms.append({ field.var: list(field.values) for field in form.fields if field.var is not None }) result = { "identities": identities, "features": features, "forms": forms } return result def _set_captured_events(self, events): self.captured_events = events
class AbstractItem(xso.XSO): fields = xso.ChildList([Field])
if (self.type_ != DataType.RESULT and (self.reported is not None or self.items)): raise ValueError("report in non-result") if (self.type_ == DataType.RESULT and (self.reported is not None or self.items)): self._validate_result() def get_form_type(self): """ Extract the ``FORM_TYPE`` from the fields. :return: ``FORM_TYPE`` value or :data:`None` :rtype: :class:`str` or :data:`None` Return :data:`None` if no well-formed ``FORM_TYPE`` field is found in the list of fields. .. versionadded:: 0.8 """ for field in self.fields: if field.var == "FORM_TYPE" and field.type_ == FieldType.HIDDEN: if len(field.values) != 1: return None return field.values[0] aioxmpp.Message.xep0004_data = xso.ChildList([Data])
class Item(xso.XSO): """ A contact item in a roster. .. attribute:: jid The bare :class:`~aioxmpp.JID of the contact. .. attribute:: name The optional display name of the contact. .. attribute:: groups A :class:`~aioxmpp.xso.model.XSOList` of :class:`Group` instances which describe the roster groups in which the contact is. The following attributes represent the subscription status of the contact. A client **must not** set these attributes when sending roster items to the server. To change subscription status, use presence stanzas of the respective type. The only exception is a :attr:`subscription` value of ``"remove"``, which is used to remove an entry from the roster. .. attribute:: subscription Primary subscription status, one of ``"none"`` (the default), ``"to"``, ``"from"`` and ``"both"``. In addition, :attr:`subscription` can be set to ``"remove"`` to remove an item from the roster during a roster set. Removing an entry from the roster will also cancel any presence subscriptions from and to that entries entity. .. attribute:: approved Whether the subscription has been pre-approved by the owning entity. .. attribute:: ask Subscription sub-states, one of ``"subscribe"`` and :data:`None`. .. note:: Do not confuse this class with :class:`~aioxmpp.roster.Item`. """ TAG = (namespaces.rfc6121_roster, "item") approved = xso.Attr( "approved", type_=xso.Bool(), default=False, ) ask = xso.Attr( "ask", validator=xso.RestrictToSet({ None, "subscribe", }), validate=xso.ValidateMode.ALWAYS, default=None, ) jid = xso.Attr( "jid", type_=xso.JID(), ) name = xso.Attr( "name", default=None, ) subscription = xso.Attr( "subscription", validator=xso.RestrictToSet({ "none", "to", "from", "both", "remove", }), validate=xso.ValidateMode.ALWAYS, default="none", ) groups = xso.ChildList([Group]) def __init__(self, jid, *, name=None, groups=(), subscription="none", approved=False, ask=None): super().__init__() if jid is not None: self.jid = jid self.name = name self.groups.extend(groups) self.subscription = subscription self.approved = approved self.ask = ask
class Data(AbstractItem): """ A :xep:`4` ``x`` element, that is, a Data Form. :param type_: Initial value for the :attr:`type_` attribute. .. attribute:: type_ The ``type`` attribute of the form, represented by one of the members of the :class:`DataType` enumeration. .. attribute:: title The (optional) title of the form. Either a :class:`str` or :data:`None`. .. attribute:: instructions A sequence of strings which represent the instructions elements on the form. .. attribute:: fields If the :class:`Data` is a form, this is a sequence of :class:`Field` elements which represent the fields to be filled in. This does not make sense on :attr:`.DataType.RESULT` typed objects. .. attribute:: items If the :class:`Data` is a table, this is a sequence of :class:`Item` instances which represent the table rows. This only makes sense on :attr:`.DataType.RESULT` typed objects. .. attribute:: reported If the :class:`Data` is a table, this is a :class:`Reported` object representing the table header. This only makes sense on :attr:`.DataType.RESULT` typed objects. .. automethod:: get_form_type """ TAG = (namespaces.xep0004_data, "x") type_ = xso.Attr("type", type_=xso.EnumCDataType(DataType)) title = xso.ChildText( (namespaces.xep0004_data, "title"), default=None, ) instructions = xso.ChildValueList(type_=InstructionsElement()) items = xso.ChildList([Item]) reported = xso.Child([Reported], required=False) def __init__(self, type_): super().__init__() self.type_ = type_ def _validate_result(self): if self.fields: raise ValueError("field in report result") fieldvars = {field.var for field in self.reported.fields} if not fieldvars: raise ValueError("empty report header") for item in self.items: itemvars = {field.var for field in item.fields} if itemvars != fieldvars: raise ValueError("field mismatch between row and header") def validate(self): super().validate() if (self.type_ != DataType.RESULT and (self.reported is not None or self.items)): raise ValueError("report in non-result") if (self.type_ == DataType.RESULT and (self.reported is not None or self.items)): self._validate_result() def get_form_type(self): """ Extract the ``FORM_TYPE`` from the fields. :return: ``FORM_TYPE`` value or :data:`None` :rtype: :class:`str` or :data:`None` Return :data:`None` if no well-formed ``FORM_TYPE`` field is found in the list of fields. .. versionadded:: 0.8 """ for field in self.fields: if field.var == "FORM_TYPE" and field.type_ == FieldType.HIDDEN: if len(field.values) != 1: return None return field.values[0]
The timestamp (as :class:`datetime.datetime`) at which the stanza was originally sent or intended to be sent. .. attribute:: reason The reason for which the stanza was delayed or :data:`None`. .. warning:: Please take the security considerations of :xep:`203` into account. """ TAG = namespaces.xep0203_delay, "delay" from_ = xso.Attr( "from", type_=xso.JID(), default=None, ) stamp = xso.Attr( "stamp", type_=xso.DateTime(), ) reason = xso.Text(default=None) Message.xep0203_delay = xso.ChildList([Delay])