aboutsummaryrefslogtreecommitdiffstats
path: root/doc/build/runtime.rst
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-11-12 17:27:11 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2010-11-12 17:27:11 -0500
commita9da8487c7da377c9378bd5c997cc96ce7079efa (patch)
tree8cba4a1248ff10feff9e26caf40ca9a10f4ed5c0 /doc/build/runtime.rst
parent4ce916525fd94116e696f4d8cde19333e9ed946c (diff)
downloadexternal_python_mako-a9da8487c7da377c9378bd5c997cc96ce7079efa.tar.gz
external_python_mako-a9da8487c7da377c9378bd5c997cc96ce7079efa.tar.bz2
external_python_mako-a9da8487c7da377c9378bd5c997cc96ce7079efa.zip
looks good
Diffstat (limited to 'doc/build/runtime.rst')
-rw-r--r--doc/build/runtime.rst237
1 files changed, 237 insertions, 0 deletions
diff --git a/doc/build/runtime.rst b/doc/build/runtime.rst
index 8b13789..8db081a 100644
--- a/doc/build/runtime.rst
+++ b/doc/build/runtime.rst
@@ -1 +1,238 @@
+.. _runtime_toplevel:
+
+=============================
+The Mako Runtime Environment
+=============================
+
+This section describes a little bit about the objects and
+built-in functions that are available in templates.
+
+Context
+=======
+
+The :class:`.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 :meth:`~.Template.render` function and
+some built-in variables provided by Mako's runtime environment.
+
+The Buffer
+----------
+
+The buffer is stored within the :class:`.Context`, and writing
+to it is achieved by calling :meth:`.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
+:ref:`filtering_toplevel`, or if you want to programmatically
+send content to the output stream, such as within a ``<% %>``
+block.
+
+.. sourcecode:: mako
+
+ <%
+ context.write("some programmatic text")
+ %>
+
+The actual buffer may or may not be the original buffer sent to
+the :class:`.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
+:meth:`.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
+:class:`.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
+:class:`.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 :class:`.Template` or :class:`.TemplateLookup`. This will cause
+ any non-present variables to raise an immediate ``NameError``
+ which includes the name of the variable in its message
+ when :meth:`~.Template.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 :class:`.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:
+
+ .. sourcecode:: mako
+
+ % if someval is UNDEFINED:
+ someval is: no value
+ % else:
+ someval is: ${someval}
+ % endif
+
+Another facet of the :class:`.Context` is that its dictionary of
+variables is **immutable**. Whatever is set when
+:meth:`~.Template.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 :class:`.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 :class:`.Context` will not necessarily make that value
+available in other parts of the template's execution. Examples
+of where Mako creates copies of the :class:`.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 :class:`.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 :class:`.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:
+
+ .. sourcecode:: python
+
+ output = template.render(attributes={})
+
+ Within a template, just reference the dictionary:
+
+ .. sourcecode:: mako
+
+ <%
+ 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 :class:`.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.:
+
+.. sourcecode:: mako
+
+ ${next.body(**context.kwargs)}
+
+* ``write(text)`` - write some text to the current output
+ stream.
+* ``lookup`` - returns the :class:`.TemplateLookup` instance that is
+ used for all file-lookups within the current execution (even
+ though individual :class:`.Template` instances can conceivably have
+ different instances of a :class:`.TemplateLookup`, only the
+ :class:`.TemplateLookup` of the originally-called :class:`.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 :class:`.Namespace`, which are described
+in the next section, :ref:`namespaces_toplevel`. Also, most of
+these names other than :class:`.Context` and ``UNDEFINED`` are
+also present *within* the :class:`.Context` itself.
+
+* ``local`` - the namespace of the current template, described
+ in :ref:`namespaces_builtin`.
+* ``self`` - the namespace of the topmost template in an
+ inheritance chain (if any, otherwise the same as ``local``),
+ mostly described in :ref:`inheritance_toplevel`.
+* ``parent`` - the namespace of the parent template in an
+ inheritance chain (otherwise undefined); see
+ :ref:`inheritance_toplevel`.
+* ``next`` - the namespace of the next template in an
+ inheritance chain (otherwise undefined); see
+ :ref:`inheritance_toplevel`.
+* ``caller`` - a "mini" namespace created when using the
+ ``<%call>`` tag to define a "def call with content"; described
+ in :ref:`defs_with_content`.
+* ``capture`` - a function that calls a given def and captures
+ its resulting content into a string, which is returned. Usage
+ is described in :ref:`filtering_toplevel`.
+* ``UNDEFINED`` - a global singleton that is applied to all
+ otherwise uninitialized template variables that were not
+ located within the :class:`.Context` when rendering began,
+ unless the :class:`.Template` flag ``strict_undefined``
+ is set to ``True``. ``UNDEFINED`` is
+ an instance of :class:`.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
+ :ref:`namespaces_body`.
+
+API Reference
+==============
+
+.. autoclass:: mako.runtime.Context
+ :show-inheritance:
+ :members:
+
+.. autoclass:: mako.runtime.Undefined
+ :show-inheritance:
+
+