Skip to content

Commit 0eeffa9

Browse files
committed
Merged XEP-0004.Multiple.Items.Form.Results patch. Thanks to Iván Lloro
1 parent 81b671f commit 0eeffa9

File tree

1 file changed

+107
-3
lines changed

1 file changed

+107
-3
lines changed

xmpp/protocol.py

+107-3
Original file line numberDiff line numberDiff line change
@@ -668,14 +668,114 @@ def setVar(self,val):
668668
""" Set 'var' attribute value of this field. """
669669
return self.setAttr('var',val)
670670

671+
class DataReported(Node):
672+
""" This class is used in the DataForm class to describe the 'reported data field' data items which are used in
673+
'multiple item form results' (as described in XEP-0004).
674+
Represents the fields that will be returned from a search. This information is useful when
675+
you try to use the jabber:iq:search namespace to return dynamic form information.
676+
"""
677+
def __init__(self,node=None):
678+
""" Create new empty 'reported data' field. However, note that, according XEP-0004:
679+
* It MUST contain one or more DataFields.
680+
* Contained DataFields SHOULD possess a 'type' and 'label' attribute in addition to 'var' attribute
681+
* Contained DataFields SHOULD NOT contain a <value/> element.
682+
Alternatively other XML object can be passed in as the 'node' parameted to replicate it as a new
683+
dataitem.
684+
"""
685+
Node.__init__(self,'reported',node=node)
686+
if node:
687+
newkids=[]
688+
for n in self.getChildren():
689+
if n.getName()=='field': newkids.append(DataField(node=n))
690+
else: newkids.append(n)
691+
self.kids=newkids
692+
def getField(self,name):
693+
""" Return the datafield object with name 'name' (if exists). """
694+
return self.getTag('field',attrs={'var':name})
695+
def setField(self,name,typ=None,label=None):
696+
""" Create if nessessary or get the existing datafield object with name 'name' and return it.
697+
If created, attributes 'type' and 'label' are applied to new datafield."""
698+
f=self.getField(name)
699+
if f: return f
700+
return self.addChild(node=DataField(name,None,typ,0,label))
701+
def asDict(self):
702+
""" Represent dataitem as simple dictionary mapping of datafield names to their values."""
703+
ret={}
704+
for field in self.getTags('field'):
705+
name=field.getAttr('var')
706+
typ=field.getType()
707+
if isinstance(typ,(str,unicode)) and typ[-6:]=='-multi':
708+
val=[]
709+
for i in field.getTags('value'): val.append(i.getData())
710+
else: val=field.getTagData('value')
711+
ret[name]=val
712+
if self.getTag('instructions'): ret['instructions']=self.getInstructions()
713+
return ret
714+
def __getitem__(self,name):
715+
""" Simple dictionary interface for getting datafields values by their names."""
716+
item=self.getField(name)
717+
if item: return item.getValue()
718+
raise IndexError('No such field')
719+
def __setitem__(self,name,val):
720+
""" Simple dictionary interface for setting datafields values by their names."""
721+
return self.setField(name).setValue(val)
722+
723+
class DataItem(Node):
724+
""" This class is used in the DataForm class to describe data items which are used in 'multiple
725+
item form results' (as described in XEP-0004).
726+
"""
727+
def __init__(self,node=None):
728+
""" Create new empty data item. However, note that, according XEP-0004, DataItem MUST contain ALL
729+
DataFields described in DataReported.
730+
Alternatively other XML object can be passed in as the 'node' parameted to replicate it as a new
731+
dataitem.
732+
"""
733+
Node.__init__(self,'item',node=node)
734+
if node:
735+
newkids=[]
736+
for n in self.getChildren():
737+
if n.getName()=='field': newkids.append(DataField(node=n))
738+
else: newkids.append(n)
739+
self.kids=newkids
740+
def getField(self,name):
741+
""" Return the datafield object with name 'name' (if exists). """
742+
return self.getTag('field',attrs={'var':name})
743+
def setField(self,name):
744+
""" Create if nessessary or get the existing datafield object with name 'name' and return it. """
745+
f=self.getField(name)
746+
if f: return f
747+
return self.addChild(node=DataField(name))
748+
def asDict(self):
749+
""" Represent dataitem as simple dictionary mapping of datafield names to their values."""
750+
ret={}
751+
for field in self.getTags('field'):
752+
name=field.getAttr('var')
753+
typ=field.getType()
754+
if isinstance(typ,(str,unicode)) and typ[-6:]=='-multi':
755+
val=[]
756+
for i in field.getTags('value'): val.append(i.getData())
757+
else: val=field.getTagData('value')
758+
ret[name]=val
759+
if self.getTag('instructions'): ret['instructions']=self.getInstructions()
760+
return ret
761+
def __getitem__(self,name):
762+
""" Simple dictionary interface for getting datafields values by their names."""
763+
item=self.getField(name)
764+
if item: return item.getValue()
765+
raise IndexError('No such field')
766+
def __setitem__(self,name,val):
767+
""" Simple dictionary interface for setting datafields values by their names."""
768+
return self.setField(name).setValue(val)
769+
671770
class DataForm(Node):
672771
""" DataForm class. Used for manipulating dataforms in XMPP.
673772
Relevant XEPs: 0004, 0068, 0122.
674773
Can be used in disco, pub-sub and many other applications."""
675774
def __init__(self, typ=None, data=[], title=None, node=None):
676775
"""
677-
Create new dataform of type 'typ'. 'data' is the list of DataField
678-
instances that this dataform contains, 'title' - the title string.
776+
Create new dataform of type 'typ'; 'data' is the list of DataReported,
777+
DataItem and DataField instances that this dataform contains; 'title'
778+
is the title string.
679779
You can specify the 'node' argument as the other node to be used as
680780
base for constructing this dataform.
681781
@@ -690,7 +790,9 @@ def __init__(self, typ=None, data=[], title=None, node=None):
690790
if node:
691791
newkids=[]
692792
for n in self.getChildren():
693-
if n.getName()=='field': newkids.append(DataField(node=n))
793+
if n.getName()=='field': newkids.append(DataField(node=n))
794+
elif n.getName()=='item': newkids.append(DataItem(node=n))
795+
elif n.getName()=='reported': newkids.append(DataReported(node=n))
694796
else: newkids.append(n)
695797
self.kids=newkids
696798
if typ: self.setType(typ)
@@ -703,6 +805,8 @@ def __init__(self, typ=None, data=[], title=None, node=None):
703805
for child in data:
704806
if type(child) in [type(''),type(u'')]: self.addInstructions(child)
705807
elif child.__class__.__name__=='DataField': self.kids.append(child)
808+
elif child.__class__.__name__=='DataItem': self.kids.append(child)
809+
elif child.__class__.__name__=='DataReported': self.kids.append(child)
706810
else: self.kids.append(DataField(node=child))
707811
def getType(self):
708812
""" Return the type of dataform. """

0 commit comments

Comments
 (0)