Merge branch 'refactor_forms' into add_xep_0122
This commit is contained in:
commit
7059400020
@ -9,7 +9,7 @@
|
|||||||
import copy
|
import copy
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from sleekxmpp.thirdparty import OrderedDict
|
from sleekxmpp.thirdparty import OrderedDict, OrderedSet
|
||||||
|
|
||||||
from sleekxmpp.xmlstream import ElementBase, ET
|
from sleekxmpp.xmlstream import ElementBase, ET
|
||||||
from sleekxmpp.plugins.xep_0004.stanza import FormField
|
from sleekxmpp.plugins.xep_0004.stanza import FormField
|
||||||
@ -22,7 +22,7 @@ class Form(ElementBase):
|
|||||||
namespace = 'jabber:x:data'
|
namespace = 'jabber:x:data'
|
||||||
name = 'x'
|
name = 'x'
|
||||||
plugin_attrib = 'form'
|
plugin_attrib = 'form'
|
||||||
interfaces = set(('instructions', 'items', 'reported', 'title', 'type', ))
|
interfaces = OrderedSet(('instructions', 'reported', 'title', 'type', 'items', ))
|
||||||
sub_interfaces = set(('title',))
|
sub_interfaces = set(('title',))
|
||||||
form_types = set(('cancel', 'form', 'result', 'submit'))
|
form_types = set(('cancel', 'form', 'result', 'submit'))
|
||||||
|
|
||||||
@ -169,7 +169,7 @@ class Form(ElementBase):
|
|||||||
def get_reported(self):
|
def get_reported(self):
|
||||||
fields = OrderedDict()
|
fields = OrderedDict()
|
||||||
xml = self.xml.findall('{%s}reported/{%s}field' % (self.namespace,
|
xml = self.xml.findall('{%s}reported/{%s}field' % (self.namespace,
|
||||||
FormField.namespace))
|
FormField.namespace))
|
||||||
for field in xml:
|
for field in xml:
|
||||||
field = FormField(xml=field)
|
field = FormField(xml=field)
|
||||||
fields[field['var']] = field
|
fields[field['var']] = field
|
||||||
@ -219,10 +219,26 @@ class Form(ElementBase):
|
|||||||
self.add_item(item)
|
self.add_item(item)
|
||||||
|
|
||||||
def set_reported(self, reported):
|
def set_reported(self, reported):
|
||||||
|
"""
|
||||||
|
This either needs a dictionary or dictionaries or a dictionary of form fields.
|
||||||
|
:param reported:
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
for var in reported:
|
for var in reported:
|
||||||
field = reported[var]
|
field = reported[var]
|
||||||
field['var'] = var
|
|
||||||
self.add_reported(var, **field)
|
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
|
||||||
|
|
||||||
def set_values(self, values):
|
def set_values(self, values):
|
||||||
fields = self.get_fields()
|
fields = self.get_fields()
|
||||||
|
1
sleekxmpp/thirdparty/__init__.py
vendored
1
sleekxmpp/thirdparty/__init__.py
vendored
@ -10,3 +10,4 @@ except:
|
|||||||
|
|
||||||
from sleekxmpp.thirdparty import socks
|
from sleekxmpp.thirdparty import socks
|
||||||
from sleekxmpp.thirdparty.mini_dateutil import tzutc, tzoffset, parse_iso
|
from sleekxmpp.thirdparty.mini_dateutil import tzutc, tzoffset, parse_iso
|
||||||
|
from sleekxmpp.thirdparty.orderedset import OrderedSet
|
||||||
|
89
sleekxmpp/thirdparty/orderedset.py
vendored
Normal file
89
sleekxmpp/thirdparty/orderedset.py
vendored
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
# Copyright (c) 2009 Raymond Hettinger
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person
|
||||||
|
# obtaining a copy of this software and associated documentation files
|
||||||
|
# (the "Software"), to deal in the Software without restriction,
|
||||||
|
# including without limitation the rights to use, copy, modify, merge,
|
||||||
|
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
# and to permit persons to whom the Software is furnished to do so,
|
||||||
|
# subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be
|
||||||
|
# included in all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||||
|
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
||||||
|
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||||
|
# OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
import collections
|
||||||
|
|
||||||
|
class OrderedSet(collections.MutableSet):
|
||||||
|
|
||||||
|
def __init__(self, iterable=None):
|
||||||
|
self.end = end = []
|
||||||
|
end += [None, end, end] # sentinel node for doubly linked list
|
||||||
|
self.map = {} # key --> [key, prev, next]
|
||||||
|
if iterable is not None:
|
||||||
|
self |= iterable
|
||||||
|
|
||||||
|
def __len__(self):
|
||||||
|
return len(self.map)
|
||||||
|
|
||||||
|
def __contains__(self, key):
|
||||||
|
return key in self.map
|
||||||
|
|
||||||
|
def add(self, key):
|
||||||
|
if key not in self.map:
|
||||||
|
end = self.end
|
||||||
|
curr = end[1]
|
||||||
|
curr[2] = end[1] = self.map[key] = [key, curr, end]
|
||||||
|
|
||||||
|
def discard(self, key):
|
||||||
|
if key in self.map:
|
||||||
|
key, prev, next = self.map.pop(key)
|
||||||
|
prev[2] = next
|
||||||
|
next[1] = prev
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
end = self.end
|
||||||
|
curr = end[2]
|
||||||
|
while curr is not end:
|
||||||
|
yield curr[0]
|
||||||
|
curr = curr[2]
|
||||||
|
|
||||||
|
def __reversed__(self):
|
||||||
|
end = self.end
|
||||||
|
curr = end[1]
|
||||||
|
while curr is not end:
|
||||||
|
yield curr[0]
|
||||||
|
curr = curr[1]
|
||||||
|
|
||||||
|
def pop(self, last=True):
|
||||||
|
if not self:
|
||||||
|
raise KeyError('set is empty')
|
||||||
|
key = self.end[1][0] if last else self.end[2][0]
|
||||||
|
self.discard(key)
|
||||||
|
return key
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if not self:
|
||||||
|
return '%s()' % (self.__class__.__name__,)
|
||||||
|
return '%s(%r)' % (self.__class__.__name__, list(self))
|
||||||
|
|
||||||
|
def __eq__(self, other):
|
||||||
|
if isinstance(other, OrderedSet):
|
||||||
|
return len(self) == len(other) and list(self) == list(other)
|
||||||
|
return set(self) == set(other)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
s = OrderedSet('abracadaba')
|
||||||
|
t = OrderedSet('simsalabim')
|
||||||
|
print(s | t)
|
||||||
|
print(s & t)
|
||||||
|
print(s - t)
|
@ -563,7 +563,7 @@ class ElementBase(object):
|
|||||||
|
|
||||||
.. versionadded:: 1.0-Beta1
|
.. versionadded:: 1.0-Beta1
|
||||||
"""
|
"""
|
||||||
values = {}
|
values = OrderedDict()
|
||||||
values['lang'] = self['lang']
|
values['lang'] = self['lang']
|
||||||
for interface in self.interfaces:
|
for interface in self.interfaces:
|
||||||
if isinstance(self[interface], JID):
|
if isinstance(self[interface], JID):
|
||||||
|
@ -197,5 +197,52 @@ class TestDataForms(SleekTest):
|
|||||||
<x xmlns="jabber:x:data" type="cancel" />
|
<x xmlns="jabber:x:data" type="cancel" />
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
def testReported(self):
|
||||||
|
msg = self.Message()
|
||||||
|
form = msg['form']
|
||||||
|
form['type'] = 'result'
|
||||||
|
|
||||||
|
form.add_reported(var='f1', ftype='text-single', label='Username')
|
||||||
|
|
||||||
|
form.add_item({'f1': 'username@example.org'})
|
||||||
|
|
||||||
|
self.check(msg, """
|
||||||
|
<message>
|
||||||
|
<x xmlns="jabber:x:data" type="result">
|
||||||
|
<reported>
|
||||||
|
<field var="f1" type="text-single" label="Username" />
|
||||||
|
</reported>
|
||||||
|
<item>
|
||||||
|
<field var="f1">
|
||||||
|
<value>username@example.org</value>
|
||||||
|
</field>
|
||||||
|
</item>
|
||||||
|
</x>
|
||||||
|
</message>
|
||||||
|
""")
|
||||||
|
|
||||||
|
def testSetReported(self):
|
||||||
|
msg = self.Message()
|
||||||
|
form = msg['form']
|
||||||
|
form['type'] = 'result'
|
||||||
|
|
||||||
|
reported = {'f1': {
|
||||||
|
'var': 'f1',
|
||||||
|
'type': 'text-single',
|
||||||
|
'label': 'Username'
|
||||||
|
}}
|
||||||
|
|
||||||
|
form.set_reported(reported)
|
||||||
|
|
||||||
|
self.check(msg, """
|
||||||
|
<message>
|
||||||
|
<x xmlns="jabber:x:data" type="result">
|
||||||
|
<reported>
|
||||||
|
<field var="f1" type="text-single" label="Username" />
|
||||||
|
</reported>
|
||||||
|
</x>
|
||||||
|
</message>
|
||||||
|
""")
|
||||||
|
|
||||||
|
|
||||||
suite = unittest.TestLoader().loadTestsFromTestCase(TestDataForms)
|
suite = unittest.TestLoader().loadTestsFromTestCase(TestDataForms)
|
||||||
|
Loading…
Reference in New Issue
Block a user