summaryrefslogtreecommitdiff
path: root/doc/build/namespaces.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/build/namespaces.rst')
-rw-r--r--doc/build/namespaces.rst475
1 files changed, 475 insertions, 0 deletions
diff --git a/doc/build/namespaces.rst b/doc/build/namespaces.rst
new file mode 100644
index 0000000..afd323d
--- /dev/null
+++ b/doc/build/namespaces.rst
@@ -0,0 +1,475 @@
+.. _namespaces_toplevel:
+
+==========
+Namespaces
+==========
+
+Namespaces are used to organize groups of defs into
+categories, and also to "import" defs from other files.
+
+If the file ``components.html`` defines these two defs:
+
+.. sourcecode:: mako
+
+ ## components.html
+ <%def name="comp1()">
+ this is comp1
+ </%def>
+
+ <%def name="comp2(x)">
+ this is comp2, x is ${x}
+ </%def>
+
+you can make another file, for example ``index.html``, that
+pulls those two defs into a namespace called ``comp``:
+
+.. sourcecode:: mako
+
+ ## index.html
+ <%namespace name="comp" file="components.html"/>
+
+ Here's comp1: ${comp.comp1()}
+ Here's comp2: ${comp.comp2(x=5)}
+
+The ``comp`` variable above is an instance of
+:class:`.Namespace`, a **proxy object** which delivers
+method calls to the underlying template callable using the
+current context.
+
+``<%namespace>`` also provides an ``import`` attribute which can
+be used to pull the names into the local namespace, removing the
+need to call it via the "``.``" operator. When ``import`` is used, the
+``name`` attribute is optional.
+
+.. sourcecode:: mako
+
+ <%namespace file="components.html" import="comp1, comp2"/>
+
+ Heres comp1: ${comp1()}
+ Heres comp2: ${comp2(x=5)}
+
+``import`` also supports the "``*``" operator:
+
+.. sourcecode:: mako
+
+ <%namespace file="components.html" import="*"/>
+
+ Heres comp1: ${comp1()}
+ Heres comp2: ${comp2(x=5)}
+
+The names imported by the ``import`` attribute take precedence
+over any names that exist within the current context.
+
+.. note:: In current versions of Mako, usage of ``import='*'`` is
+ known to decrease performance of the template. This will be
+ fixed in a future release.
+
+The ``file`` argument allows expressions -- if looking for
+context variables, the ``context`` must be named explicitly:
+
+.. sourcecode:: mako
+
+ <%namespace name="dyn" file="${context['namespace_name']}"/>
+
+Ways to Call Namespaces
+=======================
+
+There are essentially four ways to call a function from a
+namespace.
+
+The "expression" format, as described previously. Namespaces are
+just Python objects with functions on them, and can be used in
+expressions like any other function:
+
+.. sourcecode:: mako
+
+ ${mynamespace.somefunction('some arg1', 'some arg2', arg3='some arg3', arg4='some arg4')}
+
+Synonymous with the "expression" format is the "custom tag"
+format, when a "closed" tag is used. This format, introduced in
+Mako 0.2.3, allows the usage of a "custom" Mako tag, with the
+function arguments passed in using named attributes:
+
+.. sourcecode:: mako
+
+ <%mynamespace:somefunction arg1="some arg1" arg2="some arg2" arg3="some arg3" arg4="some arg4"/>
+
+When using tags, the values of the arguments are taken as
+literal strings by default. To embed Python expressions as
+arguments, use the embedded expression format:
+
+.. sourcecode:: mako
+
+ <%mynamespace:somefunction arg1="${someobject.format()}" arg2="${somedef(5, 12)}"/>
+
+The "custom tag" format is intended mainly for namespace
+functions which recognize body content, which in Mako is known
+as a "def with embedded content":
+
+.. sourcecode:: mako
+
+ <%mynamespace:somefunction arg1="some argument" args="x, y">
+ Some record: ${x}, ${y}
+ </%mynamespace:somefunction>
+
+The "classic" way to call defs with embedded content is the ``<%call>`` tag:
+
+.. sourcecode:: mako
+
+ <%call expr="mynamespace.somefunction(arg1='some argument')" args="x, y">
+ Some record: ${x}, ${y}
+ </%call>
+
+For information on how to construct defs that embed content from
+the caller, see :ref:`defs_with_content`.
+
+.. _namespaces_python_modules:
+
+Namespaces from Regular Python Modules
+======================================
+
+Namespaces can also import regular Python functions from
+modules. These callables need to take at least one argument,
+``context``, an instance of :class:`.Context`. A module file
+``some/module.py`` might contain the callable:
+
+.. sourcecode:: python
+
+ def my_tag(context):
+ context.write("hello world")
+ return ''
+
+A template can use this module via:
+
+.. sourcecode:: mako
+
+ <%namespace name="hw" module="some.module"/>
+
+ ${hw.my_tag()}
+
+Note that the ``context`` argument is not needed in the call;
+the :class:`.Namespace` tag creates a locally-scoped callable which
+takes care of it. The ``return ''`` is so that the def does not
+dump a ``None`` into the output stream -- the return value of any
+def is rendered after the def completes, in addition to whatever
+was passed to :meth:`.Context.write` within its body.
+
+If your def is to be called in an "embedded content" context,
+that is as described in :ref:`defs_with_content`, you should use
+the :func:`.supports_caller` decorator, which will ensure that Mako
+will ensure the correct "caller" variable is available when your
+def is called, supporting embedded content:
+
+.. sourcecode:: python
+
+ from mako.runtime import supports_caller
+
+ @supports_caller
+ def my_tag(context):
+ context.write("<div>")
+ context['caller'].body()
+ context.write("</div>")
+ return ''
+
+Capturing of output is available as well, using the
+outside-of-templates version of the :func:`.capture` function,
+which accepts the "context" as its first argument:
+
+.. sourcecode:: python
+
+ from mako.runtime import supports_caller, capture
+
+ @supports_caller
+ def my_tag(context):
+ return "<div>%s</div>" % \
+ capture(context, context['caller'].body, x="foo", y="bar")
+
+Declaring Defs in Namespaces
+============================
+
+The ``<%namespace>`` tag supports the definition of ``<%def>``\ s
+directly inside the tag. These defs become part of the namespace
+like any other function, and will override the definitions
+pulled in from a remote template or module:
+
+.. sourcecode:: mako
+
+ ## define a namespace
+ <%namespace name="stuff">
+ <%def name="comp1()">
+ comp1
+ </%def>
+ </%namespace>
+
+ ## then call it
+ ${stuff.comp1()}
+
+.. _namespaces_body:
+
+The ``body()`` Method
+=====================
+
+Every namespace that is generated from a template contains a
+method called ``body()``. This method corresponds to the main
+body of the template, and plays its most important roles when
+using inheritance relationships as well as
+def-calls-with-content.
+
+Since the ``body()`` method is available from a namespace just
+like all the other defs defined in a template, what happens if
+you send arguments to it? By default, the ``body()`` method
+accepts no positional arguments, and for usefulness in
+inheritance scenarios will by default dump all keyword arguments
+into a dictionary called ``pageargs``. But if you actually want
+to get at the keyword arguments, Mako recommends you define your
+own argument signature explicitly. You do this via using the
+``<%page>`` tag:
+
+.. sourcecode:: mako
+
+ <%page args="x, y, someval=8, scope='foo', **kwargs"/>
+
+A template which defines the above signature requires that the
+variables ``x`` and ``y`` are defined, defines default values
+for ``someval`` and ``scope``, and sets up ``**kwargs`` to
+receive all other keyword arguments. If ``**kwargs`` or similar
+is not present, the argument ``**pageargs`` gets tacked on by
+Mako. When the template is called as a top-level template (i.e.
+via :meth:`~.Template.render`) or via the ``<%include>`` tag, the
+values for these arguments will be pulled from the ``Context``.
+In all other cases, i.e. via calling the ``body()`` method, the
+arguments are taken as ordinary arguments from the method call.
+So above, the body might be called as:
+
+.. sourcecode:: mako
+
+ ${self.body(5, y=10, someval=15, delta=7)}
+
+The :class:`.Context` object also supplies a :attr:`~.Context.kwargs`
+accessor, for cases when you'd like to pass along the top level context
+arguments to a ``body()`` callable:
+
+.. sourcecode:: mako
+
+ ${next.body(**context.kwargs)}
+
+The usefulness of calls like the above become more apparent when
+one works with inheriting templates. For more information on
+this, as well as the meanings of the names ``self`` and
+``next``, see :ref:`inheritance_toplevel`.
+
+.. _namespaces_builtin:
+
+Built-in Namespaces
+===================
+
+The namespace is so great that Mako gives your template one (or
+two) for free. The names of these namespaces are ``local`` and
+``self``. Other built-in namespaces include ``parent`` and
+``next``, which are optional and are described in
+:ref:`inheritance_toplevel`.
+
+.. _namespace_local:
+
+``local``
+---------
+
+The ``local`` namespace is basically the namespace for the
+currently executing template. This means that all of the top
+level defs defined in your template, as well as your template's
+``body()`` function, are also available off of the ``local``
+namespace.
+
+The ``local`` namespace is also where properties like ``uri``,
+``filename``, and ``module`` and the ``get_namespace`` method
+can be particularly useful.
+
+.. _namespace_self:
+
+``self``
+--------
+
+The ``self`` namespace, in the case of a template that does not
+use inheritance, is synonymous with ``local``. If inheritance is
+used, then ``self`` references the topmost template in the
+inheritance chain, where it is most useful for providing the
+ultimate form of various "method" calls which may have been
+overridden at various points in an inheritance chain. See
+:ref:`inheritance_toplevel`.
+
+Inheritable Namespaces
+======================
+
+The ``<%namespace>`` tag includes an optional attribute
+``inheritable="True"``, which will cause the namespace to be
+attached to the ``self`` namespace. Since ``self`` is globally
+available throughout an inheritance chain (described in the next
+section), all the templates in an inheritance chain can get at
+the namespace imported in a super-template via ``self``.
+
+.. sourcecode:: mako
+
+ ## base.html
+ <%namespace name="foo" file="foo.html" inheritable="True"/>
+
+ ${next.body()}
+
+ ## somefile.html
+ <%inherit file="base.html"/>
+
+ ${self.foo.bar()}
+
+This allows a super-template to load a whole bunch of namespaces
+that its inheriting templates can get to, without them having to
+explicitly load those namespaces themselves.
+
+The ``import="*"`` part of the ``<%namespace>`` tag doesn't yet
+interact with the ``inheritable`` flag, so currently you have to
+use the explicit namespace name off of ``self``, followed by the
+desired function name. But more on this in a future release.
+
+Namespace API Usage Example - Static Dependencies
+==================================================
+
+The ``<%namespace>`` tag at runtime produces an instance of
+:class:`.Namespace`. Programmatic access of :class:`.Namespace` can be used
+to build various kinds of scaffolding in templates and between templates.
+
+A common request is the ability for a particular template to declare
+"static includes" - meaning, the usage of a particular set of defs requires
+that certain Javascript/CSS files are present. Using :class:`.Namespace` as the
+object that holds together the various templates present, we can build a variety
+of such schemes. In particular, the :class:`.Context` has a ``namespaces``
+attribute, which is a dictionary of all :class:`.Namespace` objects declared.
+Iterating the values of this dictionary will provide a :class:`.Namespace`
+object for each time the ``<%namespace>`` tag was used, anywhere within the
+inheritance chain.
+
+
+.. _namespace_attr_for_includes:
+
+Version One - Use :attr:`.Namespace.attr`
+-----------------------------------------
+
+The :attr:`.Namespace.attr` attribute allows us to locate any variables declared
+in the ``<%! %>`` of a template.
+
+.. sourcecode:: mako
+
+ ## base.mako
+ ## base-most template, renders layout etc.
+ <html>
+ <head>
+ ## traverse through all namespaces present,
+ ## look for an attribute named 'includes'
+ % for ns in context.namespaces.values():
+ % for incl in getattr(ns.attr, 'includes', []):
+ ${incl}
+ % endfor
+ % endfor
+ </head>
+ <body>
+ ${next.body()}
+ </body
+ </html>
+
+ ## library.mako
+ ## library functions.
+ <%!
+ includes = [
+ '<link rel="stylesheet" type="text/css" href="mystyle.css"/>',
+ '<script type="text/javascript" src="functions.js"></script>'
+ ]
+ %>
+
+ <%def name="mytag()">
+ <form>
+ ${caller.body()}
+ </form>
+ </%def>
+
+ ## index.mako
+ ## calling template.
+ <%inherit file="base.mako"/>
+ <%namespace name="foo" file="library.mako"/>
+
+ <%foo:mytag>
+ a form
+ </%foo:mytag>
+
+
+Above, the file ``library.mako`` declares an attribute ``includes`` inside its global ``<%! %>`` section.
+``index.mako`` includes this template using the ``<%namespace>`` tag. The base template ``base.mako``, which is the inherited parent of ``index.mako`` and is responsible for layout, then locates this attribute and iterates through its contents to produce the includes that are specific to ``library.mako``.
+
+Version Two - Use a specific named def
+-----------------------------------------
+
+In this version, we put the includes into a ``<%def>`` that
+follows a naming convention.
+
+.. sourcecode:: mako
+
+ ## base.mako
+ ## base-most template, renders layout etc.
+ <html>
+ <head>
+ ## traverse through all namespaces present,
+ ## look for a %def named 'includes'
+ % for ns in context.namespaces.values():
+ % if hasattr(ns, 'includes'):
+ ${ns.includes()}
+ % endif
+ % endfor
+ </head>
+ <body>
+ ${next.body()}
+ </body
+ </html>
+
+ ## library.mako
+ ## library functions.
+
+ <%def name="includes()">
+ <link rel="stylesheet" type="text/css" href="mystyle.css"/>
+ <script type="text/javascript" src="functions.js"></script>
+ </%def>
+
+ <%def name="mytag()">
+ <form>
+ ${caller.body()}
+ </form>
+ </%def>
+
+
+ ## index.mako
+ ## calling template.
+ <%inherit file="base.mako"/>
+ <%namespace name="foo" file="library.mako"/>
+
+ <%foo:mytag>
+ a form
+ </%foo:mytag>
+
+In this version, ``library.mako`` declares a ``<%def>`` named ``includes``. The example works
+identically to the previous one, except that ``base.mako`` looks for defs named ``include``
+on each namespace it examines.
+
+API Reference
+=============
+
+.. autoclass:: mako.runtime.Namespace
+ :show-inheritance:
+ :members:
+
+.. autoclass:: mako.runtime.TemplateNamespace
+ :show-inheritance:
+ :members:
+
+.. autoclass:: mako.runtime.ModuleNamespace
+ :show-inheritance:
+ :members:
+
+.. autofunction:: mako.runtime.supports_caller
+
+.. autofunction:: mako.runtime.capture
+