2. XAttribute

class XAttribute( name, [xtype | default_value], [mode])
The XAttribute is used to define an attribute to a class inherited from XObject (see section about XObject for more precisions), there is no interest to use this class directly ... The name is mandatory and must be a non-empty string. The xtype is used to test the values that the attribute should accept. The default_value is used to set the attribute if the user does not. Note that default_value and xtype are optionals but you must give informations to check the type of your attribute. It means that at least one of default_value and xtype or, of course, both must be given. The mode precises if the attribute is readonly ('r') or readwrite ('rw'). This keyword is optional but its default value differs if the XAttribute instance is used in a constructor or to describe an object attributes.

Caution: The particuliar case where default_value is given to be None (a very common case indeed) is special. In that case, we assume that the value None should be accepted even if the xtype given does not accept it. To ensure that, the xtype is modified (for instance, if the xtype was XFloat(), the real xtype will be XMulTypes(XNone(), XFloat()). It is the only case where the developper xtype is modified ...

The following code is the unittest file used in the xdata developpement. It shows the use of XAttribute

# --
# Copyright (C) CEA, EDF
# Author : Erwan ADAM (CEA)
# --

import unittest

from xdata import *

class XAttributeTestCase(unittest.TestCase):
    def test_argslen(self):
        self.failUnlessRaises(XAttributeError, XAttribute, "toto", None)
        x= XAttribute("toto", default_value=None)
        return
    def test_name(self):
        self.failUnlessRaises(XValueError, XAttribute, 2.3, default_value=None)
        self.failUnlessRaises(XValueError, XAttribute, "", default_value=None)
        name = "x"
        x = XAttribute(name, default_value=None)
        self.failUnlessEqual(name, x.name)
        self.failUnlessEqual(name, x.getName())
        return
    def test_noargs(self):
        x = XAttribute("aaa", xtype=XString())
        self.failUnlessEqual(x.hasDefaultValue(), 0)
        self.failUnlessRaises(XValueError, x.getDefaultValue)
        self.failUnlessEqual(x.xtype("toto"), "toto")
        return
    def test_default_value_without_xtype(self):
        default_value = 123
        x = XAttribute("aaa", default_value=default_value)
        self.failUnlessEqual(x.hasDefaultValue(), 1)
        self.failUnlessEqual(x.getDefaultValue(), default_value)
        self.failUnlessEqual(x.xtype("256"), 256)
        self.failUnlessEqual(x.xtype(default_value), default_value)
        self.failUnlessRaises(XValueError, x.xtype, 1.2)
        self.failUnlessRaises(XValueError, x.xtype, "toto")
        #
        x = XAttribute("a", default_value=None)
        self.failUnlessEqual(x.hasDefaultValue(), 1)
        self.failUnlessEqual(x.getDefaultValue(), None)
        #
        return
    def test_xtype(self):
        self.failUnlessRaises(XValueError, XAttribute, "aa", xtype="toto")
        name = "toto"
        x = XAttribute(name, xtype=XFloat(min=0.5))
        self.failUnlessRaises(XValueError, x.xtype, "toto")
        self.failUnlessRaises(XValueError, x.xtype, -2.3)
        return
    def test_default_value_with_types(self):
        # particuliar case when default_value is None
        x = XAttribute("x", default_value=None, xtype=XString())
        self.failUnlessEqual(x.xtype("toto"), "toto")
        self.failUnlessEqual(x.xtype("None"), None)
        # imcompatibility between "toto" and XFloat()
        self.failUnlessRaises(XValueError, XAttribute, "x", default_value="toto", xtype=XFloat())
        return
    pass

if __name__ == '__main__':
    unittest.main()
    pass