Chris McDonough
2012-10-08 2aed2c783a99efaa48b145d174347c9512e40c5a
Merge branch 'master' of github.com:Pylons/pyramid
4 files added
76 files modified
8051 ■■■■ changed files
.travis.yml 6 ●●●●● patch | view | raw | blame | history
CHANGES.txt 114 ●●●● patch | view | raw | blame | history
CONTRIBUTORS.txt 8 ●●●● patch | view | raw | blame | history
TODO.txt 16 ●●●●● patch | view | raw | blame | history
docs/Makefile 8 ●●●● patch | view | raw | blame | history
docs/api.rst 1 ●●●● patch | view | raw | blame | history
docs/api/decorator.rst 9 ●●●●● patch | view | raw | blame | history
docs/api/request.rst 56 ●●●●● patch | view | raw | blame | history
docs/api/session.rst 2 ●●●●● patch | view | raw | blame | history
docs/api/testing.rst 2 ●●●●● patch | view | raw | blame | history
docs/conf.py 4 ●●●● patch | view | raw | blame | history
docs/designdefense.rst 14 ●●●●● patch | view | raw | blame | history
docs/glossary.rst 29 ●●●●● patch | view | raw | blame | history
docs/index.rst 2 ●●●●● patch | view | raw | blame | history
docs/latexindex.rst 1 ●●●● patch | view | raw | blame | history
docs/narr/MyProject/myproject/static/pylons.css 435 ●●●● patch | view | raw | blame | history
docs/narr/advconfig.rst 7 ●●●●● patch | view | raw | blame | history
docs/narr/install.rst 209 ●●●● patch | view | raw | blame | history
docs/narr/introduction.rst 2 ●●● patch | view | raw | blame | history
docs/narr/introspector.rst 4 ●●●● patch | view | raw | blame | history
docs/narr/project.rst 41 ●●●● patch | view | raw | blame | history
docs/narr/subrequest.rst 271 ●●●●● patch | view | raw | blame | history
docs/narr/testing.rst 24 ●●●●● patch | view | raw | blame | history
docs/narr/upgrading.rst 2 ●●●●● patch | view | raw | blame | history
docs/narr/viewconfig.rst 31 ●●●●● patch | view | raw | blame | history
docs/narr/views.rst 10 ●●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/authorization/tutorial/static/pylons.css 435 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/basiclayout/tutorial/static/pylons.css 435 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/models/tutorial/static/pylons.css 435 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/tests/tutorial/static/pylons.css 435 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki/src/views/tutorial/static/pylons.css 435 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/authorization.rst 8 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/basiclayout.rst 28 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/definingviews.rst 2 ●●● patch | view | raw | blame | history
docs/tutorials/wiki2/design.rst 3 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authorization/tutorial/__init__.py 6 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/authorization/tutorial/static/pylons.css 435 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py 6 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/basiclayout/tutorial/static/pylons.css 435 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/models/tutorial/__init__.py 6 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/models/tutorial/static/pylons.css 435 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/tests/tutorial/__init__.py 6 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/tests/tutorial/static/pylons.css 435 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/views/tutorial/__init__.py 6 ●●●● patch | view | raw | blame | history
docs/tutorials/wiki2/src/views/tutorial/static/pylons.css 435 ●●●● patch | view | raw | blame | history
docs/whatsnew-1.4.rst 279 ●●●●● patch | view | raw | blame | history
pyramid/chameleon_text.py 18 ●●●●● patch | view | raw | blame | history
pyramid/chameleon_zpt.py 18 ●●●●● patch | view | raw | blame | history
pyramid/config/factories.py 2 ●●●●● patch | view | raw | blame | history
pyramid/config/predicates.py 23 ●●●●● patch | view | raw | blame | history
pyramid/config/routes.py 1 ●●●● patch | view | raw | blame | history
pyramid/config/testing.py 26 ●●●●● patch | view | raw | blame | history
pyramid/config/views.py 31 ●●●●● patch | view | raw | blame | history
pyramid/decorator.py 28 ●●●● patch | view | raw | blame | history
pyramid/mako_templating.py 11 ●●●● patch | view | raw | blame | history
pyramid/renderers.py 45 ●●●● patch | view | raw | blame | history
pyramid/router.py 106 ●●●● patch | view | raw | blame | history
pyramid/scaffolds/alchemy/+package+/__init__.py 6 ●●●● patch | view | raw | blame | history
pyramid/scaffolds/alchemy/+package+/static/pylons.css 435 ●●●● patch | view | raw | blame | history
pyramid/scaffolds/starter/+package+/static/pylons.css 435 ●●●● patch | view | raw | blame | history
pyramid/scaffolds/zodb/+package+/static/pylons.css 435 ●●●● patch | view | raw | blame | history
pyramid/scripting.py 4 ●●●● patch | view | raw | blame | history
pyramid/scripts/pserve.py 8 ●●●● patch | view | raw | blame | history
pyramid/session.py 24 ●●●●● patch | view | raw | blame | history
pyramid/testing.py 52 ●●●●● patch | view | raw | blame | history
pyramid/tests/fixtures/withmacro.pt 1 ●●●● patch | view | raw | blame | history
pyramid/tests/pkgs/subrequestapp/__init__.py 50 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_chameleon_text.py 10 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_chameleon_zpt.py 19 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_config/test_init.py 11 ●●●● patch | view | raw | blame | history
pyramid/tests/test_config/test_predicates.py 43 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_config/test_testing.py 24 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_integration.py 59 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_mako_templating.py 14 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_renderers.py 7 ●●●● patch | view | raw | blame | history
pyramid/tests/test_scripting.py 13 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_session.py 25 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_testing.py 55 ●●●●● patch | view | raw | blame | history
pyramid/view.py 2 ●●● patch | view | raw | blame | history
setup.py 2 ●●● patch | view | raw | blame | history
.travis.yml
@@ -6,12 +6,6 @@
  - pypy
  - 3.2
# Why does travis-ci's PyPy blow up?  Pyramid's tests
# run fine under tox.
matrix:
  allow_failures:
    - python: pypy
script: python setup.py test
notifications:
CHANGES.txt
@@ -1,6 +1,77 @@
Next release
============
Bug Fixes
---------
- 1.4a ``pyramid.scripting.prepare`` behaved differently than 1.3 series
  function of same name.  In particular, if passed a request, it would not
  set the ``registry`` attribute of the request like 1.3 did.  A symptom
  would be that passing a request to ``pyramid.paster.bootstrap`` (which uses
  the function) that did not have a ``registry`` attribute could assume that
  the registry would be attached to the request by Pyramid.  This assumption
  could be made in 1.3, but not in 1.4.  The assumption can now be made in
  1.4 too (a registry is attached to a request passed to bootstrap or
  prepare).
