# `xso` — Working with XML stream contents

This subpackage deals with XML Stream Objects. XSOs can be stanzas, but in general any XML.

The facilities in this subpackage are supposed to help developers of XEP plugins, as well as the main development of `aioxmpp`. The subpackage is split in two parts, `aioxmpp.xso.model`, which provides facilities to allow declarative-style parsing and un-parsing of XML subtrees into XSOs and the `aioxmpp.xso.types` module, which provides classes which implement validators and type parsers for content represented as strings in XML.

## Terminology

### Definition of an XSO

An XSO is an object whose class inherits from `aioxmpp.xso.XSO`.

### A word on tags

Tags, as used by etree, are used throughout this module. Note that we are representing tags as tuples of `(namespace_uri, localname)`, where `namespace_uri` may be `None`.

See also

The functions `normalize_tag()` and `tag_to_str()` are useful to convert from and to ElementTree compatible strings.

### Suspendable functions

This module uses suspendable functions, implemented as generators, at several points. These may also be called coroutines, but have nothing to do with coroutines as used by `asyncio`, which is why we will call them suspendable functions here.

Suspendable functions possibly take arguments and then operate on input which is fed to them in a push-manner step by step (using the `send()` method). The main usage in this module is to process SAX events: The SAX events are processed step-by-step by the functions, and when the event is fully processed, it suspends itself (using `yield`) until the next event is sent into it.

## General functions

`aioxmpp.xso.``normalize_tag`(tag)

  Normalize an XML element tree tag into the tuple format. The following input formats are accepted:

  - ElementTree namespaced string, e.g. `{uri:bar}foo`
  - Unnamespaced tags, e.g. `foo`
  - Two-tuples consisting of namespace_uri and localpart; namespace_uri may be `None` if the tag is supposed to be namespaceless. Otherwise it must be, like localpart, a `str`.

  Return a two-tuple consisting the `(namespace_uri, localpart)` format.

`aioxmpp.xso.``tag_to_str`(tag)

  tag must be a tuple `(namespace_uri, localname)`. Return a tag string conforming to the ElementTree specification. Example:

      tag_to_str(("jabber:client", "iq")) == "{jabber:client}iq"

## Object declaration with `aioxmpp.xso.model`

This module provides facilities to create classes which map to full XML stream subtrees (for example stanzas including payload).

To create such a class, derive from `XSO` and provide attributes using the `Attr`, `Text`, `Child` and `ChildList` descriptors.

### Descriptors for XML-sourced attributes

The following descriptors can be used to load XSO attributes from XML. There are two fundamentally different descriptor types: scalar and non-scalar (e.g. list) descriptors. Assignment to the descriptor attribute is strictly type-checked for scalar descriptors.

#### Scalar descriptors

Many of the arguments and attributes used for the scalar descriptors are similar. They are described in detail on the `Attr` class and not repeated that detailed on the other classes. Refer to the documentation of the `Attr` class in those cases.

class `aioxmpp.xso.``Attr`(name, *[, type_=xso.String()][, validator=None][, validate=ValidateMode.FROM_RECV][, missing=None][, default][, erroneous_as_absent=False])

  Descriptor which represents an XML attribute.

  When assigned to a class’ attribute, it binds that attribute to the XML attribute with the given tag. tag must be a valid input to `normalize_tag()`.

  The following arguments occur at several of the descriptor classes, and are all available at `Attr`.

  Parameters:

  - type (`AbstractCDataType`) – A character data type to interpret the XML character data.
  - validator – An object which has a `validate()` method. That method receives a value which was either assigned to the property (depending on the validate argument) or parsed from XML (after it passed through type_).
  - validate – A value from the `ValidateMode` enum, which defines which values have to pass through the validator. At some points it makes sense to only validate outgoing values, but be liberal with incoming values. This defaults to `ValidateMode.FROM_RECV`.
  - default – The value which the attribute has if no value has been assigned. This must be given to allow the attribute to be missing. It defaults to a special value. If the attribute has not been assigned to and default has not been set, accessing the attribute for reading raises `AttributeError`. An attribute with default value is not emitted in the output.
  - missing – A callable which takes a `Context` instance. It is called whenever the attribute is missing (independent from the fact whether it is required or not). The callable shall return a not-`None` value for the attribute to use. If the value is `None`, the usual handling of missing attributes takes place.
  - erroneous_as_absent – Treat an erroneous value (= the type_ raises `ValueError` or `TypeError` while parsing) as if the attribute was not present. Note that this is almost never the right thing to do in XMPP.

  See also

  `LangAttr`, which is a subclass of `Attr` specialized for describing `xml:lang` attributes.

  Note

  The default argument does not need to comply with either type_ or validator. This can be used to convey meaning with the absence of the attribute. Note that assigning the default value is not possible if it does not comply with type_ or validator and the `del` operator must be used instead.

  `from_value`(instance, value)

    Convert the given value using the set type_ and store it into instance’ attribute.

  `handle_missing`(instance, ctx)

    Handle a missing attribute on instance. This is called whenever no value for the attribute is found during parsing. The call to `missing()` is independent of the value of required.

    If the missing callback is not `None`, it is called with the instance and the ctx as arguments. If the returned value is not `None`, it is used as the value of the attribute (validation takes place as if the value had been set from the code, not as if the value had been received from XML) and the handler returns.

    If the missing callback is `None` or returns `None`, the handling continues as normal: if required is true, a `ValueError` is raised.

  `to_dict`(instance, d)

    Override the implementation from `Text` by storing the formatted value in the XML attribute instead of the character data.

    If the value is `None`, no element is generated.

class `aioxmpp.xso.``LangAttr`(*[, validator=None][, validate=ValidateMode.FROM_RECV][, default=None])

  An attribute representing the `xml:lang` attribute, including inheritance semantics.

  This is a subclass of `Attr` which takes care of inheriting the `xml:lang` value of the parent. The tag is set to the `(namespaces.xml, "lang")` value to match `xml:lang` attributes. type_ is a `xso.LanguageTag` instance and missing is set to `lang_attr()`.

  Note that `LangAttr` overrides default to be `None` by default.

class `aioxmpp.xso.``Child`(classes, *[, required=False][, strict=False])

  When assigned to a class’ attribute, it collects any child which matches any `XSO.TAG` of the given classes.

  Parameters: | strict (`bool`) – Enable strict type checking on assigned values.

  The tags among the classes must be unique, otherwise `ValueError` is raised on construction.

  Instead of the default argument like supplied by `Attr`, `Child` only supports required: if required is a false value (the default), a missing child is tolerated and `None` is valid value for the described attribute. Otherwise, a missing matching child is an error and the attribute cannot be set to `None`.

  If strict is true, only instances of the exact classes registered with the descriptor can be assigned to it. Subclasses of the registered classes also need to be registered explicitly to be allowed as types for values.

  `get_tag_map`()

    Return a dictionary mapping the tags of the supported classes to the classes themselves. Can be used to obtain a set of supported tags.

  `from_events`(instance, ev_args, ctx)

    Detect the object to instanciate from the arguments ev_args of the `"start"` event. The new object is stored at the corresponding descriptor attribute on instance.

    This method is suspendable.

  `to_sax`(instance, dest)

    Take the object associated with this descriptor on instance and serialize it as child into the given `lxml.etree.Element` parent.

    If the object is `None`, no content is generated.

