summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Madden <jason+github@nextthought.com>2017-11-03 08:35:28 -0500
committerGitHub <noreply@github.com>2017-11-03 08:35:28 -0500
commit8269f2c7d418d19bba90a67bd88aa64b8ed5acdc (patch)
treec8b1cb2f945857e075546584ab719db93583f7a0
parent5a2101c0c088bca3f0b50e34166e33451ca73dac (diff)
parentd052e523e766b38c6ba058b7630a99fa36c35719 (diff)
downloadzope-tal-8269f2c7d418d19bba90a67bd88aa64b8ed5acdc.tar.gz
Merge pull request #8 from zopefoundation/rtd-docs
Documentation for RTD
-rw-r--r--.gitignore1
-rw-r--r--CHANGES.rst2
-rw-r--r--MANIFEST.in6
-rw-r--r--README.rst17
-rw-r--r--doc-requirements.txt1
-rw-r--r--docs/Makefile177
-rw-r--r--docs/changelog.rst1
-rw-r--r--docs/conf.py279
-rw-r--r--docs/htmltalparser.rst5
-rw-r--r--docs/index.rst51
-rw-r--r--docs/interfaces.rst5
-rw-r--r--docs/make.bat242
-rw-r--r--docs/taldefs.rst5
-rw-r--r--docs/talgenerator.rst5
-rw-r--r--docs/talinterpreter.rst5
-rw-r--r--docs/talparser.rst7
-rw-r--r--setup.py6
-rw-r--r--src/zope/tal/htmltalparser.py56
-rw-r--r--src/zope/tal/interfaces.py55
-rw-r--r--src/zope/tal/taldefs.py47
-rw-r--r--src/zope/tal/talgenerator.py21
-rw-r--r--src/zope/tal/talinterpreter.py65
-rw-r--r--src/zope/tal/talparser.py19
-rw-r--r--src/zope/tal/xmlparser.py8
-rw-r--r--tox.ini11
25 files changed, 990 insertions, 107 deletions
diff --git a/.gitignore b/.gitignore
index 4b51bb9..1fdbb5e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,3 +9,4 @@ develop-eggs/
coverage.xml
nosetests.xml
htmlcov/
+docs/_build/
diff --git a/CHANGES.rst b/CHANGES.rst
index eff5e0a..3abe971 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -5,7 +5,7 @@
4.3.1 (unreleased)
==================
-- Nothing changed yet.
+- Host documentation at https://zopetal.readthedocs.io
4.3.0 (2017-08-08)
diff --git a/MANIFEST.in b/MANIFEST.in
index bb70d98..3b0dece 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,5 +1,6 @@
include *.py
include *.rst
+include *.txt
include buildout.cfg
include tox.ini
include .coveragerc
@@ -8,3 +9,8 @@ include .travis.yml
recursive-include src *.pt
recursive-include src *.xml
recursive-include src *.html
+
+recursive-include docs *.rst
+recursive-include docs *.py
+recursive-include docs Makefile
+recursive-include docs make.bat
diff --git a/README.rst b/README.rst
index 5f583cc..8f69e4d 100644
--- a/README.rst
+++ b/README.rst
@@ -1,6 +1,6 @@
-==============
- ``zope.tal``
-==============
+==========
+ zope.tal
+==========
.. image:: https://img.shields.io/pypi/v/zope.tal.svg
:target: https://pypi.python.org/pypi/zope.tal/
@@ -16,6 +16,10 @@
.. image:: https://coveralls.io/repos/github/zopefoundation/zope.tal/badge.svg?branch=master
:target: https://coveralls.io/github/zopefoundation/zope.tal?branch=master
+.. image:: https://readthedocs.org/projects/zopetal/badge/?version=latest
+ :target: https://zopetal.readthedocs.io/en/latest/
+ :alt: Documentation Status
+
The Zope3 Template Attribute Languate (TAL) specifies the custom namespace
and attributes which are used by the Zope Page Templates renderer to inject
dynamic markup into a page. It also includes the Macro Expansion for TAL
@@ -24,6 +28,9 @@ dynamic markup into a page. It also includes the Macro Expansion for TAL
The dynamic values themselves are specified using a companion language,
TALES (see the `zope.tales`_ package for more).
-See: http://wiki.zope.org/ZPT/TALSpecification14
+The reference documentation for the TAL language is available at https://docs.zope.org/zope2/zope2book/AppendixC.html
+
+Detailed documentation for this implementation and its API is available at https://zopetal.readthedocs.io/
+
-.. _`zope.tales` : http://pypi.python.org/pypi/zope.tales
+.. _`zope.tales` : https://zopetales.readthedocs.io
diff --git a/doc-requirements.txt b/doc-requirements.txt
new file mode 100644
index 0000000..e9704b8
--- /dev/null
+++ b/doc-requirements.txt
@@ -0,0 +1 @@
+.[docs]
diff --git a/docs/Makefile b/docs/Makefile
new file mode 100644
index 0000000..4c2d034
--- /dev/null
+++ b/docs/Makefile
@@ -0,0 +1,177 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+BUILDDIR = _build
+
+# User-friendly check for sphinx-build
+ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
+$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
+endif
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+# the i18n builder cannot share the environment and doctrees with the others
+I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
+
+help:
+ @echo "Please use \`make <target>' where <target> is one of"
+ @echo " html to make standalone HTML files"
+ @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 " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
+ @echo " text to make text files"
+ @echo " man to make manual pages"
+ @echo " texinfo to make Texinfo files"
+ @echo " info to make Texinfo files and run them through makeinfo"
+ @echo " gettext to make PO message catalogs"
+ @echo " changes to make an overview of all changed/added/deprecated items"
+ @echo " xml to make Docutils-native XML files"
+ @echo " pseudoxml to make pseudoxml-XML files for display purposes"
+ @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 $(ALLSPHINXOPTS) $(BUILDDIR)/html
+ @echo
+ @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+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/zopecatalog.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/zopecatalog.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/zopecatalog"
+ @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/zopecatalog"
+ @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
+ @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."
+
+latexpdfja:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+ @echo "Running LaTeX files through platex and dvipdfmx..."
+ $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
+ @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."
+
+texinfo:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo
+ @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
+ @echo "Run \`make' in that directory to run these through makeinfo" \
+ "(use \`make info' here to do that automatically)."
+
+info:
+ $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
+ @echo "Running Texinfo files through makeinfo..."
+ make -C $(BUILDDIR)/texinfo info
+ @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
+
+gettext:
+ $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
+ @echo
+ @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
+
+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) $(BUILDDIR)/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in $(BUILDDIR)/doctest/output.txt."
+
+xml:
+ $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
+ @echo
+ @echo "Build finished. The XML files are in $(BUILDDIR)/xml."
+
+pseudoxml:
+ $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
+ @echo
+ @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
diff --git a/docs/changelog.rst b/docs/changelog.rst
new file mode 100644
index 0000000..d9e113e
--- /dev/null
+++ b/docs/changelog.rst
@@ -0,0 +1 @@
+.. include:: ../CHANGES.rst
diff --git a/docs/conf.py b/docs/conf.py
new file mode 100644
index 0000000..7153fb9
--- /dev/null
+++ b/docs/conf.py
@@ -0,0 +1,279 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+#
+# zope.tal documentation build configuration file, created by
+# sphinx-quickstart on Thu Jan 29 11:31:12 2015.
+#
+# 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
+import os
+import pkg_resources
+sys.path.append(os.path.abspath('../src'))
+rqmt = pkg_resources.require('zope.tal')[0]
+
+# 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('.'))
+
+# -- 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.doctest',
+ 'sphinx.ext.intersphinx',
+ 'sphinx.ext.viewcode',
+ 'repoze.sphinx.autointerface',
+]
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = 'zope.tal'
+copyright = '2015-2017, Zope Foundation 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 = '%s.%s' % tuple(map(int, rqmt.version.split('.')[:2]))
+# The full version, including alpha/beta/rc tags.
+release = rqmt.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 = []
+
+# If true, keep warnings as "system message" paragraphs in the built documents.
+#keep_warnings = False
+
+
+# -- 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 name for this set of Sphinx documents. If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# 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']
+
+# Add any extra paths that contain custom files (such as robots.txt or
+# .htaccess) here, relative to this directory. These files are copied
+# directly to the root of the documentation.
+#html_extra_path = []
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# 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 = True
+
+# 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, 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 = 'zopetaldoc'
+
+
+# -- Options for LaTeX output ---------------------------------------------
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+#'preamble': '',
+}
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title,
+# author, documentclass [howto, manual, or own class]).
+latex_documents = [
+ ('index', 'zopetal.tex', 'zope.tal Documentation',
+ 'Zope Foundation and Contributors', '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
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output ---------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'zopetal', 'zope.tal Documentation',
+ ['Zope Foundation and Contributors'], 1)
+]
+
+# If true, show URL addresses after external links.
+#man_show_urls = False
+
+
+# -- Options for Texinfo output -------------------------------------------
+
+# Grouping the document tree into Texinfo files. List of tuples
+# (source start file, target name, title, author,
+# dir menu entry, description, category)
+texinfo_documents = [
+ ('index', 'zopetal', 'zope.tal Documentation',
+ 'Zope Foundation and Contributors', 'zopetal', 'One line description of project.',
+ 'Miscellaneous'),
+]
+
+# Documents to append as an appendix to all manuals.
+#texinfo_appendices = []
+
+# If false, no module index is generated.
+#texinfo_domain_indices = True
+
+# How to display URL addresses: 'footnote', 'no', or 'inline'.
+#texinfo_show_urls = 'footnote'
+
+# If true, do not generate a @detailmenu in the "Top" node's menu.
+#texinfo_no_detailmenu = False
+
+
+# Example configuration for intersphinx: refer to the Python standard library.
+intersphinx_mapping = {
+ 'https://docs.python.org/': None,
+ 'https://zopetales.readthedocs.io/en/latest/': None,
+}
+
+autodoc_default_flags = ['members', 'show-inheritance']
+autoclass_content = 'both'
+autodoc_member_order = 'bysource'
diff --git a/docs/htmltalparser.rst b/docs/htmltalparser.rst
new file mode 100644
index 0000000..bf2ac4f
--- /dev/null
+++ b/docs/htmltalparser.rst
@@ -0,0 +1,5 @@
+============================
+ Parsing and Compiling HTML
+============================
+
+.. automodule:: zope.tal.htmltalparser
diff --git a/docs/index.rst b/docs/index.rst
new file mode 100644
index 0000000..2b80efc
--- /dev/null
+++ b/docs/index.rst
@@ -0,0 +1,51 @@
+.. include:: ../README.rst
+
+Using ``zope.tal`` requires three steps: choosing an expression engine
+(usually :mod:`zope.tales`), creating a generator and parser, and then
+interpreting the compiled program::
+
+ from io import StringIO
+ from zope.tal.talgenerator import TALGenerator
+ from zope.tal.htmltalparser import HTMLTALParser
+ from zope.tal.talinterpreter import TALInterpreter
+
+ compiler = None # Will use a compiler for a dummy language
+ source_file = '<string>'
+ source_text = '<html><body><p>Hi</p></body></html>'
+ gen = TALGenerator(compiler, source_file=source_file)
+ parser = TALParser(gen)
+ parser.parseString(source_text)
+ program, macros = parser.getCode()
+
+ output = StringIO()
+ context = None # Usually will create a zope.tales context
+ interpreter = TALInterpreter(self.program, macros, context, stream=output)
+ interpreter()
+ result = output.getvalue()
+
+These aspects are all brought together in :mod:`zope.pagetemplate`.
+
+API Documentation:
+
+.. toctree::
+ :maxdepth: 2
+
+ interfaces
+ taldefs
+ talgenerator
+ htmltalparser
+ talparser
+ talinterpreter
+
+.. toctree::
+ :maxdepth: 1
+
+ changelog
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
diff --git a/docs/interfaces.rst b/docs/interfaces.rst
new file mode 100644
index 0000000..fffc139
--- /dev/null
+++ b/docs/interfaces.rst
@@ -0,0 +1,5 @@
+============
+ Interfaces
+============
+
+.. automodule:: zope.tal.interfaces
diff --git a/docs/make.bat b/docs/make.bat
new file mode 100644
index 0000000..9372f64
--- /dev/null
+++ b/docs/make.bat
@@ -0,0 +1,242 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set BUILDDIR=_build
+set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% .
+set I18NSPHINXOPTS=%SPHINXOPTS% .
+if NOT "%PAPER%" == "" (
+ set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS%
+ set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS%
+)
+
+if "%1" == "" goto help
+
+if "%1" == "help" (
+ :help
+ echo.Please use `make ^<target^>` where ^<target^> is one of
+ echo. html to make standalone HTML files
+ 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. text to make text files
+ echo. man to make manual pages
+ echo. texinfo to make Texinfo files
+ echo. gettext to make PO message catalogs
+ echo. changes to make an overview over all changed/added/deprecated items
+ echo. xml to make Docutils-native XML files
+ echo. pseudoxml to make pseudoxml-XML files for display purposes
+ echo. linkcheck to check all external links for integrity
+ echo. doctest to run all doctests embedded in the documentation if enabled
+ goto end
+)
+
+if "%1" == "clean" (
+ for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i
+ del /q /s %BUILDDIR%\*
+ goto end
+)
+
+
+%SPHINXBUILD% 2> nul
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.http://sphinx-doc.org/
+ exit /b 1
+)
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml.
+ goto end
+)
+
+if "%1" == "singlehtml" (
+ %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in %BUILDDIR%/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in %BUILDDIR%/qthelp, like this:
+ echo.^> qcollectiongenerator %BUILDDIR%\qthelp\zopecatalog.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile %BUILDDIR%\qthelp\zopecatalog.ghc
+ goto end
+)
+
+if "%1" == "devhelp" (
+ %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished.
+ goto end
+)
+
+if "%1" == "epub" (
+ %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The epub file is in %BUILDDIR%/epub.
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished; the LaTeX files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdf" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf
+ cd %BUILDDIR%/..
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "latexpdfja" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex
+ cd %BUILDDIR%/latex
+ make all-pdf-ja
+ cd %BUILDDIR%/..
+ echo.
+ echo.Build finished; the PDF files are in %BUILDDIR%/latex.
+ goto end
+)
+
+if "%1" == "text" (
+ %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The text files are in %BUILDDIR%/text.
+ goto end
+)
+
+if "%1" == "man" (
+ %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The manual pages are in %BUILDDIR%/man.
+ goto end
+)
+
+if "%1" == "texinfo" (
+ %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo.
+ goto end
+)
+
+if "%1" == "gettext" (
+ %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The message catalogs are in %BUILDDIR%/locale.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.The overview file is in %BUILDDIR%/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in %BUILDDIR%/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in %BUILDDIR%/doctest/output.txt.
+ goto end
+)
+
+if "%1" == "xml" (
+ %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The XML files are in %BUILDDIR%/xml.
+ goto end
+)
+
+if "%1" == "pseudoxml" (
+ %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml
+ if errorlevel 1 exit /b 1
+ echo.
+ echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml.
+ goto end
+)
+
+:end
diff --git a/docs/taldefs.rst b/docs/taldefs.rst
new file mode 100644
index 0000000..ba2f6bd
--- /dev/null
+++ b/docs/taldefs.rst
@@ -0,0 +1,5 @@
+====================
+ Common Definitions
+====================
+
+.. automodule:: zope.tal.taldefs
diff --git a/docs/talgenerator.rst b/docs/talgenerator.rst
new file mode 100644
index 0000000..35fc115
--- /dev/null
+++ b/docs/talgenerator.rst
@@ -0,0 +1,5 @@
+==========================
+ Generating Compiled Code
+==========================
+
+.. automodule:: zope.tal.talgenerator
diff --git a/docs/talinterpreter.rst b/docs/talinterpreter.rst
new file mode 100644
index 0000000..0f23220
--- /dev/null
+++ b/docs/talinterpreter.rst
@@ -0,0 +1,5 @@
+============================
+ Interpreting Compiled Code
+============================
+
+.. automodule:: zope.tal.talinterpreter
diff --git a/docs/talparser.rst b/docs/talparser.rst
new file mode 100644
index 0000000..e7296f9
--- /dev/null
+++ b/docs/talparser.rst
@@ -0,0 +1,7 @@
+===========================
+ Parsing and Compiling XML
+===========================
+
+.. automodule:: zope.tal.talparser
+
+.. autoclass:: zope.tal.xmlparser.XMLParser
diff --git a/setup.py b/setup.py
index 7a8312f..578fcb7 100644
--- a/setup.py
+++ b/setup.py
@@ -77,13 +77,17 @@ setup(name='zope.tal',
'Topic :: Internet :: WWW/HTTP',
'Framework :: Zope3',
],
- url='http://github.com/zopefoundation/zope.tal',
+ url='https://github.com/zopefoundation/zope.tal',
license='ZPL 2.1',
packages=find_packages('src'),
package_dir={'': 'src'},
namespace_packages=['zope'],
extras_require={
'test': TESTS_REQUIRE,
+ 'docs': [
+ 'Sphinx',
+ 'repoze.sphinx.autointerface',
+ ],
},
test_suite="__main__.alltests", # to support "setup.py test"
tests_require=TESTS_REQUIRE,
diff --git a/src/zope/tal/htmltalparser.py b/src/zope/tal/htmltalparser.py
index c79bbea..1761bc7 100644
--- a/src/zope/tal/htmltalparser.py
+++ b/src/zope/tal/htmltalparser.py
@@ -11,7 +11,9 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""Parse HTML and compile to TALInterpreter intermediate code.
+"""
+Parse HTML and compile to :class:`~.TALInterpreter` intermediate code, using
+a :class:`~.TALGenerator`.
"""
# When Python 3 becomes mainstream please swap the try and except parts.
@@ -28,6 +30,7 @@ except ImportError:
# so here's a copy taken from Python 3.4:
class HTMLParseError(Exception):
def __init__(self, msg, position=(None, None)):
+ Exception.__init__(self)
assert msg
self.msg = msg
self.lineno = position[0]
@@ -50,30 +53,30 @@ _html_parser_extras = {}
if 'convert_charrefs' in HTMLParser.__init__.__code__.co_names:
_html_parser_extras['convert_charrefs'] = False # pragma: NO COVER py34
-
+#: List of Boolean attributes in HTML that may be given in
+#: minimized form (e.g. ``<img ismap>`` rather than ``<img ismap="">``)
+#: From http://www.w3.org/TR/xhtml1/#guidelines (C.10)
BOOLEAN_HTML_ATTRS = frozenset([
- # List of Boolean attributes in HTML that may be given in
- # minimized form (e.g. <img ismap> rather than <img ismap="">)
- # From http://www.w3.org/TR/xhtml1/#guidelines (C.10)
"compact", "nowrap", "ismap", "declare", "noshade", "checked",
"disabled", "readonly", "multiple", "selected", "noresize",
"defer"
])
+#: List of HTML tags with an empty content model; these are
+#: rendered in minimized form, e.g. ``<img />``.
+#: From http://www.w3.org/TR/xhtml1/#dtds
EMPTY_HTML_TAGS = frozenset([
- # List of HTML tags with an empty content model; these are
- # rendered in minimized form, e.g. <img />.
- # From http://www.w3.org/TR/xhtml1/#dtds
"base", "meta", "link", "hr", "br", "param", "img", "area",
"input", "col", "basefont", "isindex", "frame",
])
+#: List of HTML elements that close open paragraph-level elements
+#: and are themselves paragraph-level.
PARA_LEVEL_HTML_TAGS = frozenset([
- # List of HTML elements that close open paragraph-level elements
- # and are themselves paragraph-level.
"h1", "h2", "h3", "h4", "h5", "h6", "p",
])
+#: Tags that automatically close other tags.
BLOCK_CLOSING_TAG_MAP = {
"tr": frozenset(["tr", "td", "th"]),
"td": frozenset(["td", "th"]),
@@ -83,12 +86,13 @@ BLOCK_CLOSING_TAG_MAP = {
"dt": frozenset(["dd", "dt"]),
}
+#: List of HTML tags that denote larger sections than paragraphs.
BLOCK_LEVEL_HTML_TAGS = frozenset([
- # List of HTML tags that denote larger sections than paragraphs.
"blockquote", "table", "tr", "th", "td", "thead", "tfoot", "tbody",
"noframe", "ul", "ol", "li", "dl", "dt", "dd", "div",
])
+#: Section level HTML tags
SECTION_LEVEL_HTML_TAGS = PARA_LEVEL_HTML_TAGS.union(BLOCK_LEVEL_HTML_TAGS)
TIGHTEN_IMPLICIT_CLOSE_TAGS = PARA_LEVEL_HTML_TAGS.union(BLOCK_CLOSING_TAG_MAP)
@@ -127,25 +131,37 @@ class OpenTagError(NestingError):
HTMLParseError.__init__(self, msg, position)
class HTMLTALParser(HTMLParser):
+ """
+ Parser for HTML.
+
+ After you call either :meth:`parseFile` and :meth:`parseString`
+ you can retrieve the compiled program using :meth:`getCode`.
+ """
# External API
def __init__(self, gen=None):
+ """
+ :keyword TALGenerator gen: The configured (with an expression compiler)
+ code generator to use. If one is not given, a default will be used.
+ """
HTMLParser.__init__(self, **_html_parser_extras)
if gen is None:
gen = TALGenerator(xml=0)
self.gen = gen
self.tagstack = []
self.nsstack = []
- self.nsdict = {'tal': ZOPE_TAL_NS,
- 'metal': ZOPE_METAL_NS,
- 'i18n': ZOPE_I18N_NS,
- }
+ self.nsdict = {
+ 'tal': ZOPE_TAL_NS,
+ 'metal': ZOPE_METAL_NS,
+ 'i18n': ZOPE_I18N_NS,
+ }
def parseFile(self, file):
- f = open(file)
- data = f.read()
- f.close()
+ """Parse data in the given file."""
+ with open(file) as f:
+ data = f.read()
+
try:
self.parseString(data)
except TALError as e:
@@ -153,6 +169,7 @@ class HTMLTALParser(HTMLParser):
raise
def parseString(self, data):
+ """Parse data in the given string."""
self.feed(data)
self.close()
while self.tagstack:
@@ -160,6 +177,9 @@ class HTMLTALParser(HTMLParser):
assert self.nsstack == [], self.nsstack
def getCode(self):
+ """
+ After parsing, this returns ``(program, macros)``.
+ """
return self.gen.getCode()
# Overriding HTMLParser methods
diff --git a/src/zope/tal/interfaces.py b/src/zope/tal/interfaces.py
index 8de3819..f6c1aec 100644
--- a/src/zope/tal/interfaces.py
+++ b/src/zope/tal/interfaces.py
@@ -11,8 +11,16 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""Interface that a TAL expression implementation provides to the METAL/TAL
-implementation.
+"""
+Interface that a TAL expression implementation provides to the
+METAL/TAL implementation.
+
+This package does not provide an implementation of
+:class:`ITALExpressionCompiler`, :class:`ITALExpressionEngine` or
+:class:`ITALIterator`. An external package must provide those. The
+most commonly used are :class:`zope.tales.tales.ExpressionEngine`,
+:class:`zope.tales.tales.Context`, and
+:class:`zope.tales.tales.Iterator`, respectively.
"""
from zope.interface import Attribute, Interface
@@ -30,20 +38,20 @@ class ITALExpressionCompiler(Interface):
"""
def compile(expression):
- """Return a compiled form of 'expression' for later evaluation.
+ """Return a compiled form of *expression* for later evaluation.
- 'expression' is the source text of the expression.
+ *expression* is the source text of the expression.
- The return value may be passed to the various evaluate*()
- methods of the ITALExpressionEngine interface. No compatibility is
+ The return value may be passed to the various ``evaluate*()``
+ methods of the :class:`ITALExpressionEngine` interface. No compatibility is
required for the values of the compiled expression between
- different ITALExpressionEngine implementations.
+ different :class:`ITALExpressionEngine` implementations.
"""
def getContext(namespace):
"""Create an expression execution context
- The given namespace provides the initial top-level names.
+ The given *namespace* provides the initial top-level names.
"""
class ITALExpressionEngine(Interface):
@@ -51,20 +59,20 @@ class ITALExpressionEngine(Interface):
The TAL interpreter uses this interface to TAL expression to support
evaluation of the compiled expressions returned by
- ITALExpressionCompiler.compile().
+ :meth:`ITALExpressionCompiler.compile`.
"""
def getDefault():
- """Return the value of the 'default' TAL expression.
+ """Return the value of the ``default`` TAL expression.
- Checking a value for a match with 'default' should be done
- using the 'is' operator in Python.
+ Checking a value for a match with ``default`` should be done
+ using the ``is`` operator in Python.
"""
def setPosition(position):
"""Inform the engine of the current position in the source file.
- ``position`` is a tuple (lineno, offset).
+ *position* is a tuple (lineno, offset).
This is used to allow the evaluation engine to report
execution errors so that site developers can more easily
@@ -105,7 +113,7 @@ class ITALExpressionEngine(Interface):
"""Evaluate an expression that must return a structured
document fragment.
- The result of evaluating 'compiled_expression' must be a
+ The result of evaluating *compiled_expression* must be a
string containing a parsable HTML or XML fragment. Any TAL
markup contained in the result string will be interpreted.
"""
@@ -118,10 +126,10 @@ class ITALExpressionEngine(Interface):
responsibility of the expression itself.
If the expression evaluates to None, then that is returned. It
- represents 'nothing' in TALES.
- If the expression evaluates to what getDefault() of this interface
- returns, by comparison using 'is', then that is returned. It
- represents 'default' in TALES.
+ represents ``nothing`` in TALES.
+ If the expression evaluates to what :meth:`getDefault()`
+ returns, by comparison using ``is``, then that is returned. It
+ represents ``default`` in TALES.
"""
def evaluateValue(compiled_expression):
@@ -131,9 +139,9 @@ class ITALExpressionEngine(Interface):
"""
def createErrorInfo(exception, position):
- """Returns an ITALExpressionErrorInfo object.
+ """Returns an :class:`ITALExpressionErrorInfo` object.
- ``position`` is a tuple (lineno, offset).
+ *position* is a tuple (lineno, offset).
The returned object is used to provide information about the
error condition for the on-error handler.
@@ -142,13 +150,13 @@ class ITALExpressionEngine(Interface):
def setGlobal(name, value):
"""Set a global variable.
- The variable will be named 'name' and have the value 'value'.
+ The variable will be named *name* and have the value *value*.
"""
def setLocal(name, value):
"""Set a local variable in the current scope.
- The variable will be named 'name' and have the value 'value'.
+ The variable will be named *name* and have the value *value*.
"""
def getValue(name, default=None):
@@ -158,7 +166,7 @@ class ITALExpressionEngine(Interface):
"""
def setRepeat(name, compiled_expression):
- """Start a repetition, returning an ITALIterator.
+ """Start a repetition, returning an :class:`ITALIterator`.
The engine is expected to add the a value (typically the
returned iterator) for the name to the variable namespace.
@@ -195,6 +203,7 @@ class ITALIterator(Interface):
class ITALExpressionErrorInfo(Interface):
+ """Information about an error."""
type = Attribute("type",
"The exception class.")
diff --git a/src/zope/tal/taldefs.py b/src/zope/tal/taldefs.py
index a4aaf61..539e541 100644
--- a/src/zope/tal/taldefs.py
+++ b/src/zope/tal/taldefs.py
@@ -17,20 +17,26 @@ import re
from zope.tal.interfaces import ITALExpressionErrorInfo
from zope.interface import implementer
-
+#: Version of the specification we implement.
TAL_VERSION = "1.6"
-XML_NS = "http://www.w3.org/XML/1998/namespace" # URI for XML namespace
-XMLNS_NS = "http://www.w3.org/2000/xmlns/" # URI for XML NS declarations
+#: URI for XML namespace
+XML_NS = "http://www.w3.org/XML/1998/namespace"
+#: URI for XML NS declarations
+XMLNS_NS = "http://www.w3.org/2000/xmlns/"
+#: TAL namespace URI
ZOPE_TAL_NS = "http://xml.zope.org/namespaces/tal"
+#: METAL namespace URI
ZOPE_METAL_NS = "http://xml.zope.org/namespaces/metal"
+#: I18N namespace URI
ZOPE_I18N_NS = "http://xml.zope.org/namespaces/i18n"
# This RE must exactly match the expression of the same name in the
# zope.i18n.simpletranslationservice module:
NAME_RE = "[a-zA-Z_][-a-zA-Z0-9_]*"
+#: Known METAL attributes
KNOWN_METAL_ATTRIBUTES = frozenset([
"define-macro",
"extend-macro",
@@ -39,6 +45,7 @@ KNOWN_METAL_ATTRIBUTES = frozenset([
"fill-slot",
])
+#: Known TAL attributes
KNOWN_TAL_ATTRIBUTES = frozenset([
"define",
"condition",
@@ -53,6 +60,7 @@ KNOWN_TAL_ATTRIBUTES = frozenset([
# like <tal:x>, <metal:y>, <i18n:z>
])
+#: Known I18N attributes
KNOWN_I18N_ATTRIBUTES = frozenset([
"translate",
"domain",
@@ -66,8 +74,12 @@ KNOWN_I18N_ATTRIBUTES = frozenset([
])
class TALError(Exception):
+ """
+ A base exception for errors raised by this implementation.
+ """
def __init__(self, msg, position=(None, None)):
+ Exception.__init__(self)
assert msg != ""
self.msg = msg
self.lineno = position[0]
@@ -88,17 +100,20 @@ class TALError(Exception):
return result
class METALError(TALError):
- pass
+ """An error parsing on running METAL macros."""
class TALExpressionError(TALError):
- pass
+ """An error parsing or running a TAL expression."""
class I18NError(TALError):
- pass
+ """An error parsing a I18N expression."""
@implementer(ITALExpressionErrorInfo)
class ErrorInfo(object):
+ """
+ Default implementation of :class:`zope.tal.interfaces.ITALExpressionErrorInfo`.
+ """
def __init__(self, err, position=(None, None)):
if isinstance(err, Exception):
@@ -115,7 +130,7 @@ _attr_re = re.compile(r"\s*([^\s]+)\s+([^\s].*)\Z", re.S)
_subst_re = re.compile(r"\s*(?:(text|structure)\s+)?(.*)\Z", re.S)
def parseAttributeReplacements(arg, xml):
- dict = {}
+ attr_dict = {}
for part in splitParts(arg):
m = _attr_re.match(part)
if not m:
@@ -123,10 +138,10 @@ def parseAttributeReplacements(arg, xml):
name, expr = m.groups()
if not xml:
name = name.lower()
- if name in dict:
+ if name in attr_dict:
raise TALError("Duplicate attribute name in attributes: %r" % part)
- dict[name] = expr
- return dict
+ attr_dict[name] = expr
+ return attr_dict
def parseSubstitution(arg, position=(None, None)):
m = _subst_re.match(arg)
@@ -151,26 +166,26 @@ def isCurrentVersion(program):
version = getProgramVersion(program)
return version == TAL_VERSION
-def isinstance_(ob, type):
+def isinstance_(ob, kind):
# Proxy-friendly and faster isinstance_ check for new-style objects
try:
- return type in ob.__class__.__mro__
+ return kind in ob.__class__.__mro__
except AttributeError:
return False
def getProgramMode(program):
version = getProgramVersion(program)
- if (version == TAL_VERSION and isinstance_(program[1], tuple) and
- len(program[1]) == 2):
+ if (version == TAL_VERSION and isinstance_(program[1], tuple)
+ and len(program[1]) == 2):
opcode, mode = program[1]
if opcode == "mode":
return mode
return None
def getProgramVersion(program):
- if (len(program) >= 2 and
- isinstance_(program[0], tuple) and len(program[0]) == 2):
+ if (len(program) >= 2
+ and isinstance_(program[0], tuple) and len(program[0]) == 2):
opcode, version = program[0]
if opcode == "version":
return version
diff --git a/src/zope/tal/talgenerator.py b/src/zope/tal/talgenerator.py
index ac77c18..ce7470c 100644
--- a/src/zope/tal/talgenerator.py
+++ b/src/zope/tal/talgenerator.py
@@ -11,7 +11,8 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""Code generator for TALInterpreter intermediate code.
+"""
+Code generator for :class:`~.TALInterpreter` intermediate code.
"""
import re
@@ -37,12 +38,20 @@ except NameError:
_name_rx = re.compile(NAME_RE)
class TALGenerator(object):
+ """
+ Generate intermediate code.
+ """
inMacroUse = 0
inMacroDef = 0
source_file = None
def __init__(self, expressionCompiler=None, xml=1, source_file=None):
+ """
+ :keyword expressionCompiler: The implementation of
+ :class:`zope.tal.interfaces.ITALExpressionCompiler` to use.
+ If not given, we'll use a simple, undocumented, compiler.
+ """
if not expressionCompiler:
from zope.tal.dummyengine import DummyEngine
expressionCompiler = DummyEngine()
@@ -96,7 +105,7 @@ class TALGenerator(object):
if self.optimizeStartTag(collect, item[1], item[2], ">"):
continue
if opcode == "startEndTag":
- endsep = self.xml and "/>" or " />"
+ endsep = "/>" if self.xml else " />"
if self.optimizeStartTag(collect, item[1], item[2], endsep):
continue
if opcode in ("beginScope", "endScope"):
@@ -182,9 +191,9 @@ class TALGenerator(object):
output = program[:2]
prev2, prev1 = output
for item in program[2:]:
- if ( item[0] == "beginScope"
- and prev1[0] == "setPosition"
- and prev2[0] == "rawtextColumn"):
+ if (item[0] == "beginScope"
+ and prev1[0] == "setPosition"
+ and prev2[0] == "rawtextColumn"):
position = output.pop()[1]
text, column = output.pop()[1]
prev1 = None, None
@@ -302,7 +311,7 @@ class TALGenerator(object):
self.emit("condition", cexpr, program)
def emitRepeat(self, arg):
- m = re.match("(?s)\s*(%s)\s+(.*)\Z" % NAME_RE, arg)
+ m = re.match(r"(?s)\s*(%s)\s+(.*)\Z" % NAME_RE, arg)
if not m:
raise TALError("invalid repeat syntax: " + repr(arg),
self.position)
diff --git a/src/zope/tal/talinterpreter.py b/src/zope/tal/talinterpreter.py
index c2ad97b..82154db 100644
--- a/src/zope/tal/talinterpreter.py
+++ b/src/zope/tal/talinterpreter.py
@@ -26,10 +26,9 @@ from zope.tal.translationcontext import TranslationContext
try:
unicode
- _BLANK = unicode('')
except NameError:
unicode = str # Python 3.x
- _BLANK = ''
+_BLANK = u''
# Avoid constructing this tuple over and over
@@ -43,6 +42,7 @@ BOOLEAN_HTML_ATTRS = frozenset([
# From http://www.w3.org/TR/xhtml1/#guidelines (C.10)
# TODO: The problem with this is that this is not valid XML and
# can't be parsed back!
+ # XXX: This is an exact duplicate of htmltalparser.BOOLEAN_HTML_ATTRS. Why?
"compact", "nowrap", "ismap", "declare", "noshade", "checked",
"disabled", "readonly", "multiple", "selected", "noresize",
"defer"
@@ -116,25 +116,25 @@ class TALInterpreter(object):
"""TAL interpreter.
Some notes on source annotations. They are HTML/XML comments added to the
- output whenever sourceFile is changed by a setSourceFile bytecode. Source
+ output whenever ``sourceFile`` is changed by a ``setSourceFile`` bytecode. Source
annotations are disabled by default, but you can turn them on by passing a
- sourceAnnotations argument to the constructor. You can change the format
+ ``sourceAnnotations`` argument to the constructor. You can change the format
of the annotations by overriding formatSourceAnnotation in a subclass.
The output of the annotation is delayed until some actual text is output
for two reasons:
- 1. setPosition bytecode follows setSourceFile, and we need position
+ 1. ``setPosition`` bytecode follows ``setSourceFile``, and we need position
information to output the line number.
- 2. Comments are not allowed in XML documents before the <?xml?>
+ 2. Comments are not allowed in XML documents before the ``<?xml?>``
declaration.
For performance reasons (TODO: premature optimization?) instead of checking
- the value of _pending_source_annotation on every write to the output
- stream, the _stream_write attribute is changed to point to
- _annotated_stream_write method whenever _pending_source_annotation is
+ the value of ``_pending_source_annotation`` on every write to the output
+ stream, the ``_stream_write`` attribute is changed to point to
+ ``_annotated_stream_write`` method whenever ``_pending_source_annotation`` is
set to True, and to _stream.write when it is False. The following
- invariant always holds:
+ invariant always holds::
if self._pending_source_annotation:
assert self._stream_write is self._annotated_stream_write
@@ -149,36 +149,31 @@ class TALInterpreter(object):
sourceAnnotations=0):
"""Create a TAL interpreter.
- Optional arguments:
-
- stream -- output stream (defaults to sys.stdout).
+ :param program: A compiled program, as generated
+ by :class:`zope.tal.talgenerator.TALGenerator`
+ :param macros: Namespace of macros, usually also from
+ :class:`~.TALGenerator`
- debug -- enable debugging output to sys.stderr (off by default).
+ Optional arguments:
- wrap -- try to wrap attributes on opening tags to this number of
+ :keyword stream: output stream (defaults to sys.stdout).
+ :keyword bool debug: enable debugging output to sys.stderr (off by default).
+ :keyword int wrap: try to wrap attributes on opening tags to this number of
column (default: 1023).
-
- metal -- enable METAL macro processing (on by default).
-
- tal -- enable TAL processing (on by default).
-
- showtal -- do not strip away TAL directives. A special value of
+ :keyword bool metal: enable METAL macro processing (on by default).
+ :keyword bool tal: enable TAL processing (on by default).
+ :keyword int showtal: do not strip away TAL directives. A special value of
-1 (which is the default setting) enables showtal when TAL
processing is disabled, and disables showtal when TAL processing is
enabled. Note that you must use 0, 1, or -1; true boolean values
- are not supported (TODO: why?).
-
- strictinsert -- enable TAL processing and stricter HTML/XML
+ are not supported (for historical reasons).
+ :keyword bool strictinsert: enable TAL processing and stricter HTML/XML
checking on text produced by structure inserts (on by default).
Note that Zope turns this value off by default.
-
- stackLimit -- set macro nesting limit (default: 100).
-
- i18nInterpolate -- enable i18n translations (default: on).
-
- sourceAnnotations -- enable source annotations with HTML comments
+ :keyword int stackLimit: set macro nesting limit (default: 100).
+ :keyword bool i18nInterpolate: enable i18n translations (default: on).
+ :keyword bool sourceAnnotations: enable source annotations with HTML comments
(default: off).
-
"""
self.program = program
self.macros = macros
@@ -266,6 +261,11 @@ class TALInterpreter(object):
return self.macroStack.pop()
def __call__(self):
+ """
+ Interpret the current program.
+
+ :return: Nothing.
+ """
assert self.level == 0
assert self.scopeLevel == 0
assert self.i18nContext.parent is None
@@ -1017,8 +1017,7 @@ class TALInterpreter(object):
class FasterStringIO(list):
- """Unicode-aware append-only version of StringIO.
- """
+ # Unicode-aware append-only version of StringIO.
write = list.append
def __init__(self, value=None):
diff --git a/src/zope/tal/talparser.py b/src/zope/tal/talparser.py
index 9adba2d..d99fc9f 100644
--- a/src/zope/tal/talparser.py
+++ b/src/zope/tal/talparser.py
@@ -11,7 +11,9 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""Parse XML and compile to TALInterpreter intermediate code.
+"""
+Parse XML and compile to :class:`~.TALInterpreter` intermediate code,
+using a :class:`~.TALGenerator`.
"""
from zope.tal.taldefs import XML_NS, ZOPE_I18N_NS, ZOPE_METAL_NS, ZOPE_TAL_NS
from zope.tal.talgenerator import TALGenerator
@@ -19,10 +21,22 @@ from zope.tal.xmlparser import XMLParser
class TALParser(XMLParser):
+ """
+ Parser for XML.
+
+ After parsing with :meth:`~.XMLParser.parseFile`,
+ :meth:`~.XMLParser.parseString`, :meth:`~.XMLParser.parseURL` or
+ :meth:`~.XMLParser.parseStream`, you can call :meth:`getCode` to
+ retrieve the parsed program and macros.
+ """
ordered_attributes = 1
def __init__(self, gen=None, encoding=None): # Override
+ """
+ :keyword TALGenerator gen: The configured (with an expression compiler)
+ code generator to use. If one is not given, a default will be used.
+ """
XMLParser.__init__(self, encoding)
if gen is None:
gen = TALGenerator()
@@ -32,6 +46,7 @@ class TALParser(XMLParser):
self.nsNew = []
def getCode(self):
+ """Return the compiled program and macros after parsing."""
return self.gen.getCode()
def StartNamespaceDeclHandler(self, prefix, uri):
@@ -117,7 +132,7 @@ class TALParser(XMLParser):
def EndElementHandler(self, name):
name = self.fixname(name)[0]
- self.gen.emitEndElement(name, position=self.getpos())
+ self.gen.emitEndElement(name, position=self.getpos())
def DefaultHandler(self, text):
self.gen.emitRawText(text)
diff --git a/src/zope/tal/xmlparser.py b/src/zope/tal/xmlparser.py
index 9081d37..ca5c216 100644
--- a/src/zope/tal/xmlparser.py
+++ b/src/zope/tal/xmlparser.py
@@ -32,6 +32,9 @@ except NameError:
class XMLParser(object):
+ """
+ Parse XML using :mod:`xml.parsers.expat`.
+ """
ordered_attributes = 0
@@ -82,10 +85,12 @@ class XMLParser(object):
return expat.ParserCreate(encoding, ' ')
def parseFile(self, filename):
+ """Parse from the given filename."""
with open(filename, 'rb') as f:
self.parseStream(f)
def parseString(self, s):
+ """Parse the given string."""
if isinstance(s, unicode):
# Expat cannot deal with unicode strings, only with
# encoded ones. Also, its range of encodings is rather
@@ -94,9 +99,11 @@ class XMLParser(object):
self.parser.Parse(s, 1)
def parseURL(self, url):
+ """Parse the given URL."""
self.parseStream(urlopen(url))
def parseStream(self, stream):
+ """Parse the given stream (open file)."""
self.parser.ParseFile(stream)
def parseFragment(self, s, end=0):
@@ -113,4 +120,3 @@ class XMLParser(object):
# [1] http://python.org/doc/current/lib/xmlparser-objects.html
# [2] http://cvs.sourceforge.net/viewcvs.py/expat/expat/lib/expat.h
return (self.parser.ErrorLineNumber, self.parser.ErrorColumnNumber)
-
diff --git a/tox.ini b/tox.ini
index a62d402..4d45658 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,6 +1,6 @@
[tox]
envlist =
- py27,py34,py35,py36,pypy,pypy3,coverage
+ py27,py34,py35,py36,pypy,pypy3,coverage,docs
[testenv]
commands =
@@ -18,3 +18,12 @@ commands =
deps =
{[testenv]deps}
coverage
+
+[testenv:docs]
+basepython =
+ python2.7
+commands =
+ sphinx-build -b html -d docs/_build/doctrees docs docs/_build/html
+deps =
+ {[testenv]deps}
+ .[docs]