[albatross-users] impedance mismatch 1

Dave Cole djc at object-craft.com.au
Thu Jul 3 21:48:26 EST 2003


> One wrinkle on all this:
> >       * "environ" when inside the template refers to the same dictionary
> >         as "ctx.locals.environ" in the python code.
> 
> ... and if ctx.locals.environ doesn't exist, then it looks for
> environ in the global context of the _page display function_.  So
> you can do something like:
> 
> ----
> my_heading = 'Super Application'
> 
> class StartPage:
> 	# ...
> 	def page_display(self, ctx):
> 		ctx.run_template('start.ht')
> ----
> then, inside start.ht, something like
> 	<h1><al-value expr="my_heading"/></h1>
> and it will work.  
> 
> But the trick is it uses the global namespace of the function that
> calls run_template(). If you use page modules, it has to be in the
> page module.  If you do what I do and have a library with a base
> class for Albatross pages that has a run_template function, then you
> will get the global namespace of the library module, not the
> application, unless you override the page_display in your concrete
> page class.
> 
> (Which is probably as clear as mud....)

That is a pretty clear explanation.  I should see if I can add some
rationale...

One of the cool things about Python expression evaluation is that it
uses two namespaces.  This allows you to do things like this in
Python.

>>> a = 5
>>> def f():
...     b = 4
...     print a * b
...
>>> f()
20

In the function above I was able to use a global variable - quite
useful if you consider that modules appear in the global namespace.
Local variables are useful because...  well just because. :-)

The way Python exposes the local and global namespace to eval() is by
letting you pass two dictionaries to the eval() function.

    >>> print eval.__doc__
    eval(source[, globals[, locals]]) -> value

    Evaluate the source in the context of globals and locals.
    The source may be a string representing a Python expression
    or a code object as returned by compile().
    The globals and locals are dictionaries, defaulting to the current
    globals and locals.  If only globals is given, locals defaults to it.

That is a very powerful feature.

Now back to Albatross.

If you want to build an application from multiple modules, you might
need to access functions or values from a module inside a template
expression.

    <al-if expr="utils.a_func(something)">

If there was only one namespace exposed to template expressions you
would need to do something like this all of the time:

    import utils

    def page_display(ctx):
        ctx.locals.utils = utils
        ctx.run_template('template.html')

That is not so bad but can get quite ugly.

With the current functionality the execution context searches up the
stack frame for the function that called run_template().  It then uses
the globals of that stack frame as the globals in the execution
context for evaluating template expressions.

This means that the execution context will find the global namespace
that contains the imported utils module.  You do not need to explicity
place a reference to the utils module in the local namespace
(ctx.locals).

    import utils        # used in template.html

    def page_display(ctx):
        ctx.run_template('template.html')

- Dave

-- 
http://www.object-craft.com.au




More information about the Albatross-users mailing list