summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-11-12 13:06:43 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2010-11-12 13:06:43 -0500
commit5d4575aff2310268bfd439b514b778a7eff0fbf0 (patch)
treef39f3b3d256c964d85958642cda6def100004131
parentca21a5353a4c88f3477a53f2f45cd9ca280b0479 (diff)
downloadmako-5d4575aff2310268bfd439b514b778a7eff0fbf0.tar.gz
- initial sphinx buildout. only includes "usage" so far, needs more work.
-rw-r--r--doc/build/Makefile142
-rw-r--r--doc/build/builder/__init__.py0
-rw-r--r--doc/build/builder/builders.py69
-rw-r--r--doc/build/builder/util.py12
-rw-r--r--doc/build/caching.rst1
-rw-r--r--doc/build/conf.py280
-rw-r--r--doc/build/defs.rst1
-rw-r--r--doc/build/filtering.rst1
-rw-r--r--doc/build/genhtml.py58
-rw-r--r--doc/build/index.rst21
-rw-r--r--doc/build/inheritance.rst1
-rw-r--r--doc/build/lib/markdown.py1671
-rw-r--r--doc/build/lib/toc.py78
-rw-r--r--doc/build/namespaces.rst1
-rw-r--r--doc/build/read_markdown.py213
-rw-r--r--doc/build/runtime.rst1
-rw-r--r--doc/build/static/docs.css288
-rw-r--r--doc/build/syntax.rst1
-rw-r--r--doc/build/templates/autohandler21
-rw-r--r--doc/build/templates/base.html46
-rw-r--r--doc/build/templates/content_layout.html16
-rw-r--r--doc/build/templates/formatting.html83
-rw-r--r--doc/build/templates/genindex.mako72
-rw-r--r--doc/build/templates/layout.mako130
-rw-r--r--doc/build/templates/nav.html60
-rw-r--r--doc/build/templates/page.mako2
-rw-r--r--doc/build/templates/search.mako22
-rw-r--r--doc/build/templates/site_base.mako27
-rw-r--r--doc/build/templates/static_base.mako19
-rw-r--r--doc/build/templates/toc.html26
-rw-r--r--doc/build/unicode.rst1
-rw-r--r--doc/build/usage.rst471
-rw-r--r--doc/docs.css91
-rw-r--r--doc/highlight.css57
-rw-r--r--doc/makotemplates.txt663
-rw-r--r--mako/exceptions.py27
-rw-r--r--mako/template.py86
37 files changed, 1634 insertions, 3125 deletions
diff --git a/doc/build/Makefile b/doc/build/Makefile
new file mode 100644
index 0000000..31dce05
--- /dev/null
+++ b/doc/build/Makefile
@@ -0,0 +1,142 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = output
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest dist-html site-mako
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @echo " dist-html same as html, but places files in /doc"
+ @echo " dirhtml to make HTML files named index.html in directories"
+ @echo " singlehtml to make a single large HTML file"
+ @echo " pickle to make pickle files"
+ @echo " json to make JSON files"
+ @echo " htmlhelp to make HTML files and a HTML help project"
+ @echo " qthelp to make HTML files and a qthelp project"
+ @echo " devhelp to make HTML files and a Devhelp project"
+ @echo " epub to make an epub"
+ @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+ @echo " latexpdf to make LaTeX files and run them through pdflatex"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " linkcheck to check all external links for integrity"
+ @echo " doctest to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+ -rm -rf $(BUILDDIR)/*
+
+html:
+ $(SPHINXBUILD) -b html -A mako_layout=html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dist-html:
+ $(SPHINXBUILD) -b html -A mako_layout=html $(ALLSPHINXOPTS) ..
+ @echo
+ @echo "Build finished. The HTML pages are in ../."
+
+site-mako:
+ $(SPHINXBUILD) -b html -A mako_layout=site $(ALLSPHINXOPTS) $(BUILDDIR)/site
+ @echo
+ @echo "Build finished. The Mako pages are in $(BUILDDIR)/site."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+singlehtml:
+ $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
+ @echo
+ @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+ @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/SQLAlchemy.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/SQLAlchemy.qhc"
+
+devhelp:
+ $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
+ @echo
+ @echo "Build finished."
+ @echo "To view the help file:"
+ @echo "# mkdir -p $$HOME/.local/share/devhelp/SQLAlchemy"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/SQLAlchemy"
+ @echo "# devhelp"
+
+epub:
+ $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
+ @echo
+ @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ cp texinputs/* $(BUILDDIR)/latex/
+ @echo
+ @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+ @echo "Run \`make' in that directory to run these through (pdf)latex" \
+ "(use \`make latexpdf' here to do that automatically)."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through pdflatex..."
+ make -C $(BUILDDIR)/latex all-pdf
+ @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
+
+text:
+ $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
+ @echo
+ @echo "Build finished. The text files are in $(BUILDDIR)/text."
+
+man:
+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
+ @echo
+ @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+ @echo
+ @echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) .
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/doc/build/builder/__init__.py b/doc/build/builder/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/doc/build/builder/__init__.py
diff --git a/doc/build/builder/builders.py b/doc/build/builder/builders.py
new file mode 100644
index 0000000..afe2a21
--- /dev/null
+++ b/doc/build/builder/builders.py
@@ -0,0 +1,69 @@
+from sphinx.application import TemplateBridge
+from sphinx.builders.html import StandaloneHTMLBuilder
+from sphinx.highlighting import PygmentsBridge
+from pygments import highlight
+from pygments.lexer import RegexLexer, bygroups, using
+from pygments.token import *
+from pygments.filter import Filter, apply_filters
+from pygments.lexers import PythonLexer, PythonConsoleLexer
+from pygments.formatters import HtmlFormatter, LatexFormatter
+import re
+from mako.lookup import TemplateLookup
+from mako.template import Template
+from mako.ext.pygmentplugin import MakoLexer
+
+class MakoBridge(TemplateBridge):
+ def init(self, builder, *args, **kw):
+ self.layout = builder.config.html_context.get('mako_layout', 'html')
+
+ self.lookup = TemplateLookup(directories=builder.config.templates_path,
+ format_exceptions=True,
+ imports=[
+ "from builder import util"
+ ]
+ )
+
+ def render(self, template, context):
+ template = template.replace(".html", ".mako")
+ context['prevtopic'] = context.pop('prev', None)
+ context['nexttopic'] = context.pop('next', None)
+ context['mako_layout'] = self.layout == 'html' and 'static_base.mako' or 'site_base.mako'
+ # sphinx 1.0b2 doesn't seem to be providing _ for some reason...
+ context.setdefault('_', lambda x:x)
+ return self.lookup.get_template(template).render_unicode(**context)
+
+
+ def render_string(self, template, context):
+ context['prevtopic'] = context.pop('prev', None)
+ context['nexttopic'] = context.pop('next', None)
+ context['mako_layout'] = self.layout == 'html' and 'static_base.mako' or 'site_base.mako'
+ # sphinx 1.0b2 doesn't seem to be providing _ for some reason...
+ context.setdefault('_', lambda x:x)
+ return Template(template, lookup=self.lookup,
+ format_exceptions=True,
+ imports=[
+ "from builder import util"
+ ]
+ ).render_unicode(**context)
+
+class StripDocTestFilter(Filter):
+ def filter(self, lexer, stream):
+ for ttype, value in stream:
+ if ttype is Token.Comment and re.match(r'#\s*doctest:', value):
+ continue
+ yield ttype, value
+
+
+def autodoc_skip_member(app, what, name, obj, skip, options):
+ if what == 'class' and skip and name == '__init__':
+ return False
+ else:
+ return skip
+
+def setup(app):
+# app.connect('autodoc-skip-member', autodoc_skip_member)
+ # Mako is already in Pygments, adding the local
+ # lexer here so that the latest syntax is available
+ app.add_lexer('mako', MakoLexer())
+
+ \ No newline at end of file
diff --git a/doc/build/builder/util.py b/doc/build/builder/util.py
new file mode 100644
index 0000000..dc2e272
--- /dev/null
+++ b/doc/build/builder/util.py
@@ -0,0 +1,12 @@
+import re
+
+def striptags(text):
+ return re.compile(r'<[^>]*>').sub('', text)
+
+def go(m):
+ # .html with no anchor if present, otherwise "#" for top of page
+ return m.group(1) or '#'
+
+def strip_toplevel_anchors(text):
+ return re.compile(r'(\.html)?#[-\w]+-toplevel').sub(go, text)
+
diff --git a/doc/build/caching.rst b/doc/build/caching.rst
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/doc/build/caching.rst
@@ -0,0 +1 @@
+
diff --git a/doc/build/conf.py b/doc/build/conf.py
new file mode 100644
index 0000000..288b3f5
--- /dev/null
+++ b/doc/build/conf.py
@@ -0,0 +1,280 @@
+# -*- coding: utf-8 -*-
+#
+# Mako documentation build configuration file
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+sys.path.insert(0, os.path.abspath('../..'))
+sys.path.insert(0, os.path.abspath('.'))
+
+import mako
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+#extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode',
+# 'sphinx.ext.doctest', 'builder.builders']
+
+extensions = ['sphinx.ext.autodoc',
+ 'sphinx.ext.doctest', 'builder.builders']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['templates']
+
+nitpicky = True
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+template_bridge = "builder.builders.MakoBridge"
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Mako'
+copyright = u'the Mako authors and contributors'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = mako.__version__
+# The full version, including alpha/beta/rc tags.
+release = mako.__version__
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = ['build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'default'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The style sheet to use for HTML and HTML Help pages. A file of that name
+# must exist either in Sphinx' static/ path, or in one of the custom paths
+# given in html_static_path.
+html_style = 'default.css'
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+html_title = "%s %s Documentation" % (project, release)
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+html_last_updated_fmt = '%m/%d/%Y %H:%M:%S'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+html_domain_indices = False
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, the reST sources are included in the HTML build as _sources/<name>.
+#html_copy_source = True
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# This is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = None
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Makodoc'
+
+#autoclass_content = 'both'
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'mako_%s.tex' % release.replace('.', '_'), ur'Mako Documentation',
+ ur'Mike Bayer', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+# sets TOC depth to 2.
+latex_preamble = '\setcounter{tocdepth}{3}'
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+#latex_elements = {
+# 'papersize': 'letterpaper',
+# 'pointsize': '10pt',
+#}
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'mako', u'Mako Documentation',
+ [u'Mako authors'], 1)
+]
+
+
+# -- Options for Epub output ---------------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = u'Mako'
+epub_author = u'Mako authors'
+epub_publisher = u'Mako authors'
+epub_copyright = u'Mako authors'
+
+# The language of the text. It defaults to the language option
+# or en if the language is not set.
+#epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+#epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#epub_identifier = ''
+
+# A unique identification for the text.
+#epub_uid = ''
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_pre_files = []
+
+# HTML files shat should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+#epub_exclude_files = []
+
+# The depth of the table of contents in toc.ncx.
+#epub_tocdepth = 3
+
+# Allow duplicate toc entries.
+#epub_tocdup = True
diff --git a/doc/build/defs.rst b/doc/build/defs.rst
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/doc/build/defs.rst
@@ -0,0 +1 @@
+
diff --git a/doc/build/filtering.rst b/doc/build/filtering.rst
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/doc/build/filtering.rst
@@ -0,0 +1 @@
+
diff --git a/doc/build/genhtml.py b/doc/build/genhtml.py
deleted file mode 100644
index b547dc6..0000000
--- a/doc/build/genhtml.py
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/usr/bin/env python
-import sys,re,os,shutil
-import cPickle as pickle
-
-sys.path = ['../../', './lib/'] + sys.path
-
-from mako.lookup import TemplateLookup
-from mako import exceptions, __version__ as version
-
-import read_markdown, toc
-
-files = [
- 'index',
- 'documentation',
- 'usage',
- 'syntax',
- 'defs',
- 'runtime',
- 'namespaces',
- 'inheritance',
- 'filtering',
- 'unicode',
- 'caching',
- ]
-
-title='Mako Documentation'
-
-root = toc.TOCElement('', 'root', '', version=version, doctitle=title)
-
-shutil.copy('./content/index.html', './output/index.html')
-shutil.copy('./content/documentation.html', './output/documentation.html')
-
-read_markdown.parse_markdown_files(root, files)
-
-pickle.dump(root, file('./output/table_of_contents.pickle', 'w'))
-
-template_dirs = ['./templates', './output']
-output = os.path.dirname(os.getcwd())
-
-lookup = TemplateLookup(template_dirs, output_encoding='utf-8')
-
-def genfile(name, toc):
- infile = name + ".html"
- outname = os.path.join(os.getcwd(), '../', name + ".html")
- outfile = file(outname, 'w')
- print infile, '->', outname
- outfile.write(lookup.get_template(infile).render())
-
-for filename in files:
- try:
- genfile(filename, root)
- except:
- print exceptions.text_error_template().render()
-
-
-
-
-
diff --git a/doc/build/index.rst b/doc/build/index.rst
new file mode 100644
index 0000000..827225b
--- /dev/null
+++ b/doc/build/index.rst
@@ -0,0 +1,21 @@
+Table of Contents
+=================
+
+.. toctree::
+ :maxdepth: 2
+
+ usage
+ syntax
+ defs
+ runtime
+ namespaces
+ inheritance
+ filtering
+ unicode
+ caching
+
+Indices and tables
+------------------
+
+* :ref:`genindex`
+* :ref:`search`
diff --git a/doc/build/inheritance.rst b/doc/build/inheritance.rst
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/doc/build/inheritance.rst
@@ -0,0 +1 @@
+
diff --git a/doc/build/lib/markdown.py b/doc/build/lib/markdown.py
deleted file mode 100644
index 20882eb..0000000
--- a/doc/build/lib/markdown.py
+++ /dev/null
@@ -1,1671 +0,0 @@
-#!/usr/bin/env python
-
-# The following constant specifies the name used in the usage
-# statement displayed for python versions lower than 2.3. (With
-# python2.3 and higher the usage statement is generated by optparse
-# and uses the actual name of the executable called.)
-
-EXECUTABLE_NAME_FOR_USAGE = "python markdown.py"
-
-SPEED_TEST = 0
-
-"""
-====================================================================
-IF YOA ARE LOOKING TO EXTEND MARKDOWN, SEE THE "FOOTNOTES" SECTION
-====================================================================
-
-Python-Markdown
-===============
-
-Converts Markdown to HTML. Basic usage as a module:
-
- import markdown
- html = markdown.markdown(your_text_string)
-
-Started by [Manfred Stienstra](http://www.dwerg.net/). Continued and
-maintained by [Yuri Takhteyev](http://www.freewisdom.org).
-
-Project website: http://www.freewisdom.org/projects/python-markdown
-Contact: yuri [at] freewisdom.org
-
-License: GPL 2 (http://www.gnu.org/copyleft/gpl.html) or BSD
-
-Version: 1.5a (July 9, 2006)
-
-For changelog, see end of file
-"""
-
-import re, sys, os, random, codecs
-
-# set debug level: 3 none, 2 critical, 1 informative, 0 all
-(VERBOSE, INFO, CRITICAL, NONE) = range(4)
-
-MESSAGE_THRESHOLD = CRITICAL
-
-def message(level, text) :
- if level >= MESSAGE_THRESHOLD :
- print text
-
-
-# --------------- CONSTANTS YOU MIGHT WANT TO MODIFY -----------------
-
-# all tabs will be expanded to up to this many spaces
-TAB_LENGTH = 4
-ENABLE_ATTRIBUTES = 1
-SMART_EMPHASIS = 1
-
-# --------------- CONSTANTS YOU _SHOULD NOT_ HAVE TO CHANGE ----------
-
-# a template for html placeholders
-HTML_PLACEHOLDER_PREFIX = "qaodmasdkwaspemas"
-HTML_PLACEHOLDER = HTML_PLACEHOLDER_PREFIX + "%dajkqlsmdqpakldnzsdfls"
-
-BLOCK_LEVEL_ELEMENTS = ['p', 'div', 'blockquote', 'pre', 'table',
- 'dl', 'ol', 'ul', 'script', 'noscript',
- 'form', 'fieldset', 'iframe', 'math', 'ins',
- 'del', 'hr', 'hr/', 'style']
-
-def is_block_level (tag) :
- return ( (tag in BLOCK_LEVEL_ELEMENTS) or
- (tag[0] == 'h' and tag[1] in "0123456789") )
-
-"""
-======================================================================
-========================== NANODOM ===================================
-======================================================================
-
-The three classes below implement some of the most basic DOM
-methods. I use this instead of minidom because I need a simpler
-functionality and do not want to require additional libraries.
-
-Importantly, NanoDom does not do normalization, which is what we
-want. It also adds extra white space when converting DOM to string
-"""
-
-
-class Document :
-
- def appendChild(self, child) :
- self.documentElement = child
- child.parent = self
- self.entities = {}
-
- def createElement(self, tag, textNode=None) :
- el = Element(tag)
- el.doc = self
- if textNode :
- el.appendChild(self.createTextNode(textNode))
- return el
-
- def createTextNode(self, text) :
- node = TextNode(text)
- node.doc = self
- return node
-
- def createEntityReference(self, entity):
- if entity not in self.entities:
- self.entities[entity] = EntityReference(entity)
- return self.entities[entity]
-
- def toxml (self) :
- return self.documentElement.toxml()
-
- def normalizeEntities(self, text) :
-
- pairs = [ ("&", "&amp;"),
- ("<", "&lt;"),
- (">", "&gt;"),
- ("\"", "&quot;")]
-
-
- for old, new in pairs :
- text = text.replace(old, new)
- return text
-
- def find(self, test) :
- return self.documentElement.find(test)
-
- def unlink(self) :
- self.documentElement.unlink()
- self.documentElement = None
-
-
-class Element :
-
- type = "element"
-
- def __init__ (self, tag) :
-
- self.nodeName = tag
- self.attributes = []
- self.attribute_values = {}
- self.childNodes = []
-
- def unlink(self) :
- for child in self.childNodes :
- if child.type == "element" :
- child.unlink()
- self.childNodes = None
-
- def setAttribute(self, attr, value) :
- if not attr in self.attributes :
- self.attributes.append(attr)
-
- self.attribute_values[attr] = value
-
- def insertChild(self, position, child) :
- self.childNodes.insert(position, child)
- child.parent = self
-
- def removeChild(self, child) :
- self.childNodes.remove(child)
-
- def replaceChild(self, oldChild, newChild) :
- position = self.childNodes.index(oldChild)
- self.removeChild(oldChild)
- self.insertChild(position, newChild)
-
- def appendChild(self, child) :
- self.childNodes.append(child)
- child.parent = self
-
- def handleAttributes(self) :
- pass
-
- def find(self, test, depth=0) :
- """ Returns a list of descendants that pass the test function """
- matched_nodes = []
- for child in self.childNodes :
- if test(child) :
- matched_nodes.append(child)
- if child.type == "element" :
- matched_nodes += child.find(test, depth+1)
- return matched_nodes
-
- def toxml(self):
- if ENABLE_ATTRIBUTES :
- for child in self.childNodes:
- child.handleAttributes()
- buffer = ""
- if self.nodeName in ['h1', 'h2', 'h3', 'h4'] :
- buffer += "\n"
- elif self.nodeName in ['li'] :
- buffer += "\n "
- buffer += "<" + self.nodeName
- for attr in self.attributes :
- value = self.attribute_values[attr]
- value = self.doc.normalizeEntities(value)
- buffer += ' %s="%s"' % (attr, value)
- if self.childNodes or self.nodeName in ['blockquote']:
- buffer += ">"
- for child in self.childNodes :
- buffer += child.toxml()
- if self.nodeName == 'p' :
- buffer += "\n"
- elif self.nodeName == 'li' :
- buffer += "\n "
- buffer += "</%s>" % self.nodeName
- else :
- buffer += "/>"
- if self.nodeName in ['p', 'li', 'ul', 'ol',
- 'h1', 'h2', 'h3', 'h4'] :
- buffer += "\n"
-
- return buffer
-
-
-class TextNode :
-
- type = "text"
- attrRegExp = re.compile(r'\{@([^\}]*)=([^\}]*)}') # {@id=123}
-
- def __init__ (self, text) :
- self.value = text
-
- def attributeCallback(self, match) :
- self.parent.setAttribute(match.group(1), match.group(2))
-
- def handleAttributes(self) :
- self.value = self.attrRegExp.sub(self.attributeCallback, self.value)
-
- def toxml(self) :
- text = self.value
- if not text.startswith(HTML_PLACEHOLDER_PREFIX):
- if self.parent.nodeName == "p" :
- text = text.replace("\n", "\n ")
- elif (self.parent.nodeName == "li"
- and self.parent.childNodes[0]==self):
- text = "\n " + text.replace("\n", "\n ")
- text = self.doc.normalizeEntities(text)
- return text
-
-
-class EntityReference:
-
- type = "entity_ref"
-
- def __init__(self, entity):
- self.entity = entity
-
- def handleAttributes(self):
- pass
-
- def toxml(self):
- return "&" + self.entity + ";"
-
-
-"""
-======================================================================
-========================== PRE-PROCESSORS ============================
-======================================================================
-
-Preprocessors munge source text before we start doing anything too
-complicated.
-
-Each preprocessor implements a "run" method that takes a pointer to a list of lines of the document,
-modifies it as necessary and returns either the same pointer or a
-pointer to a new list. Preprocessors must extend
-markdown.Preprocessor.
-
-"""
-
-
-class Preprocessor :
- pass
-
-
-class HeaderPreprocessor (Preprocessor):
-
- """
- Replaces underlined headers with hashed headers to avoid
- the nead for lookahead later.
- """
-
- def run (self, lines) :
-
- i = -1
- while i+1 < len(lines) :
- i = i+1
- if not lines[i].strip() :
- continue
-
- if lines[i].startswith("#") :
- lines.insert(i+1, "\n")
-
- if (i+1 <= len(lines)
- and lines[i+1]
- and lines[i+1][0] in ['-', '=']) :
-
- underline = lines[i+1].strip()
-
- if underline == "="*len(underline) :
- lines[i] = "# " + lines[i].strip()
- lines[i+1] = ""
- elif underline == "-"*len(underline) :
- lines[i] = "## " + lines[i].strip()
- lines[i+1] = ""
-
- #for l in lines :
- # print l.encode('utf8')
- #sys.exit(0)
-
- return lines
-
-HEADER_PREPROCESSOR = HeaderPreprocessor()
-
-class LinePreprocessor (Preprocessor):
- """Deals with HR lines (needs to be done before processing lists)"""
-
- def run (self, lines) :
- for i in range(len(lines)) :
- if self._isLine(lines[i]) :
- lines[i] = "<hr />"
- return lines
-
- def _isLine(self, block) :
- """Determines if a block should be replaced with an <HR>"""
- if block.startswith(" ") : return 0 # a code block
- text = "".join([x for x in block if not x.isspace()])
- if len(text) <= 2 :
- return 0
- for pattern in ['isline1', 'isline2', 'isline3'] :
- m = RE.regExp[pattern].match(text)
- if (m and m.group(1)) :
- return 1
- else:
- return 0
-
-LINE_PREPROCESSOR = LinePreprocessor()
-
-
-class LineBreaksPreprocessor (Preprocessor):
- """Replaces double spaces at the end of the lines with <br/ >."""
-
- def run (self, lines) :
- for i in range(len(lines)) :
- if (lines[i].endswith(" ")
- and not RE.regExp['tabbed'].match(lines[i]) ):
- lines[i] += "<br />"
- return lines
-
-LINE_BREAKS_PREPROCESSOR = LineBreaksPreprocessor()
-
-
-class HtmlBlockPreprocessor (Preprocessor):
- """Removes html blocks from self.lines"""
-
- def _get_left_tag(self, block):
- return block[1:].replace(">", " ", 1).split()[0].lower()
-
-
- def _get_right_tag(self, left_tag, block):
- return block.rstrip()[-len(left_tag)-2:-1].lower()
-
- def _equal_tags(self, left_tag, right_tag):
- if left_tag in ['?', '?php', 'div'] : # handle PHP, etc.
- return True
- if ("/" + left_tag) == right_tag:
- return True
- elif left_tag == right_tag[1:] \
- and right_tag[0] != "<":
- return True
- else:
- return False
-
- def _is_oneliner(self, tag):
- return (tag in ['hr', 'hr/'])
-
-
- def run (self, lines) :
- new_blocks = []
- text = "\n".join(lines)
- text = text.split("\n\n")
-
- items = []
- left_tag = ''
- right_tag = ''
- in_tag = False # flag
-
- for block in text:
- if block.startswith("\n") :
- block = block[1:]
-
- if not in_tag:
-
- if block.startswith("<"):
-
- left_tag = self._get_left_tag(block)
- right_tag = self._get_right_tag(left_tag, block)
-
- if not (is_block_level(left_tag) \
- or block[1] in ["!", "?", "@", "%"]):
- new_blocks.append(block)
- continue
-
- if self._is_oneliner(left_tag):
- new_blocks.append(block.strip())
- continue
-
- if block[1] == "!":
- # is a comment block
- left_tag = "--"
- right_tag = self._get_right_tag(left_tag, block)
- # keep checking conditions below and maybe just append
-
- if block.rstrip().endswith(">") \
- and self._equal_tags(left_tag, right_tag):
- new_blocks.append(
- self.stash.store(block.strip()))
- continue
- elif not block[1] == "!":
- # if is block level tag and is not complete
- items.append(block.strip())
- in_tag = True
- continue
-
- new_blocks.append(block)
-
- else:
- items.append(block.strip())
-
- right_tag = self._get_right_tag(left_tag, block)
- if self._equal_tags(left_tag, right_tag):
- # if find closing tag
- in_tag = False
- new_blocks.append(
- self.stash.store('\n\n'.join(items)))
- items = []
-
- return "\n\n".join(new_blocks).split("\n")
-
-HTML_BLOCK_PREPROCESSOR = HtmlBlockPreprocessor()
-
-
-class ReferencePreprocessor (Preprocessor):
-
- def run (self, lines) :
-
- new_text = [];
- for line in lines:
- m = RE.regExp['reference-def'].match(line)
- if m:
- id = m.group(2).strip().lower()
- t = m.group(4).strip() # potential title
- if not t :
- self.references[id] = (m.group(3), t)
- elif (len(t) >= 2
- and (t[0] == t[-1] == "\""
- or t[0] == t[-1] == "\'"
- or (t[0] == "(" and t[-1] == ")") ) ) :
- self.references[id] = (m.group(3), t[1:-1])
- else :
- new_text.append(line)
- else:
- new_text.append(line)
-
- return new_text #+ "\n"
-
-REFERENCE_PREPROCESSOR = ReferencePreprocessor()
-
-"""
-======================================================================
-========================== INLINE PATTERNS ===========================
-======================================================================
-
-Inline patterns such as *emphasis* are handled by means of auxiliary
-objects, one per pattern. Pattern objects must be instances of classes
-that extend markdown.Pattern. Each pattern object uses a single regular
-expression and needs support the following methods:
-
- pattern.getCompiledRegExp() - returns a regular expression
-
- pattern.handleMatch(m, doc) - takes a match object and returns
- a NanoDom node (as a part of the provided
- doc) or None
-
-All of python markdown's built-in patterns subclass from Patter,
-but you can add additional patterns that don't.
-
-Also note that all the regular expressions used by inline must
-capture the whole block. For this reason, they all start with
-'^(.*)' and end with '(.*)!'. In case with built-in expression
-Pattern takes care of adding the "^(.*)" and "(.*)!".
-
-Finally, the order in which regular expressions are applied is very
-important - e.g. if we first replace http://.../ links with <a> tags
-and _then_ try to replace inline html, we would end up with a mess.
-So, we apply the expressions in the following order:
-
- * escape and backticks have to go before everything else, so
- that we can preempt any markdown patterns by escaping them.
-
- * then we handle auto-links (must be done before inline html)
-
- * then we handle inline HTML. At this point we will simply
- replace all inline HTML strings with a placeholder and add
- the actual HTML to a hash.
-
- * then inline images (must be done before links)
-
- * then bracketed links, first regular then reference-style
-
- * finally we apply strong and emphasis
-"""
-
-NOBRACKET = r'[^\]\[]*'
-BRK = ( r'\[('
- + (NOBRACKET + r'(\['+NOBRACKET)*6
- + (NOBRACKET+ r'\])*'+NOBRACKET)*6
- + NOBRACKET + r')\]' )
-
-BACKTICK_RE = r'\`([^\`]*)\`' # `e= m*c^2`
-DOUBLE_BACKTICK_RE = r'\`\`(.*)\`\`' # ``e=f("`")``
-ESCAPE_RE = r'\\(.)' # \<
-EMPHASIS_RE = r'\*([^\*]*)\*' # *emphasis*
-STRONG_RE = r'\*\*(.*)\*\*' # **strong**
-STRONG_EM_RE = r'\*\*\*([^_]*)\*\*\*' # ***strong***
-
-if SMART_EMPHASIS:
- EMPHASIS_2_RE = r'(?<!\S)_(\S[^_]*)_' # _emphasis_
-else :
- EMPHASIS_2_RE = r'_([^_]*)_' # _emphasis_
-
-STRONG_2_RE = r'__([^_]*)__' # __strong__
-STRONG_EM_2_RE = r'___([^_]*)___' # ___strong___
-
-LINK_RE = BRK + r'\s*\(([^\)]*)\)' # [text](url)
-LINK_ANGLED_RE = BRK + r'\s*\(<([^\)]*)>\)' # [text](<url>)
-IMAGE_LINK_RE = r'\!' + BRK + r'\s*\(([^\)]*)\)' # ![alttxt](http://x.com/)
-REFERENCE_RE = BRK+ r'\s*\[([^\]]*)\]' # [Google][3]
-IMAGE_REFERENCE_RE = r'\!' + BRK + '\s*\[([^\]]*)\]' # ![alt text][2]
-NOT_STRONG_RE = r'( \* )' # stand-alone * or _
-AUTOLINK_RE = r'<(http://[^>]*)>' # <http://www.123.com>
-AUTOMAIL_RE = r'<([^> \!]*@[^> ]*)>' # <me@example.com>
-#HTML_RE = r'(\<[^\>]*\>)' # <...>
-HTML_RE = r'(\<[a-zA-Z/][^\>]*\>)' # <...>
-ENTITY_RE = r'(&[\#a-zA-Z0-9]*;)' # &amp;
-
-class Pattern:
-
- def __init__ (self, pattern) :
- self.pattern = pattern
- self.compiled_re = re.compile("^(.*)%s(.*)$" % pattern, re.DOTALL)
-
- def getCompiledRegExp (self) :
- return self.compiled_re
-
-BasePattern = Pattern # for backward compatibility
-
-class SimpleTextPattern (Pattern) :
-
- def handleMatch(self, m, doc) :
- return doc.createTextNode(m.group(2))
-
-class SimpleTagPattern (Pattern):
-
- def __init__ (self, pattern, tag) :
- Pattern.__init__(self, pattern)
- self.tag = tag
-
- def handleMatch(self, m, doc) :
- el = doc.createElement(self.tag)
- el.appendChild(doc.createTextNode(m.group(2)))
- return el
-
-class BacktickPattern (Pattern):
-
- def __init__ (self, pattern):
- Pattern.__init__(self, pattern)
- self.tag = "code"
-
- def handleMatch(self, m, doc) :
- el = doc.createElement(self.tag)
- text = m.group(2).strip()
- #text = text.replace("&", "&amp;")
- el.appendChild(doc.createTextNode(text))
- return el
-
-
-class DoubleTagPattern (SimpleTagPattern) :
-
- def handleMatch(self, m, doc) :
- tag1, tag2 = self.tag.split(",")
- el1 = doc.createElement(tag1)
- el2 = doc.createElement(tag2)
- el1.appendChild(el2)
- el2.appendChild(doc.createTextNode(m.group(2)))
- return el1
-
-
-class HtmlPattern (Pattern):
-
- def handleMatch (self, m, doc) :
- place_holder = self.stash.store(m.group(2))
- return doc.createTextNode(place_holder)
-
-
-class LinkPattern (Pattern):
-
- def handleMatch(self, m, doc) :
- el = doc.createElement('a')
- el.appendChild(doc.createTextNode(m.group(2)))
- parts = m.group(9).split()
- # We should now have [], [href], or [href, title]
- if parts :
- el.setAttribute('href', parts[0])
- else :
- el.setAttribute('href', "")
- if len(parts) > 1 :
- # we also got a title
- title = " ".join(parts[1:]).strip()
- title = dequote(title) #.replace('"', "&quot;")
- el.setAttribute('title', title)
- return el
-
-
-class ImagePattern (Pattern):
-
- def handleMatch(self, m, doc):
- el = doc.createElement('img')
- src_parts = m.group(9).split()
- el.setAttribute('src', src_parts[0])
- if len(src_parts) > 1 :
- el.setAttribute('title', dequote(" ".join(src_parts[1:])))
- if ENABLE_ATTRIBUTES :
- text = doc.createTextNode(m.group(2))
- el.appendChild(text)
- text.handleAttributes()
- truealt = text.value
- el.childNodes.remove(text)
- else:
- truealt = m.group(2)
- el.setAttribute('alt', truealt)
- return el
-
-class ReferencePattern (Pattern):
-
- def handleMatch(self, m, doc):
- if m.group(9) :
- id = m.group(9).lower()
- else :
- # if we got something like "[Google][]"
- # we'll use "google" as the id
- id = m.group(2).lower()
- if not self.references.has_key(id) : # ignore undefined refs
- return None
- href, title = self.references[id]
- text = m.group(2)
- return self.makeTag(href, title, text, doc)
-
- def makeTag(self, href, title, text, doc):
- el = doc.createElement('a')
- el.setAttribute('href', href)
- if title :
- el.setAttribute('title', title)
- el.appendChild(doc.createTextNode(text))
- return el
-
-
-class ImageReferencePattern (ReferencePattern):
-
- def makeTag(self, href, title, text, doc):
- el = doc.createElement('img')
- el.setAttribute('src', href)
- if title :
- el.setAttribute('title', title)
- el.setAttribute('alt', text)
- return el
-
-
-class AutolinkPattern (Pattern):
-
- def handleMatch(self, m, doc):
- el = doc.createElement('a')
- el.setAttribute('href', m.group(2))
- el.appendChild(doc.createTextNode(m.group(2)))
- return el
-
-class AutomailPattern (Pattern):
-
- def handleMatch(self, m, doc) :
- el = doc.createElement('a')
- email = m.group(2)
- if email.startswith("mailto:"):
- email = email[len("mailto:"):]
- for letter in email:
- entity = doc.createEntityReference("#%d" % ord(letter))
- el.appendChild(entity)
- mailto = "mailto:" + email
- mailto = "".join(['&#%d;' % ord(letter) for letter in mailto])
- el.setAttribute('href', mailto)
- return el
-
-ESCAPE_PATTERN = SimpleTextPattern(ESCAPE_RE)
-NOT_STRONG_PATTERN = SimpleTextPattern(NOT_STRONG_RE)
-
-BACKTICK_PATTERN = BacktickPattern(BACKTICK_RE)
-DOUBLE_BACKTICK_PATTERN = BacktickPattern(DOUBLE_BACKTICK_RE)
-STRONG_PATTERN = SimpleTagPattern(STRONG_RE, 'strong')
-STRONG_PATTERN_2 = SimpleTagPattern(STRONG_2_RE, 'strong')
-EMPHASIS_PATTERN = SimpleTagPattern(EMPHASIS_RE, 'em')
-EMPHASIS_PATTERN_2 = SimpleTagPattern(EMPHASIS_2_RE, 'em')
-
-STRONG_EM_PATTERN = DoubleTagPattern(STRONG_EM_RE, 'strong,em')
-STRONG_EM_PATTERN_2 = DoubleTagPattern(STRONG_EM_2_RE, 'strong,em')
-
-LINK_PATTERN = LinkPattern(LINK_RE)
-LINK_ANGLED_PATTERN = LinkPattern(LINK_ANGLED_RE)
-IMAGE_LINK_PATTERN = ImagePattern(IMAGE_LINK_RE)
-IMAGE_REFERENCE_PATTERN = ImageReferencePattern(IMAGE_REFERENCE_RE)
-REFERENCE_PATTERN = ReferencePattern(REFERENCE_RE)
-
-HTML_PATTERN = HtmlPattern(HTML_RE)
-ENTITY_PATTERN = HtmlPattern(ENTITY_RE)
-
-AUTOLINK_PATTERN = AutolinkPattern(AUTOLINK_RE)
-AUTOMAIL_PATTERN = AutomailPattern(AUTOMAIL_RE)
-
-
-"""
-======================================================================
-========================== POST-PROCESSORS ===========================
-======================================================================
-
-Markdown also allows post-processors, which are similar to
-preprocessors in that they need to implement a "run" method. Unlike
-pre-processors, they take a NanoDom document as a parameter and work
-with that.
-
-Post-Processor should extend markdown.Postprocessor.
-
-There are currently no standard post-processors, but the footnote
-extension below uses one.
-"""
-
-class Postprocessor :
- pass
-
-
-"""
-======================================================================
-========================== MISC AUXILIARY CLASSES ====================
-======================================================================
-"""
-
-class HtmlStash :
- """This class is used for stashing HTML objects that we extract
- in the beginning and replace with place-holders."""
-
- def __init__ (self) :
- self.html_counter = 0 # for counting inline html segments
- self.rawHtmlBlocks=[]
-
- def store(self, html) :
- """Saves an HTML segment for later reinsertion. Returns a
- placeholder string that needs to be inserted into the
- document.
-
- @param html: an html segment
- @returns : a placeholder string """
- self.rawHtmlBlocks.append(html)
- placeholder = HTML_PLACEHOLDER % self.html_counter
- self.html_counter += 1
- return placeholder
-
-
-class BlockGuru :
-
- def _findHead(self, lines, fn, allowBlank=0) :
-
- """Functional magic to help determine boundaries of indented
- blocks.
-
- @param lines: an array of strings
- @param fn: a function that returns a substring of a string
- if the string matches the necessary criteria
- @param allowBlank: specifies whether it's ok to have blank
- lines between matching functions
- @returns: a list of post processes items and the unused
- remainder of the original list"""
-
- items = []
- item = -1
-
- i = 0 # to keep track of where we are
-
- for line in lines :
-
- if not line.strip() and not allowBlank:
- return items, lines[i:]
-
- if not line.strip() and allowBlank:
- # If we see a blank line, this _might_ be the end
- i += 1
-
- # Find the next non-blank line
- for j in range(i, len(lines)) :
- if lines[j].strip() :
- next = lines[j]
- break
- else :
- # There is no more text => this is the end
- break
-
- # Check if the next non-blank line is still a part of the list
-
- part = fn(next)
-
- if part :
- items.append("")
- continue
- else :
- break # found end of the list
-
- part = fn(line)
-
- if part :
- items.append(part)
- i += 1
- continue
- else :
- return items, lines[i:]
- else :
- i += 1
-
- return items, lines[i:]
-
-
- def detabbed_fn(self, line) :
- """ An auxiliary method to be passed to _findHead """
- m = RE.regExp['tabbed'].match(line)
- if m:
- return m.group(4)
- else :
- return None
-
-
- def detectTabbed(self, lines) :
-
- return self._findHead(lines, self.detabbed_fn,
- allowBlank = 1)
-
-
-def print_error(string):
- """Print an error string to stderr"""
- sys.stderr.write(string +'\n')
-
-
-def dequote(string) :
- """ Removes quotes from around a string """
- if ( ( string.startswith('"') and string.endswith('"'))
- or (string.startswith("'") and string.endswith("'")) ) :
- return string[1:-1]
- else :
- return string
-
-"""
-======================================================================
-========================== CORE MARKDOWN =============================
-======================================================================
-
-This stuff is ugly, so if you are thinking of extending the syntax,
-see first if you can do it via pre-processors, post-processors,
-inline patterns or a combination of the three.
-"""
-
-class CorePatterns :
- """This class is scheduled for removal as part of a refactoring
- effort."""
-
- patterns = {
- 'header': r'(#*)([^#]*)(#*)', # # A title
- 'reference-def' : r'(\ ?\ ?\ ?)\[([^\]]*)\]:\s*([^ ]*)(.*)',
- # [Google]: http://www.google.com/
- 'containsline': r'([-]*)$|^([=]*)', # -----, =====, etc.
- 'ol': r'[ ]{0,3}[\d]*\.\s+(.*)', # 1. text
- 'ul': r'[ ]{0,3}[*+-]\s+(.*)', # "* text"
- 'isline1': r'(\**)', # ***
- 'isline2': r'(\-*)', # ---
- 'isline3': r'(\_*)', # ___
- 'tabbed': r'((\t)|( ))(.*)', # an indented line
- 'quoted' : r'> ?(.*)', # a quoted block ("> ...")
- }
-
- def __init__ (self) :
-
- self.regExp = {}
- for key in self.patterns.keys() :
- self.regExp[key] = re.compile("^%s$" % self.patterns[key],
- re.DOTALL)
-
- self.regExp['containsline'] = re.compile(r'^([-]*)$|^([=]*)$', re.M)
-
-RE = CorePatterns()
-
-
-class Markdown:
- """ Markdown formatter class for creating an html document from
- Markdown text """
-
-
- def __init__(self, source=None,
- extensions=[],
- extension_configs=None,
- encoding=None,
- safe_mode = True):
- """Creates a new Markdown instance.
-
- @param source: The text in Markdown format.
- @param encoding: The character encoding of <text>. """
-
- self.safeMode = safe_mode
- self.encoding = encoding
- self.source = source
- self.blockGuru = BlockGuru()
- self.registeredExtensions = []
- self.stripTopLevelTags = 1
- self.docType = ""
-
- self.preprocessors = [ HEADER_PREPROCESSOR,
- LINE_PREPROCESSOR,
- HTML_BLOCK_PREPROCESSOR,
- LINE_BREAKS_PREPROCESSOR,
- # A footnote preprocessor will
- # get inserted here
- REFERENCE_PREPROCESSOR ]
-
-
- self.postprocessors = [] # a footnote postprocessor will get
- # inserted later
-
- self.textPostprocessors = [] # a footnote postprocessor will get
- # inserted later
-
- self.prePatterns = []
-
-
- self.inlinePatterns = [ DOUBLE_BACKTICK_PATTERN,
- BACKTICK_PATTERN,
- ESCAPE_PATTERN,
- IMAGE_LINK_PATTERN,
- IMAGE_REFERENCE_PATTERN,
- REFERENCE_PATTERN,
- LINK_ANGLED_PATTERN,
- LINK_PATTERN,
- AUTOLINK_PATTERN,
- AUTOMAIL_PATTERN,
- HTML_PATTERN,
- ENTITY_PATTERN,
- NOT_STRONG_PATTERN,
- STRONG_EM_PATTERN,
- STRONG_EM_PATTERN_2,
- STRONG_PATTERN,
- STRONG_PATTERN_2,
- EMPHASIS_PATTERN,
- EMPHASIS_PATTERN_2
- # The order of the handlers matters!!!
- ]
-
- self.registerExtensions(extensions = extensions,
- configs = extension_configs)
-
- self.reset()
-
-
- def registerExtensions(self, extensions, configs) :
-
- if not configs :
- configs = {}
-
- for ext in extensions :
-
- extension_module_name = "mdx_" + ext
-
- try :
- module = __import__(extension_module_name)
-
- except :
- message(CRITICAL,
- "couldn't load extension %s (looking for %s module)"
- % (ext, extension_module_name) )
- else :
-
- if configs.has_key(ext) :
- configs_for_ext = configs[ext]
- else :
- configs_for_ext = []
- extension = module.makeExtension(configs_for_ext)
- extension.extendMarkdown(self, globals())
-
-
-
-
- def registerExtension(self, extension) :
- """ This gets called by the extension """
- self.registeredExtensions.append(extension)
-
- def reset(self) :
- """Resets all state variables so that we can start
- with a new text."""
- self.references={}
- self.htmlStash = HtmlStash()
-
- HTML_BLOCK_PREPROCESSOR.stash = self.htmlStash
- REFERENCE_PREPROCESSOR.references = self.references
- HTML_PATTERN.stash = self.htmlStash
- ENTITY_PATTERN.stash = self.htmlStash
- REFERENCE_PATTERN.references = self.references
- IMAGE_REFERENCE_PATTERN.references = self.references
-
- for extension in self.registeredExtensions :
- extension.reset()
-
-
- def _transform(self):
- """Transforms the Markdown text into a XHTML body document
-
- @returns: A NanoDom Document """
-
- # Setup the document
-
- self.doc = Document()
- self.top_element = self.doc.createElement("span")
- self.top_element.appendChild(self.doc.createTextNode('\n'))
- self.top_element.setAttribute('class', 'markdown')
- self.doc.appendChild(self.top_element)
-
- # Fixup the source text
- text = self.source.strip()
- text = text.replace("\r\n", "\n").replace("\r", "\n")
- text += "\n\n"
- text = text.expandtabs(TAB_LENGTH)
-
- # Split into lines and run the preprocessors that will work with
- # self.lines
-
- self.lines = text.split("\n")
-
- # Run the pre-processors on the lines
- for prep in self.preprocessors :
- self.lines = prep.run(self.lines)
-
- # Create a NanoDom tree from the lines and attach it to Document
-
-
- buffer = []
- for line in self.lines :
- if line.startswith("#") :
- self._processSection(self.top_element, buffer)
- buffer = [line]
- else :
- buffer.append(line)
- self._processSection(self.top_element, buffer)
-
- #self._processSection(self.top_element, self.lines)
-
- # Not sure why I put this in but let's leave it for now.
- self.top_element.appendChild(self.doc.createTextNode('\n'))
-
- # Run the post-processors
- for postprocessor in self.postprocessors :
- postprocessor.run(self.doc)
-
- return self.doc
-
-
- def _processSection(self, parent_elem, lines,
- inList = 0, looseList = 0) :
-
- """Process a section of a source document, looking for high
- level structural elements like lists, block quotes, code
- segments, html blocks, etc. Some those then get stripped
- of their high level markup (e.g. get unindented) and the
- lower-level markup is processed recursively.
-
- @param parent_elem: A NanoDom element to which the content
- will be added
- @param lines: a list of lines
- @param inList: a level
- @returns: None"""
-
- if not lines :
- return
-
- # Check if this section starts with a list, a blockquote or
- # a code block
-
- processFn = { 'ul' : self._processUList,
- 'ol' : self._processOList,
- 'quoted' : self._processQuote,
- 'tabbed' : self._processCodeBlock }
-
- for regexp in ['ul', 'ol', 'quoted', 'tabbed'] :
- m = RE.regExp[regexp].match(lines[0])
- if m :
- processFn[regexp](parent_elem, lines, inList)
- return
-
- # We are NOT looking at one of the high-level structures like
- # lists or blockquotes. So, it's just a regular paragraph
- # (though perhaps nested inside a list or something else). If
- # we are NOT inside a list, we just need to look for a blank
- # line to find the end of the block. If we ARE inside a
- # list, however, we need to consider that a sublist does not
- # need to be separated by a blank line. Rather, the following
- # markup is legal:
- #
- # * The top level list item
- #
- # Another paragraph of the list. This is where we are now.
- # * Underneath we might have a sublist.
- #
-
- if inList :
-
- start, theRest = self._linesUntil(lines, (lambda line:
- RE.regExp['ul'].match(line)
- or RE.regExp['ol'].match(line)
- or not line.strip()))
-
- self._processSection(parent_elem, start,
- inList - 1, looseList = looseList)
- self._processSection(parent_elem, theRest,
- inList - 1, looseList = looseList)
-
-
- else : # Ok, so it's just a simple block
-
- paragraph, theRest = self._linesUntil(lines, lambda line:
- not line.strip())
-
- if len(paragraph) and paragraph[0].startswith('#') :
- m = RE.regExp['header'].match(paragraph[0])
- if m :
- level = len(m.group(1))
- h = self.doc.createElement("h%d" % level)
- parent_elem.appendChild(h)
- for item in self._handleInlineWrapper2(m.group(2).strip()) :
- h.appendChild(item)
- else :
- message(CRITICAL, "We've got a problem header!")
-
- elif paragraph :
-
- list = self._handleInlineWrapper2("\n".join(paragraph))
-
- if ( parent_elem.nodeName == 'li'
- and not (looseList or parent_elem.childNodes)):
-
- #and not parent_elem.childNodes) :
- # If this is the first paragraph inside "li", don't
- # put <p> around it - append the paragraph bits directly
- # onto parent_elem
- el = parent_elem
- else :
- # Otherwise make a "p" element
- el = self.doc.createElement("p")
- parent_elem.appendChild(el)
-
- for item in list :
- el.appendChild(item)
-
- if theRest :
- theRest = theRest[1:] # skip the first (blank) line
-
- self._processSection(parent_elem, theRest, inList)
-
-
-
- def _processUList(self, parent_elem, lines, inList) :
- self._processList(parent_elem, lines, inList,
- listexpr='ul', tag = 'ul')
-
- def _processOList(self, parent_elem, lines, inList) :
- self._processList(parent_elem, lines, inList,
- listexpr='ol', tag = 'ol')
-
-
- def _processList(self, parent_elem, lines, inList, listexpr, tag) :
- """Given a list of document lines starting with a list item,
- finds the end of the list, breaks it up, and recursively
- processes each list item and the remainder of the text file.
-
- @param parent_elem: A dom element to which the content will be added
- @param lines: a list of lines
- @param inList: a level
- @returns: None"""
-
- ul = self.doc.createElement(tag) # ul might actually be '<ol>'
- parent_elem.appendChild(ul)
-
- looseList = 0
-
- # Make a list of list items
- items = []
- item = -1
-
- i = 0 # a counter to keep track of where we are
-
- for line in lines :
-
- loose = 0
- if not line.strip() :
- # If we see a blank line, this _might_ be the end of the list
- i += 1
- loose = 1
-
- # Find the next non-blank line
- for j in range(i, len(lines)) :
- if lines[j].strip() :
- next = lines[j]
- break
- else :
- # There is no more text => end of the list
- break
-
- # Check if the next non-blank line is still a part of the list
- if ( RE.regExp['ul'].match(next) or
- RE.regExp['ol'].match(next) or
- RE.regExp['tabbed'].match(next) ):
- # get rid of any white space in the line
- items[item].append(line.strip())
- looseList = loose or looseList
- continue
- else :
- break # found end of the list
-
- # Now we need to detect list items (at the current level)
- # while also detabing child elements if necessary
-
- for expr in ['ul', 'ol', 'tabbed']:
-
- m = RE.regExp[expr].match(line)
- if m :
- if expr in ['ul', 'ol'] : # We are looking at a new item
- if m.group(1) :
- items.append([m.group(1)])
- item += 1
- elif expr == 'tabbed' : # This line needs to be detabbed
- items[item].append(m.group(4)) #after the 'tab'
-
- i += 1
- break
- else :
- items[item].append(line) # Just regular continuation
- i += 1 # added on 2006.02.25
- else :
- i += 1
-
- # Add the dom elements
- for item in items :
- li = self.doc.createElement("li")
- ul.appendChild(li)
-
- self._processSection(li, item, inList + 1, looseList = looseList)
-
- # Process the remaining part of the section
-
- self._processSection(parent_elem, lines[i:], inList)
-
-
- def _linesUntil(self, lines, condition) :
- """ A utility function to break a list of lines upon the
- first line that satisfied a condition. The condition
- argument should be a predicate function.
- """
-
- i = -1
- for line in lines :
- i += 1
- if condition(line) : break
- else :
- i += 1
- return lines[:i], lines[i:]
-
- def _processQuote(self, parent_elem, lines, inList) :
- """Given a list of document lines starting with a quote finds
- the end of the quote, unindents it and recursively
- processes the body of the quote and the remainder of the
- text file.
-
- @param parent_elem: DOM element to which the content will be added
- @param lines: a list of lines
- @param inList: a level
- @returns: None """
-
- dequoted = []
- i = 0
- for line in lines :
- m = RE.regExp['quoted'].match(line)
- if m :
- dequoted.append(m.group(1))
- i += 1
- else :
- break
- else :
- i += 1
-
- blockquote = self.doc.createElement('blockquote')
- parent_elem.appendChild(blockquote)
-
- self._processSection(blockquote, dequoted, inList)
- self._processSection(parent_elem, lines[i:], inList)
-
-
-
-
- def _processCodeBlock(self, parent_elem, lines, inList) :
- """Given a list of document lines starting with a code block
- finds the end of the block, puts it into the dom verbatim
- wrapped in ("<pre><code>") and recursively processes the
- the remainder of the text file.
-
- @param parent_elem: DOM element to which the content will be added
- @param lines: a list of lines
- @param inList: a level
- @returns: None"""
-
- detabbed, theRest = self.blockGuru.detectTabbed(lines)
-
- pre = self.doc.createElement('pre')
- code = self.doc.createElement('code')
- parent_elem.appendChild(pre)
- pre.appendChild(code)
- text = "\n".join(detabbed).rstrip()+"\n"
- #text = text.replace("&", "&amp;")
- code.appendChild(self.doc.createTextNode(text))
- self._processSection(parent_elem, theRest, inList)
-
-
- def _handleInlineWrapper2 (self, line) :
-
-
- parts = [line]
-
- #if not(line):
- # return [self.doc.createTextNode(' ')]
-
- for pattern in self.inlinePatterns :
-
- #print
- #print self.inlinePatterns.index(pattern)
-
- i = 0
-
- #print parts
- while i < len(parts) :
-
- x = parts[i]
- #print i
- if isinstance(x, (str, unicode)) :
- result = self._applyPattern(x, pattern)
- #print result
- #print result
- #print parts, i
- if result :
- i -= 1
- parts.remove(x)
- for y in result :
- parts.insert(i+1,y)
-
- i += 1
-
- for i in range(len(parts)) :
- x = parts[i]
- if isinstance(x, (str, unicode)) :
- parts[i] = self.doc.createTextNode(x)
-
- return parts
-
-
-
- def _handleInlineWrapper (self, line) :
-
- # A wrapper around _handleInline to avoid recursion
-
- parts = [line]
-
- i = 0
-
- while i < len(parts) :
- x = parts[i]
- if isinstance(x, (str, unicode)) :
- parts.remove(x)
- result = self._handleInline(x)
- for y in result :
- parts.insert(i,y)
- else :
- i += 1
-
- return parts
-
- def _handleInline(self, line):
- """Transform a Markdown line with inline elements to an XHTML
- fragment.
-
- This function uses auxiliary objects called inline patterns.
- See notes on inline patterns above.
-
- @param item: A block of Markdown text
- @return: A list of NanoDom nodes """
-
- if not(line):
- return [self.doc.createTextNode(' ')]
-
- for pattern in self.inlinePatterns :
- list = self._applyPattern( line, pattern)
- if list: return list
-
- return [self.doc.createTextNode(line)]
-
- def _applyPattern(self, line, pattern) :
- """ Given a pattern name, this function checks if the line
- fits the pattern, creates the necessary elements, and returns
- back a list consisting of NanoDom elements and/or strings.
-
- @param line: the text to be processed
- @param pattern: the pattern to be checked
-
- @returns: the appropriate newly created NanoDom element if the
- pattern matches, None otherwise.
- """
-
- # match the line to pattern's pre-compiled reg exp.
- # if no match, move on.
-
- m = pattern.getCompiledRegExp().match(line)
- if not m :
- return None
-
- # if we got a match let the pattern make us a NanoDom node
- # if it doesn't, move on
- node = pattern.handleMatch(m, self.doc)
-
- if node :
- # Those are in the reverse order!
- return ( m.groups()[-1], # the string to the left
- node, # the new node
- m.group(1)) # the string to the right of the match
-
- else :
- return None
-
- def __str__(self, source = None):
- """Return the document in XHTML format.
-
- @returns: A serialized XHTML body."""
- #try :
-
- if source :
- self.source = source
-
- doc = self._transform()
- xml = doc.toxml()
-
- #finally:
- # doc.unlink()
-
- # Let's stick in all the raw html pieces
-
- for i in range(self.htmlStash.html_counter) :
- html = self.htmlStash.rawHtmlBlocks[i]
- if self.safeMode :
- html = "[HTML_REMOVED]"
-
- xml = xml.replace("<p>%s\n</p>" % (HTML_PLACEHOLDER % i),
- html + "\n")
- xml = xml.replace(HTML_PLACEHOLDER % i,
- html)
-
- # And return everything but the top level tag
-
- if self.stripTopLevelTags :
- xml = xml.strip()[23:-7] + "\n"
-
- for pp in self.textPostprocessors :
- xml = pp.run(xml)
-
- return self.docType + xml
-
-
- toString = __str__
-
-
- def __unicode__(self):
- """Return the document in XHTML format as a Unicode object.
- """
- return str(self)#.decode(self.encoding)
-
-
- toUnicode = __unicode__
-
-
-
-
-# ====================================================================
-
-def markdownFromFile(input = None,
- output = None,
- extensions = [],
- encoding = None,
- message_threshold = CRITICAL,
- safe = False) :
-
- global MESSAGE_THRESHOLD
- MESSAGE_THRESHOLD = message_threshold
-
- message(VERBOSE, "input file: %s" % input)
-
-
- if not encoding :
- encoding = "utf-8"
-
- input_file = codecs.open(input, mode="r", encoding="utf-8")
- text = input_file.read()
- input_file.close()
-
- new_text = markdown(text, extensions, encoding, safe_mode = safe)
-
- if output :
- output_file = codecs.open(output, "w", encoding=encoding)
- output_file.write(new_text)
- output_file.close()
-
- else :
- sys.stdout.write(new_text.encode(encoding))
-
-def markdown(text,
- extensions = [],
- encoding = None,
- safe_mode = False) :
-
- message(VERBOSE, "in markdown.markdown(), received text:\n%s" % text)
-
- extension_names = []
- extension_configs = {}
-
- for ext in extensions :
- pos = ext.find("(")
- if pos == -1 :
- extension_names.append(ext)
- else :
- name = ext[:pos]
- extension_names.append(name)
- pairs = [x.split("=") for x in ext[pos+1:-1].split(",")]
- configs = [(x.strip(), y.strip()) for (x, y) in pairs]
- extension_configs[name] = configs
- #print configs
-
- md = Markdown(text, extensions=extension_names,
- extension_configs=extension_configs,
- safe_mode = safe_mode)
-
- return md.toString()
-
-
-class Extension :
-
- def __init__(self, configs = {}) :
- self.config = configs
-
- def getConfig(self, key) :
- if self.config.has_key(key) :
- #print self.config[key][0]
- return self.config[key][0]
- else :
- return ""
-
- def getConfigInfo(self) :
- return [(key, self.config[key][1]) for key in self.config.keys()]
-
- def setConfig(self, key, value) :
- self.config[key][0] = value
-
-
-OPTPARSE_WARNING = """
-Python 2.3 or higher required for advanced command line options.
-For lower versions of Python use:
-
- %s INPUT_FILE > OUTPUT_FILE
-
-""" % EXECUTABLE_NAME_FOR_USAGE
-
-def parse_options() :
-
- try :
- optparse = __import__("optparse")
- except :
- if len(sys.argv) == 2 :
- return {'input' : sys.argv[1],
- 'output' : None,
- 'message_threshold' : CRITICAL,
- 'safe' : False,
- 'extensions' : [],
- 'encoding' : None }
-
- else :
- print OPTPARSE_WARNING
- return None
-
- parser = optparse.OptionParser(usage="%prog INPUTFILE [options]")
-
- parser.add_option("-f", "--file", dest="filename",
- help="write output to OUTPUT_FILE",
- metavar="OUTPUT_FILE")
- parser.add_option("-e", "--encoding", dest="encoding",
- help="encoding for input and output files",)
- parser.add_option("-q", "--quiet", default = CRITICAL,
- action="store_const", const=NONE, dest="verbose",
- help="suppress all messages")
- parser.add_option("-v", "--verbose",
- action="store_const", const=INFO, dest="verbose",
- help="print info messages")
- parser.add_option("-s", "--safe",
- action="store_const", const=True, dest="safe",
- help="same mode (strip user's HTML tag)")
-
- parser.add_option("--noisy",
- action="store_const", const=VERBOSE, dest="verbose",
- help="print debug messages")
- parser.add_option("-x", "--extension", action="append", dest="extensions",
- help = "load extension EXTENSION", metavar="EXTENSION")
-
- (options, args) = parser.parse_args()
-
- if not len(args) == 1 :
- parser.print_help()
- return None
- else :
- input_file = args[0]
-
- if not options.extensions :
- options.extensions = []
-
- return {'input' : input_file,
- 'output' : options.filename,
- 'message_threshold' : options.verbose,
- 'safe' : options.safe,
- 'extensions' : options.extensions,
- 'encoding' : options.encoding }
-
-if __name__ == '__main__':
- """ Run Markdown from the command line. """
-
- options = parse_options()
-
- #if os.access(inFile, os.R_OK):
-
- if not options :
- sys.exit(0)
-
- markdownFromFile(**options)
-
-
-
-
-
-
-
-
-
-
diff --git a/doc/build/lib/toc.py b/doc/build/lib/toc.py
deleted file mode 100644
index 4f9742f..0000000
--- a/doc/build/lib/toc.py
+++ /dev/null
@@ -1,78 +0,0 @@
-"""
-defines a pickleable, recursive "table of contents" datastructure.
-
-TOCElements define a name, a description, and also a uniquely-identifying "path" which is
-used to generate hyperlinks between document sections.
-"""
-import time, re
-
-toc_by_file = {}
-toc_by_path = {}
-filenames = []
-
-class TOCElement(object):
- def __init__(self, filename, name, description, parent=None, version=None, last_updated=None, doctitle=None, **kwargs):
- self.filename = filename
- self.name = re.sub(r'[<>&;%]', '', name)
- self.description = description
- self.parent = parent
- self.content = None
- self.filenames = filenames
- self.toc_by_path = toc_by_path
- self.toc_by_file = toc_by_file
- self.last_updated = time.time()
- self.version = version
- self.doctitle = doctitle
- (self.path, self.depth) = self._create_path()
- #print "NEW TOC:", self.path
- for key, value in kwargs.iteritems():
- setattr(self, key, value)
-
- toc_by_path[self.path] = self
-
- self.is_top = (self.parent is not None and self.parent.filename != self.filename) or self.parent is None
- if self.is_top:
- toc_by_file[self.filename] = self
- if self.filename:
- filenames.append(self.filename)
-
- self.root = self.parent or self
-
- self.content = None
- self.previous = None
- self.next = None
- self.children = []
- if parent:
- if len(parent.children):
- self.previous = parent.children[-1]
- parent.children[-1].next = self
- parent.children.append(self)
-
- def get_page_root(self):
- return self.toc_by_file[self.filename]
-
- def get_by_path(self, path):
- return self.toc_by_path.get(path)
-
- def get_by_file(self, filename):
- return self.toc_by_file[filename]
-
- def get_link(self, extension='html', anchor=True, usefilename=True):
- if usefilename:
- if anchor:
- return "%s.%s#%s" % (self.filename, extension, self.path)
- else:
- return "%s.%s" % (self.filename, extension)
- else:
- return "#%s" % (self.path)
-
-
- def _create_path(self):
- elem = self
- tokens = []
- depth = 0
- while elem.parent is not None:
- tokens.insert(0, elem.name)
- elem = elem.parent
- depth +=1
- return ('_'.join(tokens), depth)
diff --git a/doc/build/namespaces.rst b/doc/build/namespaces.rst
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/doc/build/namespaces.rst
@@ -0,0 +1 @@
+
diff --git a/doc/build/read_markdown.py b/doc/build/read_markdown.py
deleted file mode 100644
index 9a533ed..0000000
--- a/doc/build/read_markdown.py
+++ /dev/null
@@ -1,213 +0,0 @@
-"""loads Markdown files, converts each one to HTML and parses the HTML into an ElementTree structure.
-The collection of ElementTrees are further parsed to generate a table of contents structure, and are
- manipulated to replace various markdown-generated HTML with specific Mako tags before being written
- to Mako templates, which then re-access the table of contents structure at runtime.
-
-Much thanks to Alexey Shamrin, who came up with the original idea and did all the heavy Markdown/Elementtree
-lifting for this module."""
-import sys, re, os
-from toc import TOCElement
-
-try:
- import xml.etree.ElementTree as et
-except:
- try:
- import elementtree.ElementTree as et
- except:
- raise "This module requires ElementTree to run (http://effbot.org/zone/element-index.htm)"
-
-import markdown
-
-def dump_tree(elem, stream):
- if elem.tag.startswith('MAKO:'):
- dump_mako_tag(elem, stream)
- else:
- if elem.tag != 'html':
- if len(elem.attrib):
- stream.write("<%s %s>" % (elem.tag, " ".join(["%s=%s" % (key, repr(val)) for key, val in elem.attrib.iteritems()])))
- else:
- stream.write("<%s>" % elem.tag)
- if elem.text:
- stream.write(elem.text)
- for child in elem:
- dump_tree(child, stream)
- if child.tail:
- stream.write(child.tail)
- stream.write("</%s>" % elem.tag)
-
-def dump_mako_tag(elem, stream):
- tag = elem.tag[5:]
- params = ','.join(['%s=%s' % i for i in elem.items()])
- stream.write('<%%call expr="%s(%s)">' % (tag, params))
- if elem.text:
- stream.write(elem.text)
- for n in elem:
- dump_tree(n, stream)
- if n.tail:
- stream.write(n.tail)
- stream.write("</%call>")
-
-def create_toc(filename, tree, tocroot):
- title = [None]
- current = [tocroot]
- level = [0]
- def process(tree):
- while True:
- i = find_header_index(tree)
- if i is None:
- return
- node = tree[i]
- taglevel = int(node.tag[1])
- start, end = i, end_of_header(tree, taglevel, i+1)
- content = tree[start+1:end]
- description = node.text.strip()
- if title[0] is None:
- title[0] = description
- name = node.get('name')
- if name is None:
- name = description.split()[0].lower()
-
- taglevel = node.tag[1]
- if taglevel > level[0]:
- current[0] = TOCElement(filename, name, description, current[0])
- elif taglevel == level[0]:
- current[0] = TOCElement(filename, name, description, current[0].parent)
- else:
- current[0] = TOCElement(filename, name, description, current[0].parent.parent)
-
- level[0] = taglevel
-
- tag = et.Element("MAKO:formatting.section", path=repr(current[0].path), paged='paged', extension='extension', toc='toc')
- tag.text = (node.tail or "") + '\n'
- tag.tail = '\n'
- tag[:] = content
- tree[start:end] = [tag]
-
- process(tag)
-
- process(tree)
- return (title[0], tocroot.get_by_file(filename))
-
-def index(parent, item):
- for n, i in enumerate(parent):
- if i is item:
- return n
-
-def find_header_index(tree):
- for i, node in enumerate(tree):
- if is_header(node):
- return i
-
-def is_header(node):
- t = node.tag
- return (isinstance(t, str) and len(t) == 2 and t[0] == 'h'
- and t[1] in '123456789')
-
-def end_of_header(tree, level, start):
- for i, node in enumerate(tree[start:]):
- if is_header(node) and int(node.tag[1]) <= level:
- return start + i
- return len(tree)
-
-def process_rel_href(tree):
- parent = get_parent_map(tree)
- for a in tree.findall('.//a'):
- m = re.match(r'(bold)?rel\:(.+)', a.get('href'))
- if m:
- (bold, path) = m.group(1,2)
- text = a.text
- if text == path:
- tag = et.Element("MAKO:nav.toclink", path=repr(path), extension='extension', paged='paged', toc='toc')
- else:
- tag = et.Element("MAKO:nav.toclink", path=repr(path), description=repr(text), extension='extension', paged='paged', toc='toc')
- a_parent = parent[a]
- if bold:
- bold = et.Element('strong')
- bold.tail = a.tail
- bold.append(tag)
- a_parent[index(a_parent, a)] = bold
- else:
- tag.tail = a.tail
- a_parent[index(a_parent, a)] = tag
-
-def replace_pre_with_mako(tree):
- parents = get_parent_map(tree)
-
- for precode in tree.findall('.//pre/code'):
- reg = re.compile(r'\{(python|mako|html|ini)(?: title="(.*?)"){0,1}\}(.*)', re.S)
- m = reg.match(precode[0].text.lstrip())
- if m:
- code = m.group(1)
- title = m.group(2)
- precode[0].text = m.group(3)
- else:
- code = title = None
-
- tag = et.Element("MAKO:formatting.code")
- if code:
- tag.attrib["syntaxtype"] = repr(code)
- if title:
- tag.attrib["title"] = repr(title)
- tag.text = precode.text
- [tag.append(x) for x in precode]
- pre = parents[precode]
- tag.tail = pre.tail
-
- pre_parent = parents[pre]
- pre_parent[reverse_parent(pre_parent, pre)] = tag
-
-def safety_code(tree):
- parents = get_parent_map(tree)
- for code in tree.findall('.//code'):
- tag = et.Element('%text')
- if parents[code].tag != 'pre':
- tag.attrib["filter"] = "h"
- tag.text = code.text
- code.append(tag)
- code.text = ""
-
-def reverse_parent(parent, item):
- for n, i in enumerate(parent):
- if i is item:
- return n
-
-def get_parent_map(tree):
- return dict([(c, p) for p in tree.getiterator() for c in p])
-
-def header(toc, title, filename):
- return """# -*- coding: utf-8 -*-
-<%%inherit file="content_layout.html"/>
-<%%page args="toc, extension, paged"/>
-<%%namespace name="formatting" file="formatting.html"/>
-<%%namespace name="nav" file="nav.html"/>
-<%%def name="title()">%s - %s</%%def>
-<%%!
- filename = '%s'
-%%>
-## This file is generated. Edit the .txt files instead of this one.
-""" % (toc.root.doctitle, title, filename)
-
-class utf8stream(object):
- def __init__(self, stream):
- self.stream = stream
- def write(self, str):
- self.stream.write(str.encode('utf8'))
-
-def parse_markdown_files(toc, files):
- for inname in files:
- infile = 'content/%s.txt' % inname
- if not os.access(infile, os.F_OK):
- continue
- html = markdown.markdown(file(infile).read())
- tree = et.fromstring("<html>" + html + "</html>")
- (title, toc_element) = create_toc(inname, tree, toc)
- safety_code(tree)
- replace_pre_with_mako(tree)
- process_rel_href(tree)
- outname = 'output/%s.html' % inname
- print infile, '->', outname
- outfile = utf8stream(file(outname, 'w'))
- outfile.write(header(toc, title, inname))
- dump_tree(tree, outfile)
-
-
diff --git a/doc/build/runtime.rst b/doc/build/runtime.rst
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/doc/build/runtime.rst
@@ -0,0 +1 @@
+
diff --git a/doc/build/static/docs.css b/doc/build/static/docs.css
new file mode 100644
index 0000000..f886e02
--- /dev/null
+++ b/doc/build/static/docs.css
@@ -0,0 +1,288 @@
+/* documentation section styles */
+
+body, td {
+ font-family: Tahoma,Geneva,sans-serif;
+}
+
+body {
+ background-color: #FDFBFC;
+ margin:38px;
+ color:#333333;
+}
+
+form {
+ display:inline;
+}
+
+p {
+ margin-top:10px;
+ margin-bottom:10px;
+}
+
+
+a {
+ font-weight:normal;
+ text-decoration:none;
+}
+a:link {color:#0000FF;}
+a:visited {color:#0000FF;}
+a:active {color:#0000FF;}
+a:hover {color:#700000;}
+
+
+strong a {
+ font-weight: bold;
+}
+
+#search {
+ float:right;
+}
+
+#searchform {
+ padding:20px;
+}
+
+#pagecontrol {
+ float:right;
+}
+
+.topnav {
+ background-color: #eeeeee;
+ border: solid 1px #ccc;
+ padding:10px;
+ margin:10px 0px 10px 0px;
+}
+
+.bottomnav {
+ background-color: #eeeeee;
+ border:1px solid #CCCCCC;
+ float:right;
+ margin: 1em 0 1em 5px;
+ padding:10px;
+}
+
+.document {
+ border: solid 1px #ccc;
+}
+
+.topnav .prevnext {
+ padding: 5px 0px 0px 0px;
+ /*font-size: 0.8em*/
+}
+
+h1, h2, h3, h4, h5 {
+ font-weight:bold;
+}
+
+h1 {
+ font-size:1.6em;
+ font-weight:bold;
+}
+.document h1, .document h2, .document h3, .document h4, .document h5 {
+ font-size: 1.2em;
+}
+
+.document img {
+ display:block;
+ margin: 0 auto;
+}
+
+.document h1 {
+ display:none;
+}
+
+.topnav h2 {
+ margin:26px 4px 0px 5px;
+ font-size:1.6em;
+ font-weight:normal;
+ line-height:1.6em;
+}
+
+.topnav h3 {
+ font-weight: bold;
+ font-size: 1.4em;
+ margin:0px;
+ display:inline;
+}
+
+.topnav li,
+li.toctree-l1,
+li.toctree-l1 li
+{
+ list-style-type:disc;
+ margin:0px;
+ padding:1px 8px;
+}
+
+
+.topnav li ul,
+li.toctree-l1 ul
+{
+ padding:0px 0px 0px 20px;
+}
+
+.topnav li ul li li,
+li.toctree-l1 ul li li
+{
+ /*font-size:.90em;*/
+}
+
+.sourcelink {
+ font-size:.8em;
+ text-align:right;
+ padding-top:10px;
+}
+
+.section {
+ line-height: 1.5em;
+ padding:8px 10px 20px 10px;
+ margin:10px 0px 0px;
+}
+
+.section .section {
+ margin:0px 0px 0px 0px;
+ padding: 0px;
+}
+
+.section .section .section {
+ margin:0px 0px 0px 20px;
+}
+
+.section .section .section .section {
+ margin:0px 0px 0px 20px;
+}
+
+th.field-name {
+ text-align:right;
+}
+
+div.note, div.warning, p.deprecated {
+ background-color:#EEFFEF;
+}
+
+
+div.admonition, div.topic, p.deprecated {
+ border:1px solid #CCCCCC;
+ margin:5px 5px 5px 5px;
+ padding:5px 5px 5px 35px;
+ font-size:.9em;
+}
+
+div.warning .admonition-title {
+ color:#FF0000;
+}
+
+div.admonition .admonition-title {
+ font-weight:bold;
+}
+
+
+.totoc {
+
+}
+
+.doc_copyright {
+ font-size:.85em;
+ padding:10px 0px 10px 0px;
+}
+
+pre {
+ background-color: #f0f0f0;
+ border: solid 1px #ccc;
+ padding:10px;
+ margin: 5px 5px 5px 5px;
+ overflow:auto;
+ line-height:1.3em;
+}
+
+.versionheader {
+ margin-top: 0.5em;
+}
+.versionnum {
+ font-weight: bold;
+}
+
+.viewcode-back, .viewcode-link {
+ float:right;
+}
+.prerelease {
+ border: solid #c25757 2px;
+ border-radius: 4px;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ background-color: #c21a1a;
+ color: white;
+ padding: 0.05em 0.2em;
+}
+
+dl.function > dt,
+dl.attribute > dt,
+dl.classmethod > dt,
+dl.method > dt,
+dl.class > dt,
+dl.exception > dt
+{
+ background-color:#F0F0F0;
+ margin:0px -10px;
+ padding: 0px 10px;
+}
+
+
+dt:target, span.highlight {
+ background-color:#FBE54E;
+}
+
+a.headerlink {
+ font-size: 0.8em;
+ padding: 0 4px 0 4px;
+ text-decoration: none;
+ visibility: hidden;
+}
+
+h1:hover > a.headerlink,
+h2:hover > a.headerlink,
+h3:hover > a.headerlink,
+h4:hover > a.headerlink,
+h5:hover > a.headerlink,
+h6:hover > a.headerlink,
+dt:hover > a.headerlink {
+ visibility: visible;
+}
+
+a.headerlink:hover {
+ background-color: #00f;
+ color: white;
+}
+
+.clearboth {
+ clear:both;
+}
+
+tt.descname {
+ background-color:transparent;
+ font-size:1.2em;
+ font-weight:bold;
+}
+
+tt.descclassname {
+ background-color:transparent;
+}
+
+tt {
+ background-color:#ECF0F3;
+ padding:0 1px;
+}
+
+@media print {
+ #nav { display: none; }
+ #pagecontrol { display: none; }
+ .topnav .prevnext { display: none; }
+ .bottomnav { display: none; }
+ .totoc { display: none; }
+ .topnav ul li a { text-decoration: none; color: #000; }
+}
+
+/* syntax highlighting overrides */
+.k, .kn {color:#0908CE;}
+.o {color:#BF0005;}
+.go {color:#804049;}
diff --git a/doc/build/syntax.rst b/doc/build/syntax.rst
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/doc/build/syntax.rst
@@ -0,0 +1 @@
+
diff --git a/doc/build/templates/autohandler b/doc/build/templates/autohandler
deleted file mode 100644
index d454f5d..0000000
--- a/doc/build/templates/autohandler
+++ /dev/null
@@ -1,21 +0,0 @@
-<html>
-<head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <title>${self.title()}</title>
- ${self.style()}
-<%def name="style()">
-</%def>
-
-</head>
-<body>
-${next.body()}
-
-</body>
-</html>
-
-
-<%def name="title()">
-Documentation
-</%def>
-
-
diff --git a/doc/build/templates/base.html b/doc/build/templates/base.html
deleted file mode 100644
index ce65865..0000000
--- a/doc/build/templates/base.html
+++ /dev/null
@@ -1,46 +0,0 @@
-<%!
- from mako.ext.autohandler import autohandler
-%>
-<%inherit file="${autohandler(template, context)}"/>
-<%page cached="False" cache_key="${self.filename}"/>
-
-<%def name="style()">
- <link rel="stylesheet" href="docs.css"></link>
- <link rel="stylesheet" href="highlight.css"></link>
- ${parent.style()}
-</%def>
-
-<%doc>
- base.html - common to all documentation pages. intentionally separate
- from autohandler, which can be swapped out for a different one
-</%doc>
-
-<%
- # bootstrap TOC structure from request args, or pickled file if not present.
- import cPickle as pickle
- import os, time
- print "%s generating from table of contents for file %s" % (local.filename, self.filename)
- filename = os.path.join(os.path.dirname(self.filename), 'table_of_contents.pickle')
- toc = pickle.load(file(filename))
- version = toc.version
- last_updated = toc.last_updated
-
- kwargs = context.kwargs
- kwargs.setdefault('extension', 'html')
- extension = kwargs['extension']
- kwargs.setdefault('paged', True)
- kwargs.setdefault('toc', toc)
-%>
-
-<div id="topanchor"><a name="top">&nbsp;</a></div>
-
-<div id="pagecontrol"><a href="index.${extension}">Multiple Pages</a> | <a href="documentation.${extension}">One Page</a></div>
-
-<h1>${toc.root.doctitle}</h1>
-
-<div class="versionheader">Version: ${version} Last Updated: ${time.strftime('%x %X', time.localtime(last_updated))}</div>
-
-${next.body(**kwargs)}
-
-
-
diff --git a/doc/build/templates/content_layout.html b/doc/build/templates/content_layout.html
deleted file mode 100644
index 5dfe6b7..0000000
--- a/doc/build/templates/content_layout.html
+++ /dev/null
@@ -1,16 +0,0 @@
-## defines the default layout for normal documentation pages (not including the index)
-<%inherit file="base.html"/>
-<%page args="toc, extension, paged"/>
-<%namespace file="nav.html" import="topnav, pagenav"/>
-
-<%
- current = toc.get_by_file(self.template.module.filename)
-%>
-
-<A name="<% current.path %>"></a>
-
-${topnav(item=current, toc=toc, extension=extension, paged=paged)}
-
-${next.body(toc=toc, extension=extension, paged=paged)}
-
-${pagenav(item=current, extension=extension, paged=paged)} \ No newline at end of file
diff --git a/doc/build/templates/formatting.html b/doc/build/templates/formatting.html
deleted file mode 100644
index 82dd12b..0000000
--- a/doc/build/templates/formatting.html
+++ /dev/null
@@ -1,83 +0,0 @@
-## formatting.myt - Provides section formatting elements, syntax-highlighted code blocks, and other special filters.
-<%!
- import string, re, cgi
- from mako import filters
-
- def plainfilter(f):
- f = re.sub(r'\n[\s\t]*\n[\s\t]*', '</p>\n<p>', f)
- f = "<p>" + f + "</p>"
- return f
-
-%>
-
-<%namespace name="nav" file="nav.html"/>
-
-<%def name="section(toc, path, paged, extension, description=None)">
- ## Main section formatting element.
- <%
- item = toc.get_by_path(path)
- subsection = item.depth > 1
- %>
- <A name="${item.path}"></a>
-
- <div class="${subsection and 'subsection' or 'section'}">
- <%
- content = capture(caller.body)
- %>
-
- <h3>${description or item.description}</h3>
-
- ${content}
-
- % if (subsection and item.next and item.next.depth >= item.depth) or not subsection:
- % if paged:
- <a href="#top">back to section top</a>
- % else:
- <a href="#${item.get_page_root().path}">back to section top</a>
- % endif
- % endif
- </div>
-
-</%def>
-
-
-<%def name="formatplain()" filter="plainfilter">
- ${ caller.body() | h}
-</%def>
-
-
-<%def name="codeline()" filter="trim,h">
- <span class="codeline">${ caller.body() }</span>
-</%def>
-
-<%def name="code(title=None, syntaxtype='mako', html_escape=False, use_sliders=False)">
- <%!
- import pygments
- from pygments.formatters import HtmlFormatter
- from pygments.lexers import PythonLexer, HtmlLexer, IniLexer
- from mako.ext.pygmentplugin import MakoHtmlLexer
- lexers = {'mako':MakoHtmlLexer(), 'python':PythonLexer(), 'html':HtmlLexer(),
- 'ini':IniLexer()}
- %>
- <%
- lexer = lexers.get(syntaxtype, None)
- # dumb hack to print a </%text> tag inside of a <%text> section
- content = re.sub(r'%CLOSETEXT', '</%text>', capture(caller.body))
-
- if lexer is not None:
- content = pygments.highlight(content, lexer, HtmlFormatter())
- else:
- content = "<pre>" + content + "</pre>"
- %>
-
- <div class="${ use_sliders and "sliding_code" or "code" }">
- % if title is not None:
- ${title}
- % endif
- ${ content }
- </div>
-</%def>
-
-
-
-
diff --git a/doc/build/templates/genindex.mako b/doc/build/templates/genindex.mako
new file mode 100644
index 0000000..bdb699a
--- /dev/null
+++ b/doc/build/templates/genindex.mako
@@ -0,0 +1,72 @@
+<%inherit file="layout.mako"/>
+
+<%def name="show_title()">${_('Index')}</%def>
+
+ <h1 id="index">${_('Index')}</h1>
+
+ % for i, (key, dummy) in enumerate(genindexentries):
+ ${i != 0 and '| ' or ''}<a href="#${key}"><strong>${key}</strong></a>
+ % endfor
+
+ <hr />
+
+ % for i, (key, entries) in enumerate(genindexentries):
+<h2 id="${key}">${key}</h2>
+<table width="100%" class="indextable"><tr><td width="33%" valign="top">
+<dl>
+ <%
+ breakat = genindexcounts[i] // 2
+ numcols = 1
+ numitems = 0
+ %>
+% for entryname, (links, subitems) in entries:
+
+<dt>
+ % if links:
+ <a href="${links[0]}">${entryname|h}</a>
+ % for link in links[1:]:
+ , <a href="${link}">[${i}]</a>
+ % endfor
+ % else:
+ ${entryname|h}
+ % endif
+
+ % if subitems:
+ <dd><dl>
+ % for subentryname, subentrylinks in subitems:
+ <dt><a href="${subentrylinks[0]}">${subentryname|h}</a>
+ % for j, link in enumerate(subentrylinks[1:]):
+ <a href="${link}">[${j}]</a>
+ % endfor
+ </dt>
+ % endfor
+ </dl></dd>
+ % endif
+ <%
+ numitems = numitems + 1 + len(subitems)
+ %>
+ % if numcols <2 and numitems > breakat:
+ <%
+ numcols = numcols + 1
+ %>
+ </dl></td><td width="33%" valign="top"><dl>
+% endif
+
+% endfor
+</dl></td></tr></table>
+% endfor
+
+<%def name="sidebarrel()">
+% if split_index:
+ <h4>${_('Index')}</h4>
+ <p>
+ % for i, (key, dummy) in enumerate(genindexentries):
+ ${i > 0 and '| ' or ''}
+ <a href="${pathto('genindex-' + key)}"><strong>${key}</strong></a>
+ % endfor
+ </p>
+
+ <p><a href="${pathto('genindex-all')}"><strong>${_('Full index on one page')}</strong></a></p>
+% endif
+ ${parent.sidebarrel()}
+</%def>
diff --git a/doc/build/templates/layout.mako b/doc/build/templates/layout.mako
new file mode 100644
index 0000000..d842fdd
--- /dev/null
+++ b/doc/build/templates/layout.mako
@@ -0,0 +1,130 @@
+## coding: utf-8
+<%inherit file="${context['mako_layout']}"/>
+
+<%def name="headers()">
+ <link rel="stylesheet" href="${pathto('_static/pygments.css', 1)}" type="text/css" />
+ <link rel="stylesheet" href="${pathto('_static/docs.css', 1)}" type="text/css" />
+
+ <script type="text/javascript">
+ var DOCUMENTATION_OPTIONS = {
+ URL_ROOT: '${pathto("", 1)}',
+ VERSION: '${release|h}',
+ COLLAPSE_MODINDEX: false,
+ FILE_SUFFIX: '${file_suffix}'
+ };
+ </script>
+ % for scriptfile in script_files + self.attr.local_script_files:
+ <script type="text/javascript" src="${pathto(scriptfile, 1)}"></script>
+ % endfor
+ <script type="text/javascript" src="${pathto('_static/init.js', 1)}"></script>
+ % if hasdoc('about'):
+ <link rel="author" title="${_('About these documents')}" href="${pathto('about')}" />
+ % endif
+ <link rel="index" title="${_('Index')}" href="${pathto('genindex')}" />
+ <link rel="search" title="${_('Search')}" href="${pathto('search')}" />
+ % if hasdoc('copyright'):
+ <link rel="copyright" title="${_('Copyright')}" href="${pathto('copyright')}" />
+ % endif
+ <link rel="top" title="${docstitle|h}" href="${pathto('index')}" />
+ % if parents:
+ <link rel="up" title="${parents[-1]['title']|util.striptags}" href="${parents[-1]['link']|h}" />
+ % endif
+ % if nexttopic:
+ <link rel="next" title="${nexttopic['title']|util.striptags}" href="${nexttopic['link']|h}" />
+ % endif
+ % if prevtopic:
+ <link rel="prev" title="${prevtopic['title']|util.striptags}" href="${prevtopic['link']|h}" />
+ % endif
+ ${self.extrahead()}
+</%def>
+<%def name="extrahead()"></%def>
+
+ <h1>${docstitle|h}</h1>
+
+ <div id="search">
+ Search:
+ <form class="search" action="${pathto('search')}" method="get">
+ <input type="text" name="q" size="18" /> <input type="submit" value="${_('Search')}" />
+ <input type="hidden" name="check_keywords" value="yes" />
+ <input type="hidden" name="area" value="default" />
+ </form>
+ </div>
+
+ <div class="versionheader">
+ Version: <span class="versionnum">${release}</span> Last Updated: ${last_updated}
+ </div>
+ <div class="clearboth"></div>
+
+ <div class="topnav">
+ <div id="pagecontrol">
+ <a href="${pathto('genindex')}">Index</a>
+
+ % if sourcename:
+ <div class="sourcelink">(<a href="${pathto('_sources/' + sourcename, True)|h}">${_('view source')})</div>
+ % endif
+ </div>
+
+ <div class="navbanner">
+ <a class="totoc" href="${pathto(master_doc)}">Table of Contents</a>
+ % if parents:
+ % for parent in parents:
+ » <a href="${parent['link']|h}" title="${parent['title']}">${parent['title']}</a>
+ % endfor
+ % endif
+ % if current_page_name != master_doc:
+ » ${self.show_title()}
+ % endif
+
+ ${prevnext()}
+ <h2>
+ ${self.show_title()}
+ </h2>
+ </div>
+ % if display_toc and not current_page_name.startswith('index'):
+ ${toc}
+ % endif
+ <div class="clearboth"></div>
+ </div>
+
+ <div class="document">
+ <div class="body">
+ ${next.body()}
+ </div>
+ </div>
+
+ <%def name="footer()">
+ <div class="bottomnav">
+ ${prevnext()}
+ <div class="doc_copyright">
+ % if hasdoc('copyright'):
+ &copy; <a href="${pathto('copyright')}">Copyright</a> ${copyright|h}.
+ % else:
+ &copy; Copyright ${copyright|h}.
+ % endif
+ % if show_sphinx:
+ Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> ${sphinx_version|h}.
+ % endif
+ </div>
+ </div>
+ </%def>
+ ${self.footer()}
+
+<%def name="prevnext()">
+<div class="prevnext">
+ % if prevtopic:
+ Previous:
+ <a href="${prevtopic['link']|h}" title="${_('previous chapter')}">${prevtopic['title']}</a>
+ % endif
+ % if nexttopic:
+ Next:
+ <a href="${nexttopic['link']|h}" title="${_('next chapter')}">${nexttopic['title']}</a>
+ % endif
+</div>
+</%def>
+
+<%def name="show_title()">
+% if title:
+ ${title}
+% endif
+</%def>
+
diff --git a/doc/build/templates/nav.html b/doc/build/templates/nav.html
deleted file mode 100644
index 08f2ecd..0000000
--- a/doc/build/templates/nav.html
+++ /dev/null
@@ -1,60 +0,0 @@
-## nav.myt - Provides page navigation elements that are derived from toc.TOCElement structures, including
-## individual hyperlinks as well as navigational toolbars and table-of-content listings.
-<%namespace name="tocns" file="toc.html"/>
-
-<%def name="itemlink(item, paged, extension, anchor=True)" filter="trim">
- <a href="${ item.get_link(anchor=anchor, usefilename=paged, extension=extension) }">${ item.description }</a>
-</%def>
-
-<%def name="toclink(toc, path, extension, paged, description=None)" filter="trim">
- <%
- item = toc.get_by_path(path)
- if description is None:
- if item:
- description = item.description
- else:
- description = path
- if item:
- anchor = not paged or item.depth > 1
- else:
- anchor = False
- %>
- % if item:
- <a href="${ item.get_link(extension=extension, anchor=anchor, usefilename=paged) }">${ description }</a>
- % else:
- <b>${ description }</b>
- % endif
-</%def>
-
-
-<%def name="link()" filter="trim(href, text, class_)">
- <a href="${ href }" ${ class_ and (('class=\"%s\"' % class_) or '')}>${ text }</a>
-</%def>
-
-<%def name="topnav(item, toc, extension, paged)">
- <div class="topnav">
-
- ${pagenav(item, extension=extension, paged=paged)}
-
- <br/>
- ${itemlink(item=item, anchor=True, paged=pagd, extension=extension)}
-
- ${tocns.printtoc(root=item, current=None, anchor_toplevel=True, paged=paged, extension=extension)}
- </div>
-</%def>
-
-<%def name="pagenav(item, paged, extension)">
- <div class="toolbar">
- <div class="prevnext">
- % if item.previous is not None:
- Previous: ${itemlink(item=item.previous, paged=paged, anchor=not paged, extension=extension)}
- % endif
-
- % if item.next is not None:
- ${item.previous is not None and "|" or ""}
- Next: ${itemlink(item=item.next, paged=paged, anchor=not paged, extension=extension)}
- % endif
- </div>
- <h3><a href="${paged and 'index' or 'documentation'}.${ extension }">Table of Contents</a></h3>
- </div>
-</%def>
diff --git a/doc/build/templates/page.mako b/doc/build/templates/page.mako
new file mode 100644
index 0000000..e0f98cf
--- /dev/null
+++ b/doc/build/templates/page.mako
@@ -0,0 +1,2 @@
+<%inherit file="layout.mako"/>
+${body| util.strip_toplevel_anchors} \ No newline at end of file
diff --git a/doc/build/templates/search.mako b/doc/build/templates/search.mako
new file mode 100644
index 0000000..dfad4d0
--- /dev/null
+++ b/doc/build/templates/search.mako
@@ -0,0 +1,22 @@
+<%inherit file="layout.mako"/>
+
+<%!
+ local_script_files = ['_static/searchtools.js']
+%>
+<%def name="show_title()">${_('Search')}</%def>
+
+<div id="searchform">
+<h3>Enter Search Terms:</h3>
+<form class="search" action="${pathto('search')}" method="get">
+ <input type="text" name="q" size="18" /> <input type="submit" value="${_('Search')}" />
+ <input type="hidden" name="check_keywords" value="yes" />
+ <input type="hidden" name="area" value="default" />
+</form>
+</div>
+
+<div id="search-results"></div>
+
+<%def name="footer()">
+ ${parent.footer()}
+ <script type="text/javascript" src="searchindex.js"></script>
+</%def>
diff --git a/doc/build/templates/site_base.mako b/doc/build/templates/site_base.mako
new file mode 100644
index 0000000..301c6a6
--- /dev/null
+++ b/doc/build/templates/site_base.mako
@@ -0,0 +1,27 @@
+<%text>#coding:utf-8
+<%inherit file="/base.html"/>
+<%page cache_type="file" cached="True"/>
+<%!
+ in_docs=True
+%>
+</%text>
+
+<div style="text-align:right">
+<b>PDF Download:</b> <a href="${pathto('sqlalchemy_' + release.replace('.', '_') + '.pdf', 1)}">download</a>
+</div>
+
+${'<%text>'}
+${next.body()}
+${'</%text>'}
+
+<%text><%def name="style()"></%text>
+ ${self.headers()}
+ <%text>${parent.style()}</%text>
+ <link href="/css/site_docs.css" rel="stylesheet" type="text/css"></link>
+<%text></%def></%text>
+
+<%text><%def name="title()"></%text>${capture(self.show_title)|util.striptags} &mdash; ${docstitle|h}<%text></%def></%text>
+
+<%!
+ local_script_files = []
+%>
diff --git a/doc/build/templates/static_base.mako b/doc/build/templates/static_base.mako
new file mode 100644
index 0000000..eaca5ce
--- /dev/null
+++ b/doc/build/templates/static_base.mako
@@ -0,0 +1,19 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+
+<html>
+ <head>
+ <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
+ ${metatags and metatags or ''}
+ <title>${capture(self.show_title)|util.striptags} &mdash; ${docstitle|h}</title>
+ ${self.headers()}
+ </head>
+ <body>
+ ${next.body()}
+ </body>
+</html>
+
+
+<%!
+ local_script_files = []
+%>
diff --git a/doc/build/templates/toc.html b/doc/build/templates/toc.html
deleted file mode 100644
index 49f4252..0000000
--- a/doc/build/templates/toc.html
+++ /dev/null
@@ -1,26 +0,0 @@
-## toc.myt - prints table of contents listings given toc.TOCElement strucures
-
-<%def name="toc(toc, paged, extension)">
- <div class="topnav">
-
- <a name="full_index"></a>
- <h3>Table of Contents</h3>
-
- ${printtoc(root=toc,paged=paged, extension=extension, current=None,children=True,anchor_toplevel=False)}
-
- </div>
-</%def>
-
-
-<%def name="printtoc(root, paged, extension, current=None, children=True, anchor_toplevel=False)">
- <ul>
- % for item in root.children:
- <li><A style="${item is current and "font-weight:bold;" or "" }" href="${item.get_link(extension=extension,anchor=anchor_toplevel, usefilename=paged) }">${item.description}</a></li>
-
- % if children:
- ${printtoc(item, current=current, children=True,anchor_toplevel=True, paged=paged, extension=extension)}
- % endif
- % endfor
- </ul>
-</%def>
-
diff --git a/doc/build/unicode.rst b/doc/build/unicode.rst
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/doc/build/unicode.rst
@@ -0,0 +1 @@
+
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
+
+
+
diff --git a/doc/docs.css b/doc/docs.css
deleted file mode 100644
index 7334dd5..0000000
--- a/doc/docs.css
+++ /dev/null
@@ -1,91 +0,0 @@
-#topanchor {position:absolute;left:0px;top:0px;width:0px;height:0px;}
-#pagecontrol {float:right;}
-
-body {
- font-family: Tahoma, Geneva, sans-serif;
- font-size:.90em;
- line-height:1.4em;
-}
-
-a { text-decoration: none; color:#2929ff;}
-a:visited { color: #2929ff;}
-a:hover { color: #600060;}
-
-h1 {
- font-size:1.6em;
- font-weight:bold;
-}
-
-h2 {
- font-size:1.1em;
- font-weight:bold;
- margin:10px 0px 10px 0px;
-}
-
-.topnav h3 {
- font-weight:normal;
- margin:0px 0px 0px 0px;
-}
-
-.prevnext {
- float:right;
-}
-.section {
-
-}
-.subsection {
- margin:0px 0px 0px 20px;
-}
-
-.topnav li {
- font-size:.9em;
- list-style-type:none;
-}
-
-.topnav ul {
- padding:0px 0px 0px 20px;
- margin:0px 0px 0px 0px;
-}
-
-.topnav .toolbar{
- margin:0px 0px 0px 0px;
- padding:0px 0px 0px 0px;
-}
-.topnav {
- background-color: #eee;
- border: 1px solid #ccc;
- padding:10px 10px 0px 10px;
- margin:0px 0px 10px 0px;
-}
-
-.smalllink {
- font-size:.80em;
-}
-code {
- font-size:1.2em;
-}
-.code {
- font-family:monospace;
-}
-p {
- /*margin:5px 20px 5px 10px;*/
-}
-
-li {
- margin:1px 0px 1px 0px;
-}
-td {
- font-size:small;
-}
-
-.section pre {
- margin: 1.5em;
- padding: .7em;
- font-size: 1em;
- line-height:1em;
- background-color: #eee;
- border: 1px solid #ccc;
- width:640px;
- overflow:auto;
-}
-
diff --git a/doc/highlight.css b/doc/highlight.css
deleted file mode 100644
index 544c9c3..0000000
--- a/doc/highlight.css
+++ /dev/null
@@ -1,57 +0,0 @@
-.c { color: #008800; font-style: italic } /* Comment */
-.err { border: 1px solid #FF0000 } /* Error */
-.k { color: #AA22FF; font-weight: bold } /* Keyword */
-.o { color: #666666 } /* Operator */
-.cm { color: #008800; font-style: italic } /* Comment.Multiline */
-.cp { color: #008800 } /* Comment.Preproc */
-.c1 { color: #008800; font-style: italic } /* Comment.Single */
-.gd { color: #A00000 } /* Generic.Deleted */
-.ge { font-style: italic } /* Generic.Emph */
-.gr { color: #FF0000 } /* Generic.Error */
-.gh { color: #000080; font-weight: bold } /* Generic.Heading */
-.gi { color: #00A000 } /* Generic.Inserted */
-.go { color: #808080 } /* Generic.Output */
-.gp { color: #000080; font-weight: bold } /* Generic.Prompt */
-.gs { font-weight: bold } /* Generic.Strong */
-.gu { color: #800080; font-weight: bold } /* Generic.Subheading */
-.gt { color: #0040D0 } /* Generic.Traceback */
-.kc { color: #AA22FF; font-weight: bold } /* Keyword.Constant */
-.kd { color: #AA22FF; font-weight: bold } /* Keyword.Declaration */
-.kp { color: #AA22FF } /* Keyword.Pseudo */
-.kr { color: #AA22FF; font-weight: bold } /* Keyword.Reserved */
-.kt { color: #AA22FF; font-weight: bold } /* Keyword.Type */
-.m { color: #666666 } /* Literal.Number */
-.s { color: #BB4444 } /* Literal.String */
-.na { color: #BB4444 } /* Name.Attribute */
-.nb { color: #AA22FF } /* Name.Builtin */
-.nc { color: #0000FF } /* Name.Class */
-.no { color: #880000 } /* Name.Constant */
-.nd { color: #AA22FF } /* Name.Decorator */
-.ni { color: #999999; font-weight: bold } /* Name.Entity */
-.ne { color: #D2413A; font-weight: bold } /* Name.Exception */
-.nf { color: #00A000 } /* Name.Function */
-.nl { color: #A0A000 } /* Name.Label */
-.nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
-.nt { color: #008000; font-weight: bold } /* Name.Tag */
-.nv { color: #B8860B } /* Name.Variable */
-.ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
-.mf { color: #666666 } /* Literal.Number.Float */
-.mh { color: #666666 } /* Literal.Number.Hex */
-.mi { color: #666666 } /* Literal.Number.Integer */
-.mo { color: #666666 } /* Literal.Number.Oct */
-.sb { color: #BB4444 } /* Literal.String.Backtick */
-.sc { color: #BB4444 } /* Literal.String.Char */
-.sd { color: #BB4444; font-style: italic } /* Literal.String.Doc */
-.s2 { color: #BB4444 } /* Literal.String.Double */
-.se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
-.sh { color: #BB4444 } /* Literal.String.Heredoc */
-.si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
-.sx { color: #008000 } /* Literal.String.Other */
-.sr { color: #BB6688 } /* Literal.String.Regex */
-.s1 { color: #BB4444 } /* Literal.String.Single */
-.ss { color: #B8860B } /* Literal.String.Symbol */
-.bp { color: #AA22FF } /* Name.Builtin.Pseudo */
-.vc { color: #B8860B } /* Name.Variable.Class */
-.vg { color: #B8860B } /* Name.Variable.Global */
-.vi { color: #B8860B } /* Name.Variable.Instance */
-.il { color: #666666 } /* Literal.Number.Integer.Long */ \ No newline at end of file
diff --git a/doc/makotemplates.txt b/doc/makotemplates.txt
deleted file mode 100644
index 08835d6..0000000
--- a/doc/makotemplates.txt
+++ /dev/null
@@ -1,663 +0,0 @@
-<html>
-
-<head>
-
-<style>
- body {
- font-family:arial,helvetica;
- }
-</style>
-
-</head>
-
-<body>
-
-# Mako Templates for Python
-
-## Slogan
-Hyperfast and Lightweight Templating for the Python Platform
-
-## Features
-- Python Server Pages. Templates compile into Python modules for maximum performance.
-<li> <p>Insanely Fast. An included bench suite, adapted from a suite included with Genshi, has these results for a simple three-sectioned layout:</p>
-<table>
-<tr><td>Mako:</td><td>0.66 ms</td></tr>
-<tr><td>Cheetah:</td><td>0.74 ms</td></tr>
-<tr><td>Django:</td><td>5.43 ms</td></tr>
-<tr><td>Myghty:</td><td>5.25 ms</td></tr>
-<tr><td>Genshi:</td><td>12.53 ms</td></tr>
-<tr><td>Kid:</td><td>19.12 ms</td></tr>
-</table>
-</li>
-
-- Super-simple API. For basic usage, just one class, `Template` is needed:
-
- from mako.template import Template
- print Template("hello ${data}!").render(data="world")
-
-- To manage many templates, leveraging industrial strength module generation and management code adapted from Myghty, use the `TemplateLookup` class:
-
- from mako.lookup import TemplateLookup
- lookup = TemplateLookup(directories=['/my/htmlfiles'])
- template = lookup.get_template('index.html')
- print template.render(data="foo")
-
-- Mako's syntax borrows from the best ideas of many others, including:
-
- - Django Templates
- - Myghty / Mason
- - Cheetah
- - Genshi
- - Java Server Pages
- - Struts Tiles
-
-- Standard template features:
- - control structures
-
- % if len(v) > 5:
- % for x in range(1,5):
- hi ${x}
- % endfor
- % endif
-
- - straight python code:
-
- <%
- data = handle.lookup()
- view = [d.name for d in data]
- %>
-
- - callable blocks, with or without arguments, which also pull names from the enclosing scope:
-
- # define:
- <%def name="foo(x, y)">
- hi im foo ${x} ${y} ${z}
- </%def>
-
- # then call:
- ${foo(4,5)}
-
- - multi-zoned page inheritance
- - "component-calls-with-content" - call any def, nesting any number locally-defined blocks of text as arguments. This is the basis for creating custom tags:
-
- # define:
- <%def name="foo(x, y)">
- ${head()}
- foo ${x} {$y}
- ${body()}
- </%def>
-
- # then call, defining two more blocks
- <%call expr="foo(3, 4)">
- <%def name="head">
- the header
- </%def>
- main body
- </%call>
-
- - filters, either the standard builtins or custom functions, applicable to any expression or `<%def>` definition:
-
- ${"some text" | h}
-
- <%def name="foo" filter="filter1, x">
- ...
- </%def>
-
- - custom tags can be created as templated components, or Python modules containing callables. Whole sets of custom tags can be imported into the current template's namespace using the `<%namespace>` tag.
- - caching built in from the ground up. any template or block of text within can be cached using memory, file, DBM or memcached backends.
-
-## Language
-
-### Control Structures
-
-Control structures use the % operator. % can start anywhere on the line, preceded by only whitespace. Blocks are terminated by name-qualified terminators.
-
- % for item in items:
- % if foo:
- ${item}
- some text
- % endif
- % endfor
-
-The amount of whitespace before the % and after the % before the code starts is not significant.
-
-Myghty style:
-
- % if x:
- % if y:
- % endif
- % endif
-
-"Cheetah" style:
-
- %if x:
- %if y:
- %endif
- %endif
-
-Messy style (you probably wouldn't want to code this way for readablity):
-
- %if x:
- %if y:
- % endif
- % endif
-
-### Comments
-
-Work similarly to %, using the # tag:
-
- <html>
- # this is a comment.
- </html>
-
-### Truncating Newlines
-
-End any line with a backslash (\\) to suppress the newline at the end:
-
- % for x in [1,2,3]:\
- ${x} \
- % endfor
-
-Produces the output:
-
- 1 2 3
-
-The newline truncator is particularly important for producing plaintext documents such as emails, as well as preformatted sections of HTML (i.e. using `<pre>`).
-
-### Expressions
-
-Expressions usually use ${expr} syntax, and compile into literal Python.
-
- ${someexpression}
-
- ${"foo" + "bar"}
-
-### Variable Namespace
-
-A template executes with a single contextual dictionary. This dictionary is completely transparent in the template itself. AST parsing of all embedded Python is performed in order to locate all referenced variable names, which are pre-declared from the dictionary at runtime (or a special "undefined" value if not present) before template-generated Python is executed. So when a variable "x" is referenced, the searched hierarchy is:
-
-- Variables declared locally, or as part of a control structure (like say, a for loop)
-- Variables declared in an enclosing scope.
-- Variables declared in the template at the module-level.
-- Names within the current context object.
-
-Notice that the context is the lowest priority for scope. This is to allow the most predictable behavior; when you create a template or component, the variables that are explicitly present regardless of the context's contents form part of the construction of that component. It should not be possible to place a name into the context that causes code which was written against an explicit scope to suddenly function differently.
-
-When variables from the context are what's specifically needed, just call them from the context explicitly:
-
- ${context['some key']}
-
-A convenience object `args` is also available which provides attribute-style access:
-
- args.mykey
-
-### Embedding Python
-#### Inline
-
-Inline Python is embedded via the <% %> tags. This is straight python so the whitespace is significant. You can emit text via the `write()` method on the context.
-
- <table>
- <tr><td>some table</td></tr>
- <tr>
- <%
- for x in ["one", "two", "three"]:
- context.write("<td>%s</td>" % x)
- %>
- </tr>
- </table>
-
-Remember that you can reference any variable name from the template's context, and it will be pulled from the context automatically.
-
-Context:
-
- {'x':'one', 'y':'two'}
-
-Template:
-
- <%
- context.write("X is " + x + "\n")
- y = "hi there"
- context.write("Y is " + y + "\n")
- %>
-
-Produces:
-
- X is one
- Y is hi there
-
-The scoping rules for variable assignment within blocks of Python are the same as that for Python callables; if you assign to a variable name, that variable becomes bound to the local scope, and you cannot access it in the block before that assignment, even if it is part of the context that was sent to the template. (We tried different combinations in this area, trying to allow a reference to the enclosing scope which can be overridden through assignment; but it quickly leads to inconsistent behaviors...Python has got it right !). If you *do* want to use a variable from the context, then reassign to it locally, just assign it from the context first:
-
- <%
- # pull y from the context.
- y = context['y']
- %>
- y is ${y}
- <%
- # now assign something different to y.
- y = "hi there"
- %>
- y is ${y}
-
-#### Module Level
-
-Module level Python is declared by the <%! %> tags. Python in these blocks occurs at module import time (i.e. global scope)
-
- <%!
- import mystuff
- def writefoo(text):
- return "foo is " +text
- %>
-
- hello ${writefoo('jack')}
-
-
-### File Includes
-
-Use the <%include> tag.
-
- <%include file="somefile.txt"/>
-
-This tag also can handle expressions:
-
- <%include file="${filename}"/>
-
-In fact every <%tag> can use expressions (i.e. ${}) inside of their quoted sections.
-
-The include tag requires that the template being called has a `TemplateLookup` available with which to locate the included template.
-
-Add the `import="true"` flag to the `<%include>` tag and when you include the file, all the `<%def>` and `<%namespace>` sections declared in that file (described later) are pulled into the local namespace of the template, as though they were declared locally:
-
- <%include file="somefile.html" import="true"/>
-
-### Components
-
-The component is the single tag used to demarcate any block of text and/or code. It exists within generated Python as a callable function.
-
- <%def name="hello">
- hello world
- </%def>
-
-They are normally called as expressions.
-
- the component: ${hello()}
-
-A `<%def>` can be declared anywhere inside a template, and becomes available throughout the template, including above where it was declared. The callable generated by `<%def>` gets generated outside of the enclosing template's callable. The name of the callable is then placed in the variable namespace of the parent component.
-
-Components have access to the current contextual namespace in exactly the same way their parent template does.
-
- Hello there ${username}, how are ya. Lets see what your account says:
-
- ${account()}
-
- <%def name="account">
- Account for ${username}:<br/>
-
- % for row in accountdata:
- Value: ${row}<br/>
- % endfor
- </%def>
-
-You can also pass arguments to a component, which show up in the component's variable namespace overriding whatever is in the enclosing namespace:
-
- ${account(name='john')}
-
- <%def name="account">
- Hi ${name}
- </%def>
-
-If you want your component to have positional arguments, you can declare them:
-
- <%def name="account(accountname, type)">
- account name: ${accountname}, type ${type}
- </%def>
-
-As well as keyword arguments explicitly declared, using normal Python conventions:
-
- <%def name="account(accountname, type='personal')">
- account name: ${accountname}, type ${type}
- </%def>
-
-When you declare explicit arguments in your component signature, they are required following normal Python conventions. This is in contrast to using variable names implicitly from the template's context, which produces `None` if the name doesn't exist. Additionally, explicitly declared arguments are handy in case you have the same names declared at the module level, and you'd like to insure that you get those arguments from the component call itself.
-
-#### Calling Components from Other Files
-
-Calling a component from another file differs from a regular `<%include>`, in that you are calling a specific component declared in that template, not the template body itself.
-
-First, load the file you want into a "namespace":
-
- <%namespace name="mystuff" file="mystuff.html"/>
-
-The namespace tag is declared once per template, and adds a local variable "mystuff" to the current scope.
-
-Then, just call the components off of `mystuff`:
-
- ${mystuff.somecomponent(x=5,y=7)}
-
-#### Components within Components
-
-The component model is totally recursive. Declaring `<%def>` inside another `<%def>` leads it to be local to its parent:
-
- <%def name="mycomponent">
- <%def name="subcomponent">
- a sub component
- </%def>
-
- im the component, and the subcomopnent is ${subcomponent()}
- </%def>
-
-The recursive component model becomes very handy for doing layouts, including usage within inheriting templates.
-
-#### Calling a component with embedded content and/or other components
-
-A flip-side to component within component is a component call with content. This is where you call a component, and at the same time declare a block of content that can be used by the component being called. This is the basic method used to declare "custom tags". To achieve this, use the `<%call>` tag instead of the regular expression syntax. By default, the body of content is assigned to the name `body`:
-
- <%def name="buildtable">
- <table>
- <tr><td>
- ${body()}
- </td></tr>
- </table>
- </%def>
-
- <%call expr="buildtable">
- I am the table body.
- </%call>
-
-This produces the output:
-
- <table>
- <tr><td>
- I am the table body.
- </td></tr>
- </table>
-
-The `body` name is executed each time its referenced. This means you can use component-call-with-content to build iterators, conditionals, etc:
-
- <%def name="lister(count)">
- % for x in range(1,count):
- ${body()}
- % endfor
- </%def>
-
- <%call expr="lister(3)">
- hi
- </%call>
-
-Produces:
-
- hi
- hi
- hi
-
-A custom "conditional" tag:
-
- <%def name="conditional(expr)">
- % if expr:
- ${body()}
- %
- </%def>
-
- <%call expr="conditional(4==4)">
- im the result
- </%call>
-
-Produces:
-
- im the result
-
-Since `body` is a callable, the hosting component can pass arguments:
-
- <%def name="layoutdata(somedata)">
- <table>
- % for item in somedata:
- <tr>
- % for col in item:
- <td>${body(col=col)}</td>\
- % endfor
- </tr>
- % endfor
- </table>
- </%def>
-
- <%call expr="layoutdata([[1,2,3],[4,5,6],[7,8,9]])">
- Body data: ${col}
- </%call>
-
-Produces:
-
- <table>
- <tr>
- <td>Body data: 1</td><td>Body data: 2</td><td>Body data: 3</td>
- <td>Body data: 2</td><td>Body data: 5</td><td>Body data: 6</td>
- <td>Body data: 3</td><td>Body data: 8</td><td>Body data: 9</td>
- </tr>
- </table>
-
-If you combine nested components with the component call with content, you can build whole layouts quite easily:
-
- <%def name="layout">
- # a layout component
- <div class="mainlayout">
- <div class="header">
- ${header()}
- </div>
- <div class="sidebar">
- ${sidebar()}
- </div>
- <div class="content">
- ${body()}
- </div>
- </div>
- </%def>
-
- # calls the layout component
- <%call expr="layout">
- <%def name="header">
- I am the header
- </%def>
- <%def name="sidebar">
- <ul>
- <li>sidebar 1</li>
- <li>sidebar 2</li>
- </ul>
- </%def>
-
- this is the body
- </%call>
-
-The above layout would produce:
-
- <div class="mainlayout">
- <div class="header">
- I am the header
- </div>
- <div class="sidebar">
- <ul>
- <li>sidebar 1</li>
- <li>sidebar 2</li>
- </ul>
- </div>
- <div class="content">
- this is the body
- </div>
- </div>
-
-### Inheritance
-
-Inheritance allows you to specify another template file that should take control of execution, using the current template's namespace. This is provided via the <%inherit> tag. This works similarly to the component call with content example above, where `body` is the main body of the template and you can also define other `<%def>` sections:
-
- # page.html:
-
- <%inherit name="base.html"/>
- <%def name="header">
- this is the header
- </%def>
-
- I am the body
-
- <%def name="footer">
- this is the footer
- </%def>
-
- # base.html:
-
- <html>
- <body>
- <div class="top">
- ${header()}
- </div>
-
- ${body()}
-
- ${footer()}
- </body>
- </html>
-
-Which produces:
-
- <html>
- <body>
- <div class="top">
- this is the header
- </div>
-
- I am the body
-
- this is the footer
- </body>
- </html>
-
-The inheritance of the parent template occurs *where you put the inherit tag.* This means whatever content is above the inherit tag gets executed normally, without any inheritance. It also means you can inherit *dynamically!*
-
- <%
- if layout=='green':
- inheritfrom = 'greentmpl.html'
- else:
- inheritfrom = 'normaltmpl.html'
- %>
- <%inherit name="${inheritfrom}"/>
-
-### Page-level arguments
-
-As components can declare optinally explicit argument signatures, so can your template, using the `<%page>` tag:
-
- <%page arguments="(arg1, arg2, arg3=None)"/>
-
-The named arguments are pulled from the incoming context dictionary, overriding any module-level declared arguments. It also serves as a way to declare certain context arguments as required.
-
-### Filters
-
-Filters are callable functions that receive a single textual argument as a string, and return a new textual string as output. They are called using the `|` operator in expressions:
-
- ${"this is some text" | html}
-
-Or using the `filter` keyword for a `<%def>` or `<%call>` directive:
-
- <%def name="mycomp" filter="html">
- </%def>
-
-Standard built-in filters are included: `html`, `xml`, `url`.
-
-Creating your own filters is easy. Any callable that is in the template's namespace can be used, or you can declare functions:
-
- <%|
- def myfilter(text):
- return "text" + text + "filtered"
- %>
-
- ${"hiya" | myfilter}
-
-Filters can also be defined using the `<%def>` tag. The text to be filtered is placed into the name 'text':
-
- <%def myfilter>
- text${text}filtered
- </%def>
-
- ${"hiya" | myfilter}
-
-Filters can take arguments ! Using a python function:
-
- <%|
- def pythonfilter(text, arg1, arg2='foo'):
- return "text" + text + "filtered"
- %>
- ${"hiya" | pythonfilter('hello', 'world')}
-
-Or a `<%def>`:
-
- <%def componentfilter(arg1, arg2='foo')>
- text${text}filtered
- </%def>
-
- ${"hiya" | componentfilter('hello', 'world')}
-
-### Caching
-
-Any template or component can be cached using the `cache` argument to the `%page` or `%def` directives:
-
- <%page cache="true"/>
-
- template text
-
- <%def name="mycomp" cache="true" cache_timeout="30" cache_type="memory">
- other text
- </%def>
-
-Cache arguments:
-- cache="false|true" - turn caching on
-- cache_timeout - number of seconds in which to invalidate the cached data
-- cache_type - type of caching. `memory`, `file`, `dbm`, or `memcached`.
-
-### Namespaces
-
-Namespaces are used to organize groups of components into categories, and also to "import" components from other files so that you don't have to type the full filename of the remote component file.
-
-If the file `components.html` defines these two components:
-
- # components.html
- <%def name="comp1">
- this is comp1
- </%def>
-
- <%def name="comp2">
- this is comp2
- </%def>
-
-You can make another file, for example `index.html`, that pulls those two components into a namespace called `comp`:
-
- # index.html
- <%namespace name="comp" file="components.html"/>
-
- Heres comp1: ${comp.comp1()}
- Heres comp2: ${comp.comp2()}
-
-The `<%namespace>` tag is more powerful than that. You can also declare `<%defs>` within the namespace:
-
- # define a namespace
- <%namespace name="stuff">
- <%def name="comp1">
- comp1
- </%def>
- </%namespace>
-
- # then call it
- ${stuff:comp1()}
-
-Namespaces can also import modules containing regular Python callables. These callables need to take at least one argument, `context`:
-
-A module file `some/module.py` might contain the callable:
-
- def my_tag(context):
- context.write("hello world")
-
-A template can use this module via:
-
- <%namespace name="hw" module="some.module"/>
-
- ${hw.my_tag()}
-
-Note that the `context` argument is not needed in the call; the `namespace` tag creates a locally-scoped callable which takes care of it.
-
-</body>
-
-</html>
diff --git a/mako/exceptions.py b/mako/exceptions.py
index b9df87e..5976d65 100644
--- a/mako/exceptions.py
+++ b/mako/exceptions.py
@@ -48,33 +48,10 @@ class TopLevelLookupException(TemplateLookupException):
pass
class RichTraceback(object):
- """pulls the current exception from the sys traceback and extracts
+ """Pulls the current exception from the sys traceback and extracts
Mako-specific template information.
- Usage:
-
- RichTraceback()
-
- Properties:
-
- error - the exception instance.
- message - the exception error message as unicode
- source - source code of the file where the error occured.
- if the error occured within a compiled template,
- this is the template source.
- 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
- 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).
- 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
- reverse_traceback - the traceback list in reverse
+ See the usage examples in :ref:`handling_exceptions`.
"""
def __init__(self, error=None, traceback=None):
diff --git a/mako/template.py b/mako/template.py
index ba4976c..0e99acf 100644
--- a/mako/template.py
+++ b/mako/template.py
@@ -14,7 +14,74 @@ import imp, os, re, shutil, stat, sys, tempfile, time, types, weakref
class Template(object):
- """a compiled template"""
+ """Represents a compiled template.
+
+ :class:`.Template` includes a reference to the original
+ template source (via the ``.source`` attribute)
+ as well as the source code of the
+ generated Python module (i.e. the ``.code`` attribute),
+ as well as a reference to an actual Python module.
+
+ :class:`.Template` is constructed using either a literal string
+ representing the template text, or a filename representing a filesystem
+ path to a source file.
+
+ :param text: textual template source. This argument is mutually exclusive
+ versus the "filename" parameter.
+
+ :param filename: filename of the source template. This argument is
+ mutually exclusive versus the "text" parameter.
+
+ :param buffer_filters:
+
+ :param cache_dir:
+
+ :param cache_enabled:
+
+ :param cache_type:
+
+ :param cache_url:
+
+ :param default_filters:
+
+ :param disable_unicode:
+
+ :param encoding_errors:
+
+ :param error_handler:
+
+ :param format_exceptions: if ``True``, exceptions which occur during
+ the render phase of this template will be caught and
+ formatted into an HTML error page, which then becomes the
+ rendered result of the :meth:`render` call. Otherwise,
+ runtime exceptions are propagated outwards.
+
+ :param imports:
+
+ :param input_encoding:
+
+ :param lookup:
+
+ :param module_directory: Filesystem location where generated Python
+ module files will be placed.
+
+ :param module_filename:
+
+ :param output_encoding:
+
+ :param preprocessor:
+
+ :param strict_undefined:
+
+ :param uri: string uri or other identifier for this template. If not provided,
+ the uri is generated from the filesystem path, or from the
+ in-memory identity of a non-file-based template. The primary usage of the
+ uri is to generate the file path of the generated Python module file,
+ if ``module_directory`` is specified.
+
+
+ """
+
def __init__(self,
text=None,
filename=None,
@@ -37,22 +104,6 @@ class Template(object):
imports=None,
preprocessor=None,
cache_enabled=True):
- """Construct a new Template instance using either literal template
- text, or a previously loaded template module
-
- :param text: textual template source, or None if a module is to be
- provided
-
- :param uri: the uri of this template, or some identifying string.
- defaults to the full filename given, or "memory:(hex id of this
- Template)" if no filename
-
- :param filename: filename of the source template, if any
-
- :param format_exceptions: catch exceptions and format them into an
- error display template
- """
-
if uri:
self.module_id = re.sub(r'\W', "_", uri)
self.uri = uri
@@ -161,6 +212,7 @@ class Template(object):
self._code = code
ModuleInfo(module, None, self, filename, code, None)
return module
+
@property
def source(self):
"""return the template source code for this Template."""