Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mako Template Variable Names

Is it it possible to get the names of the variables in a Mako Template before rendering?

from mako.template import Template
bar = Template("${foo}")

# something like:
# >> print bar.fields()
# ['foo']

Use case:

We have configuration files whereby we specify the metadata from the database to be displayed on a webpage. The client can pick one of a few hundred different pieces of named metadata. There are N slots the client can configure but we don't know in advance which pieces of metadata a particular client would like to have filled in on the form. Because if this when rendering the form we need to know, in advance, what variable names we need to pass for this clients template.

We had thought of having a consistent dictionary with all possible values and passing that in each time but it was unworkable as new available fields are added frequently to the underlying pool of available metadata the client could pick.

Because of this we had hoped to use Mako to template the config files but I can't figure out how to determine with the field values in the template would be so that I can build a full-formed Context to pass to the template.

like image 283
lycovian Avatar asked Oct 20 '22 08:10

lycovian


1 Answers

Unfortunately there is no easy way to get the names of the variables from a template object.

Fortunately there is the mako.codegen._Identifiers class and the sole purpose of its objects is to keep track of the variables during the compilation process.

Unfortunately it is buried deep beneath the Mako API surface, and it is gone after the compilation is done.

Fortunately you can get it without setting up everything Mako sets up when it compiles templates. All you need is the parse tree that you can get by using mako.lexer.Lexer.

Anyway here is the code:

from mako import lexer, codegen


lexer = lexer.Lexer("${foo}", '')
node = lexer.parse()
# ^ The node is the root element for the parse tree.
# The tree contains all the data from a template
# needed for the code generation process

# Dummy compiler. _Identifiers class requires one
# but only interested in the reserved_names field
compiler = lambda: None         
compiler.reserved_names = set() 

identifiers = codegen._Identifiers(compiler, node)
# All template variables can be found found using this
# object but you are probably interested in the
# undeclared variables:
# >>> print identifiers.undeclared
# set(['foo'])
like image 97
Igonato Avatar answered Oct 23 '22 10:10

Igonato