class `aioxmpp.xso.``ChildTag`(tags, *[, text_policy=UnknownTextPolicy.FAIL][, child_policy=UnknownChildPolicy.FAIL][, attr_policy=UnknownAttrPolicy.FAIL][, default_ns=None][, allow_none=False])

  Represents a subset of the children of an XML element, as single value.

  When assigned to a class’ attribute, this descriptor represents the presence or absence of a single child with a tag from a given set of valid tags.

  tags must be an iterable of valid arguments to `normalize_tag()` or an `enum.Enum` whose values are valid arguments to `normalize_tag()`. If `normalize_tag()` returns a false value (such as `None`) as namespace_uri, it is replaced with default_ns (defaulting to `None`, which makes this sentence a no-op). This allows a benefit to readability if you have many tags which share the same namespace. This is, however, not allowed for tags given as enumeration.

  text_policy, child_policy and attr_policy describe the behaviour if the child element unexpectedly has text, children or attributes, respectively. The default for each is to fail with a `ValueError`.

  If allow_none is `True`, assignment of `None` to the attribute to which this descriptor belongs is allowed and represents the absence of the child element.

  If declare_prefix is not `False` (note that `None` is a valid, non-`False` value in this context!), the namespace is explicitly declared using the given prefix when serializing to SAX.

  `from_events`(instance, ev_args, ctx)
  `to_sax`(instance, dest)

class `aioxmpp.xso.``ChildFlag`(tag, *[, text_policy=UnknownTextPolicy.FAIL][, child_policy=UnknownChildPolicy.FAIL][, attr_policy=UnknownAttrPolicy.FAIL])

  Represents the presence of a specific child element, as a boolean flag.

  When used as a `XSO` descriptor, it represents the presence or absence of a single child with the given tag. The presence or absence is represented by the values `True` and `False` respectively.

  tag must be a valid tag.

  The default value for attributes using this descriptor is `False`.

  text_policy, child_policy and attr_policy describe the behaviour if the child element unexpectedly has text, children or attributes, respectively. The default for each is to fail with a `ValueError`.

  If declare_prefix is not `False` (note that `None` is a valid, non-`False` value in this context!), the namespace is explicitly declared using the given prefix when serializing to SAX.

class `aioxmpp.xso.``ChildText`(tag, *[, child_policy=UnknownChildPolicy.FAIL][, attr_policy=UnknownAttrPolicy.FAIL][, type_=xso.String()][, validator=None][, validate=ValidateMode.FROM_RECV][, default][, erroneous_as_absent=False])

  Represents the character data of a child element.

  When assigned to a class’ attribute, it binds that attribute to the XML character data of a child element with the given tag. tag must be a valid input to `normalize_tag()`.

  Parameters:

  - child_policy (`UnknownChildPolicy`) – The policy to apply when children are found in the child element whose text this descriptor represents.
  - attr_policy (`UnknownAttrPolicy`) – The policy to apply when attributes are found at the child element whose text this descriptor represents.

  The type_, validate, validator, default and erroneous_as_absent arguments behave like in `Attr`.

  declare_prefix works as for `ChildTag`.

  child_policy and attr_policy describe how the parser behaves when an unknown child or attribute (respectively) is encountered on the child element whose text this descriptor represents. See `UnknownChildPolicy` and `UnknownAttrPolicy` for the possible behaviours.

  `get_tag_map`()

    Return an iterable yielding `tag`.

    This is for compatiblity with the `Child` interface.

  `from_events`(instance, ev_args, ctx)

    Starting with the element to which the start event information in ev_args belongs, parse text data. If any children are encountered, `child_policy` is enforced (see `UnknownChildPolicy`). Likewise, if the start event contains attributes, `attr_policy` is enforced (c.f. `UnknownAttrPolicy`).

    The extracted text is passed through `type_` and `validator` and if it passes, stored in the attribute on the instance with which the property is associated.

    This method is suspendable.

  `to_sax`(instance, dest)

    Create a child node at parent with the tag `tag`. Set the text contents to the value of the attribute which this descriptor represents at instance.

    If the value is `None`, no element is generated.

class `aioxmpp.xso.``Text`(*[, type_=xso.String()][, validator=None][, validate=ValidateMode.FROM_RECV][, default][, erroneous_as_absent=False])

  When assigned to a class’ attribute, it collects all character data of the XML element.

  Note that this destroys the relative ordering of child elements and character data pieces. This is known and a WONTFIX, as it is not required in XMPP to keep that relative order: Elements either have character data or other elements as children.

  The type_, validator, validate, default and erroneous_as_absent arguments behave like in `Attr`.

  `from_value`(instance, value)

    Convert the given value using the set type_ and store it into instance’ attribute.

  `to_sax`(instance, dest)

    Assign the formatted value stored at instance’ attribute to the text of el.

    If the value is `None`, no text is generated.

#### Non-scalar descriptors

class `aioxmpp.xso.``ChildList`(classes)

  The `ChildList` works like `Child`, with two key differences:

  - multiple children which are matched by this descriptor get collected into an `XSOList`.
  - the default is fixed at an empty list.
  - required is not supported
  `from_events`(instance, ev_args, ctx)

    Like `Child.from_events()`, but instead of replacing the attribute value, the new object is appended to the list.

  `to_sax`(instance, dest)

    Like `Child.to_node()`, but instead of serializing a single object, all objects in the list are serialized.

class `aioxmpp.xso.``ChildMap`(classes[, key=None])

  Represents a subset of the children of an XML element, as map.

  The `ChildMap` class works like `ChildList`, but instead of storing the child objects in a list, they are stored in a map which contains an `XSOList` of objects for each tag.

  key may be callable. If it is given, it is used while parsing to determine the dictionary key under which a newly parsed XSO will be put. For that, the key callable is called with the newly parsed XSO as the only argument and is expected to return the key.

  `from_events`(instance, ev_args, ctx)

    Like `ChildList.from_events()`, but the object is appended to the list associated with its tag in the dict.

  `to_sax`(instance, dest)

    Serialize all objects in the dict associated with the descriptor at instance to the given parent.

    The order of elements within a tag is preserved; the order of the tags relative to each other is undefined.

  The following utility function is useful when filling data into descriptors using this class:

  `fill_into_dict`(items, dest)

    Take an iterable of items and group it into the given dest dict, using the `key` function.

    The dest dict must either already contain the keys which are generated by the `key` function for the items in items, or must default them suitably. The values of the affected keys must be sequences or objects with an `append()` method which does what you want it to do.

class `aioxmpp.xso.``ChildLangMap`(classes)

  Represents a subset of the children of an XML element, as map.

  The `ChildLangMap` class is a specialized version of the `ChildMap`, which uses a key function to group the children by their XML language tag.

  It is expected that the language tag is available as `lang` attribute on the objects stored in this map.

class `aioxmpp.xso.``ChildValueList`(type_)

  Represents a subset of the child elements as values. The value representation is governed by the type_ argument.

  Parameters:

  - type (`AbstractElementType`) – Type describing the subtree to convert to python values.
  - container_type (Subclass of `MutableSequence` or `MutableSet`) – Type of the container to use.

  This descriptor parses the XSO classes advertised by the type_ (via `get_xso_types()`) and exposes the unpacked values in a container.

  The optional container_type argument must, if given, be a callable which returns a mutable container supporting either `add()` or `append()` of the values used with the type_ and iteration. It will be used instead of `list` to create the values for the descriptor.

  New in version 0.5.

