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.
Introduction¶
See also
For a more in-depth introduction into aioxmpp.xso
, please refer to
the An Introduction to XSO chapter in the user guide. This document
here is a reference manual.
The aioxmpp.xso
subpackage provides declarative-style parsing of XML
document fragments. The declarations are similar to what you might know from
declarative Object-Relational-Mappers such as sqlalchemy
. Due to the
different data model of XML and relational databases, they are not identical
of course.
An abstract class describing the common properties of an XMPP stanza might look like this:
class Stanza(xso.XSO):
from_ = xso.Attr(tag="from", type_=xso.JID(), default=None)
to = xso.Attr(tag="to", type_=xso.JID(), default=None)
lang = xso.LangAttr(tag=(namespaces.xml, "lang"))
Instances of classes deriving from aioxmpp.xso.XSO
are called XML
stream objects, or XSOs for short. Each XSO maps to an XML element node.
The declaration of an XSO class typically has one or more descriptors describing the mapping of XML child nodes of the element. XML nodes which can be mapped include attributes, text and elements (processing instructions and comments are not supported; CDATA sections are treated like text).
XSO-specific 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.
XML stream events¶
XSOs are parsed using SAX-like events. This allows them to be built one-by-one in memory (and discarded) even while the XML stream is in progress.
The XSO module uses a subset of the original SAX event list, and it uses a custom format. The reason for that is that instead of using an interface with methods, the parsing parts are implemented using suspendable functions (see below).
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 XML stream 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)[source]¶ 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, astr
.
Return a two-tuple consisting the
(namespace_uri, localpart)
format.
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¶
|
A single XML attribute. |
|
Special handler for the |
|
Character data contents of an XSO. |
|
A single child element of any of the given XSO types. |
|
Tag of a single child element with one of the given tags. |
|
Presence of a child element with the given tag, as boolean. |
|
Character data of a single child element matching the given tag. |
|
Dictionary of character data in child elements keyed by the language attribute. |
|
Child element parsed using an Element Type. |
|
List of child elements of any of the given XSO classes. |
|
Dictionary holding child elements of one or more XSO classes. |
|
Shorthand for a dictionary of child elements keyed by the language attribute. |
|
List of child elements parsed using the given Element Type. |
|
Dictiorary of child elements parsed using the given Element Type. |
|
Multi-dict of child elements parsed using the given Element Type. |
Catch-all descriptor collecting unhandled elements in an |
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])[source]¶ A single XML attribute.
- Parameters
tag (
str
ortuple
of Namespace URI and Local Name.) – The tag identifying the attribute.
If the tag is a
str
, it is converted using(None, tag)
, thus representing an unnamespaced attribute. Note that most attributes are unnamespaced; namespaced attributes always have a namespace prefix on them. Attributes without a namespace prefix, in XML, are unnamespaced (not part of the current prefixless namespace).Note
The following arguments occur at several of the descriptor classes, and are all available at
Attr
. Their semantics are identical on other classes, transferred to the respective use there.(For example, the
ChildText
descriptor is obviously not working with attributes, so the phrase “if the attribute is absent” should be mentally translated to “if the child element is absent”.)- Parameters
type (
AbstractCDataType
) – A character data type to interpret the XML character data.validator (
AbstractValidator
) – Optional validator objectvalidate (
ValidateMode
) – Control when the validator is enforced.default – The value which the attribute has if no value has been assigned.
missing (
None
or unary function) – Callback function to handle a missing attribute in the input.erroneous_as_absent (
bool
) – Treat an erroneous value (= the type_ raisesValueError
orTypeError
while parsing) as if the attribute was not present.
The type_ must be a Character Data Type, i.e. an instance of a subclass of
AbstractCDataType
. By default, it isaioxmpp.xso.String
. The type_ is used to parse the XML character data into python types as appropriate. Errors during this parsing count as parsing errors of the whole XSO (subtree), unless erroneous_as_absent is set to true. In that case, the attribute is simply treated as absent if parsing the value fails.If the XML attribute has no default assigned, the descriptor will appear to have the default value. If no default is given (the default) and an attempt is made to access the described attribute,
AttributeError
is raised as you would expect from any normal attribute.If a default is given, the default is also returned after a del operation; otherwise, del behaves as for any normal attribute.
Another peculiar property of the default is that it does not need to conform to the validator or type_. If the descriptor is set to the default value, it is not emitted on the output.
In addition to the default, it is possible to inject attribute values at parse time using the missing callback. missing must be None or a function taking a single argument. If it is not None, it will be called with the parsing
Context
as its only argument when a missing attribute is encountered. The return value, unlessNone
, is used as value for the descriptor. If the return value isNone
, the attribute is treated like any normal missing attribute.It is possible to add validation to values received over the wire or assigned to the descriptor. The validator object controls what validation occurs and validate controls when validation occurs.
validate must be a member of the
ValidateMode
enumeration (see there for the semantics of the values). validator must be an object implementing the interface defined byAbstractValidator
.Note that validation is independent of the conversions applied by type_. Validation always happens on the parsed type and happens before serialisation. Thus, if type_ is not
aioxmpp.xso.String
, the validator will not receive astr
object to operate on.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)[source]¶ 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 notNone
, 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 returnsNone
, the handling continues as normal: if required is true, aValueError
is raised.
-
class
aioxmpp.xso.
LangAttr
(*[, validator=None][, validate=ValidateMode.FROM_RECV][, default=None])[source]¶ Special handler for the
xml:lang
attribute.An attribute representing the
xml:lang
attribute, including inheritance semantics.This is a subclass of
Attr
which takes care of inheriting thexml:lang
value of the parent. The tag is set to the(namespaces.xml, "lang")
value to matchxml:lang
attributes. type_ is axso.LanguageTag
instance and missing is set tolang_attr()
.
-
class
aioxmpp.xso.
Child
(classes, *[, required=False][, strict=False])[source]¶ A single child element of any of the given XSO types.
- Parameters
classes (iterable of
aioxmpp.xso.XSO
subclasses) – XSO types to support in this attributerequired (
bool
) – If true, parsing fails if the element is missing.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 andNone
is a valid value for the described attribute. Otherwise, a missing matching child is an error and the attribute cannot be set toNone
.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.
This comes with a performance impact on every write to the descriptor, so it is disabled by default. It is recommended to enable this for descriptors where applications may register additional classes, to protect them from forgetting such a registration (which would cause issues with reception).
If during parsing, more than one child element with a tag matching one of the
XSO.TAG
values of the registered classes is encountered, it is unspecified which child is taken.-
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.
-
class
aioxmpp.xso.
ChildTag
(tags, *[, text_policy=UnknownTextPolicy.FAIL][, child_policy=UnknownChildPolicy.FAIL][, attr_policy=UnknownAttrPolicy.FAIL][, default_ns=None][, allow_none=False])[source]¶ Tag of a single child element with one of the given tags.
- Parameters
tags (iterable of valid arguments to
normalize_tags()
or aenum.Enum
subclass) – The tags to match on.text_policy (
UnknownTextPolicy
) – Determine how text content on the child elements is handled.child_policy (
UnknownChildPolicy
) – Determine how elements nested in the child elements are handled.attr_policy (
UnknownAttrPolicy
) – Determine how attributes on the child elements are handled.allow_none (
bool
) – If true,None
is used as the default if no child matching the tags is found and represents the absence of the child for serialisation.declare_prefix (
False
,None
orstr
) – Which namespace prefix, if any, to declare on the child element for its namespace.
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 anenum.Enum
whose values are valid arguments tonormalize_tag()
. Ifnormalize_tag()
returns a false value (such asNone
) as namespace_uri, it is replaced with default_ns (defaulting toNone
, 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 ofNone
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 thatNone
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.
ChildFlag
(tag, *[, text_policy=UnknownTextPolicy.FAIL][, child_policy=UnknownChildPolicy.FAIL][, attr_policy=UnknownAttrPolicy.FAIL])[source]¶ Presence of a child element with the given tag, as boolean.
- Parameters
tag (
str
ortuple
) – The tag of the child element to use as flag.text_policy (
UnknownTextPolicy
) – Determine how text content on the child elements is handled.child_policy (
UnknownChildPolicy
) – Determine how elements nested in the child elements are handled.attr_policy (
UnknownAttrPolicy
) – Determine how attributes on the child elements are handled.
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 valuesTrue
andFalse
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 thatNone
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])[source]¶ Character data of a single child element matching the given tag.
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
andUnknownAttrPolicy
for the possible behaviours.-
get_tag_map
()[source]¶ Return an iterable yielding
tag
.This is for compatibility with the
Child
interface.
-
from_events
(instance, ev_args, ctx)[source]¶ 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 (seeUnknownChildPolicy
). Likewise, if the start event contains attributes,attr_policy
is enforced (c.f.UnknownAttrPolicy
).The extracted text is passed through
type_
andvalidator
and if it passes, stored in the attribute on the instance with which the property is associated.This method is suspendable.
-
class
aioxmpp.xso.
ChildValue
(type_)[source]¶ Child element parsed using an Element Type.
Descriptor represeting a child element as parsed using an element type.
- Parameters
type (
aioxmpp.xso.AbstractElementType
) – The element type to use to parse the child element.
The descriptor value will be the unpacked child element value. Upon serialisation, the descriptor
-
class
aioxmpp.xso.
Text
(*[, type_=xso.String()][, validator=None][, validate=ValidateMode.FROM_RECV][, default][, erroneous_as_absent=False])[source]¶ Character data contents of an XSO.
Note that this does not preserve 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
.
Non-scalar descriptors¶
-
class
aioxmpp.xso.
ChildList
(classes)[source]¶ List of child elements of any of the given XSO classes.
The
ChildList
works likeChild
, 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)[source]¶ Like
Child.from_events()
, but instead of replacing the attribute value, the new object is appended to the list.
-
class
aioxmpp.xso.
ChildMap
(classes[, key=None])[source]¶ Dictionary holding child elements of one or more XSO classes.
The
ChildMap
class works likeChildList
, but instead of storing the child objects in a list, they are stored in a map which contains anXSOList
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)[source]¶ Like
ChildList.from_events()
, but the object is appended to the list associated with its tag in the dict.
-
to_sax
(instance, dest)[source]¶ 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)[source]¶ 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 anappend()
method which does what you want it to do.
-
-
class
aioxmpp.xso.
ChildLangMap
(classes)[source]¶ Shorthand for a dictionary of child elements keyed by the language attribute.
The
ChildLangMap
class is a specialized version of theChildMap
, 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_)[source]¶ List of child elements parsed using the given Element Type.
- Parameters
type (
AbstractElementType
) – Type describing the subtree to convert to python values.container_type (Subclass of
MutableSequence
orMutableSet
) – 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()
orappend()
of the values used with the type_ and iteration. It will be used instead oflist
to create the values for the descriptor.New in version 0.5.
-
class
aioxmpp.xso.
ChildValueMap
(type_, *, mapping_type=dict)[source]¶ Dictiorary of child elements parsed using the given Element Type.
- 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 inxso.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 ofdict
to create the values for the descriptor. A possible use-case is usingstructs.LanguageMap
together withTextChildMap
.See also
ChildTextMap
for a specialised version to deal withAbstractTextChild
subclasses.New in version 0.5.
-
class
aioxmpp.xso.
ChildValueMultiMap
(type_, *, mapping_type=multidict.MultiDict)[source]¶ Multi-dict of child elements parsed using the given Element Type.
- Parameters
type (
AbstractElementType
) – Type describing the subtree to convert to pairs of key and value.
This is very similar to
ChildValueMap
, but it uses amultidict.MultiDict
as storage. Interface-compatible classes can be substituted by passing them to mapping_type. Candidate for that aremultidict.CIMultiDict
.New in version 0.6.
-
class
aioxmpp.xso.
ChildTextMap
(xso_type)[source]¶ Dictionary of character data in child elements keyed by the language attribute.
A specialised version of
ChildValueMap
which usesTextChildMap
together withstructs.LanguageMap
to convert theAbstractTextChild
subclass xso_type to and from a language-text mapping.If instead of an
XSO
a tag is passed (that is, a valid argument tonormalize_tag()
) anAbstractTextChild
instance is created on demand.For an example, see
Message
.
-
class
aioxmpp.xso.
Collector
[source]¶ Catch-all descriptor collecting unhandled elements in an
lxml
element tree.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 empty 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.
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
(iterable=(), /)[source]¶ A
list
subclass; it provides the completelist
interface with the addition of the following methods:-
filter
(*, type_=None, lang=None, attrs={})[source]¶ 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 aLanguageRange
or an iterable of language ranges. The set of languages present among the working sequence is determined and used for a call tolookup_language
. If the lookup returns a language, all elements whoselang
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 namedlang
.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={})[source]¶ 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
[source]¶ 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 aXSOParser
returns a generator which parses stanzas from sax-ish events. Use withSAXDriver
).Example use:
# let Message be a XSO class, like in the XSO example result = None def catch_result(value): global result result = value parser = aioxmpp.xso.XSOParser() parser.add_class(Message, catch_result) sd = aioxmpp.xso.SAXDriver(parser) lxml.sax.saxify(lxml.etree.fromstring( "<jc:message id='foo' from='bar' to='baz' type='chat' " "xmlns:jc='jabber:client'/>" ), sd)
The following methods can be used to dynamically add and remove top-level
XSO
classes.-
add_class
(cls, callback)[source]¶ 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.
-
-
class
aioxmpp.xso.
SAXDriver
(dest_generator_factory, on_emit=None)[source]¶ 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 callclose()
to clean up internal parser 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
[source]¶ 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 throughxso_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
andAttr
-based attributes.
See also
xso.model.XMLStreamClass
is the metaclass of
XSO
. The documentation of the metaclass holds valuable information with respect to modifyingXSO
classes and subclassing.
Note
Attributes whose name starts with
xso_
or_xso_
are reserved for use by theaioxmpp.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
()[source]¶ 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 viasuper()
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
:-
xso_serialise_to_sax
(dest)[source]¶ Serialise the XSO to a SAX handler.
- Parameters
dest – SAX handler to send the events to
Changed in version 0.11: The method was renamed from unparse_to_sax to xso_serialise_to_sax.
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 aSAXDriver
.Note
While this method creates an instance of the class,
__init__
is not called. See the documentation ofxso.XSO()
for details.This method is suspendable.
-
classmethod
register_child
(prop, child_cls)¶ Register a new
XMLStreamClass
instance child_cls for a givenChild
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:
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.
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 aTypeError
.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
()[source]¶ 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)[source]¶ 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 toUnknownChildPolicy.FAIL
, descriptor and exc_info are passed asNone
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
[source]¶ 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 ofXSO.parse_events()
.Like the method it overrides,
parse_events()
is suspendable.
The
_set_captured_events()
method can be overridden by subclasses to make use of the captured events:-
abstract
_set_captured_events
(events)[source]¶ 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 withaioxmpp.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.
-
classmethod
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)[source]¶ 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: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.The above applies equivalently for
Collector
descriptors.At no point in the inheritance tree there must exist more than one
Attr
descriptor which handles a given attribute tag. Like withText
, it is allowed that the sameAttr
descriptor is inherited through multiple paths from parent classes.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 isNone
if no attribute using that descriptor is declared on the class.
-
COLLECTOR_PROPERTY
¶ The
Collector
descriptor object associated with this class. This isNone
if no attribute using that descriptor is declared on the class.
-
CHILD_MAP
¶ A dictionary mapping element tags to the
Child
(or similar) descriptor objects which accept these child elements.
-
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 aDECLARE_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 aDECLARE_NS
),DECLARE_NS
is set to{ None: namespace }
, wherenamespace
is the namespace of theTAG
.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
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 inTypeError
being raised when setting the attribute: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).New descriptors can only be added if they do not violate the rules stated at the beginning of the
XMLStreamClass
documentation.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)[source]¶ 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 anxso_class
attribute at definition time.-
to_xso
()[source]¶ 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 theenum_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 asTAG
. 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.
-
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 axso_class
attribute which is a subclass ofXSO
(not an instance of a subclass ofXSO
).The
xso_class
forTagEnum.X
also supports theenabled
attribute (due to it being monkey-patched onto it), while thexso_class
forTagEnum.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
(value)[source]¶ 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
(value)[source]¶ 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
(value)[source]¶ 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
(value)[source]¶ 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)[source]¶ Subclass of
ValueError
. ev_args must be the arguments of the"start"
event and are stored as theev_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)[source]¶ 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 withyield from
is identical to the effect of using receiver withyield 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.
Types and validators from types
¶
This module provides classes whose objects can be used as types and validators
in model
.
Character Data types¶
|
String Character Data Type, optionally with string preparation. |
|
Floating point or decimal Character Data Type. |
|
Integer Character Data Type, to the base 10. |
|
XML boolean Character Data Type. |
|
ISO datetime Character Data Type. |
|
ISO date Character Data Type. |
|
ISO time Character Data Type. |
|
Character Data Type for |
Character Data Type for |
|
|
Character Data Type for |
Character Data Type for a hostname-port pair. |
|
Character Data Type for language tags. |
|
|
Character Data Type for JSON formatted data. |
|
Use an |
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)[source]¶ String Character Data Type, optionally with string preparation.
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.
Float
[source]¶ Floating point or decimal Character Data Type.
-
class
aioxmpp.xso.
Integer
[source]¶ Integer Character Data Type, to the base 10.
-
class
aioxmpp.xso.
Bool
[source]¶ XML boolean Character Data Type.
Parse the value as boolean:
"true"
and"1"
are taken asTrue
,"false"
and"0"
are taken asFalse
,everything else results in a
ValueError
exception.
-
class
aioxmpp.xso.
DateTime
(*, legacy=False)[source]¶ ISO datetime Character Data Type.
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
[source]¶ ISO date Character Data Type.
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
[source]¶ ISO time Character Data Type.
Implement the Time type from XEP-0082.
Values must have the
time
type,datetime
is forbidden to avoid silent loss of information. Assignment oftime
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)[source]¶ Character Data Type for
bytes
encoded as base64.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
[source]¶ Character Data Type for
bytes
encoded as hexadecimal.Parse the value as hexadecimal blob and return the
bytes
object obtained from decoding.
-
class
aioxmpp.xso.
JID
(*, strict=False)[source]¶ Character Data Type for
aioxmpp.JID
objects.Parse the value as Jabber ID using
fromstr()
and return theaioxmpp.JID
object.strict is passed to
fromstr()
and defaults to false. See thefromstr()
method for a rationale and consider thatparse()
is only called for input coming from the outside.
-
class
aioxmpp.xso.
ConnectionLocation
[source]¶ Character Data Type for a hostname-port pair.
Parse the value as a host-port pair, as for example used for Stream Management reconnection location advisories.
-
class
aioxmpp.xso.
LanguageTag
[source]¶ Character Data Type for language tags.
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.
JSON
[source]¶ Character Data Type for JSON formatted data.
New in version 0.11.
Upon deserialisation, character data is parsed as JSON using
json
. On serialisation, the value is serialised as JSON. This implies that the data must be JSON serialisable, but there is no check for that incoerce()
, as this check would be (a) expensive to do for nested data structures and (b) impossible to do for mutable data structures.Example:
class JSONContainer(aioxmpp.xso.XSO): TAG = ("urn:xmpp:json:0", "json") data = aioxmpp.xso.Text( type_=aioxmpp.xso.JSON() )
-
class
aioxmpp.xso.
EnumCDataType
(enum_class, nested_type=xso.String(), *, allow_coerce=False, deprecate_coerce=False, allow_unknown=True, accept_unknown=True)[source]¶ 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
orbool
) – EmitDeprecationWarning
when coercion occurs. Requires (but does not imply) allow_coerce.allow_unknown (
bool
) – If true, unknown values are converted toUnknown
instances when parsing values from the XML stream.accept_unknown (
bool
) – If true,Unknown
instances are passed throughcoerce()
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 someenum.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 raiseTypeError
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; theValueError
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
(seewarnings
) 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 thewarnings.warn()
call. If it isTrue
, 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 anUnknown
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 aUnknown
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)[source]¶ Create and return a
EnumCDataType
orEnumElementType
, depending on the type of nested_type.If nested_type is a
AbstractCDataType
or omitted, aEnumCDataType
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 splitEnumCDataType
andEnumElementType
.It will be removed in 1.0.
-
class
aioxmpp.xso.
Unknown
(value)[source]¶ 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
andEnumElementType
, 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 anUnknown
object.
Element types¶
|
Use an |
|
A type for use with |
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)[source]¶ 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
orbool
) – EmitDeprecationWarning
when coercion occurs. Requires (but does not imply) allow_coerce.allow_unknown (
bool
) – If true, unknown values are converted toUnknown
instances when parsing values from the XML stream.accept_unknown – If true,
Unknown
instances are passed throughcoerce()
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 raiseTypeError
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; theValueError
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 anUnknown
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)[source]¶ A type for use with
xso.ChildValueMap
and descendants ofxso.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 atlang
andtext
, respectively and support the same-named keyword arguments for those attributes at the constructor.For an example see the source of
aioxmpp.Message
.New in version 0.5.
Defining custom types¶
-
class
aioxmpp.xso.
AbstractCDataType
[source]¶ 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
andText
.-
coerce
(v)[source]¶ 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 throughparse()
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.
-
abstract
parse
(v)[source]¶ 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.
-
-
class
aioxmpp.xso.
AbstractElementType
[source]¶ Subclasses of this class describe XML subtree types.
They are used to convert python values from (
unpack()
) and to (pack()
) XML subtrees represented asXSO
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
andChildValueMap
.-
coerce
(v)[source]¶ 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 throughunpack()
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.
-
abstract
unpack
(obj)[source]¶ 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 asXSO
instances) to python values.
-
abstract
pack
(v)[source]¶ 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 asXSO
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
[source]¶ This is the interface all validators must implement. In addition, a validators documentation should clearly state on which types it operates.
-
validate
(value)[source]¶ Return
True
if the value adheres to the restrictions imposed by this validator andFalse
otherwise.By default, this method calls
validate_detailed()
and returnsTrue
ifvalidate_detailed()
returned an empty result.
-
abstract
validate_detailed
(value)[source]¶ 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)[source]¶ Restrict the possible values to the values from values. Operates on any types.
-
class
aioxmpp.xso.
Nmtoken
[source]¶ 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)[source]¶ 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 ofIsInstance
to allow addition and removal of classes.
-
class
aioxmpp.xso.
NumericRange
(min_=None, max_=None)[source]¶ To be used with orderable types, such as
DateTime
orInteger
.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 isNumericRange(min_=1)
in conjunction withInteger
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)[source]¶ Wrap the expression expr so that it can be used as a filter in
[]
.
-
aioxmpp.xso.
not_
(expr)[source]¶ 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
[source]¶ 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
()[source]¶ Return the toplevel object for the given class_. Only exact matches are returned.
-
set_toplevel_object
()[source]¶ Set the toplevel object to return from
get_toplevel_object()
when asked for class_ to instance.If class_ is
None
, thetype()
of the instance is used.
In addition, it provides shortcuts for evaluating expressions:
-
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 facilitate the use.
-
class
aioxmpp.xso.
AbstractTextChild
(*args, **kwargs)[source]¶ 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 anxml: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, asLanguageTag
.
-
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
.-