Declaratively setting Property value in a subclass definition

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Declaratively setting Property value in a subclass definition

Jonathan Blakes
Hi all,

Is if possible to declaratively set the value of Property trait in a
subclass of a HasTraits object *and* trigger the setter for that property?

The example below prints '0' when I would like it to print '10'. You can
see that it uses the getter because it prints 'got here' (post
instantiation), but not the setter (at class definiton, perhaps this is
impossible even with traits metaclass magic!).


# start code

class Test(HasTraits):
     _i = Int
     i = Property(Int)
     def _set_i(self, i):
         self._i = i * 10
     def _get_i(self):
         print 'got here'
         return self._i

class TestSubclass(Test):
     i = 1

t = Test()
print t.i

# end code


# start output

'got here'
0

# end output


I would like to be able to do this because then I can define subclasses
that set some traits which can be then overwritten at instantiation,
rather than repeatedly creating instances with the same values.

My real use case is that I have a List(Instance) trait that I want to be
able to receive a list, a single instance or a list of lists, which
could be defined in a subclass.

I need the setter to be used in order to flatten the list of lists or
wrap the single instance in a list.

Any ideas?

Cheers,

Jon

_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev
Reply | Threaded
Open this post in threaded view
|

Re: Declaratively setting Property value in a subclass definition

Jonathan Blakes
In my previous example:

t = Test()
print t.i

should have been:

t = TestSubclass()
print t.i

but that still returns 1 instead of 10.

The best I can come up with is this:

class Test(HasTraits):
     def _get_i(self):
         return self._i * 10
     def _set_i(self, value):
         self._i = value
     def __init__(self, **traits):
         self.add_trait('i', Property(self._get_i, self._set_i, trait=Int))
         self.i = traits.pop('i', getattr(self, 'i',
getattr(self.__class__, 'i', 0)))

# i not defined in class
#assert Test().i == 0

# i defined in class
class TestSubclass(Test):
     i = 1
print TestSubclass.i
print TestSubclass().i
assert TestSubclass().i == 10

# i not defined and set in init
assert Test(i=2).i == 20

# i defined and set in init
assert TestSubclass(i=2).i == 20

# i defined incorrectly
class TestSubclass2(Test):
     i = 'a'
try:
     test = False
     TestSubclass2()
     test = True
except:
     assert test == False

# i set correctly
t = Test()
t.i = 10
assert t.i == 100

Adding a Property trait to each instance feels wrong.

Strangely it fails if I add either:
     _i = Int
     i = Property(Int)
to class Test

Also I don't understand why I can get away without calling super(Test,
self).__init__(**traits) or HasTraits.__init__(self, **traits)

Jon
_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev