Returning a value from code string
Kirk McDonald
mooquack at suad.org
Sat Jan 28 04:38:06 EST 2006
Fredrik Lundh wrote:
> executing the code in a custom namespace is a lot cleaner:
>
> ns = {}
> ns["os"] = os # insert "preimported" values
> ns["app"] = app # insert "preloaded" objects
> exec self.code in ns
> try:
> func = ns["std_func_name"]
> except KeyError:
> pass
> else:
> func(**kwargs)
>
> instead of using a standard function, you can let the code
> objects talk to the application via a preloaded object or an
> interface module. e.g. instead of
>
> def std_func_name(app, args):
> app.something()
>
> your code object could simply become
>
> app.something()
>
These code objects should all return an instance of a certain class (or
one of its descendants). In another branch of this topic, I described
roughly what this is for. So, without going into too much detail, I'll
just repeat that this is for a website backend. Whenever an HTML form is
submitted, a hidden "op" element (short for operation) in the form is
checked. This value will send the rest of the form data on to the code
object it represents. (If you've read my other post: These code objects
are nodes, the value for the "op" element is the ID number of one of
them, or possibly one of a few mnemonics for some of the more important
ops.)
So, taking another swipe at it with your suggestions:
def __call__(self, args=None, **kwargs):
ns = {}
ns.update(kwargs)
ns["args"] = args
ns["retval"] = None
exec self.code in ns
try:
func = ns["std_func_name"]
except KeyError:
return ns["retval"]
else:
# Already passed kwargs into the namespace
return func()
Then, a code object can either return a value by using whatever happens
to be in 'retval' when it's done executing, or by defining a
'std_func_name' function and using its return value.
So the interface for these Codenodes needs to be able to accept
arguments as a name/value dictionary corresponding to the elements in
the HTML form (the 'args' argument in my example above). This dictionary
is passed on to the code object. The kwargs are a few important
variables (not supplied by the form) that all Codenodes need to know,
such as the current user and maybe a database cursor.
Each Codenode knows how to deal with the input from its associated form.
(Or forms! There is, for example, a generalized "commit" Codenode that
knows how to update the state of *any* node if a form follows a certain
template.) When it is done, it needs to then return whichever node
should be displayed next. If the operation being attempted violates the
user's permissions, it might return the "access denied" node. (Actually,
in that case it will raise an AccessDenied exception and expect
something down the line to deal with it, so I can define what the
"access denied" node is in a central place, but you get the idea.) If
the operation resulted in a new node being created, it might return the
new node. &c.
Sorry if I tend to ramble, heh. :-)
-Kirk McDonald
More information about the Python-list
mailing list