Search code examples
pythonenthoughttraitstraitsui

Inspect for synchronized traits: Traits/TraitsUI


I'm sweeping through all the Traits in a large program, and many of our traits are synchronized. For example, consider HasTrait objects of the structure:

a = Material1.ShellMaterial
b = Material2.CoreMaterial
c = Material3.MaterialX

In our application, it turns out that a and c are synchronized traits. In other words, Material3.MaterialX is the same as Material1.ShellMaterial, and they have set using sync_trait() (HasTraits API).

Is it possible to inspect a,b,c and dynamically determine that a and c are synchronized?

The goal is to plot all of these, but hide redundant plots from the user. Typical comparisons between these like a==c return False, despite these objects representing the same data.


Solution

  • As far as I know there is no official API that allows to inspect the synchronization state of traits.

    Of course, you could simply call the sync_trait() method again to make sure that the traits are synchronized (or not synchronized, if you use remove=True). As a result, you will know the synchronization state of the traits.

    If you do not want to change the synchronization state, you have to rely on non-official API functions, which are not documented and possibly subject to change -- so use them at your own risk.

    from traits.api import HasTraits, Float
    class AA(HasTraits):
        a =Float()
    class BB(HasTraits):
        b = Float()
    aa = AA()
    bb = BB()
    aa.sync_trait("a", bb, "b")
    
    # aa.a and bb.b are synchronized
    # Now we use non-official API functions
    info = aa._get_sync_trait_info()
    
    synced = info.has_key("a") # True if aa.a is synchronized to some other trait
    if synced:
        sync_info = info["a"] # fails if a is not a synchronized trait
        # sync_info is a dictionary which maps (id(bb),"b") to a tuple (wr, "b")
        # If you do not know the id() of the HasTraits-object and the name of
        # the trait, you have to loop through all elements of sync_info and
        # search for the entry you want...
        wr, name = sync_info[(id(bb), "b")]
        # wr is a weakref to the class of bb, and name is the name 
        # of the trait which aa.a is synced to
        cls = wr() # <__main__.BB at 0x6923a98>
    

    Again, use at your own risk, but it works for me.