- When registering a view configuration that named a Chameleon ZPT renderer
  with a macro name in it (e.g. ``renderer='some/template#somemacro.pt``) as
  well as a view configuration without a macro name it it that pointed to the
  same template (e.g. ``renderer='some/template.pt'), internal caching could
  confuse the two, and your code might have rendered one instead of the
  other.
Features
--------
- The Configurator ``testing_securitypolicy`` method now returns the policy
  object it creates.
- The Configurator ``testing_securitypolicy`` method accepts two new
  arguments: ``remember_result`` and ``forget_result``.  If supplied, these
  values influence the result of the policy's ``remember`` and ``forget``
  methods, respectively.
- The DummySecurityPolicy created by ``testing_securitypolicy`` now sets a
  ``forgotten`` value on the policy (the value ``True``) when its ``forget``
  method is called.
- The DummySecurityPolicy created by ``testing_securitypolicy`` now sets a
  ``remembered`` value on the policy, which is the value of the ``principal``
  argument it's called with when its ``remember`` method is called.
1.4a2 (2012-09-27)
==================
Bug Fixes
---------
- When trying to determine Mako defnames and Chameleon macro names in asset
  specifications, take into account that the filename may have a hyphen in
  it.  See https://github.com/Pylons/pyramid/pull/692
Features
--------
- A new ``pyramid.session.check_csrf_token`` convenience function was added.
- A ``check_csrf`` view predicate was added.  For example, you can now do
  ``config.add_view(someview, check_csrf=True)``.  When the predicate is
  checked, if the ``csrf_token`` value in ``request.params`` matches the CSRF
  token in the request's session, the view will be permitted to execute.
  Otherwise, it will not be permitted to execute.
- Add ``Base.metadata.bind = engine`` to alchemy template, so that tables
  defined imperatively will work.
Documentation
-------------
- update wiki2 SQLA tutorial with the changes required after inserting
  ``Base.metadata.bind = engine`` into the alchemy scaffold.
1.4a1 (2012-09-16)
==================
Bug Fixes
---------
@@ -33,11 +104,6 @@
  differ in the case ('text/html' vs. 'text/HTML') will now raise an error.
  https://github.com/Pylons/pyramid/pull/620
- Configurator.add_directive now accepts arbitrary callables like partials or
  objects implementing ``__call__`` which dont have ``__name__`` and
  ``__doc__`` attributes.  See https://github.com/Pylons/pyramid/issues/621
  and https://github.com/Pylons/pyramid/pull/647.
- Forward-port from 1.3 branch: when registering multiple views with an
  ``accept`` predicate in a Pyramid application runing under Python 3, you
  might have received a ``TypeError: unorderable types: function() <
@@ -45,6 +111,11 @@
Features
--------
- Configurator.add_directive now accepts arbitrary callables like partials or
  objects implementing ``__call__`` which dont have ``__name__`` and
  ``__doc__`` attributes.  See https://github.com/Pylons/pyramid/issues/621
  and https://github.com/Pylons/pyramid/pull/647.
- Third-party custom view, route, and subscriber predicates can now be added
  for use by view authors via
@@ -104,13 +175,13 @@
  and ``HTTPMovedPermanently`` exceptions, so these can be caught by the
  NotFound view (and other exception views).
- The Mako renderer now accepts a def name in an asset spect.  When the def
- The Mako renderer now supports a def name in an asset spec.  When the def
  name is present in the asset spec, the system will render the template def
  within the template and will return the result. An example asset spec is
  ``package:path/to/template#defname.mako``. This will render the def named
  ``defname`` inside the ``template.pt`` package instead of rendering the
  entire template.  The old way of returning a tuple from the view is
  supported for backward compatibility, ('defname', {}).
  ``defname`` inside the ``template.mako`` template instead of rendering the
  entire template.  The old way of returning a tuple in the form
  ``('defname', {})`` from the view is supported for backward compatibility,
- The Chameleon ZPT renderer now accepts a macro name in an asset spec.  When
  the macro name is present in the asset spec, the system will render the
@@ -151,14 +222,20 @@
  ``config.add_request_method`` are now available to tweens.
- Request properties and methods added via ``config.set_request_property`` or
  ``config.add_request_method`` are now available to tweens.
- Request properties and methods added via ``config.set_request_property`` or
  ``config.add_request_method`` are now available in the request object
  returned from ``pyramid.paster.bootstrap``.
- ``request.context`` of environment request during ``bootstrap`` is now the
  root object if a context isn't already set on a provided request.
- The ``pyramid.decorator.reify`` function is now an API, and was added to
  the API documentation.
- Added the ``pyramid.testing.testConfig`` context manager, which can be used
  to generate a configurator in a test, e.g. ``with testing.testConfig(...):``.
- Users can now invoke a subrequest from within view code using a new
  ``request.invoke_subrequest`` API.
Deprecations
------------
@@ -246,11 +323,22 @@
  * ``registerSettings``, use 
    ``pyramid.config.Configurator.add_settings`` instead.
- In Pyramid 1.3 and previous, the ``__call__`` method of a Response object
  was invoked before any finished callbacks were executed.  As of this
  release, the ``__call__`` method of a Response object is invoked *after*
  finished callbacks are executed.  This is in support of the
  ``request.invoke_subrequest`` feature.
Documentation
-------------
- Added an "Upgrading Pyramid" chapter to the narrative documentation.  It
  describes how to cope with deprecations and removals of Pyramid APIs.
  describes how to cope with deprecations and removals of Pyramid APIs and
  how to show Pyramid-generated deprecation warnings while running tests and
  while running a server.
- Added a "Invoking a Subrequest" chapter to the documentation.  It describes
  how to use the new ``request.invoke_subrequest`` API.
Dependencies
------------
CONTRIBUTORS.txt
@@ -1,4 +1,4 @@
 Pylons Project Contributor Agreement
Pylons Project Contributor Agreement
====================================
The submitter agrees by adding his or her name within the section below named
@@ -177,8 +177,14 @@
- Marc Abramowitz, 2012/06/13
- Brian Sutherland, 2012/06/16
- Jeff Cook, 2012/06/16
- Ian Wilson, 2012/06/17
- Roman Kozlovskyi, 2012/08/11
- Domen Kozar, 2012/09/11
- David Gay, 2012/09/16
TODO.txt
@@ -82,15 +82,6 @@
- Deprecate pyramid.security.view_execution_permitted (it only works for
  traversal).
- Create a function which performs a recursive request.
- Create a ``render_view`` that works by using config.derive_view against an
  existing view callable instead of querying the registry (some sort of API
  for rendering a view callable object to a response from within another view
  callable). Possible idea: have config.add_view mark up the
  function/method/class like @view_config does, then use the attached info to
  derive a view callable whenever called via some API.
- Provide a ``has_view`` function.
- Update App engine chapter with less creaky directions.
@@ -143,11 +134,16 @@
  original dict (after ``__getattr__`` deprecation period, it was deprecated
  in 1.2).
- 1.5: Remove ``pyramid.requests.DeprecatedRequestMethodsMixin``.
- 1.5: Remove ``pyramid.requests.DeprecatedRequestMethodsMixin`` and code in
  renderers module that looks for _response_content_type, et. al.
- 1.5: Maybe? deprecate set_request_property in favor of pointing people at
  add_request_method, schedule removal for 1.8?
- 1.5: Remove pyramid.config.rendering set_renderer_globals_factory maybe.
- 1.5: remove pyramid.config.route _add_view_from_route function.
- 1.6: Remove IContextURL and TraversalContextURL.
Probably Bad Ideas
docs/Makefile
@@ -25,7 +25,7 @@
clean:
    -rm -rf _build/*
html: _themes
html: themes
    mkdir -p _build/html _build/doctrees
    $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
    @echo
@@ -47,7 +47,7 @@
web: pickle
htmlhelp: _themes
htmlhelp: themes
    mkdir -p _build/htmlhelp _build/doctrees
    $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
    @echo
@@ -84,5 +84,5 @@
    @echo
    @echo "Build finished. The epub file is in _build/epub."
_themes:
    git submodule update --init
themes:
    cd ..; git submodule update --init --recursive; cd docs;
docs/api.rst
@@ -12,6 +12,7 @@
   api/authentication
   api/compat
   api/config
   api/decorator
   api/events
   api/exceptions
   api/httpexceptions
docs/api/decorator.rst
New file
@@ -0,0 +1,9 @@
.. _decorator_module:
:mod:`pyramid.decorator`
--------------------------
.. automodule:: pyramid.decorator
.. autofunction:: reify
docs/api/request.rst
@@ -161,6 +161,62 @@
      request, the value of this attribute will be ``None``. See
      :ref:`matched_route`.
   .. method:: invoke_subrequest(request, use_tweens=False)
      .. warning::
         This API was added in Pyramid 1.4a1.
      Obtain a response object from the Pyramid application based on
      information in the ``request`` object provided.  The ``request`` object
      must be an object that implements the Pyramid request interface (such
      as a :class:`pyramid.request.Request` instance).  If ``use_tweens`` is
      ``True``, the request will be sent to the :term:`tween` in the tween
      stack closest to the request ingress.  If ``use_tweens`` is ``False``,
      the request will be sent to the main router handler, and no tweens will
      be invoked.
      This function also:
      - manages the threadlocal stack (so that
        :func:`~pyramid.threadlocal.get_current_request` and
        :func:`~pyramid.threadlocal.get_current_registry` work during a
        request)
      - Adds a ``registry`` attribute (the current Pyramid registry) and a
        ``invoke_subrequest`` attribute (a callable) to the request object it's
        handed.
      - sets request extensions (such as those added via
        :meth:`~pyramid.config.Configurator.add_request_method` or
        :meth:`~pyramid.config.Configurator.set_request_property`) on the
        request it's passed.
      - causes a :class:`~pyramid.event.NewRequest` event to be sent at the
        beginning of request processing.
      - causes a :class:`~pyramid.event.ContextFound` event to be sent
        when a context resource is found.
      - Ensures that the user implied by the request passed has the necessary
        authorization to invoke view callable before calling it.
      - causes a :class:`~pyramid.event.NewResponse` event to be sent when
        the Pyramid application returns a response.
      - Calls any :term:`response callback` functions defined within the
        request's lifetime if a response is obtained from the Pyramid
        application.
      - Calls any :term:`finished callback` functions defined within the
        request's lifetime.
      ``invoke_subrequest`` isn't *actually* a method of the Request object;
      it's a callable added when the Pyramid router is invoked, or when a
      subrequest is invoked.  This means that it's not available for use on a
      request provided by e.g. the ``pshell`` environment.  For more
      information, see :ref:`subrequest_chapter`.
   .. automethod:: add_response_callback
   .. automethod:: add_finished_callback
docs/api/session.rst
@@ -11,4 +11,6 @@
  .. autofunction:: signed_deserialize
  .. autofunction:: check_csrf_token
docs/api/testing.rst
@@ -9,6 +9,8 @@
  .. autofunction:: tearDown
  .. autofunction:: testConfig(registry=None, request=None, hook_zca=True, autocommit=True, settings=None)
  .. autofunction:: cleanUp
  .. autoclass:: DummyResource
docs/conf.py
@@ -81,7 +81,7 @@
# other places throughout the built documents.
#
# The short X.Y version.
version = '1.4dev'
version = '1.4a2'
# The full version, including alpha/beta/rc tags.
release = version
@@ -160,7 +160,7 @@
html_theme = 'pyramid'
html_theme_options = dict(
    github_url='https://github.com/Pylons/pyramid',
    in_progress='true',
#    in_progress='true',
    )
# 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
docs/designdefense.rst
@@ -390,20 +390,6 @@
any other sort of frameworky declarative frontend to application
configuration.
.. _model_traversal_confusion:
Pyramid Uses "Model" To Represent A Node In The Graph of Objects Traversed
--------------------------------------------------------------------------
The ``repoze.bfg`` documentation used to refer to the graph being traversed
when :term:`traversal` is used as a "model graph".  A terminology overlap
confused people who wrote applications that always use ORM packages such as
SQLAlchemy, which has a different notion of the definition of a "model".  As
a result, in Pyramid 1.0a7, the tree of objects traversed is now renamed to
:term:`resource tree` and its components are now named :term:`resource`
objects.  Associated APIs have been changed.  This hopefully alleviates the
terminology confusion caused by overriding the term "model".
Pyramid Does Traversal, And I Don't Like Traversal
--------------------------------------------------
docs/glossary.rst
@@ -41,14 +41,20 @@
   setuptools
     `Setuptools <http://peak.telecommunity.com/DevCenter/setuptools>`_
     builds on Python's ``distutils`` to provide easier building,
     distribution, and installation of libraries and applications.
     distribution, and installation of libraries and applications.  As of
     this writing, setuptools runs under Python 2, but not under Python 3.
     You can use :term:`distribute` under Python 3 instead.
   distribute
     `Distribute <http://packages.python.org/distribute/>`_ is a fork of
     :term:`setuptools` which runs on both Python 2 and Python 3.
   pkg_resources
     A module which ships with :term:`setuptools` that provides an API for
     addressing "asset files" within a Python :term:`package`.  Asset files
     are static files, template files, etc; basically anything
     non-Python-source that lives in a Python package can be considered a
     asset file.  See also `PkgResources
     A module which ships with :term:`setuptools` and :term:`distribute` that
     provides an API for addressing "asset files" within a Python
     :term:`package`.  Asset files are static files, template files, etc;
     basically anything non-Python-source that lives in a Python package can
     be considered a asset file.  See also `PkgResources
     <http://peak.telecommunity.com/DevCenter/PkgResources>`_
   asset
@@ -84,7 +90,7 @@
     (Setuptools/distutils terminology).  A file representing an
     installable library or application.  Distributions are usually
     files that have the suffix of ``.egg``, ``.tar.gz``, or ``.zip``.
     Distributions are the target of Setuptools commands such as
     Distributions are the target of Setuptools-related commands such as
     ``easy_install``.
   entry point
@@ -812,9 +818,12 @@
      application.
   session factory
      A callable, which, when called with a single argument named
      ``request`` (a :term:`request` object), returns a
      :term:`session` object.
      A callable, which, when called with a single argument named ``request``
      (a :term:`request` object), returns a :term:`session` object.  See
      :ref:`using_the_default_session_factory`,
      :ref:`using_alternate_session_factories` and
      :meth:`pyramid.config.Configurator.set_session_factory` for more
      information.
   Mako
     `Mako <http://www.makotemplates.org/>`_ is a template language language
docs/index.rst
@@ -37,6 +37,7 @@
.. toctree::
   :maxdepth: 1
   whatsnew-1.4
   whatsnew-1.3
   whatsnew-1.2
   whatsnew-1.1
@@ -82,6 +83,7 @@
   narr/traversal
   narr/security
   narr/hybrid
   narr/subrequest
   narr/hooks
   narr/introspector
   narr/extending
docs/latexindex.rst
@@ -54,6 +54,7 @@
   narr/traversal
   narr/security
   narr/hybrid
   narr/subrequest
   narr/hooks
   narr/introspector
   narr/extending
docs/narr/MyProject/myproject/static/pylons.css
@@ -1,65 +1,372 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td
{
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-size: 100%; /* 16px */
  vertical-align: baseline;
  background: transparent;
}
body
{
  line-height: 1;
}
ol, ul
{
  list-style: none;
}
blockquote, q
{
  quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after
{
  content: '';
  content: none;
}
:focus
{
  outline: 0;
}
ins
{
  text-decoration: none;
}
del
{
  text-decoration: line-through;
}
table
{
  border-collapse: collapse;
  border-spacing: 0;
}
sub
{
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}
sup
{
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}
ul, menu, dir
{
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  padding-left: 40px;
}
ol
{
  display: block;
  list-style-type: decimal-leading-zero;
  margin: 1em 0;
  padding-left: 40px;
}
li
{
  display: list-item;
}
ul ul, ul ol, ul dir, ul menu, ul dl, ol ul, ol ol, ol dir, ol menu, ol dl, dir ul, dir ol, dir dir, dir menu, dir dl, menu ul, menu ol, menu dir, menu menu, menu dl, dl ul, dl ol, dl dir, dl menu, dl dl
{
  margin-top: 0;
  margin-bottom: 0;
}
ol ul, ul ul, menu ul, dir ul, ol menu, ul menu, menu menu, dir menu, ol dir, ul dir, menu dir, dir dir
{
  list-style-type: circle;
}
ol ol ul, ol ul ul, ol menu ul, ol dir ul, ol ol menu, ol ul menu, ol menu menu, ol dir menu, ol ol dir, ol ul dir, ol menu dir, ol dir dir, ul ol ul, ul ul ul, ul menu ul, ul dir ul, ul ol menu, ul ul menu, ul menu menu, ul dir menu, ul ol dir, ul ul dir, ul menu dir, ul dir dir, menu ol ul, menu ul ul, menu menu ul, menu dir ul, menu ol menu, menu ul menu, menu menu menu, menu dir menu, menu ol dir, menu ul dir, menu menu dir, menu dir dir, dir ol ul, dir ul ul, dir menu ul, dir dir ul, dir ol menu, dir ul menu, dir menu menu, dir dir menu, dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
  list-style-type: square;
}
.hidden
{
  display: none;
}
p
{
  line-height: 1.5em;
}
h1
{
  font-size: 1.75em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h2
{
  font-size: 1.5em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h3
{
  font-size: 1.25em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h4
{
  font-size: 1em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
html, body
{
  width: 100%;
  height: 100%;
}
body
{
  margin: 0;
  padding: 0;
  background-color: #fff;
  position: relative;
  font: 16px/24px NobileRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
}
a
{
  color: #1b61d6;
  text-decoration: none;
}
a:hover
{
  color: #e88f00;
  text-decoration: underline;
}
body h1, body h2, body h3, body h4, body h5, body h6
{
  font-family: NeutonRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
  font-weight: 400;
  color: #373839;
  font-style: normal;
}
#wrap
{
  min-height: 100%;
}
#header, #footer
{
  width: 100%;
  color: #fff;
  height: 40px;
  position: absolute;
  text-align: center;
  line-height: 40px;
  overflow: hidden;
  font-size: 12px;
  vertical-align: middle;
}
#header
{
  background: #000;
  top: 0;
  font-size: 14px;
}
#footer
{
  bottom: 0;
  background: #000 url(footerbg.png) repeat-x 0 top;
  position: relative;
  margin-top: -40px;
  clear: both;
}
.header, .footer
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.wrapper
{
  width: 100%;
}
#top, #top-small, #bottom
{
  width: 100%;
}
#top
{
  color: #000;
  height: 230px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#top-small
{
  color: #000;
  height: 60px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#bottom
{
  color: #222;
  background-color: #fff;
}
.top, .top-small, .middle, .bottom
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.top
{
  padding-top: 40px;
}
.top-small
{
  padding-top: 10px;
}
#middle
{
  width: 100%;
  height: 100px;
  background: url(middlebg.png) repeat-x;
  border-top: 2px solid #fff;
  border-bottom: 2px solid #b2b2b2;
}
.app-welcome
{
  margin-top: 25px;
}
.app-name
{
  color: #000;
  font-weight: 700;
}
.bottom
{
  padding-top: 50px;
}
#left
{
  width: 350px;
  float: left;
  padding-right: 25px;
}
#right
{
  width: 350px;
  float: right;
  padding-left: 25px;
}
.align-left
{
  text-align: left;
}
.align-right
{
  text-align: right;
}
.align-center
{
  text-align: center;
}
ul.links
{
  margin: 0;
  padding: 0;
}
ul.links li
{
  list-style-type: none;
  font-size: 14px;
}
form
{
  border-style: none;
}
fieldset
{
  border-style: none;
}
input
{
  color: #222;
  border: 1px solid #ccc;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 16px;
}
input[type=text], input[type=password]
{
  width: 205px;
}
input[type=submit]
{
  background-color: #ddd;
  font-weight: 700;
}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
body:before
{
  content: "";
  height: 100%;
  float: left;
  width: 0;
  margin-top: -32767px;
}
docs/narr/advconfig.rst
@@ -414,3 +414,10 @@
constraints are not absolved by two-phase configuration.  Routes are still
added in configuration execution order.
More Information
----------------
For more information, see the article entitled `"A Whirlwind Rour of Advanced
Configuration Tactics"
<http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/configuration/whirlwind_tour.html>`_
in the Pyramid Cookbook.
docs/narr/install.rst
@@ -14,13 +14,13 @@
.. sidebar:: Python Versions
    As of this writing, :app:`Pyramid` has been tested under Python 2.6.6,
    Python 2.7.2, and Python 3.2.  :app:`Pyramid` does not run under any
    version of Python before 2.6.
    As of this writing, :app:`Pyramid` has been tested under Python 2.6.8,
    Python 2.7.3, Python 3.2.3, and Python 3.3b1.  :app:`Pyramid` does not
    run under any version of Python before 2.6.
:app:`Pyramid` is known to run on all popular UNIX-like systems such as
Linux, MacOS X, and FreeBSD as well as on Windows platforms.  It is also
known to run on :term:`PyPy` (1.6+).
known to run on :term:`PyPy` (1.9+).
:app:`Pyramid` installation does not require the compilation of any
C code, so you need only a Python interpreter that meets the
@@ -45,15 +45,15 @@
them is usually the same.
For example, on an Ubuntu Linux system, to use the system package
manager to install a Python 2.6 interpreter, use the following
manager to install a Python 2.7 interpreter, use the following
command:
.. code-block:: text
   $ sudo apt-get install python2.6-dev
   $ sudo apt-get install python2.7-dev
Once these steps are performed, the Python interpreter will usually be
invokable via ``python2.6`` from a shell prompt.
invokable via ``python2.7`` from a shell prompt.
.. index::
   pair: install; Python (from source, UNIX)
@@ -80,7 +80,7 @@
<http://developer.apple.com/tools/xcode/>`_ has much the same effect.
Once you've got development tools installed on your system, you can
install a Python 2.6 interpreter from *source*, on the same system,
install a Python 2.7 interpreter from *source*, on the same system,
using the following commands:
.. code-block:: text
@@ -90,15 +90,15 @@
   [chrism@vitaminf ~]$ mkdir opt
   [chrism@vitaminf ~]$ cd tmp
   [chrism@vitaminf tmp]$ wget \
          http://www.python.org/ftp/python/2.6.4/Python-2.6.4.tgz
   [chrism@vitaminf tmp]$ tar xvzf Python-2.6.4.tgz
   [chrism@vitaminf tmp]$ cd Python-2.6.4
   [chrism@vitaminf Python-2.6.4]$ ./configure \
           --prefix=$HOME/opt/Python-2.6.4
   [chrism@vitaminf Python-2.6.4]$ make; make install
          http://www.python.org/ftp/python/2.7.3/Python-2.7.3.tgz
   [chrism@vitaminf tmp]$ tar xvzf Python-2.7.3.tgz
   [chrism@vitaminf tmp]$ cd Python-2.7.3
   [chrism@vitaminf Python-2.7.3]$ ./configure \
           --prefix=$HOME/opt/Python-2.7.3
   [chrism@vitaminf Python-2.7.3]$ make; make install
Once these steps are performed, the Python interpreter will be
invokable via ``$HOME/opt/Python-2.6.4/bin/python`` from a shell
invokable via ``$HOME/opt/Python-2.7.3/bin/python`` from a shell
prompt.
.. index::
@@ -108,7 +108,7 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If your Windows system doesn't have a Python interpreter, you'll need
to install it by downloading a Python 2.6-series interpreter
to install it by downloading a Python 2.7-series interpreter
executable from `python.org's download section
<http://python.org/download/>`_ (the files labeled "Windows
Installer").  Once you've downloaded it, double click on the
@@ -119,7 +119,7 @@
.. warning::
   After you install Python on Windows, you may need to add the
   ``C:\Python26`` directory to your environment's ``Path`` in order
   ``C:\Python27`` directory to your environment's ``Path`` in order
   to make it possible to invoke Python from a command prompt by
   typing ``python``.  To do so, right click ``My Computer``, select
   ``Properties`` --> ``Advanced Tab`` --> ``Environment Variables``
@@ -141,39 +141,62 @@
also prevent :app:`Pyramid` from globally installing versions of
packages that are not compatible with your system Python.
To set up a virtualenv in which to install :app:`Pyramid`, first
ensure that :term:`setuptools` is installed.  Invoke ``import
setuptools`` within the Python interpreter you'd like to run
:app:`Pyramid` under:
To set up a virtualenv in which to install :app:`Pyramid`, first ensure that
:term:`setuptools` or :term:`distribute` is installed.  To do so, invoke
``import setuptools`` within the Python interpreter you'd like to run
:app:`Pyramid` under.
Here's the output you'll expect if setuptools or distribute is already
installed:
.. code-block:: text
   [chrism@vitaminf pyramid]$ python
   Python 2.6.5 (r265:79063, Apr 29 2010, 00:31:32)
   [GCC 4.4.3] on linux2
   [chrism@thinko docs]$ python2.7
   Python 2.7.3 (default, Aug  1 2012, 05:14:39)
   [GCC 4.6.3] on linux2
   Type "help", "copyright", "credits" or "license" for more information.
   >>> import setuptools
   >>>
If running ``import setuptools`` does not raise an ``ImportError``, it
means that setuptools is already installed into your Python
interpreter.  If ``import setuptools`` fails, you will need to install
setuptools manually.  Note that above we're using a Python 2.6-series
interpreter on Mac OS X; your output may differ if you're using a
later Python version or a different platform.
Here's the output you can expect if setuptools or distribute is not already
installed:
If you are using a "system" Python (one installed by your OS
distributor or a 3rd-party packager such as Fink or MacPorts), you can
usually install the setuptools package by using your system's package
manager.  If you cannot do this, or if you're using a self-installed
version of Python, you will need to install setuptools "by hand".
Installing setuptools "by hand" is always a reasonable thing to do,
even if your package manager already has a pre-chewed version of
setuptools for installation.
.. code-block:: text
To install setuptools by hand, first download `ez_setup.py
<http://peak.telecommunity.com/dist/ez_setup.py>`_ then invoke it
using the Python interpreter into which you want to install
setuptools.
   [chrism@thinko docs]$ python2.7
   Python 2.7.3 (default, Aug  1 2012, 05:14:39)
   [GCC 4.6.3] on linux2
   Type "help", "copyright", "credits" or "license" for more information.
   >>> import setutptools
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   ImportError: No module named setutptools
   >>>
If ``import setuptools`` raises an :exc:`ImportError` as it does above, you
will need to install setuptools or distribute manually.  Note that above
we're using a Python 2.7-series interpreter on Mac OS X; your output may
differ if you're using a later Python version or a different platform.
If you are using a "system" Python (one installed by your OS distributor or a
3rd-party packager such as Fink or MacPorts), you can usually install the
setuptools or distribute package by using your system's package manager.  If
you cannot do this, or if you're using a self-installed version of Python,
you will need to install setuptools or distribute "by hand".  Installing
setuptools or distribute "by hand" is always a reasonable thing to do, even
if your package manager already has a pre-chewed version of setuptools for
installation.
If you're using Python 2, you'll want to install ``setuptools``.  If you're
using Python 3, you'll want to install ``distribute``.  Below we tell you how
to do both.
Installing Setuptools On Python 2
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To install setuptools by hand under Python 2, first download `ez_setup.py
<http://peak.telecommunity.com/dist/ez_setup.py>`_ then invoke it using the
Python interpreter into which you want to install setuptools.
.. code-block:: text
@@ -188,16 +211,37 @@
   $ sudo python ez_setup.py
Installing Distribute On Python 3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
``setuptools`` doesn't work under Python 3.  Instead, you can use
``distribute``, which is a fork of setuptools that does work on Python 3.  To
install it, first download `distribute_setup.py
<http://python-distribute.org/distribute_setup.py>`_ then invoke it using the
Python interpreter into which you want to install setuptools.
.. code-block:: text
   $ python3 distribute_setup.py
Once this command is invoked, distribute should be installed on your system.
If the command fails due to permission errors, you may need to be the
administrative user on your system to successfully invoke the script.  To
remediate this, you may need to do:
.. code-block:: text
   $ sudo python3 distribute_setup.py
.. index::
   pair: install; virtualenv
Installing the ``virtualenv`` Package
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Once you've got setuptools installed, you should install the
:term:`virtualenv` package.  To install the :term:`virtualenv` package
into your setuptools-enabled Python interpreter, use the
``easy_install`` command.
Once you've got setuptools or distribute installed, you should install the
:term:`virtualenv` package.  To install the :term:`virtualenv` package into
your setuptools-enabled Python interpreter, use the ``easy_install`` command.
.. code-block:: text
@@ -269,35 +313,41 @@
Installing :app:`Pyramid` on a Windows System
-------------------------------------------------
#. Install, or find `Python 2.6
   <http://python.org/download/releases/2.6.4/>`_ for your system.
You can use Pyramid on Windows under Python 2 or under Python 3.  Directions
for both versions are included below.
Windows Using Python 2
~~~~~~~~~~~~~~~~~~~~~~
#. Install, or find `Python 2.7
   <http://www.python.org/download/releases/2.7.3/>`_ for your system.
#. Install the `Python for Windows extensions
   <http://sourceforge.net/projects/pywin32/files/>`_.  Make sure to
   pick the right download for Python 2.6 and install it using the
   pick the right download for Python 2.7 and install it using the
   same Python installation from the previous step.
#. Install latest :term:`setuptools` distribution into the Python you
   obtained/installed/found in the step above: download `ez_setup.py
   <http://peak.telecommunity.com/dist/ez_setup.py>`_ and run it using
   the ``python`` interpreter of your Python 2.6 installation using a
   the ``python`` interpreter of your Python 2.7 installation using a
   command prompt:
   .. code-block:: text
      c:\> c:\Python26\python ez_setup.py
      c:\> c:\Python27\python ez_setup.py
#. Use that Python's `bin/easy_install` to install `virtualenv`:
   .. code-block:: text
      c:\> c:\Python26\Scripts\easy_install virtualenv
      c:\> c:\Python27\Scripts\easy_install virtualenv
#. Use that Python's virtualenv to make a workspace:
   .. code-block:: text
      c:\> c:\Python26\Scripts\virtualenv --no-site-packages env
      c:\> c:\Python27\Scripts\virtualenv --no-site-packages env
#. Switch to the ``env`` directory:
@@ -308,8 +358,57 @@
#. (Optional) Consider using ``Scripts\activate.bat`` to make your shell
   environment wired to use the virtualenv.
#. Use ``easy_install`` pointed at the "current" index to get
   :app:`Pyramid` and its direct dependencies installed:
#. Use ``easy_install`` to get :app:`Pyramid` and its direct dependencies
   installed:
   .. code-block:: text
      c:\env> Scripts\easy_install pyramid
Windows Using Python 3
~~~~~~~~~~~~~~~~~~~~~~
#. Install, or find `Python 3.2
   <http://www.python.org/download/releases/3.2.3/>`_ for your system.
#. Install the `Python for Windows extensions
   <http://sourceforge.net/projects/pywin32/files/>`_.  Make sure to
   pick the right download for Python 3.2 and install it using the
   same Python installation from the previous step.
#. Install latest :term:`distribute` distribution into the Python you
   obtained/installed/found in the step above: download `distribute_setup.py
   <http://python-distribute.org/distribute_setup.py>`_ and run it using the
   ``python`` interpreter of your Python 3.2 installation using a command
   prompt:
   .. code-block:: text
      c:\> c:\Python32\python distribute_setup.py
#. Use that Python's `bin/easy_install` to install `virtualenv`:
   .. code-block:: text
      c:\> c:\Python32\Scripts\easy_install virtualenv
#. Use that Python's virtualenv to make a workspace:
   .. code-block:: text
      c:\> c:\Python32\Scripts\virtualenv --no-site-packages env
#. Switch to the ``env`` directory:
   .. code-block:: text
      c:\> cd env
#. (Optional) Consider using ``Scripts\activate.bat`` to make your shell
   environment wired to use the virtualenv.
#. Use ``easy_install`` to get :app:`Pyramid` and its direct dependencies
   installed:
   .. code-block:: text
docs/narr/introduction.rst
@@ -315,7 +315,7 @@
If you use a :term:`renderer`, you don't have to return a special kind of
"webby" ``Response`` object from a view.  Instead, you can return a
dictionary instead, and Pyramid will take care of converting that dictionary
dictionary, and Pyramid will take care of converting that dictionary
to a Response using a template on your behalf.  This makes the view easier to
test, because you don't have to parse HTML in your tests; just make an
assertion instead that the view returns "the right stuff" in the dictionary
docs/narr/introspector.rst
@@ -393,6 +393,10 @@
    The ``match_param`` argument passed to ``add_view``.
  ``csrf_token``
    The ``csrf_token`` argument passed to ``add_view``.
  ``callable``
    The (resolved) ``view`` argument passed to ``add_view``.  Represents the
docs/narr/project.rst
@@ -286,11 +286,39 @@
   $ ../bin/pserve development.ini
   Starting server in PID 16601.
   serving on 0.0.0.0:6543 view at http://127.0.0.1:6543
   serving on http://0.0.0.0:6543
By default, :app:`Pyramid` applications generated from a scaffold
will listen on TCP port 6543.  You can shut down a server started this way by
pressing ``Ctrl-C``.
When you use ``pserve`` to start the application implied by the default
rendering of a scaffold, it will respond to requests on *all* IP addresses
possessed by your system, not just requests to ``localhost``.  This is what
the ``0.0.0.0`` in ``serving on http://0.0.0.0:6543`` means.  The server will
respond to requests made to ``127.0.0.1`` and on any external IP address.
For example, your system might be configured to have an external IP address
``192.168.1.50``.  If that's the case, if you use a browser running on the
same system as Pyramid, it will be able to access the application via
``http://127.0.0.1:6543/`` as well as via
``http://129.168.1.50:6543/``. However, *other people* on other computers on
the same network will also be able to visit your Pyramid application in their
browser by visiting ``http://192.168.1.50:6543/``.
If you want to restrict access such that only a browser running on the same
machine as Pyramid will be able to access your Pyramid application, edit the
``development.ini`` file, and replace the ``host`` value in the
``[server:main]`` section.  Change it from ``0.0.0.0`` to ``127.0.0.1``.  For
example::
   [server:main]
   use = egg:waitress#main
   host = 127.0.0.1
   port = 6543
You can change the port on which the server runs on by changing the same
portion of the ``development.ini`` file.  For example, you can change the
``port = 6543`` line in the ``development.ini`` file's ``[server:main]``
section to ``port = 8080`` to run the server on port 8080 instead of
port 6543.
You can shut down a server started this way by pressing ``Ctrl-C``.
The default server used to run your Pyramid application when a project is
created from a scaffold is named :term:`Waitress`.  This server is what
@@ -308,11 +336,6 @@
under the default server, it will almost certainly work under any other
server in production if you eventually choose to use a different one.  Don't
worry about it right now.
You can change the port on which the server runs on by changing the
``development.ini`` file.  For example, you can change the ``port = 6543``
line in the ``development.ini`` file's ``[server:main]`` section to ``port =
8080`` to run the server on port 8080 instead of port 6543.
For more detailed information about the startup process, see
:ref:`startup_chapter`.  For more information about environment variables and
docs/narr/subrequest.rst
New file
@@ -0,0 +1,271 @@
.. index::
   single: subrequest
.. _subrequest_chapter:
Invoking a Subrequest
=====================
.. warning::
   This feature was added in Pyramid 1.4a1.
:app:`Pyramid` allows you to invoke a subrequest at any point during the
processing of a request.  Invoking a subrequest allows you to obtain a
:term:`response` object from a view callable within your :app:`Pyramid`
application while you're executing a different view callable within the same
application.
Here's an example application which uses a subrequest:
.. code-block:: python
   from wsgiref.simple_server import make_server
   from pyramid.config import Configurator
   from pyramid.request import Request
   def view_one(request):
       subreq = Request.blank('/view_two')
       response = request.invoke_subrequest(subreq)
       return response
   def view_two(request):
       request.response.body = 'This came from view_two'
       return request.response
   if __name__ == '__main__':
       config = Configurator()
       config.add_route('one', '/view_one')
       config.add_route('two', '/view_two')
       config.add_view(view_one, route_name='one')
       config.add_view(view_two, route_name='two')
       app = config.make_wsgi_app()
       server = make_server('0.0.0.0', 8080, app)
       server.serve_forever()
When ``/view_one`` is visted in a browser, the text printed in the browser
pane will be ``This came from view_two``.  The ``view_one`` view used the
:meth:`pyramid.request.Request.invoke_subrequest` API to obtain a response
from another view (``view_two``) within the same application when it
executed.  It did so by constructing a new request that had a URL that it
knew would match the ``view_two`` view registration, and passed that new
request along to :meth:`pyramid.request.Request.invoke_subrequest`.  The
``view_two`` view callable was invoked, and it returned a response.  The
``view_one`` view callable then simply returned the response it obtained from
the ``view_two`` view callable.
Note that it doesn't matter if the view callable invoked via a subrequest
actually returns a *literal* Response object.  Any view callable that uses a
renderer or which returns an object that can be interpreted by a response
adapter when found and invoked via
:meth:`pyramid.request.Request.invoke_subrequest` will return a Response
object:
.. code-block:: python
   from wsgiref.simple_server import make_server
   from pyramid.config import Configurator
   from pyramid.request import Request
   def view_one(request):
       subreq = Request.blank('/view_two')
       response = request.invoke_subrequest(subreq)
       return response
   def view_two(request):
       return 'This came from view_two'
   if __name__ == '__main__':
       config = Configurator()
       config.add_route('one', '/view_one')
       config.add_route('two', '/view_two')
       config.add_view(view_one, route_name='one')
       config.add_view(view_two, route_name='two', renderer='string')
       app = config.make_wsgi_app()
       server = make_server('0.0.0.0', 8080, app)
       server.serve_forever()
Even though the ``view_two`` view callable returned a string, it was invoked
in such a way that the ``string`` renderer associated with the view
registration that was found turned it into a "real" response object for
consumption by ``view_one``.
Being able to unconditionally obtain a response object by invoking a view
callable indirectly is the main advantage to using
:meth:`pyramid.request.Request.invoke_subrequest` instead of simply importing
a view callable and executing it directly.  Note that there's not much
advantage to invoking a view using a subrequest if you *can* invoke a view
callable directly.  Subrequests are slower and are less convenient if you
actually do want just the literal information returned by a function that
happens to be a view callable.
Note that, by default, if a view callable invoked by a subrequest raises an
exception, the exception will be raised to the caller of
:meth:`~pyramid.request.Request.invoke_subrequest` even if you have a
:term:`exception view` configured:
.. code-block:: python
   from wsgiref.simple_server import make_server
   from pyramid.config import Configurator
   from pyramid.request import Request
   def view_one(request):
       subreq = Request.blank('/view_two')
       response = request.invoke_subrequest(subreq)
       return response
   def view_two(request):
       raise ValueError('foo')
   def excview(request):
       request.response.body = b'An exception was raised'
       request.response.status_int = 500
       return request.response
   if __name__ == '__main__':
       config = Configurator()
       config.add_route('one', '/view_one')
       config.add_route('two', '/view_two')
       config.add_view(view_one, route_name='one')
       config.add_view(view_two, route_name='two', renderer='string')
       config.add_view(excview, context=Exception)
       app = config.make_wsgi_app()
       server = make_server('0.0.0.0', 8080, app)
       server.serve_forever()
When we run the above code and visit ``/view_one`` in a browser, the
``excview`` :term:`exception view` will *not* be executed.  Instead, the call
to :meth:`~pyramid.request.Request.invoke_subrequest` will cause a
:exc:`ValueError` exception to be raised and a response will never be
generated.  We can change this behavior; how to do so is described below in
our discussion of the ``use_tweens`` argument.
The :meth:`pyramid.request.Request.invoke_subrequest` API accepts two
arguments: a positional argument ``request`` that must be provided, and and
``use_tweens`` keyword argument that is optional; it defaults to ``False``.
The ``request`` object passed to the API must be an object that implements
the Pyramid request interface (such as a :class:`pyramid.request.Request`
instance).  If ``use_tweens`` is ``True``, the request will be sent to the
:term:`tween` in the tween stack closest to the request ingress.  If
``use_tweens`` is ``False``, the request will be sent to the main router
handler, and no tweens will be invoked.
In the example above, the call to
:meth:`~pyramid.request.Request.invoke_subrequest` will always raise an
exception.  This is because it's using the default value for ``use_tweens``,
which is ``False``.  You can pass ``use_tweens=True`` instead to ensure that
it will convert an exception to a Response if an :term:`exception view` is
configured instead of raising the exception.  This because exception views
are called by the exception view :term:`tween` as described in
:ref:`exception_views` when any view raises an exception.
We can cause the subrequest to be run through the tween stack by passing
``use_tweens=True`` to the call to
:meth:`~pyramid.request.Request.invoke_subrequest`, like this:
.. code-block:: python
   from wsgiref.simple_server import make_server
   from pyramid.config import Configurator
   from pyramid.request import Request
   def view_one(request):
       subreq = Request.blank('/view_two')
       response = request.invoke_subrequest(subreq, use_tweens=True)
       return response
   def view_two(request):
       raise ValueError('foo')
   def excview(request):
       request.response.body = b'An exception was raised'
       request.response.status_int = 500
       return request.response
   if __name__ == '__main__':
       config = Configurator()
       config.add_route('one', '/view_one')
       config.add_route('two', '/view_two')
       config.add_view(view_one, route_name='one')
       config.add_view(view_two, route_name='two', renderer='string')
       config.add_view(excview, context=Exception)
       app = config.make_wsgi_app()
       server = make_server('0.0.0.0', 8080, app)
       server.serve_forever()
In the above case, the call to ``request.invoke_subrequest(subreq)`` will not
raise an exception.  Instead, it will retrieve a "500" response from the
attempted invocation of ``view_two``, because the tween which invokes an
exception view to generate a response is run, and therefore ``excview`` is
executed.
This is one of the major differences between specifying the
``use_tweens=True`` and ``use_tweens=False`` arguments to
:meth:`~pyramid.request.Request.invoke_subrequest`.  ``use_tweens=True`` may
also imply invoking transaction commit/abort for the logic executed in the
subrequest if you've got ``pyramid_tm`` in the tween list, injecting debug
HTML if you've got ``pyramid_debugtoolbar`` in the tween list, and other
tween-related side effects as defined by your particular tween list.
The :meth:`~pyramid.request.Request.invoke_subrequest` function also
unconditionally:
- manages the threadlocal stack so that
  :func:`~pyramid.threadlocal.get_current_request` and
  :func:`~pyramid.threadlocal.get_current_registry` work during a request
  (they will return the subrequest instead of the original request)
- Adds a ``registry`` attribute and a ``invoke_subrequest`` attribute (a
  callable) to the request object it's handed.
- sets request extensions (such as those added via
  :meth:`~pyramid.config.Configurator.add_request_method` or
  :meth:`~pyramid.config.Configurator.set_request_property`) on the subrequest
  object passed as ``request``
- causes a :class:`~pyramid.event.NewRequest` event to be sent at the
  beginning of request processing.
- causes a :class:`~pyramid.event.ContextFound` event to be sent when a
  context resource is found.
- Ensures that the user implied by the request passed has the necessary
  authorization to invoke view callable before calling it.
- causes a :class:`~pyramid.event.NewResponse` event to be sent when the
  Pyramid application returns a response.
- Calls any :term:`response callback` functions defined within the subrequest's
  lifetime if a response is obtained from the Pyramid application.
- Calls any :term:`finished callback` functions defined within the subrequest's
  lifetime.
The invocation of a subrequest has more or less exactly the same effect as
the invocation of a request received by the Pyramid router from a web client
when ``use_tweens=True``.  When ``use_tweens=False``, the tweens are skipped
but all the other steps take place.
It's a poor idea to use the original ``request`` object as an argument to
:meth:`~pyramid.request.Request.invoke_subrequest`.  You should construct a
new request instead as demonstrated in the above example, using
:meth:`pyramid.request.Request.blank`.  Once you've constructed a request
object, you'll need to massage the it to match the view callable you'd like
to be executed during the subrequest.  This can be done by adjusting the
subrequest's URL, its headers, its request method, and other attributes.  The
documentation for :class:`pyramid.request.Request` exposes the methods you
should call and attributes you should set on the request you create to
massage it into something that will actually match the view you'd like to
call via a subrequest.
We've demonstrated use of a subrequest from within a view callable, but you
can use the :meth:`~pyramid.request.Request.invoke_subrequest` API from
within a tween or an event handler as well.  It's usually a poor idea to
invoke :meth:`~pyramid.request.Request.invoke_subrequest` from within a
tween, because tweens already by definition have access to a function that
will cause a subrequest (they are passed a ``handle`` function), but you can
do it.  It's fine to invoke
:meth:`~pyramid.request.Request.invoke_subrequest` from within an event
handler, however.
docs/narr/testing.rst
@@ -157,6 +157,30 @@
:class:`pyramid.testing.DummyRequest` because it's easier to construct
than a "real" :app:`Pyramid` request object.
Test setup using a context manager
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
An alternative style of setting up a test configuration is to use the
`with` statement and :func:`pyramid.testing.testConfig` to create a
context manager. The context manager will call
:func:`pyramid.testing.setUp` before the code under test and
:func:`pyramid.testing.tearDown` afterwards.
This style is useful for small self-contained tests. For example:
.. code-block:: python
   :linenos:
   import unittest
   class MyTest(unittest.TestCase):
       def test_my_function(self):
           from pyramid import testing
           with testing.testConfig() as config:
               config.add_route('bar', '/bar/{id}')
               my_function_which_needs_route_bar()
What?
~~~~~
docs/narr/upgrading.rst
@@ -1,3 +1,5 @@
.. _upgrading_chapter:
Upgrading Pyramid
=================
docs/narr/viewconfig.rst
@@ -394,6 +394,28 @@
  consideration when deciding whether or not to invoke the associated view
  callable.
``check_csrf``
  If specified, this value should be one of ``None``, ``True``, ``False``, or
  a string representing the 'check name'.  If the value is ``True`` or a
  string, CSRF checking will be performed.  If the value is ``False`` or
  ``None``, CSRF checking will not be performed.
  If the value provided is a string, that string will be used as the 'check
  name'.  If the value provided is ``True``, ``csrf_token`` will be used as
  the check name.
  If CSRF checking is performed, the checked value will be the value of
  ``request.params[check_name]``.  This value will be compared against the
  value of ``request.session.get_csrf_token()``, and the check will pass if
  these two values are the same.  If the check passes, the associated view
  will be permitted to execute.  If the check fails, the associated view
  will not be permitted to execute.
  Note that using this feature requires a :term:`session factory` to have
  been configured.
  .. versionadded:: 1.4a2
``custom_predicates``
  If ``custom_predicates`` is specified, it must be a sequence of references
  to custom predicate callables.  Use custom predicates when no set of
@@ -407,6 +429,15 @@
  If ``custom_predicates`` is not specified, no custom predicates are
  used.
``predicates``
  Pass a key/value pair here to use a third-party predicate registered via
  :meth:`pyramid.config.Configurator.add_view_predicate`.  More than one
  key/value pair can be used at the same time.  See
  :ref:`view_and_route_predicates` for more information about third-party
  predicates.
  .. versionadded:: 1.4a1
.. index::
   single: view_config decorator
docs/narr/views.rst
@@ -338,6 +338,16 @@
Exception views can be configured with any view registration mechanism:
``@view_config`` decorator or imperative ``add_view`` styles.
.. note::
   Pyramid's :term:`exception view` handling logic is implemented as a tween
   factory function: :func:`pyramid.tweens.excview_tween_factory`.  If
   Pyramid exception view handling is desired, and tween factories are
   specified via the ``pyramid.tweens`` configuration setting, the
   :func:`pyramid.tweens.excview_tween_factory` function must be added to the
   ``pyramid.tweens`` configuration setting list explicitly.  If it is not
   present, Pyramid will not perform exception view handling.
.. index::
   single: view http redirect
   single: http redirect (from a view)
docs/tutorials/wiki/src/authorization/tutorial/static/pylons.css
@@ -1,65 +1,372 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td
{
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-size: 100%; /* 16px */
  vertical-align: baseline;
  background: transparent;
}
body
{
  line-height: 1;
}
ol, ul
{
  list-style: none;
}
blockquote, q
{
  quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after
{
  content: '';
  content: none;
}
:focus
{
  outline: 0;
}
ins
{
  text-decoration: none;
}
del
{
  text-decoration: line-through;
}
table
{
  border-collapse: collapse;
  border-spacing: 0;
}
sub
{
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}
sup
{
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}
ul, menu, dir
{
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  padding-left: 40px;
}
ol
{
  display: block;
  list-style-type: decimal-leading-zero;
  margin: 1em 0;
  padding-left: 40px;
}
li
{
  display: list-item;
}
ul ul, ul ol, ul dir, ul menu, ul dl, ol ul, ol ol, ol dir, ol menu, ol dl, dir ul, dir ol, dir dir, dir menu, dir dl, menu ul, menu ol, menu dir, menu menu, menu dl, dl ul, dl ol, dl dir, dl menu, dl dl
{
  margin-top: 0;
  margin-bottom: 0;
}
ol ul, ul ul, menu ul, dir ul, ol menu, ul menu, menu menu, dir menu, ol dir, ul dir, menu dir, dir dir
{
  list-style-type: circle;
}
ol ol ul, ol ul ul, ol menu ul, ol dir ul, ol ol menu, ol ul menu, ol menu menu, ol dir menu, ol ol dir, ol ul dir, ol menu dir, ol dir dir, ul ol ul, ul ul ul, ul menu ul, ul dir ul, ul ol menu, ul ul menu, ul menu menu, ul dir menu, ul ol dir, ul ul dir, ul menu dir, ul dir dir, menu ol ul, menu ul ul, menu menu ul, menu dir ul, menu ol menu, menu ul menu, menu menu menu, menu dir menu, menu ol dir, menu ul dir, menu menu dir, menu dir dir, dir ol ul, dir ul ul, dir menu ul, dir dir ul, dir ol menu, dir ul menu, dir menu menu, dir dir menu, dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
  list-style-type: square;
}
.hidden
{
  display: none;
}
p
{
  line-height: 1.5em;
}
h1
{
  font-size: 1.75em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h2
{
  font-size: 1.5em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h3
{
  font-size: 1.25em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h4
{
  font-size: 1em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
html, body
{
  width: 100%;
  height: 100%;
}
body
{
  margin: 0;
  padding: 0;
  background-color: #fff;
  position: relative;
  font: 16px/24px NobileRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
}
a
{
  color: #1b61d6;
  text-decoration: none;
}
a:hover
{
  color: #e88f00;
  text-decoration: underline;
}
body h1, body h2, body h3, body h4, body h5, body h6
{
  font-family: NeutonRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
  font-weight: 400;
  color: #373839;
  font-style: normal;
}
#wrap
{
  min-height: 100%;
}
#header, #footer
{
  width: 100%;
  color: #fff;
  height: 40px;
  position: absolute;
  text-align: center;
  line-height: 40px;
  overflow: hidden;
  font-size: 12px;
  vertical-align: middle;
}
#header
{
  background: #000;
  top: 0;
  font-size: 14px;
}
#footer
{
  bottom: 0;
  background: #000 url(footerbg.png) repeat-x 0 top;
  position: relative;
  margin-top: -40px;
  clear: both;
}
.header, .footer
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.wrapper
{
  width: 100%;
}
#top, #top-small, #bottom
{
  width: 100%;
}
#top
{
  color: #000;
  height: 230px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#top-small
{
  color: #000;
  height: 60px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#bottom
{
  color: #222;
  background-color: #fff;
}
.top, .top-small, .middle, .bottom
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.top
{
  padding-top: 40px;
}
.top-small
{
  padding-top: 10px;
}
#middle
{
  width: 100%;
  height: 100px;
  background: url(middlebg.png) repeat-x;
  border-top: 2px solid #fff;
  border-bottom: 2px solid #b2b2b2;
}
.app-welcome
{
  margin-top: 25px;
}
.app-name
{
  color: #000;
  font-weight: 700;
}
.bottom
{
  padding-top: 50px;
}
#left
{
  width: 350px;
  float: left;
  padding-right: 25px;
}
#right
{
  width: 350px;
  float: right;
  padding-left: 25px;
}
.align-left
{
  text-align: left;
}
.align-right
{
  text-align: right;
}
.align-center
{
  text-align: center;
}
ul.links
{
  margin: 0;
  padding: 0;
}
ul.links li
{
  list-style-type: none;
  font-size: 14px;
}
form
{
  border-style: none;
}
fieldset
{
  border-style: none;
}
input
{
  color: #222;
  border: 1px solid #ccc;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 16px;
}
input[type=text], input[type=password]
{
  width: 205px;
}
input[type=submit]
{
  background-color: #ddd;
  font-weight: 700;
}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
body:before
{
  content: "";
  height: 100%;
  float: left;
  width: 0;
  margin-top: -32767px;
}
docs/tutorials/wiki/src/basiclayout/tutorial/static/pylons.css
@@ -1,65 +1,372 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td
{
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-size: 100%; /* 16px */
  vertical-align: baseline;
  background: transparent;
}
body
{
  line-height: 1;
}
ol, ul
{
  list-style: none;
}
blockquote, q
{
  quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after
{
  content: '';
  content: none;
}
:focus
{
  outline: 0;
}
ins
{
  text-decoration: none;
}
del
{
  text-decoration: line-through;
}
table
{
  border-collapse: collapse;
  border-spacing: 0;
}
sub
{
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}
sup
{
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}
ul, menu, dir
{
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  padding-left: 40px;
}
ol
{
  display: block;
  list-style-type: decimal-leading-zero;
  margin: 1em 0;
  padding-left: 40px;
}
li
{
  display: list-item;
}
ul ul, ul ol, ul dir, ul menu, ul dl, ol ul, ol ol, ol dir, ol menu, ol dl, dir ul, dir ol, dir dir, dir menu, dir dl, menu ul, menu ol, menu dir, menu menu, menu dl, dl ul, dl ol, dl dir, dl menu, dl dl
{
  margin-top: 0;
  margin-bottom: 0;
}
ol ul, ul ul, menu ul, dir ul, ol menu, ul menu, menu menu, dir menu, ol dir, ul dir, menu dir, dir dir
{
  list-style-type: circle;
}
ol ol ul, ol ul ul, ol menu ul, ol dir ul, ol ol menu, ol ul menu, ol menu menu, ol dir menu, ol ol dir, ol ul dir, ol menu dir, ol dir dir, ul ol ul, ul ul ul, ul menu ul, ul dir ul, ul ol menu, ul ul menu, ul menu menu, ul dir menu, ul ol dir, ul ul dir, ul menu dir, ul dir dir, menu ol ul, menu ul ul, menu menu ul, menu dir ul, menu ol menu, menu ul menu, menu menu menu, menu dir menu, menu ol dir, menu ul dir, menu menu dir, menu dir dir, dir ol ul, dir ul ul, dir menu ul, dir dir ul, dir ol menu, dir ul menu, dir menu menu, dir dir menu, dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
  list-style-type: square;
}
.hidden
{
  display: none;
}
p
{
  line-height: 1.5em;
}
h1
{
  font-size: 1.75em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h2
{
  font-size: 1.5em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h3
{
  font-size: 1.25em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h4
{
  font-size: 1em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
html, body
{
  width: 100%;
  height: 100%;
}
body
{
  margin: 0;
  padding: 0;
  background-color: #fff;
  position: relative;
  font: 16px/24px NobileRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
}
a
{
  color: #1b61d6;
  text-decoration: none;
}
a:hover
{
  color: #e88f00;
  text-decoration: underline;
}
body h1, body h2, body h3, body h4, body h5, body h6
{
  font-family: NeutonRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
  font-weight: 400;
  color: #373839;
  font-style: normal;
}
#wrap
{
  min-height: 100%;
}
#header, #footer
{
  width: 100%;
  color: #fff;
  height: 40px;
  position: absolute;
  text-align: center;
  line-height: 40px;
  overflow: hidden;
  font-size: 12px;
  vertical-align: middle;
}
#header
{
  background: #000;
  top: 0;
  font-size: 14px;
}
#footer
{
  bottom: 0;
  background: #000 url(footerbg.png) repeat-x 0 top;
  position: relative;
  margin-top: -40px;
  clear: both;
}
.header, .footer
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.wrapper
{
  width: 100%;
}
#top, #top-small, #bottom
{
  width: 100%;
}
#top
{
  color: #000;
  height: 230px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#top-small
{
  color: #000;
  height: 60px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#bottom
{
  color: #222;
  background-color: #fff;
}
.top, .top-small, .middle, .bottom
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.top
{
  padding-top: 40px;
}
.top-small
{
  padding-top: 10px;
}
#middle
{
  width: 100%;
  height: 100px;
  background: url(middlebg.png) repeat-x;
  border-top: 2px solid #fff;
  border-bottom: 2px solid #b2b2b2;
}
.app-welcome
{
  margin-top: 25px;
}
.app-name
{
  color: #000;
  font-weight: 700;
}
.bottom
{
  padding-top: 50px;
}
#left
{
  width: 350px;
  float: left;
  padding-right: 25px;
}
#right
{
  width: 350px;
  float: right;
  padding-left: 25px;
}
.align-left
{
  text-align: left;
}
.align-right
{
  text-align: right;
}
.align-center
{
  text-align: center;
}
ul.links
{
  margin: 0;
  padding: 0;
}
ul.links li
{
  list-style-type: none;
  font-size: 14px;
}
form
{
  border-style: none;
}
fieldset
{
  border-style: none;
}
input
{
  color: #222;
  border: 1px solid #ccc;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 16px;
}
input[type=text], input[type=password]
{
  width: 205px;
}
input[type=submit]
{
  background-color: #ddd;
  font-weight: 700;
}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
body:before
{
  content: "";
  height: 100%;
  float: left;
  width: 0;
  margin-top: -32767px;
}
docs/tutorials/wiki/src/models/tutorial/static/pylons.css
@@ -1,65 +1,372 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-snall,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td
{
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-size: 100%; /* 16px */
  vertical-align: baseline;
  background: transparent;
}
body
{
  line-height: 1;
}
ol, ul
{
  list-style: none;
}
blockquote, q
{
  quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after
{
  content: '';
  content: none;
}
:focus
{
  outline: 0;
}
ins
{
  text-decoration: none;
}
del
{
  text-decoration: line-through;
}
table
{
  border-collapse: collapse;
  border-spacing: 0;
}
sub
{
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}
sup
{
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}
ul, menu, dir
{
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  padding-left: 40px;
}
ol
{
  display: block;
  list-style-type: decimal-leading-zero;
  margin: 1em 0;
  padding-left: 40px;
}
li
{
  display: list-item;
}
ul ul, ul ol, ul dir, ul menu, ul dl, ol ul, ol ol, ol dir, ol menu, ol dl, dir ul, dir ol, dir dir, dir menu, dir dl, menu ul, menu ol, menu dir, menu menu, menu dl, dl ul, dl ol, dl dir, dl menu, dl dl
{
  margin-top: 0;
  margin-bottom: 0;
}
ol ul, ul ul, menu ul, dir ul, ol menu, ul menu, menu menu, dir menu, ol dir, ul dir, menu dir, dir dir
{
  list-style-type: circle;
}
ol ol ul, ol ul ul, ol menu ul, ol dir ul, ol ol menu, ol ul menu, ol menu menu, ol dir menu, ol ol dir, ol ul dir, ol menu dir, ol dir dir, ul ol ul, ul ul ul, ul menu ul, ul dir ul, ul ol menu, ul ul menu, ul menu menu, ul dir menu, ul ol dir, ul ul dir, ul menu dir, ul dir dir, menu ol ul, menu ul ul, menu menu ul, menu dir ul, menu ol menu, menu ul menu, menu menu menu, menu dir menu, menu ol dir, menu ul dir, menu menu dir, menu dir dir, dir ol ul, dir ul ul, dir menu ul, dir dir ul, dir ol menu, dir ul menu, dir menu menu, dir dir menu, dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
  list-style-type: square;
}
.hidden
{
  display: none;
}
p
{
  line-height: 1.5em;
}
h1
{
  font-size: 1.75em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h2
{
  font-size: 1.5em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h3
{
  font-size: 1.25em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h4
{
  font-size: 1em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
html, body
{
  width: 100%;
  height: 100%;
}
body
{
  margin: 0;
  padding: 0;
  background-color: #fff;
  position: relative;
  font: 16px/24px NobileRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
}
a
{
  color: #1b61d6;
  text-decoration: none;
}
a:hover
{
  color: #e88f00;
  text-decoration: underline;
}
body h1, body h2, body h3, body h4, body h5, body h6
{
  font-family: NeutonRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
  font-weight: 400;
  color: #373839;
  font-style: normal;
}
#wrap
{
  min-height: 100%;
}
#header, #footer
{
  width: 100%;
  color: #fff;
  height: 40px;
  position: absolute;
  text-align: center;
  line-height: 40px;
  overflow: hidden;
  font-size: 12px;
  vertical-align: middle;
}
#header
{
  background: #000;
  top: 0;
  font-size: 14px;
}
#footer
{
  bottom: 0;
  background: #000 url(footerbg.png) repeat-x 0 top;
  position: relative;
  margin-top: -40px;
  clear: both;
}
.header, .footer
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.wrapper
{
  width: 100%;
}
#top, #top-small, #bottom
{
  width: 100%;
}
#top
{
  color: #000;
  height: 230px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#top-small
{
  color: #000;
  height: 60px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#bottom
{
  color: #222;
  background-color: #fff;
}
.top, .top-small, .middle, .bottom
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.top
{
  padding-top: 40px;
}
.top-small
{
  padding-top: 10px;
}
#middle
{
  width: 100%;
  height: 100px;
  background: url(middlebg.png) repeat-x;
  border-top: 2px solid #fff;
  border-bottom: 2px solid #b2b2b2;
}
.app-welcome
{
  margin-top: 25px;
}
.app-name
{
  color: #000;
  font-weight: 700;
}
.bottom
{
  padding-top: 50px;
}
#left
{
  width: 350px;
  float: left;
  padding-right: 25px;
}
#right
{
  width: 350px;
  float: right;
  padding-left: 25px;
}
.align-left
{
  text-align: left;
}
.align-right
{
  text-align: right;
}
.align-center
{
  text-align: center;
}
ul.links
{
  margin: 0;
  padding: 0;
}
ul.links li
{
  list-style-type: none;
  font-size: 14px;
}
form
{
  border-style: none;
}
fieldset
{
  border-style: none;
}
input
{
  color: #222;
  border: 1px solid #ccc;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 16px;
}
input[type=text], input[type=password]
{
  width: 205px;
}
input[type=submit]
{
  background-color: #ddd;
  font-weight: 700;
}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
body:before
{
  content: "";
  height: 100%;
  float: left;
  width: 0;
  margin-top: -32767px;
}
docs/tutorials/wiki/src/tests/tutorial/static/pylons.css
@@ -1,65 +1,372 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td
{
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-size: 100%; /* 16px */
  vertical-align: baseline;
  background: transparent;
}
body
{
  line-height: 1;
}
ol, ul
{
  list-style: none;
}
blockquote, q
{
  quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after
{
  content: '';
  content: none;
}
:focus
{
  outline: 0;
}
ins
{
  text-decoration: none;
}
del
{
  text-decoration: line-through;
}
table
{
  border-collapse: collapse;
  border-spacing: 0;
}
sub
{
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}
sup
{
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}
ul, menu, dir
{
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  padding-left: 40px;
}
ol
{
  display: block;
  list-style-type: decimal-leading-zero;
  margin: 1em 0;
  padding-left: 40px;
}
li
{
  display: list-item;
}
ul ul, ul ol, ul dir, ul menu, ul dl, ol ul, ol ol, ol dir, ol menu, ol dl, dir ul, dir ol, dir dir, dir menu, dir dl, menu ul, menu ol, menu dir, menu menu, menu dl, dl ul, dl ol, dl dir, dl menu, dl dl
{
  margin-top: 0;
  margin-bottom: 0;
}
ol ul, ul ul, menu ul, dir ul, ol menu, ul menu, menu menu, dir menu, ol dir, ul dir, menu dir, dir dir
{
  list-style-type: circle;
}
ol ol ul, ol ul ul, ol menu ul, ol dir ul, ol ol menu, ol ul menu, ol menu menu, ol dir menu, ol ol dir, ol ul dir, ol menu dir, ol dir dir, ul ol ul, ul ul ul, ul menu ul, ul dir ul, ul ol menu, ul ul menu, ul menu menu, ul dir menu, ul ol dir, ul ul dir, ul menu dir, ul dir dir, menu ol ul, menu ul ul, menu menu ul, menu dir ul, menu ol menu, menu ul menu, menu menu menu, menu dir menu, menu ol dir, menu ul dir, menu menu dir, menu dir dir, dir ol ul, dir ul ul, dir menu ul, dir dir ul, dir ol menu, dir ul menu, dir menu menu, dir dir menu, dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
  list-style-type: square;
}
.hidden
{
  display: none;
}
p
{
  line-height: 1.5em;
}
h1
{
  font-size: 1.75em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h2
{
  font-size: 1.5em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h3
{
  font-size: 1.25em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h4
{
  font-size: 1em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
html, body
{
  width: 100%;
  height: 100%;
}
body
{
  margin: 0;
  padding: 0;
  background-color: #fff;
  position: relative;
  font: 16px/24px NobileRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
}
a
{
  color: #1b61d6;
  text-decoration: none;
}
a:hover
{
  color: #e88f00;
  text-decoration: underline;
}
body h1, body h2, body h3, body h4, body h5, body h6
{
  font-family: NeutonRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
  font-weight: 400;
  color: #373839;
  font-style: normal;
}
#wrap
{
  min-height: 100%;
}
#header, #footer
{
  width: 100%;
  color: #fff;
  height: 40px;
  position: absolute;
  text-align: center;
  line-height: 40px;
  overflow: hidden;
  font-size: 12px;
  vertical-align: middle;
}
#header
{
  background: #000;
  top: 0;
  font-size: 14px;
}
#footer
{
  bottom: 0;
  background: #000 url(footerbg.png) repeat-x 0 top;
  position: relative;
  margin-top: -40px;
  clear: both;
}
.header, .footer
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.wrapper
{
  width: 100%;
}
#top, #top-small, #bottom
{
  width: 100%;
}
#top
{
  color: #000;
  height: 230px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#top-small
{
  color: #000;
  height: 60px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#bottom
{
  color: #222;
  background-color: #fff;
}
.top, .top-small, .middle, .bottom
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.top
{
  padding-top: 40px;
}
.top-small
{
  padding-top: 10px;
}
#middle
{
  width: 100%;
  height: 100px;
  background: url(middlebg.png) repeat-x;
  border-top: 2px solid #fff;
  border-bottom: 2px solid #b2b2b2;
}
.app-welcome
{
  margin-top: 25px;
}
.app-name
{
  color: #000;
  font-weight: 700;
}
.bottom
{
  padding-top: 50px;
}
#left
{
  width: 350px;
  float: left;
  padding-right: 25px;
}
#right
{
  width: 350px;
  float: right;
  padding-left: 25px;
}
.align-left
{
  text-align: left;
}
.align-right
{
  text-align: right;
}
.align-center
{
  text-align: center;
}
ul.links
{
  margin: 0;
  padding: 0;
}
ul.links li
{
  list-style-type: none;
  font-size: 14px;
}
form
{
  border-style: none;
}
fieldset
{
  border-style: none;
}
input
{
  color: #222;
  border: 1px solid #ccc;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 16px;
}
input[type=text], input[type=password]
{
  width: 205px;
}
input[type=submit]
{
  background-color: #ddd;
  font-weight: 700;
}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
body:before
{
  content: "";
  height: 100%;
  float: left;
  width: 0;
  margin-top: -32767px;
}
docs/tutorials/wiki/src/views/tutorial/static/pylons.css
@@ -1,65 +1,372 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td
{
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-size: 100%; /* 16px */
  vertical-align: baseline;
  background: transparent;
}
body
{
  line-height: 1;
}
ol, ul
{
  list-style: none;
}
blockquote, q
{
  quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after
{
  content: '';
  content: none;
}
:focus
{
  outline: 0;
}
ins
{
  text-decoration: none;
}
del
{
  text-decoration: line-through;
}
table
{
  border-collapse: collapse;
  border-spacing: 0;
}
sub
{
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}
sup
{
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}
ul, menu, dir
{
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  padding-left: 40px;
}
ol
{
  display: block;
  list-style-type: decimal-leading-zero;
  margin: 1em 0;
  padding-left: 40px;
}
li
{
  display: list-item;
}
ul ul, ul ol, ul dir, ul menu, ul dl, ol ul, ol ol, ol dir, ol menu, ol dl, dir ul, dir ol, dir dir, dir menu, dir dl, menu ul, menu ol, menu dir, menu menu, menu dl, dl ul, dl ol, dl dir, dl menu, dl dl
{
  margin-top: 0;
  margin-bottom: 0;
}
ol ul, ul ul, menu ul, dir ul, ol menu, ul menu, menu menu, dir menu, ol dir, ul dir, menu dir, dir dir
{
  list-style-type: circle;
}
ol ol ul, ol ul ul, ol menu ul, ol dir ul, ol ol menu, ol ul menu, ol menu menu, ol dir menu, ol ol dir, ol ul dir, ol menu dir, ol dir dir, ul ol ul, ul ul ul, ul menu ul, ul dir ul, ul ol menu, ul ul menu, ul menu menu, ul dir menu, ul ol dir, ul ul dir, ul menu dir, ul dir dir, menu ol ul, menu ul ul, menu menu ul, menu dir ul, menu ol menu, menu ul menu, menu menu menu, menu dir menu, menu ol dir, menu ul dir, menu menu dir, menu dir dir, dir ol ul, dir ul ul, dir menu ul, dir dir ul, dir ol menu, dir ul menu, dir menu menu, dir dir menu, dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
  list-style-type: square;
}
.hidden
{
  display: none;
}
p
{
  line-height: 1.5em;
}
h1
{
  font-size: 1.75em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h2
{
  font-size: 1.5em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h3
{
  font-size: 1.25em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h4
{
  font-size: 1em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
html, body
{
  width: 100%;
  height: 100%;
}
body
{
  margin: 0;
  padding: 0;
  background-color: #fff;
  position: relative;
  font: 16px/24px NobileRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
}
a
{
  color: #1b61d6;
  text-decoration: none;
}
a:hover
{
  color: #e88f00;
  text-decoration: underline;
}
body h1, body h2, body h3, body h4, body h5, body h6
{
  font-family: NeutonRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
  font-weight: 400;
  color: #373839;
  font-style: normal;
}
#wrap
{
  min-height: 100%;
}
#header, #footer
{
  width: 100%;
  color: #fff;
  height: 40px;
  position: absolute;
  text-align: center;
  line-height: 40px;
  overflow: hidden;
  font-size: 12px;
  vertical-align: middle;
}
#header
{
  background: #000;
  top: 0;
  font-size: 14px;
}
#footer
{
  bottom: 0;
  background: #000 url(footerbg.png) repeat-x 0 top;
  position: relative;
  margin-top: -40px;
  clear: both;
}
.header, .footer
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.wrapper
{
  width: 100%;
}
#top, #top-small, #bottom
{
  width: 100%;
}
#top
{
  color: #000;
  height: 230px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#top-small
{
  color: #000;
  height: 60px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#bottom
{
  color: #222;
  background-color: #fff;
}
.top, .top-small, .middle, .bottom
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.top
{
  padding-top: 40px;
}
.top-small
{
  padding-top: 10px;
}
#middle
{
  width: 100%;
  height: 100px;
  background: url(middlebg.png) repeat-x;
  border-top: 2px solid #fff;
  border-bottom: 2px solid #b2b2b2;
}
.app-welcome
{
  margin-top: 25px;
}
.app-name
{
  color: #000;
  font-weight: 700;
}
.bottom
{
  padding-top: 50px;
}
#left
{
  width: 350px;
  float: left;
  padding-right: 25px;
}
#right
{
  width: 350px;
  float: right;
  padding-left: 25px;
}
.align-left
{
  text-align: left;
}
.align-right
{
  text-align: right;
}
.align-center
{
  text-align: center;
}
ul.links
{
  margin: 0;
  padding: 0;
}
ul.links li
{
  list-style-type: none;
  font-size: 14px;
}
form
{
  border-style: none;
}
fieldset
{
  border-style: none;
}
input
{
  color: #222;
  border: 1px solid #ccc;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 16px;
}
input[type=text], input[type=password]
{
  width: 205px;
}
input[type=submit]
{
  background-color: #ddd;
  font-weight: 700;
}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
body:before
{
  content: "";
  height: 100%;
  float: left;
  width: 0;
  margin-top: -32767px;
}
docs/tutorials/wiki2/authorization.rst
@@ -112,7 +112,7 @@
the class we created above:
.. literalinclude:: src/authorization/tutorial/__init__.py
   :lines: 19-20
   :lines: 23-24
   :linenos:
   :emphasize-lines: 2
   :language: python
@@ -144,7 +144,7 @@
Now add those policies to the configuration:
.. literalinclude:: src/authorization/tutorial/__init__.py
   :lines: 16-22
   :lines: 20-26
   :linenos:
   :emphasize-lines: 1-3,6-7
   :language: python
@@ -206,7 +206,7 @@
routes:
.. literalinclude:: src/authorization/tutorial/__init__.py
   :lines: 25-26
   :lines: 29-30
   :linenos:
   :language: python
@@ -333,7 +333,7 @@
.. literalinclude:: src/authorization/tutorial/__init__.py
   :linenos:
   :emphasize-lines: 2-3,7,16-18,20-22,25-26
   :emphasize-lines: 2-3,7,23-24,20-26,29-30
   :language: python
(Only the highlighted lines need to be added.)
docs/tutorials/wiki2/basiclayout.rst
@@ -51,21 +51,33 @@
(something like ``sqlite://``):
   .. literalinclude:: src/basiclayout/tutorial/__init__.py
      :lines: 9
      :lines: 12
      :linenos:
      :language: py
``main`` then initializes our SQL database using SQLAlchemy, passing it the
``main`` then initializes our SQLAlchemy session object, passing it the
engine:
   .. literalinclude:: src/basiclayout/tutorial/__init__.py
      :lines: 10
      :lines: 13
      :language: py
``main`` subsequently initializes our SQLAlchemy declarative Base object,
assigning the engine we created to the ``bind`` attribute of it's
``metadata`` object.  This allows table definitions done imperatively
(instead of declaratively, via a class statement) to work.  We won't use any
such tables in our application, but if you add one later, long after you've
forgotten about this tutorial, you won't be left scratching your head when it
doesn't work.
   .. literalinclude:: src/basiclayout/tutorial/__init__.py
      :lines: 14
      :language: py
The next step of ``main`` is to construct a :term:`Configurator` object:
   .. literalinclude:: src/basiclayout/tutorial/__init__.py
      :lines: 11
      :lines: 15
      :language: py
``settings`` is passed to the Configurator as a keyword argument with the
@@ -78,7 +90,7 @@
two arguments: ``static`` (the name), and ``static`` (the path):
   .. literalinclude:: src/basiclayout/tutorial/__init__.py
      :lines: 12
      :lines: 16
      :language: py
This registers a static resource view which will match any URL that starts
@@ -96,7 +108,7 @@
used when the URL is ``/``:
   .. literalinclude:: src/basiclayout/tutorial/__init__.py
      :lines: 13
      :lines: 17
      :language: py
Since this route has a ``pattern`` equalling ``/`` it is the route that will
@@ -109,7 +121,7 @@
application URLs to be mapped to some code.
   .. literalinclude:: src/basiclayout/tutorial/__init__.py
      :lines: 14
      :lines: 18
      :language: py
Finally, ``main`` is finished configuring things, so it uses the
@@ -117,7 +129,7 @@
:term:`WSGI` application:
   .. literalinclude:: src/basiclayout/tutorial/__init__.py
      :lines: 15
      :lines: 19
      :language: py
View Declarations via ``views.py``
docs/tutorials/wiki2/definingviews.rst
@@ -342,7 +342,7 @@
.. literalinclude:: src/views/tutorial/__init__.py
   :linenos:
   :language: python
   :emphasize-lines: 13-16
   :emphasize-lines: 17-20
(The highlighted lines are the ones that need to be added or edited.)
docs/tutorials/wiki2/design.rst
@@ -115,7 +115,8 @@
|                      |  redirect to          |             |            |            |
|                      |  /PageName            |             |            |            |
+----------------------+-----------------------+-------------+------------+------------+
| /login               |  Display login form.  |  login      |  login.pt  |            |
| /login               |  Display login form,  |  login      |  login.pt  |            |
|                      |   Forbidden [3]_      |             |            |            |
|                      |                       |             |            |            |
|                      |  If the form was      |             |            |            |
|                      |  submitted,           |             |            |            |
docs/tutorials/wiki2/src/authorization/tutorial/__init__.py
@@ -6,13 +6,17 @@
from tutorial.security import groupfinder
from .models import DBSession
from .models import (
    DBSession,
    Base,
    )
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)
    Base.metadata.bind = engine
    authn_policy = AuthTktAuthenticationPolicy(
        'sosecret', callback=groupfinder)
    authz_policy = ACLAuthorizationPolicy()
docs/tutorials/wiki2/src/authorization/tutorial/static/pylons.css
@@ -1,65 +1,372 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td
{
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-size: 100%; /* 16px */
  vertical-align: baseline;
  background: transparent;
}
body
{
  line-height: 1;
}
ol, ul
{
  list-style: none;
}
blockquote, q
{
  quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after
{
  content: '';
  content: none;
}
:focus
{
  outline: 0;
}
ins
{
  text-decoration: none;
}
del
{
  text-decoration: line-through;
}
table
{
  border-collapse: collapse;
  border-spacing: 0;
}
sub
{
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}
sup
{
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}
ul, menu, dir
{
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  padding-left: 40px;
}
ol
{
  display: block;
  list-style-type: decimal-leading-zero;
  margin: 1em 0;
  padding-left: 40px;
}
li
{
  display: list-item;
}
ul ul, ul ol, ul dir, ul menu, ul dl, ol ul, ol ol, ol dir, ol menu, ol dl, dir ul, dir ol, dir dir, dir menu, dir dl, menu ul, menu ol, menu dir, menu menu, menu dl, dl ul, dl ol, dl dir, dl menu, dl dl
{
  margin-top: 0;
  margin-bottom: 0;
}
ol ul, ul ul, menu ul, dir ul, ol menu, ul menu, menu menu, dir menu, ol dir, ul dir, menu dir, dir dir
{
  list-style-type: circle;
}
ol ol ul, ol ul ul, ol menu ul, ol dir ul, ol ol menu, ol ul menu, ol menu menu, ol dir menu, ol ol dir, ol ul dir, ol menu dir, ol dir dir, ul ol ul, ul ul ul, ul menu ul, ul dir ul, ul ol menu, ul ul menu, ul menu menu, ul dir menu, ul ol dir, ul ul dir, ul menu dir, ul dir dir, menu ol ul, menu ul ul, menu menu ul, menu dir ul, menu ol menu, menu ul menu, menu menu menu, menu dir menu, menu ol dir, menu ul dir, menu menu dir, menu dir dir, dir ol ul, dir ul ul, dir menu ul, dir dir ul, dir ol menu, dir ul menu, dir menu menu, dir dir menu, dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
  list-style-type: square;
}
.hidden
{
  display: none;
}
p
{
  line-height: 1.5em;
}
h1
{
  font-size: 1.75em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h2
{
  font-size: 1.5em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h3
{
  font-size: 1.25em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h4
{
  font-size: 1em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
html, body
{
  width: 100%;
  height: 100%;
}
body
{
  margin: 0;
  padding: 0;
  background-color: #fff;
  position: relative;
  font: 16px/24px NobileRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
}
a
{
  color: #1b61d6;
  text-decoration: none;
}
a:hover
{
  color: #e88f00;
  text-decoration: underline;
}
body h1, body h2, body h3, body h4, body h5, body h6
{
  font-family: NeutonRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
  font-weight: 400;
  color: #373839;
  font-style: normal;
}
#wrap
{
  min-height: 100%;
}
#header, #footer
{
  width: 100%;
  color: #fff;
  height: 40px;
  position: absolute;
  text-align: center;
  line-height: 40px;
  overflow: hidden;
  font-size: 12px;
  vertical-align: middle;
}
#header
{
  background: #000;
  top: 0;
  font-size: 14px;
}
#footer
{
  bottom: 0;
  background: #000 url(footerbg.png) repeat-x 0 top;
  position: relative;
  margin-top: -40px;
  clear: both;
}
.header, .footer
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.wrapper
{
  width: 100%;
}
#top, #top-small, #bottom
{
  width: 100%;
}
#top
{
  color: #000;
  height: 230px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#top-small
{
  color: #000;
  height: 60px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#bottom
{
  color: #222;
  background-color: #fff;
}
.top, .top-small, .middle, .bottom
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.top
{
  padding-top: 40px;
}
.top-small
{
  padding-top: 10px;
}
#middle
{
  width: 100%;
  height: 100px;
  background: url(middlebg.png) repeat-x;
  border-top: 2px solid #fff;
  border-bottom: 2px solid #b2b2b2;
}
.app-welcome
{
  margin-top: 25px;
}
.app-name
{
  color: #000;
  font-weight: 700;
}
.bottom
{
  padding-top: 50px;
}
#left
{
  width: 350px;
  float: left;
  padding-right: 25px;
}
#right
{
  width: 350px;
  float: right;
  padding-left: 25px;
}
.align-left
{
  text-align: left;
}
.align-right
{
  text-align: right;
}
.align-center
{
  text-align: center;
}
ul.links
{
  margin: 0;
  padding: 0;
}
ul.links li
{
  list-style-type: none;
  font-size: 14px;
}
form
{
  border-style: none;
}
fieldset
{
  border-style: none;
}
input
{
  color: #222;
  border: 1px solid #ccc;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 16px;
}
input[type=text], input[type=password]
{
  width: 205px;
}
input[type=submit]
{
  background-color: #ddd;
  font-weight: 700;
}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
body:before
{
  content: "";
  height: 100%;
  float: left;
  width: 0;
  margin-top: -32767px;
}
docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py
@@ -1,13 +1,17 @@
from pyramid.config import Configurator
from sqlalchemy import engine_from_config
from .models import DBSession
from .models import (
    DBSession,
    Base,
    )
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)
    Base.metadata.bind = engine
    config = Configurator(settings=settings)
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.add_route('home', '/')
docs/tutorials/wiki2/src/basiclayout/tutorial/static/pylons.css
@@ -1,65 +1,372 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td
{
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-size: 100%; /* 16px */
  vertical-align: baseline;
  background: transparent;
}
body
{
  line-height: 1;
}
ol, ul
{
  list-style: none;
}
blockquote, q
{
  quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after
{
  content: '';
  content: none;
}
:focus
{
  outline: 0;
}
ins
{
  text-decoration: none;
}
del
{
  text-decoration: line-through;
}
table
{
  border-collapse: collapse;
  border-spacing: 0;
}
sub
{
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}
sup
{
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}
ul, menu, dir
{
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  padding-left: 40px;
}
ol
{
  display: block;
  list-style-type: decimal-leading-zero;
  margin: 1em 0;
  padding-left: 40px;
}
li
{
  display: list-item;
}
ul ul, ul ol, ul dir, ul menu, ul dl, ol ul, ol ol, ol dir, ol menu, ol dl, dir ul, dir ol, dir dir, dir menu, dir dl, menu ul, menu ol, menu dir, menu menu, menu dl, dl ul, dl ol, dl dir, dl menu, dl dl
{
  margin-top: 0;
  margin-bottom: 0;
}
ol ul, ul ul, menu ul, dir ul, ol menu, ul menu, menu menu, dir menu, ol dir, ul dir, menu dir, dir dir
{
  list-style-type: circle;
}
ol ol ul, ol ul ul, ol menu ul, ol dir ul, ol ol menu, ol ul menu, ol menu menu, ol dir menu, ol ol dir, ol ul dir, ol menu dir, ol dir dir, ul ol ul, ul ul ul, ul menu ul, ul dir ul, ul ol menu, ul ul menu, ul menu menu, ul dir menu, ul ol dir, ul ul dir, ul menu dir, ul dir dir, menu ol ul, menu ul ul, menu menu ul, menu dir ul, menu ol menu, menu ul menu, menu menu menu, menu dir menu, menu ol dir, menu ul dir, menu menu dir, menu dir dir, dir ol ul, dir ul ul, dir menu ul, dir dir ul, dir ol menu, dir ul menu, dir menu menu, dir dir menu, dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
  list-style-type: square;
}
.hidden
{
  display: none;
}
p
{
  line-height: 1.5em;
}
h1
{
  font-size: 1.75em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h2
{
  font-size: 1.5em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h3
{
  font-size: 1.25em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h4
{
  font-size: 1em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
html, body
{
  width: 100%;
  height: 100%;
}
body
{
  margin: 0;
  padding: 0;
  background-color: #fff;
  position: relative;
  font: 16px/24px NobileRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
}
a
{
  color: #1b61d6;
  text-decoration: none;
}
a:hover
{
  color: #e88f00;
  text-decoration: underline;
}
body h1, body h2, body h3, body h4, body h5, body h6
{
  font-family: NeutonRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
  font-weight: 400;
  color: #373839;
  font-style: normal;
}
#wrap
{
  min-height: 100%;
}
#header, #footer
{
  width: 100%;
  color: #fff;
  height: 40px;
  position: absolute;
  text-align: center;
  line-height: 40px;
  overflow: hidden;
  font-size: 12px;
  vertical-align: middle;
}
#header
{
  background: #000;
  top: 0;
  font-size: 14px;
}
#footer
{
  bottom: 0;
  background: #000 url(footerbg.png) repeat-x 0 top;
  position: relative;
  margin-top: -40px;
  clear: both;
}
.header, .footer
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.wrapper
{
  width: 100%;
}
#top, #top-small, #bottom
{
  width: 100%;
}
#top
{
  color: #000;
  height: 230px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#top-small
{
  color: #000;
  height: 60px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#bottom
{
  color: #222;
  background-color: #fff;
}
.top, .top-small, .middle, .bottom
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.top
{
  padding-top: 40px;
}
.top-small
{
  padding-top: 10px;
}
#middle
{
  width: 100%;
  height: 100px;
  background: url(middlebg.png) repeat-x;
  border-top: 2px solid #fff;
  border-bottom: 2px solid #b2b2b2;
}
.app-welcome
{
  margin-top: 25px;
}
.app-name
{
  color: #000;
  font-weight: 700;
}
.bottom
{
  padding-top: 50px;
}
#left
{
  width: 350px;
  float: left;
  padding-right: 25px;
}
#right
{
  width: 350px;
  float: right;
  padding-left: 25px;
}
.align-left
{
  text-align: left;
}
.align-right
{
  text-align: right;
}
.align-center
{
  text-align: center;
}
ul.links
{
  margin: 0;
  padding: 0;
}
ul.links li
{
  list-style-type: none;
  font-size: 14px;
}
form
{
  border-style: none;
}
fieldset
{
  border-style: none;
}
input
{
  color: #222;
  border: 1px solid #ccc;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 16px;
}
input[type=text], input[type=password]
{
  width: 205px;
}
input[type=submit]
{
  background-color: #ddd;
  font-weight: 700;
}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
body:before
{
  content: "";
  height: 100%;
  float: left;
  width: 0;
  margin-top: -32767px;
}
docs/tutorials/wiki2/src/models/tutorial/__init__.py
@@ -1,13 +1,17 @@
from pyramid.config import Configurator
from sqlalchemy import engine_from_config
from .models import DBSession
from .models import (
    DBSession,
    Base,
    )
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)
    Base.metadata.bind = engine
    config = Configurator(settings=settings)
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.add_route('home', '/')
docs/tutorials/wiki2/src/models/tutorial/static/pylons.css
@@ -1,65 +1,372 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td
{
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-size: 100%; /* 16px */
  vertical-align: baseline;
  background: transparent;
}
body
{
  line-height: 1;
}
ol, ul
{
  list-style: none;
}
blockquote, q
{
  quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after
{
  content: '';
  content: none;
}
:focus
{
  outline: 0;
}
ins
{
  text-decoration: none;
}
del
{
  text-decoration: line-through;
}
table
{
  border-collapse: collapse;
  border-spacing: 0;
}
sub
{
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}
sup
{
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}
ul, menu, dir
{
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  padding-left: 40px;
}
ol
{
  display: block;
  list-style-type: decimal-leading-zero;
  margin: 1em 0;
  padding-left: 40px;
}
li
{
  display: list-item;
}
ul ul, ul ol, ul dir, ul menu, ul dl, ol ul, ol ol, ol dir, ol menu, ol dl, dir ul, dir ol, dir dir, dir menu, dir dl, menu ul, menu ol, menu dir, menu menu, menu dl, dl ul, dl ol, dl dir, dl menu, dl dl
{
  margin-top: 0;
  margin-bottom: 0;
}
ol ul, ul ul, menu ul, dir ul, ol menu, ul menu, menu menu, dir menu, ol dir, ul dir, menu dir, dir dir
{
  list-style-type: circle;
}
ol ol ul, ol ul ul, ol menu ul, ol dir ul, ol ol menu, ol ul menu, ol menu menu, ol dir menu, ol ol dir, ol ul dir, ol menu dir, ol dir dir, ul ol ul, ul ul ul, ul menu ul, ul dir ul, ul ol menu, ul ul menu, ul menu menu, ul dir menu, ul ol dir, ul ul dir, ul menu dir, ul dir dir, menu ol ul, menu ul ul, menu menu ul, menu dir ul, menu ol menu, menu ul menu, menu menu menu, menu dir menu, menu ol dir, menu ul dir, menu menu dir, menu dir dir, dir ol ul, dir ul ul, dir menu ul, dir dir ul, dir ol menu, dir ul menu, dir menu menu, dir dir menu, dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
  list-style-type: square;
}
.hidden
{
  display: none;
}
p
{
  line-height: 1.5em;
}
h1
{
  font-size: 1.75em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h2
{
  font-size: 1.5em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h3
{
  font-size: 1.25em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h4
{
  font-size: 1em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
html, body
{
  width: 100%;
  height: 100%;
}
body
{
  margin: 0;
  padding: 0;
  background-color: #fff;
  position: relative;
  font: 16px/24px NobileRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
}
a
{
  color: #1b61d6;
  text-decoration: none;
}
a:hover
{
  color: #e88f00;
  text-decoration: underline;
}
body h1, body h2, body h3, body h4, body h5, body h6
{
  font-family: NeutonRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
  font-weight: 400;
  color: #373839;
  font-style: normal;
}
#wrap
{
  min-height: 100%;
}
#header, #footer
{
  width: 100%;
  color: #fff;
  height: 40px;
  position: absolute;
  text-align: center;
  line-height: 40px;
  overflow: hidden;
  font-size: 12px;
  vertical-align: middle;
}
#header
{
  background: #000;
  top: 0;
  font-size: 14px;
}
#footer
{
  bottom: 0;
  background: #000 url(footerbg.png) repeat-x 0 top;
  position: relative;
  margin-top: -40px;
  clear: both;
}
.header, .footer
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.wrapper
{
  width: 100%;
}
#top, #top-small, #bottom
{
  width: 100%;
}
#top
{
  color: #000;
  height: 230px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#top-small
{
  color: #000;
  height: 60px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#bottom
{
  color: #222;
  background-color: #fff;
}
.top, .top-small, .middle, .bottom
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.top
{
  padding-top: 40px;
}
.top-small
{
  padding-top: 10px;
}
#middle
{
  width: 100%;
  height: 100px;
  background: url(middlebg.png) repeat-x;
  border-top: 2px solid #fff;
  border-bottom: 2px solid #b2b2b2;
}
.app-welcome
{
  margin-top: 25px;
}
.app-name
{
  color: #000;
  font-weight: 700;
}
.bottom
{
  padding-top: 50px;
}
#left
{
  width: 350px;
  float: left;
  padding-right: 25px;
}
#right
{
  width: 350px;
  float: right;
  padding-left: 25px;
}
.align-left
{
  text-align: left;
}
.align-right
{
  text-align: right;
}
.align-center
{
  text-align: center;
}
ul.links
{
  margin: 0;
  padding: 0;
}
ul.links li
{
  list-style-type: none;
  font-size: 14px;
}
form
{
  border-style: none;
}
fieldset
{
  border-style: none;
}
input
{
  color: #222;
  border: 1px solid #ccc;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 16px;
}
input[type=text], input[type=password]
{
  width: 205px;
}
input[type=submit]
{
  background-color: #ddd;
  font-weight: 700;
}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
body:before
{
  content: "";
  height: 100%;
  float: left;
  width: 0;
  margin-top: -32767px;
}
docs/tutorials/wiki2/src/tests/tutorial/__init__.py
@@ -6,13 +6,17 @@
from tutorial.security import groupfinder
from .models import DBSession
from .models import (
    DBSession,
    Base,
    )
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)
    Base.metadata.bind = engine
    authn_policy = AuthTktAuthenticationPolicy(
        'sosecret', callback=groupfinder)
    authz_policy = ACLAuthorizationPolicy()
docs/tutorials/wiki2/src/tests/tutorial/static/pylons.css
@@ -1,65 +1,372 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td
{
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-size: 100%; /* 16px */
  vertical-align: baseline;
  background: transparent;
}
body
{
  line-height: 1;
}
ol, ul
{
  list-style: none;
}
blockquote, q
{
  quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after
{
  content: '';
  content: none;
}
:focus
{
  outline: 0;
}
ins
{
  text-decoration: none;
}
del
{
  text-decoration: line-through;
}
table
{
  border-collapse: collapse;
  border-spacing: 0;
}
sub
{
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}
sup
{
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}
ul, menu, dir
{
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  padding-left: 40px;
}
ol
{
  display: block;
  list-style-type: decimal-leading-zero;
  margin: 1em 0;
  padding-left: 40px;
}
li
{
  display: list-item;
}
ul ul, ul ol, ul dir, ul menu, ul dl, ol ul, ol ol, ol dir, ol menu, ol dl, dir ul, dir ol, dir dir, dir menu, dir dl, menu ul, menu ol, menu dir, menu menu, menu dl, dl ul, dl ol, dl dir, dl menu, dl dl
{
  margin-top: 0;
  margin-bottom: 0;
}
ol ul, ul ul, menu ul, dir ul, ol menu, ul menu, menu menu, dir menu, ol dir, ul dir, menu dir, dir dir
{
  list-style-type: circle;
}
ol ol ul, ol ul ul, ol menu ul, ol dir ul, ol ol menu, ol ul menu, ol menu menu, ol dir menu, ol ol dir, ol ul dir, ol menu dir, ol dir dir, ul ol ul, ul ul ul, ul menu ul, ul dir ul, ul ol menu, ul ul menu, ul menu menu, ul dir menu, ul ol dir, ul ul dir, ul menu dir, ul dir dir, menu ol ul, menu ul ul, menu menu ul, menu dir ul, menu ol menu, menu ul menu, menu menu menu, menu dir menu, menu ol dir, menu ul dir, menu menu dir, menu dir dir, dir ol ul, dir ul ul, dir menu ul, dir dir ul, dir ol menu, dir ul menu, dir menu menu, dir dir menu, dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
  list-style-type: square;
}
.hidden
{
  display: none;
}
p
{
  line-height: 1.5em;
}
h1
{
  font-size: 1.75em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h2
{
  font-size: 1.5em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h3
{
  font-size: 1.25em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h4
{
  font-size: 1em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
html, body
{
  width: 100%;
  height: 100%;
}
body
{
  margin: 0;
  padding: 0;
  background-color: #fff;
  position: relative;
  font: 16px/24px NobileRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
}
a
{
  color: #1b61d6;
  text-decoration: none;
}
a:hover
{
  color: #e88f00;
  text-decoration: underline;
}
body h1, body h2, body h3, body h4, body h5, body h6
{
  font-family: NeutonRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
  font-weight: 400;
  color: #373839;
  font-style: normal;
}
#wrap
{
  min-height: 100%;
}
#header, #footer
{
  width: 100%;
  color: #fff;
  height: 40px;
  position: absolute;
  text-align: center;
  line-height: 40px;
  overflow: hidden;
  font-size: 12px;
  vertical-align: middle;
}
#header
{
  background: #000;
  top: 0;
  font-size: 14px;
}
#footer
{
  bottom: 0;
  background: #000 url(footerbg.png) repeat-x 0 top;
  position: relative;
  margin-top: -40px;
  clear: both;
}
.header, .footer
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.wrapper
{
  width: 100%;
}
#top, #top-small, #bottom
{
  width: 100%;
}
#top
{
  color: #000;
  height: 230px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#top-small
{
  color: #000;
  height: 60px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#bottom
{
  color: #222;
  background-color: #fff;
}
.top, .top-small, .middle, .bottom
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.top
{
  padding-top: 40px;
}
.top-small
{
  padding-top: 10px;
}
#middle
{
  width: 100%;
  height: 100px;
  background: url(middlebg.png) repeat-x;
  border-top: 2px solid #fff;
  border-bottom: 2px solid #b2b2b2;
}
.app-welcome
{
  margin-top: 25px;
}
.app-name
{
  color: #000;
  font-weight: 700;
}
.bottom
{
  padding-top: 50px;
}
#left
{
  width: 350px;
  float: left;
  padding-right: 25px;
}
#right
{
  width: 350px;
  float: right;
  padding-left: 25px;
}
.align-left
{
  text-align: left;
}
.align-right
{
  text-align: right;
}
.align-center
{
  text-align: center;
}
ul.links
{
  margin: 0;
  padding: 0;
}
ul.links li
{
  list-style-type: none;
  font-size: 14px;
}
form
{
  border-style: none;
}
fieldset
{
  border-style: none;
}
input
{
  color: #222;
  border: 1px solid #ccc;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 16px;
}
input[type=text], input[type=password]
{
  width: 205px;
}
input[type=submit]
{
  background-color: #ddd;
  font-weight: 700;
}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
body:before
{
  content: "";
  height: 100%;
  float: left;
  width: 0;
  margin-top: -32767px;
}
docs/tutorials/wiki2/src/views/tutorial/__init__.py
@@ -1,13 +1,17 @@
from pyramid.config import Configurator
from sqlalchemy import engine_from_config
from .models import DBSession
from .models import (
    DBSession,
    Base,
    )
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)
    Base.metadata.bind = engine
    config = Configurator(settings=settings)
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.add_route('view_wiki', '/')
docs/tutorials/wiki2/src/views/tutorial/static/pylons.css
@@ -1,65 +1,372 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td
{
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-size: 100%; /* 16px */
  vertical-align: baseline;
  background: transparent;
}
body
{
  line-height: 1;
}
ol, ul
{
  list-style: none;
}
blockquote, q
{
  quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after
{
  content: '';
  content: none;
}
:focus
{
  outline: 0;
}
ins
{
  text-decoration: none;
}
del
{
  text-decoration: line-through;
}
table
{
  border-collapse: collapse;
  border-spacing: 0;
}
sub
{
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}
sup
{
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}
ul, menu, dir
{
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  padding-left: 40px;
}
ol
{
  display: block;
  list-style-type: decimal-leading-zero;
  margin: 1em 0;
  padding-left: 40px;
}
li
{
  display: list-item;
}
ul ul, ul ol, ul dir, ul menu, ul dl, ol ul, ol ol, ol dir, ol menu, ol dl, dir ul, dir ol, dir dir, dir menu, dir dl, menu ul, menu ol, menu dir, menu menu, menu dl, dl ul, dl ol, dl dir, dl menu, dl dl
{
  margin-top: 0;
  margin-bottom: 0;
}
ol ul, ul ul, menu ul, dir ul, ol menu, ul menu, menu menu, dir menu, ol dir, ul dir, menu dir, dir dir
{
  list-style-type: circle;
}
ol ol ul, ol ul ul, ol menu ul, ol dir ul, ol ol menu, ol ul menu, ol menu menu, ol dir menu, ol ol dir, ol ul dir, ol menu dir, ol dir dir, ul ol ul, ul ul ul, ul menu ul, ul dir ul, ul ol menu, ul ul menu, ul menu menu, ul dir menu, ul ol dir, ul ul dir, ul menu dir, ul dir dir, menu ol ul, menu ul ul, menu menu ul, menu dir ul, menu ol menu, menu ul menu, menu menu menu, menu dir menu, menu ol dir, menu ul dir, menu menu dir, menu dir dir, dir ol ul, dir ul ul, dir menu ul, dir dir ul, dir ol menu, dir ul menu, dir menu menu, dir dir menu, dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
  list-style-type: square;
}
.hidden
{
  display: none;
}
p
{
  line-height: 1.5em;
}
h1
{
  font-size: 1.75em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h2
{
  font-size: 1.5em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h3
{
  font-size: 1.25em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h4
{
  font-size: 1em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
html, body
{
  width: 100%;
  height: 100%;
}
body
{
  margin: 0;
  padding: 0;
  background-color: #fff;
  position: relative;
  font: 16px/24px NobileRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
}
a
{
  color: #1b61d6;
  text-decoration: none;
}
a:hover
{
  color: #e88f00;
  text-decoration: underline;
}
body h1, body h2, body h3, body h4, body h5, body h6
{
  font-family: NeutonRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
  font-weight: 400;
  color: #373839;
  font-style: normal;
}
#wrap
{
  min-height: 100%;
}
#header, #footer
{
  width: 100%;
  color: #fff;
  height: 40px;
  position: absolute;
  text-align: center;
  line-height: 40px;
  overflow: hidden;
  font-size: 12px;
  vertical-align: middle;
}
#header
{
  background: #000;
  top: 0;
  font-size: 14px;
}
#footer
{
  bottom: 0;
  background: #000 url(footerbg.png) repeat-x 0 top;
  position: relative;
  margin-top: -40px;
  clear: both;
}
.header, .footer
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.wrapper
{
  width: 100%;
}
#top, #top-small, #bottom
{
  width: 100%;
}
#top
{
  color: #000;
  height: 230px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#top-small
{
  color: #000;
  height: 60px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#bottom
{
  color: #222;
  background-color: #fff;
}
.top, .top-small, .middle, .bottom
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.top
{
  padding-top: 40px;
}
.top-small
{
  padding-top: 10px;
}
#middle
{
  width: 100%;
  height: 100px;
  background: url(middlebg.png) repeat-x;
  border-top: 2px solid #fff;
  border-bottom: 2px solid #b2b2b2;
}
.app-welcome
{
  margin-top: 25px;
}
.app-name
{
  color: #000;
  font-weight: 700;
}
.bottom
{
  padding-top: 50px;
}
#left
{
  width: 350px;
  float: left;
  padding-right: 25px;
}
#right
{
  width: 350px;
  float: right;
  padding-left: 25px;
}
.align-left
{
  text-align: left;
}
.align-right
{
  text-align: right;
}
.align-center
{
  text-align: center;
}
ul.links
{
  margin: 0;
  padding: 0;
}
ul.links li
{
  list-style-type: none;
  font-size: 14px;
}
form
{
  border-style: none;
}
fieldset
{
  border-style: none;
}
input
{
  color: #222;
  border: 1px solid #ccc;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 16px;
}
input[type=text], input[type=password]
{
  width: 205px;
}
input[type=submit]
{
  background-color: #ddd;
  font-weight: 700;
}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
body:before
{
  content: "";
  height: 100%;
  float: left;
  width: 0;
  margin-top: -32767px;
}
docs/whatsnew-1.4.rst
New file
@@ -0,0 +1,279 @@
What's New In Pyramid 1.4
=========================
This article explains the new features in :app:`Pyramid` version 1.4 as
compared to its predecessor, :app:`Pyramid` 1.3.  It also documents backwards
incompatibilities between the two versions and deprecations added to
:app:`Pyramid` 1.4, as well as software dependency changes and notable
documentation additions.
Major Feature Additions
-----------------------
The major feature additions in Pyramid 1.4 follow.
Third-Party Predicates
~~~~~~~~~~~~~~~~~~~~~~~
- Third-party custom view, route, and subscriber predicates can now be added
  for use by view authors via
  :meth:`pyramid.config.Configurator.add_view_predicate`,
  :meth:`pyramid.config.Configurator.add_route_predicate` and
  :meth:`pyramid.config.Configurator.add_subscriber_predicate`.  So, for
  example, doing this::
     config.add_view_predicate('abc', my.package.ABCPredicate)
  Might allow a view author to do this in an application that configured that
  predicate::
     @view_config(abc=1)
  Similar features exist for :meth:`pyramid.config.Configurator.add_route`,
  and :meth:`pyramid.config.Configurator.add_subscriber`.  See
  :ref:`registering_thirdparty_predicates` for more information.
Easy Custom JSON Serialization
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Views can now return custom objects which will be serialized to JSON by a
  JSON renderer by defining a ``__json__`` method on the object's class. This
  method should return values natively serializable by ``json.dumps`` (such
  as ints, lists, dictionaries, strings, and so forth).  See
  :ref:`json_serializing_custom_objects` for more information.  The JSON
  renderer now also allows for the definition of custom type adapters to
  convert unknown objects to JSON serializations, in case you can't add a
  ``__json__`` method to returned objects.
Partial Mako and Chameleon Template Renderings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- The Mako renderer now supports using a def name in an asset spec.  When the
  def name is present in the asset spec, the system will render the template
  named def within the template instead of rendering the entire template. An
  example asset spec which names a def is
  ``package:path/to/template#defname.mako``. This will render the def named
  ``defname`` inside the ``template.mako`` template instead of rendering the
  entire template.  The old way of returning a tuple in the form
  ``('defname', {})`` from the view is supported for backward compatibility.
- The Chameleon ZPT renderer now supports using a macro name in an asset
  spec.  When the macro name is present in the asset spec, the system will
  render the macro listed as a ``define-macro`` and return the result instead
  of rendering the entire template.  An example asset spec:
  ``package:path/to/template#macroname.pt``.  This will render the macro
  defined as ``macroname`` within the ``template.pt`` template instead of the
  entire templae.
Subrequest Support
~~~~~~~~~~~~~~~~~~
- Developers may invoke a subrequest by using the
  :meth:`pyramid.request.Request.invoke_subrequest` API.  This allows a
  developer to obtain a response from one view callable by issuing a subrequest
  from within a different view callable.  See :ref:`subrequest_chapter` for
  more information.
Minor Feature Additions
-----------------------
- :meth:`pyramid.config.Configurator.add_directive` now accepts arbitrary
  callables like partials or objects implementing ``__call__`` which dont
  have ``__name__`` and ``__doc__`` attributes.  See
  https://github.com/Pylons/pyramid/issues/621 and
  https://github.com/Pylons/pyramid/pull/647.
- As of this release, the ``request_method`` view/route predicate, when used,
  will also imply that ``HEAD`` is implied when you use ``GET``.  For
  example, using ``@view_config(request_method='GET')`` is equivalent to
  using ``@view_config(request_method=('GET', 'HEAD'))``.  Using
  ``@view_config(request_method=('GET', 'POST')`` is equivalent to using
  ``@view_config(request_method=('GET', 'HEAD', 'POST')``.  This is because
  HEAD is a variant of GET that omits the body, and WebOb has special support
  to return an empty body when a HEAD is used.
- :meth:`pyramid.config.Configurator.add_request_method` has been introduced
  to support extending request objects with arbitrary callables. This method
  expands on the now documentation-deprecated
  :meth:`pyramid.config.Configurator.set_request_property` by supporting
  methods as well as properties. This method also causes less code to be
  executed at request construction time than
  :meth:`~pyramid.config.Configurator.set_request_property`.
- The static view machinery now raises rather than returns
  :class:`pyramid.httpexceptions.HTTPNotFound` and
  :class:`pyramid.httpexceptions.HTTPMovedPermanently` exceptions, so these can
  be caught by the notfound view (and other exception views).
- When there is a predicate mismatch exception (seen when no view matches for
  a given request due to predicates not working), the exception now contains
  a textual description of the predicate which didn't match.
- An :meth:`pyramid.config.Configurator.add_permission` directive method was
  added to the Configurator.  This directive registers a free-standing
  permission introspectable into the Pyramid introspection system.
  Frameworks built atop Pyramid can thus use the the ``permissions``
  introspectable category data to build a comprehensive list of permissions
  supported by a running system.  Before this method was added, permissions
  were already registered in this introspectable category as a side effect of
  naming them in an :meth:`pyramid.config.Configurator.add_view` call, this
  method just makes it possible to arrange for a permission to be put into
  the ``permissions`` introspectable category without naming it along with an
  associated view.  Here's an example of usage of ``add_permission``::
      config = Configurator()
      config.add_permission('view')
- The :func:`pyramid.session.UnencryptedCookieSessionFactoryConfig` function
  now accepts ``signed_serialize`` and ``signed_deserialize`` hooks which may
  be used to influence how the sessions are marshalled (by default this is
  done with HMAC+pickle).
- :class:`pyramid.testing.DummyRequest` now supports methods supplied by the
  ``pyramid.util.InstancePropertyMixin`` class such as ``set_property``.
- Request properties and methods added via
  :meth:`pyramid.config.Configurator.add_request_method` or
  :meth:`pyramid.config.Configurator.set_request_property` are now available to
  tweens.
- Request properties and methods added via
  :meth:`pyramid.config.Configurator.add_request_method` or
  :meth:`pyramid.config.Configurator.set_request_property` are now available
  in the request object returned from :func:`pyramid.paster.bootstrap`.
- ``request.context`` of environment request during
  :func:`pyramid.paster.bootstrap` is now the root object if a context isn't
  already set on a provided request.
- :class:`pyramid.decorator.reify`  is now an API, and was added to
  the API documentation.
- Added the :func:`pyramid.testing.testConfig` context manager, which can be
  used to generate a configurator in a test, e.g. ``with
  testing.testConfig(...):``.
- A new :func:`pyramid.session.check_csrf_token` convenience API function was
  added.
- A ``check_csrf`` view predicate was added.  For example, you can now do
  ``config.add_view(someview, check_csrf=True)``.  When the predicate is
  checked, if the ``csrf_token`` value in ``request.params`` matches the csrf
  token in the request's session, the view will be permitted to execute.
  Otherwise, it will not be permitted to execute.
- Add ``Base.metadata.bind = engine`` to ``alchemy`` scaffold, so that tables
  defined imperatively will work.
Backwards Incompatibilities
---------------------------
- The Pyramid router no longer adds the values ``bfg.routes.route`` or
  ``bfg.routes.matchdict`` to the request's WSGI environment dictionary.
  These values were docs-deprecated in ``repoze.bfg`` 1.0 (effectively seven
  minor releases ago).  If your code depended on these values, use
  request.matched_route and request.matchdict instead.
- It is no longer possible to pass an environ dictionary directly to
  ``pyramid.traversal.ResourceTreeTraverser.__call__`` (aka
  ``ModelGraphTraverser.__call__``).  Instead, you must pass a request
  object.  Passing an environment instead of a request has generated a
  deprecation warning since Pyramid 1.1.
- Pyramid will no longer work properly if you use the
  ``webob.request.LegacyRequest`` as a request factory.  Instances of the
  LegacyRequest class have a ``request.path_info`` which return a string.
  This Pyramid release assumes that ``request.path_info`` will
  unconditionally be Unicode.
- The functions from ``pyramid.chameleon_zpt`` and ``pyramid.chameleon_text``
  named ``get_renderer``, ``get_template``, ``render_template``, and
  ``render_template_to_response`` have been removed.  These have issued a
  deprecation warning upon import since Pyramid 1.0.  Use
  :func:`pyramid.renderers.get_renderer`,
  ``pyramid.renderers.get_renderer().implementation()``,
  :func:`pyramid.renderers.render` or
  :func:`pyramid.renderers.render_to_response` respectively instead of these
  functions.
- The ``pyramid.configuration`` module was removed.  It had been deprecated
  since Pyramid 1.0 and printed a deprecation warning upon its use.  Use
  :mod:`pyramid.config` instead.
- The ``pyramid.paster.PyramidTemplate`` API was removed.  It had been
  deprecated since Pyramid 1.1 and issued a warning on import.  If your code
  depended on this, adjust your code to import
  :class:`pyramid.scaffolds.PyramidTemplate` instead.
- The ``pyramid.settings.get_settings()`` API was removed.  It had been
  printing a deprecation warning since Pyramid 1.0.  If your code depended on
  this API, use ``pyramid.threadlocal.get_current_registry().settings``
  instead or use the ``settings`` attribute of the registry available from
  the request (``request.registry.settings``).
- These APIs from the ``pyramid.testing`` module were removed.  They have
  been printing deprecation warnings since Pyramid 1.0:
  * ``registerDummySecurityPolicy``, use
    :meth:`pyramid.config.Configurator.testing_securitypolicy` instead.
  * ``registerResources`` (aka ``registerModels``), use
    :meth:`pyramid.config.Configurator.testing_resources` instead.
  * ``registerEventListener``, use
    :meth:`pyramid.config.Configurator.testing_add_subscriber` instead.
  * ``registerTemplateRenderer`` (aka `registerDummyRenderer``), use
    :meth:`pyramid.config.Configurator.testing_add_template` instead.
  * ``registerView``, use :meth:`pyramid.config.Configurator.add_view` instead.
  * ``registerUtility``, use
    :meth:`pyramid.config.Configurator.registry.registerUtility` instead.
  * ``registerAdapter``, use
    :meth:`pyramid.config.Configurator.registry.registerAdapter` instead.
  * ``registerSubscriber``, use
    :meth:`pyramid.config.Configurator.add_subscriber` instead.
  * ``registerRoute``, use
    :meth:`pyramid.config.Configurator.add_route` instead.
  * ``registerSettings``, use
    :meth:`pyramid.config.Configurator.add_settings` instead.
- In Pyramid 1.3 and previous, the ``__call__`` method of a Response object
  returned by a view was invoked before any finished callbacks were executed.
  As of this release, the ``__call__`` method of a Response object is invoked
  *after* finished callbacks are executed.  This is in support of the
  :meth:`pyramid.request.Request.invoke_subrequest` feature.
Deprecations
------------
- The :meth:`pyramid.config.Configurator.set_request_property` directive has
  been documentation-deprecated.  The method remains usable but the more
  featureful :meth:`pyramid.config.Configurator.add_request_method` should be
  used in its place (it has all of the same capabilities but can also extend
  the request object with methods).
Documentation Enhancements
--------------------------
- Added an :ref:`upgrading_chapter` chapter to the narrative documentation.
  It describes how to cope with deprecations and removals of Pyramid APIs and
  how to show Pyramid-generated deprecation warnings while running tests and
  while running a server.
- Added a :ref:`subrequest_chapter` chapter to the narrative documentation.
- Many cleanups and improvements to narrative and API docs.
Dependency Changes
------------------
- Pyramid now requires WebOb 1.2b3+ (the prior Pyramid release only relied on
  1.2dev+).  This is to ensure that we obtain a version of WebOb that returns
  ``request.path_info`` as text.
pyramid/chameleon_text.py
@@ -1,19 +1,6 @@
import sys
from zope.interface import implementer
from pyramid.compat import reraise
try:
    from chameleon.zpt.template import PageTextTemplateFile
    # prevent pyflakes complaining about a redefinition below
    PageTextTemplateFile
except ImportError: # pragma: no cover
    exc_class, exc, tb = sys.exc_info()
    # Chameleon doesn't work on non-CPython platforms
    class PageTextTemplateFile(object):
        def __init__(self, *arg, **kw):
            reraise(ImportError, exc, tb)
from chameleon.zpt.template import PageTextTemplateFile
from pyramid.interfaces import ITemplateRenderer
@@ -33,9 +20,6 @@
    @reify # avoid looking up reload_templates before manager pushed
    def template(self):
        if sys.platform.startswith('java'): # pragma: no cover
            raise RuntimeError(
                'Chameleon templates are not compatible with Jython')
        return PageTextTemplateFile(self.path,
                                    auto_reload=self.lookup.auto_reload,
                                    debug=self.lookup.debug,
pyramid/chameleon_zpt.py
@@ -1,21 +1,8 @@
import sys
from zope.interface import implementer
from pyramid.compat import reraise
try:
    from chameleon.zpt.template import PageTemplateFile
    PageTemplateFile # prevent pyflakes complaining about a redefinition below
except ImportError: # pragma: no cover
    exc_class, exc, tb = sys.exc_info()
    # Chameleon doesn't work on non-CPython platforms
    class PageTemplateFile(object):
        def __init__(self, *arg, **kw):
            reraise(ImportError, exc, tb)
from chameleon.zpt.template import PageTemplateFile
from pyramid.interfaces import ITemplateRenderer
from pyramid.decorator import reify
from pyramid import renderers
@@ -31,9 +18,6 @@
    @reify # avoid looking up reload_templates before manager pushed
    def template(self):
        if sys.platform.startswith('java'): # pragma: no cover
            raise RuntimeError(
                'Chameleon templates are not compatible with Jython')
        tf = PageTemplateFile(self.path,
                              auto_reload=self.lookup.auto_reload,
                              debug=self.lookup.debug,
pyramid/config/factories.py
@@ -1,11 +1,9 @@
from zope.interface import implementer
from pyramid.compat import iteritems_
from pyramid.config.util import action_method
from pyramid.interfaces import (
    IDefaultRootFactory,
    INewRequest,
    IRequestFactory,
    IRequestExtensions,
    IRootFactory,
pyramid/config/predicates.py
@@ -13,6 +13,8 @@
from pyramid.util import object_description
from pyramid.session import check_csrf_token
from .util import as_sorted_tuple
class XHRPredicate(object):
@@ -226,3 +228,24 @@
        # injects ``traverse`` into the matchdict.  As a result, we just
        # return True.
        return True
class CheckCSRFTokenPredicate(object):
    check_csrf_token = staticmethod(check_csrf_token) # testing
    def __init__(self, val, config):
        self.val = val
    def text(self):
        return 'check_csrf = %s' % (self.val,)
    phash = text
    def __call__(self, context, request):
        val = self.val
        if val:
            if val is True:
                val = 'csrf_token'
            return self.check_csrf_token(request, val, raises=False)
        return True
pyramid/config/routes.py
@@ -4,7 +4,6 @@
    IRequest,
    IRouteRequest,
    IRoutesMapper,
    PHASE1_CONFIG,
    PHASE2_CONFIG,
    )
pyramid/config/testing.py
@@ -19,7 +19,8 @@
class TestingConfiguratorMixin(object):
    # testing API
    def testing_securitypolicy(self, userid=None, groupids=(),
                               permissive=True):
                               permissive=True, remember_result=None,
                               forget_result=None):
        """Unit/integration testing helper: Registers a pair of faux
        :app:`Pyramid` security policies: a :term:`authentication
        policy` and a :term:`authorization policy`.
@@ -30,6 +31,24 @@
        this policy allows all access.  If ``permissive`` is false, a
        nonpermissive :term:`authorization policy` is registered; this
        policy denies all access.
        ``remember_result``, if provided, should be the result returned by
        the ``remember`` method of the faux authentication policy.  If it is
        not provided (or it is provided, and is ``None``), the default value
        ``[]`` (the empty list) will be returned by ``remember``.
        .. note::
           ``remember_result`` is new as of Pyramid 1.4.
        ``forget_result``, if provided, should be the result returned by
        the ``forget`` method of the faux authentication policy.  If it is
        not provided (or it is provided, and is ``None``), the default value
        ``[]`` (the empty list) will be returned by ``forget``.
        .. note::
           ``forget_result`` is new as of Pyramid 1.4.
        The behavior of the registered :term:`authentication policy`
        depends on the values provided for the ``userid`` and
@@ -47,9 +66,12 @@
        :func:`pyramid.security.principals_allowed_by_permission`.
        """
        from pyramid.testing import DummySecurityPolicy
        policy = DummySecurityPolicy(userid, groupids, permissive)
        policy = DummySecurityPolicy(
            userid, groupids, permissive, remember_result, forget_result
            )
        self.registry.registerUtility(policy, IAuthorizationPolicy)
        self.registry.registerUtility(policy, IAuthenticationPolicy)
        return policy
    def testing_resources(self, resources):
        """Unit/integration testing helper: registers a dictionary of
pyramid/config/views.py
@@ -662,6 +662,7 @@
        mapper=None,
        http_cache=None,
        match_param=None,
        check_csrf=None,
        **predicates):
        """ Add a :term:`view configuration` to the current
        configuration state.  Arguments to ``add_view`` are broken
@@ -989,6 +990,29 @@
          variable.  If the regex matches, this predicate will be
          ``True``.
        check_csrf
          If specified, this value should be one of ``None``, ``True``,
          ``False``, or a string representing the 'check name'.  If the value
          is ``True`` or a string, CSRF checking will be performed.  If the
          value is ``False`` or ``None``, CSRF checking will not be performed.
          If the value provided is a string, that string will be used as the
          'check name'.  If the value provided is ``True``, ``csrf_token`` will
          be used as the check name.
          If CSRF checking is performed, the checked value will be the value
          of ``request.params[check_name]``.  This value will be compared
          against the value of ``request.session.get_csrf_token()``, and the
          check will pass if these two values are the same.  If the check
          passes, the associated view will be permitted to execute.  If the
          check fails, the associated view will not be permitted to execute.
          Note that using this feature requires a :term:`session factory` to
          have been configured.
          .. versionadded:: 1.4a2
        custom_predicates
          This value should be a sequence of references to custom
@@ -1007,7 +1031,9 @@
          :meth:`pyramid.config.Configurator.add_view_predicate`.  More than
          one key/value pair can be used at the same time.  See
          :ref:`view_and_route_predicates` for more information about
          third-party predicates.  This argument is new as of Pyramid 1.4.
          third-party predicates.
          .. versionadded: 1.4a1
        """
        view = self.maybe_dotted(view)
@@ -1061,6 +1087,7 @@
                containment=containment,
                request_type=request_type,
                match_param=match_param,
                check_csrf=check_csrf,
                custom=predvalseq(custom_predicates),
                )
            )
@@ -1098,6 +1125,7 @@
                 header=header,
                 path_info=path_info,
                 match_param=match_param,
                 check_csrf=check_csrf,
                 callable=view,
                 mapper=mapper,
                 decorator=decorator,
@@ -1340,6 +1368,7 @@
            ('containment', p.ContainmentPredicate),
            ('request_type', p.RequestTypePredicate),
            ('match_param', p.MatchParamPredicate),
            ('check_csrf', p.CheckCSRFTokenPredicate),
            ('custom', p.CustomPredicate),
            ):
            self.add_view_predicate(name, factory)
pyramid/decorator.py
@@ -1,9 +1,31 @@
class reify(object):
    """ Use as a class method decorator.  It operates almost exactly like the
    Python ``@property`` decorator, but it puts the result of the method it
    decorates into the instance dict after the first call, effectively
    replacing the function it decorates with an instance variable.  It is, in
    Python parlance, a non-data descriptor.  An example:
    """ Put the result of a method which uses this (non-data)
    descriptor decorator in the instance dict after the first call,
    effectively replacing the decorator with an instance variable."""
    .. code-block:: python
       class Foo(object):
           @reify
           def jammy(self):
               print 'jammy called'
               return 1
    And usage of Foo:
    .. code-block:: text
       >>> f = Foo()
       >>> v = f.jammy
       'jammy called'
       >>> print v
       1
       >>> f.jammy
       1
       >>> # jammy func not called the second time; it replaced itself with 1
    """
    def __init__(self, wrapped):
        self.wrapped = wrapped
        try:
pyramid/mako_templating.py
@@ -91,11 +91,13 @@
    def __call__(self, info):
        p = re.compile(
                r'(?P<asset>[\w_.:/]+)'
                r'(?P<asset>[\w_.:/-]+)'
                r'(?:\#(?P<defname>[\w_]+))?'
                r'(\.(?P<ext>.*))'
                )
        asset, defname, ext = p.match(info.name).group('asset', 'defname', 'ext')
        asset, defname, ext = p.match(info.name).group(
            'asset', 'defname', 'ext'
            )
        path = '%s.%s' % (asset, ext)
        registry = info.registry
        settings = info.settings
@@ -154,12 +156,9 @@
                preprocessor=preprocessor
                )
            registry_lock.acquire()
            try:
            with registry_lock:
                registry.registerUtility(lookup, IMakoLookup,
                                         name=settings_prefix)
            finally:
                registry_lock.release()
        return MakoLookupTemplateRenderer(path, defname, lookup)
pyramid/renderers.py
@@ -367,6 +367,12 @@
@implementer(IChameleonLookup)
class ChameleonRendererLookup(object):
    spec_re = re.compile(
        r'(?P<asset>[\w_.:/-]+)'
        r'(?:\#(?P<defname>[\w_]+))?'
        r'(\.(?P<ext>.*))'
        )
    def __init__(self, impl, registry):
        self.impl = impl
        self.registry = registry
@@ -417,6 +423,12 @@
            return False
        return settings.get('reload_templates', False)
    def _crack_spec(self, spec):
        asset, macro, ext = self.spec_re.match(spec).group(
            'asset', 'defname', 'ext'
            )
        return asset, macro, ext
    def __call__(self, info):
        spec = self.get_spec(info.name, info.package)
        registry = info.registry
@@ -429,46 +441,36 @@
            if renderer is None:
                renderer = self.impl(spec, self, macro=None)
                # cache the template
                try:
                    self.lock.acquire()
                with self.lock:
                    registry.registerUtility(renderer,
                                             ITemplateRenderer, name=spec)
                finally:
                    self.lock.release()
        else:
            # spec is a package:relpath asset spec
            renderer = registry.queryUtility(ITemplateRenderer, name=spec)
            if renderer is None:
                p = re.compile(
                    r'(?P<asset>[\w_.:/]+)'
                    r'(?:\#(?P<defname>[\w_]+))?'
                    r'(\.(?P<ext>.*))'
                    )
                asset, macro, ext = p.match(spec).group(
                    'asset', 'defname', 'ext')
                spec = '%s.%s' % (asset, ext)
                asset, macro, ext = self._crack_spec(spec)
                spec_without_macro = '%s.%s' % (asset, ext)
                try:
                    package_name, filename = spec.split(':', 1)
                    package_name, filename = spec_without_macro.split(':', 1)
                except ValueError: # pragma: no cover
                    # somehow we were passed a relative pathname; this
                    # should die
                    package_name = caller_package(4).__name__
                    filename = spec
                    filename = spec_without_macro
                abspath = pkg_resources.resource_filename(package_name,
                                                          filename)
                if not pkg_resources.resource_exists(package_name, filename):
                    raise ValueError(
                        'Missing template asset: %s (%s)' % (spec, abspath))
                        'Missing template asset: %s (%s)' % (
                            spec_without_macro, abspath)
                        )
                renderer = self.impl(abspath, self, macro=macro)
                settings = info.settings
                if not settings.get('reload_assets'):
                    # cache the template
                    self.lock.acquire()
                    try:
                    with self.lock:
                        registry.registerUtility(renderer, ITemplateRenderer,
                                                 name=spec)
                    finally:
                        self.lock.release()
        return renderer
@@ -479,11 +481,8 @@
    lookup = registry.queryUtility(IChameleonLookup, name=info.type)
    if lookup is None:
        lookup = ChameleonRendererLookup(impl, registry)
        lock.acquire()
        try:
        with lock:
            registry.registerUtility(lookup, IChameleonLookup, name=info.type)
        finally:
            lock.release()
    return lookup(info)
@implementer(IRendererInfo)
pyramid/router.py
@@ -53,6 +53,7 @@
        tweens = q(ITweens)
        if tweens is None:
            tweens = excview_tween_factory
        self.orig_handle_request = self.handle_request
        self.handle_request = tweens(self.handle_request, registry)
        self.root_policy = self.root_factory # b/w compat
        self.registry = registry
@@ -161,6 +162,83 @@
        return response
    def invoke_subrequest(self, request, use_tweens=False):
        """
        Obtain a response object from the Pyramid application based on
        information in the ``request`` object provided.  The ``request``
        object must be an object that implements the Pyramid request
        interface (such as a :class:`pyramid.request.Request` instance).  If
        ``use_tweens`` is ``True``, the request will be sent to the
        :term:`tween` in the tween stack closest to the request ingress.  If
        ``use_tweens`` is ``False``, the request will be sent to the main
        router handler, and no tweens will be invoked.  This function also:
        - manages the threadlocal stack (so that
          :func:`~pyramid.threadlocal.get_current_request` and
          :func:`~pyramid.threadlocal.get_current_registry` work during a
          request)
        - Adds a ``registry`` attribute and a ``invoke_subrequest`` attribute
          (a callable) to the request object it's handed.
        - sets request extensions (such as those added via
          :meth:`~pyramid.config.Configurator.add_request_method` or
          :meth:`~pyramid.config.Configurator.set_request_property`) on the
          request it's passed.
        - causes a :class:`~pyramid.event.NewRequest` event to be sent at the
          beginning of request processing.
        - causes a :class:`~pyramid.event.ContextFound` event to be sent
          when a context resource is found.
        - causes a :class:`~pyramid.event.NewResponse` event to be sent when
          the Pyramid application returns a response.
        - Calls any :term:`response callback` functions defined within the
          request's lifetime if a response is obtained from the Pyramid
          application.
        - Calls any :term:`finished callback` functions defined within the
          request's lifetime.
        See also :ref:`subrequest_chapter`.
        """
        registry = self.registry
        has_listeners = self.registry.has_listeners
        notify = self.registry.notify
        threadlocals = {'registry':registry, 'request':request}
        manager = self.threadlocal_manager
        manager.push(threadlocals)
        request.registry = registry
        request.invoke_subrequest = self.invoke_subrequest
        if use_tweens:
            handle_request = self.handle_request
        else:
            handle_request = self.orig_handle_request
        try:
            try:
                extensions = self.request_extensions
                if extensions is not None:
                    request._set_extensions(extensions)
                response = handle_request(request)
                has_listeners and notify(NewResponse(request, response))
                if request.response_callbacks:
                    request._process_response_callbacks(response)
                return response
            finally:
                if request.finished_callbacks:
                    request._process_finished_callbacks()
        finally:
            manager.pop()
    def __call__(self, environ, start_response):
        """
        Accept ``environ`` and ``start_response``; create a
@@ -169,31 +247,7 @@
        within the application registry; call ``start_response`` and
        return an iterable.
        """
        registry = self.registry
        has_listeners = self.registry.has_listeners
        notify = self.registry.notify
        request = self.request_factory(environ)
        threadlocals = {'registry':registry, 'request':request}
        manager = self.threadlocal_manager
        manager.push(threadlocals)
        request.registry = registry
        try:
        response = self.invoke_subrequest(request, use_tweens=True)
        return response(request.environ, start_response)
            try:
                extensions = self.request_extensions
                if extensions is not None:
                    request._set_extensions(extensions)
                response = self.handle_request(request)
                has_listeners and notify(NewResponse(request, response))
                if request.response_callbacks:
                    request._process_response_callbacks(response)
                return response(request.environ, start_response)
            finally:
                if request.finished_callbacks:
                    request._process_finished_callbacks()
        finally:
            manager.pop()
pyramid/scaffolds/alchemy/+package+/__init__.py
@@ -1,13 +1,17 @@
from pyramid.config import Configurator
from sqlalchemy import engine_from_config
from .models import DBSession
from .models import (
    DBSession,
    Base,
    )
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    engine = engine_from_config(settings, 'sqlalchemy.')
    DBSession.configure(bind=engine)
    Base.metadata.bind = engine
    config = Configurator(settings=settings)
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.add_route('home', '/')
pyramid/scaffolds/alchemy/+package+/static/pylons.css
@@ -1,65 +1,372 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td
{
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-size: 100%; /* 16px */
  vertical-align: baseline;
  background: transparent;
}
body
{
  line-height: 1;
}
ol, ul
{
  list-style: none;
}
blockquote, q
{
  quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after
{
  content: '';
  content: none;
}
:focus
{
  outline: 0;
}
ins
{
  text-decoration: none;
}
del
{
  text-decoration: line-through;
}
table
{
  border-collapse: collapse;
  border-spacing: 0;
}
sub
{
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}
sup
{
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}
ul, menu, dir
{
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  padding-left: 40px;
}
ol
{
  display: block;
  list-style-type: decimal-leading-zero;
  margin: 1em 0;
  padding-left: 40px;
}
li
{
  display: list-item;
}
ul ul, ul ol, ul dir, ul menu, ul dl, ol ul, ol ol, ol dir, ol menu, ol dl, dir ul, dir ol, dir dir, dir menu, dir dl, menu ul, menu ol, menu dir, menu menu, menu dl, dl ul, dl ol, dl dir, dl menu, dl dl
{
  margin-top: 0;
  margin-bottom: 0;
}
ol ul, ul ul, menu ul, dir ul, ol menu, ul menu, menu menu, dir menu, ol dir, ul dir, menu dir, dir dir
{
  list-style-type: circle;
}
ol ol ul, ol ul ul, ol menu ul, ol dir ul, ol ol menu, ol ul menu, ol menu menu, ol dir menu, ol ol dir, ol ul dir, ol menu dir, ol dir dir, ul ol ul, ul ul ul, ul menu ul, ul dir ul, ul ol menu, ul ul menu, ul menu menu, ul dir menu, ul ol dir, ul ul dir, ul menu dir, ul dir dir, menu ol ul, menu ul ul, menu menu ul, menu dir ul, menu ol menu, menu ul menu, menu menu menu, menu dir menu, menu ol dir, menu ul dir, menu menu dir, menu dir dir, dir ol ul, dir ul ul, dir menu ul, dir dir ul, dir ol menu, dir ul menu, dir menu menu, dir dir menu, dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
  list-style-type: square;
}
.hidden
{
  display: none;
}
p
{
  line-height: 1.5em;
}
h1
{
  font-size: 1.75em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h2
{
  font-size: 1.5em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h3
{
  font-size: 1.25em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h4
{
  font-size: 1em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
html, body
{
  width: 100%;
  height: 100%;
}
body
{
  margin: 0;
  padding: 0;
  background-color: #fff;
  position: relative;
  font: 16px/24px NobileRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
}
a
{
  color: #1b61d6;
  text-decoration: none;
}
a:hover
{
  color: #e88f00;
  text-decoration: underline;
}
body h1, body h2, body h3, body h4, body h5, body h6
{
  font-family: NeutonRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
  font-weight: 400;
  color: #373839;
  font-style: normal;
}
#wrap
{
  min-height: 100%;
}
#header, #footer
{
  width: 100%;
  color: #fff;
  height: 40px;
  position: absolute;
  text-align: center;
  line-height: 40px;
  overflow: hidden;
  font-size: 12px;
  vertical-align: middle;
}
#header
{
  background: #000;
  top: 0;
  font-size: 14px;
}
#footer
{
  bottom: 0;
  background: #000 url(footerbg.png) repeat-x 0 top;
  position: relative;
  margin-top: -40px;
  clear: both;
}
.header, .footer
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.wrapper
{
  width: 100%;
}
#top, #top-small, #bottom
{
  width: 100%;
}
#top
{
  color: #000;
  height: 230px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#top-small
{
  color: #000;
  height: 60px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#bottom
{
  color: #222;
  background-color: #fff;
}
.top, .top-small, .middle, .bottom
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.top
{
  padding-top: 40px;
}
.top-small
{
  padding-top: 10px;
}
#middle
{
  width: 100%;
  height: 100px;
  background: url(middlebg.png) repeat-x;
  border-top: 2px solid #fff;
  border-bottom: 2px solid #b2b2b2;
}
.app-welcome
{
  margin-top: 25px;
}
.app-name
{
  color: #000;
  font-weight: 700;
}
.bottom
{
  padding-top: 50px;
}
#left
{
  width: 350px;
  float: left;
  padding-right: 25px;
}
#right
{
  width: 350px;
  float: right;
  padding-left: 25px;
}
.align-left
{
  text-align: left;
}
.align-right
{
  text-align: right;
}
.align-center
{
  text-align: center;
}
ul.links
{
  margin: 0;
  padding: 0;
}
ul.links li
{
  list-style-type: none;
  font-size: 14px;
}
form
{
  border-style: none;
}
fieldset
{
  border-style: none;
}
input
{
  color: #222;
  border: 1px solid #ccc;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 16px;
}
input[type=text], input[type=password]
{
  width: 205px;
}
input[type=submit]
{
  background-color: #ddd;
  font-weight: 700;
}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
body:before
{
  content: "";
  height: 100%;
  float: left;
  width: 0;
  margin-top: -32767px;
}
pyramid/scaffolds/starter/+package+/static/pylons.css
@@ -1,65 +1,372 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td
{
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-size: 100%; /* 16px */
  vertical-align: baseline;
  background: transparent;
}
body
{
  line-height: 1;
}
ol, ul
{
  list-style: none;
}
blockquote, q
{
  quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after
{
  content: '';
  content: none;
}
:focus
{
  outline: 0;
}
ins
{
  text-decoration: none;
}
del
{
  text-decoration: line-through;
}
table
{
  border-collapse: collapse;
  border-spacing: 0;
}
sub
{
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}
sup
{
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}
ul, menu, dir
{
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  padding-left: 40px;
}
ol
{
  display: block;
  list-style-type: decimal-leading-zero;
  margin: 1em 0;
  padding-left: 40px;
}
li
{
  display: list-item;
}
ul ul, ul ol, ul dir, ul menu, ul dl, ol ul, ol ol, ol dir, ol menu, ol dl, dir ul, dir ol, dir dir, dir menu, dir dl, menu ul, menu ol, menu dir, menu menu, menu dl, dl ul, dl ol, dl dir, dl menu, dl dl
{
  margin-top: 0;
  margin-bottom: 0;
}
ol ul, ul ul, menu ul, dir ul, ol menu, ul menu, menu menu, dir menu, ol dir, ul dir, menu dir, dir dir
{
  list-style-type: circle;
}
ol ol ul, ol ul ul, ol menu ul, ol dir ul, ol ol menu, ol ul menu, ol menu menu, ol dir menu, ol ol dir, ol ul dir, ol menu dir, ol dir dir, ul ol ul, ul ul ul, ul menu ul, ul dir ul, ul ol menu, ul ul menu, ul menu menu, ul dir menu, ul ol dir, ul ul dir, ul menu dir, ul dir dir, menu ol ul, menu ul ul, menu menu ul, menu dir ul, menu ol menu, menu ul menu, menu menu menu, menu dir menu, menu ol dir, menu ul dir, menu menu dir, menu dir dir, dir ol ul, dir ul ul, dir menu ul, dir dir ul, dir ol menu, dir ul menu, dir menu menu, dir dir menu, dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
  list-style-type: square;
}
.hidden
{
  display: none;
}
p
{
  line-height: 1.5em;
}
h1
{
  font-size: 1.75em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h2
{
  font-size: 1.5em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h3
{
  font-size: 1.25em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h4
{
  font-size: 1em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
html, body
{
  width: 100%;
  height: 100%;
}
body
{
  margin: 0;
  padding: 0;
  background-color: #fff;
  position: relative;
  font: 16px/24px NobileRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
}
a
{
  color: #1b61d6;
  text-decoration: none;
}
a:hover
{
  color: #e88f00;
  text-decoration: underline;
}
body h1, body h2, body h3, body h4, body h5, body h6
{
  font-family: NeutonRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
  font-weight: 400;
  color: #373839;
  font-style: normal;
}
#wrap
{
  min-height: 100%;
}
#header, #footer
{
  width: 100%;
  color: #fff;
  height: 40px;
  position: absolute;
  text-align: center;
  line-height: 40px;
  overflow: hidden;
  font-size: 12px;
  vertical-align: middle;
}
#header
{
  background: #000;
  top: 0;
  font-size: 14px;
}
#footer
{
  bottom: 0;
  background: #000 url(footerbg.png) repeat-x 0 top;
  position: relative;
  margin-top: -40px;
  clear: both;
}
.header, .footer
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.wrapper
{
  width: 100%;
}
#top, #top-small, #bottom
{
  width: 100%;
}
#top
{
  color: #000;
  height: 230px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#top-small
{
  color: #000;
  height: 60px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#bottom
{
  color: #222;
  background-color: #fff;
}
.top, .top-small, .middle, .bottom
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.top
{
  padding-top: 40px;
}
.top-small
{
  padding-top: 10px;
}
#middle
{
  width: 100%;
  height: 100px;
  background: url(middlebg.png) repeat-x;
  border-top: 2px solid #fff;
  border-bottom: 2px solid #b2b2b2;
}
.app-welcome
{
  margin-top: 25px;
}
.app-name
{
  color: #000;
  font-weight: 700;
}
.bottom
{
  padding-top: 50px;
}
#left
{
  width: 350px;
  float: left;
  padding-right: 25px;
}
#right
{
  width: 350px;
  float: right;
  padding-left: 25px;
}
.align-left
{
  text-align: left;
}
.align-right
{
  text-align: right;
}
.align-center
{
  text-align: center;
}
ul.links
{
  margin: 0;
  padding: 0;
}
ul.links li
{
  list-style-type: none;
  font-size: 14px;
}
form
{
  border-style: none;
}
fieldset
{
  border-style: none;
}
input
{
  color: #222;
  border: 1px solid #ccc;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 16px;
}
input[type=text], input[type=password]
{
  width: 205px;
}
input[type=submit]
{
  background-color: #ddd;
  font-weight: 700;
}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
body:before
{
  content: "";
  height: 100%;
  float: left;
  width: 0;
  margin-top: -32767px;
}
pyramid/scaffolds/zodb/+package+/static/pylons.css
@@ -1,65 +1,372 @@
html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td{margin:0;padding:0;border:0;outline:0;font-size:100%;/* 16px */
vertical-align:baseline;background:transparent;}
body{line-height:1;}
ol,ul{list-style:none;}
blockquote,q{quotes:none;}
blockquote:before,blockquote:after,q:before,q:after{content:'';content:none;}
:focus{outline:0;}
ins{text-decoration:none;}
del{text-decoration:line-through;}
table{border-collapse:collapse;border-spacing:0;}
sub{vertical-align:sub;font-size:smaller;line-height:normal;}
sup{vertical-align:super;font-size:smaller;line-height:normal;}
ul,menu,dir{display:block;list-style-type:disc;margin:1em 0;padding-left:40px;}
ol{display:block;list-style-type:decimal-leading-zero;margin:1em 0;padding-left:40px;}
li{display:list-item;}
ul ul,ul ol,ul dir,ul menu,ul dl,ol ul,ol ol,ol dir,ol menu,ol dl,dir ul,dir ol,dir dir,dir menu,dir dl,menu ul,menu ol,menu dir,menu menu,menu dl,dl ul,dl ol,dl dir,dl menu,dl dl{margin-top:0;margin-bottom:0;}
ol ul,ul ul,menu ul,dir ul,ol menu,ul menu,menu menu,dir menu,ol dir,ul dir,menu dir,dir dir{list-style-type:circle;}
ol ol ul,ol ul ul,ol menu ul,ol dir ul,ol ol menu,ol ul menu,ol menu menu,ol dir menu,ol ol dir,ol ul dir,ol menu dir,ol dir dir,ul ol ul,ul ul ul,ul menu ul,ul dir ul,ul ol menu,ul ul menu,ul menu menu,ul dir menu,ul ol dir,ul ul dir,ul menu dir,ul dir dir,menu ol ul,menu ul ul,menu menu ul,menu dir ul,menu ol menu,menu ul menu,menu menu menu,menu dir menu,menu ol dir,menu ul dir,menu menu dir,menu dir dir,dir ol ul,dir ul ul,dir menu ul,dir dir ul,dir ol menu,dir ul menu,dir menu menu,dir dir menu,dir ol dir,dir ul dir,dir menu dir,dir dir dir{list-style-type:square;}
.hidden{display:none;}
p{line-height:1.5em;}
h1{font-size:1.75em;line-height:1.7em;font-family:helvetica,verdana;}
h2{font-size:1.5em;line-height:1.7em;font-family:helvetica,verdana;}
h3{font-size:1.25em;line-height:1.7em;font-family:helvetica,verdana;}
h4{font-size:1em;line-height:1.7em;font-family:helvetica,verdana;}
html,body{width:100%;height:100%;}
body{margin:0;padding:0;background-color:#ffffff;position:relative;font:16px/24px "NobileRegular","Lucida Grande",Lucida,Verdana,sans-serif;}
a{color:#1b61d6;text-decoration:none;}
a:hover{color:#e88f00;text-decoration:underline;}
body h1,
body h2,
body h3,
body h4,
body h5,
body h6{font-family:"NeutonRegular","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#373839;font-style:normal;}
#wrap{min-height:100%;}
#header,#footer{width:100%;color:#ffffff;height:40px;position:absolute;text-align:center;line-height:40px;overflow:hidden;font-size:12px;vertical-align:middle;}
#header{background:#000000;top:0;font-size:14px;}
#footer{bottom:0;background:#000000 url(footerbg.png) repeat-x 0 top;position:relative;margin-top:-40px;clear:both;}
.header,.footer{width:750px;margin-right:auto;margin-left:auto;}
.wrapper{width:100%}
#top,#top-small,#bottom{width:100%;}
#top{color:#000000;height:230px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#top-small{color:#000000;height:60px;background:#ffffff url(headerbg.png) repeat-x 0 top;position:relative;}
#bottom{color:#222;background-color:#ffffff;}
.top,.top-small,.middle,.bottom{width:750px;margin-right:auto;margin-left:auto;}
.top{padding-top:40px;}
.top-small{padding-top:10px;}
#middle{width:100%;height:100px;background:url(middlebg.png) repeat-x;border-top:2px solid #ffffff;border-bottom:2px solid #b2b2b2;}
.app-welcome{margin-top:25px;}
.app-name{color:#000000;font-weight:bold;}
.bottom{padding-top:50px;}
#left{width:350px;float:left;padding-right:25px;}
#right{width:350px;float:right;padding-left:25px;}
.align-left{text-align:left;}
.align-right{text-align:right;}
.align-center{text-align:center;}
ul.links{margin:0;padding:0;}
ul.links li{list-style-type:none;font-size:14px;}
form{border-style:none;}
fieldset{border-style:none;}
input{color:#222;border:1px solid #ccc;font-family:sans-serif;font-size:12px;line-height:16px;}
input[type=text],input[type=password]{width:205px;}
input[type=submit]{background-color:#ddd;font-weight:bold;}
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, font, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td
{
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  font-size: 100%; /* 16px */
  vertical-align: baseline;
  background: transparent;
}
body
{
  line-height: 1;
}
ol, ul
{
  list-style: none;
}
blockquote, q
{
  quotes: none;
}
blockquote:before, blockquote:after, q:before, q:after
{
  content: '';
  content: none;
}
:focus
{
  outline: 0;
}
ins
{
  text-decoration: none;
}
del
{
  text-decoration: line-through;
}
table
{
  border-collapse: collapse;
  border-spacing: 0;
}
sub
{
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}
sup
{
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}
ul, menu, dir
{
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  padding-left: 40px;
}
ol
{
  display: block;
  list-style-type: decimal-leading-zero;
  margin: 1em 0;
  padding-left: 40px;
}
li
{
  display: list-item;
}
ul ul, ul ol, ul dir, ul menu, ul dl, ol ul, ol ol, ol dir, ol menu, ol dl, dir ul, dir ol, dir dir, dir menu, dir dl, menu ul, menu ol, menu dir, menu menu, menu dl, dl ul, dl ol, dl dir, dl menu, dl dl
{
  margin-top: 0;
  margin-bottom: 0;
}
ol ul, ul ul, menu ul, dir ul, ol menu, ul menu, menu menu, dir menu, ol dir, ul dir, menu dir, dir dir
{
  list-style-type: circle;
}
ol ol ul, ol ul ul, ol menu ul, ol dir ul, ol ol menu, ol ul menu, ol menu menu, ol dir menu, ol ol dir, ol ul dir, ol menu dir, ol dir dir, ul ol ul, ul ul ul, ul menu ul, ul dir ul, ul ol menu, ul ul menu, ul menu menu, ul dir menu, ul ol dir, ul ul dir, ul menu dir, ul dir dir, menu ol ul, menu ul ul, menu menu ul, menu dir ul, menu ol menu, menu ul menu, menu menu menu, menu dir menu, menu ol dir, menu ul dir, menu menu dir, menu dir dir, dir ol ul, dir ul ul, dir menu ul, dir dir ul, dir ol menu, dir ul menu, dir menu menu, dir dir menu, dir ol dir, dir ul dir, dir menu dir, dir dir dir
{
  list-style-type: square;
}
.hidden
{
  display: none;
}
p
{
  line-height: 1.5em;
}
h1
{
  font-size: 1.75em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h2
{
  font-size: 1.5em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h3
{
  font-size: 1.25em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
h4
{
  font-size: 1em;
  line-height: 1.7em;
  font-family: helvetica, verdana;
}
html, body
{
  width: 100%;
  height: 100%;
}
body
{
  margin: 0;
  padding: 0;
  background-color: #fff;
  position: relative;
  font: 16px/24px NobileRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
}
a
{
  color: #1b61d6;
  text-decoration: none;
}
a:hover
{
  color: #e88f00;
  text-decoration: underline;
}
body h1, body h2, body h3, body h4, body h5, body h6
{
  font-family: NeutonRegular, "Lucida Grande", Lucida, Verdana, sans-serif;
  font-weight: 400;
  color: #373839;
  font-style: normal;
}
#wrap
{
  min-height: 100%;
}
#header, #footer
{
  width: 100%;
  color: #fff;
  height: 40px;
  position: absolute;
  text-align: center;
  line-height: 40px;
  overflow: hidden;
  font-size: 12px;
  vertical-align: middle;
}
#header
{
  background: #000;
  top: 0;
  font-size: 14px;
}
#footer
{
  bottom: 0;
  background: #000 url(footerbg.png) repeat-x 0 top;
  position: relative;
  margin-top: -40px;
  clear: both;
}
.header, .footer
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.wrapper
{
  width: 100%;
}
#top, #top-small, #bottom
{
  width: 100%;
}
#top
{
  color: #000;
  height: 230px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#top-small
{
  color: #000;
  height: 60px;
  background: #fff url(headerbg.png) repeat-x 0 top;
  position: relative;
}
#bottom
{
  color: #222;
  background-color: #fff;
}
.top, .top-small, .middle, .bottom
{
  width: 750px;
  margin-right: auto;
  margin-left: auto;
}
.top
{
  padding-top: 40px;
}
.top-small
{
  padding-top: 10px;
}
#middle
{
  width: 100%;
  height: 100px;
  background: url(middlebg.png) repeat-x;
  border-top: 2px solid #fff;
  border-bottom: 2px solid #b2b2b2;
}
.app-welcome
{
  margin-top: 25px;
}
.app-name
{
  color: #000;
  font-weight: 700;
}
.bottom
{
  padding-top: 50px;
}
#left
{
  width: 350px;
  float: left;
  padding-right: 25px;
}
#right
{
  width: 350px;
  float: right;
  padding-left: 25px;
}
.align-left
{
  text-align: left;
}
.align-right
{
  text-align: right;
}
.align-center
{
  text-align: center;
}
ul.links
{
  margin: 0;
  padding: 0;
}
ul.links li
{
  list-style-type: none;
  font-size: 14px;
}
form
{
  border-style: none;
}
fieldset
{
  border-style: none;
}
input
{
  color: #222;
  border: 1px solid #ccc;
  font-family: sans-serif;
  font-size: 12px;
  line-height: 16px;
}
input[type=text], input[type=password]
{
  width: 205px;
}
input[type=submit]
{
  background-color: #ddd;
  font-weight: 700;
}
/*Opera Fix*/
body:before{content:"";height:100%;float:left;width:0;margin-top:-32767px;}
body:before
{
  content: "";
  height: 100%;
  float: left;
  width: 0;
  margin-top: -32767px;
}
pyramid/scripting.py
@@ -71,6 +71,10 @@
                                 'before trying to activate it.')
    if request is None:
        request = _make_request('/', registry)
    # NB: even though _make_request might have already set registry on
    # request, we reset it in case someone has passed in their own
    # request.
    request.registry = registry
    threadlocals = {'registry':registry, 'request':request}
    threadlocal_manager.push(threadlocals)
    extensions = registry.queryUtility(IRequestExtensions)
pyramid/scripts/pserve.py
@@ -583,12 +583,8 @@
    def open(self):
        if self.fileobj is None:
            self.lock.acquire()
            try:
                if self.fileobj is None:
                    self.fileobj = open(self.filename, self.mode)
            finally:
                self.lock.release()
            with self.lock:
                self.fileobj = open(self.filename, self.mode)
        return self.fileobj
    def close(self):
pyramid/session.py
@@ -15,6 +15,7 @@
    native_,
    )
from pyramid.httpexceptions import HTTPBadRequest
from pyramid.interfaces import ISession
from pyramid.util import strings_differ
@@ -80,6 +81,29 @@
    return pickle.loads(pickled)
def check_csrf_token(request, token='csrf_token', raises=True):
    """ Check the CSRF token in the request's session against the value in
    ``request.params.get(token)``.  If a ``token`` keyword is not supplied
    to this function, the string ``csrf_token`` will be used to look up
    the token within ``request.params``.  If the value in
    ``request.params.get(token)`` doesn't match the value supplied by
    ``request.session.get_csrf_token()``, and ``raises`` is ``True``, this
    function will raise an :exc:`pyramid.httpexceptions.HTTPBadRequest`
    exception.  If the check does succeed and ``raises`` is ``False``, this
    function will return ``False``.  If the CSRF check is successful, this
    function will return ``True`` unconditionally.
    Note that using this function requires that a :term:`session factory` is
    configured.
    .. versionadded:: 1.4a2
    """
    if request.params.get(token) != request.session.get_csrf_token():
        if raises:
            raise HTTPBadRequest('incorrect CSRF token')
        return False
    return True
def UnencryptedCookieSessionFactoryConfig(
    secret,
    timeout=1200,
pyramid/testing.py
@@ -1,5 +1,6 @@
import copy
import os
from contextlib import contextmanager
from zope.interface import (
    implementer,
@@ -52,10 +53,17 @@
class DummySecurityPolicy(object):
    """ A standin for both an IAuthentication and IAuthorization policy """
    def __init__(self, userid=None, groupids=(), permissive=True):
    def __init__(self, userid=None, groupids=(), permissive=True,
                 remember_result=None, forget_result=None):
        self.userid = userid
        self.groupids = groupids
        self.permissive = permissive
        if remember_result is None:
            remember_result = []
        if forget_result is None:
            forget_result = []
        self.remember_result = remember_result
        self.forget_result = forget_result
    def authenticated_userid(self, request):
        return self.userid
@@ -72,10 +80,12 @@
        return effective_principals
    def remember(self, request, principal, **kw):
        return []
        self.remembered = principal
        return self.remember_result
    def forget(self, request):
        return []
        self.forgotten = True
        return self.forget_result
    def permits(self, context, principals, permission):
        return self.permissive
@@ -293,7 +303,7 @@
    request.  For example, by default, the DummyRequest ``GET`` and ``POST``
    attributes are of type ``dict``, unlike a normal Request's GET and POST,
    which are of type ``MultiDict``. If your code uses the features of
    MultiDict, you should either use a"real" :class:`pyramid.request.Request`
    MultiDict, you should either use a real :class:`pyramid.request.Request`
    or adapt your DummyRequest by replacing the attributes with ``MultiDict``
    instances.
@@ -572,3 +582,37 @@
            return wrapper
    return decorator
skip_on.os_name = os.name # for testing
@contextmanager
def testConfig(registry=None,
        request=None,
        hook_zca=True,
        autocommit=True,
        settings=None):
    """Returns a context manager for test set up.
    This context manager calls :func:`pyramid.testing.testSetup` when
    entering and :func:`pyramid.testing.tearDown` when exiting.
    All arguments are passed directly to :func:`pyramid.testing.testSetup`.
    If the ZCA is hooked, it will always be un-hooked in tearDown.
    This context manager allows you to write test code like this:
    .. code-block:: python
        :linenos:
        with testConfig() as config:
            config.add_route('bar', '/bar/{id}')
            req = DummyRequest()
            resp = myview(req),
    """
    config = setUp(registry=registry,
            request=request,
            hook_zca=hook_zca,
            autocommit=autocommit,
            settings=settings)
    try:
        yield config
    finally:
        tearDown(unhook_zca=hook_zca)
pyramid/tests/fixtures/withmacro.pt
@@ -1,4 +1,5 @@
<html>
Outside macro
<metal:m define-macro="foo">
  Hello!
</metal:m>
pyramid/tests/pkgs/subrequestapp/__init__.py
New file
@@ -0,0 +1,50 @@
from pyramid.config import Configurator
from pyramid.request import Request
def view_one(request):
    subreq = Request.blank('/view_two')
    response = request.invoke_subrequest(subreq, use_tweens=False)
    return response
def view_two(request):
    return 'This came from view_two'
def view_three(request):
    subreq = Request.blank('/view_four')
    try:
        return request.invoke_subrequest(subreq, use_tweens=True)
    except: # pragma: no cover
        request.response.body = b'Value error raised'
        return request.response
def view_four(request):
    raise ValueError('foo')
def view_five(request):
    subreq = Request.blank('/view_four')
    try:
        return request.invoke_subrequest(subreq, use_tweens=False)
    except ValueError:
        request.response.body = b'Value error raised'
        return request.response
def excview(request):
    request.response.status_int = 500
    request.response.body = b'Bad stuff happened'
    return request.response
def main():
    config = Configurator()
    config.add_route('one', '/view_one')
    config.add_route('two', '/view_two')
    config.add_route('three', '/view_three')
    config.add_route('four', '/view_four')
    config.add_route('five', '/view_five')
    config.add_view(excview, context=Exception)
    config.add_view(view_one, route_name='one')
    config.add_view(view_two, route_name='two', renderer='string')
    config.add_view(view_three, route_name='three')
    config.add_view(view_four, route_name='four')
    config.add_view(view_five, route_name='five')
    return config
pyramid/tests/test_chameleon_text.py
@@ -2,7 +2,6 @@
import unittest
from pyramid.compat import binary_type
from pyramid.testing import skip_on
from pyramid import testing
class Base(object):
@@ -50,7 +49,6 @@
        from pyramid.interfaces import ITemplateRenderer
        verifyClass(ITemplateRenderer, self._getTargetClass())
    @skip_on('java')
    def test_template_reified(self):
        minimal = self._getTemplatePath('minimal.txt')
        lookup = DummyLookup()
@@ -59,7 +57,6 @@
        template  = instance.template
        self.assertEqual(template, instance.__dict__['template'])
    @skip_on('java')
    def test_template_with_ichameleon_translate(self):
        minimal = self._getTemplatePath('minimal.txt')
        lookup = DummyLookup()
@@ -68,7 +65,6 @@
        template  = instance.template
        self.assertEqual(template.translate, lookup.translate)
    @skip_on('java')
    def test_template_with_debug_templates(self):
        minimal = self._getTemplatePath('minimal.txt')
        lookup = DummyLookup()
@@ -78,7 +74,6 @@
        template  = instance.template
        self.assertEqual(template.debug, True)
    @skip_on('java')
    def test_template_with_reload_templates(self):
        minimal = self._getTemplatePath('minimal.txt')
        lookup = DummyLookup()
@@ -88,7 +83,6 @@
        template  = instance.template
        self.assertEqual(template.auto_reload, True)
    @skip_on('java')
    def test_template_without_reload_templates(self):
        minimal = self._getTemplatePath('minimal.txt')
        lookup = DummyLookup()
@@ -98,7 +92,6 @@
        template  = instance.template
        self.assertEqual(template.auto_reload, False)
    @skip_on('java')
    def test_call(self):
        minimal = self._getTemplatePath('minimal.txt')
        lookup = DummyLookup()
@@ -107,14 +100,12 @@
        self.assertTrue(isinstance(result, binary_type))
        self.assertEqual(result, b'Hello.\n')
    @skip_on('java')
    def test_call_with_nondict_value(self):
        minimal = self._getTemplatePath('minimal.txt')
        lookup = DummyLookup()
        instance = self._makeOne(minimal, lookup)
        self.assertRaises(ValueError, instance, None, {})
    @skip_on('java')
    def test_call_nonminimal(self):
        nonminimal = self._getTemplatePath('nonminimal.txt')
        lookup = DummyLookup()
@@ -123,7 +114,6 @@
        self.assertTrue(isinstance(result, binary_type))
        self.assertEqual(result, b'Hello, Chris!\n')
    @skip_on('java')
    def test_implementation(self):
        minimal = self._getTemplatePath('minimal.txt')
        lookup = DummyLookup()
pyramid/tests/test_chameleon_zpt.py
@@ -1,7 +1,6 @@
import sys
import unittest
from pyramid.testing import skip_on
from pyramid import testing
from pyramid.compat import text_type
@@ -50,7 +49,6 @@
        from pyramid.interfaces import ITemplateRenderer
        verifyClass(ITemplateRenderer, self._getTargetClass())
    @skip_on('java')
    def test_call(self):
        minimal = self._getTemplatePath('minimal.pt')
        lookup = DummyLookup()
@@ -60,7 +58,6 @@
        self.assertEqual(result.rstrip('\n'),
                     '<div xmlns="http://www.w3.org/1999/xhtml">\n</div>')
    @skip_on('java')
    def test_template_reified(self):
        minimal = self._getTemplatePath('minimal.pt')
        lookup = DummyLookup()
@@ -69,7 +66,6 @@
        template  = instance.template
        self.assertEqual(template, instance.__dict__['template'])
    @skip_on('java')
    def test_template_with_ichameleon_translate(self):
        minimal = self._getTemplatePath('minimal.pt')
        lookup = DummyLookup()
@@ -78,7 +74,6 @@
        template  = instance.template
        self.assertEqual(template.translate, lookup.translate)
    @skip_on('java')
    def test_template_with_debug_templates(self):
        minimal = self._getTemplatePath('minimal.pt')
        lookup = DummyLookup()
@@ -88,7 +83,6 @@
        template  = instance.template
        self.assertEqual(template.debug, True)
    @skip_on('java')
    def test_template_without_debug_templates(self):
        minimal = self._getTemplatePath('minimal.pt')
        lookup = DummyLookup()
@@ -98,7 +92,6 @@
        template  = instance.template
        self.assertEqual(template.debug, False)
    @skip_on('java')
    def test_template_with_reload_templates(self):
        minimal = self._getTemplatePath('minimal.pt')
        lookup = DummyLookup()
@@ -108,7 +101,6 @@
        template  = instance.template
        self.assertEqual(template.auto_reload, True)
    @skip_on('java')
    def test_template_without_reload_templates(self):
        minimal = self._getTemplatePath('minimal.pt')
        lookup = DummyLookup()
@@ -118,14 +110,12 @@
        template  = instance.template
        self.assertEqual(template.auto_reload, False)
    @skip_on('java')
    def test_call_with_nondict_value(self):
        minimal = self._getTemplatePath('minimal.pt')
        lookup = DummyLookup()
        instance = self._makeOne(minimal, lookup)
        self.assertRaises(ValueError, instance, None, {})
    @skip_on('java')
    def test_implementation(self):
        minimal = self._getTemplatePath('minimal.pt')
        lookup = DummyLookup()
@@ -142,8 +132,13 @@
        result = instance.implementation()()
        self.assertEqual(result, '\n  Hello!\n')
        
    def test_macro_notsupplied(self):
        minimal = self._getTemplatePath('withmacro.pt')
        lookup = DummyLookup()
        instance = self._makeOne(minimal, lookup)
        result = instance.implementation()()
        self.assertEqual(result,
                         '<html>\nOutside macro\n\n  Hello!\n\n</html>\n\n')
class DummyLookup(object):
    auto_reload=True
pyramid/tests/test_config/test_init.py
@@ -923,12 +923,13 @@
        result = render_view_to_response(ctx, req, 'another_stacked_class2')
        self.assertEqual(result, 'another_stacked_class')
        if not os.name.startswith('java'):
            # on Jython, a class without an __init__ apparently accepts
            # any number of arguments without raising a TypeError.
        # NB: on Jython, a class without an __init__ apparently accepts
        # any number of arguments without raising a TypeError, so the next
        # assertion may fail there.  We don't support Jython at the moment,
        # this is just a note to a future self.
            self.assertRaises(TypeError,
                              render_view_to_response, ctx, req, 'basemethod')
        self.assertRaises(TypeError,
                          render_view_to_response, ctx, req, 'basemethod')
        result = render_view_to_response(ctx, req, 'method1')
        self.assertEqual(result, 'method1')
pyramid/tests/test_config/test_predicates.py
@@ -256,6 +256,49 @@
        inst = self._makeOne('/abc')
        self.assertEqual(inst.phash(), '')
class Test_CheckCSRFTokenPredicate(unittest.TestCase):
    def _makeOne(self, val, config):
        from pyramid.config.predicates import CheckCSRFTokenPredicate
        return CheckCSRFTokenPredicate(val, config)
    def test_text(self):
        inst = self._makeOne(True, None)
        self.assertEqual(inst.text(), 'check_csrf = True')
    def test_phash(self):
        inst = self._makeOne(True, None)
        self.assertEqual(inst.phash(), 'check_csrf = True')
    def test_it_call_val_True(self):
        inst = self._makeOne(True, None)
        request = Dummy()
        def check_csrf_token(req, val, raises=True):
            self.assertEqual(req, request)
            self.assertEqual(val, 'csrf_token')
            self.assertEqual(raises, False)
            return True
        inst.check_csrf_token  = check_csrf_token
        result = inst(None, request)
        self.assertEqual(result, True)
    def test_it_call_val_str(self):
        inst = self._makeOne('abc', None)
        request = Dummy()
        def check_csrf_token(req, val, raises=True):
            self.assertEqual(req, request)
            self.assertEqual(val, 'abc')
            self.assertEqual(raises, False)
            return True
        inst.check_csrf_token  = check_csrf_token
        result = inst(None, request)
        self.assertEqual(result, True)
    def test_it_call_val_False(self):
        inst = self._makeOne(False, None)
        request = Dummy()
        result = inst(None, request)
        self.assertEqual(result, True)
class predicate(object):
    def __repr__(self):
        return 'predicate'
pyramid/tests/test_config/test_testing.py
@@ -23,6 +23,30 @@
        self.assertEqual(ut.groupids, ('group1', 'group2'))
        self.assertEqual(ut.permissive, False)
    def test_testing_securitypolicy_remember_result(self):
        from pyramid.security import remember
        config = self._makeOne(autocommit=True)
        pol = config.testing_securitypolicy(
            'user', ('group1', 'group2'),
            permissive=False, remember_result=True)
        request = DummyRequest()
        request.registry = config.registry
        val = remember(request, 'fred')
        self.assertEqual(pol.remembered, 'fred')
        self.assertEqual(val, True)
    def test_testing_securitypolicy_forget_result(self):
        from pyramid.security import forget
        config = self._makeOne(autocommit=True)
        pol = config.testing_securitypolicy(
            'user', ('group1', 'group2'),
            permissive=False, forget_result=True)
        request = DummyRequest()
        request.registry = config.registry
        val = forget(request)
        self.assertEqual(pol.forgotten, True)
        self.assertEqual(val, True)
    def test_testing_resources(self):
        from pyramid.traversal import find_resource
        from pyramid.interfaces import ITraverser
pyramid/tests/test_integration.py
@@ -578,26 +578,49 @@
        res = self.testapp.get('/hello', status=200)
        self.assertTrue(b'Hello' in res.body)
if os.name != 'java': # uses chameleon
    class RendererScanAppTest(IntegrationBase, unittest.TestCase):
        package = 'pyramid.tests.pkgs.rendererscanapp'
        def test_root(self):
            res = self.testapp.get('/one', status=200)
            self.assertTrue(b'One!' in res.body)
class SubrequestAppTest(unittest.TestCase):
    def setUp(self):
        from pyramid.tests.pkgs.subrequestapp import main
        config = main()
        app = config.make_wsgi_app()
        from webtest import TestApp
        self.testapp = TestApp(app)
        self.config = config
        def test_two(self):
            res = self.testapp.get('/two', status=200)
            self.assertTrue(b'Two!' in res.body)
    def tearDown(self):
        self.config.end()
        def test_rescan(self):
            self.config.scan('pyramid.tests.pkgs.rendererscanapp')
            app = self.config.make_wsgi_app()
            from webtest import TestApp
            testapp = TestApp(app)
            res = testapp.get('/one', status=200)
            self.assertTrue(b'One!' in res.body)
            res = testapp.get('/two', status=200)
            self.assertTrue(b'Two!' in res.body)
    def test_one(self):
        res = self.testapp.get('/view_one', status=200)
        self.assertTrue(b'This came from view_two' in res.body)
    def test_three(self):
        res = self.testapp.get('/view_three', status=500)
        self.assertTrue(b'Bad stuff happened' in res.body)
    def test_five(self):
        res = self.testapp.get('/view_five', status=200)
        self.assertTrue(b'Value error raised' in res.body)
class RendererScanAppTest(IntegrationBase, unittest.TestCase):
    package = 'pyramid.tests.pkgs.rendererscanapp'
    def test_root(self):
        res = self.testapp.get('/one', status=200)
        self.assertTrue(b'One!' in res.body)
    def test_two(self):
        res = self.testapp.get('/two', status=200)
        self.assertTrue(b'Two!' in res.body)
    def test_rescan(self):
        self.config.scan('pyramid.tests.pkgs.rendererscanapp')
        app = self.config.make_wsgi_app()
        from webtest import TestApp
        testapp = TestApp(app)
        res = testapp.get('/one', status=200)
        self.assertTrue(b'One!' in res.body)
        res = testapp.get('/two', status=200)
        self.assertTrue(b'Two!' in res.body)
class DummyContext(object):
    pass
pyramid/tests/test_mako_templating.py
@@ -31,6 +31,20 @@
        from pyramid.mako_templating import IMakoLookup
        return self.config.registry.getUtility(IMakoLookup, name=name)
    def test_hyphen_filenames(self):
        from pyramid.mako_templating import renderer_factory
        info = DummyRendererInfo({
            'name':'app:moon-and-world.mak',
            'package':None,
            'registry':self.config.registry,
            'settings':{},
            'type': ''
        })
        result = renderer_factory(info)
        self.assertEqual(result.path, 'app:moon-and-world.mak')
    def test_no_directories(self):
        info = DummyRendererInfo({
            'name':'pyramid.tests:fixtures/helloworld.mak',
pyramid/tests/test_renderers.py
@@ -295,6 +295,7 @@
        self.assertEqual(factory.kw, {'macro':None})
    def test___call__spec_withmacro(self):
        from pyramid.interfaces import ITemplateRenderer
        import os
        from pyramid import tests
        module_name = tests.__name__
@@ -302,10 +303,11 @@
        renderer = {}
        factory = DummyFactory(renderer)
        spec = '%s:%s' % (module_name, relpath)
        reg = self.config.registry
        info = DummyRendererInfo({
            'name':spec,
            'package':None,
            'registry':self.config.registry,
            'registry':reg,
            'settings':{},
            'type':'type',
            })
@@ -318,6 +320,9 @@
            'withmacro.pt')
        self.assertTrue(factory.path.startswith(path))
        self.assertEqual(factory.kw, {'macro':'foo'})
        self.assertTrue(
            reg.getUtility(ITemplateRenderer, name=spec) is renderer
            )
    def test___call__reload_assets_true(self):
        import pyramid.tests
pyramid/tests/test_scripting.py
@@ -72,7 +72,7 @@
        self.assertEqual(self.default, self.manager.get())
        self.assertEqual(request.context, root)
    def test_it_withrequest(self):
    def test_it_withrequest_hasregistry(self):
        request = DummyRequest({})
        registry = request.registry = self._makeRegistry()
        info = self._callFUT(request=request)
@@ -85,6 +85,17 @@
        closer()
        self.assertEqual(self.default, self.manager.get())
        self.assertEqual(request.context, root)
        self.assertEqual(request.registry, registry)
    def test_it_withrequest_noregistry(self):
        request = DummyRequest({})
        registry = self._makeRegistry()
        info = self._callFUT(request=request, registry=registry)
        root, closer, request = info['root'], info['closer'], info['request']
        closer()
        self.assertEqual(request.context, root)
        # should be set by prepare
        self.assertEqual(request.registry, registry)
    def test_it_with_request_and_registry(self):
        request = DummyRequest({})
pyramid/tests/test_session.py
@@ -355,6 +355,31 @@
        serialized = 'bad' + serialize('123', 'secret')
        self.assertRaises(ValueError, self._callFUT, serialized, 'secret')
        
class Test_check_csrf_token(unittest.TestCase):
    def _callFUT(self, request, token, raises=True):
        from ..session import check_csrf_token
        return check_csrf_token(request, token, raises=raises)
    def test_success(self):
        request = testing.DummyRequest()
        request.params['csrf_token'] = request.session.get_csrf_token()
        self.assertEqual(self._callFUT(request, 'csrf_token'), True)
    def test_success_default_token(self):
        from ..session import check_csrf_token
        request = testing.DummyRequest()
        request.params['csrf_token'] = request.session.get_csrf_token()
        self.assertEqual(check_csrf_token(request), True)
    def test_failure_raises(self):
        from pyramid.httpexceptions import HTTPBadRequest
        request = testing.DummyRequest()
        self.assertRaises(HTTPBadRequest, self._callFUT, request, 'csrf_token')
    def test_failure_no_raises(self):
        request = testing.DummyRequest()
        result = self._callFUT(request, 'csrf_token', raises=False)
        self.assertEqual(result, False)
class DummySessionFactory(dict):
    _dirty = False
pyramid/tests/test_testing.py
@@ -646,3 +646,58 @@
    def __init__(self, kw):
        self.__dict__.update(kw)
        
class Test_testConfig(unittest.TestCase):
    def _setUp(self, **kw):
        self._log.append(('setUp', kw))
        return 'fake config'
    def _tearDown(self, **kw):
        self._log.append(('tearDown', kw))
    def setUp(self):
        from pyramid import testing
        self._log = []
        self._orig_setUp = testing.setUp
        testing.setUp = self._setUp
        self._orig_tearDown = testing.tearDown
        testing.tearDown = self._tearDown
    def tearDown(self):
        from pyramid import testing
        testing.setUp = self._orig_setUp
        testing.tearDown = self._orig_tearDown
    def _callFUT(self, inner, **kw):
        from pyramid.testing import testConfig
        with testConfig(**kw) as config:
            inner(config)
    def test_ok_calls(self):
        self.assertEqual(self._log, [])
        def inner(config):
            self.assertEqual(self._log,
                    [('setUp',
                        {'autocommit': True,
                            'hook_zca': True,
                            'registry': None,
                            'request': None,
                            'settings': None})])
            self._log.pop()
        self._callFUT(inner)
        self.assertEqual(self._log,
                [('tearDown', {'unhook_zca': True})])
    def test_teardown_called_on_exception(self):
        class TestException(Exception):
            pass
        def inner(config):
            self._log = []
            raise TestException('oops')
        self.assertRaises(TestException, self._callFUT, inner)
        self.assertEqual(self._log[0][0], 'tearDown')
    def test_ok_get_config(self):
        def inner(config):
            self.assertEqual(config, 'fake config')
        self._callFUT(inner)
pyramid/view.py
@@ -170,7 +170,7 @@
    ``request_type``, ``route_name``, ``request_method``, ``request_param``,
    ``containment``, ``xhr``, ``accept``, ``header``, ``path_info``,
    ``custom_predicates``, ``decorator``, ``mapper``, ``http_cache``,
    ``match_param``, and ``predicates``.
    ``match_param``, ``csrf_token``, and ``predicates``.
    The meanings of these arguments are the same as the arguments passed to
    :meth:`pyramid.config.Configurator.add_view`.  If any argument is left
setup.py
@@ -68,7 +68,7 @@
    ]
setup(name='pyramid',
      version='1.4dev',
      version='1.4a2',
      description=('The Pyramid web application development framework, a '
                   'Pylons project'),
      long_description=README + '\n\n' +  CHANGES,