forms — Data Forms support (XEP-0004)¶
This subpackage contains tools to deal with XEP-0004 Data Forms. Data Forms is a pervasive and highly flexible protocol used in XMPP. It allows for machine-readable (and processable) forms as well as tables of data. This flexibility comes unfortunately at the price of complexity. This subpackage attempts to take some of the load of processing Data Forms off the application developer.
Cheat Sheet:
- The Form class exists for use cases where automated processing of Data Forms is supposed to happen. The Declarative-style Forms allow convenient access to and manipulation of form data from within code.
- Direct use of the Data XSO is advisable if you want to present forms or data to sentient beings: even though Form is more convenient for machine-to-machine use, using the Data sent by the peer easily allows showing the user all fields supported by the peer.
- For machine-processed tables, there is no tooling (yet).
New in version 0.7: Even though the aioxmpp.forms module existed pre-0.7, it has not been documented and was thus not part of the public API.
Note
The authors are not entirely happy with the API at some points. Specifically, at some places where mutable data structures are used, the mutation of these data structures may have unexpected side effects. This may be rectified in a future release by replacing these data structures with their appropriate immutable equivalents.
These locations are marked accordingly.
Declarative-style Forms¶
Base class¶
- class aioxmpp.forms.Form¶
A form template for XEP-0004 Data Forms.
Fields are declared using the different field descriptors available in this module:
TextSingle Represent a "text-single" input with the given var. TextMulti Represent a "text-multi" input with the given var. TextPrivate Represent a "text-private" input with the given var. JIDSingle Represent a "jid-single" input with the given var. JIDMulti Represent a "jid-multi" input with the given var. ListSingle Represent a "list-single" input with the given var. ListMulti Represent a "list-multi" input with the given var. Boolean Represent a "boolean" input with the given var. A form template can be instantiated by two different means:
- the from_xso() method can be called on a xso.Data instance to fill in the template with the data from the XSO.
- the constructor can be called.
With the first method, labels, descriptions, options and values are taken from the XSO. The descriptors declared on the form merely act as a convenient way to access the fields in the XSO.
If a field is missing from the XSO, its descriptor still works as if the form had been constructed using its constructor. It will not be emitted when re-serialising the form for a response using render_reply().
If the XSO has more fields than the form template, these fields are re-emitted when the form is serialised using render_reply().
- LAYOUT¶
A mixed list of descriptors and strings to determine form layout as generated by render_request(). The semantics are the following:
- each str is converted to a "fixed" field without var attribute in the output.
- each AbstractField descriptor is rendered to its corresponding Field XSO.
The elements of LAYOUT are processed in-order. This attribute is optional and can be set on either the Form or a specific instance. If it is absent, it is treated as if it were set to list(self.DESCRIPTORS).
- from_xso(xso)¶
Construct and return an instance from the given xso.
Note
This is a static method (classmethod), even though sphinx does not document it as such.
Parameters: Raises: - ValueError – if the FORM_TYPE mismatches
- ValueError – if field types mismatch
- ValueError – if the type_ does not indicate a form
Returns: newly created instance of this class
The fields from the given xso are matched against the fields on the form. Any matching field loads its data from the xso field. Fields which occur on the form template but not in the xso are skipped. Fields which occur in the xso but not on the form template are also skipped (but are re-emitted when the form is rendered as reply, see render_reply()).
If the form template has a FORM_TYPE attribute and the incoming xso also has a FORM_TYPE field, a mismatch between the two values leads to a ValueError.
The field types of matching fields are checked. If the field type on the incoming XSO may not be upcast to the field type declared on the form (see allow_upcast()), a ValueError is raised.
If the type_ does not indicate an actual form (but rather a cancellation request or tabular result), ValueError is raised.
- render_reply()¶
Create a Data object equal to the object from which the from was created through from_xso(), except that the values of the fields are exchanged with the values set on the form.
Fields which have no corresponding form descriptor are left untouched. Fields which are accessible through form descriptors, but are not in the original Data are not included in the output.
This method only works on forms created through from_xso().
Fields¶
Text fields¶
- class aioxmpp.forms.TextSingle(var, type_=xso.String(), *[, default=None][, required=False][, desc=None][, label=None])¶
Represent a "text-single" input with the given var.
Parameters: default – A default value to initialise the field. See also
- BoundSingleValueField
- is the bound field class used by fields of this type.
- AbstractField
- for documentation on the var, type_, required, desc and label arguments.
- class aioxmpp.forms.TextPrivate(var, type_=xso.String(), *[, default=None][, required=False][, desc=None][, label=None])¶
Represent a "text-private" input with the given var.
Parameters: default – A default value to initialise the field. See also
- BoundSingleValueField
- is the bound field class used by fields of this type.
- AbstractField
- for documentation on the var, type_, required, desc and label arguments.
- class aioxmpp.forms.TextMulti(var, type_=xso.String(), *[, default=()][, required=False][, desc=None][, label=None])¶
Represent a "text-multi" input with the given var.
Parameters: default (tuple) – A default value to initialise the field. See also
- BoundMultiValueField
- is the bound field class used by fields of this type.
- AbstractField
- for documentation on the var, type_, required, desc and label arguments.
JID fields¶
- class aioxmpp.forms.JIDSingle(var, *[, default=None][, required=False][, desc=None][, label=None])¶
Represent a "jid-single" input with the given var.
Parameters: default – A default value to initialise the field. See also
- BoundSingleValueField
- is the bound field class used by fields of this type.
- AbstractField
- for documentation on the var, required, desc and label arguments.
- class aioxmpp.forms.JIDMulti(var, *[, default=()][, required=False][, desc=None][, label=None])¶
Represent a "jid-multi" input with the given var.
Parameters: default (tuple) – A default value to initialise the field. See also
- BoundMultiValueField
- is the bound field class used by fields of this type.
- AbstractField
- for documentation on the var, type_, required, desc and label arguments.
Selection fields¶
- class aioxmpp.forms.ListSingle(var, type_=xso.String(), *[, default=None][, options=[]][, required=False][, desc=None][, label=None])¶
Represent a "list-single" input with the given var.
Parameters: default – A default value to initialise the field. This must be a member of the options. See also
- BoundMultiValueField
- is the bound field class used by fields of this type.
- AbstractChoiceField
- for documentation on the options argument.
- AbstractField
- for documentation on the var, type_, required, desc and label arguments.
- class aioxmpp.forms.ListMulti(var, type_=xso.String(), *[, default=frozenset()][, options=[]][, required=False][, desc=None][, label=None])¶
Represent a "list-multi" input with the given var.
Parameters: default (iterable) – An iterable of options keys default is evaluated into a frozenset and all elements must be keys of the options mapping argument.
See also
- BoundMultiValueField
- is the bound field class used by fields of this type.
- AbstractChoiceField
- for documentation on the options argument.
- AbstractField
- for documentation on the var, type_, required, desc and label arguments.
Other fields¶
- class aioxmpp.forms.Boolean(var, *[, default=False][, required=False][, desc=None][, label=None])¶
Represent a "boolean" input with the given var.
Parameters: default – A default value to initialise the field. See also
- BoundSingleValueField
- is the bound field class used by fields of this type.
- AbstractField
- for documentation on the var, required, desc and label arguments.
Abstract base classes¶
- class aioxmpp.forms.fields.AbstractField(var, type_, *, required=False, desc=None, label=None)[source]¶
Abstract base class to implement field descriptor classes.
Parameters: - var (str) – The field var attribute this descriptor is supposed to represent.
- type (AbstractType) – The type of the data, defaults to String.
- required (bool) – Flag to indicate that the field is required.
- desc (str, without newlines) – Description text for the field, e.g. for tool-tips.
- label (str) – Short, human-readable label for the field
The arguments are used to initialise the respective attributes. Details on the semantics can be found in the respective documentation pieces below.
- desc[source]¶
Represents the description as specified per XEP-0004.
The value of this attribute is used when forms are generated locally. When forms are received from remote peers and Form instances are constructed from that data, this attribute is not used when rendering a reply or when the value is accessed through the bound field.
See also
- desc
- for details on the semantics of this attribute
- label¶
Represents the label flag as specified per XEP-0004.
The value of this attribute is used when forms are generated locally. When forms are received from remote peers and Form instances are constructed from that data, this attribute is not used when rendering a reply or when the value is accessed through the bound field.
See also
- label
- for details on the semantics of this attribute
- required¶
Represents the required flag as specified per XEP-0004.
The value of this attribute is used when forms are generated locally. When forms are received from remote peers and Form instances are constructed from that data, this attribute is not used when rendering a reply or when the value is accessed through the bound field.
See also
- required
- for details on the semantics of this attribute
- var[source]¶
Represents the field ID as specified per XEP-0004.
The value of this attribute is used to match fields when instantiating Form classes from Data XSOs.
See also
- var
- for details on the semantics of this attribute
- create_bound(for_instance)[source]¶
Create a bound field class instance for this field for the given form object and return it.
Parameters: for_instance – The form instance to which the bound field should be bound. This method must be re-implemented by subclasses.
See also
- make_bound()
- creates (using this method) or returns an existing bound field for a given form instance.
- default()[source]¶
Create and return a default value for this field.
This must be implemented by subclasses.
- make_bound(for_instance)[source]¶
Create a new bound field class or return an existing one for the given form object.
Parameters: for_instance – The form instance to which the bound field should be bound. If no bound field can be found on the given for_instance for this field, a new one is created using create_bound(), stored at the instance and returned. Otherwise, the existing instance is returned.
See also
- create_bound()
- creates a new bound field for the given form instance (without storing it anywhere).
- class aioxmpp.forms.fields.AbstractChoiceField(var, type_=xso.String(), *[, options=[]][, required=False][, desc=None][, label=None])[source]¶
Abstract base class to implement field descriptor classes using options.
Parameters: - type (AbstractType) – Type used for the option keys.
- options (sequence of pairs or mapping) – A sequence of key-value pairs or a mapping object representing the options available.
The keys of the options mapping (or the first elements in the pairs in the sequence of pairs) must be compatible with type_, in the sense that must pass through coerce() (this is enforced when the field is instantiated).
Fields using this base class:
aioxmpp.forms.ListSingle Represent a "list-single" input with the given var. aioxmpp.forms.ListMulti Represent a "list-multi" input with the given var. See also
- BoundOptionsField
- is an abstract base class to implement bound field classes for fields inheriting from this class.
- AbstractField
- for documentation on the var, required, desc and label arguments.
Bound fields¶
Bound fields are objects which are returned when the descriptor attribute is accessed on a form instance. It holds the value of the field, as well as overrides for the default (specified on the descriptors themselves) values for certain attributes (such as desc).
For the different field types, there are different classes of bound fields, which are documented below.
- class aioxmpp.forms.fields.BoundField(field, instance)[source]¶
Abstract base class for objects returned by the field descriptors.
Parameters: - field (AbstractField) – field descriptor to bind
- instance (object) – form instance to bind to
BoundField instances represent the connection between the field descriptors present at a form class and the instance of that class.
They store of course the value of the field for the specific instance, but also possible instance-specific overrides for the metadata attributes desc, label and required (and possibly BoundOptionsField.options). By default, these attributes return the same value as set on the corresponding field, but the attributes can be set to different values, which only affects the single form instance.
The use case is to fill these fields with the information obtained from a Data XSO when creating a form with Form.from_xso(): it allows the fields to behave exactly like the sender specified.
Deep-copying a BoundField deepcopies all attributes, except the field and instance attributes. See also clone_for() for copying a bound field for a new instance.
Subclass overview:
BoundSingleValueField(field, instance) A bound field which has only a single value at any time. BoundMultiValueField(field, instance) A bound field which can have multiple values. BoundSelectField(field, instance) Bound field carrying one value out of a set of options. BoundMultiSelectField(field, instance) Bound field carrying a subset of values out of a set of options. Binding relationship:
- instance¶
The instance as passed to the constructor.
Field metadata attributes:
- desc[source]¶
See also
- Field.desc
- for a full description of the desc semantics.
- label[source]¶
See also
- Field.label
- for a full description of the label semantics.
- required[source]¶
See also
- Field.required
- for a full description of the required semantics.
Helper methods:
- clone_for(other_instance, memo=None)[source]¶
Clone this bound field for another instance, possibly during a deepcopy() operation.
Parameters: If this is called during a deepcopy operation, passing the memo helps preserving and preventing loops. This method is essentially a deepcopy-operation, with a modification of the instance afterwards.
The following methods must be implemented by base classes.
- load(field_xso)[source]¶
Load the field information from a data field.
Parameters: field_xso (Field) – XSO describing the field. This loads the current value, description, label and possibly options from the field_xso, shadowing the information from the declaration of the field on the class.
This method is must be overriden and is thus marked abstract. However, when called from a subclass, it loads the desc, label and required from the given field_xso. Subclasses are supposed to implement a mechansim to load options and/or values from the field_xso and then call this implementation through super().
- render(*, use_local_metadata=True)[source]¶
Return a Field containing the values and metadata set in the field.
Parameters: use_local_metadata (bool) – if true, the description, label and required metadata can be sourced from the field descriptor associated with this bound field. Returns: A new Field instance. The returned object uses the values accessible through this object; that means, any values set for e.g. desc take precedence over the values declared at the class level. If use_local_metadata is false, values declared at the class level are not used if no local values are declared. This is useful when generating a reply to a form received by a peer, as it avoids sending a modified form.
This method is must be overriden and is thus marked abstract. However, when called from a subclass, it creates the Field instance and initialies its var, type_, desc, required and label attributes and returns the result. Subclasses are supposed to override this method, call the base implementation through super() to obtain the Field instance and then fill in the values and/or options.
- class aioxmpp.forms.fields.BoundSingleValueField(field, instance)[source]¶
A bound field which has only a single value at any time. Only the first value is parsed when loading data from a Field XSO. When writing data to a Field XSO, None is treated as the absence of any value; every other value is serialised through the type_ of the field.
See also
- BoundField
- for a description of the arguments.
This bound field is used by TextSingle, TextPrivate and JIDSingle.
- value[source]¶
The current value of the field. If no value is set when this attribute is accessed for reading, the default() of the field is invoked and the result is set and returned as value.
Only values which pass through coerce() of the type_ of the field can be set. To revert the value to its default, use the del operator.
- class aioxmpp.forms.fields.BoundMultiValueField(field, instance)[source]¶
A bound field which can have multiple values.
See also
- BoundField
- for a description of the arguments.
This bound field is used by TextMulti and JIDMulti.
- value[source]¶
A tuple of values. This attribute can be set with any iterable; the iterable is then evaluated into a tuple and stored at the bound field.
Whenever values are written to this attribute, they are passed through the coerce() method of the type_ of the field. To revert the value to its default, use the del operator.
- class aioxmpp.forms.fields.BoundOptionsField(field, instance)[source]¶
This is an intermediate base class used to implement bound fields for fields which have options from which one or more values must be chosen.
See also
- BoundField
- for a description of the arguments.
When the field is loaded from a Field XSO, the options are also loaded from there and thus shadow the options defined at the field. This may come to a surprise of code expecting a specific set of options.
Subclass overview:
BoundSelectField(field, instance) Bound field carrying one value out of a set of options. BoundMultiSelectField(field, instance) Bound field carrying a subset of values out of a set of options. - options[source]¶
This is a collections.OrderedDict which maps option keys to their labels. The keys are used as the values of the field; the labels are human-readable text for display.
This attribute can be written with any object which is compatible with the dict-constructor. The order is preserved if a sequence of key-value pairs is used.
When writing the attribute, the keys are checked against the coerce() method of the type_ of the field. To make the options attribute identical to the options attribute, use the del operator.
Warning
This attribute is mutable, however, mutating it directly may have unexpected side effects:
If the attribute has not been set before, you will actually be mutating the options attributes value.
This may be changed in the future by copying more eagerly.
The type checking cannot take place when keys are added by direct mutation of the dictionary. This means that errors will be delayed until the actual serialisation of the data form, which may be a confusing thing to debug.
Relying on the above behaviour or any other behaviour induced by directly mutating the value returned by this attribute is not recommended. Changes to this behaviour are not considered breaking changes and will be done without the usual deprecation.
- class aioxmpp.forms.fields.BoundSelectField(field, instance)[source]¶
Bound field carrying one value out of a set of options.
See also
- BoundField
- for a description of the arguments.
- BoundOptionsField.options
- for semantics and behaviour of the options attribute
- value[source]¶
The current value of the field. If no value is set when this attribute is accessed for reading, the default() of the field is invoked and the result is set and returned as value.
Only values contained in the options can be set, other values are rejected with a ValueError. To revert the value to the default value specified in the descriptor, use the del operator.
- class aioxmpp.forms.fields.BoundMultiSelectField(field, instance)[source]¶
Bound field carrying a subset of values out of a set of options.
See also
- BoundField
- for a description of the arguments.
- BoundOptionsField.options
- for semantics and behaviour of the options attribute
- value[source]¶
A frozenset whose elements are a subset of the keys of the options mapping.
This value can be written with any iterable; the iterable is then evaluated into a frozenset. If it contains any value not contained in the set of keys of options, the attribute is not written and ValueError is raised.
To revert the value to the default specified by the field descriptor, use the del operator.
XSOs¶
- class aioxmpp.forms.Data(type_)¶
A XEP-0004 x element, that is, a Data Form.
Parameters: type – Initial value for the type_ attribute. - type_¶
The type attribute of the form, represented by one of the members of the DataType enumeration.
- instructions¶
A sequence of strings which represent the instructions elements on the form.
- fields¶
If the Data is a form, this is a sequence of Field elements which represent the fields to be filled in.
This does not make sense on DataType.RESULT typed objects.
- items¶
If the Data is a table, this is a sequence of Item instances which represent the table rows.
This only makes sense on DataType.RESULT typed objects.
- reported¶
If the Data is a table, this is a Reported object representing the table header.
This only makes sense on DataType.RESULT typed objects.
- class aioxmpp.forms.DataType¶
Enumeration containing the Data types defined in XEP-0004.
Quotations in the following attribute descriptions are from XEP-0004.
- FORM¶
The "form" type:
The form-processing entity is asking the form-submitting entity to complete a form.
- SUBMIT¶
The "submit" type:
The form-submitting entity is submitting data to the form-processing entity. The submission MAY include fields that were not provided in the empty form, but the form-processing entity MUST ignore any fields that it does not understand.
- CANCEL¶
The "cancel" type:
The form-submitting entity has cancelled submission of data to the form-processing entity.
- RESULT¶
The "result" type:
The form-processing entity is returning data (e.g., search results) to the form-submitting entity, or the data is a generic data set.
- class aioxmpp.forms.Field(*, type_=<FieldType.TEXT_SINGLE: 'text-single'>, options={}, values=[], desc=None, label=None, required=False, var=None)¶
Represent a single field in a Data Form.
Parameters: - type (FieldType) – Field type, must be one of the valid field types specified in XEP-0004.
- options (dict mapping str to str) – A mapping of values to labels defining the options in a list-* field.
- values (list of str) – A sequence of values currently given for the field. Having more than one value is only valid in *-multi fields.
- desc (str or :data:`None`s) – Description which can be shown in a tool-tip or similar, without newlines.
- label (str or None) – Human-readable label to be shown next to the field input
- required (bool) – Flag to indicate that the field is required
- var (str or None) – “ID” identifying the field uniquely inside the form. Only required for fields carrying a meaning (thus, not for fixed).
The semantics of a Field are different depending on where it occurs: in a Data, it is a form field to be filled in, in a Item it is a cell of a row and in a Reported it represents a column header.
- required¶
A boolean flag indicating whether the field is required.
If true, the XML serialisation will contain the corresponding <required/> tag.
- desc¶
Single line of description for the field. This attribute represents the <desc/> element from XEP-0004.
- values¶
A sequence of strings representing the <value/> elements of the field, one string for each value.
Note
Since the requirements on the sequence of strings in values change depending on the type_ attribute, validation and type conversion on assignment is very lax. The attribute accepts all sequences of strings, even if the field is for example a FieldType.BOOLEAN field, which allows for at most one string of a well-defined format (see the documentation there for the details).
This makes it easy to inadvertendly generate invalid forms, which is why you should be using Form subclasses when accessing forms from within normal code and some other, generic mechanism taking care of these details when showing forms in a UI framework to users. Note that devising such a mechanism is out of scope for aioxmpp, as every UI framework has different requirements.
- options¶
A dictionary mapping values to human-readable labels, representing the <option/> elements of the field.
- var¶
The uniquely identifying string of the (valued, that is, non-FieldType.FIXED field). Represents the var attribute of the field.
- class aioxmpp.forms.FieldType¶
Enumeration containing the field types defined in XEP-0004.
See also
- Field.values
- for important information regarding typing, restrictions, validation and constraints of values in that attribute.
Each type has the following attributes and methods:
- allow_upcast(to)¶
Return true if the field type may be upcast to the other field type to.
This relation specifies when it is safe to transfer data from this field type to the given other field type to.
This is the case if any of the following holds true:
- to is equal to this type
- this type is TEXT_SINGLE and to is TEXT_PRIVATE
- has_options¶
true for the list- field types, false otherwise.
- is_multivalued¶
true for the -multi field types, false otherwise.
Quotations in the following attribute descriptions are from said XEP.
- BOOLEAN¶
The "boolean" field:
The field enables an entity to gather or provide an either-or choice between two options. The default value is “false”.The Field.values sequence should contain zero or one elements. If it contains an element, it must be "0", "1", "false", or "true", in accordance with the XML Schema documents.
- FIXED¶
The "fixed" field:
The field is intended for data description (e.g., human-readable text such as “section” headers) rather than data gathering or provision. The <value/> child SHOULD NOT contain newlines (the \n and \r characters); instead an application SHOULD generate multiple fixed fields, each with one <value/> child.As such, the Field.values sequence should contain exactly one element. Field.desc, Field.label, Field.options and Field.var should be set to None or empty containers.
- HIDDEN¶
The "hidden" field:
The field is not shown to the form-submitting entity, but instead is returned with the form. The form-submitting entity SHOULD NOT modify the value of a hidden field, but MAY do so if such behavior is defined for the “using protocol”.This type is commonly used for the var="FORM_TYPE" field, as specified in XEP-0068.
- JID_MULTI¶
The "jid-multi" field:
The field enables an entity to gather or provide multiple Jabber IDs. Each provided JID SHOULD be unique (as determined by comparison that includes application of the Nodeprep, Nameprep, and Resourceprep profiles of Stringprep as specified in XMPP Core), and duplicate JIDs MUST be ignored.As such, the Field.values sequence should contain zero or more strings representing Jabber IDs. Field.options should be empty.
- JID_SINGLE¶
The "jid-single" field:
The field enables an entity to gather or provide a single Jabber ID.As such, the Field.values sequence should contain zero or one string representing a Jabber ID. Field.options should be empty.
- LIST_MULTI¶
The "list-multi" field:
The field enables an entity to gather or provide one or more options from among many. A form-submitting entity chooses one or more items from among the options presented by the form-processing entity and MUST NOT insert new options. The form-submitting entity MUST NOT modify the order of items as received from the form-processing entity, since the order of items MAY be significant.Thus, Field.values should contain a subset of the keys of the Field.options dictionary.
- LIST_SINGLE¶
The "list-single" field:
The field enables an entity to gather or provide one option from among many. A form-submitting entity chooses one item from among the options presented by the form-processing entity and MUST NOT insert new options.Thus, Field.values should contain a zero or one of the keys of the Field.options dictionary.
- TEXT_MULTI¶
The "text-multi" field:
The field enables an entity to gather or provide multiple lines of text.Each string in the Field.values attribute should be a single line of text. Newlines are not allowed in data forms fields (due to the ambiguity between \r and \n and combinations thereof), which is why the text is split on the line endings.
- TEXT_PRIVATE¶
The "text-private" field:
The field enables an entity to gather or provide a single line or word of text, which shall be obscured in an interface (e.g., with multiple instances of the asterisk character).The Field.values attribute should contain zero or one string without any newlines.
- TEXT_SINGLE¶
The "text-single" field:
The field enables an entity to gather or provide a single line or word of text, which may be shown in an interface. This field type is the default and MUST be assumed if a form-submitting entity receives a field type it does not understand.The Field.values attribute should contain zero or one string without any newlines.