class `aioxmpp.xso.``ChildValueMap`(type_, *, mapping_type=dict)

  A mapping of keys to values, generated by child tags.

  Parameters:

  - type (`AbstractElementType`) – Type describing the subtree to convert to pairs of key and value.
  - mapping_type (Subclass of `MutableMapping`) – Type of the mapping to use.

  This works very similar to `ChildValueList`, but instead of a mutable sequence, the value of the descriptor is a mutable mapping.

  The type_ must return key-value pairs from `xso.AbstractElementType.unpack()` and must accept such key-value pairs in `xso.AbstractElementType.pack()`.

  The optional mapping_type argument must, if given, be a callable which returns a `collections.abc.MutableMapping` supporting the keys and values used by the type_. It will be used instead of `dict` to create the values for the descriptor. A possible use-case is using `structs.LanguageMap` together with `TextChildMap`.

  See also

  `ChildTextMap` for a specialised version to deal with `AbstractTextChild` subclasses.

  New in version 0.5.

class `aioxmpp.xso.``ChildValueMultiMap`(type_, *, mapping_type=multidict.MultiDict)

  A mapping of keys to lists of values, representing child tags.

  Parameters: | type (`AbstractElementType`) – Type describing the subtree to convert to pairs of key and value.

  This is very similar to `ChildValueMap`, but it uses a `multidict.MultiDict` as storage. Interface-compatible classes can be substituted by passing them to mapping_type. Candidate for that are `multidict.CIMultiDict`.

  New in version 0.6.

class `aioxmpp.xso.``ChildTextMap`(xso_type)

  A specialised version of `ChildValueMap` which uses `TextChildMap` together with `structs.LanguageMap` to convert the `AbstractTextChild` subclass xso_type to and from a language-text mapping.

  For an example, see `Message`.

class `aioxmpp.xso.``Collector`

  When assigned to a class’ attribute, it collects all children which are not known to any other descriptor into an XML tree. The root node has the tag of the XSO class it pertains to.

  The default is fixed to the emtpy root node.

  Changed in version 0.10: Before the subtrees were collected in a list. This was changed to an ElementTree to allow using XPath over all collected elements. Most code should not be affected by this, since the interface is very similar. Assignment is now forbidden. Use ``[:] = `` instead.

  `from_events`(instance, ev_args, ctx)

    Collect the events and convert them to a single XML subtree, which then gets appended to the list at instance. ev_args must be the arguments of the `"start"` event of the new child.

    This method is suspendable.

  `to_sax`(instance, dest)

#### Container for child lists

The child lists in `ChildList`, `ChildMap` and `ChildLangMap` descriptors use a specialized list-subclass which provides advanced capabilities for filtering `XSO` objects.

class `aioxmpp.xso.model.``XSOList`

  A `list` subclass; it provides the complete `list` interface with the addition of the following methods:

  `filter`(*, type_=None, lang=None, attrs={})

    Return an iterable which produces a sequence of the elements inside this `XSOList`, filtered by the criteria given as arguments. The function starts with a working sequence consisting of the whole list.

    If type_ is not `None`, elements which are not an instance of the given type are excluded from the working sequence.

    If lang is not `None`, it must be either a `LanguageRange` or an iterable of language ranges. The set of languages present among the working sequence is determined and used for a call to `lookup_language`. If the lookup returns a language, all elements whose `lang` is different from that value are excluded from the working sequence.

    Note

    If an iterable of language ranges is given, it is evaluated into a list. This may be of concern if a huge iterable is about to be used for language ranges, but it is an requirement of the `lookup_language` function which is used under the hood.

    Note

    Filtering by language assumes that the elements have a `LangAttr` descriptor named `lang`.

    If attrs is not empty, the filter iterates over each key-value pair. For each iteration, all elements which do not have an attribute of the name in key or where that attribute has a value not equal to value are excluded from the working sequence.

    In general, the iterable returned from `filter()` can only be used once. It is dynamic in the sense that changes to elements which are in the list behind the last element returned from the iterator will still be picked up when the iterator is resumed.

  `filtered`(*, type_=None, lang=None, attrs={})

    This method is a convencience wrapper around `filter()` which evaluates the result into a list and returns that list.

  In the future, methods to add indices to `XSOList` instances may be added; right now, there is no need for the huge complexity which would arise from keeping the indices up-to-date with changes in the elements attributes.

### Parsing XSOs

To parse XSOs, an asynchronous approach which uses SAX-like events is followed. For this, the suspendable functions explained earlier are used. The main class to parse a XSO from events is `XSOParser`. To drive that suspendable callable from SAX events, use a `SAXDriver`.

class `aioxmpp.xso.``XSOParser`

  A generic XSO parser which supports a dynamic set of XSOs to parse. `XSOParser` objects are callable and they are suspendable methods (i.e. calling a `XSOParser` returns a generator which parses stanzas from sax-ish events. Use with `SAXDriver`).

  Example use:

      # let Message be a XSO class, like in the XSO example
      result = None
      def catch_result(value):
          nonlocal result
          result = value

      parser = aioxmpp.xso.XSOParser()
      parser.add_class(Message, catch_result)
      sd = aioxmpp.xso.SAXDriver(parser)
      lxml.sax.saxify(lmxl.etree.fromstring(
          "<message id='foo' from='bar' type='chat' />"
      ))

  The following methods can be used to dynamically add and remove top-level `XSO` classes.

  `add_class`(cls, callback)

    Add a class cls for parsing as root level element. When an object of cls type has been completely parsed, callback is called with the object as argument.

  `remove_class`(cls)

    Remove a XSO class cls from parsing. This method raises `KeyError` with the classes `TAG` attribute as argument if removing fails because the class is not registered.

  `get_tag_map`()

    Return the internal mapping which maps tags to tuples of `(cls, callback)`.

    Warning

    The results of modifying this dict are undefined. Make a copy if you need to modify the result of this function.

class `aioxmpp.xso.``SAXDriver`(dest_generator_factory, on_emit=None)

  This is a `xml.sax.handler.ContentHandler` subclass which only supports namespace-conforming SAX event sources.

  dest_generator_factory must be a function which returns a new suspendable method supporting the interface of `XSOParser`. The SAX events are converted to an internal event format and sent to the suspendable function in order.

  on_emit may be a callable. Whenever a suspendable function returned by dest_generator_factory returns, with the return value as sole argument.

  When you are done with a `SAXDriver`, you should call `close()` to clean up internal parser state.

  `close`()

    Clean up all internal state.

### Base and meta class

The `XSO` base class makes use of the `model.XMLStreamClass` metaclass and provides implementations for utility methods. For an object to work with this module, it must derive from `XSO` or provide an identical interface.

