[twill] Twill/Flunc blocks
Ian Bicking
ianb at colorstudy.com
Fri Oct 19 14:11:48 PDT 2007
Just throwing an idea out for Twill/Flunc (Flunc is our test runner that
uses Twill). Our basic problem: we need some higher-level constructs to
generalize our tests. So what if we add Tcl style strings?
For people who don't know Tcl -- probably most of you -- it has a string
literal syntax that looks very much like a programming structure. But
it's actually just a string literal syntax.
When you do this in Tcl:
proc function_name {args} {
stuff you do, maybe with $args
}
what it actually does is call the function "proc" and pass it the
arguments "function_name", "args", and "\n stuff you do, maybe with
$args\n". Specifically {} is just another way to quote a string -- when
you use that kind of quoting there's no backslash quoting or
substitution (so $args doesn't get substituted), and the {}'s are kept
balanced. Here's what the implementation of proc might look like:
def proc(func_name, args, body):
if isinstance(args, basestring):
args = args.split()
func = ProcFunction(func_name, args, body)
twill.namespaces.get_twill_glocals()[0][func_name] = func
twill.parse.command_list.append(func_name)
class ProcFunction(object):
def __init__(self, name, args, body):
self.name = name
self.args = args
self.body = body
def __repr__(self):
return '<Twill function %s(%s)>' % (
self.name, ', '.join(self.args))
def __call__(self, *args):
ns = twill.namespaces.new_local_dict()
try:
# Javascript style:
ns['arguments'] = args
if len(args) < len(self.args):
args = list(args) + [None]*(len(self.args)-len(args))
for name, value in zip(self.args, args):
ns[name] = value
twill.parse.execute_string(
self.body, source='proc %s' % self.name)
finally:
twill.namespaces.pop_local_dict()
There's no return values here. Not sure what to do about that. Twill
just doesn't have return values generally. Implementing all the
fundamentals of Tcl would not actually be that hard; I think the only
missing piece is being able to do [func args...] in an expression, which
is similar to `command args` in a shell script. That and some notion of
eval in addition to just execute.
Note that I showed function definitions because they seem hardest, but
things like a for loop, try/except, or other higher-level constructs are
entirely possible as well.
A quick look at the twill code doesn't make this look terribly hard, but
I'm not immediately sure how to do this in pyparsing; it's really just a
change to how the line is lexed, but balanced characters for strings is
not something that parsers necessarily make easy -- they all want to get
inside the string and start parsing its innards, which exactly what we
want to avoid here.
--
Ian Bicking : ianb at colorstudy.com : http://blog.ianbicking.org
More information about the twill
mailing list