Commits

Ralph Bean committed 464802e Merge with conflicts

Merge branch 'develop'

Conflicts:
.travis.yml

  • Participants
  • Parent commits 5f565fc, a09dc57

Comments (0)

Files changed (13)

 install: python setup.py install
 script: python setup.py test
 notifications:
+    email: false
     irc:
         - "irc.freenode.net#toscawidgets"
     on_success: change
-# -*- coding: utf-8 -*-
-#
-# ToscaWidgets 2 documentation build configuration file, created by
-# sphinx-quickstart on Tue Mar 10 11:38:11 2009.
-#
-# This file is execfile()d with the current directory set to its containing dir.
-#
-# The contents of this file are pickled, so don't put values in the namespace
-# that aren't pickleable (module imports are okay, they're removed automatically).
-#
-# 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
-import pkg_resources
-dist = pkg_resources.get_distribution('tw2.core')
-
-# If your extensions are in another directory, add it here. If the directory
-# is relative to the documentation root, use os.path.abspath to make it
-# absolute, like shown here.
-#sys.path.append(os.path.abspath('.'))
-
-# General configuration
-# ---------------------
-
-# 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']
-
-# 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'
-
-# The master toctree document.
-master_doc = 'index'
-
-# General information about the project.
-project = u'ToscaWidgets 2'
-copyright = u'2010, Paul Johnston, Alberto Valverde & 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 = '2.0'
-# The full version, including alpha/beta/rc tags.
-release = dist.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 documents that shouldn't be included in the build.
-#unused_docs = []
-
-# List of directories, relative to source directory, that shouldn't be searched
-# for source files.
-exclude_trees = ['.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'
-
-
-# Options for HTML output
-# -----------------------
-
-# 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 = 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']
-
-# 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_use_modindex = 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, the reST sources are included in the HTML build as _sources/<name>.
-#html_copy_source = 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 = ''
-
-# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
-#html_file_suffix = ''
-
-# Output file base name for HTML help builder.
-htmlhelp_basename = 'ToscaWidgets2doc'
-
-
-# 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, document class [howto/manual]).
-latex_documents = [
-  ('index', 'ToscaWidgets2.tex', ur'ToscaWidgets 2 Documentation',
-   ur'Paul Johnston, Alberto Valverde & 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
-
-# Additional stuff for the LaTeX preamble.
-#latex_preamble = ''
-
-# Documents to append as an appendix to all manuals.
-#latex_appendices = []
-
-# If false, no module index is generated.
-#latex_use_modindex = True
+# -*- coding: utf-8 -*-
+#
+# ToscaWidgets 2 documentation build configuration file, created by
+# sphinx-quickstart on Tue Mar 10 11:38:11 2009.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# The contents of this file are pickled, so don't put values in the namespace
+# that aren't pickleable (module imports are okay, they're removed automatically).
+#
+# 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
+import pkg_resources
+dist = pkg_resources.get_distribution('tw2.core')
+
+# If your extensions are in another directory, add it here. If the directory
+# is relative to the documentation root, use os.path.abspath to make it
+# absolute, like shown here.
+#sys.path.append(os.path.abspath('.'))
+
+# General configuration
+# ---------------------
+
+# 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']
+
+# 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'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'ToscaWidgets 2'
+copyright = u'2010, Paul Johnston, Alberto Valverde & 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 = '2.0'
+# The full version, including alpha/beta/rc tags.
+release = dist.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 documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be searched
+# for source files.
+exclude_trees = ['.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'
+
+
+# Options for HTML output
+# -----------------------
+
+# 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 = 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']
+
+# 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_use_modindex = 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, the reST sources are included in the HTML build as _sources/<name>.
+#html_copy_source = 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 = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'ToscaWidgets2doc'
+
+
+# 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, document class [howto/manual]).
+latex_documents = [
+  ('index', 'ToscaWidgets2.tex', ur'ToscaWidgets 2 Documentation',
+   ur'Paul Johnston, Alberto Valverde & 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
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_use_modindex = True
-Design
-------
-
-Widget Overview
-===============
-
-The main purpose of a widget is to display a functional control within an HTML page. A widget has a template to generate its own HTML, and a set of parameters that control how it will be displayed. It can also reference resources - JavaScript or CSS files that support the widget.
-
-When defining Widgets, some parameters with be static - they will stay constant for the whole lifetime of the application. Some parameters are dynamic - they may change for every request. To ensure thread-safety, a separate widget instance is created for every request, and dynamic parameters are only set on an instance. Static parameters are set by subclassing a widget. For example::
-
-    # Initialisation
-    class MyWidget(Widget):
-        id = 'myid'
-
-    # In a request
-    my_widget = MyWidget.req()
-    my_widget.value = 'my value'
-
-To make initialisation more concise, the ``__new__`` method on ``Widget`` is overriden, so it creates subclasses, rather than instances. The following code is equivalent to that above::
-
-    # Initialisation
-    MyWidget = Widget(id='myid')
-
-In practice, you will rarely need to explictly create an instance, using ``req()``. If the ``display`` or ``validate`` methods are called on a Widget class, they automatically create an instance. For example, the following are equivalent::
-
-    # Explicit creation
-    my_widget = MyWidget.req()
-    my_widget.value = 'my value'
-    my_widget.display()
-
-    # Implicit creation
-    MyWidget.display(value='my value')
-
-
-Parameters
-~~~~~~~~~~
-
-The parameters are how the user of the widget controls its display and behaviour. Parameters exist primarily for documentation purposes, although they do have some run-time effects. When creating widgets, it's important to decide on a convenient set of parameters for the user of the widget, and to document these.
-
-A parameter definition looks like this::
-
-    import tw2.core as twc
-    class MyTextField(twc.Widget):
-        size = twc.Param('The size of the field', default=30)
-        validator = twc.LengthValidator(max=30)
-        highlight = twc.Variable('Region to highlight')
-
-In this case, :class:`TextField` gets all the parameters of its base class, :class:`tw2.core.widget` and defines a new parameter - :attr:`size`. A widget can also override parameter in its base class, either with another :class:`tw2.core.Param` instance, or a new default value.
-
-.. autoclass:: tw2.core.Param
-.. autoclass:: tw2.core.Variable
-.. autoclass:: tw2.core.ChildParam
-.. autoclass:: tw2.core.ChildVariable
-
-
-Code Hooks
-~~~~~~~~~~
-
-Subclasses of Widget can override the following methods. It is not recommended to override any other methods, e.g. display, validate, __init__.
-
-.. automethod:: tw2.core.widgets.Widget.post_define
-.. automethod:: tw2.core.widgets.Widget.prepare
-.. automethod:: tw2.core.widgets.Widget.generate_output
-
-**Mutable Members**
-
-If a widget's :meth:`prepare` method modifies a mutable member on the widget, it must take care not to modify a class member, as this is not thread safe. In general, the code should call :attr:`self.safe_modify(member_name)`, which detects class members and creates a copy on the instance. Users of widgets should be aware that if a mutable is set on an instance, the widget may modify this. The most common case of a mutable member is :attr:`attrs`. While this arrangement is thread-safe and reasonably simple, copying may be bad for performance. In some cases, widgets may deliberately decide not to call :meth:`safe_modify`, if the implications of this are understood.
-
-
-Widget Hierarchy
-================
-
-Widgets can be arranged in a hierarchy. This is useful for applications like layouts, where the layout will be a parent widget and fields will be children of this. There are four roles a widget can take in the hierarchy, depending on the base class used:
-
-.. autoclass:: tw2.core.Widget
-.. autoclass:: tw2.core.CompoundWidget
-.. autoclass:: tw2.core.RepeatingWidget
-.. autoclass:: tw2.core.DisplayOnlyWidget
-
-**Value Propagation**
-
-An important feature of the hierarchy is value propagation. When the value is set for a compound or repeating widget, this causes the value to be set for the child widgets. In general, a leaf widget takes a scalar type as a value, a compound widget takes a dict or an  object, and a repeating widget takes a list.
-
-The hierarchy also affects the generation of compound ids, and validation.
-
-**Identifier**
-
-In general, a widget needs to have an identifier. Without an id, it cannot participate in value propagation or validation, and it does not get an HTML id attribute. There are some exceptions to this:
-
- * Some widgets do not need an id (e.g. Label, Spacer) and provide a default id of None.
- * The child of a RepeatingWidget must not have an id.
- * An id can be specified either on a DisplayOnlyWidget, or it's child, but not both. The widget that does not have the id specified automatically picks it up from the other.
-
-Compound IDs are formed by joining the widget's id with those of its ancestors. These are used in two situations:
-
- * For the HTML id attribute, and also the name attribute for form fields
- * For the URL path a controller widget is registered at
-
-The separator is a colon (:), resulting in compound ids like "form:sub_form:field". **Note** this causes issues with CSS and will be changed shortly, and made configurable.
-
-In generel, the id on a DisplayOnlyWidget is not included in the compound id. However, when generating the compound id for a DisplayOnlyWidget, the id is included. In addition *id_suffix* is appended, to avoid generating duplicate IDs. The *id_suffix* is not appended for URL paths, to keep the paths short. There is a risk of duplicate IDs, but this is not expected to be a problem in practice.
-
-For children of a RepeatingWidget, the repetition is used instead of the id, for generating the compound HTML id. For the URL path, the element is skipped entirely.
-
-
-**Deep Children**
-
-This is a feature that helps have a form layout that doesn't exactly match the database layout. For example, we might have a sinlge database table, with fields like title, customer, start_date, end_date. We want to display this in a Form that's broken up into two FieldSets. Without deep children, the FieldSets would have to have ids, and field makes would be dotted, like info.title. The deep children feature lets us set the id to None::
-
-    class MyForm(twf.Form):
-        class child(twc.CompoundWidget):
-            class info(twf.TableFieldSet):
-                id = None
-                title = twf.TextField()
-                customer = twf.TextField()
-            class dates(twf.TableFieldSet):
-                id = None
-                start_date = twf.TextField()
-                end_date = twf.TextField()
-
-When a value like ``{'title': 'my title'}`` is passed to MyForm, this will propagate correctly.
-
-
-Template
-========
-
-Every widget can have a template. ToscaWidgets aims to support any templating engine that support the ``buffet`` interface, which is an initiative by the TurboGears project to create a standard interface for template libraries. In practice, there are more differences between template engines than the buffet interface standardises. So, ToscaWidgets has some template-language hooks, and support is primarily for: Genshi, Mako, Kid and Cheetah.
-
-The :attr:`template` parameter takes the form ``engine_name:template_path``. The ``engine_name`` is the name that the template engine defines in the ``python.templating.engines`` entry point, e.g. ``genshi`` or ``mako``. The ``template_path`` is a string the engine can use to locate the template; usually this is dot-notation that mimics the semantics of Python's import statement, e.g. ``myapp.templates.mytemplate``. Genshi templates allow specifications like ``./template.html`` which is beneficial for simple applications.
-
-It is also possible to allow your widget to utilize multiple templates, or to have TW2 support any template language you provide a template for.  To do this, simply leave the name of the template engine off of the template parameter, and TW2 will select the appropriate template, based on specifications in the TW2 middleware.
-
-For instance, you might have a form.mak and a form.html template (mako and genshi). TW2 will render the mako template if mako is listed ahead of genshi in the middleware config's ``preferred_rendering_engines``.  See the documentation regarding :ref:`middleware` for more information on how to set up your middleware for desired output.
-
-.. autoclass:: tw2.core.template.EngineManager
-   :members: render, _get_adaptor_renderer
-
-
-Non-template Output
-===================
-
-Instead of using a template, a widget can also override the ``generate_output`` method. This function generates the HTML output for a widget; by default, it renders the widget's template as described in the previous section, but can be overridden by any function that returns a string of HTML.
-
-
-Resources
-=========
-
-Widgets often need to access resources, such as JavaScript or CSS files. A key feature of widgets is the ability to automatically serve such resources, and insert links into appropriate sections of the page, e.g. ``<HEAD>``. There are several parts to this:
-
- * Widgets can define resources they use, using the :attr:`resources` parameter.
- * When a resource is defined, it is registered with the resource server.
- * When a Widget is displayed, it registers resources in request-local storage.
- * The resource injection middleware detects resources in request-local storage, and rewrites the generated page to include appropriate links.
- * The resource server middleware serves static files used by widgets
- * Widgets can also access resources at display time, e.g. to get links
- * Resources can themselves declare dependency on other resources, e.g.
-   jquery-ui.js depends on jquery.js and must be included on the page
-   subsequently.
-
-**Defining Resources**
-
-To define a resource, just add a :class:`tw2.core.Resource` subclass to the widget's :attr:`resources` parameter. It is also possible to append to :attr:`resources` from within the :meth:`prepare` method. The following resource types are available:
-
-.. autoclass:: tw2.core.CSSLink
-.. autoclass:: tw2.core.CSSSource
-.. autoclass:: tw2.core.JSLink
-.. autoclass:: tw2.core.JSSource
-.. autoclass:: tw2.core.JSFuncCall
-
-Resources are widgets, but follow a slightly different lifecycle. Resource subclasses are passed into the :attr:`resources` parameter. An instance is created for each request, but this is only done at the time of the parent Widget's :meth:`display` method. This gives widgets a chance to add dynamic resources in their :meth:`prepare` method.
-
-**Deploying Resources**
-
-If running behind mod_wsgi, tw2 resource provisioning will typically fail.
-Resources are only served when they are registered with the request-local
-thread, and resources are only registered when their dependant widget is
-displayed in a request.  An initial page request may make available resource
-``A``, but the subsequent request to actually retrieve resource ``A`` will not
-have that resource registered.
-
-To solve this problem (and to introduce a speed-up for production deployment),
-Toscawidgets2 provides an ``archive_tw2_resources`` distutils command::
-
-    $ python setup.py archive_tw2_resources \
-        --distributions=myapplication \
-        --output=/var/www/myapplication
-
-.. _middleware:
-
-Middleware
-==========
-
-
-The WSGI middleware has three functions:
-
- * Request-local storage
- * Configuration
- * Resource injection
-
-**Configuration**
-
-In general, ToscaWidgets configuration is done on the middleware instance. At the beginning of each request, the middleware stores a reference to itself in request-local storage. So, during a request, a widget can consult request-local storage, and get the configuration for the middleware active in that request. This allows multiple applications to use ToscaWidgets, with different configurations, in a single Python environment.
-
-Configuration is passed as keyword arguments to the middleware constructor. The available parameters are:
-
-.. autoclass:: tw2.core.middleware.Config
-
-
-Declarative Instantiation
-=========================
-
-Instantiating compound widgets can result in less-than-beautiful code. To help alleviate this, widgets can be defined declaratively, and this is the recommended approach. A definition looks like this::
-
-    class MovieForm(twf.TableForm):
-        id = twf.HiddenField()
-        year = twf.TextField()
-        desc = twf.TextArea(rows=5)
-
-Any class members that are subclasses of Widget become children. All the children get their ``id`` from the name of the member variable. Note: it is important that all children are defined like ``id = twf.HiddenField()`` and not ``id = twf.HiddenField``. Otherwise, the order of the children will not be preserved.
-
-It is possible to define children that have the same name as parameters, using this syntax. However, doing so does prevent a widget overriding a parameter, and defining a child with the same name. If you need to do this, you must use a throwaway name for the member variable, and specify the id explicitly, e.g.::
-
-    class MovieForm(twf.TableForm):
-        resources = [my_resource]
-        id = twf.HiddenField()
-        noname = twf.TextArea(id='resources')
-
-
-**Nesting and Inheritence**
-
-Nested declarative definitions can be used, like this::
-
-    class MyForm(twf.Form):
-        class child(twf.TableLayout):
-            b = twf.TextArea()
-            x = twf.Label(text='this is a test')
-            c = twf.TextField()
-
-Inheritence is supported - a subclass gets the children from the base class, plus any defined on the subclass. If there's a name clash, the subclass takes priority. Multiple inheritence resolves name clashes in a similar way. For example::
-
-    class MyFields(twc.CompoundWidget):
-        b = twf.TextArea()
-        x = twf.Label(text='this is a test')
-        c = twf.TextField()
-
-    class TableFields(MyFields, twf.TableLayout):
-        pass
-
-    class ListFields(MyFields, twf.ListLayout):
-        b = twf.TextField()
-
-**Proxying children**
-
-Without this feature, double nesting of classes is often necessary, e.g.::
-
-    class MyForm(twf.Form):
-        class child(twf.TableLayout):
-            b = twf.TextArea()
-
-Proxying children means that if :class:`RepeatingWidget` or :class:`DisplayOnlyWidget` have :attr:`children` set, this is passed to their :attr:`child`. The following is equivalent to the definition above::
-
-    class MyForm(twf.Form):
-        child = twf.TableLayout()
-        b = twf.TextArea()
-
-And this is used by classes like :class:`TableForm` and :class:`TableFieldSet` to allow the user more concise widget definitions::
-
-    class MyForm(twf.TableForm):
-        b = twf.TextArea()
-
-
-**Automatic ID**
-
-Sub classes of :class:`Page` that do not have an id, will have the id automatically set to the name of the class. This can be disabled by setting :attr:`_no_autoid` on the class. This only affects that specific class, not any subclasses.
-
-
-Widgets as Controllers
-======================
-
-Sometimes widgets will want to define controller methods. This is particularly useful for Ajax widgets. Any widget can have a :meth:`request` method, which is called with a WebOb :class:`Request` object, and must return a WebOb :class:`Response` object, like this::
-
-    class MyWidget(twc.Widget):
-        id = 'my_widget'
-        @classmethod
-        def request(cls, req):
-            resp = webob.Response(request=req, content_type="text/html; charset=UTF8")
-            # ...
-            return resp
-
-For the :meth:`request` method to be called, the widget must be registered with the :class:`ControllersApp` in the middleware. By default, the path is constructed from /controllers/, and the widget's id. A request to /controllers/ refers to a widget with id ``index``. You can specify :attr:`controllers_prefix` in the configuration.
-
-For convenience, widgets that have a :meth:`request` method, and an :attr:`id` will be registered automatically. By default, this uses a global :class:`ControllersApp` instance, which is also the default controllers for :func:`make_middleware`. If you want to use multiple controller applications in a single python instance, you will need to override this.
-
-You can also manually register widgets::
-
-    twc.core.register_controller(MyWidget, 'mywidget')
-
-Sometimes it is useful to dynamically acquire what URL path a Widget's
-controller is mounted on.  For this you can use::
-
-    MyWidget.controller_path()
-
-**Methods to override**
-
-    `view_request`
-        Instance method - get self and req. load from db
-
-    `validated_request`
-        Class method - get cls and validated data
-
-    `ajax_request`
-        Return python data that is automatically converted to an ajax response
-
-
-Validation
-==========
-
-One of the main features of any forms library is the validation of form input, e.g checking that an email address is valid, or that a user name is not already taken. If there are validation errors, these must be displayed to the user in a helpful way. Many validation tasks are common, so these should be easy for the developer, while less-common tasks are still possible.
-
-We can configure validation on form fields like this::
-
-    class child(twf.TableForm):
-        name = twf.TextField(validator=twc.Required)
-        group = twf.SingleSelectField(options=['', 'Red', 'Green', 'Blue'])
-        notes = twf.TextArea(validator=twc.StringLengthValidator(min=10))
-
-To enable validation we also need to modify the application to handle POST requests::
-
-    def app(environ, start_response):
-        req = wo.Request(environ)
-        resp = wo.Response(request=req, content_type="text/html; charset=UTF8")
-        if req.method == 'GET':
-            resp.body = MyForm.display().encode('utf-8')
-        elif req.method == 'POST':
-            try:
-                data = MyForm.validate(req.POST)
-                resp.body = 'Posted successfully ' + wo.html_escape(repr(data))
-            except twc.ValidationError, e:
-                resp.body = e.widget.display().encode('utf-8')
-        return resp(environ, start_response)
-
-If you submit the form with some invalid fields, you should see error messages sidle up to each relevant field.
-
-**Whole Form Message**
-
-If you want to display a message at the top of the form, when there are any errors, define the following validator::
-
-    class MyFormValidator(twc.Validator):
-        msgs = {
-            'childerror': ('form_childerror', 'There were problems with the details you entered. Review the messages below to correct your submission.'),
-        }
-
-And in your form::
-
-    validator = MyFormValidator()
-
-
-**Conversion**
-
-Validation is also responsible for conversion to and from python types. For example, the DateValidator takes a string from the form and produces a python date object. If it is unable to do this, that is a validation failure.
-
-To keep related functionality together, validators also support coversion from python to string, for display. This should be complete, in that there are no python values that cause it to fail. It should also be precise, in that converting from python to string, and back again, should always give a value equal to the original python value. The converse is not always true, e.g. the string "1/2/2004" may be converted to a python date object, then back to "01/02/2004".
-
-**Validation Errors**
-
-When there is an error, all fields should still be validated and multiple errors displayed, rather than stopping after the first error.
-
-When validation fails, the user should see the invalid values they entered. This is helpful in the case that a field is entered only slightly wrong, e.g. a number entered as "2,000" when commas are not allowed. In such cases, conversion to and from python may not be possible, so the value is kept as a string. Some widgets will not be able to display an invalid value (e.g. selection fields); this is fine, they just have to do the best they can.
-
-When there is an error is some fields, other valid fields can potentially normalise their value, by converting to python and back again (e.g. 01234 -> 1234). However, it was decided to use the original value in this case.
-
-In some cases, validation may encounter a major error, as if the web user has tampered with the HTML source. However, we can never be completely sure this is the case, perhaps they have a buggy browser, or caught the site in the middle of an upgrade. In these cases, validation will produce the most helpful error messages it can, but not attempt to identify which field is at fault, nor redisplay invalid values.
-
-**Required Fields**
-
-If a field has no value, if defaults to ``None``. It is down to that field's validator to raise an error if the field is required. By default, fields are not required. It was considered to have a dedicated ``Missing`` class, but this was decided against, as ``None`` is already intended to convey the absence of data.
-
-**Security Consideration**
-
-When a widget is redisplayed after a validation failure, it's value is derived from unvalidated user input. This means widgets must be "safe" for all input values. In practice, this is almost always the case without great care, so widgets are assumed to be safe. 
-
-.. warning::
-    If a particular widget is not safe in this way, it must override :meth:`_validate` and set :attr:`value` to *None* in case of error.
-
-**Validation Messages**
-
-When validation fails, the validator raises :class:`ValidationError`. This must be passed the short message name, e.g. "required". Each validator has a dictionary mapping short names to messages that are presented to the user, e.g.::
-
-    msgs = {
-        'tooshort': 'Value is too short',
-        'toolong': 'Value is too long',
-    }
-
-Messages can be overridden on a global basis, using :attr:`validator_msgs` on the middleware configuration. For example, the user may prefer "Value is required" instead of the default "Enter a value" for a missing field.
-
-A Validator can also rename mesages, by specifying a tuple in the :attr:`msgs` dict. For example, :class:`ListLengthValidator` is a subclass of :class:`LengthValidator` which raises either ``tooshort`` or ``toolong``. However, it's desired to have different message names, so that any global override would be applied separately. The following :attr:`msgs` dict is used::
-
-    msgs = {
-        'tooshort': ('list_tooshort', 'Select at least $min'),
-        'toolong': ('list_toolong', 'Select no more than $max'),
-    }
-
-Within the messages, tags like ``$min`` are substituted with the corresponding attribute from the validator. It is not possible to specify the value in this way; this is to discourage using values within messages.
-
-**FormEncode**
-
-Earlier versions of ToscaWidgets used FormEncode for validation and there are good reasons for this. Some aspects of the design work very well, and FormEncode has a lot of clever validators, e.g. the ability to check that a post code is in the correct format for a number of different countries.
-
-However, there are challenges making FormEncode and ToscaWidgets work together. For example, both libraries store the widget hierarchy internally. This makes implementing some features (e.g. ``strip_name`` and :class:`tw2.dynforms.HidingSingleSelectField`) difficult. There are different needs for the handling of unicode, leading ToscaWidgets to override some behaviour. Also, FormEncode just does not support client-side validation, a planned feature of ToscaWidgets 2.
-
-ToscaWidgets 2 does not rely on FormEncode. However, developers can use FormEncode validators for individual fields. The API is compatible in that :meth:`to_python` and :meth:`from_python` are called for conversion, and :class:`formencode.Invalid` is caught. Also, if FormEncode is installed, the :class:`ValidationError` class is a subclass of :class:`formencode.Invalid`.
-
-
-Using Validators
-~~~~~~~~~~~~~~~~
-
-There's two parts to using validators. First, specify validators in the widget definition, like this::
-
-    class RegisterUser(twf.TableForm):
-        validator = twc.MatchValidator('email', 'confirm_email')
-        name = twf.TextField()
-        email = twf.TextField(validator=twc.EmailValidator)
-        confirm_email = twf.PasswordField()
-
-You can specify a validator on any widget, either a class or an instance. Using an instance lets you pass parameters to the validator. You can code your own validator by subclassing :class:`tw2.core.Validator`. All validators have at least these parameters:
-
-.. autoclass:: tw2.core.Validator
-
-Second, when the form values are submitted, call :meth:`validate` on the outermost widget. Pass this a dictionary of the request parameters. It will call the same method on all contained widgets, and either return the validated data, with all conversions applied, or raise :class:`tw2.core.ValidationError`. In the case of a validation failure, it stores the invalid value and an error message on the affected widget.
-
-**Chaining Validators**
-
-In some cases you may want validation to succeed if any one of a number of
-checks pass.  In other cases you may want validation to succeed only if the
-input passes `all` of a number of checks.  For this, :mod:`tw2.core` provides
-the :class:`Any` and :class:`All` validators which are subclasses of the
-extendable :class:`CompoundValidator`.
-
-Implementation
-~~~~~~~~~~~~~~
-
-A two-pass approach is used internally, although this is generally hidden from the developer. When :meth:`Widget.validate` is called it first calls:
-
-.. autofunction:: tw2.core.validation.unflatten_params
-
-If this fails, there is no attempt to determine which parameter failed; the whole submission is considered corrupt. If the root widget has an ``id``, this is stripped from the dictionary, e.g. ``{'myid': {'param':'value', ...}}`` is converted to ``{'param':'value', ...}``. A widget instance is created, and stored in request local storage. This allows compatibility with existing frameworks, e.g. the ``@validate`` decorator in TurboGears. There is a hook in :meth:`display` that detects the request local instance. After creating the instance, validate works recursively, using the :meth:`_validate`. 
-
-.. automethod:: tw2.core.Widget._validate
-
-.. automethod:: tw2.core.RepeatingWidget._validate
-
-.. automethod:: tw2.core.CompoundWidget._validate
-
-Both :meth:`_validate` and :meth:`validate_python` take an optional state argument. :class:`CompoundWidget` and :class:`RepeatingWidget` pass the partially built dict/list to their child widgets as state. This is useful for creating validators like :class:`MatchValidator` that reference sibling values. If one of the child widgets fails validation, the slot is filled with an :class:`Invalid` instance.
-
-
-General Considerations
-======================
-
-**Request-Local Storage**
-
-ToscaWidgets needs access to request-local storage. In particular, it's important that the middleware sees the request-local information that was set when a widget is instatiated, so that resources are collected correctly.
-
-The function tw2.core.request_local returns a dictionary that is local to the current request. Multiple calls in the same request always return the same dictionary. The default implementation of request_local is a thread-local system, which the middleware clears before and after each request.
-
-In some situations thread-local is not appropriate, e.g. twisted. In this case the application will need to monkey patch request_local to use appropriate request_local storage.
-
-**pkg_resources**
-
-tw2.core aims to take advantage of pkg_resources where it is available, but not to depend on it. This allows tw2.core to be used on Google App Engine. pkg_resources is used in two places:
-
- * In ResourcesApp, to serve resources from modules, which may be zipped eggs. If pkg_resources is not available, this uses a simpler system that does not support zipped eggs.
- * In EngingeManager, to load a templating engine from a text string, e.g. "genshi". If pkg_resources is not available, this uses a simple, built-in mapping that covers the most common template engines.
-
-**Framework Interface**
-
-ToscaWidgets is designed to be standalone WSGI middeware and not have any framework interactions. However, when using ToscaWidgets with a framework, there are some configuration settings that need to be consistent with the framework, for correct interaction. Future vesions of ToscaWidgets may include framework-specific hooks to automatically gather this configuration. The settings are:
-
- * default_view - the template engine used by the framework. When root widgets are rendered, they will return a type suitable for including in this template engine. This setting is not needed if only Page widgets are used as root widgets, as there is no containing template in that case.
- * translator - needed for ToscaWidget to use the same i18n function as the framework.
-
-**Unit Tests**
-
-To run the tests, in ``tw2.devtools/tests`` issue::
-
-    nosetests --with-doctest --doctest-extension=.txt
+Design
+------
+
+Widget Overview
+===============
+
+The main purpose of a widget is to display a functional control within an HTML page. A widget has a template to generate its own HTML, and a set of parameters that control how it will be displayed. It can also reference resources - JavaScript or CSS files that support the widget.
+
+When defining Widgets, some parameters with be static - they will stay constant for the whole lifetime of the application. Some parameters are dynamic - they may change for every request. To ensure thread-safety, a separate widget instance is created for every request, and dynamic parameters are only set on an instance. Static parameters are set by subclassing a widget. For example::
+
+    # Initialisation
+    class MyWidget(Widget):
+        id = 'myid'
+
+    # In a request
+    my_widget = MyWidget.req()
+    my_widget.value = 'my value'
+
+To make initialisation more concise, the ``__new__`` method on ``Widget`` is overriden, so it creates subclasses, rather than instances. The following code is equivalent to that above::
+
+    # Initialisation
+    MyWidget = Widget(id='myid')
+
+In practice, you will rarely need to explictly create an instance, using ``req()``. If the ``display`` or ``validate`` methods are called on a Widget class, they automatically create an instance. For example, the following are equivalent::
+
+    # Explicit creation
+    my_widget = MyWidget.req()
+    my_widget.value = 'my value'
+    my_widget.display()
+
+    # Implicit creation
+    MyWidget.display(value='my value')
+
+
+Parameters
+~~~~~~~~~~
+
+The parameters are how the user of the widget controls its display and behaviour. Parameters exist primarily for documentation purposes, although they do have some run-time effects. When creating widgets, it's important to decide on a convenient set of parameters for the user of the widget, and to document these.
+
+A parameter definition looks like this::
+
+    import tw2.core as twc
+    class MyTextField(twc.Widget):
+        size = twc.Param('The size of the field', default=30)
+        validator = twc.LengthValidator(max=30)
+        highlight = twc.Variable('Region to highlight')
+
+In this case, :class:`TextField` gets all the parameters of its base class, :class:`tw2.core.widget` and defines a new parameter - :attr:`size`. A widget can also override parameter in its base class, either with another :class:`tw2.core.Param` instance, or a new default value.
+
+.. autoclass:: tw2.core.Param
+.. autoclass:: tw2.core.Variable
+.. autoclass:: tw2.core.ChildParam
+.. autoclass:: tw2.core.ChildVariable
+
+
+Code Hooks
+~~~~~~~~~~
+
+Subclasses of Widget can override the following methods. It is not recommended to override any other methods, e.g. display, validate, __init__.
+
+.. automethod:: tw2.core.widgets.Widget.post_define
+.. automethod:: tw2.core.widgets.Widget.prepare
+.. automethod:: tw2.core.widgets.Widget.generate_output
+
+**Mutable Members**
+
+If a widget's :meth:`prepare` method modifies a mutable member on the widget, it must take care not to modify a class member, as this is not thread safe. In general, the code should call :attr:`self.safe_modify(member_name)`, which detects class members and creates a copy on the instance. Users of widgets should be aware that if a mutable is set on an instance, the widget may modify this. The most common case of a mutable member is :attr:`attrs`. While this arrangement is thread-safe and reasonably simple, copying may be bad for performance. In some cases, widgets may deliberately decide not to call :meth:`safe_modify`, if the implications of this are understood.
+
+
+Widget Hierarchy
+================
+
+Widgets can be arranged in a hierarchy. This is useful for applications like layouts, where the layout will be a parent widget and fields will be children of this. There are four roles a widget can take in the hierarchy, depending on the base class used:
+
+.. autoclass:: tw2.core.Widget
+.. autoclass:: tw2.core.CompoundWidget
+.. autoclass:: tw2.core.RepeatingWidget
+.. autoclass:: tw2.core.DisplayOnlyWidget
+
+**Value Propagation**
+
+An important feature of the hierarchy is value propagation. When the value is set for a compound or repeating widget, this causes the value to be set for the child widgets. In general, a leaf widget takes a scalar type as a value, a compound widget takes a dict or an  object, and a repeating widget takes a list.
+
+The hierarchy also affects the generation of compound ids, and validation.
+
+**Identifier**
+
+In general, a widget needs to have an identifier. Without an id, it cannot participate in value propagation or validation, and it does not get an HTML id attribute. There are some exceptions to this:
+
+ * Some widgets do not need an id (e.g. Label, Spacer) and provide a default id of None.
+ * The child of a RepeatingWidget must not have an id.
+ * An id can be specified either on a DisplayOnlyWidget, or it's child, but not both. The widget that does not have the id specified automatically picks it up from the other.
+
+Compound IDs are formed by joining the widget's id with those of its ancestors. These are used in two situations:
+
+ * For the HTML id attribute, and also the name attribute for form fields
+ * For the URL path a controller widget is registered at
+
+The separator is a colon (:), resulting in compound ids like "form:sub_form:field". **Note** this causes issues with CSS and will be changed shortly, and made configurable.
+
+In generel, the id on a DisplayOnlyWidget is not included in the compound id. However, when generating the compound id for a DisplayOnlyWidget, the id is included. In addition *id_suffix* is appended, to avoid generating duplicate IDs. The *id_suffix* is not appended for URL paths, to keep the paths short. There is a risk of duplicate IDs, but this is not expected to be a problem in practice.
+
+For children of a RepeatingWidget, the repetition is used instead of the id, for generating the compound HTML id. For the URL path, the element is skipped entirely.
+
+
+**Deep Children**
+
+This is a feature that helps have a form layout that doesn't exactly match the database layout. For example, we might have a sinlge database table, with fields like title, customer, start_date, end_date. We want to display this in a Form that's broken up into two FieldSets. Without deep children, the FieldSets would have to have ids, and field makes would be dotted, like info.title. The deep children feature lets us set the id to None::
+
+    class MyForm(twf.Form):
+        class child(twc.CompoundWidget):
+            class info(twf.TableFieldSet):
+                id = None
+                title = twf.TextField()
+                customer = twf.TextField()
+            class dates(twf.TableFieldSet):
+                id = None
+                start_date = twf.TextField()
+                end_date = twf.TextField()
+
+When a value like ``{'title': 'my title'}`` is passed to MyForm, this will propagate correctly.
+
+
+Template
+========
+
+Every widget can have a template. ToscaWidgets aims to support any templating engine that support the ``buffet`` interface, which is an initiative by the TurboGears project to create a standard interface for template libraries. In practice, there are more differences between template engines than the buffet interface standardises. So, ToscaWidgets has some template-language hooks, and support is primarily for: Genshi, Mako, Kid and Cheetah.
+
+The :attr:`template` parameter takes the form ``engine_name:template_path``. The ``engine_name`` is the name that the template engine defines in the ``python.templating.engines`` entry point, e.g. ``genshi`` or ``mako``. The ``template_path`` is a string the engine can use to locate the template; usually this is dot-notation that mimics the semantics of Python's import statement, e.g. ``myapp.templates.mytemplate``. Genshi templates allow specifications like ``./template.html`` which is beneficial for simple applications.
+
+It is also possible to allow your widget to utilize multiple templates, or to have TW2 support any template language you provide a template for.  To do this, simply leave the name of the template engine off of the template parameter, and TW2 will select the appropriate template, based on specifications in the TW2 middleware.
+
+For instance, you might have a form.mak and a form.html template (mako and genshi). TW2 will render the mako template if mako is listed ahead of genshi in the middleware config's ``preferred_rendering_engines``.  See the documentation regarding :ref:`middleware` for more information on how to set up your middleware for desired output.
+
+.. autoclass:: tw2.core.template.EngineManager
+   :members: render, _get_adaptor_renderer
+
+
+Non-template Output
+===================
+
+Instead of using a template, a widget can also override the ``generate_output`` method. This function generates the HTML output for a widget; by default, it renders the widget's template as described in the previous section, but can be overridden by any function that returns a string of HTML.
+
+
+Resources
+=========
+
+Widgets often need to access resources, such as JavaScript or CSS files. A key feature of widgets is the ability to automatically serve such resources, and insert links into appropriate sections of the page, e.g. ``<HEAD>``. There are several parts to this:
+
+ * Widgets can define resources they use, using the :attr:`resources` parameter.
+ * When a resource is defined, it is registered with the resource server.
+ * When a Widget is displayed, it registers resources in request-local storage.
+ * The resource injection middleware detects resources in request-local storage, and rewrites the generated page to include appropriate links.
+ * The resource server middleware serves static files used by widgets
+ * Widgets can also access resources at display time, e.g. to get links
+ * Resources can themselves declare dependency on other resources, e.g.
+   jquery-ui.js depends on jquery.js and must be included on the page
+   subsequently.
+
+**Defining Resources**
+
+To define a resource, just add a :class:`tw2.core.Resource` subclass to the widget's :attr:`resources` parameter. It is also possible to append to :attr:`resources` from within the :meth:`prepare` method. The following resource types are available:
+
+.. autoclass:: tw2.core.CSSLink
+.. autoclass:: tw2.core.CSSSource
+.. autoclass:: tw2.core.JSLink
+.. autoclass:: tw2.core.JSSource
+.. autoclass:: tw2.core.JSFuncCall
+
+Resources are widgets, but follow a slightly different lifecycle. Resource subclasses are passed into the :attr:`resources` parameter. An instance is created for each request, but this is only done at the time of the parent Widget's :meth:`display` method. This gives widgets a chance to add dynamic resources in their :meth:`prepare` method.
+
+**Using Your Own Resources**
+
+Resources that are defined by pre-existing tw2 packages can be altered globally.
+For instance, say that you want to use your own patched version of jquery and
+you want all tw2 packages that require jquery to use your version, and not the
+one already packaged up in ``tw2.jquery``.  The following code will alter
+``jquery_js`` in not just the local scope, but also in all other modules that
+use it (including ``tw2.jqplugins.ui``)::
+
+    import tw2.jquery
+    tw2.jquery.jquery_js.link = "/path/to/my/patched/jquery.js"
+
+**Deploying Resources**
+
+If running behind mod_wsgi, tw2 resource provisioning will typically fail.
+Resources are only served when they are registered with the request-local
+thread, and resources are only registered when their dependant widget is
+displayed in a request.  An initial page request may make available resource
+``A``, but the subsequent request to actually retrieve resource ``A`` will not
+have that resource registered.
+
+To solve this problem (and to introduce a speed-up for production deployment),
+Toscawidgets2 provides an ``archive_tw2_resources`` distutils command::
+
+    $ python setup.py archive_tw2_resources \
+        --distributions=myapplication \
+        --output=/var/www/myapplication
+
+.. _middleware:
+
+Middleware
+==========
+
+
+The WSGI middleware has three functions:
+
+ * Request-local storage
+ * Configuration
+ * Resource injection
+
+**Configuration**
+
+In general, ToscaWidgets configuration is done on the middleware instance. At the beginning of each request, the middleware stores a reference to itself in request-local storage. So, during a request, a widget can consult request-local storage, and get the configuration for the middleware active in that request. This allows multiple applications to use ToscaWidgets, with different configurations, in a single Python environment.
+
+Configuration is passed as keyword arguments to the middleware constructor. The available parameters are:
+
+.. autoclass:: tw2.core.middleware.Config
+
+
+Declarative Instantiation
+=========================
+
+Instantiating compound widgets can result in less-than-beautiful code. To help alleviate this, widgets can be defined declaratively, and this is the recommended approach. A definition looks like this::
+
+    class MovieForm(twf.TableForm):
+        id = twf.HiddenField()
+        year = twf.TextField()
+        desc = twf.TextArea(rows=5)
+
+Any class members that are subclasses of Widget become children. All the children get their ``id`` from the name of the member variable. Note: it is important that all children are defined like ``id = twf.HiddenField()`` and not ``id = twf.HiddenField``. Otherwise, the order of the children will not be preserved.
+
+It is possible to define children that have the same name as parameters, using this syntax. However, doing so does prevent a widget overriding a parameter, and defining a child with the same name. If you need to do this, you must use a throwaway name for the member variable, and specify the id explicitly, e.g.::
+
+    class MovieForm(twf.TableForm):
+        resources = [my_resource]
+        id = twf.HiddenField()
+        noname = twf.TextArea(id='resources')
+
+
+**Nesting and Inheritence**
+
+Nested declarative definitions can be used, like this::
+
+    class MyForm(twf.Form):
+        class child(twf.TableLayout):
+            b = twf.TextArea()
+            x = twf.Label(text='this is a test')
+            c = twf.TextField()
+
+Inheritence is supported - a subclass gets the children from the base class, plus any defined on the subclass. If there's a name clash, the subclass takes priority. Multiple inheritence resolves name clashes in a similar way. For example::
+
+    class MyFields(twc.CompoundWidget):
+        b = twf.TextArea()
+        x = twf.Label(text='this is a test')
+        c = twf.TextField()
+
+    class TableFields(MyFields, twf.TableLayout):
+        pass
+
+    class ListFields(MyFields, twf.ListLayout):
+        b = twf.TextField()
+
+**Proxying children**
+
+Without this feature, double nesting of classes is often necessary, e.g.::
+
+    class MyForm(twf.Form):
+        class child(twf.TableLayout):
+            b = twf.TextArea()
+
+Proxying children means that if :class:`RepeatingWidget` or :class:`DisplayOnlyWidget` have :attr:`children` set, this is passed to their :attr:`child`. The following is equivalent to the definition above::
+
+    class MyForm(twf.Form):
+        child = twf.TableLayout()
+        b = twf.TextArea()
+
+And this is used by classes like :class:`TableForm` and :class:`TableFieldSet` to allow the user more concise widget definitions::
+
+    class MyForm(twf.TableForm):
+        b = twf.TextArea()
+
+
+**Automatic ID**
+
+Sub classes of :class:`Page` that do not have an id, will have the id automatically set to the name of the class. This can be disabled by setting :attr:`_no_autoid` on the class. This only affects that specific class, not any subclasses.
+
+
+Widgets as Controllers
+======================
+
+Sometimes widgets will want to define controller methods. This is particularly useful for Ajax widgets. Any widget can have a :meth:`request` method, which is called with a WebOb :class:`Request` object, and must return a WebOb :class:`Response` object, like this::
+
+    class MyWidget(twc.Widget):
+        id = 'my_widget'
+        @classmethod
+        def request(cls, req):
+            resp = webob.Response(request=req, content_type="text/html; charset=UTF8")
+            # ...
+            return resp
+
+For the :meth:`request` method to be called, the widget must be registered with the :class:`ControllersApp` in the middleware. By default, the path is constructed from /controllers/, and the widget's id. A request to /controllers/ refers to a widget with id ``index``. You can specify :attr:`controllers_prefix` in the configuration.
+
+For convenience, widgets that have a :meth:`request` method, and an :attr:`id` will be registered automatically. By default, this uses a global :class:`ControllersApp` instance, which is also the default controllers for :func:`make_middleware`. If you want to use multiple controller applications in a single python instance, you will need to override this.
+
+You can also manually register widgets::
+
+    twc.core.register_controller(MyWidget, 'mywidget')
+
+Sometimes it is useful to dynamically acquire what URL path a Widget's
+controller is mounted on.  For this you can use::
+
+    MyWidget.controller_path()
+
+**Methods to override**
+
+    `view_request`
+        Instance method - get self and req. load from db
+
+    `validated_request`
+        Class method - get cls and validated data
+
+    `ajax_request`
+        Return python data that is automatically converted to an ajax response
+
+
+Validation
+==========
+
+One of the main features of any forms library is the validation of form input, e.g checking that an email address is valid, or that a user name is not already taken. If there are validation errors, these must be displayed to the user in a helpful way. Many validation tasks are common, so these should be easy for the developer, while less-common tasks are still possible.
+
+We can configure validation on form fields like this::
+
+    class child(twf.TableForm):
+        name = twf.TextField(validator=twc.Required)
+        group = twf.SingleSelectField(options=['', 'Red', 'Green', 'Blue'])
+        notes = twf.TextArea(validator=twc.StringLengthValidator(min=10))
+
+To enable validation we also need to modify the application to handle POST requests::
+
+    def app(environ, start_response):
+        req = wo.Request(environ)
+        resp = wo.Response(request=req, content_type="text/html; charset=UTF8")
+        if req.method == 'GET':
+            resp.body = MyForm.display().encode('utf-8')
+        elif req.method == 'POST':
+            try:
+                data = MyForm.validate(req.POST)
+                resp.body = 'Posted successfully ' + wo.html_escape(repr(data))
+            except twc.ValidationError, e:
+                resp.body = e.widget.display().encode('utf-8')
+        return resp(environ, start_response)
+
+If you submit the form with some invalid fields, you should see error messages sidle up to each relevant field.
+
+**Whole Form Message**
+
+If you want to display a message at the top of the form, when there are any errors, define the following validator::
+
+    class MyFormValidator(twc.Validator):
+        msgs = {
+            'childerror': ('form_childerror', 'There were problems with the details you entered. Review the messages below to correct your submission.'),
+        }
+
+And in your form::
+
+    validator = MyFormValidator()
+
+
+**Conversion**
+
+Validation is also responsible for conversion to and from python types. For example, the DateValidator takes a string from the form and produces a python date object. If it is unable to do this, that is a validation failure.
+
+To keep related functionality together, validators also support coversion from python to string, for display. This should be complete, in that there are no python values that cause it to fail. It should also be precise, in that converting from python to string, and back again, should always give a value equal to the original python value. The converse is not always true, e.g. the string "1/2/2004" may be converted to a python date object, then back to "01/02/2004".
+
+**Validation Errors**
+
+When there is an error, all fields should still be validated and multiple errors displayed, rather than stopping after the first error.
+
+When validation fails, the user should see the invalid values they entered. This is helpful in the case that a field is entered only slightly wrong, e.g. a number entered as "2,000" when commas are not allowed. In such cases, conversion to and from python may not be possible, so the value is kept as a string. Some widgets will not be able to display an invalid value (e.g. selection fields); this is fine, they just have to do the best they can.
+
+When there is an error is some fields, other valid fields can potentially normalise their value, by converting to python and back again (e.g. 01234 -> 1234). However, it was decided to use the original value in this case.
+
+In some cases, validation may encounter a major error, as if the web user has tampered with the HTML source. However, we can never be completely sure this is the case, perhaps they have a buggy browser, or caught the site in the middle of an upgrade. In these cases, validation will produce the most helpful error messages it can, but not attempt to identify which field is at fault, nor redisplay invalid values.
+
+**Required Fields**
+
+If a field has no value, if defaults to ``None``. It is down to that field's validator to raise an error if the field is required. By default, fields are not required. It was considered to have a dedicated ``Missing`` class, but this was decided against, as ``None`` is already intended to convey the absence of data.
+
+**Security Consideration**
+
+When a widget is redisplayed after a validation failure, it's value is derived from unvalidated user input. This means widgets must be "safe" for all input values. In practice, this is almost always the case without great care, so widgets are assumed to be safe. 
+
+.. warning::
+    If a particular widget is not safe in this way, it must override :meth:`_validate` and set :attr:`value` to *None* in case of error.
+
+**Validation Messages**
+
+When validation fails, the validator raises :class:`ValidationError`. This must be passed the short message name, e.g. "required". Each validator has a dictionary mapping short names to messages that are presented to the user, e.g.::
+
+    msgs = {
+        'tooshort': 'Value is too short',
+        'toolong': 'Value is too long',
+    }
+
+Messages can be overridden on a global basis, using :attr:`validator_msgs` on the middleware configuration. For example, the user may prefer "Value is required" instead of the default "Enter a value" for a missing field.
+
+A Validator can also rename mesages, by specifying a tuple in the :attr:`msgs` dict. For example, :class:`ListLengthValidator` is a subclass of :class:`LengthValidator` which raises either ``tooshort`` or ``toolong``. However, it's desired to have different message names, so that any global override would be applied separately. The following :attr:`msgs` dict is used::
+
+    msgs = {
+        'tooshort': ('list_tooshort', 'Select at least $min'),
+        'toolong': ('list_toolong', 'Select no more than $max'),
+    }
+
+Within the messages, tags like ``$min`` are substituted with the corresponding attribute from the validator. It is not possible to specify the value in this way; this is to discourage using values within messages.
+
+**FormEncode**
+
+Earlier versions of ToscaWidgets used FormEncode for validation and there are good reasons for this. Some aspects of the design work very well, and FormEncode has a lot of clever validators, e.g. the ability to check that a post code is in the correct format for a number of different countries.
+
+However, there are challenges making FormEncode and ToscaWidgets work together. For example, both libraries store the widget hierarchy internally. This makes implementing some features (e.g. ``strip_name`` and :class:`tw2.dynforms.HidingSingleSelectField`) difficult. There are different needs for the handling of unicode, leading ToscaWidgets to override some behaviour. Also, FormEncode just does not support client-side validation, a planned feature of ToscaWidgets 2.
+
+ToscaWidgets 2 does not rely on FormEncode. However, developers can use FormEncode validators for individual fields. The API is compatible in that :meth:`to_python` and :meth:`from_python` are called for conversion, and :class:`formencode.Invalid` is caught. Also, if FormEncode is installed, the :class:`ValidationError` class is a subclass of :class:`formencode.Invalid`.
+
+
+Using Validators
+~~~~~~~~~~~~~~~~
+
+There's two parts to using validators. First, specify validators in the widget definition, like this::
+
+    class RegisterUser(twf.TableForm):
+        validator = twc.MatchValidator('email', 'confirm_email')
+        name = twf.TextField()
+        email = twf.TextField(validator=twc.EmailValidator)
+        confirm_email = twf.PasswordField()
+
+You can specify a validator on any widget, either a class or an instance. Using an instance lets you pass parameters to the validator. You can code your own validator by subclassing :class:`tw2.core.Validator`. All validators have at least these parameters:
+
+.. autoclass:: tw2.core.Validator
+
+Second, when the form values are submitted, call :meth:`validate` on the outermost widget. Pass this a dictionary of the request parameters. It will call the same method on all contained widgets, and either return the validated data, with all conversions applied, or raise :class:`tw2.core.ValidationError`. In the case of a validation failure, it stores the invalid value and an error message on the affected widget.
+
+**Chaining Validators**
+
+In some cases you may want validation to succeed if any one of a number of
+checks pass.  In other cases you may want validation to succeed only if the
+input passes `all` of a number of checks.  For this, :mod:`tw2.core` provides
+the :class:`Any` and :class:`All` validators which are subclasses of the
+extendable :class:`CompoundValidator`.
+
+Implementation
+~~~~~~~~~~~~~~
+
+A two-pass approach is used internally, although this is generally hidden from the developer. When :meth:`Widget.validate` is called it first calls:
+
+.. autofunction:: tw2.core.validation.unflatten_params
+
+If this fails, there is no attempt to determine which parameter failed; the whole submission is considered corrupt. If the root widget has an ``id``, this is stripped from the dictionary, e.g. ``{'myid': {'param':'value', ...}}`` is converted to ``{'param':'value', ...}``. A widget instance is created, and stored in request local storage. This allows compatibility with existing frameworks, e.g. the ``@validate`` decorator in TurboGears. There is a hook in :meth:`display` that detects the request local instance. After creating the instance, validate works recursively, using the :meth:`_validate`. 
+
+.. automethod:: tw2.core.Widget._validate
+
+.. automethod:: tw2.core.RepeatingWidget._validate
+
+.. automethod:: tw2.core.CompoundWidget._validate
+
+Both :meth:`_validate` and :meth:`validate_python` take an optional state argument. :class:`CompoundWidget` and :class:`RepeatingWidget` pass the partially built dict/list to their child widgets as state. This is useful for creating validators like :class:`MatchValidator` that reference sibling values. If one of the child widgets fails validation, the slot is filled with an :class:`Invalid` instance.
+
+
+General Considerations
+======================
+
+**Request-Local Storage**
+
+ToscaWidgets needs access to request-local storage. In particular, it's important that the middleware sees the request-local information that was set when a widget is instatiated, so that resources are collected correctly.
+
+The function tw2.core.request_local returns a dictionary that is local to the current request. Multiple calls in the same request always return the same dictionary. The default implementation of request_local is a thread-local system, which the middleware clears before and after each request.
+
+In some situations thread-local is not appropriate, e.g. twisted. In this case the application will need to monkey patch request_local to use appropriate request_local storage.
+
+**pkg_resources**
+
+tw2.core aims to take advantage of pkg_resources where it is available, but not to depend on it. This allows tw2.core to be used on Google App Engine. pkg_resources is used in two places:
+
+ * In ResourcesApp, to serve resources from modules, which may be zipped eggs. If pkg_resources is not available, this uses a simpler system that does not support zipped eggs.
+ * In EngingeManager, to load a templating engine from a text string, e.g. "genshi". If pkg_resources is not available, this uses a simple, built-in mapping that covers the most common template engines.
+
+**Framework Interface**
+
+ToscaWidgets is designed to be standalone WSGI middeware and not have any framework interactions. However, when using ToscaWidgets with a framework, there are some configuration settings that need to be consistent with the framework, for correct interaction. Future vesions of ToscaWidgets may include framework-specific hooks to automatically gather this configuration. The settings are:
+
+ * default_view - the template engine used by the framework. When root widgets are rendered, they will return a type suitable for including in this template engine. This setting is not needed if only Page widgets are used as root widgets, as there is no containing template in that case.
+ * translator - needed for ToscaWidget to use the same i18n function as the framework.
+
+**Unit Tests**
+
+To run the tests, in ``tw2.devtools/tests`` issue::
+
+    nosetests --with-doctest --doctest-extension=.txt

docs/devtools.rst

-.. index:
-
-tw2.devtools
-============
-
-To keep tw2.core as minimal as possible, features needed only for development are in a separate package, tw2.devtools. The features in devtools are:
-
- * Widget browser
- * Widget library quick start
-
-
-Widget Browser
---------------
-
-The browser essentially enumerates the ``tw2.widgets`` entrypoint. When browsing a module, it iterates through the public names in the module, and displays any that is a Widget subclass. It also imports ``samples.py`` for demo widgets. This can contain :attr:`page_options` - a dict that gives attributes for the body tag in the containing page.
-
-The parameters that are displayed are: all the required parameters, plus non-required parameters that are defined on anything other than the Widget base class. Variables are never shown.
-
-
-Widget Library Quick Start
---------------------------
-
-To create a widget library, issue::
-
-    $ paster create -t tw2.library tw2.mylib
-
-This creates an empty template that gets you started.
-
-
-Writing a good widget library
------------------------------
-
-`Widget browser`
-    This is the main documentation for the library, and it needs to give a good introduction to a new user. Every widget should have a demo, and a clear description of the widget and parameters.
-
-`Example application`
-    There should be a simple example application that demonstrates the widgets in action. Ideally this should just be a single python file that works standalone.
-
-`Parameters`
-    Every widget should have a convenient set of parameters that allow common customisation with ease, and make more complex configuration possible.
-
-`Validation`
-    Every widget needs to work correctly with validation. When a form is submitted and there is a validation failure, all widgets should maintain the same appearance. This includes a widget with no value continuing to have no value.
-
-`Growing`
-    Every widget should work correctly within a tw2.dynforms Growing container.
-
-`Database interaction`
-    Some widgets (e.g. AjaxLookup, DataGrid) can benefit from built-in database interaction. In this case, the widget library must include a base widget that does no database interaction, so it can be connected to any database/ORM. The library should include a widget that interacts with SQLAlchemy, and may include a widget that interacts with any other database/ORM.
+.. index:
+
+tw2.devtools
+============
+
+To keep tw2.core as minimal as possible, features needed only for development are in a separate package, tw2.devtools. The features in devtools are:
+
+ * Widget browser
+ * Widget library quick start
+
+
+Widget Browser
+--------------
+
+The browser essentially enumerates the ``tw2.widgets`` entrypoint. When browsing a module, it iterates through the public names in the module, and displays any that is a Widget subclass. It also imports ``samples.py`` for demo widgets. This can contain :attr:`page_options` - a dict that gives attributes for the body tag in the containing page.
+
+The parameters that are displayed are: all the required parameters, plus non-required parameters that are defined on anything other than the Widget base class. Variables are never shown.
+
+
+Widget Library Quick Start
+--------------------------
+
+To create a widget library, issue::
+
+    $ paster create -t tw2.library tw2.mylib
+
+This creates an empty template that gets you started.
+
+
+Writing a good widget library
+-----------------------------
+
+`Widget browser`
+    This is the main documentation for the library, and it needs to give a good introduction to a new user. Every widget should have a demo, and a clear description of the widget and parameters.
+
+`Example application`
+    There should be a simple example application that demonstrates the widgets in action. Ideally this should just be a single python file that works standalone.
+
+`Parameters`
+    Every widget should have a convenient set of parameters that allow common customisation with ease, and make more complex configuration possible.
+
+`Validation`
+    Every widget needs to work correctly with validation. When a form is submitted and there is a validation failure, all widgets should maintain the same appearance. This includes a widget with no value continuing to have no value.
+
+`Growing`
+    Every widget should work correctly within a tw2.dynforms Growing container.
+
+`Database interaction`
+    Some widgets (e.g. AjaxLookup, DataGrid) can benefit from built-in database interaction. In this case, the widget library must include a base widget that does no database interaction, so it can be connected to any database/ORM. The library should include a widget that interacts with SQLAlchemy, and may include a widget that interacts with any other database/ORM.
-.. index:
-
-ToscaWidgets 2 Documentation
-============================
-
-ToscaWidgets aims to be a practical and useful widgets framework that helps people build interactive websites with compelling features, faster and easier. Widgets are re-usable web components that can include a template, server-side code and JavaScripts/CSS resources. The library aims to be: flexible, reliable, documented, performant, and as simple as possible. For changes since ToscaWidgets 0.9, see :doc:`history`.
-
-You can see the available widgets in the `Widget Browser
-<http://tw2-demos.threebean.org/>`_.
-
-ToscaWidgets 2 library packages follow the same naming convention, for example:
-
- * `tw2.core <http://github.com/toscawidgets/tw2.core/>`_ -- Core functionality -- no
-   end-usable widgets here.
- * `tw2.forms <http://github.com/toscawidgets/tw2.forms/>`_ -- Basic forms library
- * `tw2.dynforms <http://github.com/toscawidgets/tw2.dynforms/>`_ -- Dynamic forms
-   -- client-side and Ajax
- * `tw2.sqla <http://github.com/toscawidgets/tw2.sqla/>`_ -- SQLAlchemy database
-   interface, similar to Sprox and Rum
- * `tw2.yui <http://github.com/toscawidgets/tw2.yui/>`_ -- tw2 wrappers around
-   Yahoo User Interface widgets
- * `tw2.jquery <http://github.com/toscawidgets/tw2.jquery>`_ -- tw2
-   wrappers around jQuery core functionality.
- * `tw2.jqplugins.ui <http://github.com/ralphbean/tw2.jqplugins.ui>`_ -- tw2
-   wrappers around jQuery-UI widgets.
- * `tw2.jit <http://github.com/ralphbean/tw2.jit>`_ -- tw2 wrappers around the
-   Javascript Infovis Toolkit.
- * ... and `many more
-   <http://pypi.python.org/pypi?%3Aaction=search&term=tw2.&submit=search>`_.
-
-----
-
-**Online Resources**
-
- * Live demos -- Pick and choose from available libraries from the `tw2 Widget
-   Browser <http://tw2-demos.threebean.org/>`_.
- * Tutorials for doing --
-
-   * Dynamic database-driven forms with :doc:`tw2 and Pyramid </pyramid>`.
-   * Dynamic database-driven forms with :doc:`tw2 and TurboGears 2.1
-     </turbogears>`.
-   * Dynamic database-driven forms with :doc:`tw2 all by its standalone self
-     </standalone>`.
-   * Interactive relationship graphs with `tw2.jit and Pyramid
-     <http://threebean.org/blog/2011/03/07/sqlaradialgraph-in-a-pyramid-app>`_.
-   * Interactive relationship graphs with `tw2.jit and TurboGears 2.1
-     <http://threebean.org/blog/2011/03/06/sqlalchemy-the-javascript-infovis-toolkit-jit>`_.
-   * `Database-aware jqgrid, with jqplot and portlets in a TG2.1 app
-     <http://threebean.org/blog/2011/04/30/tutorial-melting-your-face-off-with-tw2-and-turbogears2-1>`_.
-   * `Bubble charts with tw2.protovis
-     <http://threebean.org/blog/2010/10/24/python-wsgi-protovis-barcamproc-fall-2010/>`_.
- * Nightly run `test results <http://tw2-tests.threebean.org/>`_.
- * Email list:  `toscawidgets-discuss
-   <http://groups.google.com/group/toscawidgets-discuss/>`_.
- * IRC channel: ``#toscawidgets`` on ``irc.freenode.net``
- * Bug tracker:  `Paj's bitbucket account
-   <http://bitbucket.org/paj/tw2core/issues?status=new&status=open>`_.
-
-   * (All ToscaWidgets 2 issues should go here, regardless of which
-     component the issue exists in. However, ToscaWidgets 0.9 bugs
-     must not go on this tracker.)
-
-----
-
-**Contents**
-
-.. toctree::
-   :maxdepth: 2
-
-   tutorial
-   design
-   devtools
-   history
-
-
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
-
+.. index:
+
+ToscaWidgets 2 Documentation
+============================
+
+ToscaWidgets aims to be a practical and useful widgets framework that helps people build interactive websites with compelling features, faster and easier. Widgets are re-usable web components that can include a template, server-side code and JavaScripts/CSS resources. The library aims to be: flexible, reliable, documented, performant, and as simple as possible. For changes since ToscaWidgets 0.9, see :doc:`history`.
+
+You can see the available widgets in the `Widget Browser
+<http://tw2-demos.threebean.org/>`_.
+
+ToscaWidgets 2 library packages follow the same naming convention, for example:
+
+ * `tw2.core <http://github.com/toscawidgets/tw2.core/>`_ -- Core functionality -- no
+   end-usable widgets here.
+ * `tw2.forms <http://github.com/toscawidgets/tw2.forms/>`_ -- Basic forms library
+ * `tw2.dynforms <http://github.com/toscawidgets/tw2.dynforms/>`_ -- Dynamic forms
+   -- client-side and Ajax
+ * `tw2.sqla <http://github.com/toscawidgets/tw2.sqla/>`_ -- SQLAlchemy database
+   interface, similar to Sprox and Rum
+ * `tw2.yui <http://github.com/toscawidgets/tw2.yui/>`_ -- tw2 wrappers around
+   Yahoo User Interface widgets
+ * `tw2.jquery <http://github.com/toscawidgets/tw2.jquery>`_ -- tw2
+   wrappers around jQuery core functionality.
+ * `tw2.jqplugins.ui <http://github.com/ralphbean/tw2.jqplugins.ui>`_ -- tw2
+   wrappers around jQuery-UI widgets.
+ * `tw2.jit <http://github.com/ralphbean/tw2.jit>`_ -- tw2 wrappers around the
+   Javascript Infovis Toolkit.
+ * ... and `many more
+   <http://pypi.python.org/pypi?%3Aaction=search&term=tw2.&submit=search>`_.
+
+----
+
+**Online Resources**
+
+ * Live demos -- Pick and choose from available libraries from the `tw2 Widget
+   Browser <http://tw2-demos.threebean.org/>`_.
+ * Tutorials for doing --
+
+   * Dynamic database-driven forms with :doc:`tw2 and Pyramid </pyramid>`.
+   * Dynamic database-driven forms with :doc:`tw2 and TurboGears 2.1
+     </turbogears>`.
+   * Dynamic database-driven forms with :doc:`tw2 all by its standalone self
+     </standalone>`.
+   * Interactive relationship graphs with `tw2.jit and Pyramid
+     <http://threebean.org/blog/2011/03/07/sqlaradialgraph-in-a-pyramid-app>`_.
+   * Interactive relationship graphs with `tw2.jit and TurboGears 2.1
+     <http://threebean.org/blog/2011/03/06/sqlalchemy-the-javascript-infovis-toolkit-jit>`_.
+   * `Database-aware jqgrid, with jqplot and portlets in a TG2.1 app
+     <http://threebean.org/blog/2011/04/30/tutorial-melting-your-face-off-with-tw2-and-turbogears2-1>`_.
+   * `Bubble charts with tw2.protovis
+     <http://threebean.org/blog/2010/10/24/python-wsgi-protovis-barcamproc-fall-2010/>`_.
+ * Nightly run `test results <http://tw2-tests.threebean.org/>`_.
+ * Email list:  `toscawidgets-discuss
+   <http://groups.google.com/group/toscawidgets-discuss/>`_.
+ * IRC channel: ``#toscawidgets`` on ``irc.freenode.net``
+ * Bug tracker:  `Paj's bitbucket account
+   <http://bitbucket.org/paj/tw2core/issues?status=new&status=open>`_.
+
+   * (All ToscaWidgets 2 issues should go here, regardless of which
+     component the issue exists in. However, ToscaWidgets 0.9 bugs
+     must not go on this tracker.)
+
+----
+
+**Contents**
+
+.. toctree::
+   :maxdepth: 2
+
+   tutorial
+   design
+   devtools
+   history
+
+
+Indices and tables
+==================
+
+* :ref:`genindex`
+* :ref:`modindex`
+* :ref:`search`
+
-Pyramid Tutorial
-================
-
-.. note::
-    The files created in this tutorial can be downloaded as a `.zip file
-    <https://github.com/ralphbean/tw2.core-docs-pyramid/zipball/master>`_,
-    a `.tar file
-    <https://github.com/ralphbean/tw2.core-docs-pyramid/tarball/master>`_,
-    or can be cloned from a `github repository
-    <http://github.com/ralphbean/tw2.core-docs-pyramid>`_.
-
-
-Getting Set Up
---------------
-
-First, we'll create a python ``virtualenv`` and install ``pyramid`` into it::
-
-    $ mkvirtualenv --no-site-packages tw2-and-pyramid
-    $ pip install pyramid PasteScript
-    $ paster create -t pyramid_alchemy myapp
-    $ cd myapp
-
-Open ``setup.py`` and add the following to the ``requires=[...]`` entry::
-
-    requires=[
-
-        ...
-
-        "tw2.core",
-        "tw2.forms",
-        "tw2.dynforms",
-        "tw2.sqla",
-        "tw2.jqplugins.jqgrid",
-        ],
-
-Once that's done.  Install your dependencies by running::
-
-    $ python setup.py develop
-
-Enabling ToscaWidgets2
-----------------------
-
-Easy!  Just edit ``development.ini`` and add ``tw2.core`` to the
-pipline so that it looks like::
-
-    [pipeline:main]
-    pipeline =
-        egg:WebError#evalerror
-        tm
-        tw2.core
-        myapp
-
-We'll add another section where pyramid will take configuration values for the
-tw2.core middleware itself.  Add it just belo the ``[pipeline:main]`` section::
-
-    [filter:tw2.core]
-    use = egg:tw2.core#middleware
-
-We'll add more configuration values later.  For now,
-check that this worked by running the following and visiting
-http://localhost:6543::
-
-    $ paster serve development.ini
-
-Building a Form
----------------
-We'll create a movie database as in the :doc:`standalone` example.  We'll need
-to create the widget, expose it in a pyramid view, and render it in a template.
-
-First, create a new file ``myapp/widgets.py`` with the contents::
-
-    import tw2.core
-    import tw2.forms
-
-    class MovieForm(tw2.forms.FormPage):
-        title = 'Movie'
-        class child(tw2.forms.TableForm):
-            id = tw2.forms.HiddenField()
-            title = tw2.forms.TextField(validator=tw2.core.Required)
-            director = tw2.forms.TextField()
-            genres = tw2.forms.CheckBoxList(options=['Action', 'Comedy', 'Romance', 'Sci-fi'])
-            class cast(tw2.forms.GridLayout):
-                extra_reps = 5
-                character = tw2.forms.TextField()
-                actor = tw2.forms.TextField()
-
-Second, modify ``myapp/views.py`` and add a new view callable like so::
-
-    def view_widget(context, request):
-        return {'widget': context}
-
-Thirdly, add a new template ``myapp/templates/widget.pt`` (which is a `chameleon
-<http://pypi.python.org/pypi/Chameleon>`_ template) with the following
-contents::
-
-    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
-    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
-    <head>
-      <title>The Pyramid Web Application Development Framework</title>
-      <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
-      <meta name="keywords" content="python web application" />
-      <meta name="description" content="pyramid web application" />
-      <link rel="shortcut icon" href="${request.static_url('myapp:static/favicon.ico')}" />
-    </head>
-    <body>
-      <div id="wrap">
-        <div tal:content="structure widget.display()"></div>
-      </div>
-      <div id="footer">
-        <div class="footer">&copy; Copyright 2008-2011, Agendaless Consulting.</div>
-      </div>
-    </body>
-    </html>
-
-Fourthly, modify the class responsible for producing your resource tree,
-the ``MyApp`` class in ``myapp/models.py``.  At the top of the file add::
-
-Add the following hook into the ``def __getitem__(self, key):`` method of the ``MyApp`` class just above the ``session= DBSession()`` line::
-
-    if key == 'movie':
-        import myapp.widgets
-        w = myapp.widgets.MovieForm.req()
-        w.__parent__ = self
-        w.__name__ = key
-        return w
-
-Having modified the resource tree in ``myapp/models.py``, added a new view
-callable to ``myapp/views.py``, added the new template
-``myapp/templates/widget.pt``, and having added the widget definition
-itself to ``myapp/widgets.py``, all that's left is to wire it all together.
-Edit your applications configuration in ``myapp/__init__.py`` and add the
-view to the application registry with the following call::
-
-    config.add_view('myapp.views.view_widget',
-                    context='myapp.widgets.MovieForm',
-                    renderer="templates/widget.pt")
-
-With those five file edits in place, you should be able to restart the
-application with ``paster serve development.ini`` (there is a ``--reload``
-option for convenience) and point your browser
-at http://localhost:6543/movie.
-
-You should see the form, but it doesn't look very appealing.  To try to
-improve this, lets add some CSS.  We'll start with something simple;
-create ``myapp/static/myapp.css`` with the following::
-
-    th {
-        vertical-align: top;
-        text-align: left;
-        font-weight: normal;
-    }
-
-    ul {
-        list-style-type: none;
-    }
-
-    .required th {
-        font-weight: bold;
-    }
-
-Notice the use of the "required" class. TableForm applies this to rows that
-contain a field that is required.
-
-Before TableForm will inject ``myapp.css`` into the page, we'll have to add
-it to the list of resources. Add the following to the top of the `MovieForm`
-class definition in ``myapp/widgets.py`` just above the line
-``title = 'Movie'``::
-
-    resources = [tw2.core.CSSLink(link='static/myapp.css')]
-
-Restart ``paster`` and browse to http://localhost:6543/1
-to see the new css in action.
-
-Connecting to a Database
-------------------------
-
-The next step is to save movies to a database.  To do this, we'll use only
-`SQLAlchemy <http://www.sqlalchemy.org/>`_ just like in the :doc:`turbogears`
-tutorial (and not `elixir <http://elixir.ematia.de/trac/wiki>`_ as in
-the :doc:`standalone` tutorial).  SQLAlchemy is built into our pyramid app
-from the get-go by way of us using the pyramid_alchemy paster template.
-Edit ``development.ini`` and modify the ``[filter:tw2.core]`` section like
-so::
-
-    [filter:tw2.core]
-    use = egg:tw2.core#middleware
-    controller_prefix = /tw2_controllers/
-    serve_controllers = True
-
-Next, edit ``myapp/models.py`` with the following changes.  Add this set of
-imports to the top::
-
-    from sqlalchemy import Table
-    from sqlalchemy import ForeignKey
-    from sqlalchemy.orm import relation
-    from sqlalchemy.orm import backref
-
-Just above the definition of ``class MyModel(Base):`` add::
-
-    Base.query = DBSession.query_property()
-
-    movie_genre_table = Table('movie_genre', Base.metadata,
-        Column('movie_id', Integer, ForeignKey('movies.id',
-            onupdate="CASCADE", ondelete="CASCADE"), primary_key=True),
-        Column('genre_id', Integer, ForeignKey('genres.id',
-            onupdate="CASCADE", ondelete="CASCADE"), primary_key=True)
-    )
-
-    class Movie(Base):
-        __tablename__ = 'movies'
-        id = Column(Integer, primary_key=True)
-        title = Column(Unicode(255))
-        director = Column(Unicode(255))
-
-    class Genre(Base):
-        __tablename__ = 'genres'
-        id = Column(Integer, primary_key=True)
-        name = Column(Unicode(255))
-        movies = relation('Movie', secondary=movie_genre_table, backref='genres')
-        def __unicode__(self):
-            return unicode(self.name)
-
-    class Cast(Base):
-        __tablename__ = 'casts'
-        id = Column(Integer, primary_key=True)
-        movie_id = Column(Integer, ForeignKey(Movie.id))
-        movie = relation(Movie, backref=backref('cast'))
-        character = Column(Unicode(255))
-        actor = Column(Unicode(255))
-
-And finally inside the ``def populate()`` method of the same file add::
-
-    for name in ['Action', 'Comedy', 'Romance', 'Sci-fi']:
-        session.add(Genre(name=name))
-
-Now done with ``myapp/models.py``, edit ``myapp/views.py`` and replace the definition of ``def view_widget(context, request):`` with::
-
-    import tw2.core
-    def view_widget(context, request):
-        context.fetch_data(request)
-        tw2.core.register_controller(context, 'movie_submit')
-        return {'widget': context}
-
-Lastly, edit ``myapp/widgets.py`` and add::
-
-    import tw2.sqla
-    import myapp.models
-
-Change ``class MovieForm(tw2.forms.FormPage):`` to::
-
-    class MovieForm(tw2.sqla.DbFormPage):
-        entity = myapp.models.Movie
-
-To the body of ``class child(tw2.forms.TableForm):`` add::
-
-    action = '/tw2_controllers/movie_submit'
-
-And the last for the `MovieForm`, change ``genres = tw2.forms.CheckBoxList( ... )`` to::
-
-    genres = tw2.sqla.DbCheckBoxList(entity=myapp.models.Genre)
-
-Now, in your command prompt run::
-
-    rm myapp.db
-    paster serve development.ini
-
-This will recreate and initialize your database in a sqlite DB.
-
-We're almost done, but not quite.  Nonetheless, this is a good point to restart
-your app and test to see if any mistakes have cropped up.  Restart `paster`
-and visit http://localhost:6543/movie.  Submit your first entry.  It
-should give you an `Error 404`, but don't worry.  Point your browser now to
-http://localhost:6543/movie?id=1 and you should see the same
-movie entry that you just submitted.
-
-Great -- we can write to the database and read back an entry, now how about
-a list of entries?
-
-Add a whole new class to ``myapp/widgets.py``::
-
-    class MovieList(tw2.sqla.DbListPage):
-        entity = myapp.models.Movie
-        title = 'Movies'
-        newlink = tw2.forms.LinkField(link='/movie', text='New', value=1)
-        class child(tw2.forms.GridLayout):
-            title = tw2.forms.LabelField()
-            id = tw2.forms.LinkField(link='/movie?id=$', text='Edit', label=None)
-
-In ``myapp/widgets.py`` also add the following line just inside the definition
-of ``MovieForm``::
-
-    redirect = '/list'
-
-Add another hook into the ``MyApp`` ``__getitem__(...)`` method in ``myapp/models.py``::
-
-    if key == 'list':
-        import myapp.widgets
-        w = myapp.widgets.MovieList.req()
-        w.__parent__ = self
-        w.__name__ = key
-        return w
-
-
-And add the following view configuration in ``myapp/__init__.py``::
-
-    config.add_view('myapp.views.view_widget',
-                    context='myapp.widgets.MovieList',
-                    renderer="templates/widget.pt")
-
-Now restart `paster` and browse to http://localhost:6543/list
-
-Getting Fancy
--------------
-
-We could also make things dynamic by editing ``myapp/widgets.py`` and adding at the top::
-
-    import tw2.dynforms
-
-replacing ``class child(tw2.forms.TableForm):`` with::
-
-    class child(tw2.dynforms.CustomisedTableForm):
-
-and replacing::
-
-    class cast(tw2.forms.GridLayout):
-        extra_reps = 5
-
-with::
-
-    class cast(tw2.dynforms.GrowingGridLayout):
-
-Getting Fancier
----------------
-
-There are a lot of `non-core` TW2 widget libraries out there, and just to give
-you a taste, we'll use one to add one more view to our Movie app.
-
-Edit ``myapp/widgets.py`` and add the following to the top::
-
-    import tw2.jqplugins.jqgrid
-
-Add the following class definition to the same file::
-
-    class GridWidget(tw2.jqplugins.jqgrid.SQLAjqGridWidget):
-        id = 'grid_widget'
-        entity = myapp.models.Movie
-        excluded_columns = ['id']
-        prmFilter = {'stringResult': True, 'searchOnEnter': False}
-        pager_options = { "search" : True, "refresh" : True, "add" : False, }
-        options = {
-            'url': '/tw2_controllers/db_jqgrid/',
-            'rowNum':15,
-            'rowList':[15,30,50],
-            'viewrecords':True,
-            'imgpath': 'scripts/jqGrid/themes/green/images',
-            'width': 900,
-            'height': 'auto',
-        }
-
-Add the following to your view configuration in ``myapp/__init__.py``::
-
-    config.add_view('myapp.views.view_grid_widget',
-                    context='myapp.widgets.GridWidget',
-                    renderer="templates/widget.pt")
-
-
-Add that view to ``myapp/views.py`` itself::
-
-    def view_grid_widget(context, request):
-        tw2.core.register_controller(context, 'db_jqgrid')
-        return {'widget': context}
-
-Finally add another hook into ``MyApp.__getitem__(...)``::
-
-    if key == 'grid':
-        import myapp.widgets
-        w = myapp.widgets.GridWidget.req()
-        w.__parent__ = self
-        w.__name__ = key
-        return w
-
-
-Redirect your browser to http://localhost:6543/grid and you should
-see the sortable, searchable jQuery grid.
+Pyramid Tutorial
+================
+
+.. note::
+    The files created in this tutorial can be downloaded as a `.zip file
+    <https://github.com/ralphbean/tw2.core-docs-pyramid/zipball/master>`_,
+    a `.tar file
+    <https://github.com/ralphbean/tw2.core-docs-pyramid/tarball/master>`_,
+    or can be cloned from a `github repository
+    <http://github.com/ralphbean/tw2.core-docs-pyramid>`_.
+
+
+Getting Set Up
+--------------
+
+First, we'll create a python ``virtualenv`` and install ``pyramid`` into it::
+
+    $ mkvirtualenv --no-site-packages tw2-and-pyramid
+    $ pip install pyramid PasteScript
+    $ paster create -t pyramid_alchemy myapp
+    $ cd myapp
+
+Open ``setup.py`` and add the following to the ``requires=[...]`` entry::
+
+    requires=[
+
+        ...
+
+        "tw2.core",
+        "tw2.forms",
+        "tw2.dynforms",
+        "tw2.sqla",
+        "tw2.jqplugins.jqgrid",
+        ],
+
+Once that's done.  Install your dependencies by running::
+
+    $ python setup.py develop
+
+Enabling ToscaWidgets2
+----------------------
+
+Easy!  Just edit ``development.ini`` and add ``tw2.core`` to the
+pipline so that it looks like::
+
+    [pipeline:main]
+    pipeline =
+        egg:WebError#evalerror
+        tm
+        tw2.core
+        myapp
+
+We'll add another section where pyramid will take configuration values for the
+tw2.core middleware itself.  Add it just belo the ``[pipeline:main]`` section::
+
+    [filter:tw2.core]
+    use = egg:tw2.core#middleware
+
+We'll add more configuration values later.  For now,
+check that this worked by running the following and visiting
+http://localhost:6543::
+
+    $ paster serve development.ini
+
+Building a Form
+---------------
+We'll create a movie database as in the :doc:`standalone` example.  We'll need
+to create the widget, expose it in a pyramid view, and render it in a template.
+
+First, create a new file ``myapp/widgets.py`` with the contents::
+
+    import tw2.core
+    import tw2.forms
+
+    class MovieForm(tw2.forms.FormPage):
+        title = 'Movie'
+        class child(tw2.forms.TableForm):
+            id = tw2.forms.HiddenField()
+            title = tw2.forms.TextField(validator=tw2.core.Required)
+            director = tw2.forms.TextField()
+            genres = tw2.forms.CheckBoxList(options=['Action', 'Comedy', 'Romance', 'Sci-fi'])
+            class cast(tw2.forms.GridLayout):
+                extra_reps = 5
+                character = tw2.forms.TextField()
+                actor = tw2.forms.TextField()
+
+Second, modify ``myapp/views.py`` and add a new view callable like so::
+
+    def view_widget(context, request):
+        return {'widget': context}
+
+Thirdly, add a new template ``myapp/templates/widget.pt`` (which is a `chameleon
+<http://pypi.python.org/pypi/Chameleon>`_ template) with the following
+contents::
+
+    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
+    <head>
+      <title>The Pyramid Web Application Development Framework</title>
+      <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+      <meta name="keywords" content="python web application" />
+      <meta name="description" content="pyramid web application" />
+      <link rel="shortcut icon" href="${request.static_url('myapp:static/favicon.ico')}" />
+    </head>
+    <body>
+      <div id="wrap">
+        <div tal:content="structure widget.display()"></div>
+      </div>
+      <div id="footer">