Mako 0.4.1 Documentation

Version: 0.4.1 Last Updated: 04/06/2011 19:09:35
Index

The Mako Runtime Environment

This section describes a little bit about the objects and built-in functions that are available in templates.

Context

The Context is the central object that is created when a template is first executed, and is responsible for handling all communication with the outside world. This includes two major components, one of which is the output buffer, which is a file-like object such as Python’s StringIO or similar, and the other a dictionary of variables that can be freely referenced within a template; this dictionary is a combination of the arguments sent to the render() function and some built-in variables provided by Mako’s runtime environment.

The Buffer

The buffer is stored within the Context, and writing to it is achieved by calling Context.write(). You usually don’t need to care about this as all text within a template, as well as all expressions provided by ${}, automatically send everything to this method. The cases you might want to be aware of its existence are if you are dealing with various filtering/buffering scenarios, which are described in Filtering and Buffering, or if you want to programmatically send content to the output stream, such as within a <% %> block.

<%
    context.write("some programmatic text")
%>

The actual buffer may or may not be the original buffer sent to the Context object, as various filtering/caching scenarios may “push” a new buffer onto the context’s underlying buffer stack. For this reason, just stick with Context.write() and content will always go to the topmost buffer.

Context Variables

When your template is compiled into a Python module, the body content is enclosed within a Python function called render_body. Other top-level defs defined in the template are defined within their own function bodies which are named after the def’s name with the prefix render_ (i.e. render_mydef). One of the first things that happens within these functions is that all variable names that are referenced within the function which are not defined in some other way (i.e. such as via assignment, module level imports, etc.) are pulled from the Context object’s dictionary of variables. This is how you’re able to freely reference variable names in a template which automatically correspond to what was passed into the current Context.

  • What happens if I reference a variable name that is not in the current context? - the value you get back is a special value called UNDEFINED, or if the strict_undefined=True flag is used a NameError is raised. UNDEFINED is just a simple global variable with the class mako.runtime.Undefined. The UNDEFINED object throws an error when you call str() on it, which is what happens if you try to use it in an expression.
  • UNDEFINED makes it hard for me to find what name is missing - An alternative introduced in version 0.3.6 is to specify the option strict_undefined=True to the Template or TemplateLookup. This will cause any non-present variables to raise an immediate NameError which includes the name of the variable in its message when render() is called - UNDEFINED is not used.
  • Why not just return None? Using UNDEFINED, or raising a NameError is more explicit and allows differentiation between a value of None that was explicitly passed to the Context and a value that wasn’t present at all.
  • Why raise an exception when you call str() on it ? Why not just return a blank string? - Mako tries to stick to the Python philosophy of “explicit is better than implicit”. In this case, its decided that the template author should be made to specifically handle a missing value rather than experiencing what may be a silent failure. Since UNDEFINED is a singleton object just like Python’s True or False, you can use the is operator to check for it:
% if someval is UNDEFINED:
    someval is: no value
% else:
    someval is: ${someval}
% endif

Another facet of the Context is that its dictionary of variables is immutable. Whatever is set when render() is called is what stays. Of course, since its Python, you can hack around this and change values in the context’s internal dictionary, but this will probably will not work as well as you’d think. The reason for this is that Mako in many cases creates copies of the Context object, which get sent to various elements of the template and inheriting templates used in an execution. So changing the value in your local Context will not necessarily make that value available in other parts of the template’s execution. Examples of where Mako creates copies of the Context include within top-level def calls from the main body of the template (the context is used to propagate locally assigned variables into the scope of defs; since in the template’s body they appear as inlined functions, Mako tries to make them act that way), and within an inheritance chain (each template in an inheritance chain has a different notion of parent and next, which are all stored in unique Context instances).

  • So what if I want to set values that are global to everyone within a template request? - All you have to do is provide a dictionary to your Context when the template first runs, and everyone can just get/set variables from that. Lets say its called attributes.

    Running the template looks like:

    output = template.render(attributes={})
    

    Within a template, just reference the dictionary:

    <%
        attributes['foo'] = 'bar'
    %>
    'foo' attribute is: ${attributes['foo']}
    
  • Why can’t “attributes” be a built-in feature of the Context? - This is an area where Mako is trying to make as few decisions about your application as it possibly can. Perhaps you don’t want your templates to use this technique of assigning and sharing data, or perhaps you have a different notion of the names and kinds of data structures that should be passed around. Once again Mako would rather ask the user to be explicit.

Context Methods and Accessors

Significant members off of Context include:

  • context[key] / context.get(key, default=None) - dictionary-like accessors for the context. Normally, any variable you use in your template is automatically pulled from the context if it isnt defined somewhere already. Use the dictionary accessor and/or get method when you want a variable that is already defined somewhere else, such as in the local arguments sent to a %def call. If a key is not present, like a dictionary it raises KeyError.
  • keys() - all the names defined within this context.
  • kwargs - this returns a copy of the context’s dictionary of variables. This is useful when you want to propagate the variables in the current context to a function as keyword arguments, i.e.:
${next.body(**context.kwargs)}
  • write(text) - write some text to the current output stream.
  • lookup - returns the TemplateLookup instance that is used for all file-lookups within the current execution (even though individual Template instances can conceivably have different instances of a TemplateLookup, only the TemplateLookup of the originally-called Template gets used in a particular execution).

All the built-in names

A one-stop shop for all the names Mako defines. Most of these names are instances of Namespace, which are described in the next section, Namespaces. Also, most of these names other than Context and UNDEFINED are also present within the Context itself.

  • local - the namespace of the current template, described in Built-in Namespaces.
  • self - the namespace of the topmost template in an inheritance chain (if any, otherwise the same as local), mostly described in Inheritance.
  • parent - the namespace of the parent template in an inheritance chain (otherwise undefined); see Inheritance.
  • next - the namespace of the next template in an inheritance chain (otherwise undefined); see Inheritance.
  • caller - a “mini” namespace created when using the <%call> tag to define a “def call with content”; described in Calling a def with embedded content and/or other defs.
  • capture - a function that calls a given def and captures its resulting content into a string, which is returned. Usage is described in Filtering and Buffering.
  • UNDEFINED - a global singleton that is applied to all otherwise uninitialized template variables that were not located within the Context when rendering began, unless the Template flag strict_undefined is set to True. UNDEFINED is an instance of Undefined, and raises an exception when its __str__() method is called.
  • pageargs - this is a dictionary which is present in a template which does not define any **kwargs section in its <%page> tag. All keyword arguments sent to the body() function of a template (when used via namespaces) go here by default unless otherwise defined as a page argument. If this makes no sense, it shouldn’t; read the section The “body()” method.

API Reference

class mako.runtime.Context(buffer, **data)

Bases: object

Provides runtime namespace, output buffer, and various callstacks for templates.

See The Mako Runtime Environment for detail on the usage of

Context.

get(key, default=None)

Return a value from this Context.

keys()

Return a list of all names established in this Context.

kwargs

Return the dictionary of keyword argments associated with this Context.

locals_(d)

create a new Context with a copy of this Context‘s current state, updated with the given dictionary.

lookup

Return the TemplateLookup associated with this Context.

pop_caller()

Pops a ‘caller’ callable onto the callstack for this Context.

push_caller(caller)

Pushes a ‘caller’ callable onto the callstack for this Context.

write(string)

Write a string to this Context object’s underlying output buffer.

writer()

Return the current writer function

class mako.runtime.Undefined

Bases: object

Represents an undefined value in a template.

All template modules have a constant value UNDEFINED present which is an instance of this object.

Previous: Defs and Blocks Next: Namespaces