class `aioxmpp.xso.``XSO`

  XSO is short for XML Stream Object and means an object which represents a subtree of an XML stream. These objects can also be created and validated on-the-fly from SAX-like events using `XSOParser`.

  The constructor does not require any arguments and forwards them directly the next class in the resolution order. Note that during deserialization, `__init__` is not called. It is assumed that all data is loaded from the XML stream and thus no initialization is required.

  This is beneficial to applications, as it allows them to define mandatory arguments for `__init__`. This would not be possible if `__init__` was called during deserialization. A way to execute code after successful deserialization is provided through `xso_after_load()`.

  `XSO` objects support copying. Like with deserialisation, `__init__` is not called during copy. The default implementation only copies the XSO descriptors’ values (with deepcopy, they are copied deeply). If you have more attributes to copy, you need to override `__copy__` and `__deepcopy__` methods.

  Changed in version 0.4: Copy and deepcopy support has been added. Previously, copy copied not enough data, while deepcopy copied too much data (including descriptor objects).

  To declare an XSO, inherit from `XSO` and provide the following attributes on your class:

  - A `TAG` attribute, which is a tuple `(namespace_uri, localname)` representing the tag of the XML element you want to match.
  - An arbitrary number of `Text`, `Collector`, `Child`, `ChildList` and `Attr`-based attributes.

  See also

  `xso.model.XMLStreamClass`
    is the metaclass of `XSO`. The documentation of the metaclass holds valuable information with respect to modifying `XSO` classes and subclassing.

  Note

  Attributes whose name starts with `xso_` or `_xso_` are reserved for use by the `aioxmpp.xso` implementation. Do not use these in your code if you can possibly avoid it.

  `XSO` subclasses automatically declare a `__slots__` attribute which does not include the `__dict__` value. This effectively prevents any attributes not declared on the class as descriptors from being written. The rationale is detailed on in the linked documentation. To prevent this from happening in your subclass, inherit with protect set to false:

      class MyXSO(xso.XSO, protect=False):
          pass

  New in version 0.6: The handling of the `__slots__` attribute was added.

  To further influence the parsing behaviour of a class, two attributes are provided which give policies for unexpected elements in the XML tree:

  `UNKNOWN_CHILD_POLICY = UnknownChildPolicy.DROP`

    A value from the `UnknownChildPolicy` enum which defines the behaviour if a child is encountered for which no matching attribute is found.

    Note that this policy has no effect if a `Collector` descriptor is present, as it takes all children for which no other descriptor exists, thus all children are known.

  `UNKNOWN_ATTR_POLICY = UnknownAttrPolicy.DROP`

    A value from the `UnknownAttrPolicy` enum which defines the behaviour if an attribute is encountered for which no matching descriptor is found.

  Example:

      class Body(aioxmpp.xso.XSO):
          TAG = ("jabber:client", "body")

          text = aioxmpp.xso.Text()

      class Message(aioxmpp.xso.XSO):
          TAG = ("jabber:client", "message")
          UNKNOWN_CHILD_POLICY = aioxmpp.xso.UnknownChildPolicy.DROP

          type_ = aioxmpp.xso.Attr(tag="type")
          from_ = aioxmpp.xso.Attr(tag="from")
          to = aioxmpp.xso.Attr(tag="to")
          id_ = aioxmpp.xso.Attr(tag="id")

          body = aioxmpp.xso.Child([Body])

  Beyond the validation of the individual descriptor values, it is possible to implement more complex validation steps by overriding the `validate()` method:

  `validate`()

    Validate the objects structure beyond the values of individual fields (which have their own validators).

    This first calls `_PropBase.validate_contents()` recursively on the values of all child descriptors. These may raise (or re-raise) errors which occur during validation of the child elements.

    To implement your own validation logic in a subclass of `XSO`, override this method and call it via `super()` before doing your own validation.

    Validate is called by the parsing stack after an object has been fully deserialized from the SAX event stream. If the deserialization fails due to invalid values of descriptors or due to validation failures in child objects, this method is obviously not called.

  The following methods are available on instances of `XSO`:

  `unparse_to_sax`(dest)

  The following class methods are provided by the metaclass:

  classmethod `parse_events`(ev_args)

    Create an instance of this class, using the events sent into this function. ev_args must be the event arguments of the `"start"` event.

    See also

    You probably should not call this method directly, but instead use `XSOParser` with a `SAXDriver`.

    Note

    While this method creates an instance of the class, `__init__` is not called. See the documentation of `xso.XSO()` for details.

    This method is suspendable.

  classmethod `register_child`(prop, child_cls)

    Register a new `XMLStreamClass` instance child_cls for a given `Child` descriptor prop.

    Warning

    This method cannot be used after a class has been derived from this class. This is for consistency: the method modifies the bookkeeping attributes of the class. There would be two ways to deal with the situation:

    1. Updating all the attributes at all the subclasses and re-evaluate the constraints of inheritance. This is simply not implemented, although it would be the preferred way.
    2. Only update the bookkeeping attributes on this class, hiding the change from any existing subclasses. New subclasses would pick the change up, however, which is inconsistent. This is the way which was previously documented here and is not supported anymore.

    Obviously, (2) is bad, which is why it is not supported anymore. (1) might be supported at some point in the future.

    Attempting to use `register_child()` on a class which already has subclasses results in a `TypeError`.

    Note that first using `register_child()` and only then deriving clasess is a valid use: it will still lead to a consistent inheritance hierarchy and is a convenient way to break reference cycles (e.g. if an XSO may be its own child).

  To customize behaviour of deserialization, these methods are provided which can be re-implemented by subclasses:

  `xso_after_load`()

    After an object has been successfully deserialized, this method is called. Note that `__init__` is never called on objects during deserialization.

  `xso_error_handler`(descriptor, ev_args, exc_info)

    This method is called whenever an error occurs while parsing.

    If an exception is raised by the parsing function of a descriptor attribute, such as `Attr`, the descriptor is passed as first argument, the exc_info tuple as third argument and the arguments which led to the descriptor being invoked as second argument.

    If an unknown child is encountered and the `UNKNOWN_CHILD_POLICY` is set to `UnknownChildPolicy.FAIL`, descriptor and exc_info are passed as `None` and ev_args are the arguments to the `"start"` event of the child (i.e. a triple `(namespace_uri, localname, attributes)`).

    If the error handler wishes to suppress the exception, it must return a true value. Otherwise, the exception is propagated (or a new exception is raised, if the error was not caused by an exception). The error handler may also raise its own exception.

    Warning

    Suppressing exceptions can cause invalid input to reside in the object or the object in general being in a state which violates the schema.

    For example, suppressing exceptions about missing attributes will cause the attribute to remain uninitialized (i.e. left at its `default` value).

    Even if the error handler suppresses an exception caused by a broken child, that child will not be added to the object.

class `aioxmpp.xso.``CapturingXSO`

  The following class methods is provided by the metaclass (which is not publicly available, but a subclass of `XMLStreamClass`):

  classmethod `parse_events`(ev_args, parent_ctx)

    Capture the events sent to `XSO.parse_events()`, including the initial ev_args to a list and call `_set_captured_events()` on the result of `XSO.parse_events()`.

    Like the method it overrides, `parse_events()` is suspendable.

  The `_set_captured_events()` method can be overriden by subclasses to make use of the captured events:

  `_set_captured_events`(events)

    This method is called by `parse_events()` after parsing the object. events is the list of event tuples which this object was deserialised from.

    Subclasses must override this method.

  An example use case for this class is `disco.InfoQuery`, combined with `aioxmpp.entitycaps`. We want to be able to store hashes and the generating XML data for use with future versions, including XML data which cannot be parsed by an XSO in the current process (for example, due to an unknown namespace or a plugin which is available but not loaded). With the captured events, it is possible to re-create XML semantically equivalent to the XML originally received.

  New in version 0.5.

The metaclass takes care of collecting the special descriptors in attributes where they can be used by the SAX event interpreter to fill the class with data. It also provides a class method for late registration of child classes.

