[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) :
protocols.advise(
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) :
sys.stderr.write(
"%s [OPTIONS] [COMMAND [COMP1 [COMP2 [...]]]]\n"
"\n"
"Avalilable commands:\n" % self._argv[0]
)
cmds = self._commandRegistry.keys()
cmds.sort()
for c in cmds :
sys.stderr.write(" %s\n" % c)
sys.stderr.write(
"\n"
"Internal options:\n"
" --abort call abortTransaction at end\n"
" --help prints this help\n"
"\n"
"Command options:\n"
)
for o in self._options.iterkeys() :
sys.stderr.write(" --%s=PYTHON_EXPR\n" % o)
sys.stderr.write("\n")
sys.exit(0)
_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])
sys.exit(1)
abort = False
kw = {}
for o,v in opts :
if o == "--help" :
self.Usage()
elif o == "--abort" :
abort = True
else :
kw[o[2:]] = eval(v)
if not args :
print "Registered commands:"
print
for cmd, cr in self._commandRegistry.iteritems() :
print "Command %r:" % cmd
for p, comp in cr.iteritems() :
print " ", p, " ", comp[0]
print
sys.exit(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])
sys.exit(1)
if kw.get('verbose') :
print "+"
print "+ START TRANSACTION"
storage.begin(self)
for path, comp_cmd in self._commandRegistry[command].iteritems() :
if paths and path not in paths :
continue
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"
storage.abort(self)
else :
if kw.get('verbose') :
print "+"
print "+ COMMIT TRANSACTION"
storage.commit(self)
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)
Application(config.makeRoot()).Main()
More information about the PEAK
mailing list