Thanks!
Dan Lepage
First, you need to realize that a NameError, or any python exception,
could have been raised from either a Mako-compiled template, or
from any other regular python function or module called by that template.
So the error may or may not have occurred "in" the template itself.
However you may be able to extract where in the template you
were at by examining the python traceback. You should look at
the "mako.exceptions.RichTraceback" class, as it contains useful
functions for parsing the exception traceback and mapping those
to the original template source code, if possible.
See http://www.makotemplates.org/docs/usage.html#usage_handling
--
Deron Meranda
On Mar 29, 2:04 pm, Deron Meranda <deron.mera...@gmail.com> wrote:
> On Mon, Mar 29, 2010 at 1:44 PM, dplepage <dplep...@gmail.com> wrote:
> > Hey everyone,
> > Maybe I'm just missing this in the documentation, but if I write a
> > template and get "NameError: Undefined" when I render it, is there an
> > easy way to figure out which variable was undefined and where in the
> > template it occurs?
>
> First, you need to realize that a NameError, or any python exception,
> could have been raised from either a Mako-compiled template, or
> from any other regular python function or module called by that template.
> So the error may or may not have occurred "in" the template itself.
I'm aware that NameErrors can be raised elsewhere; in many cases,
however, I know that they're happening within the template, and
regardless it would be helpful to know for sure which name caused the
error.
> However you may be able to extract where in the template you
> were at by examining the python traceback. You should look at
> the "mako.exceptions.RichTraceback" class, as it contains useful
> functions for parsing the exception traceback and mapping those
> to the original template source code, if possible.
>
> Seehttp://www.makotemplates.org/docs/usage.html#usage_handling
That's helpful, thanks! Does this mean, though, that there's no way
after the fact to figure out programmatically which name caused the
problem? In an ideal world, I'd like an error message such as:
NameError: "x" is Undefined
Is there any way to get this information, or was it lost when x became
Undefined because Undefined is a singleton?
Thanks,
Dan Lepage
If Python raises the NameError, then the message will have
the name of the variable. Try this:
try:
someunknownvariable == 1
except NameError, err: # or ... as err in Python 3
print repr( err.args )
It however appears that the NameError you're seeing was
explicitly raised by Mako and not by Python. In the file
mako/runtime.py there is this class:
class Undefined(object):
"""represents an undefined value in a template."""
def __str__(self):
raise NameError("Undefined")
def __nonzero__(self):
return False
That is where Mako's special "UNDEFINED" value comes from,
which is what you get if in a template you have, say:
${ someunknownvariable }
Basically Mako is just not passing the original name through
to the undefined object. In order for that to happen, it would
could no longer be a singleton. We'll have to let Michael
respond as to whether that might or might not be a reasonable
thing to do.
However, you may want to read up in the documentation
for more insight:
http://www.makotemplates.org/docs/runtime.html#runtime_context_variables
--
Deron Meranda
that's the reason we don't load UNDEFINED with the name, yup. so that
you can say "x is UNDEFINED". i don't see a way to get both worlds
unless we intercepted the "is" operator in code.
I suspect that wouldn't be that hard to do (since it's a reserved
word, any substring matching (?=\W)is(?<=\W) must be the "is"
operator), but I can imagine that there would be a lot of ugly corner
cases and it probably wouldn't be worth the effort.
Just out of curiosity, why did you choose a singleton for UNDEFINED?
Was it just for the "is", or are there other benefits? I wouldn't mind
typing "x == UNDEFINED" instead of "x is UNDEFINED" if it made
debugging templates easier. Or maybe I'm the only one who ever has
this problem :-)
Thanks,
Dan Lepage
it was for the "is" and no you're not the only person to have this problem. we'd have to hard shift it on people and tell them to change all "x is UNDEFINED" into something awkward like "UNDEFINED.is(x)". its not trivial to find the "is" via a plain regexp since these are full blocks of Python code. We do some AST parsing though only on small expressions, not whole blocks of Python which would also have to be accounted for.
the one idea that could make the shift more palatable is to have the generation of UNDEFINED vs. UNDEFINED('x') be based on a template/lookup configurational flag. Wouldn't be very hard to do.