class `aioxmpp.xso.model.``XMLStreamClass`(name, bases, namespace, protect=True)

  This metaclass is used to implement the fancy features of `XSO` classes and instances. Its documentation details on some of the restrictions and features of XML Stream Classes.

  Note

  There should be no need to use this metaclass directly when implementing your own XSO classes. Instead, derive from `XSO`.

  The following restrictions apply when a class uses the `XMLStreamClass` metaclass:

  1. At no point in the inheritance tree there must exist more than one distinct `Text` descriptor. It is possible to inherit two identical text descriptors from several base classes though.
  2. The above applies equivalently for `Collector` descriptors.
  3. At no point in the inheritance tree there must exist more than one `Attr` descriptor which handles a given attribute tag. Like with `Text`, it is allowed that the same `Attr` descriptor is inherited through multiple paths from parent classes.
  4. The above applies likewise for element tags and `Child` (or similar) descriptors.

  Objects of this metaclass (i.e. classes) have some useful attributes. The following attributes are gathered from the namespace of the class, by collecting the different XSO-related descriptors:

  `TEXT_PROPERTY`

    The `Text` descriptor object associated with this class. This is `None` if no attribute using that descriptor is declared on the class.

  `COLLECTOR_PROPERTY`

    The `Collector` descriptor object associated with this class. This is `None` if no attribute using that descriptor is declared on the class.

  `ATTR_MAP`

    A dictionary mapping attribute tags to the `Attr` descriptor objects for these attributes.

  `CHILD_MAP`

    A dictionary mapping element tags to the `Child` (or similar) descriptor objects which accept these child elements.

  `CHILD_PROPS`

    A set of all `Child` (or `ChildList`) descriptor objects of this class.

  `DECLARE_NS`

    A dictionary which defines the namespace mappings which shall be declared when serializing this element. It must map namespace prefixes (such as `None` or `"foo"`) to namespace URIs.

    For maximum compatibility with legacy XMPP implementations (I’m looking at you, ejabberd!), `DECLARE_NS` is set by this metaclass unless it is provided explicitly when declaring the class:

    - If no `TAG` is set, `DECLARE_NS` is also not set. The attribute does not exist on the class in that case, unless it is inherited from a base class.
    - If `TAG` is set and at least one base class has a `DECLARE_NS`, `DECLARE_NS` is not auto generated, so that inheritance can take place.
    - If `TAG` is set and has a namespace (and no base class has a `DECLARE_NS`), `DECLARE_NS` is set to `{ None: namespace }`, where `namespace` is the namespace of the `TAG`.
    - If `TAG` is set and does not have a namespace, `DECLARE_NS` is set to the empty dict. This should not occur outside testing, and support for tags without namespace might be removed in future versions.

    Warning

    It is discouraged to use namespace prefixes of the format `"ns{:d}".format(n)`, for any given number n. These prefixes are reserved for ad-hoc namespace declarations, and attempting to use them may have unwanted side-effects.

    Changed in version 0.4: The automatic generation of the `DECLARE_NS` attribute was added in 0.4.

  `__slots__`

    The metaclass automatically sets this attribute to the empty tuple, unless a different value is set in the class or protect is passed as false to the metaclass.

    Thus, to disable the automatic setting of `__slots__`, inherit for example like this:

        class MyXSO(xso.XSO, protect=False):
            pass

    The rationale for this is that attributes on XSO instances are magic. Having a typo in an attribute may fail non-obviously, if it causes an entirely different semantic to be invoked at the peer (for example the `Message.type_` attribute).

    Setting `__slots__` to empty by default prevents assigning any attribute not bound to an descriptor.

    See also

    slots
      The official Python documentation describes the semantics of the `__slots__` attribute in more detail.

    `XSO` automatically sets a sensible `__slots__` (including `__weakref__`, but not `__dict__`).

    New in version 0.6.

    Note

    If you need to stay compatible with versions before 0.6 and have arbitrary attributes writable, the correct way of doing things is to explicitly set `__slots__` to `("__dict__",)` in your class. You cannot use protect because it is not known in pre-0.6 versions.

  Note

  `XSO` defines defaults for more attributes which also must be present on objects which are used as XSOs.

  When inheriting from `XMLStreamClass` objects, the properties are merged sensibly.

  Rebinding attributes of `XMLStreamClass` instances (i.e. classes using this metaclass) is somewhat restricted. The following rules cannot be broken, attempting to do so will result in `TypeError` being raised when setting the attribute:

  1. Existing descriptors for XSO purposes (such as `xso.Attr`) cannot be removed (either by assigning a new value to the name they are bound to or deleting the name).
  2. New descriptors can only be added if they do not violate the rules stated at the beginning of the `XMLStreamClass` documentation.
  3. New descriptors can only be added if no subclasses exist (see `xso.XSO.register_child()` for reasons why).

To create an enumeration of XSO classes, the following mixin can be used:

class `aioxmpp.xso.``XSOEnumMixin`(namespace, localname)

  Mix-in to create enumerations of XSOs.

  New in version 0.10.

  The enumeration member values must be pairs of `namespace`, `localpart` strings. Each enumeration member is equipped with an `xso_class` attribute at definition time.

  `to_xso`()

    A new instance of the `xso_class`.

    This method exists to make it easier to use the XSO objects and the enumeration members interchangeably. The XSO objects also have the `to_xso()` method which just returns the XSO unmodified.

    Code which needs an XSO, but does not care about the data, can thus use the `to_xso()` method to “coerce” either (enumeration members and instances of their XSO classes) into XSOs.

  `enum_member`

    The object (enum member) itself.

    This property exists to make it easier to use the XSO objects and the enumeration members interchangeably. The XSO objects also have the `enum_member` property to obtain the enumeration member to which they belong. Code which is only interested in the enumeration member can thus access the `enum_member` attribute to “coerce” both (enumeration members and instances of their XSO classes) into enumeration members.

  `xso_class`

    A `aioxmpp.xso.XSO` subclass which has the enumeration members value as `TAG`. So the subclass matches elements which have the qualified tag in the enumeration member value.

    The class does not have any XSO descriptors assigned. They can be added after class definition.

    `enum_member`

      The enumeration member to which the `xso_class` belongs.

      This allows to use XSOs and enumeration members more interchangeably; see `enum_member` for details.

    `to_xso`()

      Return the XSO itself.

      This allows to use XSOs and enumeration members more interchangeably; see `to_xso()` for details.

  Example usage:

      class TagEnum(aioxmpp.xso.XSOEnumMixin, enum.Enum):
          X = ("uri:foo", "x")
          Y = ("uri:foo", "y")

      TagEnum.X.xso_class.enabled = aioxmpp.xso.Attr(
          "enabled",
          type_=aioxmpp.xso.Bool()
      )

  The `TagEnum` members then have a `xso_class` attribute which is a subclass of `XSO` (not an instance of a subclass of `XSO`).

  The `xso_class` for `TagEnum.X` also supports the `enabled` attribute (due to it being monkey-patched onto it), while the `xso_class` for `TagEnum.Y` does not. Thus, monkey-patching can be used to customize the individual XSO classes of the members.

  To use such an enum on a descriptor, the following syntax can be used:

      class Element(aioxmpp.xso.XSO):
          TAG = ("uri:foo", "parent")

          child = aioxmpp.xso.Child([
              member.xso_class
              for member in TagEnum
          ])

### Functions, enumerations and exceptions

The values of the following enumerations are used on “magic” attributes of `XMLStreamClass` instances (i.e. classes).

class `aioxmpp.xso.``UnknownChildPolicy`

  Describe the event which shall take place whenever a child element is encountered for which no descriptor can be found to parse it.

  `FAIL`

    Raise a `ValueError`

  `DROP`

    Drop and ignore the element and all of its children

class `aioxmpp.xso.``UnknownAttrPolicy`

  Describe the event which shall take place whenever a XML attribute is encountered for which no descriptor can be found to parse it.

  `FAIL`

    Raise a `ValueError`

  `DROP`

    Drop and ignore the attribute

