aboutsummaryrefslogtreecommitdiffstats
path: root/doc/build/usage.rst
diff options
context:
space:
mode:
Diffstat (limited to 'doc/build/usage.rst')
-rw-r--r--doc/build/usage.rst471
1 files changed, 471 insertions, 0 deletions
diff --git a/doc/build/usage.rst b/doc/build/usage.rst
new file mode 100644
index 0000000..fb26f37
--- /dev/null
+++ b/doc/build/usage.rst
@@ -0,0 +1,471 @@
+=====
+Usage
+=====
+
+Basic Usage
+===========
+
+This section describes the Python API for Mako templates. If you
+are using Mako within a web framework such as Pylons, the work
+of integrating Mako's API is already done for you, in which case
+you can skip to the next section, [syntax](rel:syntax).
+
+The most basic way to create a template and render it is through
+the :class:`.Template` class::
+
+ from mako.template import Template
+
+ mytemplate = Template("hello world!")
+ print mytemplate.render()
+
+Above, the text argument to :class:`.Template` is **compiled** into a
+Python module representation. This module contains a function
+called :meth:`~.Template.render_body()`, which produces the output of the
+template. When ``mytemplate.render()`` is called, Mako sets up a
+runtime environment for the template and calls the
+:meth:`~.Template.render_body()` function, capturing the output into a buffer and
+returning its string contents.
+
+
+The code inside the ``render_body()`` function has access to a
+namespace of variables. You can specify these variables by
+sending them as additional keyword arguments to the :meth:`~.Template.render`
+method::
+
+ from mako.template import Template
+
+ mytemplate = Template("hello, ${name}!")
+ print mytemplate.render(name="jack")
+
+The :meth:`~.Template.render` method calls upon Mako to create a
+:class:`.Context` object, which stores all the variable names accessible
+to the template and also stores a buffer used to capture output.
+You can create this :class:`.Context` yourself and have the template
+render with it, using the :meth:`~.Template.render_context` method::
+
+ from mako.template import Template
+ from mako.runtime import Context
+ from StringIO import StringIO
+
+ mytemplate = Template("hello, ${name}!")
+ buf = StringIO()
+ ctx = Context(buf, name="jack")
+ mytemplate.render_context(ctx)
+ print buf.getvalue()
+
+Using File-Based Templates
+===========================
+
+A `Template` can also load its template source code from a file,
+using the `filename` keyword argument::
+
+ from mako.template import Template
+
+ mytemplate = Template(filename='/docs/mytmpl.txt')
+ print mytemplate.render()
+
+For improved performance, a `Template` which is loaded from a
+file can also cache the source code to its generated module on
+the filesystem as a regular Python module file (i.e. a .py
+file). To do this, just add the `module_directory` argument to
+the template::
+
+ from mako.template import Template
+
+ mytemplate = Template(filename='/docs/mytmpl.txt', module_directory='/tmp/mako_modules')
+ print mytemplate.render()
+
+When the above code is rendered, a file
+``/tmp/mako_modules/docs/mytmpl.txt.py`` is created containing the
+source code for the module. The next time a `Template` with the
+same arguments is created, this module file will be
+automatically re-used.
+
+Using :class:`.TemplateLookup`
+===============================
+
+All of the examples thus far have dealt with the usage of a
+single `Template` object. If the code within those templates
+tries to locate another template resource, it will need some way
+to find them, using simple URI strings. For this need, the
+resolution of other templates from within a template is
+accomplished by the `TemplateLookup` class. This class is
+constructed given a list of directories in which to search for
+templates, as well as keyword arguments that will be passed to
+the `Template` objects it creates::
+
+ from mako.template import Template
+ from mako.lookup import TemplateLookup
+
+ mylookup = TemplateLookup(directories=['/docs'])
+ mytemplate = Template("""<%include file="header.txt"/> hello world!""", lookup=mylookup)
+
+Above, we created a textual template which includes the file
+`header.txt`. In order for it to have somewhere to look for
+`header.txt`, we passed a `TemplateLookup` object to it, which
+will search in the directory `/docs` for the file `header.txt`.
+
+Usually, an application will store most or all of its templates
+as text files on the filesystem. So far, all of our examples
+have been a little bit contrived in order to illustrate the
+basic concepts. But a real application would get most or all of
+its templates directly from the `TemplateLookup`, using the
+aptly named `get_template` method, which accepts the URI of the
+desired template::
+
+ from mako.template import Template
+ from mako.lookup import TemplateLookup
+
+ mylookup = TemplateLookup(directories=['/docs'], module_directory='/tmp/mako_modules')
+
+ def serve_template(templatename, **kwargs):
+ mytemplate = mylookup.get_template(templatename)
+ print mytemplate.render(**kwargs)
+
+In the example above, we create a `TemplateLookup` which will
+look for templates in the `/docs` directory, and will store
+generated module files in the `/tmp/mako_modules` directory. The
+lookup locates templates by appending the given URI to each of
+its search directories; so if you gave it a URI of
+`/etc/beans/info.txt`, it would search for the file
+`/docs/etc/beans/info.txt`, else raise a `TopLevelNotFound`
+exception, which is a custom Mako exception.
+
+When the lookup locates templates, it will also assign a `uri`
+property to the `Template` which is the uri passed to the
+`get_template()` call. `Template` uses this uri to calculate the
+name of its module file. So in the above example, a
+`templatename` argument of `/etc/beans/info.txt` will create a
+module file `/tmp/mako_modules/etc/beans/info.txt.py`.
+
+Setting the Collection Size
+---------------------------
+
+The `TemplateLookup` also serves the important need of caching a
+fixed set of templates in memory at a given time, so that
+successive uri lookups do not result in full template
+compilations and/or module reloads on each request. By default,
+the `TemplateLookup` size is unbounded. You can specify a fixed
+size using the `collection_size` argument::
+
+ mylookup = TemplateLookup(directories=['/docs'],
+ module_directory='/tmp/mako_modules', collection_size=500)
+
+The above lookup will continue to load templates into memory
+until it reaches a count of around 500. At that point, it will
+clean out a certain percentage of templates using a **least
+recently used** scheme.
+
+Setting Filesystem Checks
+--------------------------
+
+Another important flag on `TemplateLookup` is
+`filesystem_checks`. This defaults to `True`, and says that each
+time a template is returned by the `get_template()` method, the
+revision time of the original template file is checked against
+the last time the template was loaded, and if the file is newer
+will reload its contents and recompile the template. On a
+production system, setting `filesystem_checks` to `False` can
+afford a small to moderate performance increase (depending on
+the type of filesystem used).
+
+Using Unicode and Encoding
+===========================
+
+Both `Template` and `TemplateLookup` accept `output_encoding`
+and `encoding_errors` parameters which can be used to encode the
+output in any Python supported codec::
+
+ from mako.template import Template
+ from mako.lookup import TemplateLookup
+
+ mylookup = TemplateLookup(directories=['/docs'], output_encoding='utf-8', encoding_errors='replace')
+
+ mytemplate = mylookup.get_template("foo.txt")
+ print mytemplate.render()
+
+When using Python 3, the `render()` method will return a `bytes`
+object, **if** `output_encoding` is set. Otherwise it returns a
+`string`.
+
+Additionally, the `render_unicode()` method exists which will
+return the template output as a Python `unicode` object, or in
+Python 3 a `string`::
+
+ print mytemplate.render_unicode()
+
+The above method disregards the output encoding keyword argument; you can encode yourself by saying::
+
+ print mytemplate.render_unicode().encode('utf-8', 'replace')
+
+Note that Mako's ability to return data in any encoding and/or
+`unicode` implies that the underlying output stream of the
+template is a Python unicode object. This behavior is described
+fully in [unicode](rel:unicode).
+
+.. _handling_exceptions:
+
+Handling Exceptions
+====================
+
+Template exceptions can occur in two distinct places. One is
+when you **lookup, parse and compile** the template, the other
+is when you **run** the template. Within the running of a
+template, exceptions are thrown normally from whatever Python
+code originated the issue. Mako has its own set of exception
+classes which mostly apply to the lookup and lexer/compiler
+stages of template construction. Mako provides some library
+routines that can be used to help provide Mako-specific
+information about any exception's stack trace, as well as
+formatting the exception within textual or HTML format. In all
+cases, the main value of these handlers is that of converting
+Python filenames, line numbers, and code samples into Mako
+template filenames, line numbers, and code samples. All lines
+within a stack trace which correspond to a Mako template module
+will be converted to be against the originating template file.
+
+To format exception traces, the `text_error_template` and
+`html_error_template` functions are provided. They make usage of
+`sys.exc_info()` to get at the most recently thrown exception.
+Usage of these handlers usually looks like::
+
+ from mako import exceptions
+
+ try:
+ template = lookup.get_template(uri)
+ print template.render()
+ except:
+ print exceptions.text_error_template().render()
+
+Or for the HTML render function::
+
+ from mako import exceptions
+
+ try:
+ template = lookup.get_template(uri)
+ print template.render()
+ except:
+ print exceptions.html_error_template().render()
+
+The `html_error_template` template accepts two options:
+specifying `full=False` causes only a section of an HTML
+document to be rendered. Specifying `css=False` will disable the
+default stylesheet from being rendered.
+
+E.g.::
+
+ print exceptions.html_error_template().render(full=False)
+
+The HTML render function is also available built-in to
+`Template` using the `format_exceptions` flag. In this case, any
+exceptions raised within the **render** stage of the template
+will result in the output being substituted with the output of
+`html_error_template`::
+
+ template = Template(filename="/foo/bar", format_exceptions=True)
+ print template.render()
+
+Note that the compile stage of the above template occurs when
+you construct the `Template` itself, and no output stream is
+defined. Therefore exceptions which occur within the
+lookup/parse/compile stage will not be handled and will
+propagate normally. While the pre-render traceback usually will
+not include any Mako-specific lines anyway, it will mean that
+exceptions which occur previous to rendering and those which
+occur within rendering will be handled differently...so the
+`try/except` patterns described previously are probably of more
+general use.
+
+The underlying object used by the error template functions is
+the `RichTraceback` object. This object can also be used
+directly to provide custom error views. Here's an example usage
+which describes its general API::
+
+ from mako.exceptions import RichTraceback
+
+ try:
+ template = lookup.get_template(uri)
+ print template.render()
+ except:
+ traceback = RichTraceback()
+ for (filename, lineno, function, line) in traceback.traceback:
+ print "File %s, line %s, in %s" % (filename, lineno, function)
+ print line, "\n"
+ print "%s: %s" % (str(traceback.error.__class__.__name__), traceback.error)
+
+Further information about `RichTraceback` is available within
+the module-level documentation for `mako.exceptions`.
+
+Common Framework Integrations
+=============================
+
+The Mako distribution includes a little bit of helper code for
+the purpose of using Mako in some popular web framework
+scenarios. This is a brief description of whats included.
+
+WSGI
+----
+
+A sample WSGI application is included in the distrubution in the
+file `examples/wsgi/run_wsgi.py`. This runner is set up to pull
+files from a `templates` as well as an `htdocs` directory and
+includes a rudimental two-file layout. The WSGI runner acts as a
+fully functional standalone web server, using `wsgiutils` to run
+itself, and propagates GET and POST arguments from the request
+into the `Context`, can serve images, css files and other kinds
+of files, and also displays errors using Mako's included
+exception-handling utilities.
+
+Pygments
+---------
+
+A `Pygments <http://pygments.pocoo.org>`_-compatible syntax
+highlighting module is included under `mako.ext.pygmentplugin`.
+This module is used in the generation of Mako documentation and
+also contains various setuptools entry points under the heading
+`pygments.lexers`, including `mako`, `html+mako`, `xml+mako`
+(see the `setup.py` file for all the entry points).
+
+Babel
+------
+
+Mako provides support for extracting gettext messages from
+templates via a `Babel`_ extractor
+entry point under `mako.ext.babelplugin`.
+
+Gettext messages are extracted from all Python code sections,
+even the more obscure ones such as [control
+structures](rel:syntax_control), [def tag function
+declarations](rel:defs), [call tag
+exprs](rel:defs_defswithcontent) and even [page tag
+args](rel:syntax_tags_page).
+
+`Translator
+comments <http://babel.edgewall.org/wiki/Documentation/messages.html#comments-tags-and-translator-comments-explanation>`_
+may also be extracted from Mako templates when a comment tag is
+specified to `Babel`_ (such as with
+the -c option).
+
+For example, a project '`myproj`' contains the following Mako
+template at myproj/myproj/templates/name.html::
+
+ <div id="name">
+ Name:
+ ## TRANSLATORS: This is a proper name. See the gettext
+ ## manual, section Names.
+ ${_('Francois Pinard')}
+ </div>
+
+To extract gettext messages from this template the project needs
+a Mako section in its `Babel Extraction Method Mapping
+file <http://babel.edgewall.org/wiki/Documentation/messages.html#extraction-method-mapping-and-configuration>`_
+(typically located at myproj/babel.cfg)::
+
+ # Extraction from Python source files
+
+ [python: myproj/**.py]
+
+ # Extraction from Mako templates
+
+ [mako: myproj/templates/**.html]
+ input_encoding = utf-8
+
+The Mako extractor supports an optional `input_encoding`
+parameter specifying the encoding of the templates (identical to
+`Template`/`TemplateLookup`'s `input_encoding` parameter).
+
+Invoking `Babel`_'s extractor at the
+command line in the project's root directory::
+
+ myproj$ pybabel extract -F babel.cfg -c "TRANSLATORS:" .
+
+Will output a gettext catalog to stdout including the following::
+
+ #. TRANSLATORS: This is a proper name. See the gettext
+ #. manual, section Names.
+ #: myproj/templates/name.html:5
+ msgid "Francois Pinard"
+ msgstr ""
+
+This is only a basic example:
+`Babel`_ can be invoked from setup.py
+and its command line options specified in the accompanying
+setup.cfg via `Babel Distutils/Setuptools
+Integration <http://babel.edgewall.org/wiki/Documentation/setup.html>`_.
+
+Comments must immediately precede a gettext message to be
+extracted. In the following case the TRANSLATORS: comment would
+not have been extracted:
+
+.. sourcecode:: mako
+
+ <div id="name">
+ ## TRANSLATORS: This is a proper name. See the gettext
+ ## manual, section Names.
+ Name: ${_('Francois Pinard')}
+ </div>
+
+See the `Babel User
+Guide <http://babel.edgewall.org/wiki/Documentation/index.html>`_
+for more information.
+
+.. _babel: http://babel.edgewall.org/
+
+
+API Documentation
+=================
+
+.. autoclass:: mako.template.Template
+ :members:
+
+.. autoclass:: mako.lookup.TemplateLookup
+ :members:
+
+.. autoclass:: mako.exceptions.RichTraceback
+
+ .. py:attribute:: error
+
+ the exception instance.
+
+ .. py:attribute:: message
+
+ the exception error message as unicode
+
+ .. py:attribute:: source
+
+ source code of the file where the error occured.
+ if the error occured within a compiled template,
+ this is the template source.
+
+ .. py:attribute:: lineno
+
+ line number where the error occured. if the error
+ occured within a compiled template, the line number
+ is adjusted to that of the template source
+
+ .. py:attribute:: records
+
+ a list of 8-tuples containing the original
+ python traceback elements, plus the
+ filename, line number, source line, and full template source
+ for the traceline mapped back to its originating source
+ template, if any for that traceline (else the fields are None).
+
+ .. py:attribute:: reverse_records
+
+ the list of records in reverse
+ traceback - a list of 4-tuples, in the same format as a regular
+ python traceback, with template-corresponding
+ traceback records replacing the originals
+
+ .. py:attribute:: reverse_traceback
+
+ the traceback list in reverse
+
+
+.. autofunction:: mako.exceptions.html_error_template
+
+.. autofunction:: mako.exceptions.text_error_template
+
+
+