[TransWarp] Component hierarchy traversal

Phillip J. Eby pje at telecommunity.com
Wed Oct 1 12:05:28 EDT 2003


At 05:48 PM 10/1/03 +0200, Radek Kanovsky wrote:
>Hi,
>
>I have started to implement traverseComponents(comp) generator, that
>traverses given component hierarchy and return one component-path pair
>in one iteration. Traversal order is not important. There are some
>components dispersed in hierarchy that implements some interface. I need
>to find them and call its methods. But I am not sure if my solution is
>correct or if it is ever possible doing it such way. My first prototype
>is here:
>
>     def traverseComponents (comp, reg=None) :
>         if reg is None :
>             reg = {}
>         yield (comp, binding.getComponentPath(comp))
>         reg[comp] = 1
>         for a,d in comp.__class__.__all_descriptors__.items() :
>             if not isinstance(d, binding.Attribute) :
>                 continue

Did you find that you needed the isinstance() check in practice?  I'm just 
curious.


>             i = comp._getBinding(a)

And why access the attribute in the dictionary, instead of using 'getattr()'?


>Another solution that i have tried was global registry of such
>components.

This is probably a more scalable approach.


>Every interfaces.IResourceComponent class has attribute
>that is computed upon assembly. Side effect of this computation is that
>instances register itself in global registry. Then I have all such
>components in registry and I have no need for traversal function. But
>some bindings don't have uponAssembly flag set and I don't know how to
>force assembling from given root. root.uponAssembly() works only if
>whole hierarchy is binded with uponAssembly flag.

Right.  To be precise, all the parents above the items to be registered, 
must be assembled.  That's not quite the whole hierarchy, unless every 
object in the system needs to be registered.



>Is there some pattern how to solve this?

If you know the paths of the objects in advance, you can use something like:

     allMyObjects = binding.Obtain(
         ['path/to/item1', 'path/to/item2', .... ], uponAssembly=True
     )

in some object that needs the list; the 'allMyObjects' attribute will then 
equal a tuple of the listed objects.

Could you explain your application a little?  It may be that there are 
additional ways to accomplish what you need.




More information about the PEAK mailing list