Source code for slixmpp.plugins.xep_0004.stanza.form
# Slixmpp: The Slick XMPP Library
# Copyright (C) 2011 Nathanael C. Fritz, Lance J.T. Stout
# This file is part of Slixmpp.
# See the file LICENSE for copying permission.
import copy
import logging
from slixmpp.thirdparty import OrderedSet
from slixmpp.xmlstream import ElementBase, ET
from slixmpp.plugins.xep_0004.stanza import FormField
log = logging.getLogger(__name__)
[docs]class Form(ElementBase):
namespace = 'jabber:x:data'
name = 'x'
plugin_attrib = 'form'
plugin_multi_attrib = 'forms'
interfaces = OrderedSet(('instructions', 'reported', 'title', 'type', 'items', 'values'))
sub_interfaces = {'title'}
form_types = {'cancel', 'form', 'result', 'submit'}
def __init__(self, *args, **kwargs):
title = None
if 'title' in kwargs:
title = kwargs['title']
del kwargs['title']
ElementBase.__init__(self, *args, **kwargs)
if title is not None:
self['title'] = title
[docs] def setup(self, xml=None):
if ElementBase.setup(self, xml):
# If we had to generate xml
self['type'] = 'form'
@property
def field(self):
return self.get_fields()
[docs] def set_type(self, ftype):
self._set_attr('type', ftype)
if ftype == 'submit':
fields = self.get_fields()
for var in fields:
field = fields[var]
if field['type'] != 'hidden':
del field['type']
del field['label']
del field['desc']
del field['required']
del field['options']
elif ftype == 'cancel':
del self['fields']
[docs] def add_field(self, var='', ftype=None, label='', desc='',
required=False, value=None, options=None, **kwargs):
kwtype = kwargs.get('type', None)
if kwtype is None:
kwtype = ftype
field = FormField()
field['var'] = var
field['type'] = kwtype
field['value'] = value
if self['type'] in ('form', 'result'):
field['label'] = label
field['desc'] = desc
field['required'] = required
if options is not None:
for option in options:
field.add_option(**option)
else:
if field['type'] != 'hidden':
del field['type']
self.append(field)
return field
[docs] def add_item(self, values):
itemXML = ET.Element('{%s}item' % self.namespace)
self.xml.append(itemXML)
reported_vars = self['reported'].keys()
for var in reported_vars:
field = FormField()
field._type = self['reported'][var]['type']
field['var'] = var
field['value'] = values.get(var, None)
itemXML.append(field.xml)
[docs] def add_reported(self, var, ftype=None, label='', desc='', **kwargs):
kwtype = kwargs.get('type', None)
if kwtype is None:
kwtype = ftype
reported = self.xml.find('{%s}reported' % self.namespace)
if reported is None:
reported = ET.Element('{%s}reported' % self.namespace)
self.xml.append(reported)
fieldXML = ET.Element('{%s}field' % FormField.namespace)
reported.append(fieldXML)
field = FormField(xml=fieldXML)
field['var'] = var
field['type'] = kwtype
field['label'] = label
field['desc'] = desc
return field
[docs] def del_fields(self):
fieldsXML = self.xml.findall('{%s}field' % FormField.namespace)
for fieldXML in fieldsXML:
self.xml.remove(fieldXML)
[docs] def del_instructions(self):
instsXML = self.xml.findall('{%s}instructions')
for instXML in instsXML:
self.xml.remove(instXML)
[docs] def del_items(self):
itemsXML = self.xml.find('{%s}item' % self.namespace)
for itemXML in itemsXML:
self.xml.remove(itemXML)
[docs] def del_reported(self):
reportedXML = self.xml.find('{%s}reported' % self.namespace)
if reportedXML is not None:
self.xml.remove(reportedXML)
[docs] def get_fields(self, use_dict=False):
fields = {}
for stanza in self['substanzas']:
if isinstance(stanza, FormField):
fields[stanza['var']] = stanza
return fields
[docs] def get_instructions(self):
instsXML = self.xml.findall('{%s}instructions' % self.namespace)
return "\n".join([instXML.text for instXML in instsXML])
[docs] def get_items(self):
items = []
itemsXML = self.xml.findall('{%s}item' % self.namespace)
for itemXML in itemsXML:
item = {}
fieldsXML = itemXML.findall('{%s}field' % FormField.namespace)
for fieldXML in fieldsXML:
field = FormField(xml=fieldXML)
item[field['var']] = field['value']
items.append(item)
return items
[docs] def get_reported(self):
fields = {}
xml = self.xml.findall('{%s}reported/{%s}field' % (self.namespace,
FormField.namespace))
for field in xml:
field = FormField(xml=field)
fields[field['var']] = field
return fields
[docs] def get_values(self):
values = {}
fields = self.get_fields()
for var in fields:
values[var] = fields[var]['value']
return values
[docs] def reply(self):
if self['type'] == 'form':
self['type'] = 'submit'
elif self['type'] == 'submit':
self['type'] = 'result'
[docs] def set_fields(self, fields):
del self['fields']
if not isinstance(fields, list):
fields = fields.items()
for var, field in fields:
field['var'] = var
self.add_field(
var=field.get('var'),
label=field.get('label'),
desc=field.get('desc'),
required=field.get('required'),
value=field.get('value'),
options=field.get('options'),
type=field.get('type'))
[docs] def set_instructions(self, instructions):
del self['instructions']
if instructions in [None, '']:
return
if not isinstance(instructions, list):
instructions = instructions.split('\n')
for instruction in instructions:
inst = ET.Element('{%s}instructions' % self.namespace)
inst.text = instruction
self.xml.append(inst)
[docs] def set_reported(self, reported):
"""
This either needs a dictionary of dictionaries or a dictionary of form fields.
:param reported:
:return:
"""
for var in reported:
field = reported[var]
if isinstance(field, dict):
self.add_reported(**field)
else:
reported = self.xml.find('{%s}reported' % self.namespace)
if reported is None:
reported = ET.Element('{%s}reported' % self.namespace)
self.xml.append(reported)
fieldXML = ET.Element('{%s}field' % FormField.namespace)
reported.append(fieldXML)
new_field = FormField(xml=fieldXML)
new_field.values = field.values
[docs] def set_values(self, values):
fields = self.get_fields()
for field in values:
if field not in self.get_fields():
fields[field] = self.add_field(var=field)
self.get_fields()[field]['value'] = values[field]
[docs] def merge(self, other):
new = copy.copy(self)
if type(other) == dict:
new['values'] = other
return new
nfields = new['fields']
ofields = other['fields']
nfields.update(ofields)
new['fields'] = nfields
return new
Form.addField = Form.add_field
Form.addReported = Form.add_reported
Form.delFields = Form.del_fields
Form.delInstructions = Form.del_instructions
Form.delReported = Form.del_reported
Form.getFields = Form.get_fields
Form.getInstructions = Form.get_instructions
Form.getReported = Form.get_reported
Form.getValues = Form.get_values
Form.setFields = Form.set_fields
Form.setInstructions = Form.set_instructions
Form.setReported = Form.set_reported
Form.setValues = Form.set_values