coding standards
This commit is contained in:
parent
0b7f2c3fe7
commit
6d9ea872e8
|
@ -21,15 +21,18 @@
|
||||||
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
|
||||||
##
|
##
|
||||||
|
|
||||||
""" This module contains wrappers for different parts of data forms (JEP 0004). For information
|
""" This module contains wrappers for different parts of data forms (JEP 0004).
|
||||||
how to use them, read documentation. """
|
For information how to use them, read documentation. """
|
||||||
|
|
||||||
import xmpp
|
import xmpp
|
||||||
|
|
||||||
# exceptions used in this module
|
# exceptions used in this module
|
||||||
class Error(Exception): pass # base class
|
# base class
|
||||||
class UnknownDataForm(Error): pass # when we get xmpp.Node which we do not understand
|
class Error(Exception): pass
|
||||||
class WrongFieldValue(Error): pass # when we get xmpp.Node which contains bad fields
|
# when we get xmpp.Node which we do not understand
|
||||||
|
class UnknownDataForm(Error): pass
|
||||||
|
# when we get xmpp.Node which contains bad fields
|
||||||
|
class WrongFieldValue(Error): pass
|
||||||
|
|
||||||
# helper class to change class of already existing object
|
# helper class to change class of already existing object
|
||||||
class ExtendedNode(xmpp.Node, object):
|
class ExtendedNode(xmpp.Node, object):
|
||||||
|
@ -56,7 +59,8 @@ def Field(typ, **attrs):
|
||||||
''' Helper function to create a field of given type. '''
|
''' Helper function to create a field of given type. '''
|
||||||
f = {
|
f = {
|
||||||
'boolean': BooleanField,
|
'boolean': BooleanField,
|
||||||
'fixed': TextMultiField, # not editable, still can have multiple lines of text
|
# not editable, still can have multiple lines of text
|
||||||
|
'fixed': TextMultiField,
|
||||||
'hidden': StringField,
|
'hidden': StringField,
|
||||||
'text-private': StringField,
|
'text-private': StringField,
|
||||||
'text-single': StringField,
|
'text-single': StringField,
|
||||||
|
@ -101,33 +105,40 @@ class DataField(ExtendedNode):
|
||||||
""" Keeps data about one field - var, field type, labels, instructions...
|
""" Keeps data about one field - var, field type, labels, instructions...
|
||||||
Base class for different kinds of fields. Use Field() function to
|
Base class for different kinds of fields. Use Field() function to
|
||||||
construct one of these. """
|
construct one of these. """
|
||||||
def __init__(self, typ=None, var=None, value=None, label=None, desc=None, required=False,
|
|
||||||
options=None, extend=None):
|
def __init__(self, typ=None, var=None, value=None, label=None, desc=None,
|
||||||
|
required=False, options=None, extend=None):
|
||||||
|
|
||||||
if extend is None:
|
if extend is None:
|
||||||
ExtendedNode.__init__(self, 'field')
|
ExtendedNode.__init__(self, 'field')
|
||||||
|
|
||||||
self.type = typ
|
self.type = typ
|
||||||
self.var = var
|
self.var = var
|
||||||
if value is not None: self.value = value
|
if value is not None:
|
||||||
if label is not None: self.label = label
|
self.value = value
|
||||||
if desc is not None: self.desc = desc
|
if label is not None:
|
||||||
|
self.label = label
|
||||||
|
if desc is not None:
|
||||||
|
self.desc = desc
|
||||||
self.required = required
|
self.required = required
|
||||||
self.options = options
|
self.options = options
|
||||||
|
|
||||||
@nested_property
|
@nested_property
|
||||||
def type():
|
def type():
|
||||||
'''Type of field. Recognized values are: 'boolean', 'fixed', 'hidden', 'jid-multi',
|
'''Type of field. Recognized values are: 'boolean', 'fixed', 'hidden',
|
||||||
'jid-single', 'list-multi', 'list-single', 'text-multi', 'text-private',
|
'jid-multi', 'jid-single', 'list-multi', 'list-single', 'text-multi',
|
||||||
'text-single'. If you set this to something different, DataField will store
|
'text-private', 'text-single'. If you set this to something different,
|
||||||
given name, but treat all data as text-single.'''
|
DataField will store given name, but treat all data as text-single.'''
|
||||||
def fget(self):
|
def fget(self):
|
||||||
t = self.getAttr('type')
|
t = self.getAttr('type')
|
||||||
if t is None: return 'text-single'
|
if t is None:
|
||||||
|
return 'text-single'
|
||||||
return t
|
return t
|
||||||
|
|
||||||
def fset(self, value):
|
def fset(self, value):
|
||||||
assert isinstance(value, basestring)
|
assert isinstance(value, basestring)
|
||||||
self.setAttr('type', value)
|
self.setAttr('type', value)
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@nested_property
|
@nested_property
|
||||||
|
@ -135,11 +146,14 @@ class DataField(ExtendedNode):
|
||||||
'''Field identifier.'''
|
'''Field identifier.'''
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.getAttr('var')
|
return self.getAttr('var')
|
||||||
|
|
||||||
def fset(self, value):
|
def fset(self, value):
|
||||||
assert isinstance(value, basestring)
|
assert isinstance(value, basestring)
|
||||||
self.setAttr('var', value)
|
self.setAttr('var', value)
|
||||||
|
|
||||||
def fdel(self):
|
def fdel(self):
|
||||||
self.delAttr('var')
|
self.delAttr('var')
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@nested_property
|
@nested_property
|
||||||
|
@ -147,12 +161,15 @@ class DataField(ExtendedNode):
|
||||||
'''Human-readable field name.'''
|
'''Human-readable field name.'''
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.getAttr('label')
|
return self.getAttr('label')
|
||||||
|
|
||||||
def fset(self, value):
|
def fset(self, value):
|
||||||
assert isinstance(value, basestring)
|
assert isinstance(value, basestring)
|
||||||
self.setAttr('label', value)
|
self.setAttr('label', value)
|
||||||
|
|
||||||
def fdel(self):
|
def fdel(self):
|
||||||
if self.getAttr('label'):
|
if self.getAttr('label'):
|
||||||
self.delAttr('label')
|
self.delAttr('label')
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@nested_property
|
@nested_property
|
||||||
|
@ -160,16 +177,19 @@ class DataField(ExtendedNode):
|
||||||
'''Human-readable description of field meaning.'''
|
'''Human-readable description of field meaning.'''
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.getTagData('desc') or u''
|
return self.getTagData('desc') or u''
|
||||||
|
|
||||||
def fset(self, value):
|
def fset(self, value):
|
||||||
assert isinstance(value, basestring)
|
assert isinstance(value, basestring)
|
||||||
if value == '':
|
if value == '':
|
||||||
fdel(self)
|
fdel(self)
|
||||||
else:
|
else:
|
||||||
self.setTagData('desc', value)
|
self.setTagData('desc', value)
|
||||||
|
|
||||||
def fdel(self):
|
def fdel(self):
|
||||||
t = self.getTag('desc')
|
t = self.getTag('desc')
|
||||||
if t is not None:
|
if t is not None:
|
||||||
self.delChild(t)
|
self.delChild(t)
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@nested_property
|
@nested_property
|
||||||
|
@ -177,12 +197,14 @@ class DataField(ExtendedNode):
|
||||||
'''Controls whether this field required to fill. Boolean.'''
|
'''Controls whether this field required to fill. Boolean.'''
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return bool(self.getTag('required'))
|
return bool(self.getTag('required'))
|
||||||
|
|
||||||
def fset(self, value):
|
def fset(self, value):
|
||||||
t = self.getTag('required')
|
t = self.getTag('required')
|
||||||
if t and not value:
|
if t and not value:
|
||||||
self.delChild(t)
|
self.delChild(t)
|
||||||
elif not t and value:
|
elif not t and value:
|
||||||
self.addChild('required')
|
self.addChild('required')
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
class BooleanField(DataField):
|
class BooleanField(DataField):
|
||||||
|
@ -191,16 +213,22 @@ class BooleanField(DataField):
|
||||||
'''Value of field. May contain True, False or None.'''
|
'''Value of field. May contain True, False or None.'''
|
||||||
def fget(self):
|
def fget(self):
|
||||||
v = self.getTagData('value')
|
v = self.getTagData('value')
|
||||||
if v in ('0', 'false'): return False
|
if v in ('0', 'false'):
|
||||||
if v in ('1', 'true'): return True
|
return False
|
||||||
if v is None: return False # default value is False
|
if v in ('1', 'true'):
|
||||||
|
return True
|
||||||
|
if v is None:
|
||||||
|
return False # default value is False
|
||||||
raise WrongFieldValue
|
raise WrongFieldValue
|
||||||
|
|
||||||
def fset(self, value):
|
def fset(self, value):
|
||||||
self.setTagData('value', value and '1' or '0')
|
self.setTagData('value', value and '1' or '0')
|
||||||
|
|
||||||
def fdel(self, value):
|
def fdel(self, value):
|
||||||
t = self.getTag('value')
|
t = self.getTag('value')
|
||||||
if t is not None:
|
if t is not None:
|
||||||
self.delChild(t)
|
self.delChild(t)
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
class StringField(DataField):
|
class StringField(DataField):
|
||||||
|
@ -210,20 +238,23 @@ class StringField(DataField):
|
||||||
'''Value of field. May be any unicode string.'''
|
'''Value of field. May be any unicode string.'''
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.getTagData('value') or u''
|
return self.getTagData('value') or u''
|
||||||
|
|
||||||
def fset(self, value):
|
def fset(self, value):
|
||||||
assert isinstance(value, basestring)
|
assert isinstance(value, basestring)
|
||||||
if value == '':
|
if value == '':
|
||||||
return fdel(self)
|
return fdel(self)
|
||||||
self.setTagData('value', value)
|
self.setTagData('value', value)
|
||||||
|
|
||||||
def fdel(self):
|
def fdel(self):
|
||||||
try:
|
try:
|
||||||
self.delChild(self.getTag('value'))
|
self.delChild(self.getTag('value'))
|
||||||
except ValueError: # if there already were no value tag
|
except ValueError: # if there already were no value tag
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
class ListField(DataField):
|
class ListField(DataField):
|
||||||
''' Covers fields of types: jid-multi, jid-single, list-multi, list-single. '''
|
'''Covers fields of types: jid-multi, jid-single, list-multi, list-single.'''
|
||||||
@nested_property
|
@nested_property
|
||||||
def options():
|
def options():
|
||||||
'''Options.'''
|
'''Options.'''
|
||||||
|
@ -231,22 +262,27 @@ class ListField(DataField):
|
||||||
options = []
|
options = []
|
||||||
for element in self.getTags('option'):
|
for element in self.getTags('option'):
|
||||||
v = element.getTagData('value')
|
v = element.getTagData('value')
|
||||||
if v is None: raise WrongFieldValue
|
if v is None:
|
||||||
|
raise WrongFieldValue
|
||||||
options.append((element.getAttr('label'), v))
|
options.append((element.getAttr('label'), v))
|
||||||
return options
|
return options
|
||||||
|
|
||||||
def fset(self, values):
|
def fset(self, values):
|
||||||
fdel(self)
|
fdel(self)
|
||||||
for value, label in values:
|
for value, label in values:
|
||||||
self.addChild('option', {'label': label}).setTagData('value', value)
|
self.addChild('option', {'label': label}).setTagData('value', value)
|
||||||
|
|
||||||
def fdel(self):
|
def fdel(self):
|
||||||
for element in self.getTags('option'):
|
for element in self.getTags('option'):
|
||||||
self.delChild(element)
|
self.delChild(element)
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
def iter_options(self):
|
def iter_options(self):
|
||||||
for element in self.iterTags('option'):
|
for element in self.iterTags('option'):
|
||||||
v = element.getTagData('value')
|
v = element.getTagData('value')
|
||||||
if v is None: raise WrongFieldValue
|
if v is None:
|
||||||
|
raise WrongFieldValue
|
||||||
l = element.getAttr('label')
|
l = element.getAttr('label')
|
||||||
if not l:
|
if not l:
|
||||||
l = v
|
l = v
|
||||||
|
@ -266,13 +302,16 @@ class ListMultiField(ListField):
|
||||||
for element in self.getTags('value'):
|
for element in self.getTags('value'):
|
||||||
values.append(element.getData())
|
values.append(element.getData())
|
||||||
return values
|
return values
|
||||||
|
|
||||||
def fset(self, values):
|
def fset(self, values):
|
||||||
fdel(self)
|
fdel(self)
|
||||||
for value in values:
|
for value in values:
|
||||||
self.addChild('value').setData(value)
|
self.addChild('value').setData(value)
|
||||||
|
|
||||||
def fdel(self):
|
def fdel(self):
|
||||||
for element in self.getTags('value'):
|
for element in self.getTags('value'):
|
||||||
self.delChild(element)
|
self.delChild(element)
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
def iter_values(self):
|
def iter_values(self):
|
||||||
|
@ -288,14 +327,18 @@ class TextMultiField(DataField):
|
||||||
for element in self.iterTags('value'):
|
for element in self.iterTags('value'):
|
||||||
value += '\n' + element.getData()
|
value += '\n' + element.getData()
|
||||||
return value[1:]
|
return value[1:]
|
||||||
|
|
||||||
def fset(self, value):
|
def fset(self, value):
|
||||||
fdel(self)
|
fdel(self)
|
||||||
if value == '': return
|
if value == '':
|
||||||
|
return
|
||||||
for line in value.split('\n'):
|
for line in value.split('\n'):
|
||||||
self.addChild('value').setData(line)
|
self.addChild('value').setData(line)
|
||||||
|
|
||||||
def fdel(self):
|
def fdel(self):
|
||||||
for element in self.getTags('value'):
|
for element in self.getTags('value'):
|
||||||
self.delChild(element)
|
self.delChild(element)
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
class DataRecord(ExtendedNode):
|
class DataRecord(ExtendedNode):
|
||||||
|
@ -308,7 +351,8 @@ class DataRecord(ExtendedNode):
|
||||||
# we have to build this object from scratch
|
# we have to build this object from scratch
|
||||||
xmpp.Node.__init__(self)
|
xmpp.Node.__init__(self)
|
||||||
|
|
||||||
if fields is not None: self.fields = fields
|
if fields is not None:
|
||||||
|
self.fields = fields
|
||||||
else:
|
else:
|
||||||
# we already have xmpp.Node inside - try to convert all
|
# we already have xmpp.Node inside - try to convert all
|
||||||
# fields into DataField objects
|
# fields into DataField objects
|
||||||
|
@ -327,15 +371,18 @@ class DataRecord(ExtendedNode):
|
||||||
'''List of fields in this record.'''
|
'''List of fields in this record.'''
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.getTags('field')
|
return self.getTags('field')
|
||||||
|
|
||||||
def fset(self, fields):
|
def fset(self, fields):
|
||||||
fdel(self)
|
fdel(self)
|
||||||
for field in fields:
|
for field in fields:
|
||||||
if not isinstance(field, DataField):
|
if not isinstance(field, DataField):
|
||||||
ExtendField(extend=field)
|
ExtendField(extend=field)
|
||||||
self.addChild(node=field)
|
self.addChild(node=field)
|
||||||
|
|
||||||
def fdel(self):
|
def fdel(self):
|
||||||
for element in self.getTags('field'):
|
for element in self.getTags('field'):
|
||||||
self.delChild(element)
|
self.delChild(element)
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
def iter_fields(self):
|
def iter_fields(self):
|
||||||
|
@ -359,9 +406,12 @@ class DataForm(ExtendedNode):
|
||||||
# we have to build form from scratch
|
# we have to build form from scratch
|
||||||
xmpp.Node.__init__(self, 'x', attrs={'xmlns': xmpp.NS_DATA})
|
xmpp.Node.__init__(self, 'x', attrs={'xmlns': xmpp.NS_DATA})
|
||||||
|
|
||||||
if type_ is not None: self.type_=type_
|
if type_ is not None:
|
||||||
if title is not None: self.title=title
|
self.type_=type_
|
||||||
if instructions is not None: self.instructions=instructions
|
if title is not None:
|
||||||
|
self.title=title
|
||||||
|
if instructions is not None:
|
||||||
|
self.instructions=instructions
|
||||||
|
|
||||||
@nested_property
|
@nested_property
|
||||||
def type():
|
def type():
|
||||||
|
@ -370,9 +420,11 @@ class DataForm(ExtendedNode):
|
||||||
filledform = DataForm(replyto=thisform)...'''
|
filledform = DataForm(replyto=thisform)...'''
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.getAttr('type')
|
return self.getAttr('type')
|
||||||
|
|
||||||
def fset(self, type_):
|
def fset(self, type_):
|
||||||
assert type_ in ('form', 'submit', 'cancel', 'result')
|
assert type_ in ('form', 'submit', 'cancel', 'result')
|
||||||
self.setAttr('type', type_)
|
self.setAttr('type', type_)
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@nested_property
|
@nested_property
|
||||||
|
@ -380,13 +432,16 @@ class DataForm(ExtendedNode):
|
||||||
''' Title of the form. Human-readable, should not contain any \\r\\n.'''
|
''' Title of the form. Human-readable, should not contain any \\r\\n.'''
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return self.getTagData('title')
|
return self.getTagData('title')
|
||||||
|
|
||||||
def fset(self, title):
|
def fset(self, title):
|
||||||
self.setTagData('title', title)
|
self.setTagData('title', title)
|
||||||
|
|
||||||
def fdel(self):
|
def fdel(self):
|
||||||
try:
|
try:
|
||||||
self.delChild('title')
|
self.delChild('title')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
@nested_property
|
@nested_property
|
||||||
|
@ -398,19 +453,24 @@ class DataForm(ExtendedNode):
|
||||||
for valuenode in self.getTags('instructions'):
|
for valuenode in self.getTags('instructions'):
|
||||||
value += '\n' + valuenode.getData()
|
value += '\n' + valuenode.getData()
|
||||||
return value[1:]
|
return value[1:]
|
||||||
|
|
||||||
def fset(self, value):
|
def fset(self, value):
|
||||||
fdel(self)
|
fdel(self)
|
||||||
if value == '': return
|
if value == '': return
|
||||||
for line in value.split('\n'):
|
for line in value.split('\n'):
|
||||||
self.addChild('instructions').setData(line)
|
self.addChild('instructions').setData(line)
|
||||||
|
|
||||||
def fdel(self):
|
def fdel(self):
|
||||||
for value in self.getTags('instructions'):
|
for value in self.getTags('instructions'):
|
||||||
self.delChild(value)
|
self.delChild(value)
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
class SimpleDataForm(DataForm, DataRecord):
|
class SimpleDataForm(DataForm, DataRecord):
|
||||||
def __init__(self, type_=None, title=None, instructions=None, fields=None, extend=None):
|
def __init__(self, type_=None, title=None, instructions=None, fields=None, \
|
||||||
DataForm.__init__(self, type_=type_, title=title, instructions=instructions, extend=extend)
|
extend=None):
|
||||||
|
DataForm.__init__(self, type_=type_, title=title,
|
||||||
|
instructions=instructions, extend=extend)
|
||||||
DataRecord.__init__(self, fields=fields, extend=self, associated=self)
|
DataRecord.__init__(self, fields=fields, extend=self, associated=self)
|
||||||
|
|
||||||
def get_purged(self):
|
def get_purged(self):
|
||||||
|
@ -433,12 +493,14 @@ class SimpleDataForm(DataForm, DataRecord):
|
||||||
return c
|
return c
|
||||||
|
|
||||||
class MultipleDataForm(DataForm):
|
class MultipleDataForm(DataForm):
|
||||||
def __init__(self, type_=None, title=None, instructions=None, items=None, extend=None):
|
def __init__(self, type_=None, title=None, instructions=None, items=None,
|
||||||
DataForm.__init__(self, type_=type_, title=title, instructions=instructions, extend=extend)
|
extend=None):
|
||||||
|
DataForm.__init__(self, type_=type_, title=title,
|
||||||
|
instructions=instructions, extend=extend)
|
||||||
# all records, recorded into DataRecords
|
# all records, recorded into DataRecords
|
||||||
if extend is None:
|
if extend is None:
|
||||||
|
if items is not None:
|
||||||
if items is not None: self.items = items
|
self.items = items
|
||||||
else:
|
else:
|
||||||
# we already have xmpp.Node inside - try to convert all
|
# we already have xmpp.Node inside - try to convert all
|
||||||
# fields into DataField objects
|
# fields into DataField objects
|
||||||
|
@ -449,22 +511,25 @@ class MultipleDataForm(DataForm):
|
||||||
self.delChild(item)
|
self.delChild(item)
|
||||||
self.items = items
|
self.items = items
|
||||||
reported_tag = self.getTag('reported')
|
reported_tag = self.getTag('reported')
|
||||||
self.reported = DataRecord(extend = reported_tag)
|
self.reported = DataRecord(extend=reported_tag)
|
||||||
|
|
||||||
@nested_property
|
@nested_property
|
||||||
def items():
|
def items():
|
||||||
''' A list of all records. '''
|
''' A list of all records. '''
|
||||||
def fget(self):
|
def fget(self):
|
||||||
return list(self.iter_records())
|
return list(self.iter_records())
|
||||||
|
|
||||||
def fset(self, records):
|
def fset(self, records):
|
||||||
fdel(self)
|
fdel(self)
|
||||||
for record in records:
|
for record in records:
|
||||||
if not isinstance(record, DataRecord):
|
if not isinstance(record, DataRecord):
|
||||||
DataRecord(extend=record)
|
DataRecord(extend=record)
|
||||||
self.addChild(node=record)
|
self.addChild(node=record)
|
||||||
|
|
||||||
def fdel(self):
|
def fdel(self):
|
||||||
for record in self.getTags('item'):
|
for record in self.getTags('item'):
|
||||||
self.delChild(record)
|
self.delChild(record)
|
||||||
|
|
||||||
return locals()
|
return locals()
|
||||||
|
|
||||||
def iter_records(self):
|
def iter_records(self):
|
||||||
|
|
Loading…
Reference in New Issue