class `aioxmpp.xso.``UnknownTextPolicy`

  Describe the event which shall take place whenever XML character data is encountered on an object which does not support it.

  `FAIL`

    Raise a `ValueError`

  `DROP`

    Drop and ignore the text

class `aioxmpp.xso.``ValidateMode`

  Control which ways to set a value in a descriptor are passed through a validator.

  `FROM_RECV`

    Values which are obtained from XML source are validated.

  `FROM_CODE`

    Values which are set through attribute access are validated.

  `ALWAYS`

    All values, whether set by attribute or obtained from XML source, are validated.

The following exceptions are generated at some places in this module:

class `aioxmpp.xso.``UnknownTopLevelTag`(msg, ev_args)

  Subclass of `ValueError`. ev_args must be the arguments of the `"start"` event and are stored as the `ev_args` attribute for inspection.

  `ev_args`

    The ev_args passed to the constructor.

The following special value is used to indicate that no default is used with a descriptor:

`aioxmpp.xso.``NO_DEFAULT`

  This is a special value which is used to indicate that no defaulting should take place. It can be passed to the default arguments of descriptors, and usually is the default value of these arguments.

  It compares unequal to everything but itself, does not support ordering, conversion to bool, float or integer.

`aioxmpp.xso.``capture_events`(receiver, dest)

  Capture all events sent to receiver in the sequence dest. This is a generator, and it is best used with `yield from`. The observable effect of using this generator with `yield from` is identical to the effect of using receiver with `yield from` directly (including the return value), but in addition, the values which are sent to the receiver are captured in dest.

  If receiver raises an exception or the generator is closed prematurely using its `close()`, dest is cleared.

  This is used to implement `CapturingXSO`. See the documentation there for use cases.

  New in version 0.5.

`aioxmpp.xso.``events_to_sax`(events, dest)

  Convert an iterable events of XSO events to SAX events by calling the matching SAX methods on dest

#### Handlers for missing attributes

`aioxmpp.xso.``lang_attr`(instance, ctx)

  A missing handler for `Attr` descriptors. If any parent object has a `xml:lang` attribute set, its value is used.

  Pass as missing argument to `Attr` constructors to use this behaviour for a given attribute.

## Types and validators from `types`

This module provides classes whose objects can be used as types and validators in `model`.

### Character Data types

These types describe character data, i.e. text in XML. Thus, they can be used with `Attr`, `Text` and similar descriptors. They are used to deserialise XML character data to python values, such as integers or dates and vice versa. These types inherit from `AbstractCDataType`.

class `aioxmpp.xso.``String`(prepfunc=None)

  Interpret the input value as string.

  Optionally, a stringprep function prepfunc can be applied on the string. A stringprep function must take the string and prepare it accordingly; if it is invalid input, it must raise `ValueError`. Otherwise, it shall return the prepared string.

  If no prepfunc is given, this type is the identity operation.

class `aioxmpp.xso.``Integer`

  Parse the value as base-10 integer and return the result as `int`.

class `aioxmpp.xso.``Bool`

  Parse the value as boolean:

  - `"true"` and `"1"` are taken as `True`,
  - `"false"` and `"0"` are taken as `False`,
  - everything else results in a `ValueError` exception.

class `aioxmpp.xso.``DateTime`(*, legacy=False)

  Parse the value as ISO datetime, possibly including microseconds and timezone information.

  Timezones are handled as constant offsets from UTC, and are converted to UTC before the `datetime` object is returned (which is correctly tagged with UTC tzinfo). Values without timezone specification are not tagged.

  If legacy is true, the formatted dates use the legacy date/time format (`CCYYMMDDThh:mm:ss`), as used for example in XEP-0082 or XEP-0009 (whereas in the latter it is not legacy, but defined by XML RPC). In any case, parsing of the legacy format is transparently supported. Timestamps in the legacy format are assumed to be in UTC, and datetime objects are converted to UTC before emitting the legacy format. The timezone designator is never emitted with the legacy format, and ignored if given.

  This class makes use of `pytz`.

  New in version 0.5: The legacy argument was added.

class `aioxmpp.xso.``Date`

  Implement the Date type from XEP-0082.

  Values must have the `date` type, `datetime` is forbidden to avoid silent loss of information.

  New in version 0.5.

class `aioxmpp.xso.``Time`

  Implement the Time type from XEP-0082.

  Values must have the `time` type, `datetime` is forbidden to avoid silent loss of information. Assignment of `time` values in time zones which are not UTC is not allowed either. The reason is that the translation to UTC on formatting is not properly defined without an accompanying date (think daylight saving time transitions, redefinitions of time zones, …).

  New in version 0.5.

class `aioxmpp.xso.``Base64Binary`(*, empty_as_equal=False)

  Parse the value as base64 and return the `bytes` object obtained from decoding.

  If empty_as_equal is `True`, an empty value is represented using a single equal sign. This is used in the SASL protocol.

class `aioxmpp.xso.``HexBinary`

  Parse the value as hexadecimal blob and return the `bytes` object obtained from decoding.

class `aioxmpp.xso.``JID`(*, strict=False)

  Parse the value as Jabber ID using `fromstr()` and return the `aioxmpp.JID` object.

  strict is passed to `fromstr()` and defaults to false. See the `fromstr()` method for a rationale and consider that `parse()` is only called for input coming from the outside.

class `aioxmpp.xso.``ConnectionLocation`

  Parse the value as a host-port pair, as for example used for Stream Management reconnection location advisories.

class `aioxmpp.xso.``LanguageTag`

  Parses the value as Language Tag using `fromstr()`.

  Type coercion requires that any value assigned to a descriptor using this type is an instance of `LanguageTag`.

class `aioxmpp.xso.``EnumCDataType`(enum_class, nested_type=xso.String(), *, allow_coerce=False, deprecate_coerce=False, allow_unknown=True, accept_unknown=True)

  Use an `enum.Enum` as type for an XSO descriptor.

  Parameters:

  - enum_class – The `Enum` to use as type.
  - nested_type (`AbstractCDataType`) – A type which can handle the values of the enumeration members.
  - allow_coerce (`bool`) – Allow coercion of different types to enumeration values.
  - deprecate_coerce (`int` or `bool`) – Emit `DeprecationWarning` when coercion occurs. Requires (but does not imply) allow_coerce.
  - allow_unknown (`bool`) – If true, unknown values are converted to `Unknown` instances when parsing values from the XML stream.
  - accept_unknown (`bool`) – If true, `Unknown` instances are passed through `coerce()` and can thus be assigned to descriptors using this type.
  - pass_unknown (`bool`) – If true, unknown values are accepted unmodified (both on the receiving and on the sending side). It is useful for some `enum.IntEnum` use cases.

  A descriptor using this type will accept elements from the given enum_class as values. Upon serialisiation, the `value` of the enumeration element is taken and formatted through the given nested_type.

  Normally, `coerce()` will raise `TypeError` for any value which is not an instance of enum_class. However, if allow_coerce is true, the value is passed to the enum_class constructor and the result is returned; the `ValueError` raised from the enum_class constructor if an invalid value is passed propagates unmodified.

  Note

  When using allow_coerce, keep in mind that this may have surprising effects for users. Coercion means that the value assigned to an attribute and the value subsequently read from that attribute may not be the same; this may be very surprising to users:

      class E(enum.Enum):
          X = "foo"

      class SomeXSO(xso.XSO):
          attr = xso.Attr("foo", xso.EnumCDataType(E, allow_coerce=True))

      x = SomeXSO()
      x.attr = "foo"
      assert x.attr == "foo"  # assertion fails!

  To allow coercion transitionally while moving from e.g. string-based values to a proper enum, deprecate_coerce can be used. In that case, a `DeprecationWarning` (see `warnings`) is emitted when coercion takes place, to warn users about future removal of the coercion capability. If deprecate_coerce is an integer, it is used as the stacklevel argument for the `warnings.warn()` call. If it is `True`, the stacklevel is 4, which leads to the warning pointing to a descriptor assignment when used with XSO descriptors.

  Handling of `Unknown` values: Using allow_unknown and accept_unknown is advisable to stay compatible with future protocols, which is why both are enabled by default. Considering that constructing an `Unknown` value needs to be done explicitly in code, it is unlikely that a user will accidentally assign an unspecified value to a descriptor using this type with accept_unknown.

  pass_unknown requires allow_unknown and accept_unknown. When set to true, values which are not a member of enum_class are used without modification (but they are validated against the nested_type). This applies to both the sending and the receiving side. The intended use case is with `enum.IntEnum` classes. If a `Unknown` value is passed, it is unwrapped and treated as if the original value had been passed.

  Example:

      class SomeEnum(enum.Enum):
          X = 1
          Y = 2
          Z = 3

      class SomeXSO(xso.XSO):
          attr = xso.Attr(
              "foo",
              type_=xso.EnumCDataType(
                  SomeEnum,
                  # have to use integer, because the value of e.g. SomeEnum.X
                  # is integer!
                  xso.Integer()
              ),
          )

  Changed in version 0.10: Support for pass_unknown was added.

