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