[TransWarp] Component hierarchy traversal

Radek Kanovsky rk at dat.cz
Fri Oct 10 13:35:14 EDT 2003

On Fri, Oct 10, 2003 at 01:13:46PM -0400, Phillip J. Eby wrote:

> >Looking at peak.binding.component:Component.__parentComponent method
> >it seems that bindings with uponAssembly set are evaluated before binding
> >`__parentComponent = Make(__parentComponent, suggestParent=False)' finish.
> That doesn't seem right.  __parentComponent() sets 'd[a]=parent' before 
> calling self.uponAssembly(), so it should know its own parent.  Hmmm.

Sorry for mistake.

> >So my registration routines are invoked before instance config.makeRoot()
> >is set up as parent of my application and lookupComponent(ICommandRoot)
> >fails with exception peak.exceptions.InvalidRoot because my Application
> >instance is supposed to be root at that time.
> That doesn't seem possible, at least if you are creating your app with:
> Application(config.makeRoot(), ...)

Yes, I do.

> Maybe I'm misunderstanding something about how you're doing this.

Binding `cmdBar=registerCommand(bar=cmdBar)' sets uponAssembly=True
and should register cmdBar method in ICommandRoot instance as command bar.
But computeValue fails on `root=binding.lookupComponent(self, ICommandRoot)'.
The code bellow raises exception for me. I have a fresh peak from CVS.

Radek K

from peak.api import binding, adapt, protocols, storage, config
import sys

__all__ = ["ICommandRoot", "CommandRoot", "registerCommand"]

class ICommandRoot (protocols.Interface) :
    """Root component that is able to invoke registered commands."""

    def _registerCommand (comp, cmdname, cmd) :
        """Registers command cmd of component comp upon assembly."""
    def Main (argv) :
        """Main method."""

class registerCommand (binding.Attribute) :
    cmdname = cmd = None

    def __init__ (self, **kw) :
        if len(kw) != 1 :
            raise ValueError("One keyword argument required (name=Command)")
        self.cmdname, self.cmd = kw.items()[0]
        super(registerCommand, self).__init__(uponAssembly=True)
    def computeValue (self, comp, instanceDict, attrName) :
        root = binding.lookupComponent(self, ICommandRoot)
        root._registerCommand(comp, self.cmdname, self.cmd)
        return self.cmd

class CommandRoot (binding.Component) :

        instancesProvide = [ICommandRoot],

    _me = binding.Obtain('.', offerAs=[ICommandRoot], uponAssembly=True)

    _commandRegistry = binding.Make(dict)

    _options = binding.Make(dict)

    _internal_options = {"abort":1, "help":1}

    def _registerCommand (self, comp, cmdname, cmd) :
        fc = cmd.func_code
        opts = fc.co_varnames[1:fc.co_argcount]
        if cmd.func_defaults and len(opts) != len(cmd.func_defaults) :
            raise SyntaxError(
                "Command %s of component %s has positional " \
                "argument without default value" % (cmd, comp))
        for o in opts :
            if o in self._internal_options :
                raise SyntaxError(
                    "Argument %s is for internal purpose (%s of %s)" % (
                    o, cmd, comp))
            self._options[o] = 1
        cr = self._commandRegistry.setdefault(cmdname, {})
        cr[str(binding.getComponentPath(comp))] = (comp, cmd)

    def Usage (self) :
            "%s [OPTIONS] [COMMAND [COMP1 [COMP2 [...]]]]\n"
            "Avalilable commands:\n" % self._argv[0]
        cmds = self._commandRegistry.keys()
        for c in cmds :
            sys.stderr.write("  %s\n" % c)
            "Internal options:\n"
            "  --abort    call abortTransaction at end\n"
            "  --help     prints this help\n"
            "Command options:\n"
        for o in self._options.iterkeys() :
            sys.stderr.write("  --%s=PYTHON_EXPR\n" % o)

    _argv = binding.Make(lambda s,d,a: sys.argv)

    def Main (self) :
        import getopt
        try :
            opts, args = getopt.getopt(self._argv[1:], "",
                                self._internal_options.keys() +
                                ["%s=" % o for o in self._options.iterkeys()]
        except getopt.error, e :
            sys.stderr.write(str(e) + "\n")
            sys.stderr.write("try ``%s --help''\n" % self._argv[0])

        abort = False
        kw = {}
        for o,v in opts :
            if o == "--help" :
            elif o == "--abort" :
                abort = True
            else :
                kw[o[2:]] = eval(v)

        if not args :
            print "Registered commands:"
            for cmd, cr in self._commandRegistry.iteritems() :
                print "Command %r:" % cmd
                for p, comp in cr.iteritems() :
                    print "  ", p, "  ", comp[0]
        command = args[0]
        paths = args[1:]
        if not command in self._commandRegistry :
            sys.stderr.write("Command %s not registered\n" % command)
            sys.stderr.write("try ``%s --help''\n" % self._argv[0])

        if kw.get('verbose') :
            print "+"
            print "+ START TRANSACTION"
        for path, comp_cmd in self._commandRegistry[command].iteritems() :
            if paths and path not in paths :
            comp, cmd = comp_cmd
            fc = cmd.func_code
            opts = fc.co_varnames[1:fc.co_argcount]
            fkw = dict([(k,v) for k,v in kw.iteritems() if k in opts ])
            if kw.get('verbose') :
                print "+"
                print "+ COMMAND %s/%s(%s)" % (
                    path, command, 
                    ",".join([("%s=%s" % (k,v)) for k,v in fkw.iteritems()]))
            cmd(comp, **fkw)

        if abort :
            if kw.get('verbose') :
                print "+"
                print "+ ABORT TRANSACTION"
        else :
            if kw.get('verbose') :
                print "+"
                print "+ COMMIT TRANSACTION"

if __name__ == '__main__' :
    class Foo (binding.Component) :
        def cmdFoo (self, arg1=12) :
            print '%r.cmdFoo(arg1=%r)' % (self, arg1)

        cmdFoo = registerCommand(foo=cmdFoo)

    class Bar (Foo) :
        def cmdBar (self, arg1=12, arg2=42) :
            print '%r.cmdBar(arg1=%r, arg2=%r)' % (self, arg1, arg2)

        cmdBar = registerCommand(bar=cmdBar)

    class Application (CommandRoot) :
        """My application."""

        foo = binding.Make(Foo, uponAssembly=True)
        bar = binding.Make(Bar, uponAssembly=True)


More information about the PEAK mailing list