`aioxmpp.xso.``EnumType`(enum_class, [nested_type, ]*, allow_coerce=False, deprecate_coerce=False, allow_unknown=True, accept_unknown=True)

  Create and return a `EnumCDataType` or `EnumElementType`, depending on the type of nested_type.

  If nested_type is a `AbstractCDataType` or omitted, a `EnumCDataType` is constructed. Otherwise, `EnumElementType` is used.

  The arguments are forwarded to the respective class’ constructor.

  New in version 0.10.

  Deprecated since version 0.10: This function was introduced to ease the transition in 0.10 from a unified `EnumType` to split `EnumCDataType` and `EnumElementType`.

  It will be removed in 1.0.

class `aioxmpp.xso.``Unknown`(value)

  A wrapper for an unknown enumeration value.

  Parameters: | value (arbitrary) – The raw value of the “enumeration” “member”.

  Instances of this class may be emitted from and accepted by `EnumCDataType` and `EnumElementType`, see the documentation there for details.

  `Unknown` instances compare equal when they hold an equal value. `Unknown` objects are hashable if their values are hashable. The value they refer to cannot be changed during the lifetime of an `Unknown` object.

### Element types

These types describe structured XML data, i.e. subtrees. Thus, they can be used with the `ChildValueList` and `ChildValueMap` family of descriptors (which represent XSOs as python values). These types inherit from `AbstractElementType`.

class `aioxmpp.xso.``EnumElementType`(enum_class, nested_type, *, allow_coerce=False, deprecate_coerce=False, allow_unknown=True, accept_unknown=True)

  Use an `enum.Enum` as type for an XSO descriptor.

  Parameters:

  - enum_class – The `Enum` to use as type.
  - nested_type (`AbstractElementType`) – Type which describes the value type of the enum_class.
  - allow_coerce (`bool`) – Allow coercion of different types to enumeration values.
  - deprecate_coerce (`int` or `bool`) – Emit `DeprecationWarning` when coercion occurs. Requires (but does not imply) allow_coerce.
  - allow_unknown (`bool`) – If true, unknown values are converted to `Unknown` instances when parsing values from the XML stream.
  - accept_unknown – If true, `Unknown` instances are passed through `coerce()` and can thus be assigned to descriptors using this type.

  A descriptor using this type will accept elements from the given enum_class as values. Upon serialisiation, the `value` of the enumeration element is taken and packed through the given nested_type.

  Normally, `coerce()` will raise `TypeError` for any value which is not an instance of enum_class. However, if allow_coerce is true, the value is passed to the enum_class constructor and the result is returned; the `ValueError` raised from the enum_class constructor if an invalid value is passed propagates unmodified.

  See also

  `EnumCDataType`
    for a detailed discussion on the implications of coercion.

  Handling of `Unknown` values: Using allow_unknown and accept_unknown is advisable to stay compatible with future protocols, which is why both are enabled by default. Considering that constructing an `Unknown` value needs to be done explicitly in code, it is unlikely that a user will accidentally assign an unspecified value to a descriptor using this type with accept_unknown.

class `aioxmpp.xso.``TextChildMap`(xso_type)

  A type for use with `xso.ChildValueMap` and descendants of `xso.AbstractTextChild`.

  This type performs the packing and unpacking of language-text-pairs to and from the xso_type. xso_type must have an interface compatible with `xso.AbstractTextChild`, which means that it must have the language and text at `lang` and `text`, respectively and support the same-named keyword arguments for those attributes at the consturctor.

  For an example see the source of `aioxmpp.Message`.

  New in version 0.5.

### Defining custom types

class `aioxmpp.xso.``AbstractCDataType`

  Subclasses of this class describe character data types.

  They are used to convert python values from (`parse()`) and to (`format()`) XML character data as well as enforce basic type restrictions (`coerce()`) when values are assigned to descriptors using this type.

  This type can be used by the character data descriptors, like `Attr` and `Text`.

  `coerce`(v)

    Force the given value v to be of the type represented by this `AbstractCDataType`.

    `coerce()` is called when user code assigns values to descriptors which use the type; it is notably not called when values are extracted from SAX events, as these go through `parse()` and that is expected to return correctly typed values.

    If v cannot be sensibly coerced, `TypeError` is raised (in some rare occasions, `ValueError` may be ok too).

    Return a coerced version of v or v itself if it matches the required type.

    Note

    For the sake of usability, coercion should only take place rarely; in most of the cases, throwing `TypeError` is the preferred method.

    Otherwise, a user might be surprised why the `int` they assigned to an attribute suddenly became a `str`.

  `parse`(v)

    Convert the given string v into a value of the appropriate type this class implements and return the result.

    If conversion fails, `ValueError` is raised.

    The result of `parse()` must pass through `coerce()` unchanged.

  `format`(v)

    Convert the value v of the type this class implements to a str.

    This conversion does not fail.

    The returned value can be passed to `parse()` to obtain v.

