[traits] dynamic metadata update

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

[traits] dynamic metadata update

Satrajit Ghosh
hi,

i'm trying to get a hashing property implemented on my class with the idea that the hash will be calculated whenever any of the attributes change.

i thought i could follow the example in:
http://code.enthought.com/projects/traits/docs/html/traits_user_manual/advanced.html?highlight=depends_on#caching-a-property-value

but can't get it to work. any help/suggestions would be much appreciated.

---------
class MyBaseHasTraits(HasTraits):
     hashval=Property(desc='provides hash value')

     @cached_property
     def _get_hashval(self):
          return 12345

class A(MyBaseHasTraits):
        foo = Str
        bar = Int
----------

i would like to change the depends_on metadata of the Property trait in the base class to include foo and bar. so i tried to use add_trait, but a change in foo or bar doesn't trigger a hash recalc.

-----------
class MyBaseHasTraits(HasTraits):
    def __init__(self, **kwargs):
        super(MyBaseHasTraits, self).__init__(**kwargs)
        self.add_trait('hashval',
                       Property(desc='hash of spec',
                           fget = self._get_hashval,
                           depends_on = [k for k, _ in self.items()]))

    def items(self):
        for name, trait_spec in sorted(self.traits().items()):
            if name in ['trait_added', 'trait_modified', 'hashval']:
                # Skip these trait api functions
                continue
            yield name, trait_spec

     @cached_property
     def _get_hashval(self):
          print "computing hash"
          return 12345
----------

cheers,

satra




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

Re: [traits] dynamic metadata update

bryce hendrix-2
On 3/18/2010 7:20 AM, Satrajit Ghosh wrote:
hi,

i'm trying to get a hashing property implemented on my class with the idea that the hash will be calculated whenever any of the attributes change.

i thought i could follow the example in:
http://code.enthought.com/projects/traits/docs/html/traits_user_manual/advanced.html?highlight=depends_on#caching-a-property-value

but can't get it to work. any help/suggestions would be much appreciated.

---------
class MyBaseHasTraits(HasTraits):
     hashval=Property(desc='provides hash value')

     @cached_property
     def _get_hashval(self):
          return 12345

class A(MyBaseHasTraits):
        foo = Str
        bar = Int
----------

i would like to change the depends_on metadata of the Property trait in the base class to include foo and bar. so i tried to use add_trait, but a change in foo or bar doesn't trigger a hash recalc.

depends_on wants a string, so try depends_on=','.join(k for k in self.trait_names())

I haven't used add_trait with Properties in the same way you're trying to do it, but I think it should work. There is another alternative, which is to declare an event and a trait handler which catches everything:

class MyBaseHasTraits(HasTraits):
    trigger = Event
    hashval = Property(depends_on='trigger')

    @on_trait_change('*')
    def _any_trait_changed(self):
        trigger = True

hope that helps,
Bryce


-----------
class MyBaseHasTraits(HasTraits):
    def __init__(self, **kwargs):
        super(MyBaseHasTraits, self).__init__(**kwargs)
        self.add_trait('hashval',
                       Property(desc='hash of spec',
                           fget = self._get_hashval,
                           depends_on = [k for k, _ in self.items()]))

    def items(self):
        for name, trait_spec in sorted(self.traits().items()):
            if name in ['trait_added', 'trait_modified', 'hashval']:
                # Skip these trait api functions
                continue
            yield name, trait_spec

     @cached_property
     def _get_hashval(self):
          print "computing hash"
          return 12345
----------

cheers,

satra



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


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

Re: [traits] dynamic metadata update

Satrajit Ghosh
hi bryce,

thanks very much.

depends_on wants a string, so try depends_on=','.join(k for k in self.trait_names())

I haven't used add_trait with Properties in the same way you're trying to do it, but I think it should work.

the string option didn't help, but the following did. i was using a dirty flag earlier, but the Event trigger is very nice (i'm very new to traits!)

There is another alternative, which is to declare an event and a trait handler which catches everything:

class MyBaseHasTraits(HasTraits):
    trigger = Event
    hashval = Property(depends_on='trigger')

    @on_trait_change('*')
    def _any_trait_changed(self):
        trigger = True

a variant of this works (traitedspec2 in the gist below). there is a crash happening that i don't understand with on_trait_change. perhaps the crash is more meaningful to you.

http://gist.github.com/336482

cheers,

satra

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

Re: [traits] dynamic metadata update

bryce hendrix-2
Satrajit Ghosh wrote:
hi bryce,

thanks very much.

depends_on wants a string, so try depends_on=','.join(k for k in self.trait_names())

I haven't used add_trait with Properties in the same way you're trying to do it, but I think it should work.

the string option didn't help, but the following did. i was using a dirty flag earlier, but the Event trigger is very nice (i'm very new to traits!)

There is another alternative, which is to declare an event and a trait handler which catches everything:

class MyBaseHasTraits(HasTraits):
    trigger = Event
    hashval = Property(depends_on='trigger')

    @on_trait_change('*')
    def _any_trait_changed(self):
        trigger = True

a variant of this works (traitedspec2 in the gist below). there is a crash happening that i don't understand with on_trait_change. perhaps the crash is more meaningful to you.

I should have checked the docs before answering you, the on_trait_change decorator should be "@on_trait_change('+')" instead. Hopefully that solves the issue. Your use of _anytrait_changed is fine too (actually better is several ways).

Bryce

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