coding standards

This commit is contained in:
Yann Leboulanger 2009-01-28 07:47:38 +00:00
parent 0b7f2c3fe7
commit 6d9ea872e8
1 changed files with 99 additions and 34 deletions

View File

@ -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):