class `aioxmpp.xso.``AbstractElementType`

  Subclasses of this class describe XML subtree types.

  They are used to convert python values from (`unpack()`) and to (`pack()`) XML subtrees represented as `XSO` instances as well as enforce basic type restrictions (`coerce()`) when values are assigned to descriptors using this type.

  This type can be used by the element descriptors, like `ChildValueList` and `ChildValueMap`.

  `get_xso_types`()

    Return the `XSO` subclasses supported by this type.

    Return type: | `Iterable` of `XMLStreamClass`
    Returns: | The `XSO` subclasses which can be passed to `unpack()`.

  `coerce`(v)

    Force the given value v to be compatible to `pack()`.

    `coerce()` is called when user code assigns values to descriptors which use the type; it is notably not called when values are extracted from SAX events, as these go through `unpack()` and that is expected to return correctly typed values.

    If v cannot be sensibly coerced, `TypeError` is raised (in some rare occasions, `ValueError` may be ok too).

    Return a coerced version of v or v itself if it matches the required type.

    Note

    For the sake of usability, coercion should only take place rarely; in most of the cases, throwing `TypeError` is the preferred method.

    Otherwise, a user might be surprised why the `int` they assigned to an attribute suddenly became a `str`.

  `unpack`(obj)

    Convert a `XSO` instance to another object, usually a scalar value or a tuple.

    Parameters: | obj (One of the types returned by `get_xso_types()`.) – The object to unpack.
    Raises: | ValueError – if the conversaion fails.
    Returns: | The unpacked value.

    Think of unpack like a high-level `struct.unpack()`: it converts wire-format data (XML subtrees represented as `XSO` instances) to python values.

  `pack`(v)

    Convert the value v of the type this class implements to an `XSO` instance.

    Parameters: | v (as returned by `unpack()`) – Value to pack
    Return type: | One of the types returned by `get_xso_types()`.
    Returns: | The packed value.

    The returned value can be passed through `unpack()` to obtain a value equal to v.

    Think of pack like a high-level `struct.pack()`: it converts python values to wire-format (XML subtrees represented as `XSO` instances).

### Validators

Validators validate the python values after they have been parsed from XML-sourced strings or even when being assigned to a descriptor attribute (depending on the choice in the validate argument).

They can be useful both for defending and rejecting incorrect input and to avoid producing incorrect output.

#### The basic validator interface

class `aioxmpp.xso.``AbstractValidator`

  This is the interface all validators must implement. In addition, a validators documentation should clearly state on which types it operates.

  `validate`(value)

    Return `True` if the value adheres to the restrictions imposed by this validator and `False` otherwise.

    By default, this method calls `validate_detailed()` and returns `True` if `validate_detailed()` returned an empty result.

  `validate_detailed`(value)

    Return an empty list if the value adheres to the restrictions imposed by this validator.

    If the value does not comply, return a list of `UserValueError` instances which each represent a condition which was violated in a human-readable way.

#### Implementations

class `aioxmpp.xso.``RestrictToSet`(values)

  Restrict the possible values to the values from values. Operates on any types.

class `aioxmpp.xso.``Nmtoken`

  Restrict the possible strings to the NMTOKEN specification of XML Schema Definitions. The validator only works with strings.

  Warning

  This validator is probably incorrect. It is a good first line of defense to avoid creating obvious incorrect output and should not be used as input validator.

  It most likely falsely rejects valid values and may let through invalid values.

class `aioxmpp.xso.``IsInstance`(valid_classes)

  This validator checks that the value is an instance of any of the classes given in valid_classes.

  valid_classes is not copied into the `IsInstance` instance, but instead shared; it can be mutated after the construction of `IsInstance` to allow addition and removal of classes.

class `aioxmpp.xso.``NumericRange`(min_=None, max_=None)

  To be used with orderable types, such as `DateTime` or `Integer`.

  The value is enforced to be within [min, max] (this is the interval from min_ to max_, including both ends).

  Setting min_ or max_ to `None` disables enforcement of that end of the interval. A common use is `NumericRange(min_=1)` in conjunction with `Integer` to enforce the use of positive integers.

  New in version 0.6.

## Querying data from XSOs

With XML, we have XPath as query language to retrieve data from XML trees. With XSOs, we have `aioxmpp.xso.query`, even though it’s not as powerful as XPath.

Syntactically, it’s oriented on XPath. Consider the following XSO classes:

    class FooXSO(xso.XSO):
        TAG = (None, "foo")

        attr = xso.Attr(
            "attr"
        )

    class BarXSO(xso.XSO):
        TAG = (None, "bar")

        child = xso.Child([
            FooXSO,
        ])

    class BazXSO(FooXSO):
        TAG = (None, "baz")

        attr2 = xso.Attr(
            "attr2"
        )

    class RootXSO(xso.XSO):
        TAG = (None, "root")

        children = xso.ChildList([
            FooXSO,
            BarXSO,
        ])

        attr = xso.Attr(
            "attr"
        )

To perform a query, we first need to set up a `query.EvaluationContext`:

    root_xso = # a RootXSO instance
    ec = xso.query.EvaluationContext()
    ec.set_toplevel_object(root_xso)

Using the context, we can now execute queries:

    # to find all FooXSO children of the RootXSO
    ec.eval(RootXSO.children / FooXSO)

    # to find all BarXSO children of the RootXSO
    ec.eval(RootXSO.children / BarXSO)

    # to find all FooXSO children of the RootXSO, where FooXSO.attr
    # is set
    ec.eval(RootXSO.children / FooXSO[where(FooXSO.attr)])

    # to find all FooXSO children of the RootXSO, where FooXSO.attr
    # is *not* set
    ec.eval(RootXSO.children / FooXSO[where(not FooXSO.attr)])

    # to find all FooXSO children of the RootXSO, where FooXSO.attr
    # is set to "foobar"
    ec.eval(RootXSO.children / FooXSO[where(FooXSO.attr == "foobar")])

    # to test whether there is a FooXSO which has attr set to
    # "foobar"
    ec.eval(RootXSO.children / FooXSO.attr == "foobar")

    # to find the first three FooXSO children where attr is set
    ec.eval(RootXSO.children / FooXSO[where(FooXSO.attr)][:3])

The following operators are available in the `aioxmpp.xso` namespace:

class `aioxmpp.xso.``where`(expr)

  Wrap the expression expr so that it can be used as a filter in `[]`.

`aioxmpp.xso.``not_`(expr)

  Return the boolean-not of the value of expr. A expression value is true if it contains at least one element and false otherwise.

  See also

  `EvaluationContext.eval_bool()`
    which is used behind the scenes to calculate the boolean value of expr.
  `NotOp`
    which actually implements the operator.

The following need to be explicitly sourced from `aioxmpp.xso.query`, as they are rarely used directly in user code.

class `aioxmpp.xso.query.``EvaluationContext`

  The evaluation context holds contextual information for the evaluation of a query expression.

  Most notably, it provides the methods for acquiring and replacing the toplevel objects of classes:

  `get_toplevel_object`()

    Return the toplevel object for the given class_. Only exact matches are returned.

  `set_toplevel_object`()

    Set the toplevel object to return from `get_toplevel_object()` when asked for class_ to instance.

    If class_ is `None`, the `type()` of the instance is used.

  In addition, it provides shortcuts for evaluating expressions:

  `eval`(expr)

    Evaluate the expression expr and return the result.

    The result of an expression is always an iterable.

  `eval_bool`(expr)

    Evaluate the expression expr and return the truthness of its result. A result of an expression is said to be true if it contains at least one value. It has the same semantics as `bool()` on sequences.s

Note

The implementation details of the query language are documented in the source. They are not useful unless you want to implement custom query operators, which is not possible without modifying the `aioxmpp.xso.query` source anyways.

## Predefined XSO base classes

Some patterns reoccur when using this subpackage. For these, base classes are provided which faciliate the use.

class `aioxmpp.xso.``AbstractTextChild`(text=None, lang=None)

  One of the recurring patterns when using `xso` is the use of a XSO subclass to represent an XML node which has only character data and an `xml:lang` attribute.

  The text and lang arguments to the constructor can be used to initialize the attributes.

  This class provides exactly that. It inherits from `XSO`.

  `lang`

    The `xml:lang` of the node, as `LanguageTag`.

  `text`

    The textual content of the node (XML character data).

  Example use as base class:

      class Subject(xso.AbstractTextChild):
          TAG = (namespaces.client, "subject")

  The full example can also be found in the source code of `stanza.Subject`.