summaryrefslogtreecommitdiff
path: root/doc/build/namespaces.rst
blob: 1453b80102f07cb346421c9e06f6160794461e89 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
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 reponsible 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