summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/Makefile9
m---------docs/_themes0
-rw-r--r--docs/api.rst41
-rw-r--r--docs/api/config.rst1
-rw-r--r--docs/api/paster.rst2
-rw-r--r--docs/api/registry.rst9
-rw-r--r--docs/api/request.rst12
-rw-r--r--docs/authorintro.rst4
-rw-r--r--docs/conf.py55
-rw-r--r--docs/conventions.rst33
-rw-r--r--docs/copyright.rst2
-rw-r--r--docs/designdefense.rst24
-rw-r--r--docs/foreword.rst2
-rw-r--r--docs/glossary.rst71
-rw-r--r--docs/index.rst119
-rw-r--r--docs/latexindex.rst46
-rw-r--r--docs/narr/MyProject/myproject/templates/mytemplate.pt4
-rw-r--r--docs/narr/MyProject/setup.py6
-rw-r--r--docs/narr/advconfig.rst12
-rw-r--r--docs/narr/assets.rst12
-rw-r--r--docs/narr/commandline.rst95
-rw-r--r--docs/narr/configuration.rst1
-rw-r--r--docs/narr/environment.rst12
-rw-r--r--docs/narr/events.rst93
-rw-r--r--docs/narr/extconfig.rst8
-rw-r--r--docs/narr/extending.rst8
-rw-r--r--docs/narr/firstapp.rst13
-rw-r--r--docs/narr/hooks.rst87
-rw-r--r--docs/narr/i18n.rst79
-rw-r--r--docs/narr/install.rst361
-rw-r--r--docs/narr/introduction.rst17
-rw-r--r--docs/narr/introspector.rst6
-rw-r--r--docs/narr/logging.rst51
-rw-r--r--docs/narr/muchadoabouttraversal.rst18
-rw-r--r--docs/narr/paste.rst6
-rw-r--r--docs/narr/project.rst73
-rw-r--r--docs/narr/renderers.rst29
-rw-r--r--docs/narr/resources.rst4
-rw-r--r--docs/narr/router.rst2
-rw-r--r--docs/narr/scaffolding.rst12
-rw-r--r--docs/narr/security.rst43
-rw-r--r--docs/narr/sessions.rst154
-rw-r--r--docs/narr/startup.rst10
-rw-r--r--docs/narr/subrequest.rst12
-rw-r--r--docs/narr/templates.rst13
-rw-r--r--docs/narr/testing.rst31
-rw-r--r--docs/narr/threadlocals.rst5
-rw-r--r--docs/narr/traversal.rst29
-rw-r--r--docs/narr/upgrading.rst2
-rw-r--r--docs/narr/urldispatch.rst66
-rw-r--r--docs/narr/viewconfig.rst105
-rw-r--r--docs/narr/views.rst60
-rw-r--r--docs/narr/webob.rst8
-rw-r--r--docs/narr/zca.rst12
-rw-r--r--docs/quick_tour.rst860
-rw-r--r--docs/quick_tour/awesome/CHANGES.txt4
-rw-r--r--docs/quick_tour/awesome/MANIFEST.in2
-rw-r--r--docs/quick_tour/awesome/README.txt4
-rw-r--r--docs/quick_tour/awesome/awesome/__init__.py23
-rw-r--r--docs/quick_tour/awesome/awesome/locale/awesome.pot21
-rw-r--r--docs/quick_tour/awesome/awesome/locale/de/LC_MESSAGES/awesome.mobin0 -> 460 bytes
-rw-r--r--docs/quick_tour/awesome/awesome/locale/de/LC_MESSAGES/awesome.po21
-rw-r--r--docs/quick_tour/awesome/awesome/locale/fr/LC_MESSAGES/awesome.mobin0 -> 461 bytes
-rw-r--r--docs/quick_tour/awesome/awesome/locale/fr/LC_MESSAGES/awesome.po21
-rw-r--r--docs/quick_tour/awesome/awesome/models.py8
-rw-r--r--docs/quick_tour/awesome/awesome/static/favicon.icobin0 -> 1406 bytes
-rw-r--r--docs/quick_tour/awesome/awesome/static/logo.pngbin0 -> 6641 bytes
-rw-r--r--docs/quick_tour/awesome/awesome/static/pylons.css73
-rw-r--r--docs/quick_tour/awesome/awesome/templates/mytemplate.jinja287
-rw-r--r--docs/quick_tour/awesome/awesome/tests.py21
-rw-r--r--docs/quick_tour/awesome/awesome/views.py6
-rw-r--r--docs/quick_tour/awesome/development.ini49
-rw-r--r--docs/quick_tour/awesome/message-extraction.ini3
-rw-r--r--docs/quick_tour/awesome/setup.cfg28
-rw-r--r--docs/quick_tour/awesome/setup.py36
-rw-r--r--docs/quick_tour/hello_world/app.py16
-rw-r--r--docs/quick_tour/jinja2/app.py11
-rw-r--r--docs/quick_tour/jinja2/hello_world.jinja28
-rw-r--r--docs/quick_tour/jinja2/views.py8
-rw-r--r--docs/quick_tour/json/app.py15
-rw-r--r--docs/quick_tour/json/hello_world.jinja210
-rw-r--r--docs/quick_tour/json/hello_world.pt17
-rw-r--r--docs/quick_tour/json/views.py13
-rw-r--r--docs/quick_tour/package/CHANGES.txt4
-rw-r--r--docs/quick_tour/package/MANIFEST.in2
-rw-r--r--docs/quick_tour/package/README.txt4
-rw-r--r--docs/quick_tour/package/development.ini54
-rw-r--r--docs/quick_tour/package/hello_world/__init__.py34
-rw-r--r--docs/quick_tour/package/hello_world/init.py34
-rw-r--r--docs/quick_tour/package/hello_world/locale/de/LC_MESSAGES/hello_world.mobin0 -> 460 bytes
-rw-r--r--docs/quick_tour/package/hello_world/locale/de/LC_MESSAGES/hello_world.po21
-rw-r--r--docs/quick_tour/package/hello_world/locale/fr/LC_MESSAGES/hello_world.mobin0 -> 461 bytes
-rw-r--r--docs/quick_tour/package/hello_world/locale/fr/LC_MESSAGES/hello_world.po21
-rw-r--r--docs/quick_tour/package/hello_world/locale/hello_world.pot21
-rw-r--r--docs/quick_tour/package/hello_world/models.py8
-rw-r--r--docs/quick_tour/package/hello_world/static/favicon.icobin0 -> 1406 bytes
-rw-r--r--docs/quick_tour/package/hello_world/static/logo.pngbin0 -> 6641 bytes
-rw-r--r--docs/quick_tour/package/hello_world/static/pylons.css73
-rw-r--r--docs/quick_tour/package/hello_world/templates/mytemplate.jinja290
-rw-r--r--docs/quick_tour/package/hello_world/tests.py20
-rw-r--r--docs/quick_tour/package/hello_world/views.py22
-rw-r--r--docs/quick_tour/package/message-extraction.ini3
-rw-r--r--docs/quick_tour/package/setup.cfg28
-rw-r--r--docs/quick_tour/package/setup.py41
-rw-r--r--docs/quick_tour/requests/app.py24
-rw-r--r--docs/quick_tour/routing/app.py12
-rw-r--r--docs/quick_tour/routing/views.py10
-rw-r--r--docs/quick_tour/sqla_demo/CHANGES.txt4
-rw-r--r--docs/quick_tour/sqla_demo/MANIFEST.in2
-rw-r--r--docs/quick_tour/sqla_demo/README.txt14
-rw-r--r--docs/quick_tour/sqla_demo/development.ini71
-rw-r--r--docs/quick_tour/sqla_demo/production.ini62
-rw-r--r--docs/quick_tour/sqla_demo/setup.cfg27
-rw-r--r--docs/quick_tour/sqla_demo/setup.py44
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo.sqlitebin0 -> 3072 bytes
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/__init__.py20
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/models.py29
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/scripts/__init__.py1
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/scripts/initializedb.py37
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/static/favicon.icobin0 -> 1406 bytes
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/static/footerbg.pngbin0 -> 333 bytes
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/static/headerbg.pngbin0 -> 203 bytes
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/static/ie6.css8
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/static/middlebg.pngbin0 -> 2797 bytes
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/static/pylons.css372
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/static/pyramid-small.pngbin0 -> 7044 bytes
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/static/pyramid.pngbin0 -> 33055 bytes
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/static/transparent.gifbin0 -> 49 bytes
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.pt76
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/tests.py33
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/views.py37
-rw-r--r--docs/quick_tour/static_assets/app.py14
-rw-r--r--docs/quick_tour/static_assets/hello_world.jinja210
-rw-r--r--docs/quick_tour/static_assets/hello_world.pt16
-rw-r--r--docs/quick_tour/static_assets/static/app.css4
-rw-r--r--docs/quick_tour/static_assets/views.py6
-rw-r--r--docs/quick_tour/templating/app.py10
-rw-r--r--docs/quick_tour/templating/hello_world.pt9
-rw-r--r--docs/quick_tour/templating/views.py8
-rw-r--r--docs/quick_tour/view_classes/app.py13
-rw-r--r--docs/quick_tour/view_classes/delete.jinja29
-rw-r--r--docs/quick_tour/view_classes/edit.jinja29
-rw-r--r--docs/quick_tour/view_classes/hello.jinja217
-rw-r--r--docs/quick_tour/view_classes/views.py32
-rw-r--r--docs/quick_tour/views/app.py13
-rw-r--r--docs/quick_tour/views/views.py29
-rw-r--r--docs/tutorials/bfg/index.rst8
-rw-r--r--docs/tutorials/modwsgi/index.rst8
-rw-r--r--docs/tutorials/wiki/NOTE-relocatable.txt2
-rw-r--r--docs/tutorials/wiki/authorization.rst64
-rw-r--r--docs/tutorials/wiki/basiclayout.rst2
-rw-r--r--docs/tutorials/wiki/definingviews.rst2
-rw-r--r--docs/tutorials/wiki/distributing.rst4
-rw-r--r--docs/tutorials/wiki/installation.rst24
-rw-r--r--docs/tutorials/wiki/src/authorization/setup.py6
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt4
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt4
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt7
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt4
-rw-r--r--docs/tutorials/wiki/src/basiclayout/setup.py6
-rw-r--r--docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt7
-rw-r--r--docs/tutorials/wiki/src/models/setup.py6
-rw-r--r--docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt7
-rw-r--r--docs/tutorials/wiki/src/models/tutorial/tests.py2
-rw-r--r--docs/tutorials/wiki/src/tests/setup.py6
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt4
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/login.pt4
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt7
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/view.pt4
-rw-r--r--docs/tutorials/wiki/src/views/setup.py6
-rw-r--r--docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt4
-rw-r--r--docs/tutorials/wiki/tests.rst10
-rw-r--r--docs/tutorials/wiki2/authorization.rst8
-rw-r--r--docs/tutorials/wiki2/basiclayout.rst30
-rw-r--r--docs/tutorials/wiki2/definingmodels.rst11
-rw-r--r--docs/tutorials/wiki2/definingviews.rst52
-rw-r--r--docs/tutorials/wiki2/design.rst8
-rw-r--r--docs/tutorials/wiki2/distributing.rst4
-rw-r--r--docs/tutorials/wiki2/installation.rst208
-rw-r--r--docs/tutorials/wiki2/src/authorization/README.txt6
-rw-r--r--docs/tutorials/wiki2/src/authorization/setup.py6
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt4
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/README.txt6
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/setup.py6
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt7
-rw-r--r--docs/tutorials/wiki2/src/models/README.txt6
-rw-r--r--docs/tutorials/wiki2/src/models/setup.py6
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt7
-rw-r--r--docs/tutorials/wiki2/src/tests/README.txt6
-rw-r--r--docs/tutorials/wiki2/src/tests/setup.py6
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/templates/edit.pt4
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/templates/login.pt4
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/templates/mytemplate.pt7
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/templates/view.pt4
-rw-r--r--docs/tutorials/wiki2/src/views/README.txt6
-rw-r--r--docs/tutorials/wiki2/src/views/setup.py6
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt4
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt7
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/templates/view.pt4
-rw-r--r--docs/tutorials/wiki2/tests.rst10
-rw-r--r--docs/whatsnew-1.0.rst2
-rw-r--r--docs/whatsnew-1.1.rst15
-rw-r--r--docs/whatsnew-1.2.rst20
-rw-r--r--docs/whatsnew-1.3.rst26
-rw-r--r--docs/whatsnew-1.4.rst11
-rw-r--r--docs/whatsnew-1.5.rst158
206 files changed, 4549 insertions, 1254 deletions
diff --git a/docs/Makefile b/docs/Makefile
index c98fdc65e..12dc88bf8 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -63,8 +63,13 @@ latex:
cp _static/latex-note.png _build/latex
@echo
@echo "Build finished; the LaTeX files are in _build/latex."
- @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
- "run these through (pdf)latex."
+ @echo "Run \`make latexpdf' to build a PDF file from them."
+
+latexpdf:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
+ @echo "Running LaTeX files through pdflatex..."
+ $(MAKE) -C _build/latex all-pdf
+ @echo "pdflatex finished; the PDF file is in _build/latex."
changes:
mkdir -p _build/changes _build/doctrees
diff --git a/docs/_themes b/docs/_themes
-Subproject f59f7bfce5259f50fbb67b9040c03ecb080130b
+Subproject a181b85d4ca08fa109ee2786d4f1b5b17e9b458
diff --git a/docs/api.rst b/docs/api.rst
deleted file mode 100644
index 9e540b49b..000000000
--- a/docs/api.rst
+++ /dev/null
@@ -1,41 +0,0 @@
-API Documentation
-=================
-
-Comprehensive reference material for every public API exposed by
-:app:`Pyramid` is available within this chapter. The API
-documentation is organized alphabetically by module name.
-
-.. toctree::
- :maxdepth: 1
-
- api/authorization
- api/authentication
- api/compat
- api/config
- api/decorator
- api/events
- api/exceptions
- api/httpexceptions
- api/i18n
- api/interfaces
- api/location
- api/paster
- api/path
- api/registry
- api/renderers
- api/request
- api/response
- api/scaffolds
- api/scripting
- api/security
- api/session
- api/settings
- api/static
- api/testing
- api/threadlocal
- api/traversal
- api/tweens
- api/url
- api/view
- api/wsgi
-
diff --git a/docs/api/config.rst b/docs/api/config.rst
index 39d504348..1f65be9f1 100644
--- a/docs/api/config.rst
+++ b/docs/api/config.rst
@@ -135,3 +135,4 @@
will only exist for the lifetime of the actual applications for which they
are being used.
+.. autoclass:: not_
diff --git a/docs/api/paster.rst b/docs/api/paster.rst
index bde128e05..edc3738fc 100644
--- a/docs/api/paster.rst
+++ b/docs/api/paster.rst
@@ -9,6 +9,6 @@
.. autofunction:: get_app(config_uri, name=None, options=None)
- .. autofunction:: get_appsettings(config_uri, name=None)
+ .. autofunction:: get_appsettings(config_uri, name=None, options=None)
.. autofunction:: setup_logging(config_uri)
diff --git a/docs/api/registry.rst b/docs/api/registry.rst
index db348495c..7736cf075 100644
--- a/docs/api/registry.rst
+++ b/docs/api/registry.rst
@@ -29,6 +29,15 @@
This attribute is often accessed as ``request.registry.introspector`` in
a typical Pyramid application.
+ .. method:: notify(*events)
+
+ Fire one or more events. All event subscribers to the event(s)
+ will be notified. The subscribers will be called synchronously.
+ This method is often accessed as ``request.registry.notify``
+ in Pyramid applications to fire custom events. See
+ :ref:`custom_events` for more information.
+
+
.. class:: Introspectable
.. versionadded:: 1.3
diff --git a/docs/api/request.rst b/docs/api/request.rst
index 7b843f86e..a90cb1ac0 100644
--- a/docs/api/request.rst
+++ b/docs/api/request.rst
@@ -156,7 +156,7 @@
.. attribute:: matched_route
If a :term:`route` has matched during this request, this attribute will
- be an obect representing the route matched by the URL pattern
+ be an object representing the route matched by the URL pattern
associated with the route. If a route has not matched during this
request, the value of this attribute will be ``None``. See
:ref:`matched_route`.
@@ -190,16 +190,16 @@
: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
+ - causes a :class:`~pyramid.events.NewRequest` event to be sent at the
beginning of request processing.
- - causes a :class:`~pyramid.event.ContextFound` event to be sent
+ - causes a :class:`~pyramid.events.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
+ - causes a :class:`~pyramid.events.NewResponse` event to be sent when
the Pyramid application returns a response.
- Calls any :term:`response callback` functions defined within the
@@ -238,7 +238,7 @@
.. attribute:: response_*
In Pyramid 1.0, you could set attributes on a
- :class:`pyramid.request.Request` which influenced the behavor of
+ :class:`pyramid.request.Request` which influenced the behavior of
*rendered* responses (views which use a :term:`renderer` and which
don't directly return a response). These attributes began with
``response_``, such as ``response_headerlist``. If you needed to
diff --git a/docs/authorintro.rst b/docs/authorintro.rst
index f1a9d1484..ebc6bcff8 100644
--- a/docs/authorintro.rst
+++ b/docs/authorintro.rst
@@ -2,7 +2,7 @@
Author Introduction
=====================
-Welcome to "The :app:`Pyramid` Web Application Framework". In this
+Welcome to "The :app:`Pyramid` Web Framework". In this
introduction, I'll describe the audience for this book, I'll describe
the book content, I'll provide some context regarding the genesis of
:app:`Pyramid`, and I'll thank some important people.
@@ -73,7 +73,7 @@ This book is divided into three major parts:
concepts in terms of the sample. You should read the tutorials if
you want a guided tour of :app:`Pyramid`.
-:ref:`api_reference`
+:ref:`api_documentation`
Comprehensive reference material for every public API exposed by
:app:`Pyramid`. The API documentation is organized
diff --git a/docs/conf.py b/docs/conf.py
index 8d22d4d42..a7a4a441a 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -19,6 +19,8 @@ import warnings
warnings.simplefilter('ignore', DeprecationWarning)
+import pkg_resources
+
# skip raw nodes
from sphinx.writers.text import TextTranslator
from sphinx.writers.latex import LaTeXTranslator
@@ -55,14 +57,39 @@ extensions = [
# Looks for objects in external projects
intersphinx_mapping = {
- 'who': ('http://docs.repoze.org/who/2.0', None),
- 'python': ('http://docs.python.org', None),
- 'python3': ('http://docs.python.org/3', None),
- 'tstring':
+ 'tutorials': ('http://docs.pylonsproject.org/projects/pyramid_tutorials/en/latest/', None),
+ 'jinja2': ('http://docs.pylonsproject.org/projects/pyramid_jinja2/en/latest/', None),
+ 'tm': (
+ 'http://docs.pylonsproject.org/projects/pyramid_tm/en/latest/',
+ None,
+ ),
+ 'zcomponent': ('http://docs.zope.org/zope.component', None),
+ 'webtest': ('http://webtest.pythonpaste.org/en/latest', None),
+ 'webob': ('http://docs.webob.org/en/latest', None),
+ 'colander': (
+ 'http://docs.pylonsproject.org/projects/colander/en/latest',
+ None),
+ 'deform': (
+ 'http://docs.pylonsproject.org/projects/deform/en/latest',
+ None),
+ 'sqla': ('http://docs.sqlalchemy.org/en/latest', None),
+ 'beaker': (
+ 'http://docs.pylonsproject.org/projects/pyramid_beaker/en/latest',
+ None),
+ 'who': ('http://docs.repoze.org/who/latest', None),
+ 'python': ('http://docs.python.org', None),
+ 'python3': ('http://docs.python.org/3', None),
+ 'tstring':
('http://docs.pylonsproject.org/projects/translationstring/en/latest',
None),
- 'venusian':
+ 'venusian':
('http://docs.pylonsproject.org/projects/venusian/en/latest', None),
+ 'toolbar':
+ ('http://docs.pylonsproject.org/projects/pyramid_debugtoolbar/en/latest',
+ None),
+ 'zcml':
+ ('http://docs.pylonsproject.org/projects/pyramid_zcml/en/latest',
+ None),
}
# Add any paths that contain templates here, relative to this directory.
@@ -75,7 +102,7 @@ source_suffix = '.rst'
master_doc = 'index'
# General substitutions.
-project = 'The Pyramid Web Application Development Framework'
+project = 'The Pyramid Web Framework'
thisyear = datetime.datetime.now().year
copyright = '2008-%s, Agendaless Consulting' % thisyear
@@ -83,7 +110,7 @@ copyright = '2008-%s, Agendaless Consulting' % thisyear
# other places throughout the built documents.
#
# The short X.Y version.
-version = '1.4'
+version = pkg_resources.get_distribution('pyramid').version
# The full version, including alpha/beta/rc tags.
release = version
@@ -160,7 +187,7 @@ html_theme_path = ['_themes']
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
@@ -169,7 +196,7 @@ html_theme_options = dict(
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
-html_title = 'The Pyramid Web Application Development Framework v%s' % release
+html_title = 'The Pyramid Web Framework v%s' % release
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = 'Home'
@@ -194,7 +221,7 @@ html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
-#html_use_smartypants = True
+html_use_smartypants = False # people use cutnpaste in some places
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
@@ -241,7 +268,7 @@ latex_additional_files = ['_static/latex-note.png', '_static/latex-warning.png']
# (source start file, target name, title, author, document class [howto/manual]).
latex_documents = [
('latexindex', 'pyramid.tex',
- 'The Pyramid Web Application Development Framework',
+ 'The Pyramid Web Framework',
'Chris McDonough', 'manual'),
]
@@ -376,7 +403,7 @@ latex_elements = {
'wrapperclass': 'book',
'date': '',
'releasename': 'Version',
- 'title': r'The Pyramid Web Application \newline Development Framework',
+ 'title': r'The Pyramid Web Framework',
# 'pointsize':'12pt', # uncomment for 12pt version
}
@@ -481,7 +508,7 @@ def resig(app, what, name, obj, options, signature, return_annotation):
# -- Options for Epub output ---------------------------------------------------
# Bibliographic Dublin Core info.
-epub_title = 'The Pyramid Web Application Development Framework, Version %s' \
+epub_title = 'The Pyramid Web Framework, Version %s' \
% release
epub_author = 'Chris McDonough'
epub_publisher = 'Agendaless Consulting'
@@ -499,7 +526,7 @@ epub_scheme = 'ISBN'
epub_identifier = '0615445675'
# A unique identification for the text.
-epub_uid = 'The Pyramid Web Application Development Framework, Version %s' \
+epub_uid = 'The Pyramid Web Framework, Version %s' \
% release
# HTML files that should be inserted before the pages created by sphinx.
# The format is a list of tuples containing the path and title.
diff --git a/docs/conventions.rst b/docs/conventions.rst
index 0c38e11d8..21b506623 100644
--- a/docs/conventions.rst
+++ b/docs/conventions.rst
@@ -55,21 +55,25 @@ character, e.g.:
.. code-block:: text
- $ ../bin/nosetests
+ $ $VENV/bin/nosetests
+
+(See :term:`virtualenv` for the meaning of ``$VENV``)
Example blocks representing Windows ``cmd.exe`` commands are prefixed with a
drive letter and/or a directory name, e.g.:
.. code-block:: text
- c:\examples> ..\Scripts\nosetests
+ c:\examples> %VENV%\Scripts\nosetests
+
+(See :term:`virtualenv` for the meaning of ``%VENV%``)
Sometimes, when it's unknown which directory is current, Windows ``cmd.exe``
example block commands are prefixed only with a ``>`` character, e.g.:
.. code-block:: text
- > ..\Scripts\nosetests
+ > %VENV%\Scripts\nosetests
When a command that should be typed on one line is too long to fit on a page,
the backslash ``\`` is used to indicate that the following printed line
@@ -77,7 +81,7 @@ should actually be part of the command:
.. code-block:: text
- c:\bigfntut\tutorial> ..\Scripts\nosetests --cover-package=tutorial \
+ c:\bigfntut\tutorial> %VENV%\Scripts\nosetests --cover-package=tutorial \
--cover-erase --with-coverage
A sidebar, which presents a concept tangentially related to content
@@ -87,3 +91,24 @@ discussed on a page, is rendered like so:
Sidebar information.
+When multiple objects are imported from the same package,
+the following convention is used:
+
+ .. code-block:: python
+
+ from foo import (
+ bar,
+ baz,
+ )
+
+It may look unusual, but it has advantages:
+
+* It allows one to swap out the higher-level package ``foo`` for something
+ else that provides the similar API. An example would be swapping out
+ one Database for another (e.g. graduating from SQLite to PostgreSQL).
+
+* Looks more neat in cases where a large number of objects get imported from
+ that package.
+
+* Adding/removing imported objects from the package is quicker and results
+ in simpler diffs.
diff --git a/docs/copyright.rst b/docs/copyright.rst
index 8f3a5f5e7..980335827 100644
--- a/docs/copyright.rst
+++ b/docs/copyright.rst
@@ -1,7 +1,7 @@
Copyright, Trademarks, and Attributions
=======================================
-*The Pyramid Web Application Development Framework, Version 1.1*
+*The Pyramid Web Framework, Version 1.1*
by Chris McDonough
diff --git a/docs/designdefense.rst b/docs/designdefense.rst
index 69a921498..cebcf6218 100644
--- a/docs/designdefense.rst
+++ b/docs/designdefense.rst
@@ -38,13 +38,13 @@ forking is also a Zope derivative.
Implementations of these features were *required* to allow the :app:`Pyramid`
authors to build the bread-and-butter CMS-type systems for customers in the
-way they were accustomed to building them. No other system, save for Zope itself,
-had such features. And Zope itself was beginning to show signs of its age.
+way in which they were accustomed. No other system, save for Zope itself,
+had such features, and Zope itself was beginning to show signs of its age.
We were becoming hampered by consequences of its early design mistakes.
Zope's lack of documentation was also difficult to work around: it was hard
to hire smart people to work on Zope applications, because there was no
comprehensive documentation set to point them at which explained "it all" in
-one consumble place, and it was too large and self-inconsistent to document
+one consumable place, and it was too large and self-inconsistent to document
properly. Before :mod:`repoze.bfg` went under development, its authors
obviously looked around for other frameworks that fit the bill. But no
non-Zope framework did. So we embarked on building :mod:`repoze.bfg`.
@@ -120,7 +120,6 @@ that uses the ZCA global API is somewhat high. Consider a ZCA neophyte
reading the code that performs a typical "unnamed utility" lookup using the
:func:`zope.component.getUtility` global API:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -190,7 +189,6 @@ special-purpose API functions that *do* use ZCA APIs. Take for example the
present in the current request or ``None`` if no userid is present in the
current request. The application developer calls it like so:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -238,7 +236,7 @@ registry API.
:app:`Pyramid` framework developers were so concerned about conceptual load
issues of the ZCA registry API for framework developers that a `replacement
-registry implementation <http://svn.repoze.org/repoze.component/trunk>`_
+registry implementation <https://github.com/repoze/repoze.component>`_
named :mod:`repoze.component` was actually developed. Though this package
has a registry implementation which is fully functional and well-tested, and
its API is much nicer than the ZCA registry API, work on it was largely
@@ -500,7 +498,6 @@ which match information in an associated "urlconf" such as
Zope, likewise allows you to add arbitrary keyword and positional
arguments to any method of a resource object found via traversal:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -517,7 +514,7 @@ the method is called (if possible) with its argument list filled with values
mentioned therein. TurboGears and Pylons 1.X operate similarly.
Out of the box, :app:`Pyramid` is configured to have none of these features.
-By default, :mod:`pyramid` view callables always accept only ``request`` and
+By default, :app:`Pyramid` view callables always accept only ``request`` and
no other arguments. The rationale: this argument specification matching done
aggressively can be costly, and :app:`Pyramid` has performance as one of its
main goals, so we've decided to make people, by default, obtain information
@@ -1030,7 +1027,7 @@ but its intended userbase is much the same. Many others exist. We've
actually even (only as a teaching tool, not as any sort of official project)
`created one using Pyramid <http://bfg.repoze.org/videos#groundhog1>`_ (the
videos use BFG, a precursor to Pyramid, but the resulting code is `available
-for Pyramid too <http://github.com/Pylons/groundhog>`_). Microframeworks are
+for Pyramid too <https://github.com/Pylons/groundhog>`_). Microframeworks are
small frameworks with one common feature: each allows its users to create a
fully functional application that lives in a single Python file.
@@ -1298,6 +1295,9 @@ predictability.
a registry in another module. This has the effect that
double-registrations will never be performed.
+
+.. _routes_need_ordering:
+
Routes Need Relative Ordering
+++++++++++++++++++++++++++++
@@ -1461,7 +1461,7 @@ code below:
def afunc():
for i in range(10):
- print i
+ print(i)
By its nature, the *request* object created as the result of a WSGI server's
call into a long-lived web framework cannot be global, because the lifetime
@@ -1681,7 +1681,7 @@ was written to address these issues.
If it's Zope3-the-web-framework, Pyramid is *definitely* not that. Making
use of lots of Zope 3 technologies is territory already staked out by the
:term:`Grok` project. Save for the obvious fact that they're both web
-frameworks, :mod:`Pyramid` is very, very different than Grok. Grok exposes
+frameworks, :app:`Pyramid` is very, very different than Grok. Grok exposes
lots of Zope technologies to end users. On the other hand, if you need to
understand a Zope-only concept while using Pyramid, then we've failed on some
very basic axis.
@@ -1694,7 +1694,7 @@ some sort of monolithic thing, and a lot of its software is usable
externally. And while it's not really the job of this document to defend it,
Zope has been around for over 10 years and has an incredibly large, active
community. If you don't believe this,
-http://taichino.appspot.com/pypi_ranking/authors is an eye-opening reality
+http://pypi-ranking.info/author is an eye-opening reality
check.
Love Simplicity
diff --git a/docs/foreword.rst b/docs/foreword.rst
index aa8d7c77b..cc8271bdf 100644
--- a/docs/foreword.rst
+++ b/docs/foreword.rst
@@ -1,3 +1,5 @@
+:orphan:
+
Foreword
========
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 9220e6b5f..8ade889a3 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -18,7 +18,7 @@ Glossary
response
An object returned by a :term:`view callable` that represents response
- data returned to the requesting user agent. It must implements the
+ data returned to the requesting user agent. It must implement the
:class:`pyramid.interfaces.IResponse` interface. A response object is
typically an instance of the :class:`pyramid.response.Response` class or
a subclass such as :class:`pyramid.httpexceptions.HTTPFound`. See
@@ -146,16 +146,19 @@ Glossary
request before it returns a :term:`context` resource.
virtualenv
- An isolated Python environment. Allows you to control which
- packages are used on a particular project by cloning your main
- Python. `virtualenv <http://pypi.python.org/pypi/virtualenv>`_
- was created by Ian Bicking.
+ A term referring both to an isolated Python environment,
+ or `the leading tool <http://www.virtualenv.org>`_ that allows one to
+ create such environments.
+
+ Note: whenever you encounter commands prefixed with ``$VENV`` (Unix)
+ or ``%VENV`` (Windows), know that that is the environment variable whose
+ value is the root of the virtual environment in question.
resource
An object representing a node in the :term:`resource tree` of an
- application. If :mod:`traversal` is used, a resource is an element in
+ application. If :term:`traversal` is used, a resource is an element in
the resource tree traversed by the system. When traversal is used, a
- resource becomes the :term:`context` of a :term:`view`. If :mod:`url
+ resource becomes the :term:`context` of a :term:`view`. If :term:`url
dispatch` is used, a single resource is generated for each request and
is used as the context resource of a view.
@@ -311,7 +314,7 @@ Glossary
pipeline
The :term:`PasteDeploy` term for a single configuration of a WSGI
- server, a WSGI application, with a set of middleware in-between.
+ server, a WSGI application, with a set of :term:`middleware` in-between.
Zope
`The Z Object Publishing Framework <http://zope.org>`_, a
@@ -324,25 +327,19 @@ Glossary
`A full-featured Python web framework <http://djangoproject.com>`_.
Pylons
- `A lightweight Python web framework <http://pylonshq.com>`_ and a
- predecessor of Pyramid.
+ `A lightweight Python web framework <http://docs.pylonsproject.org/projects/pylons-webframework/en/latest/>`_
+ and a predecessor of Pyramid.
ZODB
`Zope Object Database <http://zodb.org>`_, a
persistent Python object store.
- ZEO
- `Zope Enterprise Objects
- <http://www.zope.org/Documentation/Books/ZopeBook/2_6Edition/ZEO.stx>`_
- allows multiple simultaneous processes to access a single
- :term:`ZODB` database.
-
WebOb
`WebOb <http://webob.org>`_ is a WSGI request/response
library created by Ian Bicking.
PasteDeploy
- `PasteDeploy <http://pythonpaste.org>`_ is a library used by
+ `PasteDeploy <http://pythonpaste.org/deploy/>`_ is a library used by
:app:`Pyramid` which makes it possible to configure
:term:`WSGI` components together declaratively within an ``.ini``
file. It was developed by Ian Bicking.
@@ -400,10 +397,9 @@ Glossary
dispatching and other application configuration tasks.
reStructuredText
- A `plain text format <http://docutils.sourceforge.net/rst.html>`_
- that is the defacto standard for descriptive text shipped in
- :term:`distribution` files, and Python docstrings. This
- documentation is authored in ReStructuredText format.
+ A `plain text markup format <http://docutils.sourceforge.net/rst.html>`_
+ that is the defacto standard for documenting Python projects.
+ The Pyramid documentation is written in reStructuredText.
root
The object at which :term:`traversal` begins when :app:`Pyramid`
@@ -618,13 +614,13 @@ Glossary
:term:`configuration decoration` and a :term:`scan` to configure your
Pyramid application.
- Not Found view
+ Not Found View
An :term:`exception view` invoked by :app:`Pyramid` when the developer
explicitly raises a :class:`pyramid.httpexceptions.HTTPNotFound`
exception from within :term:`view` code or :term:`root factory` code,
or when the current request doesn't match any :term:`view
configuration`. :app:`Pyramid` provides a default implementation of a
- not found view; it can be overridden. See
+ Not Found View; it can be overridden. See
:ref:`changing_the_notfound_view`.
Forbidden view
@@ -654,10 +650,9 @@ Glossary
<http://en.wikipedia.org/wiki/Thread_(computer_science)>`_ used by the
application may have a different value for this same "global" variable.
:app:`Pyramid` uses a small number of thread local variables, as
- described in :ref:`threadlocals_chapter`. See also the `threading.local
- documentation
- <http://docs.python.org/library/threading.html#threading.local>`_ for
- more information.
+ described in :ref:`threadlocals_chapter`.
+ See also the :class:`stdlib documentation <threading.local>`
+ for more information.
multidict
An ordered dictionary that can have multiple values for each key. Adds
@@ -685,7 +680,7 @@ Glossary
The C implementation of the Python language. This is the
reference implementation that most people refer to as simply
"Python"; :term:`Jython`, Google's App Engine, and `PyPy
- <http://codespeak.net/pypy/dist/pypy/doc/>`_ are examples of
+ <http://doc.pypy.org/en/latest/>`_ are examples of
non-C based Python implementations.
View Lookup
@@ -703,7 +698,7 @@ Glossary
:app:`Pyramid` runs on GAE.
Venusian
- `Venusian <http://docs.repoze.org/venusian>`_ is a library which
+ :ref:`Venusian` is a library which
allows framework authors to defer decorator actions. Instead of
taking actions when a function (or class) decorator is executed
at import time, the action usually taken by the decorator is
@@ -906,9 +901,9 @@ Glossary
The scaffold has been retired but the demo plays a similar role.
Pyramid Cookbook
- An additional documentation resource for Pyramid which presents topical,
- practical usages of Pyramid available via
- http://docs.pylonsproject.org/ .
+ Additional documentation for Pyramid which presents topical,
+ practical uses of Pyramid:
+ http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest.
distutils
The standard system for packaging and distributing Python packages. See
@@ -931,18 +926,18 @@ Glossary
provide, for example, Pyramid-specific view timing support, bookkeeping
code that examines exceptions before they are returned to the upstream
WSGI application, or a variety of other features. Tweens behave a bit
- like :term:`WSGI` 'middleware' but they have the benefit of running in a
+ like :term:`WSGI` :term:`middleware` but they have the benefit of running in a
context in which they have access to the Pyramid :term:`application
registry` as well as the Pyramid rendering machinery. See
:ref:`registering_tweens`.
pyramid_debugtoolbar
- A Pyramid add on which displays a helpful debug toolbar "on top of" HTML
+ A Pyramid add-on which displays a helpful debug toolbar "on top of" HTML
pages rendered by your application, displaying request, routing, and
database information. :mod:`pyramid_debugtoolbar` is configured into
the ``development.ini`` of all applications which use a Pyramid
:term:`scaffold`. For more information, see
- http://docs.pylonsproject.org/projects/pyramid_debugtoolbar/dev/ .
+ http://docs.pylonsproject.org/projects/pyramid_debugtoolbar/en/latest/.
scaffold
A project template that generates some of the major parts of a Pyramid
@@ -959,7 +954,7 @@ Glossary
console script
A script written to the ``bin`` (on UNIX, or ``Scripts`` on Windows)
- directory of a Python installation or virtualenv as the result of
+ directory of a Python installation or :term:`virtualenv` as the result of
running ``setup.py install`` or ``setup.py develop``.
introspector
@@ -1023,3 +1018,7 @@ Glossary
system. See :ref:`registering_thirdparty_predicates` for more
information.
+ add-on
+ A Python :term:`distribution` that uses Pyramid's extensibility
+ to plug into a Pyramid application and provide extra,
+ configurable services. \ No newline at end of file
diff --git a/docs/index.rst b/docs/index.rst
index d4b7ed492..d2a0008a8 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -1,11 +1,11 @@
.. _index:
-=================================================
-The Pyramid Web Application Development Framework
-=================================================
+=========================
+The Pyramid Web Framework
+=========================
-:app:`Pyramid` is a small, fast, down-to-earth Python web application
-development framework. It is developed as part of the `Pylons Project
+:app:`Pyramid` is a small, fast, down-to-earth Python web framework. It
+is developed as part of the `Pylons Project
<http://docs.pylonsproject.org/>`_. It is licensed under a `BSD-like license
<http://repoze.org/license.html>`_.
@@ -31,21 +31,41 @@ Front Matter
copyright.rst
conventions.rst
-What's New
-==========
+.. _html_getting_started:
+
+Getting Started
+===============
+
+If you are new to Pyramid, we have a few resources that can help you get
+up to speed right away.
.. toctree::
- :maxdepth: 1
+ :hidden:
+
+ quick_tour
+
+* :doc:`quick_tour` goes through the major features in Pyramid, covering
+ a little about a lot.
+
+* To see a minimal Pyramid web application, check out
+ :ref:`firstapp_chapter`.
+
+* For help getting Pyramid set up, try
+ :ref:`installing_chapter`.
+
+* Like learning by example? Visit the official
+ :doc:`wiki tutorial <../tutorials/wiki2/index>` as well as the
+ community-contributed
+ :ref:`Pyramid tutorials <tutorials:pyramid-tutorials>`, which include
+ a :ref:`single file tasks tutorial <tutorials:single-file-tutorial>`.
+
+* Need help? See :ref:`Support and
+ Development <support-and-development>`.
- whatsnew-1.4
- whatsnew-1.3
- whatsnew-1.2
- whatsnew-1.1
- whatsnew-1.0
.. _html_narrative_documentation:
-Narrative documentation
+Narrative Documentation
=======================
Narrative documentation in chapter form explaining how to use
@@ -109,15 +129,18 @@ platforms.
tutorials/bfg/index.rst
tutorials/modwsgi/index.rst
+.. _html_api_documentation:
+
API Documentation
-==================
+=================
-Documentation for every :app:`Pyramid` API.
+Comprehensive reference material for every public API exposed by :app:`Pyramid`:
.. toctree::
- :maxdepth: 2
+ :maxdepth: 1
+ :glob:
- api
+ api/*
Change History
==============
@@ -125,6 +148,12 @@ Change History
.. toctree::
:maxdepth: 1
+ whatsnew-1.5
+ whatsnew-1.4
+ whatsnew-1.3
+ whatsnew-1.2
+ whatsnew-1.1
+ whatsnew-1.0
changes
Design Documents
@@ -135,51 +164,7 @@ Design Documents
designdefense
-Sample Applications
-===================
-
-.. note::
-
- These applications run only on Python 2.x, and so do some of their
- dependencies.
-
-`cluegun <https://github.com/Pylons/cluegun>`_ is a simple pastebin
-application based on Rocky Burt's `ClueBin
-<http://pypi.python.org/pypi/ClueBin/0.2.3>`_. It demonstrates form
-processing, security, and the use of :term:`ZODB` within a :app:`Pyramid`
-application. Check this application out via:
-
-.. code-block:: text
-
- git clone git://github.com/Pylons/cluegun.git
-
-`virginia <https://github.com/Pylons/virginia>`_ is a very simple dynamic
-file rendering application. It is willing to render structured text
-documents, HTML documents, and images from a filesystem directory.
-It's also a good example of :term:`traversal`. An
-earlier version of this application runs the `repoze.org
-<http://repoze.org>`_ website. Check this application out via:
-
-.. code-block:: text
-
- git clone git://github.com/Pylons/virginia.git
-
-`shootout <https://github.com/Pylons/shootout>`_ is an example "idea
-competition" application by Carlos de la Guardia and Lukasz Fidosz. It
-demonstrates :term:`URL dispatch`, simple authentication, integration
-with `SQLAlchemy <http://www.sqlalchemy.org/>`_ and ``pyramid_simpleform``.
-Check this application out of version control via:
-
-.. code-block:: text
-
- git clone git://github.com/Pylons/shootout.git
-
-`KARL <http://karlproject.org>`_ is a moderately-sized application (roughly
-80K lines of Python code) built on top of :app:`Pyramid`. It is an open
-source web system for collaboration, organizational intranets, and knowledge
-management. It provides facilities for wikis, calendars, manuals, searching,
-tagging, commenting, and file uploads. See the `KARL site
-<http://karlproject.org>`_ for download and installation details.
+.. _support-and-development:
Support and Development
=======================
@@ -188,7 +173,7 @@ The `Pylons Project web site <http://pylonsproject.org/>`_ is the main online
source of :app:`Pyramid` support and development information.
To report bugs, use the `issue tracker
-<http://github.com/Pylons/pyramid/issues>`_.
+<https://github.com/Pylons/pyramid/issues>`_.
If you've got questions that aren't answered by this documentation,
contact the `Pylons-discuss maillist
@@ -196,7 +181,7 @@ contact the `Pylons-discuss maillist
IRC channel <irc://irc.freenode.net/#pyramid>`_.
Browse and check out tagged and trunk versions of :app:`Pyramid` via
-the `Pyramid GitHub repository <http://github.com/Pylons/pyramid/>`_.
+the `Pyramid GitHub repository <https://github.com/Pylons/pyramid/>`_.
To check out the trunk via ``git``, use this command:
.. code-block:: text
@@ -215,12 +200,8 @@ Index and Glossary
* :ref:`search`
-.. add glossary, foreword, and latexindex in a hidden toc to avoid warnings
-
.. toctree::
:hidden:
glossary
- foreword.rst
- latexindex.rst
diff --git a/docs/latexindex.rst b/docs/latexindex.rst
index 6bb875f73..eb14f5076 100644
--- a/docs/latexindex.rst
+++ b/docs/latexindex.rst
@@ -1,8 +1,10 @@
+:orphan:
+
.. _latexindex:
-@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
-The :app:`Pyramid` Web Application Framework
-@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
+=========================
+The Pyramid Web Framework
+=========================
.. frontmatter::
@@ -28,8 +30,8 @@ Narrative Documentation
narr/introduction
narr/install
- narr/configuration
narr/firstapp
+ narr/configuration
narr/project
narr/startup
narr/router
@@ -50,6 +52,7 @@ Narrative Documentation
narr/vhosting
narr/testing
narr/resources
+ narr/hellotraversal
narr/muchadoabouttraversal
narr/traversal
narr/security
@@ -60,6 +63,8 @@ Narrative Documentation
narr/extending
narr/advconfig
narr/extconfig
+ narr/scaffolding
+ narr/upgrading
narr/threadlocals
narr/zca
@@ -71,42 +76,21 @@ Tutorials
.. toctree::
:maxdepth: 1
- tutorials/wiki/index.rst
tutorials/wiki2/index.rst
+ tutorials/wiki/index.rst
tutorials/bfg/index.rst
tutorials/modwsgi/index.rst
-.. _api_reference:
+.. _api_documentation:
-API Reference
-@@@@@@@@@@@@@
+API Documentation
+@@@@@@@@@@@@@@@@@
.. toctree::
:maxdepth: 1
+ :glob:
- api/authorization
- api/authentication
- api/config
- api/events
- api/exceptions
- api/httpexceptions
- api/i18n
- api/interfaces
- api/location
- api/paster
- api/registry
- api/renderers
- api/request
- api/response
- api/scripting
- api/security
- api/settings
- api/testing
- api/threadlocal
- api/traversal
- api/url
- api/view
- api/wsgi
+ api/*
.. backmatter::
diff --git a/docs/narr/MyProject/myproject/templates/mytemplate.pt b/docs/narr/MyProject/myproject/templates/mytemplate.pt
index 0bfac946e..0fccba624 100644
--- a/docs/narr/MyProject/myproject/templates/mytemplate.pt
+++ b/docs/narr/MyProject/myproject/templates/mytemplate.pt
@@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>The Pyramid Web Application Development Framework</title>
+ <title>The Pyramid Web Framework</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
@@ -24,7 +24,7 @@
<div class="middle align-center">
<p class="app-welcome">
Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
- the Pyramid web application development framework.
+ the Pyramid Web Framework.
</p>
</div>
</div>
diff --git a/docs/narr/MyProject/setup.py b/docs/narr/MyProject/setup.py
index f24b6984e..6969c73e7 100644
--- a/docs/narr/MyProject/setup.py
+++ b/docs/narr/MyProject/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/narr/advconfig.rst b/docs/narr/advconfig.rst
index ba43f3ea6..1b8e33de3 100644
--- a/docs/narr/advconfig.rst
+++ b/docs/narr/advconfig.rst
@@ -148,14 +148,14 @@ one:
config.add_route(...)
Don't call this function directly with ``config`` as an argument. Instead,
-use :meth:`pyramid.config.Configuration.include`:
+use :meth:`pyramid.config.Configurator.include`:
.. code-block:: python
:linenos:
config.include(add_routes)
-Using :meth:`~pyramid.config.Configuration.include` instead of calling the
+Using :meth:`~pyramid.config.Configurator.include` instead of calling the
function directly provides a modicum of automated conflict resolution, with
the configuration statements you define in the calling code overriding those
of the included function. See also :ref:`automatic_conflict_resolution` and
@@ -333,7 +333,7 @@ his application:
config.add_route(...)
Rather than calling this function directly with ``config`` as an argument.
-Instead, use :meth:`pyramid.config.Configuration.include`:
+Instead, use :meth:`pyramid.config.Configurator.include`:
.. code-block:: python
:linenos:
@@ -343,7 +343,7 @@ Instead, use :meth:`pyramid.config.Configuration.include`:
Using ``include`` rather than calling the function directly will allow
:ref:`automatic_conflict_resolution` to work.
-:meth:`~pyramid.config.Configuration.include` can also accept a :term:`module`
+:meth:`~pyramid.config.Configurator.include` can also accept a :term:`module`
as an argument:
.. code-block:: python
@@ -357,7 +357,7 @@ For this to work properly, the ``myapp`` module must contain a callable with
the special name ``includeme``, which should perform configuration (like the
``add_routes`` callable we showed above as an example).
-:meth:`~pyramid.config.Configuration.include` can also accept a :term:`dotted
+:meth:`~pyramid.config.Configurator.include` can also accept a :term:`dotted
Python name` to a function or a module.
.. note: See :ref:`the_include_tag` for a declarative alternative to
@@ -417,7 +417,7 @@ added in configuration execution order.
More Information
----------------
-For more information, see the article,`"A Whirlwind Tour of Advanced
+For more information, see the article, `"A Whirlwind Tour of Advanced
Configuration Tactics"
<http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/configuration/whirlwind_tour.html>`_,
in the Pyramid Cookbook.
diff --git a/docs/narr/assets.rst b/docs/narr/assets.rst
index 7b620548d..26b3e3a92 100644
--- a/docs/narr/assets.rst
+++ b/docs/narr/assets.rst
@@ -50,7 +50,6 @@ application might address the asset using the :term:`asset specification`
``myapp:templates/some_template.pt`` using that API within a ``views.py``
file inside a ``myapp`` package:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -120,7 +119,7 @@ from the ``/var/www/static`` directory of the computer which runs the
# config is an instance of pyramid.config.Configurator
config.add_static_view(name='static', path='/var/www/static')
-The ``name`` prepresents a URL *prefix*. In order for files that live in the
+The ``name`` represents a URL *prefix*. In order for files that live in the
``path`` directory to be served, a URL that requests one of them must begin
with that prefix. In the example above, ``name`` is ``static``, and ``path``
is ``/var/www/static``. In English, this means that you wish to serve the
@@ -272,7 +271,7 @@ assets which begin with ``mypackage:images`` will be prefixed with
# -> http://example.com/images/logo.png
Using :meth:`~pyramid.request.Request.static_url` in conjunction with a
-:meth:`~pyramid.configuration.Configurator.add_static_view` makes it possible
+:meth:`~pyramid.config.Configurator.add_static_view` makes it possible
to put static media on a separate webserver during production (if the
``name`` argument to :meth:`~pyramid.config.Configurator.add_static_view` is
a URL), while keeping static media package-internal and served by the
@@ -323,7 +322,7 @@ its behavior is almost exactly the same once it's configured.
``add_view`` (at least those without a ``route_name``). A
:class:`~pyramid.static.static_view` static view cannot be made
root-relative when you use traversal unless it's registered as a
- :term:`Not Found view`.
+ :term:`Not Found View`.
To serve files within a directory located on your filesystem at
``/path/to/static/dir`` as the result of a "catchall" route hanging from the
@@ -331,7 +330,6 @@ root that exists at the end of your routing table, create an instance of the
:class:`~pyramid.static.static_view` class inside a ``static.py`` file in
your application root as below.
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -458,7 +456,6 @@ The ``override_asset`` API
An individual call to :meth:`~pyramid.config.Configurator.override_asset`
can override a single asset. For example:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -473,7 +470,6 @@ colon separator in a specification separates the *package name* from the
are not specified, the override attempts to resolve every lookup into a
package from the directory of another package. For example:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -482,7 +478,6 @@ package from the directory of another package. For example:
Individual subdirectories within a package can also be overridden:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -511,7 +506,6 @@ construction file resides (or the ``package`` argument to the
:class:`~pyramid.config.Configurator` class construction).
For example:
-.. ignore-next-block
.. code-block:: python
:linenos:
diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst
index 0a5feafc4..58b9bdd21 100644
--- a/docs/narr/commandline.rst
+++ b/docs/narr/commandline.rst
@@ -32,7 +32,7 @@ Here is an example for a simple view configuration using :term:`traversal`:
.. code-block:: text
:linenos:
- $ ../bin/pviews development.ini#tutorial /FrontPage
+ $ $VENV/bin/pviews development.ini#tutorial /FrontPage
URL = /FrontPage
@@ -56,7 +56,7 @@ A more complex configuration might generate something like this:
.. code-block:: text
:linenos:
- $ ../bin/pviews development.ini#shootout /about
+ $ $VENV/bin/pviews development.ini#shootout /about
URL = /about
@@ -146,7 +146,7 @@ name ``main`` as a section name:
.. code-block:: text
- chrism@thinko env26]$ bin/pshell starter/development.ini#main
+ $ $VENV/bin starter/development.ini#main
Python 2.6.5 (r265:79063, Apr 29 2010, 00:31:32)
[GCC 4.4.3] on linux2
Type "help" for more information.
@@ -172,8 +172,8 @@ name ``main`` as a section name:
The WSGI application that is loaded will be available in the shell as the
``app`` global. Also, if the application that is loaded is the :app:`Pyramid`
-app with no surrounding middleware, the ``root`` object returned by the
-default :term:`root factory`, ``registry``, and ``request`` will be
+app with no surrounding :term:`middleware`, the ``root`` object returned by
+the default :term:`root factory`, ``registry``, and ``request`` will be
available.
You can also simply rely on the ``main`` default section name by omitting any
@@ -181,7 +181,7 @@ hash after the filename:
.. code-block:: text
- chrism@thinko env26]$ bin/pshell starter/development.ini
+ $ $VENV/bin/pshell starter/development.ini
Press ``Ctrl-D`` to exit the interactive shell (or ``Ctrl-Z`` on Windows).
@@ -244,7 +244,7 @@ exposed, and the request is configured to generate urls from the host
.. code-block:: text
- chrism@thinko env26]$ bin/pshell starter/development.ini
+ $ $VENV/bin/pshell starter/development.ini
Python 2.6.5 (r265:79063, Apr 29 2010, 00:31:32)
[GCC 4.4.3] on linux2
Type "help" for more information.
@@ -276,18 +276,17 @@ exposed, and the request is configured to generate urls from the host
IPython or bpython
~~~~~~~~~~~~~~~~~~
-If you have `IPython <http://en.wikipedia.org/wiki/IPython>`_ or
-`bpython <http://bpython-interpreter.org/>`_ or both installed in
+If you have `IPython <http://en.wikipedia.org/wiki/IPython>`_ and/or
+`bpython <http://bpython-interpreter.org/>`_ in
the interpreter you use to invoke the ``pshell`` command, ``pshell`` will
-autodiscover them and use the first respectively found in this order :
+autodiscover and use the first one found, in this order:
IPython, bpython, standard Python interpreter. However you could
specifically invoke one of your choice with the ``-p choice`` or
``--python-shell choice`` option.
.. code-block:: text
- [chrism@vitaminf shellenv]$ ../bin/pshell -p ipython | bpython | python \
- development.ini#MyProject
+ $ $VENV/bin/pshell -p ipython | bpython | python development.ini#MyProject
.. index::
pair: routes; printing
@@ -312,7 +311,7 @@ For example:
.. code-block:: text
:linenos:
- [chrism@thinko MyProject]$ ../bin/proutes development.ini
+ $ $VENV/bin/proutes development.ini
Name Pattern View
---- ------- ----
home / <function my_view>
@@ -321,8 +320,8 @@ For example:
static/ static/*subpath <static_view object>
catchall /*subpath <function static_view>
-``proutes`` generates a table. The table has three columns: a Name
-column, a Pattern column, and a View column. The items listed in the
+``proutes`` generates a table with three columns: *Name*, *Pattern*,
+and *View*. The items listed in the
Name column are route names, the items listed in the Pattern column are route
patterns, and the items listed in the View column are representations of the
view callable that will be invoked when a request matches the associated
@@ -355,7 +354,7 @@ configured without any explicit tweens:
.. code-block:: text
:linenos:
- [chrism@thinko pyramid]$ myenv/bin/ptweens development.ini
+ $ $VENV/bin/ptweens development.ini
"pyramid.tweens" config value NOT set (implicitly ordered tweens used)
Implicit Tween Chain
@@ -373,7 +372,7 @@ explicit tweens defined in its ``development.ini`` file:
.. code-block:: text
:linenos:
- [chrism@thinko pyramid]$ ptweens development.ini
+ $ ptweens development.ini
"pyramid.tweens" config value set (explicitly ordered tweens used)
Explicit Tween Chain (used)
@@ -399,7 +398,7 @@ Here's the application configuration section of the ``development.ini`` used
by the above ``ptweens`` command which reports that the explicit tween chain
is used:
-.. code-block:: text
+.. code-block:: ini
:linenos:
[app:main]
@@ -442,7 +441,7 @@ There are two required arguments to ``prequest``:
For example::
- $ bin/prequest development.ini /
+ $ $VENV/bin/prequest development.ini /
This will print the body of the response to the console on which it was
invoked.
@@ -453,14 +452,14 @@ config file name or URL.
``prequest`` has a ``-d`` (aka ``--display-headers``) option which prints the
status and headers returned by the server before the output::
- $ bin/prequest -d development.ini /
+ $ $VENV/bin/prequest -d development.ini /
This will print the status, then the headers, then the body of the response
to the console.
You can add request header values by using the ``--header`` option::
- $ bin/prequest --header=Host:example.com development.ini /
+ $ $VENV/bin/prequest --header=Host:example.com development.ini /
Headers are added to the WSGI environment by converting them to their
CGI/WSGI equivalents (e.g. ``Host=example.com`` will insert the ``HTTP_HOST``
@@ -473,7 +472,31 @@ using the ``-m`` (aka ``--method``) option. ``GET``, ``HEAD``, ``POST`` and
``DELETE`` are currently supported. When you use ``POST``, the standard
input of the ``prequest`` process is used as the ``POST`` body::
- $ bin/prequest -mPOST development.ini / < somefile
+ $ $VENV/bin/prequest -mPOST development.ini / < somefile
+
+Showing All Installed Distributions and their Versions
+------------------------------------------------------
+
+.. versionadded:: 1.5
+
+You can use the ``pdistreport`` command to show the Pyramid version in use, the
+Python version in use, and all installed versions of Python distributions in
+your Python environment::
+
+ $ $VENV/bin/pdistreport
+ Pyramid version: 1.5dev
+ Platform Linux-3.2.0-51-generic-x86_64-with-debian-wheezy-sid
+ Packages:
+ authapp 0.0
+ /home/chrism/projects/foo/src/authapp
+ beautifulsoup4 4.1.3
+ /home/chrism/projects/foo/lib/python2.7/site-packages/beautifulsoup4-4.1.3-py2.7.egg
+ ... more output ...
+
+``pdistreport`` takes no options. Its output is useful to paste into a
+pastebin when you are having problems and need someone with more familiarity
+with Python packaging and distribution than you have to look at your
+environment.
.. _writing_a_script:
@@ -515,7 +538,7 @@ representing Pyramid your application configuration as a single argument:
from pyramid.paster import bootstrap
env = bootstrap('/path/to/my/development.ini')
- print env['request'].route_url('home')
+ print(env['request'].route_url('home'))
:func:`pyramid.paster.bootstrap` returns a dictionary containing
framework-related information. This dictionary will always contain a
@@ -573,8 +596,8 @@ configuration implied by the ``[pipeline:main]`` section of your
configuration file by default. Specifying ``/path/to/my/development.ini`` is
logically equivalent to specifying ``/path/to/my/development.ini#main``. In
this case, we'll be using a configuration that includes an ``app`` object
-which is wrapped in the Paste "translogger" middleware (which logs requests
-to the console).
+which is wrapped in the Paste "translogger" :term:`middleware` (which logs
+requests to the console).
You can also specify a particular *section* of the PasteDeploy ``.ini`` file
to load instead of ``main``:
@@ -583,7 +606,7 @@ to load instead of ``main``:
from pyramid.paster import bootstrap
env = bootstrap('/path/to/my/development.ini#another')
- print env['request'].route_url('home')
+ print(env['request'].route_url('home'))
The above example specifies the ``another`` ``app``, ``pipeline``, or
``composite`` section of your PasteDeploy configuration file. The ``app``
@@ -620,7 +643,7 @@ the desired request and passing it into :func:`~pyramid.paster.bootstrap`:
request = Request.blank('/', base_url='https://example.com/prefix')
env = bootstrap('/path/to/my/development.ini#another', request=request)
- print env['request'].application_url
+ print(env['request'].application_url)
# will print 'https://example.com/prefix'
Now you can readily use Pyramid's APIs for generating URLs:
@@ -775,8 +798,10 @@ top-level directory your ``setup.py`` file will look something like this:
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
- README = open(os.path.join(here, 'README.txt')).read()
- CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+ with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+ with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = ['pyramid', 'pyramid_debugtoolbar']
@@ -830,8 +855,10 @@ The result will be something like:
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
- README = open(os.path.join(here, 'README.txt')).read()
- CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+ with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+ with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = ['pyramid', 'pyramid_debugtoolbar']
@@ -863,7 +890,7 @@ The result will be something like:
""",
)
-Once you've done this, invoking ``$somevirtualenv/bin/python setup.py
+Once you've done this, invoking ``$$VENV/bin/python setup.py
develop`` will install a file named ``show_settings`` into the
``$somevirtualenv/bin`` directory with a small bit of Python code that points
to your entry point. It will be executable. Running it without any
@@ -874,9 +901,7 @@ with ``foo``. Running it with two "omit" options (e.g. ``--omit=foo
--omit=bar``) will omit all settings that have keys that start with either
``foo`` or ``bar``::
- [chrism@thinko somevenv]$ bin/show_settings development.ini \
- --omit=pyramid \
- --omit=debugtoolbar
+ $ $VENV/bin/show_settings development.ini --omit=pyramid --omit=debugtoolbar
debug_routematch False
debug_templates True
reload_templates True
diff --git a/docs/narr/configuration.rst b/docs/narr/configuration.rst
index 6f82baf32..f7a69d613 100644
--- a/docs/narr/configuration.rst
+++ b/docs/narr/configuration.rst
@@ -140,7 +140,6 @@ In the example above, the scanner translates the arguments to
:class:`~pyramid.view.view_config` into a call to the
:meth:`pyramid.config.Configurator.add_view` method, effectively:
-.. ignore-next-block
.. code-block:: python
config.add_view(hello)
diff --git a/docs/narr/environment.rst b/docs/narr/environment.rst
index 281bb6919..f0c0c18fe 100644
--- a/docs/narr/environment.rst
+++ b/docs/narr/environment.rst
@@ -212,7 +212,7 @@ sequence can take several different forms.
package1 package2 package3
- The package names can also be separated by carriage returns::
+ The package names can also be separated by carriage returns::
package1
package2
@@ -302,7 +302,7 @@ Ideally, you won't need to use the ``pyramid.tweens`` setting at all. Tweens
are generally ordered and included "implicitly" when an add-on package which
registers a tween is "included". Packages are included when you name a
``pyramid.includes`` setting in your configuration or when you call
-:meth:`pyramid.config.Configuration.include`.
+:meth:`pyramid.config.Configurator.include`.
Authors of included add-ons provide "implicit" tween configuration ordering
hints to Pyramid when their packages are included. However, the implicit
@@ -546,7 +546,7 @@ for settings documented as such. For example, you might start your
.. code-block:: text
$ PYRAMID_DEBUG_AUTHORIZATION=1 PYRAMID_RELOAD_TEMPLATES=1 \
- bin/paster serve MyProject.ini
+ $VENV/bin/pserve MyProject.ini
If you started your application this way, your :app:`Pyramid`
application would behave in the same manner as if you had placed the
@@ -666,9 +666,9 @@ Here's how:
def includeme(config):
settings = config.registry.settings
debug_frobnosticator = settings['debug_frobnosticator']
-
-- In the runtime code that you need to access the new settings value, find
- the value in the ``registry.settings`` dictionary and use it. In
+
+- In the runtime code from where you need to access the new settings value,
+ find the value in the ``registry.settings`` dictionary and use it. In
:term:`view` code (or any other code that has access to the request), the
easiest way to do this is via ``request.registry.settings``. For example:
diff --git a/docs/narr/events.rst b/docs/narr/events.rst
index 929208083..2accb3dbe 100644
--- a/docs/narr/events.rst
+++ b/docs/narr/events.rst
@@ -26,7 +26,7 @@ subscriber is a function that accepts a single argument named `event`:
:linenos:
def mysubscriber(event):
- print event
+ print(event)
The above is a subscriber that simply prints the event to the console
when it's called.
@@ -53,7 +53,7 @@ method (see also :term:`Configurator`):
from subscribers import mysubscriber
- # "config" below is assumed to be an instance of a
+ # "config" below is assumed to be an instance of a
# pyramid.config.Configurator object
config.add_subscriber(mysubscriber, NewRequest)
@@ -77,7 +77,7 @@ type via the :func:`pyramid.events.subscriber` function.
@subscriber(NewRequest)
def mysubscriber(event):
- event.request.foo = 1
+ event.request.foo = 1
When the :func:`~pyramid.events.subscriber` decorator is used a
:term:`scan` must be performed against the package containing the
@@ -113,10 +113,10 @@ your application like so:
:linenos:
def handle_new_request(event):
- print 'request', event.request
+ print('request', event.request)
def handle_new_response(event):
- print 'response', event.response
+ print('response', event.response)
You may configure these functions to be called at the appropriate
times by adding the following code to your application's
@@ -150,3 +150,86 @@ application, because the interface defined at
:class:`pyramid.interfaces.INewResponse` says it must
(:class:`pyramid.events.NewResponse` objects also have a ``request``).
+.. _custom_events:
+
+Creating Your Own Events
+------------------------
+
+In addition to using the events that the Pyramid framework creates,
+you can create your own events for use in your application. This can
+be useful to decouple parts of your application.
+
+For example, suppose your application has to do many things when a new
+document is created. Rather than putting all this logic in the view
+that creates the document, you can create the document in your view
+and then fire a custom event. Subscribers to the custom event can take
+other actions, such as indexing the document, sending email, or
+sending a message to a remote system.
+
+An event is simply an object. There are no required attributes or
+method for your custom events. In general, your events should keep
+track of the information that subscribers will need. Here are some
+example custom event classes:
+
+.. code-block:: python
+ :linenos:
+
+ class DocCreated(object):
+ def __init__(self, doc, request):
+ self.doc = doc
+ self.request = request
+
+ class UserEvent(object):
+ def __init__(self, user):
+ self.user = user
+
+ class UserLoggedIn(UserEvent):
+ pass
+
+Some Pyramid applications choose to define custom events classes in an
+``events`` module.
+
+You can subscribe to custom events in the same way that you subscribe
+to Pyramid events -- either imperatively or with a decorator. You can
+also use custom events with :ref:`subscriber predicates
+<subscriber_predicates>`. Here's an example of subscribing to a custom
+event with a decorator:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.events import subscriber
+ from .events import DocCreated
+ from .index import index_doc
+
+ @subscriber(DocCreated)
+ def index_doc(event):
+ # index the document using our application's index_doc function
+ index_doc(event.doc, event.request)
+
+The above example assumes that the application defines a
+``DocCreated`` event class and an ``index_doc`` function.
+
+To fire your custom events use the
+:meth:`pyramid.registry.Registry.notify` method, which is most often
+accessed as ``request.registry.notify``. For example:
+
+.. code-block:: python
+ :linenos:
+
+ from .events import DocCreated
+
+ def new_doc_view(request):
+ doc = MyDoc()
+ event = DocCreated(doc, request)
+ request.registry.notify(event)
+ return {'document': doc}
+
+This example view will notify all subscribers to the custom
+``DocCreated`` event.
+
+Note that when you fire an event, all subscribers are run
+synchronously so it's generally not a good idea
+to create event handlers that may take a long time to run. Although
+event handlers could be used as a central place to spawn tasks on your
+own message queues.
diff --git a/docs/narr/extconfig.rst b/docs/narr/extconfig.rst
index f33326279..6587aef92 100644
--- a/docs/narr/extconfig.rst
+++ b/docs/narr/extconfig.rst
@@ -55,7 +55,7 @@ method of the Configurator:
:linenos:
def mysubscriber(event):
- print event.request
+ print(event.request)
config.add_newrequest_subscriber(mysubscriber)
@@ -79,7 +79,7 @@ able to install it and subsequently do:
:linenos:
def mysubscriber(event):
- print event.request
+ print(event.request)
from pyramid.config import Configurator
config = Configurator()
@@ -129,8 +129,8 @@ called (either explicitly or as the result of calling
:meth:`~pyramid.config.Configurator.make_wsgi_app`), conflicting actions are
potentially automatically resolved as per
:ref:`automatic_conflict_resolution`. If a conflict cannot be automatically
-resolved, a :exc:`ConfigurationConflictError` is raised and application
-startup is prevented.
+resolved, a :exc:`pyramid.exceptions.ConfigurationConflictError` is raised
+and application startup is prevented.
In our above example, therefore, if a consumer of our ``add_jammyjam``
directive did this:
diff --git a/docs/narr/extending.rst b/docs/narr/extending.rst
index dd9281c73..a60a49fea 100644
--- a/docs/narr/extending.rst
+++ b/docs/narr/extending.rst
@@ -50,7 +50,7 @@ layers are apt to provide the necessary "opinions" (such as mandating a
storage layer, a templating system, and a structured, well-documented pattern
of registering that certain URLs map to certain bits of code) which makes the
concept of a "pluggable application" possible. "Pluggable applications",
-thus, should not plug in to Pyramid itself but should instead plug into a
+thus, should not plug into Pyramid itself but should instead plug into a
system written atop Pyramid.
Although it does not provide for "pluggable applications", Pyramid *does*
@@ -200,8 +200,8 @@ like this:
overridden elements, such as templates and static assets as necessary.
- Install the new package into the same Python environment as the original
- application (e.g. ``$myvenv/bin/python setup.py develop`` or
- ``$myvenv/bin/python setup.py install``).
+ application (e.g. ``$VENV/bin/python setup.py develop`` or
+ ``$VENV/bin/python setup.py install``).
- Change the ``main`` function in the new package's ``__init__.py`` to include
the original :app:`Pyramid` application's configuration functions via
@@ -209,7 +209,7 @@ like this:
- Wire the new views and assets created in the new package up using
imperative registrations within the ``main`` function of the
- ``__init__.py`` file of the new application. These wiring should happen
+ ``__init__.py`` file of the new application. This wiring should happen
*after* including the configuration functions of the old application.
These registrations will extend or override any registrations performed by
the original application. See :ref:`overriding_views`,
diff --git a/docs/narr/firstapp.rst b/docs/narr/firstapp.rst
index d61d95685..e73ef66ac 100644
--- a/docs/narr/firstapp.rst
+++ b/docs/narr/firstapp.rst
@@ -29,13 +29,13 @@ On UNIX:
.. code-block:: text
- $ /path/to/your/virtualenv/bin/python helloworld.py
+ $ $VENV/bin/python helloworld.py
On Windows:
.. code-block:: text
- C:\> \path\to\your\virtualenv\Scripts\python.exe helloworld.py
+ C:\> %VENV%\Scripts\python.exe helloworld.py
This command will not return and nothing will be printed to the console.
When port 8080 is visited by a browser on the URL ``/hello/world``, the
@@ -166,7 +166,6 @@ the application.
Adding Configuration
~~~~~~~~~~~~~~~~~~~~
-.. ignore-next-block
.. literalinclude:: helloworld.py
:linenos:
:lines: 11-12
@@ -175,9 +174,9 @@ First line above calls the :meth:`pyramid.config.Configurator.add_route`
method, which registers a :term:`route` to match any URL path that begins
with ``/hello/`` followed by a string.
-The second line, ``config.add_view(hello_world, route_name='hello')``,
-registers the ``hello_world`` function as a :term:`view callable` and makes
-sure that it will be called when the ``hello`` route is matched.
+The second line registers the ``hello_world`` function as a
+:term:`view callable` and makes sure that it will be called when the
+``hello`` route is matched.
.. index::
single: make_wsgi_app
@@ -186,7 +185,6 @@ sure that it will be called when the ``hello`` route is matched.
WSGI Application Creation
~~~~~~~~~~~~~~~~~~~~~~~~~
-.. ignore-next-block
.. literalinclude:: helloworld.py
:linenos:
:lines: 13
@@ -215,7 +213,6 @@ to its ``add_view`` and ``add_route`` methods.
WSGI Application Serving
~~~~~~~~~~~~~~~~~~~~~~~~
-.. ignore-next-block
.. literalinclude:: helloworld.py
:linenos:
:lines: 14-15
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index 7d4d03b89..3a2568775 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -14,27 +14,28 @@ in various ways.
Changing the Not Found View
---------------------------
-When :app:`Pyramid` can't map a URL to view code, it invokes a :term:`not
-found view`, which is a :term:`view callable`. A default notfound view
-exists. The default not found view can be overridden through application
-configuration.
+When :app:`Pyramid` can't map a URL to view code, it invokes a :term:`Not
+Found View`, which is a :term:`view callable`. The default Not Found View
+can be overridden through application configuration.
If your application uses :term:`imperative configuration`, you can replace
-the Not Found view by using the
+the Not Found View by using the
:meth:`pyramid.config.Configurator.add_notfound_view` method:
.. code-block:: python
:linenos:
- from helloworld.views import notfound
- config.add_notfound_view(notfound)
+ def notfound(request):
+ return Response('Not Found, dude', status='404 Not Found')
-Replace ``helloworld.views.notfound`` with a reference to the :term:`view
-callable` you want to use to represent the Not Found view. The :term:`not
-found view` callable is a view callable like any other.
+ def main(globals, **settings):
+ config = Configurator()
+ config.add_notfound_view(notfound)
+
+The :term:`Not Found View` callable is a view callable like any other.
If your application instead uses :class:`pyramid.view.view_config` decorators
-and a :term:`scan`, you can replace the Not Found view by using the
+and a :term:`scan`, you can replace the Not Found View by using the
:class:`pyramid.view.notfound_view_config` decorator:
.. code-block:: python
@@ -47,17 +48,17 @@ and a :term:`scan`, you can replace the Not Found view by using the
return Response('Not Found, dude', status='404 Not Found')
def main(globals, **settings):
- config = Configurator()
- config.scan()
+ config = Configurator()
+ config.scan()
This does exactly what the imperative example above showed.
-Your application can define *multiple* not found views if necessary. Both
+Your application can define *multiple* Not Found Views if necessary. Both
:meth:`pyramid.config.Configurator.add_notfound_view` and
:class:`pyramid.view.notfound_view_config` take most of the same arguments as
:class:`pyramid.config.Configurator.add_view` and
-:class:`pyramid.view.view_config`, respectively. This means that not found
-views can carry predicates limiting their applicability. For example:
+:class:`pyramid.view.view_config`, respectively. This means that Not Found
+Views can carry predicates limiting their applicability. For example:
.. code-block:: python
:linenos:
@@ -80,7 +81,7 @@ The ``notfound_get`` view will be called when a view could not be found and
the request method was ``GET``. The ``notfound_post`` view will be called
when a view could not be found and the request method was ``POST``.
-Like any other view, the notfound view must accept at least a ``request``
+Like any other view, the Not Found View must accept at least a ``request``
parameter, or both ``context`` and ``request``. The ``request`` is the
current :term:`request` representing the denied action. The ``context`` (if
used in the call signature) will be the instance of the
@@ -92,7 +93,8 @@ Both :meth:`pyramid.config.Configurator.add_notfound_view` and
redirect requests to slash-appended routes. See
:ref:`redirecting_to_slash_appended_routes` for examples.
-Here's some sample code that implements a minimal NotFound view callable:
+Here's some sample code that implements a minimal :term:`Not Found View`
+callable:
.. code-block:: python
:linenos:
@@ -104,14 +106,13 @@ Here's some sample code that implements a minimal NotFound view callable:
.. note::
- When a NotFound view callable is invoked, it is passed a
+ When a Not Found View callable is invoked, it is passed a
:term:`request`. The ``exception`` attribute of the request will be an
instance of the :exc:`~pyramid.httpexceptions.HTTPNotFound` exception that
- caused the not found view to be called. The value of
- ``request.exception.message`` will be a value explaining why the not found
- error was raised. This message will be different when the
- ``pyramid.debug_notfound`` environment setting is true than it is when it
- is false.
+ caused the Not Found View to be called. The value of
+ ``request.exception.message`` will be a value explaining why the Not Found
+ error was raised. This message has different values depending whether the
+ ``pyramid.debug_notfound`` environment setting is true or false.
.. note::
@@ -123,7 +124,7 @@ Here's some sample code that implements a minimal NotFound view callable:
.. warning::
- When a NotFound view callable accepts an argument list as
+ When a Not Found View callable accepts an argument list as
described in :ref:`request_and_context_view_definitions`, the ``context``
passed as the first argument to the view callable will be the
:exc:`~pyramid.httpexceptions.HTTPNotFound` exception instance. If
@@ -155,12 +156,12 @@ forbidden view:
.. code-block:: python
:linenos:
- from helloworld.views import forbidden_view
- from pyramid.httpexceptions import HTTPForbidden
- config.add_forbidden_view(forbidden_view)
+ def forbidden(request):
+ return Response('forbidden')
-Replace ``helloworld.views.forbidden_view`` with a reference to the Python
-:term:`view callable` you want to use to represent the Forbidden view.
+ def main(globals, **settings):
+ config = Configurator()
+ config.add_forbidden_view(forbidden_view)
If instead you prefer to use decorators and a :term:`scan`, you can use the
:class:`pyramid.view.forbidden_view_config` decorator to mark a view callable
@@ -208,9 +209,9 @@ Here's some sample code that implements a minimal forbidden view:
that caused the forbidden view to be called. The value of
``request.exception.message`` will be a value explaining why the forbidden
was raised and ``request.exception.result`` will be extended information
- about the forbidden exception. These messages will be different when the
- ``pyramid.debug_authorization`` environment setting is true than it is when
- it is false.
+ about the forbidden exception. These messages have different values
+ depending whether the ``pyramid.debug_authorization`` environment setting
+ is true or false.
.. index::
single: request factory
@@ -290,7 +291,7 @@ actually execute the function until accessed.
return sum(args)
def prop(request):
- print "getting the property"
+ print("getting the property")
return "the property"
config = Configurator()
@@ -331,7 +332,7 @@ Here is an example of passing a class to ``Configurator.add_request_method``:
# use @property if you don't want to cache the result
@reify
def prop(self):
- print "getting the property"
+ print("getting the property")
return "the property"
config = Configurator()
@@ -674,7 +675,7 @@ traverser.
If you've added a traverser, you can change how
:meth:`~pyramid.request.Request.resource_url` generates a URL for a specific
type of resource by adding a call to
-:meth:`pyramid.config.add_resource_url_adapter`.
+:meth:`pyramid.config.Configurator.add_resource_url_adapter`.
For example:
@@ -694,7 +695,7 @@ represents the type of interface that must be possessed by the resource for
this resource url factory to be found. If the ``resource_iface`` argument is
omitted, this resource url adapter will be used for *all* resources.
-The API that must be implemented by your a class that provides
+The API that must be implemented by a class that provides
:class:`~pyramid.interfaces.IResourceURL` is as follows:
.. code-block:: python
@@ -712,7 +713,7 @@ The API that must be implemented by your a class that provides
The default context URL generator is available for perusal as the class
:class:`pyramid.traversal.ResourceURL` in the `traversal module
-<http://github.com/Pylons/pyramid/blob/master/pyramid/traversal.py>`_ of the
+<https://github.com/Pylons/pyramid/blob/master/pyramid/traversal.py>`_ of the
:term:`Pylons` GitHub Pyramid repository.
See :meth:`pyramid.config.add_resource_url_adapter` for more information.
@@ -930,7 +931,7 @@ set a *default* view mapper (overriding the superdefault view mapper used by
Pyramid itself).
A *single* view registration can use a view mapper by passing the mapper as
-the ``mapper`` argument to :meth:`~pyramid.config.Configuration.add_view`.
+the ``mapper`` argument to :meth:`~pyramid.config.Configurator.add_view`.
.. index::
single: configuration decorator
@@ -1036,7 +1037,7 @@ upstream WSGI component that uses :app:`Pyramid` as its "app". This is a
feature that may be used by Pyramid framework extensions, to provide, for
example, Pyramid-specific view timing support bookkeeping code that examines
exceptions before they are returned to the upstream WSGI application. Tweens
-behave a bit like :term:`WSGI` middleware but they have the benefit of
+behave a bit like :term:`WSGI` :term:`middleware` but they have the benefit of
running in a context in which they have access to the Pyramid
:term:`application registry` as well as the Pyramid rendering machinery.
@@ -1110,8 +1111,8 @@ Once you've created a tween factory, you can register it into the implicit
tween chain using the :meth:`pyramid.config.Configurator.add_tween` method
using its :term:`dotted Python name`.
-Here's an example of registering the a tween factory as an "implicit"
-tween in a Pyramid application:
+Here's an example of registering a tween factory as an "implicit" tween in a
+Pyramid application:
.. code-block:: python
:linenos:
@@ -1447,7 +1448,7 @@ view/route predicate:
subscriber predicates will assume a certain event type.
Here's an example of a subscriber predicate that can be used in conjunction
-with a subscriber that subscribes to the :class:`pyramid.events.NewReqest`
+with a subscriber that subscribes to the :class:`pyramid.events.NewRequest`
event type.
.. code-block:: python
diff --git a/docs/narr/i18n.rst b/docs/narr/i18n.rst
index 511464322..555b06e0f 100644
--- a/docs/narr/i18n.rst
+++ b/docs/narr/i18n.rst
@@ -276,7 +276,7 @@ like so:
.. code-block:: text
$ cd /my/virtualenv
- $ bin/easy_install Babel lingua
+ $ $VENV/bin/easy_install Babel lingua
Installation on Windows
+++++++++++++++++++++++
@@ -287,8 +287,7 @@ like so:
.. code-block:: text
- C> cd \my\virtualenv
- C> Scripts\easy_install Babel lingua
+ C> %VENV%\Scripts\easy_install Babel lingua
.. index::
single: Babel; message extractors
@@ -347,7 +346,7 @@ extract the messages:
$ cd /place/where/myapplication/setup.py/lives
$ mkdir -p myapplication/locale
- $ $myvenv/bin/python setup.py extract_messages
+ $ $VENV/bin/python setup.py extract_messages
The message catalog ``.pot`` template will end up in:
@@ -439,7 +438,7 @@ init_catalog`` command:
.. code-block:: text
$ cd /place/where/myapplication/setup.py/lives
- $ $myvenv/bin/python setup.py init_catalog -l es
+ $ $VENV/bin/python setup.py init_catalog -l es
By default, the message catalog ``.po`` file will end up in:
@@ -471,7 +470,7 @@ Then use the ``setup.py update_catalog`` command.
.. code-block:: text
$ cd /place/where/myapplication/setup.py/lives
- $ $myvenv/bin/python setup.py update_catalog
+ $ $VENV/bin/python setup.py update_catalog
.. index::
pair: compiling; message catalog
@@ -487,7 +486,7 @@ translations, compile ``.po`` files to ``.mo`` files:
.. code-block:: text
$ cd /place/where/myapplication/setup.py/lives
- $ $myvenv/bin/python setup.py compile_catalog
+ $ $VENV/bin/python setup.py compile_catalog
This will create a ``.mo`` file for each ``.po`` file in your
application. As long as the :term:`translation directory` in which
@@ -580,18 +579,9 @@ signature:
def pluralize(singular, plural, n, domain=None, mapping=None):
...
-The ``singular`` and ``plural`` arguments should each be a Unicode
-value representing a :term:`message identifier`. ``n`` should be an
-integer. ``domain`` should be a :term:`translation domain`, and
-``mapping`` should be a dictionary that is used for *replacement
-value* interpolation of the translated string. If ``n`` is plural
-for the current locale, ``pluralize`` will return a Unicode
-translation for the message id ``plural``, otherwise it will return a
-Unicode translation for the message id ``singular``.
-
-The arguments provided as ``singular`` and/or ``plural`` may also be
-:term:`translation string` objects, but the domain and mapping
-information attached to those objects is ignored.
+The simplest case is the ``singular`` and ``plural`` arguments being passed as
+unicode literals. This returns the appropriate literal according to the locale
+pluralization rules for the number ``n``, and interpolates ``mapping``.
.. code-block:: python
:linenos:
@@ -603,6 +593,49 @@ information attached to those objects is ignored.
translated = localizer.pluralize('Item', 'Items', 1, 'mydomain')
# ... use translated ...
+However, for support of other languages, the ``singular`` argument should
+be a Unicode value representing a :term:`message identifier`. In this
+case the ``plural`` value is ignored.
+``domain`` should be a :term:`translation domain`, and
+``mapping`` should be a dictionary that is used for *replacement
+value* interpolation of the translated string.
+
+The value of ``n`` will be used to find the appropriate plural form for the
+current language and ``pluralize`` will return a Unicode translation for the
+message id ``singular``. The message file must have defined ``singular`` as a
+translation with plural forms.
+
+The argument provided as ``singular`` may be a :term:`translation string`
+object, but the domain and mapping information attached is ignored.
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.i18n import get_localizer
+
+ def aview(request):
+ localizer = get_localizer(request)
+ num = 1
+ translated = localizer.pluralize(_('item_plural', default="${number} items"),
+ None, num, 'mydomain', mapping={'number':num})
+
+The corresponding message catalog must have language plural definitions and
+plural alternatives set.
+
+.. code-block:: text
+ :linenos:
+
+ "Plural-Forms: nplurals=3; plural=n==0 ? 0 : n==1 ? 1 : 2;"
+
+ msgid "item_plural"
+ msgid_plural ""
+ msgstr[0] "No items"
+ msgstr[1] "${number} item"
+ msgstr[2] "${number} items"
+
+More information on complex plurals can be found in the `gettext documentation
+<https://www.gnu.org/savannah-checkouts/gnu/gettext/manual/html_node/Plural-forms.html>`_.
+
.. index::
single: locale name
single: get_locale_name
@@ -736,9 +769,7 @@ through translation before being rendered:
The features represented by attributes of the ``i18n`` namespace of
Chameleon will also consult the :app:`Pyramid` translations.
-See
-`http://chameleon.repoze.org/docs/latest/i18n.html#the-i18n-namespace
-<http://chameleon.repoze.org/docs/latest/i18n.html#the-i18n-namespace>`_.
+See http://chameleon.readthedocs.org/en/latest/reference.html#id50.
.. note::
@@ -811,7 +842,7 @@ If this setting is supplied within the :app:`Pyramid` application
default_locale_name = settings['pyramid.default_locale_name']
.. index::
- single: detecting langauges
+ single: detecting languages
"Detecting" Available Languages
-------------------------------
@@ -987,7 +1018,7 @@ requires no additional coding or configuration.
The default locale negotiator implementation named
:class:`~pyramid.i18n.default_locale_negotiator` uses the following
-set of steps to dermine the locale name.
+set of steps to determine the locale name.
- First, the negotiator looks for the ``_LOCALE_`` attribute of the
request object (possibly set directly by view code or by a listener
diff --git a/docs/narr/install.rst b/docs/narr/install.rst
index 85dfd5bf4..fb67b899b 100644
--- a/docs/narr/install.rst
+++ b/docs/narr/install.rst
@@ -9,30 +9,50 @@ Installing :app:`Pyramid`
Before You Install
------------------
-You will need `Python <http://python.org>`_ version 2.6 or better to
-run :app:`Pyramid`.
+You will need `Python <http://python.org>`_ version 2.6 or better to run
+:app:`Pyramid`.
.. sidebar:: Python Versions
- As of this writing, :app:`Pyramid` has been tested under Python 2.6,
- Python 2.7, Python 3.2, and Python 3.3. :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, Python
+ 2.7, Python 3.2, and Python 3.3. :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.9+).
+:app:`Pyramid` is known to run on all popular UNIX-like systems such as Linux,
+Mac OS X, and FreeBSD as well as on Windows platforms. It is also 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
-requirements mentioned.
+:app:`Pyramid` installation does not require the compilation of any C code, so
+you need only a Python interpreter that meets the requirements mentioned.
+
+For Mac OS X Users
+~~~~~~~~~~~~~~~~~~
+
+From `Python.org <http://python.org/download/mac/>`_:
+
+ Python comes pre-installed on Mac OS X, but due to Apple's release cycle,
+ it's often one or even two years old. The overwhelming recommendation of
+ the "MacPython" community is to upgrade your Python by downloading and
+ installing a newer version from `the Python standard release page
+ <http://python.org/download/releases/>`_.
+
+It is recommended to download one of the *installer* versions, unless you
+prefer to install your Python through a packgage manager (e.g., macports or
+homebrew) or to build your Python from source.
+
+Unless you have a need for a specific earlier version, it is recommended to
+install the latest 2.x or 3.x version of Python.
+
+If you use an installer for your Python, then you can skip to the section
+:ref:`installing_unix`.
If You Don't Yet Have A Python Interpreter (UNIX)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If your system doesn't have a Python interpreter, and you're on UNIX,
-you can either install Python using your operating system's package
-manager *or* you can install Python from source fairly easily on any
-UNIX system that has development tools.
+If your system doesn't have a Python interpreter, and you're on UNIX, you can
+either install Python using your operating system's package manager *or* you
+can install Python from source fairly easily on any UNIX system that has
+development tools.
.. index::
pair: install; Python (from package, UNIX)
@@ -40,9 +60,8 @@ UNIX system that has development tools.
Package Manager Method
++++++++++++++++++++++
-You can use your system's "package manager" to install Python.
-Each package manager is slightly different, but the "flavor" of
-them is usually the same.
+You can use your system's "package manager" to install Python. Each package
+manager is slightly different, but the "flavor" of them is usually the same.
For example, on a Debian or Ubuntu system, use the following command:
@@ -63,28 +82,27 @@ invokable via ``python2.7`` from a shell prompt.
Source Compile Method
+++++++++++++++++++++
-It's useful to use a Python interpreter that *isn't* the "system"
-Python interpreter to develop your software. The authors of
-:app:`Pyramid` tend not to use the system Python for development
-purposes; always a self-compiled one. Compiling Python is usually
-easy, and often the "system" Python is compiled with options that
-aren't optimal for web development. For an explanation, see
+It's useful to use a Python interpreter that *isn't* the "system" Python
+interpreter to develop your software. The authors of :app:`Pyramid` tend not
+to use the system Python for development purposes; always a self-compiled one.
+Compiling Python is usually easy, and often the "system" Python is compiled
+with options that aren't optimal for web development. For an explanation, see
https://github.com/Pylons/pyramid/issues/747.
-To compile software on your UNIX system, typically you need
-development tools. Often these can be installed via the package
-manager. For example, this works to do so on an Ubuntu Linux system:
+To compile software on your UNIX system, typically you need development tools.
+Often these can be installed via the package manager. For example, this works
+to do so on an Ubuntu Linux system:
.. code-block:: text
$ sudo apt-get install build-essential
-On Mac OS X, installing `XCode
-<http://developer.apple.com/tools/xcode/>`_ has much the same effect.
+On Mac OS X, installing `XCode <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.7 interpreter from *source*, on the same system,
-using the following commands:
+Once you've got development tools installed on your system, you can install a
+Python 2.7 interpreter from *source*, on the same system, using the following
+commands:
.. code-block:: text
@@ -98,9 +116,8 @@ using the following commands:
$ ./configure --prefix=$HOME/opt/Python-2.7.3
$ make && make install
-Once these steps are performed, the Python interpreter will be
-invokable via ``$HOME/opt/Python-2.7.3/bin/python`` from a shell
-prompt.
+Once these steps are performed, the Python interpreter will be invokable via
+``$HOME/opt/Python-2.7.3/bin/python`` from a shell prompt.
.. index::
pair: install; Python (from package, Windows)
@@ -108,24 +125,21 @@ prompt.
If You Don't Yet Have A Python Interpreter (Windows)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If your Windows system doesn't have a Python interpreter, you'll need
-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
-executable and accept the defaults during the installation process.
-You may also need to download and install the `Python for Windows
-extensions <http://sourceforge.net/projects/pywin32/files/>`_.
+If your Windows system doesn't have a Python interpreter, you'll need 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
+executable and accept the defaults during the installation process. You may
+also need to download and install the Python for Windows extensions.
.. warning::
- After you install Python on Windows, you may need to add the
- ``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``
- and add that directory to the end of the ``Path`` environment
- variable.
+ After you install Python on Windows, you may need to add the ``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`` and add that directory to the end of the ``Path``
+ environment variable.
.. index::
single: installing on UNIX
@@ -135,27 +149,26 @@ extensions <http://sourceforge.net/projects/pywin32/files/>`_.
Installing :app:`Pyramid` on a UNIX System
---------------------------------------------
-It is best practice to install :app:`Pyramid` into a "virtual"
-Python environment in order to obtain isolation from any "system"
-packages you've got installed in your Python version. This can be
-done by using the :term:`virtualenv` package. Using a virtualenv will
-also prevent :app:`Pyramid` from globally installing versions of
-packages that are not compatible with your system Python.
+It is best practice to install :app:`Pyramid` into a "virtual" Python
+environment in order to obtain isolation from any "system" packages you've got
+installed in your Python version. This can be done by using the
+:term:`virtualenv` package. Using a virtualenv will 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` or :term:`distribute` is installed. To do so, invoke
-``import setuptools`` within the Python interpreter you'd like to run
-:app:`Pyramid` under.
+:term:`setuptools` is installed. To do so, invoke ``import setuptools`` within
+the Python interpreter you'd like to run :app:`Pyramid` under.
-The following command will not display anything if setuptools or distribute is
-already installed:
+The following command will not display anything if setuptools is already
+installed:
.. code-block:: text
$ python2.7 -c 'import setuptools'
-Running the same command will yield the following output if setuptools or
-distribute is not yet installed:
+Running the same command will yield the following output if setuptools is not
+yet installed:
.. code-block:: text
@@ -164,62 +177,35 @@ distribute is not yet installed:
ImportError: No module named setuptools
If ``import setuptools`` raises an :exc:`ImportError` as it does above, you
-will need to install setuptools or distribute manually.
+will need to install setuptools manually.
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.
+third-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.
-Installing Setuptools On Python 2
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Installing Setuptools
+~~~~~~~~~~~~~~~~~~~~~
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.
+<https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py>`_ then invoke
+it using the Python interpreter into which you want to install setuptools.
.. code-block:: text
$ python ez_setup.py
-Once this command is invoked, setuptools 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 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. 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.
+Once this command is invoked, setuptools 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
+ $ sudo python ez_setup.py
.. index::
pair: install; virtualenv
@@ -227,9 +213,9 @@ remediate this, you may need to do:
Installing the ``virtualenv`` Package
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-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.
+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.
.. warning::
@@ -242,16 +228,16 @@ your setuptools-enabled Python interpreter, use the ``easy_install`` command.
Turing-complete.
If you insist on using ``pyvenv``, you'll need to understand how to install
- software such as ``distribute`` into the virtual environment manually,
- which this guide does not cover.
+ software such as ``setuptools`` into the virtual environment manually, which
+ this guide does not cover.
.. code-block:: text
$ easy_install virtualenv
This command should succeed, and tell you that the virtualenv package is now
-installed. If it fails due to permission errors, you may need to install it
-as your system's administrative user. For example:
+installed. If it fails due to permission errors, you may need to install it as
+your system's administrative user. For example:
.. code-block:: text
@@ -264,45 +250,44 @@ as your system's administrative user. For example:
Creating the Virtual Python Environment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Once the :term:`virtualenv` package is installed in your Python, you
-can then create a virtual environment. To do so, invoke the
-following:
+Once the :term:`virtualenv` package is installed in your Python environment,
+you can then create a virtual environment. To do so, invoke the following:
.. code-block:: text
- $ virtualenv --no-site-packages env
- New python executable in env/bin/python
+ $ export VENV=~/env
+ $ virtualenv $VENV
+ New python executable in /home/foo/env/bin/python
Installing setuptools.............done.
+You can either follow the use of the environment variable, ``$VENV``, or
+replace it with the root directory of the :term:`virtualenv`. In that case, the
+`export` command can be skipped. If you choose the former approach, ensure that
+it's an absolute path.
+
.. warning::
- Using ``--no-site-packages`` when generating your
- virtualenv is *very important*. This flag provides the necessary
- isolation for running the set of packages required by
- :app:`Pyramid`. If you do not specify ``--no-site-packages``,
- it's possible that :app:`Pyramid` will not install properly into
- the virtualenv, or, even if it does, may not run properly,
- depending on the packages you've already got installed into your
- Python's "main" site-packages dir.
+ Avoid using the ``--system-site-packages`` option when creating the
+ virtualenv unless you know what you are doing. For versions of virtualenv
+ prior to 1.7, make sure to use the ``--no-site-packages`` option, because
+ this option was formerly not the default and may produce undesirable
+ results.
-.. warning:: *do not* use ``sudo`` to run the
- ``virtualenv`` script. It's perfectly acceptable (and desirable)
- to create a virtualenv as a normal user.
+.. warning::
+
+ *do not* use ``sudo`` to run the ``virtualenv`` script. It's perfectly
+ acceptable (and desirable) to create a virtualenv as a normal user.
-You should perform any following commands that mention a "bin"
-directory from within the ``env`` virtualenv dir.
Installing :app:`Pyramid` Into the Virtual Python Environment
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-After you've got your ``env`` virtualenv installed, you may install
-:app:`Pyramid` itself using the following commands from within the
-virtualenv (``env``) directory you created in the last step.
+After you've got your virtualenv installed, you may install :app:`Pyramid`
+itself using the following commands:
.. code-block:: text
- $ cd env
- $ bin/easy_install pyramid
+ $ $VENV/bin/easy_install pyramid
The ``easy_install`` command will take longer than the previous ones to
complete, as it downloads and installs a number of dependencies.
@@ -315,98 +300,58 @@ complete, as it downloads and installs a number of dependencies.
Installing :app:`Pyramid` on a Windows 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
-~~~~~~~~~~~~~~~~~~~~~~
+You can use Pyramid on Windows under Python 2 or 3.
-#. Install, or find `Python 2.7
- <http://www.python.org/download/releases/2.7.3/>`_ for your system.
+#. Download and install the most recent `Python 2.7.x or 3.3.x version
+ <http://www.python.org/download/>`_ 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.7 and install it using the
- same Python installation from the previous step.
+#. Download and install the `Python for Windows extensions
+ <http://sourceforge.net/projects/pywin32/files/pywin32/>`_. Carefully read
+ the README.txt file at the end of the list of builds, and follow its
+ directions. Make sure you get the proper 32- or 64-bit build and Python
+ version.
-#. 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.7 installation using a
- command prompt:
+#. Install latest :term:`setuptools` distribution into the Python from step 1
+ above: download `ez_setup.py
+ <https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py>`_ and run
+ it using the ``python`` interpreter of your Python 2.7 or 3.3 installation
+ using a command prompt:
.. code-block:: text
+ # modify the command according to the python version, e.g.:
+ # for Python 2.7:
c:\> c:\Python27\python ez_setup.py
+ # for Python 3.3:
+ c:\> c:\Python33\python ez_setup.py
-#. Use that Python's `bin/easy_install` to install `virtualenv`:
+#. Install `virtualenv`:
.. code-block:: text
+ # modify the command according to the python version, e.g.:
+ # for Python 2.7:
c:\> c:\Python27\Scripts\easy_install virtualenv
+ # for Python 3.3:
+ c:\> c:\Python33\Scripts\easy_install virtualenv
-#. Use that Python's virtualenv to make a workspace:
-
- .. code-block:: text
-
- c:\> c:\Python27\Scripts\virtualenv --no-site-packages env
-
-#. Switch to the ``env`` directory:
+#. Make a :term:`virtualenv` workspace:
.. 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
-
- 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:\> set VENV=c:\env
+ # modify the command according to the python version, e.g.:
+ # for Python 2.7:
+ c:\> c:\Python27\Scripts\virtualenv %VENV%
+ # for Python 3.3:
+ c:\> c:\Python33\Scripts\virtualenv %VENV%
- c:\> cd env
+ You can either follow the use of the environment variable, ``%VENV%``, or
+ replace it with the root directory of the :term:`virtualenv`. In that case,
+ the `set` command can be skipped. If you choose the former approach, ensure
+ that it's an absolute path.
-#. (Optional) Consider using ``Scripts\activate.bat`` to make your shell
+#. (Optional) Consider using ``%VENV%\Scripts\activate.bat`` to make your shell
environment wired to use the virtualenv.
#. Use ``easy_install`` to get :app:`Pyramid` and its direct dependencies
@@ -414,7 +359,7 @@ Windows Using Python 3
.. code-block:: text
- c:\env> Scripts\easy_install pyramid
+ c:\env> %VENV%\Scripts\easy_install pyramid
What Gets Installed
-------------------
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index 3540ee5c4..032f4be6b 100644
--- a/docs/narr/introduction.rst
+++ b/docs/narr/introduction.rst
@@ -52,9 +52,7 @@ Documentation
Speed
:app:`Pyramid` is designed to provide noticeably fast execution for common
- tasks such as templating and simple response generation. Although "hardware
- is cheap", the limits of this approach become painfully evident when one
- finds him or herself responsible for managing a great many machines.
+ tasks such as templating and simple response generation.
Reliability
:app:`Pyramid` is developed conservatively and tested exhaustively. Where
@@ -219,7 +217,8 @@ that the Pyramid core doesn't. Add-on packages already exist which let you
easily send email, let you use the Jinja2 templating system, let you use
XML-RPC or JSON-RPC, let you integrate with jQuery Mobile, etc.
-Examples: http://docs.pylonsproject.org/docs/pyramid.html#pyramid-add-on-documentation
+Examples: http://docs.pylonsproject.org/en/latest/docs/pyramid.html#pyramid-add-on-documentation
+
Class-based and function-based views
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -603,10 +602,10 @@ Examples: :ref:`hello_traversal_chapter` and
Tweens
~~~~~~
-Pyramid has a sort of internal WSGI-middleware-ish pipeline that can be
-hooked by arbitrary add-ons named "tweens". The debug toolbar is a "tween",
-and the ``pyramid_tm`` transaction manager is also. Tweens are more useful
-than WSGI middleware in some circumstances because they run in the context of
+Pyramid has a sort of internal WSGI-middleware-ish pipeline that can be hooked
+by arbitrary add-ons named "tweens". The debug toolbar is a "tween", and the
+``pyramid_tm`` transaction manager is also. Tweens are more useful than WSGI
+:term:`middleware` in some circumstances because they run in the context of
Pyramid itself, meaning you have access to templates and other renderers, a
"real" request object, and other niceties.
@@ -860,7 +859,7 @@ It's our goal that no Pyramid question go unanswered. Whether you ask a
question on IRC, on the Pylons-discuss maillist, or on StackOverflow, you're
likely to get a reasonably prompt response. We don't tolerate "support
trolls" or other people who seem to get their rocks off by berating fellow
-users in our various offical support channels. We try to keep it well-lit
+users in our various official support channels. We try to keep it well-lit
and new-user-friendly.
Example: Visit irc\://freenode.net#pyramid (the ``#pyramid`` channel on
diff --git a/docs/narr/introspector.rst b/docs/narr/introspector.rst
index 7784e8960..dec22c5b1 100644
--- a/docs/narr/introspector.rst
+++ b/docs/narr/introspector.rst
@@ -7,6 +7,8 @@
Pyramid Configuration Introspection
===================================
+.. versionadded:: 1.3
+
When Pyramid starts up, each call to a :term:`configuration directive` causes
one or more :term:`introspectable` objects to be registered with an
:term:`introspector`. The introspector can be queried by application code to
@@ -15,10 +17,6 @@ feature is useful for debug toolbars, command-line scripts which show some
aspect of configuration, and for runtime reporting of startup-time
configuration settings.
-.. warning::
-
- Introspection is new in Pyramid 1.3.
-
Using the Introspector
----------------------
diff --git a/docs/narr/logging.rst b/docs/narr/logging.rst
index f4c38abb6..b3bfb8a1e 100644
--- a/docs/narr/logging.rst
+++ b/docs/narr/logging.rst
@@ -22,25 +22,23 @@ Logging Configuration
---------------------
A :app:`Pyramid` project created from a :term:`scaffold` is configured to
-allow you to send messages to `Python standard library logging package
-<http://docs.python.org/library/logging.html>`_ loggers from within your
+allow you to send messages to :mod:`Python standard library logging package
+<logging>` loggers from within your
application. In particular, the :term:`PasteDeploy` ``development.ini`` and
``production.ini`` files created when you use a scaffold include a basic
configuration for the Python :mod:`logging` package.
-PasteDeploy ``.ini`` files use the Python standard library `ConfigParser
-format <http://docs.python.org/lib/module-ConfigParser.html>`_; this the same
-format used as the Python `logging module's Configuration file format
-<http://docs.python.org/lib/logging-config-fileformat.html>`_. The
-application-related and logging-related sections in the configuration file
+PasteDeploy ``.ini`` files use the Python standard library :mod:`ConfigParser
+format <ConfigParser>`; this is the same format used as the Python
+:ref:`logging module's Configuration file format <logging-config-fileformat>`.
+The application-related and logging-related sections in the configuration file
can coexist peacefully, and the logging-related sections in the file are used
from when you run ``pserve``.
The ``pserve`` command calls the :func:`pyramid.paster.setup_logging`
-function, a thin wrapper around the `logging.fileConfig
-<http://docs.python.org/lib/logging-config-api.html>`_ using the specified
-ini file if it contains a ``[loggers]`` section (all of the
-scaffold-generated ``.ini`` files do). ``setup_logging`` reads the
+function, a thin wrapper around the :func:`logging.config.fileConfig`
+using the specified ``.ini`` file if it contains a ``[loggers]`` section
+(all of the scaffold-generated ``.ini`` files do). ``setup_logging`` reads the
logging configuration from the ini file upon which ``pserve`` was
invoked.
@@ -300,14 +298,14 @@ Request Logging with Paste's TransLogger
----------------------------------------
Paste provides the `TransLogger
-<http://pythonpaste.org/modules/translogger.html>`_ middleware for logging
-requests using the `Apache Combined Log Format
+<http://pythonpaste.org/modules/translogger.html>`_ :term:`middleware` for
+logging requests using the `Apache Combined Log Format
<http://httpd.apache.org/docs/2.2/logs.html#combined>`_. TransLogger combined
with a FileHandler can be used to create an ``access.log`` file similar to
Apache's.
-Like any standard middleware with a Paste entry point, TransLogger can be
-configured to wrap your application using ``.ini`` file syntax. First,
+Like any standard :term:`middleware` with a Paste entry point, TransLogger can
+be configured to wrap your application using ``.ini`` file syntax. First,
rename your Pyramid ``.ini`` file's ``[app:main]`` section to
``[app:mypyramidapp]``, then add a ``[filter:translogger]`` section, then use
a ``[pipeline:main]`` section file to form a WSGI pipeline with both the
@@ -334,7 +332,7 @@ To this:
mypyramidapp
Using PasteDeploy this way to form and serve a pipeline is equivalent to
-wrapping your app in a TransLogger instance via the bottom the ``main``
+wrapping your app in a TransLogger instance via the bottom of the ``main``
function of your project's ``__init__`` file:
.. code-block:: python
@@ -350,7 +348,7 @@ called with no arguments, so it 'just works' in environments that don't
configure logging. Since we've configured our own logging handlers, we need
to disable that option via ``setup_console_handler = False``.
-With the filter in place, TransLogger's logger (named the 'wsgi' logger) will
+With the filter in place, TransLogger's logger (named the ``wsgi`` logger) will
propagate its log messages to the parent logger (the root logger), sending
its output to the console when we request a page:
@@ -364,14 +362,18 @@ its output to the console when we request a page:
Firefox/2.0.0.6"
To direct TransLogger to an ``access.log`` FileHandler, we need to add that
-FileHandler to the wsgi logger's list of handlers:
+FileHandler to the list of handlers (named ``accesslog``), and ensure that the
+``wsgi`` logger is configured and uses this handler accordingly:
.. code-block:: ini
# Begin logging configuration
- [loggers]
- keys = root, myapp, wsgi
+ [loggers]
+ keys = root, myapp, wsgi
+
+ [handlers]
+ keys = console, accesslog
[logger_wsgi]
level = INFO
@@ -387,20 +389,19 @@ FileHandler to the wsgi logger's list of handlers:
As mentioned above, non-root loggers by default propagate their log records
to the root logger's handlers (currently the console handler). Setting
-``propagate`` to 0 (false) here disables this; so the ``wsgi`` logger directs
-its records only to the ``accesslog`` handler.
+``propagate`` to ``0`` (``False``) here disables this; so the ``wsgi`` logger
+directs its records only to the ``accesslog`` handler.
Finally, there's no need to use the ``generic`` formatter with TransLogger as
TransLogger itself provides all the information we need. We'll use a
-formatter that passes-through the log messages as is:
+formatter that passes-through the log messages as is. Add a new formatter
+called ``accesslog`` by include the following in your configuration file:
.. code-block:: ini
[formatters]
keys = generic, accesslog
-.. code-block:: ini
-
[formatter_accesslog]
format = %(message)s
diff --git a/docs/narr/muchadoabouttraversal.rst b/docs/narr/muchadoabouttraversal.rst
index 40d498391..483b1bb16 100644
--- a/docs/narr/muchadoabouttraversal.rst
+++ b/docs/narr/muchadoabouttraversal.rst
@@ -168,18 +168,12 @@ hood, when ``adict`` is a dictionary-like object, Python translates
``adict['a']`` to ``adict.__getitem__('a')``. Try doing this in a Python
interpreter prompt if you don't believe us:
-.. code-block:: text
- :linenos:
-
- Python 2.4.6 (#2, Apr 29 2010, 00:31:48)
- [GCC 4.4.3] on linux2
- Type "help", "copyright", "credits" or "license" for more information.
- >>> adict = {}
- >>> adict['a'] = 1
- >>> adict['a']
- 1
- >>> adict.__getitem__('a')
- 1
+>>> adict = {}
+>>> adict['a'] = 1
+>>> adict['a']
+1
+>>> adict.__getitem__('a')
+1
The dictionary-like root object stores the ids of all of its subresources as
diff --git a/docs/narr/paste.rst b/docs/narr/paste.rst
index 86b047aec..3427b6d53 100644
--- a/docs/narr/paste.rst
+++ b/docs/narr/paste.rst
@@ -21,7 +21,7 @@ of starting, stopping, and debugging an application.
This chapter is not a replacement for documentation about PasteDeploy; it
only contextualizes the use of PasteDeploy within Pyramid. For detailed
-documentation, see http://pythonpaste.org.
+documentation, see http://pythonpaste.org/deploy/.
PasteDeploy
-----------
@@ -62,7 +62,7 @@ Take a look at the generated ``setup.py`` file for this project.
:language: python
:linenos:
-Note that the ``entry_point`` line in ``setup.py`` points at a string which
+Note that ``entry_points`` is assigned a string which
looks a lot like an ``.ini`` file. This string representation of an ``.ini``
file has a section named ``[paste.app_factory]``. Within this section, there
is a key named ``main`` (the entry point name) which has a value
@@ -85,6 +85,8 @@ function. This is the function called by :term:`PasteDeploy` when the
``pserve`` command is invoked against our application. It accepts a global
configuration object and *returns* an instance of our application.
+.. _defaults_section_of_pastedeploy_file:
+
``[DEFAULTS]`` Section of a PasteDeploy ``.ini`` File
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index 5a8ea0ecf..52f13d5a8 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -49,9 +49,7 @@ The included scaffolds are these:
URL mapping via :term:`URL dispatch` and no persistence mechanism.
``zodb``
- URL mapping via :term:`traversal` and persistence via :term:`ZODB`. *Note
- that, as of this writing, this scaffold will not run under Python 3, only
- under Python 2.*
+ URL mapping via :term:`traversal` and persistence via :term:`ZODB`.
``alchemy``
URL mapping via :term:`URL dispatch` and persistence via
@@ -80,13 +78,13 @@ On UNIX:
.. code-block:: text
- $ bin/pcreate -s starter MyProject
+ $ $VENV/bin/pcreate -s starter MyProject
Or on Windows:
.. code-block:: text
- > Scripts\pcreate -s starter MyProject
+ > %VENV%\Scripts\pcreate -s starter MyProject
The above command uses the ``pcreate`` command to create a project with the
``starter`` scaffold. To use a different scaffold, such as
@@ -95,20 +93,20 @@ on UNIX:
.. code-block:: text
- $ bin/pcreate -s alchemy MyProject
+ $ $VENV/bin/pcreate -s alchemy MyProject
Or on Windows:
.. code-block:: text
- > Scripts\pcreate -s alchemy MyProject
+ > %VENV%\Scripts\pcreate -s alchemy MyProject
Here's sample output from a run of ``pcreate`` on UNIX for a project we name
``MyProject``:
.. code-block:: text
- $ bin/pcreate -s starter MyProject
+ $ $VENV/bin/pcreate -s starter MyProject
Creating template pyramid
Creating directory ./MyProject
# ... more output ...
@@ -177,21 +175,21 @@ On UNIX:
.. code-block:: text
$ cd MyProject
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
Or on Windows:
.. code-block:: text
> cd MyProject
- > ..\Scripts\python.exe setup.py develop
+ > %VENV%\Scripts\python.exe setup.py develop
Elided output from a run of this command on UNIX is shown below:
.. code-block:: text
$ cd MyProject
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
...
Finished processing dependencies for MyProject==0.0
@@ -216,19 +214,19 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py test -q
+ $ $VENV/bin/python setup.py test -q
Or on Windows:
.. code-block:: text
- > ..\Scripts\python.exe setup.py test -q
+ > %VENV%\Scripts\python.exe setup.py test -q
Here's sample output from a test run on UNIX:
.. code-block:: text
- $ ../bin/python setup.py test -q
+ $ $VENV/bin/python setup.py test -q
running test
running egg_info
writing requirements to MyProject.egg-info/requires.txt
@@ -272,19 +270,19 @@ On UNIX:
.. code-block:: text
- $ ../bin/pserve development.ini
+ $ $VENV/bin/pserve development.ini
On Windows:
.. code-block:: text
- > ..\Scripts\pserve development.ini
+ > %VENV%\Scripts\pserve development.ini
Here's sample output from a run of ``pserve`` on UNIX:
.. code-block:: text
- $ ../bin/pserve development.ini
+ $ $VENV/bin/pserve development.ini
Starting server in PID 16601.
serving on http://0.0.0.0:6543
@@ -305,7 +303,9 @@ 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::
+example:
+
+.. code-block:: ini
[server:main]
use = egg:waitress#main
@@ -357,7 +357,7 @@ For example, on UNIX:
.. code-block:: text
- $ ../bin/pserve development.ini --reload
+ $ $VENV/bin/pserve development.ini --reload
Starting subprocess with file monitor
Starting server in PID 16601.
serving on http://0.0.0.0:6543
@@ -414,7 +414,7 @@ If you don't see the debug toolbar image on the right hand top of the page,
it means you're browsing from a system that does not have debugging access.
By default, for security reasons, only a browser originating from
``localhost`` (``127.0.0.1``) can see the debug toolbar. To allow your
-browser on a remote system to access the server, add the a line within the
+browser on a remote system to access the server, add a line within the
``[app:main]`` section of the ``development.ini`` file in the form
``debugtoolbar.hosts = X.X.X.X``. For example, if your Pyramid application
is running on a remote system, and you're browsing from a host with the IP
@@ -459,20 +459,9 @@ Put a hash mark at the beginning of the ``pyramid_debugtoolbar`` line:
Then restart the application to see that the toolbar has been turned off.
Note that if you comment out the ``pyramid_debugtoolbar`` line, the ``#``
-*must* be in the first column. If you put the hash mark anywhere except the
-first column instead, for example like this:
-
-.. code-block:: ini
- :linenos:
-
- [app:main]
- ...
- pyramid.includes =
- #pyramid_debugtoolbar
-
-When you attempt to restart the application with a section like the above
-you'll receive an error that ends something like this, and the application
-will not start:
+*must* be in the first column. If you put it anywhere else,
+and then attempt to restart the application,
+you'll receive an error that ends something like this:
.. code-block:: text
@@ -703,7 +692,7 @@ work properly.
The ``setup.py`` file is a :term:`setuptools` setup file. It is meant to be
run directly from the command line to perform a variety of functions, such as
-testing your application, packaging, and distributing your application.
+testing, packaging, and distributing your application.
.. note::
@@ -1001,6 +990,8 @@ prompt with a similar configuration as would be loaded if you were running
your Pyramid application via ``pserve``. This can be a useful debugging tool.
See :ref:`interactive_shell` for more details.
+.. _what_is_this_pserve_thing:
+
What Is This ``pserve`` Thing
-----------------------------
@@ -1014,12 +1005,12 @@ Pyramid application based on the data in the file.
application. As we saw in :ref:`firstapp_chapter`, ``pserve`` needn't be
invoked at all to run a :app:`Pyramid` application. The use of ``pserve`` to
run a :app:`Pyramid` application is purely conventional based on the output
-of its scaffolding. But we strongly recommend using while developing your
-application, because many other convenience introspection commands (such as
-``pviews``, ``prequest``, ``proutes`` and others) are also implemented in
-terms of configuration availability of this ``.ini`` file format. It also
-configures Pyramid logging and provides the ``--reload`` switch for
-convenient restarting of the server when code changes.
+of its scaffolding. But we strongly recommend using ``pserve`` while
+developing your application, because many other convenience introspection
+commands (such as ``pviews``, ``prequest``, ``proutes`` and others) are also
+implemented in terms of configuration availability of this ``.ini`` file
+format. It also configures Pyramid logging and provides the ``--reload``
+switch for convenient restarting of the server when code changes.
.. _alternate_wsgi_server:
diff --git a/docs/narr/renderers.rst b/docs/narr/renderers.rst
index 08ebd881e..a2811dbae 100644
--- a/docs/narr/renderers.rst
+++ b/docs/narr/renderers.rst
@@ -33,14 +33,11 @@ by the view must be compatible with the particular kind of renderer used, or
an error may occur during view invocation.
One exception exists: it is *always* OK to return a Response object, even
-when a ``renderer`` is configured. If a view callable returns a response
-object from a view that is configured with a renderer, the renderer is
+when a ``renderer`` is configured. In such cases, the renderer is
bypassed entirely.
Various types of renderers exist, including serialization renderers
-and renderers which use templating systems. See also
-:ref:`views_which_use_a_renderer`.
-
+and renderers which use templating systems.
.. index::
single: renderer
@@ -51,8 +48,8 @@ and renderers which use templating systems. See also
Writing View Callables Which Use a Renderer
-------------------------------------------
-As we've seen, view callables needn't always return a Response object.
-Instead, they may return an arbitrary Python object, with the expectation
+As we've seen, a view callable needn't always return a Response object.
+Instead, it may return an arbitrary Python object, with the expectation
that a :term:`renderer` will convert that object into a response instance on
your behalf. Some renderers use a templating system; other renderers use
object serialization techniques.
@@ -80,12 +77,10 @@ response attributes (such as headers and the HTTP status code) by attaching a
property to the ``request.response`` attribute.
See :ref:`request_response_attr`.
-If the :term:`view callable` associated with a :term:`view configuration`
-returns a Response object directly, any renderer associated with the view
-configuration is ignored, and the response is passed back to :app:`Pyramid`
-unchanged. For example, if your view callable returns an instance of the
-:class:`pyramid.response.Response` class as a response, no renderer
-will be employed.
+As already mentioned, if the :term:`view callable` associated with a
+:term:`view configuration` returns a Response object (or its instance),
+any renderer associated with the view configuration is ignored,
+and the response is passed back to :app:`Pyramid` unchanged. For example:
.. code-block:: python
:linenos:
@@ -140,7 +135,7 @@ used in the ``renderer`` attribute of view configurations.
``string``: String Renderer
~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The ``string`` renderer is a renderer which renders a view callable result to
+The ``string`` renderer renders a view callable result to
a string. If a view callable returns a non-Response object, and the
``string`` renderer is associated in that view's configuration, the result
will be to run the object through the Python ``str`` function to generate a
@@ -203,7 +198,7 @@ representing the JSON serialization of the return value:
.. code-block:: python
- '{"content": "Hello!"}'
+ {"content": "Hello!"}
The return value needn't be a dictionary, but the return value must contain
values serializable by the configured serializer (by default ``json.dumps``).
@@ -362,7 +357,7 @@ For example (Javascript):
jqhxr = $.getJSON(api_url);
The string ``callback=?`` above in the ``url`` param to the JQuery
-``getAjax`` function indicates to jQuery that the query should be made as
+``getJSON`` function indicates to jQuery that the query should be made as
a JSONP request; the ``callback`` parameter will be automatically filled
in for you and used.
@@ -720,7 +715,7 @@ factory, which expects to be passed a filesystem path:
Adding the above code to your application startup will allow you to use the
``my.package.MyJinja2Renderer`` renderer factory implementation in view
-configurations by referring to any ``renderer`` which *ends in* ``.jinja`` in
+configurations by referring to any ``renderer`` which *ends in* ``.jinja2`` in
the ``renderer`` attribute of a :term:`view configuration`:
.. code-block:: python
diff --git a/docs/narr/resources.rst b/docs/narr/resources.rst
index a24c44f29..b1bb611e5 100644
--- a/docs/narr/resources.rst
+++ b/docs/narr/resources.rst
@@ -171,7 +171,7 @@ you will reach the filesystem root directory.
URL generated (as opposed to a single leading slash or empty tuple
element).
-.. sidebar:: Using :mod:`pyramid_traversalwrapper`
+.. sidebar:: For your convenience
If you'd rather not manage the ``__name__`` and ``__parent__`` attributes
of your resources "by hand", an add-on package named
@@ -300,7 +300,7 @@ the resource by :meth:`~pyramid.request.Request.resource_url`.
The ``__resource_url__`` hook is passed two arguments: ``request`` and
``info``. ``request`` is the :term:`request` object passed to
:meth:`~pyramid.request.Request.resource_url`. ``info`` is a dictionary with
-two keys:
+the following keys:
``physical_path``
A string representing the "physical path" computed for the resource, as
diff --git a/docs/narr/router.rst b/docs/narr/router.rst
index b78362066..ac3deefdc 100644
--- a/docs/narr/router.rst
+++ b/docs/narr/router.rst
@@ -46,7 +46,7 @@ request enters a :app:`Pyramid` application through to the point that
:class:`~pyramid.interfaces.IRoute` object representing the route which
matched. The root object associated with the route found is also
generated: if the :term:`route configuration` which matched has an
- associated a ``factory`` argument, this factory is used to generate the
+ associated ``factory`` argument, this factory is used to generate the
root object, otherwise a default :term:`root factory` is used.
#. If a route match was *not* found, and a ``root_factory`` argument was
diff --git a/docs/narr/scaffolding.rst b/docs/narr/scaffolding.rst
index 9ac579a87..534b2caf4 100644
--- a/docs/narr/scaffolding.rst
+++ b/docs/narr/scaffolding.rst
@@ -74,10 +74,14 @@ concrete examples of scaffold directories (``zodb``, ``alchemy``, and
After you've created the template directory, add the following to the
``entry_points`` value of your distribution's ``setup.py``:
- [pyramid.scaffold]
- coolextension=coolextension.scaffolds:CoolExtensionTemplate
+.. code-block:: ini
+
+ [pyramid.scaffold]
+ coolextension=coolextension.scaffolds:CoolExtensionTemplate
-For example::
+For example:
+
+.. code-block:: python
def setup(
...,
@@ -95,7 +99,7 @@ because that's the name we gave it in the entry point setup. Running
output directory named ``MyStuff``.
See the module documentation for :mod:`pyramid.scaffolds` for information
-about the API of the :class:`pyramid.scaffolds.PyramidScaffold` class and
+about the API of the :class:`pyramid.scaffolds.Template` class and
related classes. You can override methods of this class to get special
behavior.
diff --git a/docs/narr/security.rst b/docs/narr/security.rst
index 3a94b4f7d..6517fedf8 100644
--- a/docs/narr/security.rst
+++ b/docs/narr/security.rst
@@ -65,7 +65,7 @@ policies.
Enabling an Authorization Policy
--------------------------------
-By default, :app:`Pyramid` enables no authorization policy. All
+:app:`Pyramid` does not enable any authorization policy by default. All
views are accessible by completely anonymous users. In order to begin
protecting views from execution based on security settings, you need
to enable an authorization policy.
@@ -80,12 +80,11 @@ policy.
You must also enable an :term:`authentication policy` in order to enable the
authorization policy. This is because authorization, in general, depends
upon authentication. Use the
-:meth:`~pyramid.config.Configurator.set_authentication_policy` and method
+:meth:`~pyramid.config.Configurator.set_authentication_policy` method
during application setup to specify the authentication policy.
For example:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -98,7 +97,7 @@ For example:
config.set_authentication_policy(authn_policy)
config.set_authorization_policy(authz_policy)
-.. note:: the ``authentication_policy`` and ``authorization_policy``
+.. note:: The ``authentication_policy`` and ``authorization_policy``
arguments may also be passed to their respective methods mentioned above
as :term:`dotted Python name` values, each representing the dotted name
path to a suitable implementation global defined at Python module scope.
@@ -151,7 +150,6 @@ API:
The equivalent view registration including the ``add`` permission name
may be performed via the ``@view_config`` decorator:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -234,8 +232,8 @@ class:
.. code-block:: python
:linenos:
- from pyramid.security import Everyone
from pyramid.security import Allow
+ from pyramid.security import Everyone
class Blog(object):
__acl__ = [
@@ -250,8 +248,8 @@ Or, if your resources are persistent, an ACL might be specified via the
.. code-block:: python
:linenos:
- from pyramid.security import Everyone
from pyramid.security import Allow
+ from pyramid.security import Everyone
class Blog(object):
pass
@@ -270,6 +268,27 @@ resource instances with an ACL (as opposed to just decorating their class) in
applications such as "CMS" systems where fine-grained access is required on
an object-by-object basis.
+Dynamic ACLs are also possible by turning the ACL into a callable on the
+resource. This may allow the ACL to dynamically generate rules based on
+properties of the instance.
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.security import Allow
+ from pyramid.security import Everyone
+
+ class Blog(object):
+ def __acl__(self):
+ return [
+ (Allow, Everyone, 'view'),
+ (Allow, self.owner, 'edit'),
+ (Allow, 'group:editors', 'edit'),
+ ]
+
+ def __init__(self, owner):
+ self.owner = owner
+
.. index::
single: ACE
single: access control entry
@@ -282,8 +301,8 @@ Here's an example ACL:
.. code-block:: python
:linenos:
- from pyramid.security import Everyone
from pyramid.security import Allow
+ from pyramid.security import Everyone
__acl__ = [
(Allow, Everyone, 'view'),
@@ -312,7 +331,7 @@ A principal is usually a user id, however it also may be a group id if your
authentication system provides group information and the effective
:term:`authentication policy` policy is written to respect group information.
For example, the
-:class:`pyramid.authentication.RepozeWho1AuthenicationPolicy` respects group
+:class:`pyramid.authentication.RepozeWho1AuthenticationPolicy` respects group
information if you configure it with a ``callback``.
Each ACE in an ACL is processed by an authorization policy *in the
@@ -321,9 +340,9 @@ order dictated by the ACL*. So if you have an ACL like this:
.. code-block:: python
:linenos:
- from pyramid.security import Everyone
from pyramid.security import Allow
from pyramid.security import Deny
+ from pyramid.security import Everyone
__acl__ = [
(Allow, Everyone, 'view'),
@@ -359,8 +378,8 @@ ACE, as below.
.. code-block:: python
:linenos:
- from pyramid.security import Everyone
from pyramid.security import Allow
+ from pyramid.security import Everyone
__acl__ = [
(Allow, Everyone, 'view'),
@@ -507,7 +526,7 @@ example:
.. code-block:: text
- $ PYRAMID_DEBUG_AUTHORIZATION=1 bin/pserve myproject.ini
+ $ PYRAMID_DEBUG_AUTHORIZATION=1 $VENV/bin/pserve myproject.ini
When any authorization takes place during a top-level view rendering,
a message will be logged to the console (to stderr) about what ACE in
diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst
index fa4affd8a..358977089 100644
--- a/docs/narr/sessions.rst
+++ b/docs/narr/sessions.rst
@@ -148,6 +148,7 @@ Some gotchas:
.. index::
single: pyramid_beaker
single: Beaker
+ single: pyramid_redis_sessions
single: session factory (alternates)
.. _using_alternate_session_factories:
@@ -155,11 +156,17 @@ Some gotchas:
Using Alternate Session Factories
---------------------------------
-At the time of this writing, exactly one alternate session factory
-implementation exists, named ``pyramid_beaker``. This is a session factory
-that uses the `Beaker <http://beaker.groovie.org/>`_ library as a backend.
-Beaker has support for file-based sessions, database based sessions, and
-encrypted cookie-based sessions. See `the pyramid_beaker documentation
+At the time of this writing, exactly two alternate session factories
+exist.
+
+The first is named ``pyramid_redis_sessions``. It can be downloaded from PyPI.
+It uses Redis as a backend. It is the recommended persistent session solution
+at the time of this writing.
+
+The second is named ``pyramid_beaker``. This is a session factory that uses the
+`Beaker <http://beaker.groovie.org/>`_ library as a backend. Beaker has
+support for file-based sessions, database based sessions, and encrypted
+cookie-based sessions. See `the pyramid_beaker documentation
<http://docs.pylonsproject.org/projects/pyramid_beaker/en/latest/>`_ for more
information about ``pyramid_beaker``.
@@ -181,6 +188,8 @@ implementation in the :mod:`pyramid.session` module as inspiration.
.. index::
single: flash messages
+.. _flash_messages:
+
Flash Messages
--------------
@@ -252,25 +261,19 @@ that were added to the flash queue, and empties the queue.
.. method:: pop_flash(queue='')
-.. code-block:: python
- :linenos:
-
- >>> request.session.flash('info message')
- >>> request.session.pop_flash()
- ['info message']
+>>> request.session.flash('info message')
+>>> request.session.pop_flash()
+['info message']
Calling ``session.pop_flash()`` again like above without a corresponding call
to ``session.flash()`` will return an empty list, because the queue has already
been popped.
-.. code-block:: python
- :linenos:
-
- >>> request.session.flash('info message')
- >>> request.session.pop_flash()
- ['info message']
- >>> request.session.pop_flash()
- []
+>>> request.session.flash('info message')
+>>> request.session.pop_flash()
+['info message']
+>>> request.session.pop_flash()
+[]
.. index::
single: session.peek_flash
@@ -285,18 +288,15 @@ popped from flash storage.
.. method:: peek_flash(queue='')
-.. code-block:: python
- :linenos:
-
- >>> request.session.flash('info message')
- >>> request.session.peek_flash()
- ['info message']
- >>> request.session.peek_flash()
- ['info message']
- >>> request.session.pop_flash()
- ['info message']
- >>> request.session.peek_flash()
- []
+>>> request.session.flash('info message')
+>>> request.session.peek_flash()
+['info message']
+>>> request.session.peek_flash()
+['info message']
+>>> request.session.pop_flash()
+['info message']
+>>> request.session.peek_flash()
+[]
.. index::
single: preventing cross-site request forgery attacks
@@ -307,14 +307,15 @@ Preventing Cross-Site Request Forgery Attacks
`Cross-site request forgery
<http://en.wikipedia.org/wiki/Cross-site_request_forgery>`_ attacks are a
-phenomenon whereby a user with an identity on your website might click on a
-URL or button on another website which secretly redirects the user to your
-application to perform some command that requires elevated privileges.
-
-You can avoid most of these attacks by making sure that the correct *CSRF
-token* has been set in an :app:`Pyramid` session object before performing any
-actions in code which requires elevated privileges that is invoked via a form
-post. To use CSRF token support, you must enable a :term:`session factory`
+phenomenon whereby a user who is logged in to your website might inadvertantly
+load a URL because it is linked from, or embedded in, an attacker's website.
+If the URL is one that may modify or delete data, the consequences can be dire.
+
+You can avoid most of these attacks by issuing a unique token to the browser
+and then requiring that it be present in all potentially unsafe requests.
+:app:`Pyramid` sessions provide facilities to create and check CSRF tokens.
+
+To use CSRF tokens, you must first enable a :term:`session factory`
as described in :ref:`using_the_default_session_factory` or
:ref:`using_alternate_session_factories`.
@@ -333,33 +334,82 @@ To get the current CSRF token from the session, use the
The ``session.get_csrf_token()`` method accepts no arguments. It returns a
CSRF *token* string. If ``session.get_csrf_token()`` or
-``session.new_csrf_token()`` was invoked previously for this session, the
+``session.new_csrf_token()`` was invoked previously for this session, then the
existing token will be returned. If no CSRF token previously existed for
-this session, a new token will be will be set into the session and returned.
+this session, then a new token will be will be set into the session and returned.
The newly created token will be opaque and randomized.
You can use the returned token as the value of a hidden field in a form that
-posts to a method that requires elevated privileges. The handler for the
-form post should use ``session.get_csrf_token()`` *again* to obtain the
-current CSRF token related to the user from the session, and compare it to
-the value of the hidden form field. For example, if your form rendering
-included the CSRF token obtained via ``session.get_csrf_token()`` as a hidden
-input field named ``csrf_token``:
+posts to a method that requires elevated privileges, or supply it as a request
+header in AJAX requests.
+
+For example, include the CSRF token as a hidden field:
+
+.. code-block:: html
+
+ <form method="post" action="/myview">
+ <input type="hidden" name="csrf_token" value="${request.session.get_csrf_token()}">
+ <input type="submit" value="Delete Everything">
+ </form>
+
+Or, include it as a header in a jQuery AJAX request:
+
+.. code-block:: javascript
+
+ var csrfToken = ${request.session.get_csrf_token()};
+ $.ajax({
+ type: "POST",
+ url: "/myview",
+ headers: { 'X-CSRF-Token': csrfToken }
+ }).done(function() {
+ alert("Deleted");
+ });
+
+
+The handler for the URL that receives the request
+should then require that the correct CSRF token is supplied.
+
+Using the ``session.check_csrf_token`` Method
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In request handling code, you can check the presence and validity of a CSRF
+token with ``session.check_csrf_token(request)``. If the token is valid,
+it will return True, otherwise it will raise ``HTTPBadRequest``.
+
+By default, it checks for a GET or POST parameter named ``csrf_token`` or a
+header named ``X-CSRF-Token``.
.. code-block:: python
- :linenos:
- token = request.session.get_csrf_token()
- if token != request.POST['csrf_token']:
- raise ValueError('CSRF token did not match')
+ def myview(request):
+ session = request.session
+
+ # Require CSRF Token
+ session.check_csrf_token(request):
+
+ ...
.. index::
single: session.new_csrf_token
+Checking CSRF Tokens With A View Predicate
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A convenient way to require a valid CSRF Token for a particular view is to
+include ``check_csrf=True`` as a view predicate.
+See :meth:`pyramid.config.Configurator.add_route`.
+
+.. code-block:: python
+
+ @view_config(request_method='POST', check_csrf=True, ...)
+ def myview(request):
+ ...
+
+
Using the ``session.new_csrf_token`` Method
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-To explicitly add a new CSRF token to the session, use the
+To explicitly create a new CSRF token, use the
``session.new_csrf_token()`` method. This differs only from
``session.get_csrf_token()`` inasmuch as it clears any existing CSRF token,
creates a new CSRF token, sets the token into the session, and returns the
diff --git a/docs/narr/startup.rst b/docs/narr/startup.rst
index f5c741f52..1affa1758 100644
--- a/docs/narr/startup.rst
+++ b/docs/narr/startup.rst
@@ -8,12 +8,12 @@ you'll see something much like this show up on the console:
.. code-block:: text
- $ pserve myproject/MyProject.ini
+ $ pserve development.ini
Starting server in PID 16601.
serving on 0.0.0.0:6543 view at http://127.0.0.1:6543
This chapter explains what happens between the time you press the "Return"
-key on your keyboard after typing ``pserve myproject/MyProject.ini``
+key on your keyboard after typing ``pserve development.ini``
and the time the line ``serving on 0.0.0.0:6543 ...`` is output to your
console.
@@ -77,9 +77,9 @@ Here's a high-level time-ordered overview of what happens when you press
Note that the constructor function accepts a ``global_config`` argument,
which is a dictionary of key/value pairs mentioned in the ``[DEFAULT]``
- section of an ``.ini`` file (if `[DEFAULT]
- <http://docs.pylonsproject.org/projects/pyramid/dev/narr/paste.html#defaults-section-of-a-pastedeploy-ini-file>`__
- is present). It also accepts a ``**settings`` argument, which collects
+ section of an ``.ini`` file
+ (if :ref:`[DEFAULT] <defaults_section_of_pastedeploy_file>` is present).
+ It also accepts a ``**settings`` argument, which collects
another set of arbitrary key/value pairs. The arbitrary key/value pairs
received by this function in ``**settings`` will be composed of all the
key/value pairs that are present in the ``[app:main]`` section (except for
diff --git a/docs/narr/subrequest.rst b/docs/narr/subrequest.rst
index 033f045a6..6437bd0fa 100644
--- a/docs/narr/subrequest.rst
+++ b/docs/narr/subrequest.rst
@@ -155,7 +155,7 @@ In the example above, the call to
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
+configured instead of raising the exception. This is because exception views
are called by the exception view :term:`tween` as described in
:ref:`exception_views` when any view raises an exception.
@@ -223,16 +223,16 @@ unconditionally:
: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
+- causes a :class:`~pyramid.events.NewRequest` event to be sent at the
beginning of request processing.
-- causes a :class:`~pyramid.event.ContextFound` event to be sent when a
+- causes a :class:`~pyramid.events.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
+- causes a :class:`~pyramid.events.NewResponse` event to be sent when the
Pyramid application returns a response.
- Calls any :term:`response callback` functions defined within the subrequest's
@@ -250,7 +250,7 @@ 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
+object, you'll need to massage 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
diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst
index 6a1fbf916..26bb6b6cd 100644
--- a/docs/narr/templates.rst
+++ b/docs/narr/templates.rst
@@ -150,7 +150,6 @@ string, then return that string as the body of a :app:`Pyramid`
For example, here's an example of using "raw" `Mako
<http://www.makotemplates.org/>`_ from within a :app:`Pyramid` :term:`view`:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -524,7 +523,7 @@ And ``templates/mytemplate.pt`` might look like so:
Using A Chameleon Macro Name Within a Renderer Name
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Sommetime you'd like to render a macro inside of a Chameleon ZPT template
+At times, you may want to render a macro inside of a Chameleon ZPT template
instead of the full Chameleon ZPT template. To render the content of a
``define-macro`` field inside a Chameleon ZPT template, given a Chameleon
template file named ``foo.pt`` and a macro named ``bar`` defined within it
@@ -617,11 +616,13 @@ extension so that these ``svn:ignore`` patterns work.
.. index::
pair: debugging; templates
+.. _debugging_templates:
+
Debugging Templates
-------------------
A :exc:`NameError` exception resulting from rendering a template with an
-undefined variable (e.g. ``${wrong}``) might will end like this:
+undefined variable (e.g. ``${wrong}``) might end up looking like this:
.. code-block:: text
@@ -712,7 +713,7 @@ look like:
<h1 class="title">Welcome to <code>${project}</code>, an
application generated by the <a
href="http://docs.pylonsproject.org/projects/pyramid/current/"
- >pyramid</a> web application framework.</h1>
+ >pyramid</a> web framework.</h1>
</body>
</html>
@@ -724,7 +725,7 @@ This template doesn't use any advanced features of Mako, only the
Using A Mako def name Within a Renderer Name
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Sommetime you'd like to render a ``def`` inside of a Mako template instead of
+Sometimes you'd like to render a ``def`` inside of a Mako template instead of
the full Mako template. To render a def inside a Mako template, given a
:term:`Mako` template file named ``foo.mak`` and a def named ``bar``, you can
configure the template as a :term:`renderer` like so:
@@ -771,7 +772,7 @@ variable set to ``1``, For example:
.. code-block:: text
- $ PYRAMID_RELOAD_TEMPLATES=1 bin/pserve myproject.ini
+ $ PYRAMID_RELOAD_TEMPLATES=1 $VENV/bin/pserve myproject.ini
To use a setting in the application ``.ini`` file for the same
purpose, set the ``pyramid.reload_templates`` key to ``true`` within the
diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst
index 20017064b..88d6904c7 100644
--- a/docs/narr/testing.rst
+++ b/docs/narr/testing.rst
@@ -70,7 +70,7 @@ Test Set Up and Tear Down
--------------------------
:app:`Pyramid` uses a "global" (actually :term:`thread local`) data structure
-to hold on to two items: the current :term:`request` and the current
+to hold two items: the current :term:`request` and the current
:term:`application registry`. These data structures are available via the
:func:`pyramid.threadlocal.get_current_request` and
:func:`pyramid.threadlocal.get_current_registry` functions, respectively.
@@ -125,10 +125,10 @@ method attached to ``MyTest`` will use an isolated registry.
The :func:`~pyramid.testing.setUp` and :func:`~pyramid.testing.tearDown`
functions accepts various arguments that influence the environment of the
-test. See the :ref:`testing_module` chapter for information about the extra
+test. See the :ref:`testing_module` API for information about the extra
arguments supported by these functions.
-If you also want to make :func:`~pyramid.get_current_request` return something
+If you also want to make :func:`~pyramid.threadlocal.get_current_request` return something
other than ``None`` during the course of a single test, you can pass a
:term:`request` object into the :func:`pyramid.testing.setUp` within the
``setUp`` method of your test:
@@ -202,7 +202,7 @@ any ``get_current*`` function.
Using the ``Configurator`` and ``pyramid.testing`` APIs in Unit Tests
---------------------------------------------------------------------
-The ``Configurator`` API and the ``pyramid.testing`` module provide a number
+The ``Configurator`` API and the :mod:`pyramid.testing` module provide a number
of functions which can be used during unit testing. These functions make
:term:`configuration declaration` calls to the current :term:`application
registry`, but typically register a "stub" or "dummy" feature in place of the
@@ -222,6 +222,12 @@ function.
raise HTTPForbidden
return {'greeting':'hello'}
+.. note::
+
+ This code implies that you have defined a renderer imperatively in a
+ relevant :class:`pyramid.config.Configurator` instance,
+ otherwise it would fail when run normally.
+
Without doing anything special during a unit test, the call to
:func:`~pyramid.security.has_permission` in this view function will always
return a ``True`` value. When a :app:`Pyramid` application starts normally,
@@ -231,7 +237,7 @@ application registry is not created and populated (e.g. by initializing the
configurator with an authorization policy), like when you invoke application
code via a unit test, :app:`Pyramid` API functions will tend to either fail
or return default results. So how do you test the branch of the code in this
-view function that raises :exc:`HTTPForbidden`?
+view function that raises :exc:`~pyramid.httpexceptions.HTTPForbidden`?
The testing API provided by :app:`Pyramid` allows you to simulate various
application registry registrations for use under a unit testing framework
@@ -272,7 +278,7 @@ without needing to invoke the actual application configuration implied by its
self.assertEqual(response, {'greeting':'hello'})
In the above example, we create a ``MyTest`` test case that inherits from
-:mod:`unittest.TestCase`. If it's in our :app:`Pyramid` application, it will
+:class:`unittest.TestCase`. If it's in our :app:`Pyramid` application, it will
be found when ``setup.py test`` is run. It has two test methods.
The first test method, ``test_view_fn_forbidden`` tests the ``view_fn`` when
@@ -287,10 +293,11 @@ request object that requires less setup than a "real" :app:`Pyramid` request.
We call the function being tested with the manufactured request. When the
function is called, :func:`pyramid.security.has_permission` will call the
"dummy" authentication policy we've registered through
-:meth:`~pyramid.config.Configuration.testing_securitypolicy`, which denies
-access. We check that the view function raises a :exc:`HTTPForbidden` error.
+:meth:`~pyramid.config.Configurator.testing_securitypolicy`, which denies
+access. We check that the view function raises a
+:exc:`~pyramid.httpexceptions.HTTPForbidden` error.
-The second test method, named ``test_view_fn_allowed`` tests the alternate
+The second test method, named ``test_view_fn_allowed``, tests the alternate
case, where the authentication policy allows access. Notice that we pass
different values to
:meth:`~pyramid.config.Configurator.testing_securitypolicy` to obtain this
@@ -372,7 +379,7 @@ after accessing some values that require a fully set up environment.
result = my_view(request)
self.assertEqual(result.status, '200 OK')
body = result.app_iter[0]
- self.failUnless('Welcome to' in body)
+ self.assertTrue('Welcome to' in body)
self.assertEqual(len(result.headerlist), 2)
self.assertEqual(result.headerlist[0],
('Content-Type', 'text/html; charset=UTF-8'))
@@ -415,7 +422,7 @@ functional testing package written by Ian Bicking.
def test_root(self):
res = self.testapp.get('/', status=200)
- self.failUnless('Pyramid' in res.body)
+ self.assertTrue('Pyramid' in res.body)
When this test is run, each test creates a "real" WSGI application using the
``main`` function in your ``myapp.__init__`` module and uses :term:`WebTest`
@@ -425,4 +432,4 @@ invoke the root URL. We then assert that the returned HTML has the string
``Pyramid`` in it.
See the :term:`WebTest` documentation for further information about the
-methods available to a :class:`webtest.TestApp` instance.
+methods available to a :class:`webtest.app.TestApp` instance.
diff --git a/docs/narr/threadlocals.rst b/docs/narr/threadlocals.rst
index 909f643a0..a90ee4905 100644
--- a/docs/narr/threadlocals.rst
+++ b/docs/narr/threadlocals.rst
@@ -62,8 +62,7 @@ Because one :app:`Pyramid` application is permitted to call
(perhaps as a :term:`WSGI` app with help from the
:func:`pyramid.wsgi.wsgiapp2` decorator), these variables are
managed in a *stack* during normal system operations. The stack
-instance itself is a `threading.local
-<http://docs.python.org/library/threading.html#threading.local>`_.
+instance itself is a :class:`threading.local`.
During normal operations, the thread locals stack is managed by a
:term:`Router` object. At the beginning of a request, the Router
@@ -130,7 +129,7 @@ follows:
ever be called within application-specific forks of third-party
library code. The library you've forked almost certainly has
nothing to do with :app:`Pyramid`, and making it dependent on
- :app:`Pyramid` (rather than making your :mod:`pyramid`
+ :app:`Pyramid` (rather than making your :app:`pyramid`
application depend upon it) means you're forming a dependency in the
wrong direction.
diff --git a/docs/narr/traversal.rst b/docs/narr/traversal.rst
index 8e7f93a1b..a60c5ba56 100644
--- a/docs/narr/traversal.rst
+++ b/docs/narr/traversal.rst
@@ -22,10 +22,13 @@ resource found as the result of a traversal becomes the
subsystem is used to find some view code willing to "publish" this
resource by generating a :term:`response`.
-Using :term:`Traversal` to map a URL to code is optional. It is often
-less easy to understand than :term:`URL dispatch`, so if you're a rank
-beginner, it probably makes sense to use URL dispatch to map URLs to
-code instead of traversal. In that case, you can skip this chapter.
+.. note::
+
+ Using :term:`Traversal` to map a URL to code is optional. If you're creating
+ your first Pyramid application it probably makes more sense to use :term:`URL
+ dispatch` to map URLs to code instead of traversal, as new Pyramid developers
+ tend to find URL dispatch slightly easier to understand. If you use URL
+ dispatch, you needn't read this chapter.
.. index::
single: traversal details
@@ -286,7 +289,7 @@ system uses this algorithm to find a :term:`context` resource and a
return resource "C".
#. Traversal ends when a) the entire path is exhausted or b) when any
- resouce raises a :exc:`KeyError` from its ``__getitem__`` or c) when any
+ resource raises a :exc:`KeyError` from its ``__getitem__`` or c) when any
non-final path element traversal does not have a ``__getitem__`` method
(resulting in a :exc:`AttributeError`) or d) when any path element is
prefixed with the set of characters ``@@`` (indicating that the characters
@@ -356,13 +359,13 @@ when this request comes in that we're traversing the following resource tree:
Here's what happens:
-- :mod:`traversal` traverses the root, and attempts to find "foo", which it
+- :term:`traversal` traverses the root, and attempts to find "foo", which it
finds.
-- :mod:`traversal` traverses "foo", and attempts to find "bar", which it
+- :term:`traversal` traverses "foo", and attempts to find "bar", which it
finds.
-- :mod:`traversal` traverses "bar", and attempts to find "baz", which it does
+- :term:`traversal` traverses "bar", and attempts to find "baz", which it does
not find (the "bar" resource raises a :exc:`KeyError` when asked for
"baz").
@@ -389,7 +392,7 @@ Using the :term:`view name` (``baz``) and the type, view lookup asks the
Let's say that view lookup finds no matching view type. In this
circumstance, the :app:`Pyramid` :term:`router` returns the result of the
-:term:`not found view` and the request ends.
+:term:`Not Found View` and the request ends.
However, for this tree:
@@ -407,16 +410,16 @@ However, for this tree:
The user asks for ``http://example.com/foo/bar/baz/biz/buz.txt``
-- :mod:`traversal` traverses "foo", and attempts to find "bar", which it
+- :term:`traversal` traverses "foo", and attempts to find "bar", which it
finds.
-- :mod:`traversal` traverses "bar", and attempts to find "baz", which it
+- :term:`traversal` traverses "bar", and attempts to find "baz", which it
finds.
-- :mod:`traversal` traverses "baz", and attempts to find "biz", which it
+- :term:`traversal` traverses "baz", and attempts to find "biz", which it
finds.
-- :mod:`traversal` traverses "biz", and attempts to find "buz.txt" which it
+- :term:`traversal` traverses "biz", and attempts to find "buz.txt" which it
does not find.
The fact that it does not find a resource related to "buz.txt" at this point
diff --git a/docs/narr/upgrading.rst b/docs/narr/upgrading.rst
index 20487b448..ca6dc565b 100644
--- a/docs/narr/upgrading.rst
+++ b/docs/narr/upgrading.rst
@@ -183,7 +183,7 @@ server run with the ``PYTHONWARNINGS`` environment variable set to
.. code-block:: bash
- $ PYTHONWARNINGS=default bin/pserve development.ini
+ $ PYTHONWARNINGS=default $VENV/bin/pserve development.ini
On Windows, you need to issue two commands:
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index 749a2d49a..62eb89348 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -16,12 +16,13 @@ receives the :term:`request` and returns a :term:`response` object.
High-Level Operational Overview
-------------------------------
-If route configuration is present in an application, the :app:`Pyramid`
+If any route configuration is present in an application, the :app:`Pyramid`
:term:`Router` checks every incoming request against an ordered set of URL
matching patterns present in a *route map*.
If any route pattern matches the information in the :term:`request`,
-:app:`Pyramid` will invoke :term:`view lookup` to find a matching view.
+:app:`Pyramid` will invoke the :term:`view lookup` process to find a
+matching view.
If no route pattern in the route map matches the information in the
:term:`request` provided in your application, :app:`Pyramid` will fail over
@@ -54,7 +55,6 @@ The :meth:`pyramid.config.Configurator.add_route` method adds a single
:term:`route configuration` to the :term:`application registry`. Here's an
example:
-.. ignore-next-block
.. code-block:: python
# "config" below is presumed to be an instance of the
@@ -70,20 +70,18 @@ via its ``route_name`` predicate, that view callable will always be found and
invoked when the associated route pattern matches during a request.
More commonly, you will not use any ``add_view`` statements in your project's
-"setup" code, instead only using ``add_route`` statements using a
-:term:`scan` for to associate view callables with routes. For example, if
+"setup" code. You will instead use ``add_route`` statements, and use a
+:term:`scan` to associate view callables with routes. For example, if
this is a portion of your project's ``__init__.py``:
.. code-block:: python
- # in your project's __init__.py (mypackage.__init__)
-
config.add_route('myroute', '/prefix/{one}/{two}')
config.scan('mypackage')
Note that we don't call :meth:`~pyramid.config.Configurator.add_view` in this
setup code. However, the above :term:`scan` execution
-``config.scan('mypackage')`` will pick up all :term:`configuration
+``config.scan('mypackage')`` will pick up each :term:`configuration
decoration`, including any objects decorated with the
:class:`pyramid.view.view_config` decorator in the ``mypackage`` Python
package. For example, if you have a ``views.py`` in your package, a scan will
@@ -92,8 +90,6 @@ that references ``myroute`` as a ``route_name`` parameter:
.. code-block:: python
- # in your project's views.py module (mypackage.views)
-
from pyramid.view import view_config
from pyramid.response import Response
@@ -109,6 +105,7 @@ to using the previous combination of ``add_route`` and ``add_view``.
.. _route_pattern_syntax:
+
Route Pattern Syntax
~~~~~~~~~~~~~~~~~~~~
@@ -131,6 +128,10 @@ and:
/{foo}/bar/baz
+If a pattern is a valid URL it won't be ever matched against an incoming
+request. Instead it can be useful for generating external URLs. See
+:ref:`External routes <external_route_narr>` for details.
+
A pattern segment (an individual item between ``/`` characters in the
pattern) may either be a literal string (e.g. ``foo``) *or* it may be a
replacement marker (e.g. ``{foo}``) or a certain combination of both. A
@@ -758,9 +759,39 @@ other non-``name`` and non-``pattern`` arguments to
exception to this rule is use of the ``pregenerator`` argument, which is not
ignored when ``static`` is ``True``.
+:ref:`External routes <external_route_narr>` are implicitly static.
+
.. versionadded:: 1.1
the ``static`` argument to :meth:`~pyramid.config.Configurator.add_route`
+.. _external_route_narr:
+
+
+External Routes
+---------------
+
+.. versionadded:: 1.5
+
+Route patterns that are valid URLs, are treated as external routes. Like
+:ref:`static routes <static_route_narr>` they are useful for URL generation
+purposes only and are never considered for matching at request time.
+
+.. code-block:: python
+ :linenos:
+
+ >>> config = Configurator()
+ >>> config.add_route('youtube', 'https://youtube.com/watch/{video_id}')
+ ...
+ >>> request.route_url('youtube', video_id='oHg5SJYRHA0')
+ >>> "https://youtube.com/watch/oHg5SJYRHA0"
+
+Most pattern replacements and calls to
+:meth:`pyramid.request.Request.route_url` will work as expected. However, calls
+to :meth:`pyramid.request.Request.route_path` against external patterns will
+raise an exception, and passing ``_app_url`` to
+:meth:`~pyramid.request.Request.route_url` to generate a URL against a route
+that has an external pattern will also raise an exception.
+
.. index::
single: redirecting to slash-appended routes
@@ -818,7 +849,7 @@ bro." body.
If a request enters the application with the ``PATH_INFO`` value of
``/has_slash/``, the second route will match. If a request enters the
application with the ``PATH_INFO`` value of ``/has_slash``, a route *will* be
-found by the slash-appending not found view. An HTTP redirect to
+found by the slash-appending :term:`Not Found View`. An HTTP redirect to
``/has_slash/`` will be returned to the user's browser. As a result, the
``notfound`` view will never actually be called.
@@ -853,12 +884,12 @@ exactly the same job:
.. warning::
You **should not** rely on this mechanism to redirect ``POST`` requests.
- The redirect of the slash-appending not found view will turn a ``POST``
- request into a ``GET``, losing any ``POST`` data in the original
+ The redirect of the slash-appending :term:`Not Found View` will turn a
+ ``POST`` request into a ``GET``, losing any ``POST`` data in the original
request.
See :ref:`view_module` and :ref:`changing_the_notfound_view` for a more
-general description of how to configure a view and/or a not found view.
+general description of how to configure a view and/or a :term:`Not Found View`.
.. index::
pair: debugging; route matching
@@ -869,7 +900,7 @@ Debugging Route Matching
------------------------
It's useful to be able to take a peek under the hood when requests that enter
-your application arent matching your routes as you expect them to. To debug
+your application aren't matching your routes as you expect them to. To debug
route matching, use the ``PYRAMID_DEBUG_ROUTEMATCH`` environment variable or the
``pyramid.debug_routematch`` configuration file setting (set either to ``true``).
Details of the route matching decision for a particular request to the
@@ -879,8 +910,7 @@ which you started the application from. For example:
.. code-block:: text
:linenos:
- [chrism@thinko pylonsbasic]$ PYRAMID_DEBUG_ROUTEMATCH=true \
- bin/pserve development.ini
+ $ PYRAMID_DEBUG_ROUTEMATCH=true $VENV/bin/pserve development.ini
Starting server in PID 13586.
serving on 0.0.0.0:6543 view at http://127.0.0.1:6543
2010-12-16 14:45:19,956 no route matched for url \
@@ -1268,7 +1298,7 @@ invoked with the request that caused the invocation.
For most usage, you needn't understand more than this; how it works is an
implementation detail. In the interest of completeness, however, we'll
-explain how it *does* work in the this section. You can skip it if you're
+explain how it *does* work in this section. You can skip it if you're
uninterested.
When a view is associated with a route configuration, :app:`Pyramid` ensures
diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst
index 7001cd980..e09fd83ab 100644
--- a/docs/narr/viewconfig.rst
+++ b/docs/narr/viewconfig.rst
@@ -38,11 +38,11 @@ A view configuration statement is made about information present in the
View configuration is performed in one of two ways:
-- by running a :term:`scan` against application source code which has a
+- By running a :term:`scan` against application source code which has a
:class:`pyramid.view.view_config` decorator attached to a Python object as
per :ref:`mapping_views_using_a_decorator_section`.
-- by using the :meth:`pyramid.config.Configurator.add_view` method as per
+- By using the :meth:`pyramid.config.Configurator.add_view` method as per
:ref:`mapping_views_using_imperative_config_section`.
.. index::
@@ -62,13 +62,13 @@ particular view callable.
:term:`View predicate` attributes are an important part of view configuration
that enables the :term:`view lookup` subsystem to find and invoke the
-appropriate view. The greater number of predicate attributes possessed by a
+appropriate view. The greater the number of predicate attributes possessed by a
view's configuration, the more specific the circumstances need to be before
-the registered view callable will be invoked. The fewer number of predicates
+the registered view callable will be invoked. The fewer the number of predicates
which are supplied to a particular view configuration, the more likely it is
that the associated view callable will be invoked. A view with five
predicates will always be found and evaluated before a view with two, for
-example. All predicates must match for the associated view to be called.
+example.
This does not mean however, that :app:`Pyramid` "stops looking" when it
finds a view registration with predicates that don't match. If one set
@@ -81,7 +81,7 @@ invoked.
If no view can be found with predicates which allow it to be matched up with
the request, :app:`Pyramid` will return an error to the user's browser,
representing a "not found" (404) page. See :ref:`changing_the_notfound_view`
-for more information about changing the default notfound view.
+for more information about changing the default :term:`Not Found View`.
Other view configuration arguments are non-predicate arguments. These tend
to modify the response of the view callable or prevent the view callable from
@@ -290,10 +290,10 @@ configured view.
of the ``REQUEST_METHOD`` of the :term:`WSGI` environment.
``request_param``
- This value can be any string or a sequence of strings. A view declaration
- with this argument ensures that the view will only be called when the
- :term:`request` has a key in the ``request.params`` dictionary (an HTTP
- ``GET`` or ``POST`` variable) that has a name which matches the a
+ This value can be any string or a sequence of strings. A view declaration
+ with this argument ensures that the view will only be called when the
+ :term:`request` has a key in the ``request.params`` dictionary (an HTTP
+ ``GET`` or ``POST`` variable) that has a name which matches the
supplied value.
If any value supplied has a ``=`` sign in it,
@@ -306,16 +306,14 @@ configured view.
consideration of keys and values in the ``request.params`` dictionary.
``match_param``
- .. versionadded:: 1.2
-
This param may be either a single string of the format "key=value" or a
dict of key/value pairs.
This argument ensures that the view will only be called when the
:term:`request` has key/value pairs in its :term:`matchdict` that equal
- those supplied in the predicate. e.g. ``match_param="action=edit" would
+ those supplied in the predicate. e.g. ``match_param="action=edit"`` would
require the ``action`` parameter in the :term:`matchdict` match the right
- hande side of the expression (``edit``) for the view to "match" the current
+ hand side of the expression (``edit``) for the view to "match" the current
request.
If the ``match_param`` is a dict, every key/value pair must match for the
@@ -324,6 +322,8 @@ configured view.
If ``match_param`` is not supplied, the view will be invoked without
consideration of the keys and values in ``request.matchdict``.
+ .. versionadded:: 1.2
+
``containment``
This value should be a reference to a Python class or :term:`interface`
that a parent object in the context resource's :term:`lineage` must provide
@@ -475,7 +475,7 @@ Adding View Configuration Using the ``@view_config`` Decorator
.. warning::
- Using this feature tends to slows down application startup slightly, as
+ Using this feature tends to slow down application startup slightly, as
more work is performed at application startup to scan for view
configuration declarations. For maximum startup performance, use the view
configuration method described in
@@ -488,7 +488,6 @@ acts as a :app:`Pyramid` view callable.
Here's an example of the :class:`~pyramid.view.view_config` decorator that
lives within a :app:`Pyramid` application module ``views.py``:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -503,11 +502,10 @@ lives within a :app:`Pyramid` application module ``views.py``:
Using this decorator as above replaces the need to add this imperative
configuration stanza:
-.. ignore-next-block
.. code-block:: python
:linenos:
- config.add_view('mypackage.views.my_view', route_name='ok',
+ config.add_view('mypackage.views.my_view', route_name='ok',
request_method='POST', permission='read')
All arguments to ``view_config`` may be omitted. For example:
@@ -559,6 +557,35 @@ form of :term:`declarative configuration`, while
:meth:`pyramid.config.Configurator.add_view` is a form of :term:`imperative
configuration`. However, they both do the same thing.
+Inverting Predicate Values
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+You can invert the meaning of any predicate value by wrapping it in a call to
+:class:`pyramid.config.not_`.
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.config import not_
+
+ config.add_view(
+ 'mypackage.views.my_view',
+ route_name='ok',
+ request_method=not_('POST')
+ )
+
+The above example will ensure that the view is called if the request method
+is *not* ``POST``, at least if no other view is more specific.
+
+This technique of wrapping a predicate value in ``not_`` can be used anywhere
+predicate values are accepted:
+
+- :meth:`pyramid.config.Configurator.add_view`
+
+- :meth:`pyramid.view.view_config`
+
+.. versionadded:: 1.5
+
.. index::
single: view_config placement
@@ -583,8 +610,7 @@ If your view callable is a function, it may be used as a function decorator:
return Response('edited!')
If your view callable is a class, the decorator can also be used as a class
-decorator in Python 2.6 and better (Python 2.5 and below do not support class
-decorators). All the arguments to the decorator are the same when applied
+decorator. All the arguments to the decorator are the same when applied
against a class as when they are applied against a function. For example:
.. code-block:: python
@@ -601,25 +627,6 @@ against a class as when they are applied against a function. For example:
def __call__(self):
return Response('hello')
-You can use the :class:`~pyramid.view.view_config` decorator as a simple
-callable to manually decorate classes in Python 2.5 and below without the
-decorator syntactic sugar, if you wish:
-
-.. code-block:: python
- :linenos:
-
- from pyramid.response import Response
- from pyramid.view import view_config
-
- class MyView(object):
- def __init__(self, request):
- self.request = request
-
- def __call__(self):
- return Response('hello')
-
- my_view = view_config(route_name='hello')(MyView)
-
More than one :class:`~pyramid.view.view_config` decorator can be stacked on
top of any number of others. Each decorator creates a separate view
registration. For example:
@@ -706,11 +713,10 @@ this method are very similar to the arguments that you provide to the
# pyramid.config.Configurator class
config.add_view(hello_world, route_name='hello')
-The first argument, ``view``, is required. It must either be a Python object
-which is the view itself or a :term:`dotted Python name` to such an object.
-In the above example, ``view`` is the ``hello_world`` function. All other
-arguments are optional. See :meth:`pyramid.config.Configurator.add_view` for
-more information.
+The first argument, a :term:`view callable`, is the only required argument.
+It must either be a Python object which is the view itself or a
+:term:`dotted Python name` to such an object.
+In the above example, the ``view callable`` is the ``hello_world`` function.
When you use only :meth:`~pyramid.config.Configurator.add_view` to add view
configurations, you don't need to issue a :term:`scan` in order for the view
@@ -825,7 +831,7 @@ of this:
config.add_view(
RESTView, route_name='rest', attr='delete', request_method='DELETE')
-To reduce the amount of repetion in the ``config.add_view`` statements, we
+To reduce the amount of repetition in the ``config.add_view`` statements, we
can move the ``route_name='rest'`` argument to a ``@view_default`` class
decorator on the RESTView class:
@@ -931,10 +937,11 @@ per :ref:`protecting_views`.
.. _debug_notfound_section:
-:exc:`NotFound` Errors
-~~~~~~~~~~~~~~~~~~~~~~
+:exc:`~pyramid.exceptions.NotFound` Errors
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-It's useful to be able to debug :exc:`NotFound` error responses when they
+It's useful to be able to debug :exc:`~pyramid.exceptions.NotFound`
+error responses when they
occur unexpectedly due to an application registry misconfiguration. To debug
these errors, use the ``PYRAMID_DEBUG_NOTFOUND`` environment variable or the
``pyramid.debug_notfound`` configuration file setting. Details of why a view
@@ -998,6 +1005,8 @@ invoked as the result of the ``http_cache`` argument to view configuration.
.. index::
pair: view configuration; debugging
+.. _debugging_view_configuration:
+
Debugging View Configuration
----------------------------
diff --git a/docs/narr/views.rst b/docs/narr/views.rst
index 860c380f3..b2dd549ce 100644
--- a/docs/narr/views.rst
+++ b/docs/narr/views.rst
@@ -39,7 +39,7 @@ object. A request object represents a :term:`WSGI` environment provided to
object contains everything your application needs to know about the specific
HTTP request being made.
-A view callable's ultimate responsibility is to create a :mod:`Pyramid`
+A view callable's ultimate responsibility is to create a :app:`Pyramid`
:term:`Response` object. This can be done by creating a :term:`Response`
object in the view callable code and returning it directly or by raising
special kinds of exceptions from within the body of a view callable.
@@ -176,7 +176,7 @@ exception` objects.
HTTP Exceptions
~~~~~~~~~~~~~~~
-All classes documented in the :mod:`pyramid.httpexceptions` module documented
+All :mod:`pyramid.httpexceptions` classes which are documented
as inheriting from the :class:`pyramid.httpexceptions.HTTPException` are
:term:`http exception` objects. Instances of an HTTP exception object may
either be *returned* or *raised* from within view code. In either case
@@ -236,12 +236,11 @@ How Pyramid Uses HTTP Exceptions
HTTP exceptions are meant to be used directly by application
developers. However, Pyramid itself will raise two HTTP exceptions at
various points during normal operations:
-:exc:`pyramid.httpexceptions.HTTPNotFound` and
-:exc:`pyramid.httpexceptions.HTTPForbidden`. Pyramid will raise the
-:exc:`~pyramid.httpexceptions.HTTPNotFound` exception are raised when it
-cannot find a view to service a request. Pyramid will raise the
-:exc:`~pyramid.httpexceptions.Forbidden` exception or when authorization was
-forbidden by a security policy.
+
+* :exc:`~pyramid.httpexceptions.HTTPNotFound`
+ gets raised when a view to service a request is not found.
+* :exc:`~pyramid.httpexceptions.HTTPForbidden`
+ gets raised when authorization was forbidden by a security policy.
If :exc:`~pyramid.httpexceptions.HTTPNotFound` is raised by Pyramid itself or
within view code, the result of the :term:`Not Found View` will be returned
@@ -265,9 +264,9 @@ also be used by application developers to convert arbitrary exceptions to
responses.
To register a view that should be called whenever a particular exception is
-raised from with :app:`Pyramid` view code, use the exception class or one of
-its superclasses as the ``context`` of a view configuration which points at a
-view callable you'd like to generate a response.
+raised from within :app:`Pyramid` view code, use the exception class (or one of
+its superclasses) as the :term:`context` of a view configuration which points
+at a view callable you'd like to generate a response for.
For example, given the following exception class in a module named
``helloworld.exceptions``:
@@ -354,7 +353,7 @@ Exception views can be configured with any view registration mechanism:
.. _http_redirect:
-Using a View Callable to Do an HTTP Redirect
+Using a View Callable to do an HTTP Redirect
--------------------------------------------
You can issue an HTTP redirect by using the
@@ -525,7 +524,6 @@ The :term:`context` and :term:`request` arguments passed to a view function
defined in this style can be defined as follows:
context
-
The :term:`resource` object found via tree :term:`traversal` or :term:`URL
dispatch`.
@@ -538,41 +536,41 @@ The following types work as view callables in this style:
e.g.:
.. code-block:: python
- :linenos:
+ :linenos:
- from pyramid.response import Response
+ from pyramid.response import Response
- def view(context, request):
- return Response('OK')
+ def view(context, request):
+ return Response('OK')
#. Classes that have an ``__init__`` method that accepts ``context,
request`` and a ``__call__`` method which accepts no arguments, e.g.:
.. code-block:: python
- :linenos:
+ :linenos:
- from pyramid.response import Response
+ from pyramid.response import Response
- class view(object):
- def __init__(self, context, request):
- self.context = context
- self.request = request
+ class view(object):
+ def __init__(self, context, request):
+ self.context = context
+ self.request = request
- def __call__(self):
- return Response('OK')
+ def __call__(self):
+ return Response('OK')
#. Arbitrary callables that have a ``__call__`` method that accepts
``context, request``, e.g.:
.. code-block:: python
- :linenos:
+ :linenos:
- from pyramid.response import Response
+ from pyramid.response import Response
- class View(object):
- def __call__(self, context, request):
- return Response('OK')
- view = View() # this is the view callable
+ class View(object):
+ def __call__(self, context, request):
+ return Response('OK')
+ view = View() # this is the view callable
This style of calling convention is most useful for :term:`traversal` based
applications, where the context object is frequently used within the view
diff --git a/docs/narr/webob.rst b/docs/narr/webob.rst
index 44940f9e6..f0a4b5a0b 100644
--- a/docs/narr/webob.rst
+++ b/docs/narr/webob.rst
@@ -287,7 +287,7 @@ When such a request reaches a view in your application, the
@view_config(renderer='string')
def aview(request):
- print request.json_body
+ print(request.json_body)
return 'OK'
For the above view, printed to the console will be:
@@ -326,7 +326,6 @@ package that uses SQLAlchemy, and you'd like the current SQLAlchemy database
session to be removed after each request. Put the following in the
``mypackage.__init__`` module:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -355,7 +354,7 @@ initialization.
cause ``DBSession.remove`` to be called in an application generated from
any :app:`Pyramid` scaffold, because these all use the ``pyramid_tm``
package. The cleanup done by ``DBSession.remove`` is unnecessary when
- ``pyramid_tm`` middleware is configured into the application.
+ ``pyramid_tm`` :term:`middleware` is configured into the application.
More Details
++++++++++++
@@ -488,10 +487,9 @@ module.
Each class is named ``pyramid.httpexceptions.HTTP*``, where ``*`` is the
reason for the error. For instance,
:class:`pyramid.httpexceptions.HTTPNotFound` subclasses
-:class:`pyramid.Response`, so you can manipulate the instances in the same
+:class:`pyramid.response.Response`, so you can manipulate the instances in the same
way. A typical example is:
-.. ignore-next-block
.. code-block:: python
:linenos:
diff --git a/docs/narr/zca.rst b/docs/narr/zca.rst
index f7707ea29..b0e9b1709 100644
--- a/docs/narr/zca.rst
+++ b/docs/narr/zca.rst
@@ -21,7 +21,6 @@ application can be opaque. For example, here is a typical "unnamed
utility" lookup using the :func:`zope.component.getUtility` global API
as it might appear in a traditional Zope application:
-.. ignore-next-block
.. code-block:: python
:linenos:
@@ -45,7 +44,7 @@ framework implementation detail.
However, developers who are already used to writing :term:`Zope`
applications often still wish to use the ZCA while building a
-:app:`Pyramid` application; :mod:`pyramid` makes this possible.
+:app:`Pyramid` application; :app:`Pyramid` makes this possible.
.. index::
single: get_current_registry
@@ -84,7 +83,7 @@ While this services a reasonable goal, it causes some issues when
trying to use patterns which you might use to build a typical
:term:`Zope` application to build a :app:`Pyramid` application.
Without special help, ZCA "global" APIs such as
-``zope.component.getUtility`` and ``zope.component.getSiteManager``
+:func:`zope.component.getUtility` and :func:`zope.component.getSiteManager`
will use the ZCA "global" registry. Therefore, these APIs
will appear to fail when used in a :app:`Pyramid` application,
because they'll be consulting the ZCA global registry rather than the
@@ -105,8 +104,8 @@ Disusing the Global ZCA API
+++++++++++++++++++++++++++
ZCA "global" API functions such as ``zope.component.getSiteManager``,
-``zope.component.getUtility``, ``zope.component.getAdapter``, and
-``zope.component.getMultiAdapter`` aren't strictly necessary. Every
+``zope.component.getUtility``, :func:`zope.component.getAdapter`, and
+:func:`zope.component.getMultiAdapter` aren't strictly necessary. Every
component registry has a method API that offers the same
functionality; it can be used instead. For example, presuming the
``registry`` value below is a Zope Component Architecture component
@@ -114,7 +113,6 @@ registry, the following bit of code is equivalent to
``zope.component.getUtility(IFoo)``:
.. code-block:: python
- :linenos:
registry.getUtility(IFoo)
@@ -152,7 +150,6 @@ Consider the following bit of idiomatic :app:`Pyramid` startup code:
.. code-block:: python
:linenos:
- from zope.component import getGlobalSiteManager
from pyramid.config import Configurator
def app(global_settings, **settings):
@@ -189,7 +186,6 @@ For example:
.. code-block:: python
:linenos:
- from zope.component import getGlobalSiteManager
from pyramid.config import Configurator
def app(global_settings, **settings):
diff --git a/docs/quick_tour.rst b/docs/quick_tour.rst
new file mode 100644
index 000000000..f75533220
--- /dev/null
+++ b/docs/quick_tour.rst
@@ -0,0 +1,860 @@
+.. _quick_tour:
+
+=====================
+Quick Tour of Pyramid
+=====================
+
+Pyramid lets you start small and finish big. This *Quick Tour* guide
+walks you through many of Pyramid's key features. Let's put the
+emphasis on *start* by doing a quick tour through Pyramid, with
+snippets of code to illustrate major concepts.
+
+.. note::
+
+ We use Python 3 in our samples. Pyramid was one of the first
+ (October 2011) web frameworks to fully support Python 3. You can
+ use Python 3 as well for this guide, but you can also use Python 2.7.
+
+Python Setup
+============
+
+First things first: we need our Python environment in ship-shape.
+Pyramid encourages standard Python development practices (virtual
+environments, packaging tools, logging, etc.) so let's get our working
+area in place. For Python 3.3:
+
+.. code-block:: bash
+
+ $ pyvenv-3.3 env33
+ $ source env33/bin/activate
+ $ wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | python
+
+If ``wget`` complains with a certificate error, run it with:
+
+.. code-block:: bash
+
+ $ wget --no-check-certificate
+
+In these steps above we first made a :term:`virtualenv` and then
+"activated" it, which adjusted our path to look first in
+``env33/bin`` for commands (such as ``python``). We next downloaded
+Python's packaging support and installed it, giving us the
+``easy_install`` command-line script for adding new packages. Python
+2.7 users will need to use ``virtualenv`` instead of ``pyvenv`` to make
+their virtual environment.
+
+.. note::
+
+ Why ``easy_install`` and not ``pip``? Pyramid encourages use of
+ namespace packages which, until recently, ``pip`` didn't permit.
+ Also, Pyramid has some optional C extensions for performance. With
+ ``easy_install``, Windows users can get these extensions without
+ needing a C compiler.
+
+.. seealso:: See Also: Python 3's :mod:`venv module <python3:venv>`,
+ the ``setuptools`` `installation
+ instructions <https://pypi.python.org/pypi/setuptools/0.9.8#installation-instructions>`_,
+ `easy_install help <https://pypi.python.org/pypi/setuptools/0.9.8#using-setuptools-and-easyinstall>`_,
+ and Pyramid's :ref:`Before You Install <installing_chapter>`.
+
+Pyramid Installation
+====================
+
+We now have a standard starting point for Python. Getting Pyramid
+installed is easy:
+
+.. code-block:: bash
+
+ $ easy_install pyramid
+
+Our virtual environment now has the Pyramid software available to its
+Python.
+
+.. seealso:: See Also: :ref:`installing_unix`
+
+Hello World
+===========
+
+Microframeworks have shown that learning starts best from a very small
+first step. Here's a tiny application in Pyramid:
+
+.. literalinclude:: quick_tour/hello_world/app.py
+ :linenos:
+
+This simple example is easy to run. Save this as ``app.py`` and run it:
+
+.. code-block:: bash
+
+ $ python ./app.py
+
+Next, open `http://localhost:6543/ <http://localhost:6543/>`_ in a
+browser and you will see the ``Hello World!`` message.
+
+New to Python web programming? If so, some lines in module merit
+explanation:
+
+#. *Line 10*. The ``if __name__ == '__main__':`` is Python's way of
+ saying "Start here when running from the command line".
+
+#. *Lines 11-13*. Use Pyramid's :term:`configurator` to connect
+ :term:`view` code to particular URL :term:`route`.
+
+#. *Lines 6-7*. Implement the view code that generates the
+ :term:`response`.
+
+#. *Lines 14-16*. Publish a :term:`WSGI` app using an HTTP server.
+
+As shown in this example, the :term:`configurator` plays a central role
+in Pyramid development. Building an application from loosely-coupled
+parts via :doc:`../narr/configuration` is a central idea in Pyramid,
+one that we will revisit regurlarly in this *Quick Tour*.
+
+.. seealso:: See Also: :ref:`firstapp_chapter` and
+ :ref:`Single File Tasks tutorial <tutorials:single-file-tutorial>`
+
+Handling Web Requests and Responses
+===================================
+
+Developing for the web means processing web requests. As this is a
+critical part of a web application, web developers need a robust,
+mature set of software for web requests.
+
+Pyramid has always fit nicely into the existing world of Python web
+development (virtual environments, packaging, scaffolding,
+first to embrace Python 3, etc.) For request handling, Pyramid turned
+to the well-regarded :term:`WebOb` Python library for request and
+response handling. In our example
+above, Pyramid hands ``hello_world`` a ``request`` that is
+:ref:`based on WebOb <webob_chapter>`.
+
+Let's see some features of requests and responses in action:
+
+.. literalinclude:: quick_tour/requests/app.py
+ :pyobject: hello_world
+
+In this Pyramid view, we get the URL being visited from ``request.url``.
+Also, if you visited ``http://localhost:6543/?name=alice``,
+the name is included in the body of the response::
+
+ URL http://localhost:6543/?name=alice with name: alice
+
+Finally, we set the response's content type and return the Response.
+
+.. seealso:: See Also: :ref:`webob_chapter`
+
+Views
+=====
+
+For the examples above, the ``hello_world`` function is a "view". In
+Pyramid, views are the primary way to accept web requests and return
+responses.
+
+So far our examples place everything in one file:
+
+- the view function
+
+- its registration with the configurator
+
+- the route to map it to a URL
+
+- the WSGI application launcher
+
+Let's move the views out to their own ``views.py`` module and change
+the ``app.py`` to scan that module, looking for decorators that setup
+the views. First, our revised ``app.py``:
+
+.. literalinclude:: quick_tour/views/app.py
+ :linenos:
+
+We added some more routes, but we also removed the view code.
+Our views, and their registrations (via decorators) are now in a module
+``views.py`` which is scanned via ``config.scan('views')``.
+
+We now have a ``views.py`` module that is focused on handling requests
+and responses:
+
+.. literalinclude:: quick_tour/views/views.py
+ :linenos:
+
+We have 4 views, each leading to the other. If you start at
+``http://localhost:6543/``, you get a response with a link to the next
+view. The ``hello_view`` (available at the URL ``/howdy``) has a link
+to the ``redirect_view``, which shows issuing a redirect to the final
+view.
+
+Earlier we saw ``config.add_view`` as one way to configure a view. This
+section introduces ``@view_config``. Pyramid's configuration supports
+:term:`imperative configuration`, such as the ``config.add_view`` in
+the previous example. You can also use :term:`declarative
+configuration`, in which a Python :term:`decorator` is placed on the
+line above the view. Both approaches result in the same final
+configuration, thus usually, it is simply a matter of taste.
+
+.. seealso:: See Also: :doc:`../narr/views`,
+ :doc:`../narr/viewconfig`, and
+ :ref:`debugging_view_configuration`
+
+Routing
+=======
+
+Writing web applications usually means sophisticated URL design. We
+just saw some Pyramid machinery for requests and views. Let's look at
+features that help in routing.
+
+Above we saw the basics of routing URLs to views in Pyramid:
+
+- Your project's "setup" code registers a route name to be used when
+ matching part of the URL
+
+- Elsewhere, a view is configured to be called for that route name
+
+.. note::
+
+ Why do this twice? Other Python web frameworks let you create a
+ route and associate it with a view in one step. As
+ illustrated in :ref:`routes_need_ordering`, multiple routes might
+ match the same URL pattern. Rather than provide ways to help guess,
+ Pyramid lets you be explicit in ordering. Pyramid also gives
+ facilities to avoid the problem.
+
+What if we want part of the URL to be available as data in my view? This
+route declaration:
+
+.. literalinclude:: quick_tour/routing/app.py
+ :start-after: Start Route 1
+ :end-before: End Route 1
+
+With this, URLs such as ``/howdy/amy/smith`` will assign ``amy`` to
+``first`` and ``smith`` to ``last``. We can then use this data in our
+view:
+
+.. literalinclude:: quick_tour/routing/views.py
+ :start-after: Start Route 1
+ :end-before: End Route 1
+
+``request.matchdict`` contains values from the URL that match the
+"replacement patterns" (the curly braces) in the route declaration.
+This information can then be used in your view.
+
+.. seealso:: See Also: :doc:`../narr/urldispatch`,
+ :ref:`debug_routematch_section`, and
+ :doc:`../narr/router`
+
+Templating
+==========
+
+Ouch. We have been making our own ``Response`` and filling the response
+body with HTML. You usually won't embed an HTML string directly in
+Python, but instead, will use a templating language.
+
+Pyramid doesn't mandate a particular database system, form library,
+etc. It encourages replaceability. This applies equally to templating,
+which is fortunate: developers have strong views about template
+languages. That said, Pyramid bundles Chameleon and Mako,
+so in this step, let's use Chameleon as an example:
+
+.. literalinclude:: quick_tour/templating/views.py
+ :start-after: Start View 1
+ :end-before: End View 1
+
+Ahh, that looks better. We have a view that is focused on Python code.
+Our ``@view_config`` decorator specifies a :term:`renderer` that points
+our template file. Our view then simply returns data which is then
+supplied to our template:
+
+.. literalinclude:: quick_tour/templating/hello_world.pt
+ :language: html
+
+Since our view returned ``dict(name=request.matchdict['name'])``,
+we can use ``name`` as a variable in our template via
+``${name}``.
+
+.. seealso:: See Also: :doc:`../narr/templates`,
+ :ref:`debugging_templates`, and
+ :ref:`mako_templates`
+
+Templating With ``jinja2``
+==========================
+
+We just said Pyramid doesn't prefer one templating language over
+another. Time to prove it. Jinja2 is a popular templating system,
+modelled after Django's templates. Let's add ``pyramid_jinja2``,
+a Pyramid :term:`add-on` which enables Jinja2 as a :term:`renderer` in
+our Pyramid applications:
+
+.. code-block:: bash
+
+ $ easy_install pyramid_jinja2
+
+With the package installed, we can include the template bindings into
+our configuration:
+
+.. code-block:: python
+
+ config.include('pyramid_jinja2')
+
+The only change in our view...point the renderer at the ``.jinja2`` file:
+
+.. literalinclude:: quick_tour/jinja2/views.py
+ :start-after: Start View 1
+ :end-before: End View 1
+
+Our Jinja2 template is very similar to our previous template:
+
+.. literalinclude:: quick_tour/jinja2/hello_world.jinja2
+ :language: jinja
+
+Pyramid's templating add-ons register a new kind of renderer into your
+application. The renderer registration maps to different kinds of
+filename extensions. In this case, changing the extension from ``.pt``
+to ``.jinja2`` passed the view response through the ``pyramid_jinja2``
+renderer.
+
+.. seealso:: See Also: `Jinja2 homepage <http://jinja.pocoo.org/>`_,
+ and
+ :ref:`pyramid_jinja2 Overview <jinja2:overview>`
+
+Static Assets
+=============
+
+Of course the Web is more than just markup. You need static assets:
+CSS, JS, and images. Let's point our web app at a directory where
+Pyramid will serve some static assets. First, another call to the
+:term:`configurator`:
+
+.. literalinclude:: quick_tour/static_assets/app.py
+ :start-after: Start Static 1
+ :end-before: End Static 1
+
+This tells our WSGI application to map requests under
+``http://localhost:6543/static/`` to files and directories inside a
+``static`` directory alongside our Python module.
+
+Next, make a directory ``static`` and place ``app.css`` inside:
+
+.. literalinclude:: quick_tour/static_assets/static/app.css
+ :language: css
+
+All we need to do now is point to it in the ``<head>`` of our Jinja2
+template:
+
+.. literalinclude:: quick_tour/static_assets/hello_world.pt
+ :language: html
+ :start-after: Start Link 1
+ :end-before: End Link 1
+
+This link presumes that our CSS is at a URL starting with ``/static/``.
+What if the site is later moved under ``/somesite/static/``? Or perhaps
+web developer changes the arrangement on disk? Pyramid gives a helper
+that provides flexibility on URL generation:
+
+.. literalinclude:: quick_tour/static_assets/hello_world.pt
+ :language: html
+ :start-after: Start Link 2
+ :end-before: End Link 2
+
+By using ``request.static_url`` to generate the full URL to the static
+assets, you both ensure you stay in sync with the configuration and
+gain refactoring flexibility later.
+
+.. seealso:: See Also: :doc:`../narr/assets`,
+ :ref:`preventing_http_caching`, and
+ :ref:`influencing_http_caching`
+
+Returning JSON
+==============
+
+Modern web apps are more than rendered HTML. Dynamic pages now use
+JavaScript to update the UI in the browser by requesting server data as
+JSON. Pyramid supports this with a JSON renderer:
+
+.. literalinclude:: quick_tour/json/views.py
+ :start-after: Start View 1
+ :end-before: End View 2
+
+This wires up a view that returns some data through the JSON
+:term:`renderer`, which calls Python's JSON support to serialize the data
+into JSON and set the appropriate HTTP headers.
+
+.. seealso:: See Also: :ref:`views_which_use_a_renderer`,
+ :ref:`json_renderer`, and
+ :ref:`adding_and_overriding_renderers`
+
+View Classes
+============
+
+So far our views have been simple, free-standing functions. Many times
+your views are related: different ways to look at or work on the same
+data or a REST API that handles multiple operations. Grouping these
+together as a
+:ref:`view class <class_as_view>` makes sense:
+
+- Group views
+
+- Centralize some repetitive defaults
+
+- Share some state and helpers
+
+The following shows a "Hello World" example with three operations: view
+a form, save a change, or press the delete button:
+
+.. literalinclude:: quick_tour/view_classes/views.py
+ :start-after: Start View 1
+ :end-before: End View 1
+
+As you can see, the three views are logically grouped together.
+Specifically:
+
+- The first view is returned when you go to ``/howdy/amy``. This URL is
+ mapped to the ``hello`` route that we centrally set using the optional
+ ``@view_defaults``.
+
+- The second view is returned when the form data contains a field with
+ ``form.edit``, such as clicking on
+ ``<input type="submit" name="form.edit" value="Save"/>``. This rule
+ is specified in the ``@view_config`` for that view.
+
+- The third view is returned when clicking on a button such
+ as ``<input type="submit" name="form.delete" value="Delete"/>``.
+
+Only one route needed, stated in one place atop the view class. Also,
+the assignment of the ``name`` is done in the ``__init__``. Our
+templates can then use ``{{ view.name }}``.
+
+.. seealso:: See Also: :ref:`class_as_view`
+
+Quick Project Startup with Scaffolds
+====================================
+
+So far we have done all of our *Quick Glance* as a single Python file.
+No Python packages, no structure. Most Pyramid projects, though,
+aren't developed this way.
+
+To ease the process of getting started, Pyramid provides *scaffolds*
+that generate sample projects from templates in Pyramid and Pyramid
+add-ons. Pyramid's ``pcreate`` command can list the available scaffolds:
+
+.. code-block:: bash
+
+ $ pcreate --list
+ Available scaffolds:
+ alchemy: Pyramid SQLAlchemy project using url dispatch
+ pyramid_jinja2_starter: pyramid jinja2 starter project
+ starter: Pyramid starter project
+ zodb: Pyramid ZODB project using traversal
+
+The ``pyramid_jinja2`` add-on gave us a scaffold that we can use. From
+the parent directory of where we want our Python package to be generated,
+let's use that scaffold to make our project:
+
+.. code-block:: bash
+
+ $ pcreate --scaffold pyramid_jinja2_starter hello_world
+
+We next use the normal Python development to setup our package for
+development:
+
+.. code-block:: bash
+
+ $ cd hello_world
+ $ python ./setup.py develop
+
+We are moving in the direction of a full-featured Pyramid project,
+with a proper setup for Python standards (packaging) and Pyramid
+configuration. This includes a new way of running your application:
+
+.. code-block:: bash
+
+ $ pserve development.ini
+
+Let's look at ``pserve`` and configuration in more depth.
+
+.. seealso:: See Also: :ref:`project_narr` and
+ :doc:`../narr/scaffolding`
+
+Application Running with ``pserve``
+===================================
+
+Prior to scaffolds, our project mixed a number of operations details
+into our code. Why should my main code care with HTTP server I want and
+what port number to run on?
+
+``pserve`` is Pyramid's application runner, separating operational
+details from your code. When you install Pyramid, a small command
+program called ``pserve`` is written to your ``bin`` directory. This
+program is an executable Python module. It's very small, getting most
+of its brains via import.
+
+You can run ``pserve`` with ``--help`` to see some of its options.
+Doing so reveals that you can ask ``pserve`` to watch your development
+files and reload the server when they change:
+
+.. code-block:: bash
+
+ $ pserve development.ini --reload
+
+The ``pserve`` command has a number of other options and operations.
+Most of the work, though, comes from your project's wiring, as
+expressed in the configuration file you supply to ``pserve``. Let's
+take a look at this configuration file.
+
+.. seealso:: See Also: :ref:`what_is_this_pserve_thing`
+
+Configuration with ``.ini`` Files
+=================================
+
+Earlier in *Quick Glance* we first met Pyramid's configuration system.
+At that point we did all configuration in Python code. For example,
+the port number chosen for our HTTP server was right there in Python
+code. Our scaffold has moved this decision, and more, into the
+``development.ini`` file:
+
+.. literalinclude:: quick_tour/package/development.ini
+ :language: ini
+
+Let's take a quick high-level look. First, the ``.ini`` file is divided
+into sections:
+
+- ``[app:hello_world]`` configures our WSGI app
+
+- ``[pipeline:main]`` sets up our WSGI "pipeline"
+
+- ``[server:main]`` holds our WSGI server settings
+
+- Various sections afterwards configure our Python logging system
+
+We have a few decisions made for us in this configuration:
+
+#. *Choice of web server*. The ``use = egg:pyramid#wsgiref`` tell
+ ``pserve`` to the ``wsgiref`` server that is wrapped in the Pyramid
+ package.
+
+#. *Port number*. ``port = 6543`` tells ``wsgiref`` to listen on port
+ 6543.
+
+#. *WSGI app*. What package has our WSGI application in it?
+ ``use = egg:hello_world`` in the app section tells the
+ configuration what application to load.
+
+#. *Easier development by automatic template reloading*. In development
+ mode, you shouldn't have to restart the server when editing a Jinja2
+ template. ``reload_templates = true`` sets this policy,
+ which might be different in production.
+
+Additionally, the ``development.ini`` generated by this scaffold wired
+up Python's standard logging. We'll now see in the console, for example,
+a log on every request that comes in, as well traceback information.
+
+.. seealso:: See Also: :ref:`environment_chapter` and
+ :doc:`../narr/paste`
+
+
+Easier Development with ``debugtoolbar``
+========================================
+
+As we introduce the basics we also want to show how to be productive in
+development and debugging. For example, we just discussed template
+reloading and earlier we showed ``--reload`` for application reloading.
+
+``pyramid_debugtoolbar`` is a popular Pyramid add-on which makes
+several tools available in your browser. Adding it to your project
+illustrates several points about configuration.
+
+First, change your ``setup.py`` to say:
+
+.. literalinclude:: quick_tour/package/setup.py
+ :start-after: Start Requires
+ :end-before: End Requires
+
+...and re-run your setup:
+
+.. code-block:: bash
+
+ $ python ./setup.py develop
+
+The Python package was now installed into our environment. The package
+is a Pyramid add-on, which means we need to include its configuration
+into our web application. We could do this with imperative
+configuration, as we did above for the ``pyramid_jinja2`` add-on:
+
+.. literalinclude:: quick_tour/package/hello_world/__init__.py
+ :start-after: Start Include
+ :end-before: End Include
+
+Now that we have a configuration file, we can use the
+``pyramid.includes`` facility and place this in our
+``development.ini`` instead:
+
+.. literalinclude:: quick_tour/package/development.ini
+ :language: ini
+ :start-after: Start Includes
+ :end-before: End Includes
+
+You'll now see an attractive (and
+collapsible) menu in the right of your browser, providing introspective
+access to debugging information. Even better, if your web application
+generates an error, you will see a nice traceback on the screen. When
+you want to disable this toolbar, no need to change code: you can
+remove it from ``pyramid.includes`` in the relevant ``.ini``
+configuration file.
+
+.. seealso:: See Also: :ref:`pyramid_debugtoolbar <toolbar:overview>`
+
+Unit Tests and ``nose``
+=======================
+
+Yikes! We got this far and we haven't yet discussed tests. Particularly
+egregious, as Pyramid has had a deep commitment to full test coverage
+since before it was released.
+
+Our ``pyramid_jinja2_starter`` scaffold generated a ``tests.py`` module
+with one unit test in it. To run it, let's install the handy ``nose``
+test runner by editing ``setup.py``. While we're at it, we'll throw in
+the ``coverage`` tool which yells at us for code that isn't tested:
+
+.. code-block:: python
+
+ setup(name='hello_world',
+ # Some lines removed...
+ extras_require={
+ 'testing': ['nose', 'coverage'],
+ }
+ )
+
+We changed ``setup.py`` which means we need to re-run
+``python ./setup.py develop``. We can now run all our tests:
+
+.. code-block:: bash
+
+ $ nosetests hello_world/tests.py
+ .
+ Name Stmts Miss Cover Missing
+ ---------------------------------------------------
+ hello_world 12 8 33% 11-23
+ hello_world.models 5 1 80% 8
+ hello_world.tests 14 0 100%
+ hello_world.views 4 0 100%
+ ---------------------------------------------------
+ TOTAL 35 9 74%
+ ----------------------------------------------------------------------
+ Ran 1 test in 0.931s
+
+ OK
+
+Our unit test passed. What did our test look like?
+
+.. literalinclude:: quick_tour/package/hello_world/tests.py
+
+Pyramid supplies helpers for test writing, which we use in the
+test setup and teardown. Our one test imports the view,
+makes a dummy request, and sees if the view returns what we expected.
+
+.. seealso:: See Also: :ref:`testing_chapter`
+
+Logging
+=======
+
+It's important to know what is going on inside our web application.
+In development we might need to collect some output. In production,
+we might need to detect situations when other people use the site. We
+need *logging*.
+
+Fortunately Pyramid uses the normal Python approach to logging. The
+scaffold generated, in your ``development.ini``, a number of lines that
+configure the logging for you to some reasonable defaults. You then see
+messages sent by Pyramid (for example, when a new request comes in.)
+
+Maybe you would like to log messages in your code? In your Python
+module, import and setup the logging:
+
+.. literalinclude:: quick_tour/package/hello_world/views.py
+ :start-after: Start Logging 1
+ :end-before: End Logging 1
+
+You can now, in your code, log messages:
+
+.. literalinclude:: quick_tour/package/hello_world/views.py
+ :start-after: Start Logging 2
+ :end-before: End Logging 2
+
+This will log ``Some Message`` at a ``debug`` log level,
+to the application-configured logger in your ``development.ini``. What
+controls that? These sections in the configuration file:
+
+.. literalinclude:: quick_tour/package/development.ini
+ :language: ini
+ :start-after: Start Sphinx Include
+ :end-before: End Sphinx Include
+
+Our application, a package named ``hello_world``, is setup as a logger
+and configured to log messages at a ``DEBUG`` or higher level. When you
+visit ``http://localhost:6543`` your console will now show::
+
+ 2013-08-09 10:42:42,968 DEBUG [hello_world.views][MainThread] Some Message
+
+.. seealso:: See Also: :ref:`logging_chapter`
+
+Sessions
+========
+
+When people use your web application, they frequently perform a task
+that requires semi-permanent data to be saved. For example, a shopping
+cart. This is called a :term:`session`.
+
+Pyramid has basic built-in support for sessions, with add-ons such as
+*Beaker* (or your own custom sessioning engine) that provide richer
+session support. Let's take a look at the
+:doc:`built-in sessioning support <../narr/sessions>`. In our
+``__init__.py`` we first import the kind of sessioning we want:
+
+.. literalinclude:: quick_tour/package/hello_world/__init__.py
+ :start-after: Start Sphinx Include 1
+ :end-before: End Sphinx Include 1
+
+.. warning::
+
+ As noted in the session docs, this example implementation is
+ not intended for use in settings with security implications.
+
+Now make a "factory" and pass it to the :term:`configurator`'s
+``session_factory`` argument:
+
+.. literalinclude:: quick_tour/package/hello_world/__init__.py
+ :start-after: Start Sphinx Include 2
+ :end-before: End Sphinx Include 2
+
+Pyramid's :term:`request` object now has a ``session`` attribute
+that we can use in our view code:
+
+.. literalinclude:: quick_tour/package/hello_world/views.py
+ :start-after: Start Sphinx Include 1
+ :end-before: End Sphinx Include 1
+
+With this, each reload will increase the counter displayed in our
+Jinja2 template:
+
+.. literalinclude:: quick_tour/package/hello_world/templates/mytemplate.jinja2
+ :language: jinja
+ :start-after: Start Sphinx Include 1
+ :end-before: End Sphinx Include 1
+
+.. seealso:: See Also:
+ :ref:`sessions_chapter`, :ref:`flash_messages`,
+ :ref:`session_module`, and
+ :ref:`Beaker sessioning middleware <beaker:overview>`
+
+Databases
+=========
+
+Web applications mean data. Data means databases. Frequently SQL
+databases. SQL Databases frequently mean an "ORM"
+(object-relational mapper.) In Python, ORM usually leads to the
+mega-quality *SQLAlchemy*, a Python package that greatly eases working
+with databases.
+
+Pyramid and SQLAlchemy are great friends. That friendship includes a
+scaffold!
+
+.. code-block:: bash
+
+ $ pcreate --scaffold alchemy sqla_demo
+ $ cd sqla_demo
+ $ python setup.py develop
+
+We now have a working sample SQLAlchemy application with all
+dependencies installed. The sample project provides a console script to
+initialize a SQLite database with tables. Let's run it and then start
+the application:
+
+.. code-block:: bash
+
+ $ initialize_sqla_demo_db development.ini
+ $ pserve development.ini
+
+The ORM eases the mapping of database structures into a programming
+language. SQLAlchemy uses "models" for this mapping. The scaffold
+generated a sample model:
+
+.. literalinclude:: quick_tour/sqla_demo/sqla_demo/models.py
+ :start-after: Start Sphinx Include
+ :end-before: End Sphinx Include
+
+View code, which mediates the logic between web requests and the rest
+of the system, can then easily get at the data thanks to SQLAlchemy:
+
+.. literalinclude:: quick_tour/sqla_demo/sqla_demo/views.py
+ :start-after: Start Sphinx Include
+ :end-before: End Sphinx Include
+
+.. seealso:: See Also: `SQLAlchemy <http://www.sqlalchemy.org/>`_,
+ :ref:`making_a_console_script`,
+ :ref:`bfg_sql_wiki_tutorial`, and
+ :ref:`Application Transactions With pyramid_tm <tm:overview>`
+
+Forms
+=====
+
+Developers have lots of opinions about web forms, and thus there are many
+form libraries for Python. Pyramid doesn't directly bundle a form
+library, but *Deform* is a popular choice for forms,
+along with its related *Colander* schema system.
+
+As an example, imagine we want a form that edits a wiki page. The form
+should have two fields on it, one of them a required title and the
+other a rich text editor for the body. With Deform we can express this
+as a Colander schema:
+
+.. code-block:: python
+
+ class WikiPage(colander.MappingSchema):
+ title = colander.SchemaNode(colander.String())
+ body = colander.SchemaNode(
+ colander.String(),
+ widget=deform.widget.RichTextWidget()
+ )
+
+With this in place, we can render the HTML for a form,
+perhaps with form data from an existing page:
+
+.. code-block:: python
+
+ form = self.wiki_form.render()
+
+We'd like to handle form submission, validation, and saving:
+
+.. code-block:: python
+
+ # Get the form data that was posted
+ controls = self.request.POST.items()
+ try:
+ # Validate and either raise a validation error
+ # or return deserialized data from widgets
+ appstruct = wiki_form.validate(controls)
+ except deform.ValidationFailure as e:
+ # Bail out and render form with errors
+ return dict(title=title, page=page, form=e.render())
+
+ # Change the content and redirect to the view
+ page['title'] = appstruct['title']
+ page['body'] = appstruct['body']
+
+Deform and Colander provide a very flexible combination for forms,
+widgets, schemas, and validation. Recent versions of Deform also
+include a :ref:`retail mode <deform:retail>` for gaining Deform
+features on custom forms.
+
+Also, the ``deform_bootstrap`` Pyramid add-on restyles the stock Deform
+widgets using attractive CSS from Bootstrap and more powerful widgets
+from Chosen.
+
+.. seealso:: See Also:
+ :ref:`Deform <deform:overview>`,
+ :ref:`Colander <colander:overview>`, and
+ `deform_bootstrap <https://pypi.python.org/pypi/deform_bootstrap>`_
+
+Conclusion
+==========
+
+This *Quick Tour* covered a little about a lot. We introduced a long list
+of concepts in Pyramid, many of which are expanded on more fully in the
+Pyramid developer docs. \ No newline at end of file
diff --git a/docs/quick_tour/awesome/CHANGES.txt b/docs/quick_tour/awesome/CHANGES.txt
new file mode 100644
index 000000000..ffa255da8
--- /dev/null
+++ b/docs/quick_tour/awesome/CHANGES.txt
@@ -0,0 +1,4 @@
+0.0
+---
+
+- Initial version
diff --git a/docs/quick_tour/awesome/MANIFEST.in b/docs/quick_tour/awesome/MANIFEST.in
new file mode 100644
index 000000000..e78395da8
--- /dev/null
+++ b/docs/quick_tour/awesome/MANIFEST.in
@@ -0,0 +1,2 @@
+include *.txt *.ini *.cfg *.rst
+recursive-include awesome *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml
diff --git a/docs/quick_tour/awesome/README.txt b/docs/quick_tour/awesome/README.txt
new file mode 100644
index 000000000..f695286d9
--- /dev/null
+++ b/docs/quick_tour/awesome/README.txt
@@ -0,0 +1,4 @@
+awesome README
+
+
+
diff --git a/docs/quick_tour/awesome/awesome/__init__.py b/docs/quick_tour/awesome/awesome/__init__.py
new file mode 100644
index 000000000..408033997
--- /dev/null
+++ b/docs/quick_tour/awesome/awesome/__init__.py
@@ -0,0 +1,23 @@
+from pyramid.config import Configurator
+from pyramid_jinja2 import renderer_factory
+from awesome.models import get_root
+
+def main(global_config, **settings):
+ """ This function returns a WSGI application.
+
+ It is usually called by the PasteDeploy framework during
+ ``paster serve``.
+ """
+ settings = dict(settings)
+ settings.setdefault('jinja2.i18n.domain', 'awesome')
+
+ config = Configurator(root_factory=get_root, settings=settings)
+ config.add_translation_dirs('locale/')
+ config.include('pyramid_jinja2')
+
+ config.add_static_view('static', 'static')
+ config.add_view('awesome.views.my_view',
+ context='awesome.models.MyModel',
+ renderer="mytemplate.jinja2")
+
+ return config.make_wsgi_app()
diff --git a/docs/quick_tour/awesome/awesome/locale/awesome.pot b/docs/quick_tour/awesome/awesome/locale/awesome.pot
new file mode 100644
index 000000000..9c9460cb2
--- /dev/null
+++ b/docs/quick_tour/awesome/awesome/locale/awesome.pot
@@ -0,0 +1,21 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2011-05-12 09:14-0330\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+
+msgid "Hello!"
+msgstr ""
diff --git a/docs/quick_tour/awesome/awesome/locale/de/LC_MESSAGES/awesome.mo b/docs/quick_tour/awesome/awesome/locale/de/LC_MESSAGES/awesome.mo
new file mode 100644
index 000000000..40bf0c271
--- /dev/null
+++ b/docs/quick_tour/awesome/awesome/locale/de/LC_MESSAGES/awesome.mo
Binary files differ
diff --git a/docs/quick_tour/awesome/awesome/locale/de/LC_MESSAGES/awesome.po b/docs/quick_tour/awesome/awesome/locale/de/LC_MESSAGES/awesome.po
new file mode 100644
index 000000000..0df243dba
--- /dev/null
+++ b/docs/quick_tour/awesome/awesome/locale/de/LC_MESSAGES/awesome.po
@@ -0,0 +1,21 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2011-05-12 09:14-0330\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+
+msgid "Hello!"
+msgstr "Hallo!"
diff --git a/docs/quick_tour/awesome/awesome/locale/fr/LC_MESSAGES/awesome.mo b/docs/quick_tour/awesome/awesome/locale/fr/LC_MESSAGES/awesome.mo
new file mode 100644
index 000000000..4fc438bfe
--- /dev/null
+++ b/docs/quick_tour/awesome/awesome/locale/fr/LC_MESSAGES/awesome.mo
Binary files differ
diff --git a/docs/quick_tour/awesome/awesome/locale/fr/LC_MESSAGES/awesome.po b/docs/quick_tour/awesome/awesome/locale/fr/LC_MESSAGES/awesome.po
new file mode 100644
index 000000000..dc0aae5d7
--- /dev/null
+++ b/docs/quick_tour/awesome/awesome/locale/fr/LC_MESSAGES/awesome.po
@@ -0,0 +1,21 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2011-05-12 09:14-0330\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+
+msgid "Hello!"
+msgstr "Bonjour!"
diff --git a/docs/quick_tour/awesome/awesome/models.py b/docs/quick_tour/awesome/awesome/models.py
new file mode 100644
index 000000000..edd361c9c
--- /dev/null
+++ b/docs/quick_tour/awesome/awesome/models.py
@@ -0,0 +1,8 @@
+class MyModel(object):
+ pass
+
+root = MyModel()
+
+
+def get_root(request):
+ return root
diff --git a/docs/quick_tour/awesome/awesome/static/favicon.ico b/docs/quick_tour/awesome/awesome/static/favicon.ico
new file mode 100644
index 000000000..71f837c9e
--- /dev/null
+++ b/docs/quick_tour/awesome/awesome/static/favicon.ico
Binary files differ
diff --git a/docs/quick_tour/awesome/awesome/static/logo.png b/docs/quick_tour/awesome/awesome/static/logo.png
new file mode 100644
index 000000000..88f5d9865
--- /dev/null
+++ b/docs/quick_tour/awesome/awesome/static/logo.png
Binary files differ
diff --git a/docs/quick_tour/awesome/awesome/static/pylons.css b/docs/quick_tour/awesome/awesome/static/pylons.css
new file mode 100644
index 000000000..42e2e320e
--- /dev/null
+++ b/docs/quick_tour/awesome/awesome/static/pylons.css
@@ -0,0 +1,73 @@
+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;}
+/* remember to define focus styles! */
+:focus{outline:0;}
+/* remember to highlight inserts somehow! */
+ins{text-decoration:none;}
+del{text-decoration:line-through;}
+/* tables still need 'cellspacing="0"' in the markup */
+table{border-collapse:collapse;border-spacing:0;}
+/* restyling */
+sub{vertical-align:sub;font-size:smaller;line-height:normal;}
+sup{vertical-align:super;font-size:smaller;line-height:normal;}
+/* lists */
+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;}
+/* nested lists have no top/bottom margins */
+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;}
+/* 2 deep unordered lists use a circle */
+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;}
+/* 3 deep (or more) unordered lists use a square */
+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;/* 28px */
+line-height:1.7em;font-family:helvetica,verdana;}
+h2{font-size:1.5em;/* 24px */
+line-height:1.7em;font-family:helvetica,verdana;}
+h3{font-size:1.25em;/* 20px */
+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 "Nobile","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:"Nobile","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#144fb2;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;}
+#header{background-color:#e88f00;top:0;font-size:14px;}
+#footer{background-color:#000000;bottom:0;position: relative;margin-top:-40px;clear:both;}
+.header,.footer{width:700px;margin-right:auto;margin-left:auto;}
+.wrapper{width:100%}
+#top,#bottom{width:100%;}
+#top{color:#888;background-color:#eee;height:300px;border-bottom:2px solid #ddd;}
+#bottom{color:#222;background-color:#ffffff;overflow:auto;padding-bottom:80px;}
+.top,.bottom{width:700px;margin-right:auto;margin-left:auto;}
+.top{padding-top:100px;}
+.app-welcome{margin-top:25px;}
+.app-name{color:#000000;font-weight:bold;}
+.bottom{padding-top:50px;}
+#left{width:325px;float:left;padding-right:25px;}
+#right{width:325px;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=submit]{background-color:#ddd;font-weight:bold;}
+/*Opera Fix*/
+body:before {content:"";height:100%;float:left;width:0;margin-top:-32767px;}
diff --git a/docs/quick_tour/awesome/awesome/templates/mytemplate.jinja2 b/docs/quick_tour/awesome/awesome/templates/mytemplate.jinja2
new file mode 100644
index 000000000..8bf676041
--- /dev/null
+++ b/docs/quick_tour/awesome/awesome/templates/mytemplate.jinja2
@@ -0,0 +1,87 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>The Pyramid Web Framework</title>
+ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+ <meta name="keywords" content="python web application" />
+ <meta name="description" content="pyramid web application" />
+ <link rel="shortcut icon" href="{{request.application_url}}/static/favicon.ico" />
+ <link rel="stylesheet" href="{{request.application_url}}/static/pylons.css" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <!--[if !IE 7]>
+ <style type="text/css">
+ #wrap {display:table;height:100%}
+ </style>
+ <![endif]-->
+ <style type="text/css">
+ .locale { text-align: center; }
+ .locale-name { font-weight: bold; }
+ </style>
+</head>
+<body>
+ <div id="wrap">
+ <div id="header">
+ <div class="header">The Pyramid Web Framework</div>
+ </div>
+ <div id="top">
+ <div class="top align-center">
+ <img src="{{request.application_url}}/static/logo.png" width="300" height="80" alt="Logo"/>
+ <p class="app-welcome">
+ Welcome to <span class="app-name">{{project}}</span>, an application generated by<br/>
+ the Pyramid web framework.
+ </p>
+ </div>
+ </div>
+ <div id="bottom">
+ <div class="locale">
+ <h2>{% trans %}Hello!{% endtrans %}</h2>
+ <p>Request performed with <span class="locale-name">{{ request.locale_name }}</span> locale.</p>
+ </div>
+ <div class="bottom">
+ <div id="left" class="align-right">
+ <h3>Search Pyramid documentation</h3>
+ <form method="get" action="http://docs.pylonshq.com/pyramid/dev/search.html">
+ <input type="text" id="q" name="q" value="" />
+ <input type="submit" id="x" value="Search" />
+ </form>
+ </div>
+ <div id="right" class="align-left">
+ <h3>Pyramid links</h3>
+ <ul class="links">
+ <li>
+ <a href="http://pylonshq.com">Pylons Website</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonshq.com/">The Pylons Project Documentation</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonshq.com/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonshq.com/pyramid/dev/#api-documentation">API Documentation</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonshq.com/pyramid/dev/#tutorials">Tutorials</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonshq.com/pyramid/dev/#change-history">Change History</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonshq.com/pyramid/dev/#sample-applications">Sample Applications</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonshq.com/pyramid/dev/#support-and-development">Support and Development</a>
+ </li>
+ <li>
+ <a href="irc://irc.freenode.net#pyramid">IRC Channel</a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="footer">
+ <div class="footer">© Copyright 2008-2010, Agendaless Consulting.</div>
+ </div>
+</body>
+</html>
diff --git a/docs/quick_tour/awesome/awesome/tests.py b/docs/quick_tour/awesome/awesome/tests.py
new file mode 100644
index 000000000..ac222e25b
--- /dev/null
+++ b/docs/quick_tour/awesome/awesome/tests.py
@@ -0,0 +1,21 @@
+import unittest
+from pyramid import testing
+from pyramid.i18n import TranslationStringFactory
+
+_ = TranslationStringFactory('awesome')
+
+
+class ViewTests(unittest.TestCase):
+
+ def setUp(self):
+ testing.setUp()
+
+ def tearDown(self):
+ testing.tearDown()
+
+ def test_my_view(self):
+ from awesome.views import my_view
+ request = testing.DummyRequest()
+ response = my_view(request)
+ self.assertEqual(response['project'], 'awesome')
+
diff --git a/docs/quick_tour/awesome/awesome/views.py b/docs/quick_tour/awesome/awesome/views.py
new file mode 100644
index 000000000..67b282f87
--- /dev/null
+++ b/docs/quick_tour/awesome/awesome/views.py
@@ -0,0 +1,6 @@
+from pyramid.i18n import TranslationStringFactory
+
+_ = TranslationStringFactory('awesome')
+
+def my_view(request):
+ return {'project':'awesome'}
diff --git a/docs/quick_tour/awesome/development.ini b/docs/quick_tour/awesome/development.ini
new file mode 100644
index 000000000..a473d32f1
--- /dev/null
+++ b/docs/quick_tour/awesome/development.ini
@@ -0,0 +1,49 @@
+[app:awesome]
+use = egg:awesome
+reload_templates = true
+debug_authorization = false
+debug_notfound = false
+debug_routematch = false
+debug_templates = true
+default_locale_name = en
+jinja2.directories = awesome:templates
+
+[pipeline:main]
+pipeline =
+ awesome
+
+[server:main]
+use = egg:pyramid#wsgiref
+host = 0.0.0.0
+port = 6543
+
+# Begin logging configuration
+
+[loggers]
+keys = root, awesome
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[logger_awesome]
+level = DEBUG
+handlers =
+qualname = awesome
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
+
+# End logging configuration
diff --git a/docs/quick_tour/awesome/message-extraction.ini b/docs/quick_tour/awesome/message-extraction.ini
new file mode 100644
index 000000000..0c3d54bc1
--- /dev/null
+++ b/docs/quick_tour/awesome/message-extraction.ini
@@ -0,0 +1,3 @@
+[python: **.py]
+[jinja2: **.jinja2]
+encoding = utf-8
diff --git a/docs/quick_tour/awesome/setup.cfg b/docs/quick_tour/awesome/setup.cfg
new file mode 100644
index 000000000..b1cd90d2c
--- /dev/null
+++ b/docs/quick_tour/awesome/setup.cfg
@@ -0,0 +1,28 @@
+[nosetests]
+match = ^test
+nocapture = 1
+cover-package = awesome
+with-coverage = 1
+cover-erase = 1
+
+[compile_catalog]
+directory = awesome/locale
+domain = awesome
+statistics = true
+
+[extract_messages]
+add_comments = TRANSLATORS:
+output_file = awesome/locale/awesome.pot
+width = 80
+mapping_file = message-extraction.ini
+
+[init_catalog]
+domain = awesome
+input_file = awesome/locale/awesome.pot
+output_dir = awesome/locale
+
+[update_catalog]
+domain = awesome
+input_file = awesome/locale/awesome.pot
+output_dir = awesome/locale
+previous = true
diff --git a/docs/quick_tour/awesome/setup.py b/docs/quick_tour/awesome/setup.py
new file mode 100644
index 000000000..32d666317
--- /dev/null
+++ b/docs/quick_tour/awesome/setup.py
@@ -0,0 +1,36 @@
+import os
+
+from setuptools import setup, find_packages
+
+here = os.path.abspath(os.path.dirname(__file__))
+README = open(os.path.join(here, 'README.txt')).read()
+CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+
+requires=['pyramid>=1.0.2', 'pyramid_jinja2']
+
+setup(name='awesome',
+ version='0.0',
+ description='awesome',
+ long_description=README + '\n\n' + CHANGES,
+ classifiers=[
+ "Programming Language :: Python",
+ "Framework :: Pylons",
+ "Topic :: Internet :: WWW/HTTP",
+ "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
+ ],
+ author='',
+ author_email='',
+ url='',
+ keywords='web pyramid pylons',
+ packages=find_packages(),
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=requires,
+ tests_require=requires,
+ test_suite="awesome",
+ entry_points = """\
+ [paste.app_factory]
+ main = awesome:main
+ """,
+ paster_plugins=['pyramid'],
+ )
diff --git a/docs/quick_tour/hello_world/app.py b/docs/quick_tour/hello_world/app.py
new file mode 100644
index 000000000..df5a6cf18
--- /dev/null
+++ b/docs/quick_tour/hello_world/app.py
@@ -0,0 +1,16 @@
+from wsgiref.simple_server import make_server
+from pyramid.config import Configurator
+from pyramid.response import Response
+
+
+def hello_world(request):
+ return Response('<h1>Hello World!</h1>')
+
+
+if __name__ == '__main__':
+ config = Configurator()
+ config.add_route('hello', '/')
+ config.add_view(hello_world, route_name='hello')
+ app = config.make_wsgi_app()
+ server = make_server('0.0.0.0', 6543, app)
+ server.serve_forever() \ No newline at end of file
diff --git a/docs/quick_tour/jinja2/app.py b/docs/quick_tour/jinja2/app.py
new file mode 100644
index 000000000..83af219db
--- /dev/null
+++ b/docs/quick_tour/jinja2/app.py
@@ -0,0 +1,11 @@
+from wsgiref.simple_server import make_server
+from pyramid.config import Configurator
+
+if __name__ == '__main__':
+ config = Configurator()
+ config.add_route('hello', '/howdy/{name}')
+ config.include('pyramid_jinja2')
+ config.scan('views')
+ app = config.make_wsgi_app()
+ server = make_server('0.0.0.0', 6543, app)
+ server.serve_forever() \ No newline at end of file
diff --git a/docs/quick_tour/jinja2/hello_world.jinja2 b/docs/quick_tour/jinja2/hello_world.jinja2
new file mode 100644
index 000000000..e177744b5
--- /dev/null
+++ b/docs/quick_tour/jinja2/hello_world.jinja2
@@ -0,0 +1,8 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+ <title>Hello World</title>
+</head>
+<body>
+<h1>Hello {{ name }}!</h1>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/quick_tour/jinja2/views.py b/docs/quick_tour/jinja2/views.py
new file mode 100644
index 000000000..916cdc720
--- /dev/null
+++ b/docs/quick_tour/jinja2/views.py
@@ -0,0 +1,8 @@
+from pyramid.view import view_config
+
+
+# Start View 1
+@view_config(route_name='hello', renderer='hello_world.jinja2')
+# End View 1
+def hello_world(request):
+ return dict(name=request.matchdict['name'])
diff --git a/docs/quick_tour/json/app.py b/docs/quick_tour/json/app.py
new file mode 100644
index 000000000..950cb478f
--- /dev/null
+++ b/docs/quick_tour/json/app.py
@@ -0,0 +1,15 @@
+from wsgiref.simple_server import make_server
+
+from pyramid.config import Configurator
+
+
+if __name__ == '__main__':
+ config = Configurator()
+ config.add_route('hello', '/howdy/{name}')
+ config.add_route('hello_json', 'hello.json')
+ config.add_static_view(name='static', path='static')
+ config.include('pyramid_jinja2')
+ config.scan('views')
+ app = config.make_wsgi_app()
+ server = make_server('0.0.0.0', 6543, app)
+ server.serve_forever() \ No newline at end of file
diff --git a/docs/quick_tour/json/hello_world.jinja2 b/docs/quick_tour/json/hello_world.jinja2
new file mode 100644
index 000000000..f6862e618
--- /dev/null
+++ b/docs/quick_tour/json/hello_world.jinja2
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Quick Glance</title>
+ <link rel="stylesheet" href="/static/app.css"/>
+</head>
+<body>
+<h1>Hello {{ name }}!</h1>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/quick_tour/json/hello_world.pt b/docs/quick_tour/json/hello_world.pt
new file mode 100644
index 000000000..711054aa9
--- /dev/null
+++ b/docs/quick_tour/json/hello_world.pt
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Quick Glance</title>
+ <!-- Start Link 1 -->
+ <link rel="stylesheet" href="/static/app.css" />
+ <!-- End Link 1 -->
+ <!-- Start Link 2 -->
+ <link rel="stylesheet"
+ href="${request.static_url('static/app.css')}"
+ />
+ <!-- End Link 2 -->
+</head>
+<body>
+<h1>Hello ${name}!</h1>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/quick_tour/json/views.py b/docs/quick_tour/json/views.py
new file mode 100644
index 000000000..583e220c7
--- /dev/null
+++ b/docs/quick_tour/json/views.py
@@ -0,0 +1,13 @@
+from pyramid.view import view_config
+
+
+@view_config(route_name='hello', renderer='hello_world.pt')
+def hello_world(request):
+ return dict(name=request.matchdict['name'])
+
+
+# Start View 1
+@view_config(route_name='hello_json', renderer='json')
+def hello_json(request):
+ return [1, 2, 3]
+ # End View 1 \ No newline at end of file
diff --git a/docs/quick_tour/package/CHANGES.txt b/docs/quick_tour/package/CHANGES.txt
new file mode 100644
index 000000000..ffa255da8
--- /dev/null
+++ b/docs/quick_tour/package/CHANGES.txt
@@ -0,0 +1,4 @@
+0.0
+---
+
+- Initial version
diff --git a/docs/quick_tour/package/MANIFEST.in b/docs/quick_tour/package/MANIFEST.in
new file mode 100644
index 000000000..18fbd855c
--- /dev/null
+++ b/docs/quick_tour/package/MANIFEST.in
@@ -0,0 +1,2 @@
+include *.txt *.ini *.cfg *.rst
+recursive-include hello_world *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml
diff --git a/docs/quick_tour/package/README.txt b/docs/quick_tour/package/README.txt
new file mode 100644
index 000000000..63aaf6fbd
--- /dev/null
+++ b/docs/quick_tour/package/README.txt
@@ -0,0 +1,4 @@
+hello_world README
+
+
+
diff --git a/docs/quick_tour/package/development.ini b/docs/quick_tour/package/development.ini
new file mode 100644
index 000000000..a3a73e885
--- /dev/null
+++ b/docs/quick_tour/package/development.ini
@@ -0,0 +1,54 @@
+# Start Includes
+[app:hello_world]
+pyramid.includes = pyramid_debugtoolbar
+# End Includes
+use = egg:hello_world
+reload_templates = true
+debug_authorization = false
+debug_notfound = false
+debug_routematch = false
+debug_templates = true
+default_locale_name = en
+jinja2.directories = hello_world:templates
+
+[pipeline:main]
+pipeline =
+ hello_world
+
+[server:main]
+use = egg:pyramid#wsgiref
+host = 0.0.0.0
+port = 6543
+
+# Begin logging configuration
+
+# Start Sphinx Include
+[loggers]
+keys = root, hello_world
+
+[logger_hello_world]
+level = DEBUG
+handlers =
+qualname = hello_world
+# End Sphinx Include
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
+
+# End logging configuration
diff --git a/docs/quick_tour/package/hello_world/__init__.py b/docs/quick_tour/package/hello_world/__init__.py
new file mode 100644
index 000000000..6e66bf40a
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/__init__.py
@@ -0,0 +1,34 @@
+from pyramid.config import Configurator
+from pyramid_jinja2 import renderer_factory
+# Start Sphinx Include 1
+from pyramid.session import UnencryptedCookieSessionFactoryConfig
+# End Sphinx Include 1
+
+from hello_world.models import get_root
+
+def main(global_config, **settings):
+ """ This function returns a WSGI application.
+
+ It is usually called by the PasteDeploy framework during
+ ``paster serve``.
+ """
+ settings = dict(settings)
+ settings.setdefault('jinja2.i18n.domain', 'hello_world')
+
+ # Start Sphinx Include 2
+ my_session_factory = UnencryptedCookieSessionFactoryConfig('itsaseekreet')
+ config = Configurator(root_factory=get_root, settings=settings,
+ session_factory=my_session_factory)
+ # End Sphinx Include 2
+ config.add_translation_dirs('locale/')
+ # Start Include
+ config.include('pyramid_jinja2')
+ # End Include
+
+
+ config.add_static_view('static', 'static')
+ config.add_view('hello_world.views.my_view',
+ context='hello_world.models.MyModel',
+ renderer="mytemplate.jinja2")
+
+ return config.make_wsgi_app()
diff --git a/docs/quick_tour/package/hello_world/init.py b/docs/quick_tour/package/hello_world/init.py
new file mode 100644
index 000000000..9d7ec43d8
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/init.py
@@ -0,0 +1,34 @@
+from pyramid.config import Configurator
+from pyramid_jinja2 import renderer_factory
+# Start Sphinx 1
+from pyramid.session import UnencryptedCookieSessionFactoryConfig
+# End Sphinx 1
+
+from hello_world.models import get_root
+
+def main(global_config, **settings):
+ """ This function returns a WSGI application.
+
+ It is usually called by the PasteDeploy framework during
+ ``paster serve``.
+ """
+ settings = dict(settings)
+ settings.setdefault('jinja2.i18n.domain', 'hello_world')
+
+ config = Configurator(root_factory=get_root, settings=settings)
+ config.add_translation_dirs('locale/')
+ # Start Include
+ config.include('pyramid_jinja2')
+ # End Include
+
+ # Start Sphinx Include 2
+ my_session_factory = UnencryptedCookieSessionFactoryConfig('itsaseekreet')
+ config = Configurator(session_factory=my_session_factory)
+ # End Sphinx Include 2
+
+ config.add_static_view('static', 'static')
+ config.add_view('hello_world.views.my_view',
+ context='hello_world.models.MyModel',
+ renderer="mytemplate.jinja2")
+
+ return config.make_wsgi_app()
diff --git a/docs/quick_tour/package/hello_world/locale/de/LC_MESSAGES/hello_world.mo b/docs/quick_tour/package/hello_world/locale/de/LC_MESSAGES/hello_world.mo
new file mode 100644
index 000000000..40bf0c271
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/locale/de/LC_MESSAGES/hello_world.mo
Binary files differ
diff --git a/docs/quick_tour/package/hello_world/locale/de/LC_MESSAGES/hello_world.po b/docs/quick_tour/package/hello_world/locale/de/LC_MESSAGES/hello_world.po
new file mode 100644
index 000000000..0df243dba
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/locale/de/LC_MESSAGES/hello_world.po
@@ -0,0 +1,21 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2011-05-12 09:14-0330\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+
+msgid "Hello!"
+msgstr "Hallo!"
diff --git a/docs/quick_tour/package/hello_world/locale/fr/LC_MESSAGES/hello_world.mo b/docs/quick_tour/package/hello_world/locale/fr/LC_MESSAGES/hello_world.mo
new file mode 100644
index 000000000..4fc438bfe
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/locale/fr/LC_MESSAGES/hello_world.mo
Binary files differ
diff --git a/docs/quick_tour/package/hello_world/locale/fr/LC_MESSAGES/hello_world.po b/docs/quick_tour/package/hello_world/locale/fr/LC_MESSAGES/hello_world.po
new file mode 100644
index 000000000..dc0aae5d7
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/locale/fr/LC_MESSAGES/hello_world.po
@@ -0,0 +1,21 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2011-05-12 09:14-0330\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+
+msgid "Hello!"
+msgstr "Bonjour!"
diff --git a/docs/quick_tour/package/hello_world/locale/hello_world.pot b/docs/quick_tour/package/hello_world/locale/hello_world.pot
new file mode 100644
index 000000000..9c9460cb2
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/locale/hello_world.pot
@@ -0,0 +1,21 @@
+# Translations template for PROJECT.
+# Copyright (C) 2011 ORGANIZATION
+# This file is distributed under the same license as the PROJECT project.
+# FIRST AUTHOR <EMAIL@ADDRESS>, 2011.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PROJECT VERSION\n"
+"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
+"POT-Creation-Date: 2011-05-12 09:14-0330\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 0.9.6\n"
+
+msgid "Hello!"
+msgstr ""
diff --git a/docs/quick_tour/package/hello_world/models.py b/docs/quick_tour/package/hello_world/models.py
new file mode 100644
index 000000000..edd361c9c
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/models.py
@@ -0,0 +1,8 @@
+class MyModel(object):
+ pass
+
+root = MyModel()
+
+
+def get_root(request):
+ return root
diff --git a/docs/quick_tour/package/hello_world/static/favicon.ico b/docs/quick_tour/package/hello_world/static/favicon.ico
new file mode 100644
index 000000000..71f837c9e
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/static/favicon.ico
Binary files differ
diff --git a/docs/quick_tour/package/hello_world/static/logo.png b/docs/quick_tour/package/hello_world/static/logo.png
new file mode 100644
index 000000000..88f5d9865
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/static/logo.png
Binary files differ
diff --git a/docs/quick_tour/package/hello_world/static/pylons.css b/docs/quick_tour/package/hello_world/static/pylons.css
new file mode 100644
index 000000000..42e2e320e
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/static/pylons.css
@@ -0,0 +1,73 @@
+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;}
+/* remember to define focus styles! */
+:focus{outline:0;}
+/* remember to highlight inserts somehow! */
+ins{text-decoration:none;}
+del{text-decoration:line-through;}
+/* tables still need 'cellspacing="0"' in the markup */
+table{border-collapse:collapse;border-spacing:0;}
+/* restyling */
+sub{vertical-align:sub;font-size:smaller;line-height:normal;}
+sup{vertical-align:super;font-size:smaller;line-height:normal;}
+/* lists */
+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;}
+/* nested lists have no top/bottom margins */
+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;}
+/* 2 deep unordered lists use a circle */
+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;}
+/* 3 deep (or more) unordered lists use a square */
+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;/* 28px */
+line-height:1.7em;font-family:helvetica,verdana;}
+h2{font-size:1.5em;/* 24px */
+line-height:1.7em;font-family:helvetica,verdana;}
+h3{font-size:1.25em;/* 20px */
+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 "Nobile","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:"Nobile","Lucida Grande",Lucida,Verdana,sans-serif;font-weight:normal;color:#144fb2;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;}
+#header{background-color:#e88f00;top:0;font-size:14px;}
+#footer{background-color:#000000;bottom:0;position: relative;margin-top:-40px;clear:both;}
+.header,.footer{width:700px;margin-right:auto;margin-left:auto;}
+.wrapper{width:100%}
+#top,#bottom{width:100%;}
+#top{color:#888;background-color:#eee;height:300px;border-bottom:2px solid #ddd;}
+#bottom{color:#222;background-color:#ffffff;overflow:auto;padding-bottom:80px;}
+.top,.bottom{width:700px;margin-right:auto;margin-left:auto;}
+.top{padding-top:100px;}
+.app-welcome{margin-top:25px;}
+.app-name{color:#000000;font-weight:bold;}
+.bottom{padding-top:50px;}
+#left{width:325px;float:left;padding-right:25px;}
+#right{width:325px;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=submit]{background-color:#ddd;font-weight:bold;}
+/*Opera Fix*/
+body:before {content:"";height:100%;float:left;width:0;margin-top:-32767px;}
diff --git a/docs/quick_tour/package/hello_world/templates/mytemplate.jinja2 b/docs/quick_tour/package/hello_world/templates/mytemplate.jinja2
new file mode 100644
index 000000000..25a28ed7a
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/templates/mytemplate.jinja2
@@ -0,0 +1,90 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+ <title>The Pyramid Web Framework</title>
+ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+ <meta name="keywords" content="python web application" />
+ <meta name="description" content="pyramid web application" />
+ <link rel="shortcut icon" href="{{request.application_url}}/static/favicon.ico" />
+ <link rel="stylesheet" href="{{request.application_url}}/static/pylons.css" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Nobile:regular,italic,bold,bolditalic&amp;subset=latin" type="text/css" media="screen" charset="utf-8" />
+ <!--[if !IE 7]>
+ <style type="text/css">
+ #wrap {display:table;height:100%}
+ </style>
+ <![endif]-->
+ <style type="text/css">
+ .locale { text-align: center; }
+ .locale-name { font-weight: bold; }
+ </style>
+</head>
+<body>
+ <div id="wrap">
+ <div id="header">
+ <div class="header">The Pyramid Web Framework</div>
+ </div>
+ <div id="top">
+ <div class="top align-center">
+ <img src="{{request.application_url}}/static/logo.png" width="300" height="80" alt="Logo"/>
+ <p class="app-welcome">
+ Welcome to <span class="app-name">{{project}}</span>, an application generated by<br/>
+ the Pyramid Web Framework.
+ </p>
+ </div>
+ </div>
+ <div id="bottom">
+ <div class="locale">
+ <h2>{% trans %}Hello!{% endtrans %}</h2>
+ <!-- Start Sphinx Include 1 -->
+ <p>Counter: {{ request.session.counter }}</p>
+ <!-- End Sphinx Include 1 -->
+ <p>Request performed with <span class="locale-name">{{ request.locale_name }}</span> locale.</p>
+ </div>
+ <div class="bottom">
+ <div id="left" class="align-right">
+ <h3>Search Pyramid documentation</h3>
+ <form method="get" action="http://docs.pylonshq.com/pyramid/dev/search.html">
+ <input type="text" id="q" name="q" value="" />
+ <input type="submit" id="x" value="Search" />
+ </form>
+ </div>
+ <div id="right" class="align-left">
+ <h3>Pyramid links</h3>
+ <ul class="links">
+ <li>
+ <a href="http://pylonshq.com">Pylons Website</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonshq.com/">The Pylons Project Documentation</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonshq.com/pyramid/dev/#narrative-documentation">Narrative Documentation</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonshq.com/pyramid/dev/#api-documentation">API Documentation</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonshq.com/pyramid/dev/#tutorials">Tutorials</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonshq.com/pyramid/dev/#change-history">Change History</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonshq.com/pyramid/dev/#sample-applications">Sample Applications</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonshq.com/pyramid/dev/#support-and-development">Support and Development</a>
+ </li>
+ <li>
+ <a href="irc://irc.freenode.net#pyramid">IRC Channel</a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="footer">
+ <div class="footer">© Copyright 2008-2010, Agendaless Consulting.</div>
+ </div>
+</body>
+</html>
diff --git a/docs/quick_tour/package/hello_world/tests.py b/docs/quick_tour/package/hello_world/tests.py
new file mode 100644
index 000000000..ccec14f70
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/tests.py
@@ -0,0 +1,20 @@
+import unittest
+from pyramid import testing
+from pyramid.i18n import TranslationStringFactory
+
+_ = TranslationStringFactory('hello_world')
+
+
+class ViewTests(unittest.TestCase):
+
+ def setUp(self):
+ testing.setUp()
+
+ def tearDown(self):
+ testing.tearDown()
+
+ def test_my_view(self):
+ from hello_world.views import my_view
+ request = testing.DummyRequest()
+ response = my_view(request)
+ self.assertEqual(response['project'], 'hello_world')
diff --git a/docs/quick_tour/package/hello_world/views.py b/docs/quick_tour/package/hello_world/views.py
new file mode 100644
index 000000000..109c260ad
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/views.py
@@ -0,0 +1,22 @@
+# Start Logging 1
+import logging
+log = logging.getLogger(__name__)
+# End Logging 1
+
+from pyramid.i18n import TranslationStringFactory
+
+_ = TranslationStringFactory('hello_world')
+
+
+def my_view(request):
+ # Start Logging 2
+ log.debug('Some Message')
+ # End Logging 2
+ # Start Sphinx Include 1
+ session = request.session
+ if 'counter' in session:
+ session['counter'] += 1
+ else:
+ session['counter'] = 0
+ # End Sphinx Include 1
+ return {'project': 'hello_world'}
diff --git a/docs/quick_tour/package/message-extraction.ini b/docs/quick_tour/package/message-extraction.ini
new file mode 100644
index 000000000..0c3d54bc1
--- /dev/null
+++ b/docs/quick_tour/package/message-extraction.ini
@@ -0,0 +1,3 @@
+[python: **.py]
+[jinja2: **.jinja2]
+encoding = utf-8
diff --git a/docs/quick_tour/package/setup.cfg b/docs/quick_tour/package/setup.cfg
new file mode 100644
index 000000000..186e796fc
--- /dev/null
+++ b/docs/quick_tour/package/setup.cfg
@@ -0,0 +1,28 @@
+[nosetests]
+match = ^test
+nocapture = 1
+cover-package = hello_world
+with-coverage = 1
+cover-erase = 1
+
+[compile_catalog]
+directory = hello_world/locale
+domain = hello_world
+statistics = true
+
+[extract_messages]
+add_comments = TRANSLATORS:
+output_file = hello_world/locale/hello_world.pot
+width = 80
+mapping_file = message-extraction.ini
+
+[init_catalog]
+domain = hello_world
+input_file = hello_world/locale/hello_world.pot
+output_dir = hello_world/locale
+
+[update_catalog]
+domain = hello_world
+input_file = hello_world/locale/hello_world.pot
+output_dir = hello_world/locale
+previous = true
diff --git a/docs/quick_tour/package/setup.py b/docs/quick_tour/package/setup.py
new file mode 100644
index 000000000..f118ed5fb
--- /dev/null
+++ b/docs/quick_tour/package/setup.py
@@ -0,0 +1,41 @@
+import os
+
+from setuptools import setup, find_packages
+
+here = os.path.abspath(os.path.dirname(__file__))
+README = open(os.path.join(here, 'README.txt')).read()
+CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+
+# Start Requires
+requires = ['pyramid>=1.0.2', 'pyramid_jinja2', 'pyramid_debugtoolbar']
+# End Requires
+
+setup(name='hello_world',
+ version='0.0',
+ description='hello_world',
+ long_description=README + '\n\n' + CHANGES,
+ classifiers=[
+ "Programming Language :: Python",
+ "Framework :: Pylons",
+ "Topic :: Internet :: WWW/HTTP",
+ "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
+ ],
+ author='',
+ author_email='',
+ url='',
+ keywords='web pyramid pylons',
+ packages=find_packages(),
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=requires,
+ tests_require=requires,
+ test_suite="hello_world",
+ entry_points="""\
+ [paste.app_factory]
+ main = hello_world:main
+ """,
+ paster_plugins=['pyramid'],
+ extras_require={
+ 'testing': ['nose', ],
+ }
+) \ No newline at end of file
diff --git a/docs/quick_tour/requests/app.py b/docs/quick_tour/requests/app.py
new file mode 100644
index 000000000..7ac81eb50
--- /dev/null
+++ b/docs/quick_tour/requests/app.py
@@ -0,0 +1,24 @@
+from wsgiref.simple_server import make_server
+from pyramid.config import Configurator
+from pyramid.response import Response
+
+
+def hello_world(request):
+ # Some parameters from a request such as /?name=lisa
+ url = request.url
+ name = request.params.get('name', 'No Name Provided')
+
+ body = 'URL %s with name: %s' % (url, name)
+ return Response(
+ content_type="text/plain",
+ body=body
+ )
+
+
+if __name__ == '__main__':
+ config = Configurator()
+ config.add_route('hello', '/')
+ config.add_view(hello_world, route_name='hello')
+ app = config.make_wsgi_app()
+ server = make_server('0.0.0.0', 6543, app)
+ server.serve_forever() \ No newline at end of file
diff --git a/docs/quick_tour/routing/app.py b/docs/quick_tour/routing/app.py
new file mode 100644
index 000000000..04a8a6344
--- /dev/null
+++ b/docs/quick_tour/routing/app.py
@@ -0,0 +1,12 @@
+from wsgiref.simple_server import make_server
+from pyramid.config import Configurator
+
+if __name__ == '__main__':
+ config = Configurator()
+ # Start Route 1
+ config.add_route('hello', '/howdy/{first}/{last}')
+ # End Route 1
+ config.scan('views')
+ app = config.make_wsgi_app()
+ server = make_server('0.0.0.0', 6543, app)
+ server.serve_forever() \ No newline at end of file
diff --git a/docs/quick_tour/routing/views.py b/docs/quick_tour/routing/views.py
new file mode 100644
index 000000000..8cb8d3780
--- /dev/null
+++ b/docs/quick_tour/routing/views.py
@@ -0,0 +1,10 @@
+from pyramid.response import Response
+from pyramid.view import view_config
+
+
+# Start Route 1
+@view_config(route_name='hello')
+def hello_world(request):
+ body = '<h1>Hi %(first)s %(last)s!</h1>' % request.matchdict
+ return Response(body)
+ # End Route 1 \ No newline at end of file
diff --git a/docs/quick_tour/sqla_demo/CHANGES.txt b/docs/quick_tour/sqla_demo/CHANGES.txt
new file mode 100644
index 000000000..35a34f332
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/CHANGES.txt
@@ -0,0 +1,4 @@
+0.0
+---
+
+- Initial version
diff --git a/docs/quick_tour/sqla_demo/MANIFEST.in b/docs/quick_tour/sqla_demo/MANIFEST.in
new file mode 100644
index 000000000..a432577e9
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/MANIFEST.in
@@ -0,0 +1,2 @@
+include *.txt *.ini *.cfg *.rst
+recursive-include sqla_demo *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml
diff --git a/docs/quick_tour/sqla_demo/README.txt b/docs/quick_tour/sqla_demo/README.txt
new file mode 100644
index 000000000..f35d3aec5
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/README.txt
@@ -0,0 +1,14 @@
+sqla_demo README
+==================
+
+Getting Started
+---------------
+
+- cd <directory containing this file>
+
+- $venv/bin/python setup.py develop
+
+- $venv/bin/initialize_sqla_demo_db development.ini
+
+- $venv/bin/pserve development.ini
+
diff --git a/docs/quick_tour/sqla_demo/development.ini b/docs/quick_tour/sqla_demo/development.ini
new file mode 100644
index 000000000..174468abf
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/development.ini
@@ -0,0 +1,71 @@
+###
+# app configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
+[app:main]
+use = egg:sqla_demo
+
+pyramid.reload_templates = true
+pyramid.debug_authorization = false
+pyramid.debug_notfound = false
+pyramid.debug_routematch = false
+pyramid.default_locale_name = en
+pyramid.includes =
+ pyramid_debugtoolbar
+ pyramid_tm
+
+sqlalchemy.url = sqlite:///%(here)s/sqla_demo.sqlite
+
+# By default, the toolbar only appears for clients from IP addresses
+# '127.0.0.1' and '::1'.
+# debugtoolbar.hosts = 127.0.0.1 ::1
+
+###
+# wsgi server configuration
+###
+
+[server:main]
+use = egg:waitress#main
+host = 0.0.0.0
+port = 6543
+
+###
+# logging configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
+
+[loggers]
+keys = root, sqla_demo, sqlalchemy
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[logger_sqla_demo]
+level = DEBUG
+handlers =
+qualname = sqla_demo
+
+[logger_sqlalchemy]
+level = INFO
+handlers =
+qualname = sqlalchemy.engine
+# "level = INFO" logs SQL queries.
+# "level = DEBUG" logs SQL queries and results.
+# "level = WARN" logs neither. (Recommended for production systems.)
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
diff --git a/docs/quick_tour/sqla_demo/production.ini b/docs/quick_tour/sqla_demo/production.ini
new file mode 100644
index 000000000..dc0ba304f
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/production.ini
@@ -0,0 +1,62 @@
+###
+# app configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
+###
+
+[app:main]
+use = egg:sqla_demo
+
+pyramid.reload_templates = false
+pyramid.debug_authorization = false
+pyramid.debug_notfound = false
+pyramid.debug_routematch = false
+pyramid.default_locale_name = en
+pyramid.includes =
+ pyramid_tm
+
+sqlalchemy.url = sqlite:///%(here)s/sqla_demo.sqlite
+
+[server:main]
+use = egg:waitress#main
+host = 0.0.0.0
+port = 6543
+
+###
+# logging configuration
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
+###
+
+[loggers]
+keys = root, sqla_demo, sqlalchemy
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = WARN
+handlers = console
+
+[logger_sqla_demo]
+level = WARN
+handlers =
+qualname = sqla_demo
+
+[logger_sqlalchemy]
+level = WARN
+handlers =
+qualname = sqlalchemy.engine
+# "level = INFO" logs SQL queries.
+# "level = DEBUG" logs SQL queries and results.
+# "level = WARN" logs neither. (Recommended for production systems.)
+
+[handler_console]
+class = StreamHandler
+args = (sys.stderr,)
+level = NOTSET
+formatter = generic
+
+[formatter_generic]
+format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
diff --git a/docs/quick_tour/sqla_demo/setup.cfg b/docs/quick_tour/sqla_demo/setup.cfg
new file mode 100644
index 000000000..9f91cd122
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/setup.cfg
@@ -0,0 +1,27 @@
+[nosetests]
+match=^test
+nocapture=1
+cover-package=sqla_demo
+with-coverage=1
+cover-erase=1
+
+[compile_catalog]
+directory = sqla_demo/locale
+domain = sqla_demo
+statistics = true
+
+[extract_messages]
+add_comments = TRANSLATORS:
+output_file = sqla_demo/locale/sqla_demo.pot
+width = 80
+
+[init_catalog]
+domain = sqla_demo
+input_file = sqla_demo/locale/sqla_demo.pot
+output_dir = sqla_demo/locale
+
+[update_catalog]
+domain = sqla_demo
+input_file = sqla_demo/locale/sqla_demo.pot
+output_dir = sqla_demo/locale
+previous = true
diff --git a/docs/quick_tour/sqla_demo/setup.py b/docs/quick_tour/sqla_demo/setup.py
new file mode 100644
index 000000000..ac2eed035
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/setup.py
@@ -0,0 +1,44 @@
+import os
+
+from setuptools import setup, find_packages
+
+here = os.path.abspath(os.path.dirname(__file__))
+README = open(os.path.join(here, 'README.txt')).read()
+CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+
+requires = [
+ 'pyramid',
+ 'SQLAlchemy',
+ 'transaction',
+ 'pyramid_tm',
+ 'pyramid_debugtoolbar',
+ 'zope.sqlalchemy',
+ 'waitress',
+ ]
+
+setup(name='sqla_demo',
+ version='0.0',
+ description='sqla_demo',
+ long_description=README + '\n\n' + CHANGES,
+ classifiers=[
+ "Programming Language :: Python",
+ "Framework :: Pyramid",
+ "Topic :: Internet :: WWW/HTTP",
+ "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
+ ],
+ author='',
+ author_email='',
+ url='',
+ keywords='web wsgi bfg pylons pyramid',
+ packages=find_packages(),
+ include_package_data=True,
+ zip_safe=False,
+ test_suite='sqla_demo',
+ install_requires=requires,
+ entry_points="""\
+ [paste.app_factory]
+ main = sqla_demo:main
+ [console_scripts]
+ initialize_sqla_demo_db = sqla_demo.scripts.initializedb:main
+ """,
+ )
diff --git a/docs/quick_tour/sqla_demo/sqla_demo.sqlite b/docs/quick_tour/sqla_demo/sqla_demo.sqlite
new file mode 100644
index 000000000..fa6adb104
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo.sqlite
Binary files differ
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/__init__.py b/docs/quick_tour/sqla_demo/sqla_demo/__init__.py
new file mode 100644
index 000000000..aac7c5e69
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/__init__.py
@@ -0,0 +1,20 @@
+from pyramid.config import Configurator
+from sqlalchemy import engine_from_config
+
+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', '/')
+ config.scan()
+ return config.make_wsgi_app()
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/models.py b/docs/quick_tour/sqla_demo/sqla_demo/models.py
new file mode 100644
index 000000000..3dfb40e58
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/models.py
@@ -0,0 +1,29 @@
+from sqlalchemy import (
+ Column,
+ Integer,
+ Text,
+ )
+
+from sqlalchemy.ext.declarative import declarative_base
+
+from sqlalchemy.orm import (
+ scoped_session,
+ sessionmaker,
+ )
+
+from zope.sqlalchemy import ZopeTransactionExtension
+
+DBSession = scoped_session(sessionmaker(extension=ZopeTransactionExtension()))
+Base = declarative_base()
+
+# Start Sphinx Include
+class MyModel(Base):
+ __tablename__ = 'models'
+ id = Column(Integer, primary_key=True)
+ name = Column(Text, unique=True)
+ value = Column(Integer)
+
+ def __init__(self, name, value):
+ self.name = name
+ self.value = value
+ # End Sphinx Include
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/scripts/__init__.py b/docs/quick_tour/sqla_demo/sqla_demo/scripts/__init__.py
new file mode 100644
index 000000000..5bb534f79
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/scripts/__init__.py
@@ -0,0 +1 @@
+# package
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/scripts/initializedb.py b/docs/quick_tour/sqla_demo/sqla_demo/scripts/initializedb.py
new file mode 100644
index 000000000..66feb3008
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/scripts/initializedb.py
@@ -0,0 +1,37 @@
+import os
+import sys
+import transaction
+
+from sqlalchemy import engine_from_config
+
+from pyramid.paster import (
+ get_appsettings,
+ setup_logging,
+ )
+
+from ..models import (
+ DBSession,
+ MyModel,
+ Base,
+ )
+
+
+def usage(argv):
+ cmd = os.path.basename(argv[0])
+ print('usage: %s <config_uri>\n'
+ '(example: "%s development.ini")' % (cmd, cmd))
+ sys.exit(1)
+
+
+def main(argv=sys.argv):
+ if len(argv) != 2:
+ usage(argv)
+ config_uri = argv[1]
+ setup_logging(config_uri)
+ settings = get_appsettings(config_uri)
+ engine = engine_from_config(settings, 'sqlalchemy.')
+ DBSession.configure(bind=engine)
+ Base.metadata.create_all(engine)
+ with transaction.manager:
+ model = MyModel(name='one', value=1)
+ DBSession.add(model)
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/static/favicon.ico b/docs/quick_tour/sqla_demo/sqla_demo/static/favicon.ico
new file mode 100644
index 000000000..71f837c9e
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/static/favicon.ico
Binary files differ
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/static/footerbg.png b/docs/quick_tour/sqla_demo/sqla_demo/static/footerbg.png
new file mode 100644
index 000000000..1fbc873da
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/static/footerbg.png
Binary files differ
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/static/headerbg.png b/docs/quick_tour/sqla_demo/sqla_demo/static/headerbg.png
new file mode 100644
index 000000000..0596f2020
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/static/headerbg.png
Binary files differ
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/static/ie6.css b/docs/quick_tour/sqla_demo/sqla_demo/static/ie6.css
new file mode 100644
index 000000000..b7c8493d8
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/static/ie6.css
@@ -0,0 +1,8 @@
+* html img,
+* html .png{position:relative;behavior:expression((this.runtimeStyle.behavior="none")&&(this.pngSet?this.pngSet=true:(this.nodeName == "IMG" && this.src.toLowerCase().indexOf('.png')>-1?(this.runtimeStyle.backgroundImage = "none",
+this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.src + "',sizingMethod='image')",
+this.src = "static/transparent.gif"):(this.origBg = this.origBg? this.origBg :this.currentStyle.backgroundImage.toString().replace('url("','').replace('")',''),
+this.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" + this.origBg + "',sizingMethod='crop')",
+this.runtimeStyle.backgroundImage = "none")),this.pngSet=true)
+);}
+#wrap{display:table;height:100%}
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/static/middlebg.png b/docs/quick_tour/sqla_demo/sqla_demo/static/middlebg.png
new file mode 100644
index 000000000..2369cfb7d
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/static/middlebg.png
Binary files differ
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/static/pylons.css b/docs/quick_tour/sqla_demo/sqla_demo/static/pylons.css
new file mode 100644
index 000000000..4b1c017cd
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/static/pylons.css
@@ -0,0 +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: #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;
+}
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/static/pyramid-small.png b/docs/quick_tour/sqla_demo/sqla_demo/static/pyramid-small.png
new file mode 100644
index 000000000..a5bc0ade7
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/static/pyramid-small.png
Binary files differ
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/static/pyramid.png b/docs/quick_tour/sqla_demo/sqla_demo/static/pyramid.png
new file mode 100644
index 000000000..347e05549
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/static/pyramid.png
Binary files differ
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/static/transparent.gif b/docs/quick_tour/sqla_demo/sqla_demo/static/transparent.gif
new file mode 100644
index 000000000..0341802e5
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/static/transparent.gif
Binary files differ
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.pt b/docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.pt
new file mode 100644
index 000000000..321c0f5fb
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.pt
@@ -0,0 +1,76 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
+<head>
+ <title>The Pyramid Web Framework</title>
+ <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
+ <meta name="keywords" content="python web application" />
+ <meta name="description" content="pyramid web application" />
+ <link rel="shortcut icon" href="${request.static_url('sqla_demo:static/favicon.ico')}" />
+ <link rel="stylesheet" href="${request.static_url('sqla_demo:static/pylons.css')}" type="text/css" media="screen" charset="utf-8" />
+ <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/nobile/stylesheet.css" media="screen" />
+ <link rel="stylesheet" href="http://static.pylonsproject.org/fonts/neuton/stylesheet.css" media="screen" />
+ <!--[if lte IE 6]>
+ <link rel="stylesheet" href="${request.static_url('sqla_demo:static/ie6.css')}" type="text/css" media="screen" charset="utf-8" />
+ <![endif]-->
+</head>
+<body>
+ <div id="wrap">
+ <div id="top">
+ <div class="top align-center">
+ <div><img src="${request.static_url('sqla_demo:static/pyramid.png')}" width="750" height="169" alt="pyramid"/></div>
+ </div>
+ </div>
+ <div id="middle">
+ <div class="middle align-center">
+ <p class="app-welcome">
+ Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
+ the Pyramid web framework.
+ </p>
+ </div>
+ </div>
+ <div id="bottom">
+ <div class="bottom">
+ <div id="left" class="align-right">
+ <h2>Search documentation</h2>
+ <form method="get" action="http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/search.html">
+ <input type="text" id="q" name="q" value="" />
+ <input type="submit" id="x" value="Go" />
+ </form>
+ </div>
+ <div id="right" class="align-left">
+ <h2>Pyramid links</h2>
+ <ul class="links">
+ <li>
+ <a href="http://pylonsproject.org">Pylons Website</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/#narrative-documentation">Narrative Documentation</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/#reference-material">API Documentation</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/#tutorials">Tutorials</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/#detailed-change-history">Change History</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/#sample-applications">Sample Applications</a>
+ </li>
+ <li>
+ <a href="http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/#support-and-development">Support and Development</a>
+ </li>
+ <li>
+ <a href="irc://irc.freenode.net#pyramid">IRC Channel</a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
+ <div id="footer">
+ <div class="footer">&copy; Copyright 2008-2012, Agendaless Consulting.</div>
+ </div>
+</body>
+</html>
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/tests.py b/docs/quick_tour/sqla_demo/sqla_demo/tests.py
new file mode 100644
index 000000000..6fef6d695
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/tests.py
@@ -0,0 +1,33 @@
+import unittest
+import transaction
+
+from pyramid import testing
+
+from .models import DBSession
+
+
+class TestMyView(unittest.TestCase):
+ def setUp(self):
+ self.config = testing.setUp()
+ from sqlalchemy import create_engine
+ engine = create_engine('sqlite://')
+ from .models import (
+ Base,
+ MyModel,
+ )
+ DBSession.configure(bind=engine)
+ Base.metadata.create_all(engine)
+ with transaction.manager:
+ model = MyModel(name='one', value=55)
+ DBSession.add(model)
+
+ def tearDown(self):
+ DBSession.remove()
+ testing.tearDown()
+
+ def test_it(self):
+ from .views import my_view
+ request = testing.DummyRequest()
+ info = my_view(request)
+ self.assertEqual(info['one'].name, 'one')
+ self.assertEqual(info['project'], 'sqla_demo')
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/views.py b/docs/quick_tour/sqla_demo/sqla_demo/views.py
new file mode 100644
index 000000000..768a7e42e
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/views.py
@@ -0,0 +1,37 @@
+from pyramid.response import Response
+from pyramid.view import view_config
+
+from sqlalchemy.exc import DBAPIError
+
+from .models import (
+ DBSession,
+ MyModel,
+ )
+
+
+@view_config(route_name='home', renderer='templates/mytemplate.pt')
+def my_view(request):
+ try:
+ # Start Sphinx Include
+ one = DBSession.query(MyModel).filter(MyModel.name == 'one').first()
+ # End Sphinx Include
+ except DBAPIError:
+ return Response(conn_err_msg, content_type='text/plain', status_int=500)
+ return {'one': one, 'project': 'sqla_demo'}
+
+conn_err_msg = """\
+Pyramid is having a problem using your SQL database. The problem
+might be caused by one of the following things:
+
+1. You may need to run the "initialize_sqla_demo_db" script
+ to initialize your database tables. Check your virtual
+ environment's "bin" directory for this script and try to run it.
+
+2. Your database server may not be running. Check that the
+ database server referred to by the "sqlalchemy.url" setting in
+ your "development.ini" file is running.
+
+After you fix the problem, please restart the Pyramid application to
+try it again.
+"""
+
diff --git a/docs/quick_tour/static_assets/app.py b/docs/quick_tour/static_assets/app.py
new file mode 100644
index 000000000..9c808972f
--- /dev/null
+++ b/docs/quick_tour/static_assets/app.py
@@ -0,0 +1,14 @@
+from wsgiref.simple_server import make_server
+from pyramid.config import Configurator
+
+if __name__ == '__main__':
+ config = Configurator()
+ config.add_route('hello', '/howdy/{name}')
+ # Start Static 1
+ config.add_static_view(name='static', path='static')
+ # End Static 1
+ config.include('pyramid_jinja2')
+ config.scan('views')
+ app = config.make_wsgi_app()
+ server = make_server('0.0.0.0', 6543, app)
+ server.serve_forever() \ No newline at end of file
diff --git a/docs/quick_tour/static_assets/hello_world.jinja2 b/docs/quick_tour/static_assets/hello_world.jinja2
new file mode 100644
index 000000000..f6862e618
--- /dev/null
+++ b/docs/quick_tour/static_assets/hello_world.jinja2
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Quick Glance</title>
+ <link rel="stylesheet" href="/static/app.css"/>
+</head>
+<body>
+<h1>Hello {{ name }}!</h1>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/quick_tour/static_assets/hello_world.pt b/docs/quick_tour/static_assets/hello_world.pt
new file mode 100644
index 000000000..1797146eb
--- /dev/null
+++ b/docs/quick_tour/static_assets/hello_world.pt
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html lang="en"><head>
+ <title>Quick Glance</title>
+ <!-- Start Link 1 -->
+ <link rel="stylesheet" href="/static/app.css" />
+ <!-- End Link 1 -->
+ <!-- Start Link 2 -->
+ <link rel="stylesheet"
+ href="${request.static_url('static/app.css')}"
+ />
+ <!-- End Link 2 -->
+</head>
+<body>
+<h1>Hello ${name}!</h1>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/quick_tour/static_assets/static/app.css b/docs/quick_tour/static_assets/static/app.css
new file mode 100644
index 000000000..f8acf3164
--- /dev/null
+++ b/docs/quick_tour/static_assets/static/app.css
@@ -0,0 +1,4 @@
+body {
+ margin: 2em;
+ font-family: sans-serif;
+} \ No newline at end of file
diff --git a/docs/quick_tour/static_assets/views.py b/docs/quick_tour/static_assets/views.py
new file mode 100644
index 000000000..90730ae32
--- /dev/null
+++ b/docs/quick_tour/static_assets/views.py
@@ -0,0 +1,6 @@
+from pyramid.view import view_config
+
+
+@view_config(route_name='hello', renderer='hello_world.pt')
+def hello_world(request):
+ return dict(name=request.matchdict['name'])
diff --git a/docs/quick_tour/templating/app.py b/docs/quick_tour/templating/app.py
new file mode 100644
index 000000000..6d1a29f4e
--- /dev/null
+++ b/docs/quick_tour/templating/app.py
@@ -0,0 +1,10 @@
+from wsgiref.simple_server import make_server
+from pyramid.config import Configurator
+
+if __name__ == '__main__':
+ config = Configurator()
+ config.add_route('hello', '/howdy/{name}')
+ config.scan('views')
+ app = config.make_wsgi_app()
+ server = make_server('0.0.0.0', 6543, app)
+ server.serve_forever() \ No newline at end of file
diff --git a/docs/quick_tour/templating/hello_world.pt b/docs/quick_tour/templating/hello_world.pt
new file mode 100644
index 000000000..ae14f447d
--- /dev/null
+++ b/docs/quick_tour/templating/hello_world.pt
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Quick Glance</title>
+</head>
+<body>
+<h1>Hello ${name}</h1>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/quick_tour/templating/views.py b/docs/quick_tour/templating/views.py
new file mode 100644
index 000000000..6c7846efa
--- /dev/null
+++ b/docs/quick_tour/templating/views.py
@@ -0,0 +1,8 @@
+from pyramid.view import view_config
+
+
+# Start View 1
+@view_config(route_name='hello', renderer='hello_world.pt')
+def hello_world(request):
+ return dict(name=request.matchdict['name'])
+ # End View 1 \ No newline at end of file
diff --git a/docs/quick_tour/view_classes/app.py b/docs/quick_tour/view_classes/app.py
new file mode 100644
index 000000000..468c8c29e
--- /dev/null
+++ b/docs/quick_tour/view_classes/app.py
@@ -0,0 +1,13 @@
+from wsgiref.simple_server import make_server
+from pyramid.config import Configurator
+
+if __name__ == '__main__':
+ config = Configurator()
+ # Start Routes 1
+ config.add_route('hello', '/howdy/{name}')
+ # End Routes 1
+ config.include('pyramid_jinja2')
+ config.scan('views')
+ app = config.make_wsgi_app()
+ server = make_server('0.0.0.0', 6543, app)
+ server.serve_forever() \ No newline at end of file
diff --git a/docs/quick_tour/view_classes/delete.jinja2 b/docs/quick_tour/view_classes/delete.jinja2
new file mode 100644
index 000000000..ba45b7d16
--- /dev/null
+++ b/docs/quick_tour/view_classes/delete.jinja2
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Delete World</title>
+</head>
+<body>
+<h1>Delete {{ view.name }}!</h1>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/quick_tour/view_classes/edit.jinja2 b/docs/quick_tour/view_classes/edit.jinja2
new file mode 100644
index 000000000..ce0eb5bd1
--- /dev/null
+++ b/docs/quick_tour/view_classes/edit.jinja2
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Edit World</title>
+</head>
+<body>
+<h1>Edit {{ view.name }}!</h1>
+</body>
+</html> \ No newline at end of file
diff --git a/docs/quick_tour/view_classes/hello.jinja2 b/docs/quick_tour/view_classes/hello.jinja2
new file mode 100644
index 000000000..3446b96ce
--- /dev/null
+++ b/docs/quick_tour/view_classes/hello.jinja2
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <title>Hello World</title>
+</head>
+<body>
+<h1>Hello {{ view.name }}!</h1>
+<!-- Start Form 1 -->
+<form method="POST"
+ action="{{ request.current_route_url() }}">
+ <input name="new_name"/>
+ <input type="submit" name="form.edit" value="Save"/>
+ <input type="submit" name="form.delete" value="Delete"/>
+</form>
+<!-- End Form 1 -->
+</body>
+</html> \ No newline at end of file
diff --git a/docs/quick_tour/view_classes/views.py b/docs/quick_tour/view_classes/views.py
new file mode 100644
index 000000000..62556142e
--- /dev/null
+++ b/docs/quick_tour/view_classes/views.py
@@ -0,0 +1,32 @@
+from pyramid.view import (
+ view_config,
+ view_defaults
+ )
+
+
+# Start View 1
+# One route, at /howdy/amy, so don't repeat on each @view_config
+@view_defaults(route_name='hello')
+class HelloWorldViews:
+ def __init__(self, request):
+ self.request = request
+ # Our templates can now say {{ view.name }}
+ self.name = request.matchdict['name']
+
+ # Retrieving /howdy/amy the first time
+ @view_config(renderer='hello.jinja2')
+ def hello_view(self):
+ return dict()
+
+ # Posting to /howdy/amy via the "Edit" submit button
+ @view_config(request_param='form.edit', renderer='edit.jinja2')
+ def edit_view(self):
+ print('Edited')
+ return dict()
+
+ # Posting to /howdy/amy via the "Delete" submit button
+ @view_config(request_param='form.delete', renderer='delete.jinja2')
+ def delete_view(self):
+ print('Deleted')
+ return dict()
+ # End View 1 \ No newline at end of file
diff --git a/docs/quick_tour/views/app.py b/docs/quick_tour/views/app.py
new file mode 100644
index 000000000..54dc9ed4b
--- /dev/null
+++ b/docs/quick_tour/views/app.py
@@ -0,0 +1,13 @@
+from wsgiref.simple_server import make_server
+from pyramid.config import Configurator
+
+if __name__ == '__main__':
+ config = Configurator()
+ config.add_route('home', '/')
+ config.add_route('hello', '/howdy')
+ config.add_route('redirect', '/goto')
+ config.add_route('exception', '/problem')
+ config.scan('views')
+ app = config.make_wsgi_app()
+ server = make_server('0.0.0.0', 6543, app)
+ server.serve_forever() \ No newline at end of file
diff --git a/docs/quick_tour/views/views.py b/docs/quick_tour/views/views.py
new file mode 100644
index 000000000..9dc795f14
--- /dev/null
+++ b/docs/quick_tour/views/views.py
@@ -0,0 +1,29 @@
+from pyramid.httpexceptions import HTTPFound
+from pyramid.response import Response
+from pyramid.view import view_config
+
+
+# First view, available at http://localhost:6543/
+@view_config(route_name='home')
+def home_view(request):
+ return Response('<p>Visit <a href="/howdy?name=lisa">hello</a></p>')
+
+
+# /howdy?name=alice which links to the next view
+@view_config(route_name='hello')
+def hello_view(request):
+ name = request.params.get('name', 'No Name')
+ body = '<p>Hi %s, this <a href="/goto">redirects</a></p>'
+ return Response(body % name)
+
+
+# /goto which issues HTTP redirect to the last view
+@view_config(route_name='redirect')
+def redirect_view(request):
+ return HTTPFound(location="/problem")
+
+
+# /problem which causes an site error
+@view_config(route_name='exception')
+def exception_view(request):
+ raise Exception()
diff --git a/docs/tutorials/bfg/index.rst b/docs/tutorials/bfg/index.rst
index e68e63b0b..1abb26466 100644
--- a/docs/tutorials/bfg/index.rst
+++ b/docs/tutorials/bfg/index.rst
@@ -47,7 +47,7 @@ Here's how to convert a :mod:`repoze.bfg` application to a
.. code-block:: bash
- $ bfgenv/bin/python setup.py test
+ $ $VENV/bin/python setup.py test
``bfgenv`` above will be the virtualenv into which you've installed
:mod:`repoze.bfg` 1.3.
@@ -60,9 +60,9 @@ Here's how to convert a :mod:`repoze.bfg` application to a
.. code-block:: bash
$ cd ~
- $ virtualenv --no-site-packages pyramidenv
+ $ virtualenv pyramidenv
$ cd pyramidenv
- $ bin/easy_install pyramid
+ $ $VENV/bin/easy_install pyramid
#. Put a *copy* of your :mod:`repoze.bfg` application into a temporary
location (perhaps by checking a fresh copy of the application out
@@ -186,7 +186,7 @@ Here's how to convert a :mod:`repoze.bfg` application to a
.. code-block:: bash
$ cd /tmp/bfgapp
- $ ~/pyramidenv/bin/python setup.py test
+ $ $VENV/bin/python setup.py test
#. Fix any test failures.
diff --git a/docs/tutorials/modwsgi/index.rst b/docs/tutorials/modwsgi/index.rst
index a22f12610..ddd968927 100644
--- a/docs/tutorials/modwsgi/index.rst
+++ b/docs/tutorials/modwsgi/index.rst
@@ -46,14 +46,14 @@ specific path information for commands and files.
$ cd ~
$ mkdir modwsgi
$ cd modwsgi
- $ /usr/local/bin/virtualenv --no-site-packages env
+ $ /usr/local/bin/virtualenv env
#. Install :app:`Pyramid` into the newly created virtualenv:
.. code-block:: text
$ cd ~/modwsgi/env
- $ bin/easy_install pyramid
+ $ $VENV/bin/easy_install pyramid
#. Create and install your :app:`Pyramid` application. For the purposes of
this tutorial, we'll just be using the ``pyramid_starter`` application as
@@ -63,9 +63,9 @@ specific path information for commands and files.
.. code-block:: text
$ cd ~/modwsgi/env
- $ bin/pcreate -s starter myapp
+ $ $VENV/bin/pcreate -s starter myapp
$ cd myapp
- $ ../bin/python setup.py install
+ $ $VENV/bin/python setup.py install
#. Within the virtualenv directory (``~/modwsgi/env``), create a
script named ``pyramid.wsgi``. Give it these contents:
diff --git a/docs/tutorials/wiki/NOTE-relocatable.txt b/docs/tutorials/wiki/NOTE-relocatable.txt
index cec2639f3..e942caba8 100644
--- a/docs/tutorials/wiki/NOTE-relocatable.txt
+++ b/docs/tutorials/wiki/NOTE-relocatable.txt
@@ -1,5 +1,5 @@
We specifically use relative package references where possible so this demo
-works even if the user names their package (in the 'bin/paster create -t
+works even if the user names their package (in the '$VENV/bin/pcreate -s
zodb ...' step) something other than 'tutorial'.
Specifically:
diff --git a/docs/tutorials/wiki/authorization.rst b/docs/tutorials/wiki/authorization.rst
index 7c8ba99bf..460a852e0 100644
--- a/docs/tutorials/wiki/authorization.rst
+++ b/docs/tutorials/wiki/authorization.rst
@@ -55,8 +55,8 @@ returns one of these values:
- If the userid *does not* exist in the system, it will
return ``None``.
-For example, ``groupfinder('editor', request )`` returns ['group:editor'],
-``groupfinder('viewer', request)`` returns [], and ``groupfinder('admin', request)``
+For example, ``groupfinder('editor', request )`` returns ``['group:editor']``,
+``groupfinder('viewer', request)`` returns ``[]``, and ``groupfinder('admin', request)``
returns ``None``. We will use ``groupfinder()`` as an :term:`authentication policy`
"callback" that will provide the :term:`principal` or principals
for a user.
@@ -85,7 +85,7 @@ Add the following lines to the ``Wiki`` class:
:language: python
We import :data:`~pyramid.security.Allow`, an action that
-means that permission is allowed:, and
+means that permission is allowed, and
:data:`~pyramid.security.Everyone`, a special :term:`principal`
that is associated to all requests. Both are used in the
:term:`ACE` entries that make up the ACL.
@@ -93,8 +93,8 @@ that is associated to all requests. Both are used in the
The ACL is a list that needs to be named `__acl__` and be an
attribute of a class. We define an :term:`ACL` with two
:term:`ACE` entries: the first entry allows any user the `view`
-permission. The second entry allows the ``group:editors``
-principal the `edit` permission.
+permission, and the second entry allows the ``group:editors``
+principal the `edit` permission.
The ``Wiki`` class that contains the ACL is the :term:`resource`
constructor for the :term:`root` resource, which is
@@ -104,7 +104,7 @@ the ``context`` attribute.
It's only happenstance that we're assigning this ACL at class scope. An ACL
can be attached to an object *instance* too; this is how "row level security"
-can be achieved in :app:`Pyramid` applications. We actually only need *one*
+can be achieved in :app:`Pyramid` applications. We actually need only *one*
ACL for the entire system, however, because our security requirements are
simple, so this feature is not demonstrated. See
:ref:`assigning_acls` for more information about what an
@@ -144,18 +144,20 @@ machinery represented by this policy: it is required. The ``callback`` is the
Add permission declarations
~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Add a ``permission='edit'`` parameter to the ``@view_config``
-decorator for ``add_page()`` and ``edit_page()``, for example:
+Open ``tutorial/tutorial/views.py``. Add a ``permission='edit'`` parameter
+to the ``@view_config`` decorator for ``add_page()`` and
+``edit_page()``, for example:
.. code-block:: python
:linenos:
- :emphasize-lines: 2
+ :emphasize-lines: 3
- @view_config(route_name='add_page', renderer='templates/edit.pt',
- permission='edit')
+ @view_config(name='add_page', context='.models.Wiki',
+ renderer='templates/edit.pt',
+ permission='edit')
-(Only the highlighted line needs to be added.)
+(Only the highlighted line, along with its preceding comma,
+needs to be added.)
The result is that only users who possess the ``edit``
permission at the time of the request may invoke those two views.
@@ -167,10 +169,11 @@ decorator for ``view_wiki()`` and ``view_page()``, like this:
:linenos:
:emphasize-lines: 2
- @view_config(route_name='view_page', renderer='templates/view.pt',
+ @view_config(context='.models.Page', renderer='templates/view.pt',
permission='view')
-(Only the highlighted line needs to be added.)
+(Only the highlighted line, along with its preceding comma,
+needs to be added.)
This allows anyone to invoke these two views.
@@ -199,7 +202,8 @@ head of ``tutorial/tutorial/views.py``:
:emphasize-lines: 3,6-9,11
:language: python
-(Only the highlighted lines need to be added.)
+(Only the highlighted lines, with other necessary modifications,
+need to be added.)
:meth:`~pyramid.view.forbidden_view_config` will be used
to customize the default 403 Forbidden page.
@@ -214,16 +218,16 @@ Now add the ``login`` and ``logout`` views:
:linenos:
:language: python
-``login()`` is decorated with two decorators:
+``login()`` has two decorators:
- a ``@view_config`` decorator which associates it with the
``login`` route and makes it visible when we visit ``/login``,
- a ``@forbidden_view_config`` decorator which turns it into
- an :term:`forbidden view`. ``login()`` will be invoked
- when a users tries to execute a view callable that
- they are not allowed to. For example, if a user has not logged in
- and tries to add or edit a Wiki page, he will be shown the
- login form before being allowed to continue on.
+ a :term:`forbidden view`. ``login()`` will be invoked
+ when a user tries to execute a view callable for which they lack
+ authorization. For example, if a user has not logged in
+ and tries to add or edit a Wiki page, they will be shown the
+ login form before being allowed to continue.
The order of these two :term:`view configuration` decorators
is unimportant.
@@ -241,8 +245,8 @@ content:
.. literalinclude:: src/authorization/tutorial/templates/login.pt
:language: xml
-The above template is referred to within the login view we just
-added to ``views.py``.
+The above template is referred in the login view that we just added
+in ``views.py``.
Return a logged_in flag to the renderer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -256,7 +260,8 @@ Add the following line to the import at the head of
:emphasize-lines: 4
:language: python
-(Only the highlighted line needs to be added.)
+(Only the highlighted line and a trailing comma on the preceding
+line need to be added.)
Add a ``logged_in`` parameter to the return value of
``view_page()``, ``edit_page()`` and ``add_page()``,
@@ -271,11 +276,12 @@ like this:
edit_url = edit_url,
logged_in = authenticated_userid(request))
-(Only the highlighted line needs to be added.)
+(Only the highlighted line and a trailing comma on the preceding
+line need to be added.)
-:meth:`~pyramid.security.authenticated_userid()` will return None
-if the user is not authenticated, or some user id it the user
-is authenticated.
+:meth:`~pyramid.security.authenticated_userid()` will return ``None``
+if the user is not authenticated, or a user id if the user is
+authenticated.
Add a "Logout" link when logged in
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/tutorials/wiki/basiclayout.rst b/docs/tutorials/wiki/basiclayout.rst
index f9d4775ad..25ac9aabd 100644
--- a/docs/tutorials/wiki/basiclayout.rst
+++ b/docs/tutorials/wiki/basiclayout.rst
@@ -36,7 +36,7 @@ point happens to be the ``main`` function within the file named
#. *Line 15*. Register a "static view" which answers requests whose URL path
start with ``/static`` using the
- :meth:`pyramid.config.Configurator.add_static_view method`. This
+ :meth:`pyramid.config.Configurator.add_static_view` method. This
statement registers a view that will serve up static assets, such as CSS
and image files, for us, in this case, at
``http://localhost:6543/static/`` and below. The first argument is the
diff --git a/docs/tutorials/wiki/definingviews.rst b/docs/tutorials/wiki/definingviews.rst
index 4dedf4320..23ee142af 100644
--- a/docs/tutorials/wiki/definingviews.rst
+++ b/docs/tutorials/wiki/definingviews.rst
@@ -317,7 +317,7 @@ Our templates name a single static asset named ``pylons.css``. We don't need
to create this file within our package's ``static`` directory because it was
provided at the time we created the project. This file is a little too long to
replicate within the body of this guide, however it is available `online
-<http://github.com/Pylons/pyramid/blob/master/docs/tutorials/wiki/src/views/tutorial/static/pylons.css>`_.
+<https://github.com/Pylons/pyramid/blob/master/docs/tutorials/wiki/src/views/tutorial/static/pylons.css>`_.
This CSS file will be accessed via
e.g. ``/static/pylons.css`` by virtue of the call to
diff --git a/docs/tutorials/wiki/distributing.rst b/docs/tutorials/wiki/distributing.rst
index ed0af222f..9c63cf0bd 100644
--- a/docs/tutorials/wiki/distributing.rst
+++ b/docs/tutorials/wiki/distributing.rst
@@ -12,13 +12,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py sdist
+ $ $VENV/bin/python setup.py sdist
On Windows:
.. code-block:: text
- c:\pyramidtut> ..\Scripts\python setup.py sdist
+ c:\pyramidtut> %VENV%\Scripts\python setup.py sdist
The output of such a command will be something like:
diff --git a/docs/tutorials/wiki/installation.rst b/docs/tutorials/wiki/installation.rst
index b545cdba0..b51254b92 100644
--- a/docs/tutorials/wiki/installation.rst
+++ b/docs/tutorials/wiki/installation.rst
@@ -22,7 +22,7 @@ Preparation, UNIX
.. code-block:: text
- $ bin/easy_install docutils pyramid_tm pyramid_zodbconn \
+ $ $VENV/bin/easy_install docutils pyramid_tm pyramid_zodbconn \
pyramid_debugtoolbar nose coverage
Preparation, Windows
@@ -39,7 +39,7 @@ Preparation, Windows
.. code-block:: text
- c:\pyramidtut> Scripts\easy_install docutils pyramid_tm \
+ c:\pyramidtut> %VENV%\Scripts\easy_install docutils pyramid_tm \
pyramid_zodbconn pyramid_debugtoolbar nose coverage
.. _making_a_project:
@@ -59,13 +59,13 @@ On UNIX:
.. code-block:: text
- $ bin/pcreate -s zodb tutorial
+ $ $VENV/bin/pcreate -s zodb tutorial
On Windows:
.. code-block:: text
- c:\pyramidtut> Scripts\pcreate -s zodb tutorial
+ c:\pyramidtut> %VENV%\Scripts\pcreate -s zodb tutorial
.. note:: You don't have to call it `tutorial` -- the code uses
relative paths for imports and finding templates and static
@@ -91,14 +91,14 @@ On UNIX:
.. code-block:: text
$ cd tutorial
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
On Windows:
.. code-block:: text
C:\pyramidtut> cd tutorial
- C:\pyramidtut\tutorial> ..\Scripts\python setup.py develop
+ C:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
.. _running_tests:
@@ -112,13 +112,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py test -q
+ $ $VENV/bin/python setup.py test -q
On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py test -q
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py test -q
Expose Test Coverage Information
================================
@@ -133,13 +133,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/nosetests --cover-package=tutorial --cover-erase --with-coverage
+ $ $VENV/bin/nosetests --cover-package=tutorial --cover-erase --with-coverage
On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\nosetests --cover-package=tutorial ^
+ c:\pyramidtut\tutorial> %VENV%\Scripts\nosetests --cover-package=tutorial ^
--cover-erase --with-coverage
Looks like the code in the ``zodb`` scaffold for ZODB projects is
@@ -157,13 +157,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/pserve development.ini --reload
+ $ $VENV/bin/pserve development.ini --reload
On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\pserve development.ini --reload
+ c:\pyramidtut\tutorial> %VENV%\Scripts\pserve development.ini --reload
.. note::
diff --git a/docs/tutorials/wiki/src/authorization/setup.py b/docs/tutorials/wiki/src/authorization/setup.py
index 3164fd724..5d87fedbf 100644
--- a/docs/tutorials/wiki/src/authorization/setup.py
+++ b/docs/tutorials/wiki/src/authorization/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt
index 0d0738f7f..c3a0acf6b 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt
+++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt
@@ -54,9 +54,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer"
- >&copy; Copyright 2008-2011, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt
index 2c7235761..3612dccde 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt
+++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/login.pt
@@ -50,9 +50,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer"
- >&copy; Copyright 2008-2011, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt
index 84824f605..13b41f823 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/mytemplate.pt
@@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>The Pyramid Web Application Development Framework</title>
+ <title>The Pyramid Web Framework</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
@@ -24,7 +24,7 @@
<div class="middle align-center">
<p class="app-welcome">
Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
- the Pyramid web application development framework.
+ the Pyramid Web Framework.
</p>
</div>
</div>
@@ -69,8 +69,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer">&copy; Copyright 2008-2012, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt
index 9dd6540cf..90e20764d 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt
+++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt
@@ -57,9 +57,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer"
- >&copy; Copyright 2008-2011, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki/src/basiclayout/setup.py b/docs/tutorials/wiki/src/basiclayout/setup.py
index 4998be902..75ba02611 100644
--- a/docs/tutorials/wiki/src/basiclayout/setup.py
+++ b/docs/tutorials/wiki/src/basiclayout/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt
index 84824f605..13b41f823 100644
--- a/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki/src/basiclayout/tutorial/templates/mytemplate.pt
@@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>The Pyramid Web Application Development Framework</title>
+ <title>The Pyramid Web Framework</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
@@ -24,7 +24,7 @@
<div class="middle align-center">
<p class="app-welcome">
Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
- the Pyramid web application development framework.
+ the Pyramid Web Framework.
</p>
</div>
</div>
@@ -69,8 +69,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer">&copy; Copyright 2008-2012, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki/src/models/setup.py b/docs/tutorials/wiki/src/models/setup.py
index 4998be902..75ba02611 100644
--- a/docs/tutorials/wiki/src/models/setup.py
+++ b/docs/tutorials/wiki/src/models/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt
index 84824f605..13b41f823 100644
--- a/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki/src/models/tutorial/templates/mytemplate.pt
@@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>The Pyramid Web Application Development Framework</title>
+ <title>The Pyramid Web Framework</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
@@ -24,7 +24,7 @@
<div class="middle align-center">
<p class="app-welcome">
Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
- the Pyramid web application development framework.
+ the Pyramid Web Framework.
</p>
</div>
</div>
@@ -69,8 +69,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer">&copy; Copyright 2008-2012, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki/src/models/tutorial/tests.py b/docs/tutorials/wiki/src/models/tutorial/tests.py
index 9fd13a18d..0c5f99575 100644
--- a/docs/tutorials/wiki/src/models/tutorial/tests.py
+++ b/docs/tutorials/wiki/src/models/tutorial/tests.py
@@ -45,7 +45,7 @@ class AppmakerTests(unittest.TestCase):
app_root = object()
root = {'app_root': app_root}
self._callFUT(root)
- self.failUnless(root['app_root'] is app_root)
+ self.assertTrue(root['app_root'] is app_root)
class ViewTests(unittest.TestCase):
def setUp(self):
diff --git a/docs/tutorials/wiki/src/tests/setup.py b/docs/tutorials/wiki/src/tests/setup.py
index 702d34c4c..5ff7b545c 100644
--- a/docs/tutorials/wiki/src/tests/setup.py
+++ b/docs/tutorials/wiki/src/tests/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt
index 0d0738f7f..c3a0acf6b 100644
--- a/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt
@@ -54,9 +54,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer"
- >&copy; Copyright 2008-2011, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/login.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/login.pt
index 2c7235761..3612dccde 100644
--- a/docs/tutorials/wiki/src/tests/tutorial/templates/login.pt
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/login.pt
@@ -50,9 +50,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer"
- >&copy; Copyright 2008-2011, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt
index 84824f605..13b41f823 100644
--- a/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt
@@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>The Pyramid Web Application Development Framework</title>
+ <title>The Pyramid Web Framework</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
@@ -24,7 +24,7 @@
<div class="middle align-center">
<p class="app-welcome">
Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
- the Pyramid web application development framework.
+ the Pyramid Web Framework.
</p>
</div>
</div>
@@ -69,8 +69,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer">&copy; Copyright 2008-2012, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt
index 9dd6540cf..90e20764d 100644
--- a/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt
@@ -57,9 +57,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer"
- >&copy; Copyright 2008-2011, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki/src/views/setup.py b/docs/tutorials/wiki/src/views/setup.py
index 3164fd724..5d87fedbf 100644
--- a/docs/tutorials/wiki/src/views/setup.py
+++ b/docs/tutorials/wiki/src/views/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt
index 84824f605..50102aa20 100644
--- a/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki/src/views/tutorial/templates/mytemplate.pt
@@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>The Pyramid Web Application Development Framework</title>
+ <title>The Pyramid Web Framework</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
@@ -24,7 +24,7 @@
<div class="middle align-center">
<p class="app-welcome">
Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
- the Pyramid web application development framework.
+ the Pyramid Web Framework.
</p>
</div>
</div>
diff --git a/docs/tutorials/wiki/tests.rst b/docs/tutorials/wiki/tests.rst
index 49bc780e8..e40dc286b 100644
--- a/docs/tutorials/wiki/tests.rst
+++ b/docs/tutorials/wiki/tests.rst
@@ -59,7 +59,7 @@ Change the ``requires`` list in ``setup.py`` to include ``WebTest``.
.. literalinclude:: src/tests/setup.py
:linenos:
:language: python
- :lines: 9-19
+ :lines: 11-21
:emphasize-lines: 10
After we've added a dependency on WebTest in ``setup.py``, we need to rerun
@@ -71,13 +71,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py develop
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
Once that command has completed successfully, we can run the tests
themselves:
@@ -86,13 +86,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py test -q
+ $ $VENV/bin/python setup.py test -q
On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py test -q
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py test -q
The expected result looks something like:
diff --git a/docs/tutorials/wiki2/authorization.rst b/docs/tutorials/wiki2/authorization.rst
index 5ede26920..01c301e74 100644
--- a/docs/tutorials/wiki2/authorization.rst
+++ b/docs/tutorials/wiki2/authorization.rst
@@ -381,21 +381,21 @@ We can finally examine our application in a browser (See
:ref:`wiki2-start-the-application`). Launch a browser and visit
each of the following URLs, check that the result is as expected:
-- ``http://localhost:6543/`` invokes the
+- http://localhost:6543/ invokes the
``view_wiki`` view. This always redirects to the ``view_page`` view
of the FrontPage page object. It is executable by any user.
-- ``http://localhost:6543/FrontPage`` invokes
+- http://localhost:6543/FrontPage invokes
the ``view_page`` view of the FrontPage page object.
-- ``http://localhost:6543/FrontPage/edit_page``
+- http://localhost:6543/FrontPage/edit_page
invokes the edit view for the FrontPage object. It is executable by
only the ``editor`` user. If a different user (or the anonymous
user) invokes it, a login form will be displayed. Supplying the
credentials with the username ``editor``, password ``editor`` will
display the edit page form.
-- ``http://localhost:6543/add_page/SomePageName``
+- http://localhost:6543/add_page/SomePageName
invokes the add view for a page. It is executable by only
the ``editor`` user. If a different user (or the anonymous user)
invokes it, a login form will be displayed. Supplying the
diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst
index 68be4ee7c..0193afab4 100644
--- a/docs/tutorials/wiki2/basiclayout.rst
+++ b/docs/tutorials/wiki2/basiclayout.rst
@@ -43,9 +43,9 @@ above is executed. It accepts some settings and returns a :term:`WSGI`
application. (See :ref:`startup_chapter` for more about ``pserve``.)
The main function first creates a :term:`SQLAlchemy` database engine using
-``engine_from_config`` from the ``sqlalchemy.`` prefixed settings in the
-``development.ini`` file's ``[app:main]`` section. This will be a URI
-(something like ``sqlite://``):
+:func:`sqlalchemy.engine_from_config` from the ``sqlalchemy.`` prefixed
+settings in the ``development.ini`` file's ``[app:main]`` section.
+This will be a URI (something like ``sqlite://``):
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:lines: 13
@@ -132,11 +132,10 @@ Finally, ``main`` is finished configuring things, so it uses the
View Declarations via ``views.py``
----------------------------------
-Mapping a :term:`route` to code that will be executed when a match for
-the route's pattern occurs is done by registering a :term:`view
-configuration`. Our application uses the
-:meth:`pyramid.view.view_config` decorator to map view callables to
-each route, thereby mapping URL patterns to code.
+The main function of a web framework is mapping each URL pattern to code (a
+:term:`view callable`) that is executed when the requested URL matches the
+corresponding :term:`route`. Our application uses the
+:meth:`pyramid.view.view_config` decorator to perform this mapping.
Open ``tutorial/tutorial/views.py``. It should already contain the following:
@@ -226,13 +225,12 @@ To give a simple example of a model class, we define one named ``MyModel``:
:linenos:
:language: py
-Our example model has an ``__init__`` method that takes a two arguments
+Our example model has an ``__init__`` method that takes two arguments
(``name``, and ``value``). It stores these values as ``self.name`` and
-``self.value``
-within the ``__init__`` function itself. The ``MyModel`` class also has a
-``__tablename__`` attribute. This informs SQLAlchemy which table to use to
-store the data representing instances of this class.
-
-That's about all there is to it to models, views, and initialization code in
-our stock application.
+``self.value`` on the instance created by the ``__init__`` function itself.
+The ``MyModel`` class also has a ``__tablename__`` attribute. This informs
+SQLAlchemy which table to use to store the data representing instances of this
+class.
+That's about all there is to it regarding models, views, and initialization
+code in our stock application.
diff --git a/docs/tutorials/wiki2/definingmodels.rst b/docs/tutorials/wiki2/definingmodels.rst
index bd1cb00d7..60427a911 100644
--- a/docs/tutorials/wiki2/definingmodels.rst
+++ b/docs/tutorials/wiki2/definingmodels.rst
@@ -34,7 +34,7 @@ sample and we're not going to use it.
Then, we added a ``Page`` class. Because this is a SQLAlchemy application,
this class inherits from an instance of
-:class:`sqlalchemy.ext.declarative.declarative_base`.
+:func:`sqlalchemy.ext.declarative.declarative_base`.
.. literalinclude:: src/models/tutorial/models.py
:pyobject: Page
@@ -45,9 +45,10 @@ As you can see, our ``Page`` class has a class level attribute
``__tablename__`` which equals the string ``'pages'``. This means that
SQLAlchemy will store our wiki data in a SQL table named ``pages``. Our
``Page`` class will also have class-level attributes named ``id``, ``name`` and
-``data`` (all instances of :class:`sqlalchemy.Column`). These will map to
-columns in the ``pages`` table. The ``id`` attribute will be the primary key
-in the table. The ``name`` attribute will be a text attribute, each value of
+``data`` (all instances of :class:`sqlalchemy.schema.Column`).
+These will map to columns in the ``pages`` table.
+The ``id`` attribute will be the primary key in the table.
+The ``name`` attribute will be a text attribute, each value of
which needs to be unique within the column. The ``data`` attribute is a text
attribute that will hold the body of each page.
@@ -77,8 +78,6 @@ following:
Installing the Project and re-initializing the Database
-------------------------------------------------------
-Redo the steps in :ref:`installing_project_in_dev_mode`.
-
Because our model has changed, in order to reinitialize the database, we need
to rerun the ``initialize_tutorial_db`` command to pick up the changes you've made
to both the models.py file and to the initializedb.py file.
diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst
index e83a88198..a1e2313f3 100644
--- a/docs/tutorials/wiki2/definingviews.rst
+++ b/docs/tutorials/wiki2/definingviews.rst
@@ -6,16 +6,13 @@ A :term:`view callable` in a :app:`Pyramid` application is typically a simple
Python function that accepts a single parameter named :term:`request`. A
view callable is assumed to return a :term:`response` object.
-The request object passed to every view that is called as the result of a
-route match has an attribute named ``matchdict`` that contains the elements
-placed into the URL by the ``pattern`` of a ``route`` statement. For
-instance, if a call to :meth:`pyramid.config.Configurator.add_route` in
-``__init__.py`` had the pattern ``{one}/{two}``, and the URL at
-``http://example.com/foo/bar`` was invoked, matching this pattern, the
-``matchdict`` dictionary attached to the request passed to the view would
-have a ``'one'`` key with the value ``'foo'`` and a ``'two'`` key with the
-value ``'bar'``.
-
+The request object has a dictionary as an attribute named ``matchdict``. A
+``matchdict`` maps the placeholders in the matching URL ``pattern`` to the
+substrings of the path in the :term:`request` URL. For instance, if a call to
+:meth:`pyramid.config.Configurator.add_route` has the pattern ``/{one}/{two}``,
+and a user visits ``http://example.com/foo/bar``, our pattern would be matched
+against ``/foo/bar`` and the ``matchdict`` would look like: ``{'one':'foo',
+'two':'bar'}``
Declaring Dependencies in Our ``setup.py`` File
===============================================
@@ -33,7 +30,7 @@ Open ``tutorial/setup.py`` and edit it to look like the following:
.. literalinclude:: src/views/setup.py
:linenos:
:language: python
- :emphasize-lines: 17
+ :emphasize-lines: 19
(Only the highlighted line needs to be added.)
@@ -52,14 +49,14 @@ On UNIX:
.. code-block:: text
$ cd tutorial
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
On Windows:
.. code-block:: text
c:\pyramidtut> cd tutorial
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py develop
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
Success executing this command will end with a line to the console something
like::
@@ -126,7 +123,7 @@ The ``view_page`` view function
-------------------------------
``view_page()`` is used to display a single page of our
-wiki. It renders the :term:`ReStructuredText` body of a page (stored as
+wiki. It renders the :term:`reStructuredText` body of a page (stored as
the ``data`` attribute of a ``Page`` model object) as HTML. Then it substitutes an
HTML anchor for each *WikiWord* reference in the rendered HTML using a
compiled regular expression.
@@ -148,14 +145,13 @@ As a result, the ``content`` variable is now a fully formed bit of HTML
containing various view and add links for WikiWords based on the content of
our current page object.
-We then generate an edit URL (because it's easier to do here than in the
-template), and we return a dictionary with a number of arguments. The fact
-that ``view_page()`` returns a dictionary (as opposed to a :term:`response`
-object) is a cue to :app:`Pyramid` that it should try to use a :term:`renderer`
-associated with the view configuration to render a template. In our case,
-the template which will be rendered will be the ``templates/view.pt``
-template, as indicated in the ``@view_config`` decorator that is applied to
-``view_page()``.
+We then generate an edit URL because it's easier to do here than in the
+template, and we return a dictionary with a number of arguments. The fact that
+``view_page()`` returns a dictionary (as opposed to a :term:`response` object)
+is a cue to :app:`Pyramid` that it should try to use a :term:`renderer`
+associated with the view configuration to render a response. In our case, the
+renderer used will be the ``templates/view.pt`` template, as indicated in the
+``@view_config`` decorator that is applied to ``view_page()``.
The ``add_page`` view function
------------------------------
@@ -287,7 +283,7 @@ Our templates name a single static asset named ``pylons.css``. We don't need
to create this file within our package's ``static`` directory because it was
provided at the time we created the project. This file is a little too long
to replicate within the body of this guide, however it is available `online
-<http://github.com/Pylons/pyramid/blob/master/docs/tutorials/wiki2/src/views/tutorial/static/pylons.css>`_.
+<https://github.com/Pylons/pyramid/blob/master/docs/tutorials/wiki2/src/views/tutorial/static/pylons.css>`_.
This CSS file will be accessed via
e.g. ``http://localhost:6543/static/pylons.css`` by virtue of the call to
@@ -350,20 +346,20 @@ We can finally examine our application in a browser (See
:ref:`wiki2-start-the-application`). Launch a browser and visit
each of the following URLs, check that the result is as expected:
-- ``http://localhost:6543`` in a browser invokes the
+- http://localhost:6543 in a browser invokes the
``view_wiki`` view. This always redirects to the ``view_page`` view
of the FrontPage page object.
-- ``http://localhost:6543/FrontPage`` in a browser invokes
+- http://localhost:6543/FrontPage in a browser invokes
the ``view_page`` view of the front page object.
-- ``http://localhost:6543/FrontPage/edit_page`` in a browser
+- http://localhost:6543/FrontPage/edit_page in a browser
invokes the edit view for the front page object.
-- ``http://localhost:6543/add_page/SomePageName`` in a
+- http://localhost:6543/add_page/SomePageName in a
browser invokes the add view for a page.
-- To generate an error, visit ``http://localhost:6543/foobars/edit_page`` which
+- To generate an error, visit http://localhost:6543/foobars/edit_page which
will generate a ``NoResultFound: No row was found for one()`` error.
You'll see an interactive traceback facility provided
by :term:`pyramid_debugtoolbar`.
diff --git a/docs/tutorials/wiki2/design.rst b/docs/tutorials/wiki2/design.rst
index c56d7fecf..df2c83398 100644
--- a/docs/tutorials/wiki2/design.rst
+++ b/docs/tutorials/wiki2/design.rst
@@ -100,7 +100,7 @@ listed in the following table:
| | with existing | | | |
| | content. | | | |
| | | | | |
-| | If the form was | | | |
+| | If the form is | | | |
| | submitted, redirect | | | |
| | to /PageName | | | |
+----------------------+-----------------------+-------------+------------+------------+
@@ -110,15 +110,15 @@ listed in the following table:
| | the edit form | | | |
| | without content. | | | |
| | | | | |
-| | If the form was | | | |
+| | If the form is | | | |
| | submitted, | | | |
| | redirect to | | | |
| | /PageName | | | |
+----------------------+-----------------------+-------------+------------+------------+
| /login | Display login form, | login | login.pt | |
-| | Forbidden [3]_ | | | |
+| | Forbidden [3]_ | | | |
| | | | | |
-| | If the form was | | | |
+| | If the form is | | | |
| | submitted, | | | |
| | authenticate. | | | |
| | | | | |
diff --git a/docs/tutorials/wiki2/distributing.rst b/docs/tutorials/wiki2/distributing.rst
index 96293603c..3b048a141 100644
--- a/docs/tutorials/wiki2/distributing.rst
+++ b/docs/tutorials/wiki2/distributing.rst
@@ -12,13 +12,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py sdist
+ $ $VENV/bin/python setup.py sdist
On Windows:
.. code-block:: text
- c:\pyramidtut> ..\Scripts\python setup.py sdist
+ c:\pyramidtut> %VENV%\Scripts\python setup.py sdist
The output of such a command will be something like:
diff --git a/docs/tutorials/wiki2/installation.rst b/docs/tutorials/wiki2/installation.rst
index 9fa01d513..e21bf7108 100644
--- a/docs/tutorials/wiki2/installation.rst
+++ b/docs/tutorials/wiki2/installation.rst
@@ -2,63 +2,146 @@
Installation
============
-Preparation
-===========
+Before You Begin
+================
+
+This tutorial assumes that you have already followed the steps in
+:ref:`installing_chapter`, thereby satisfying the following
+requirements.
+
+* Python interpreter is installed on your operating system
+* :term:`setuptools` or :term:`distribute` is installed
+* :term:`virtualenv` is installed
+
+Create and Use a Virtual Python Environment
+-------------------------------------------
+
+Next let's create a `virtualenv` workspace for our project. We will
+use the `VENV` environment variable instead of absolute path of the
+virtual environment.
+
+On UNIX
+^^^^^^^
+
+.. code-block:: text
+
+ $ export VENV=~/pyramidtut
+ $ virtualenv $VENV
+ New python executable in /home/foo/env/bin/python
+ Installing setuptools.............done.
+
+On Windows
+^^^^^^^^^^
-Follow the steps in :ref:`installing_chapter`, but name the virtualenv
-directory ``pyramidtut``.
+Set the `VENV` environment variable.
-Preparation, UNIX
------------------
+.. code-block:: text
+
+ c:\> set VENV=c:\pyramidtut
+
+Versions of Python use different paths, so you will need to adjust the
+path to the command for your Python version.
+
+Python 2.7:
+
+.. code-block:: text
-#. Install SQLite3 and its development packages if you don't already
- have them installed. Usually this is via your system's package
- manager. On a Debian system, this would be:
+ c:\> c:\Python27\Scripts\virtualenv %VENV%
- .. code-block:: text
+Python 3.2:
- $ sudo apt-get install libsqlite3-dev
+.. code-block:: text
-#. Switch to the ``pyramidtut`` directory:
+ c:\> c:\Python32\Scripts\virtualenv %VENV%
- .. code-block:: text
+Install Pyramid Into the Virtual Python Environment
+---------------------------------------------------
- $ cd pyramidtut
+On UNIX
+^^^^^^^
+.. code-block:: text
-Preparation, Windows
---------------------
+ $ $VENV/bin/easy_install pyramid
-#. Switch to the ``pyramidtut`` directory:
+On Windows
+^^^^^^^^^^
+
+.. code-block:: text
- .. code-block:: text
+ c:\env> %VENV%\Scripts\easy_install pyramid
- c:\> cd pyramidtut
+Install SQLite3 and Its Development Packages
+--------------------------------------------
+
+If you used a package manager to install your Python or if you compiled
+your Python from source, then you must install SQLite3 and its
+development packages. If you downloaded your Python as an installer
+from python.org, then you already have it installed and can proceed to
+the next section :ref:`sql_making_a_project`..
+
+If you need to install the SQLite3 packages, then, for example, using
+the Debian system and apt-get, the command would be the following:
+
+.. code-block:: text
+
+ $ sudo apt-get install libsqlite3-dev
+
+Change Directory to Your Virtual Python Environment
+---------------------------------------------------
+
+Change directory to the ``pyramidtut`` directory.
+
+On UNIX
+^^^^^^^
+
+.. code-block:: text
+
+ $ cd pyramidtut
+
+On Windows
+^^^^^^^^^^
+
+.. code-block:: text
+
+ c:\> cd pyramidtut
.. _sql_making_a_project:
Making a Project
================
-Your next step is to create a project. For this tutorial, we will use the
-:term:`scaffold` named ``alchemy``, which generates an application
-that uses :term:`SQLAlchemy` and :term:`URL dispatch`. :app:`Pyramid`
-supplies a variety of scaffolds to generate sample projects.
+Your next step is to create a project. For this tutorial we will use
+the :term:`scaffold` named ``alchemy`` which generates an application
+that uses :term:`SQLAlchemy` and :term:`URL dispatch`.
+
+:app:`Pyramid` supplies a variety of scaffolds to generate sample
+projects. We will use `pcreate`—a script that comes with Pyramid to
+quickly and easily generate scaffolds usually with a single command—to
+create the scaffold for our project.
+
+By passing in `alchemy` into the `pcreate` command, the script creates
+the files needed to use SQLAlchemy. By passing in our application name
+`tutorial`, the script inserts that application name into all the
+required files. For example, `pcreate` creates the
+``initialize_tutorial_db`` in the ``pyramidtut/bin`` directory.
The below instructions assume your current working directory is the
"virtualenv" named "pyramidtut".
-On UNIX:
+On UNIX
+-------
.. code-block:: text
- $ bin/pcreate -s alchemy tutorial
+ $ $VENV/bin/pcreate -s alchemy tutorial
-On Windows:
+On Windows
+----------
.. code-block:: text
- c:\pyramidtut> Scripts\pcreate -s alchemy tutorial
+ c:\pyramidtut> %VENV%\pcreate -s alchemy tutorial
.. note:: If you are using Windows, the ``alchemy``
scaffold may not deal gracefully with installation into a
@@ -66,11 +149,10 @@ On Windows:
startup problems, try putting both the virtualenv and the project
into directories that do not contain spaces in their paths.
-
.. _installing_project_in_dev_mode:
-Installing the Project in "Development Mode"
-============================================
+Installing the Project in Development Mode
+==========================================
In order to do development on the project easily, you must "register"
the project as a development egg in your workspace using the
@@ -78,22 +160,25 @@ the project as a development egg in your workspace using the
directory you created in :ref:`sql_making_a_project`, and run the
``setup.py develop`` command using the virtualenv Python interpreter.
-On UNIX:
+On UNIX
+-------
.. code-block:: text
$ cd tutorial
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
-On Windows:
+On Windows
+----------
.. code-block:: text
c:\pyramidtut> cd tutorial
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py develop
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
-Success executing this command will end with a line to the console something
-like::
+The console will show `setup.py` checking for packages and installing
+missing packages. Success executing this command will show a line like
+the following::
Finished processing dependencies for tutorial==0.0
@@ -105,17 +190,19 @@ Running the Tests
After you've installed the project in development mode, you may run
the tests for the project.
-On UNIX:
+On UNIX
+-------
.. code-block:: text
- $ ../bin/python setup.py test -q
+ $ $VENV/bin/python setup.py test -q
-On Windows:
+On Windows
+----------
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py test -q
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py test -q
For a successful test run, you should see output that ends like this::
@@ -137,32 +224,36 @@ tests.
To get this functionality working, we'll need to install the ``nose`` and
``coverage`` packages into our ``virtualenv``:
-On UNIX:
+On UNIX
+-------
.. code-block:: text
- $ ../bin/easy_install nose coverage
+ $ $VENV/bin/easy_install nose coverage
-On Windows:
+On Windows
+----------
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\easy_install nose coverage
+ c:\pyramidtut\tutorial> %VENV%\Scripts\easy_install nose coverage
Once ``nose`` and ``coverage`` are installed, we can actually run the
coverage tests.
-On UNIX:
+On UNIX
+-------
.. code-block:: text
- $ ../bin/nosetests --cover-package=tutorial --cover-erase --with-coverage
+ $ $VENV/bin/nosetests --cover-package=tutorial --cover-erase --with-coverage
-On Windows:
+On Windows
+----------
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\nosetests --cover-package=tutorial \
+ c:\pyramidtut\tutorial> %VENV%\Scripts\nosetests --cover-package=tutorial \
--cover-erase --with-coverage
If successful, you will see output something like this::
@@ -196,17 +287,19 @@ script` to initialize our database.
Type the following command, make sure you are still in the ``tutorial``
directory (the directory with a ``development.ini`` in it):
-On UNIX:
+On UNIX
+-------
.. code-block:: text
- $ ../bin/initialize_tutorial_db development.ini
+ $ $VENV/bin/initialize_tutorial_db development.ini
-On Windows:
+On Windows
+----------
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\initialize_tutorial_db development.ini
+ c:\pyramidtut\tutorial> %VENV%\Scripts\initialize_tutorial_db development.ini
The output to your console should be something like this::
@@ -244,17 +337,19 @@ Starting the Application
Start the application.
-On UNIX:
+On UNIX
+-------
.. code-block:: text
- $ ../bin/pserve development.ini --reload
+ $ $VENV/bin/pserve development.ini --reload
-On Windows:
+On Windows
+----------
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\pserve development.ini --reload
+ c:\pyramidtut\tutorial> %VENV%\Scripts\pserve development.ini --reload
If successful, you will see something like this on your console::
@@ -292,4 +387,3 @@ the following assumptions:
mechanism to map URLs to code (:term:`traversal`). However, for the
purposes of this tutorial, we'll only be using url dispatch and
SQLAlchemy.
-
diff --git a/docs/tutorials/wiki2/src/authorization/README.txt b/docs/tutorials/wiki2/src/authorization/README.txt
index 141851285..68f430110 100644
--- a/docs/tutorials/wiki2/src/authorization/README.txt
+++ b/docs/tutorials/wiki2/src/authorization/README.txt
@@ -6,9 +6,9 @@ Getting Started
- cd <directory containing this file>
-- $venv/bin/python setup.py develop
+- $VENV/bin/python setup.py develop
-- $venv/bin/initialize_tutorial_db development.ini
+- $VENV/bin/initialize_tutorial_db development.ini
-- $venv/bin/pserve development.ini
+- $VENV/bin/pserve development.ini
diff --git a/docs/tutorials/wiki2/src/authorization/setup.py b/docs/tutorials/wiki2/src/authorization/setup.py
index 36668dd33..e8fa8f396 100644
--- a/docs/tutorials/wiki2/src/authorization/setup.py
+++ b/docs/tutorials/wiki2/src/authorization/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt
index 14b88d16a..cf3da2073 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/templates/mytemplate.pt
@@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>The Pyramid Web Application Development Framework</title>
+ <title>The Pyramid Web Framework</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
@@ -24,7 +24,7 @@
<div class="middle align-center">
<p class="app-welcome">
Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
- the Pyramid web application development framework.
+ the Pyramid Web Framework.
</p>
</div>
</div>
diff --git a/docs/tutorials/wiki2/src/basiclayout/README.txt b/docs/tutorials/wiki2/src/basiclayout/README.txt
index 141851285..68f430110 100644
--- a/docs/tutorials/wiki2/src/basiclayout/README.txt
+++ b/docs/tutorials/wiki2/src/basiclayout/README.txt
@@ -6,9 +6,9 @@ Getting Started
- cd <directory containing this file>
-- $venv/bin/python setup.py develop
+- $VENV/bin/python setup.py develop
-- $venv/bin/initialize_tutorial_db development.ini
+- $VENV/bin/initialize_tutorial_db development.ini
-- $venv/bin/pserve development.ini
+- $VENV/bin/pserve development.ini
diff --git a/docs/tutorials/wiki2/src/basiclayout/setup.py b/docs/tutorials/wiki2/src/basiclayout/setup.py
index a09bf756a..e7d318128 100644
--- a/docs/tutorials/wiki2/src/basiclayout/setup.py
+++ b/docs/tutorials/wiki2/src/basiclayout/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt
index 15ea6614f..ca4e0af26 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/templates/mytemplate.pt
@@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>The Pyramid Web Application Development Framework</title>
+ <title>The Pyramid Web Framework</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
@@ -24,7 +24,7 @@
<div class="middle align-center">
<p class="app-welcome">
Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
- the Pyramid web application development framework.
+ the Pyramid Web Framework.
</p>
</div>
</div>
@@ -69,8 +69,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer">&copy; Copyright 2008-2012, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki2/src/models/README.txt b/docs/tutorials/wiki2/src/models/README.txt
index 141851285..68f430110 100644
--- a/docs/tutorials/wiki2/src/models/README.txt
+++ b/docs/tutorials/wiki2/src/models/README.txt
@@ -6,9 +6,9 @@ Getting Started
- cd <directory containing this file>
-- $venv/bin/python setup.py develop
+- $VENV/bin/python setup.py develop
-- $venv/bin/initialize_tutorial_db development.ini
+- $VENV/bin/initialize_tutorial_db development.ini
-- $venv/bin/pserve development.ini
+- $VENV/bin/pserve development.ini
diff --git a/docs/tutorials/wiki2/src/models/setup.py b/docs/tutorials/wiki2/src/models/setup.py
index a09bf756a..e7d318128 100644
--- a/docs/tutorials/wiki2/src/models/setup.py
+++ b/docs/tutorials/wiki2/src/models/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt
index fbfa9870b..ca4e0af26 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki2/src/models/tutorial/templates/mytemplate.pt
@@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>The Pyramid Web Application Development Framework</title>
+ <title>The Pyramid Web Framework</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
@@ -24,7 +24,7 @@
<div class="middle align-center">
<p class="app-welcome">
Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
- the Pyramid web application development framework.
+ the Pyramid Web Framework.
</p>
</div>
</div>
@@ -69,8 +69,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer">&copy; Copyright 2008-2011, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki2/src/tests/README.txt b/docs/tutorials/wiki2/src/tests/README.txt
index 141851285..68f430110 100644
--- a/docs/tutorials/wiki2/src/tests/README.txt
+++ b/docs/tutorials/wiki2/src/tests/README.txt
@@ -6,9 +6,9 @@ Getting Started
- cd <directory containing this file>
-- $venv/bin/python setup.py develop
+- $VENV/bin/python setup.py develop
-- $venv/bin/initialize_tutorial_db development.ini
+- $VENV/bin/initialize_tutorial_db development.ini
-- $venv/bin/pserve development.ini
+- $VENV/bin/pserve development.ini
diff --git a/docs/tutorials/wiki2/src/tests/setup.py b/docs/tutorials/wiki2/src/tests/setup.py
index 3c2961fcc..c3da36b39 100644
--- a/docs/tutorials/wiki2/src/tests/setup.py
+++ b/docs/tutorials/wiki2/src/tests/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/templates/edit.pt b/docs/tutorials/wiki2/src/tests/tutorial/templates/edit.pt
index ca28b9fa5..2004273fe 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/templates/edit.pt
+++ b/docs/tutorials/wiki2/src/tests/tutorial/templates/edit.pt
@@ -54,9 +54,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer"
- >&copy; Copyright 2008-2011, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/templates/login.pt b/docs/tutorials/wiki2/src/tests/tutorial/templates/login.pt
index 64e592ea9..5f8e9b98c 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/templates/login.pt
+++ b/docs/tutorials/wiki2/src/tests/tutorial/templates/login.pt
@@ -50,9 +50,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer"
- >&copy; Copyright 2008-2011, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/tests/tutorial/templates/mytemplate.pt
index 14b88d16a..6c1ca924a 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki2/src/tests/tutorial/templates/mytemplate.pt
@@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>The Pyramid Web Application Development Framework</title>
+ <title>The Pyramid Web Framework</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
@@ -24,7 +24,7 @@
<div class="middle align-center">
<p class="app-welcome">
Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
- the Pyramid web application development framework.
+ the Pyramid Web Framework.
</p>
</div>
</div>
@@ -69,8 +69,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer">&copy; Copyright 2008-2011, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/templates/view.pt b/docs/tutorials/wiki2/src/tests/tutorial/templates/view.pt
index 5a69818c1..19c50fb36 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/templates/view.pt
+++ b/docs/tutorials/wiki2/src/tests/tutorial/templates/view.pt
@@ -57,9 +57,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer"
- >&copy; Copyright 2008-2011, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki2/src/views/README.txt b/docs/tutorials/wiki2/src/views/README.txt
index 141851285..68f430110 100644
--- a/docs/tutorials/wiki2/src/views/README.txt
+++ b/docs/tutorials/wiki2/src/views/README.txt
@@ -6,9 +6,9 @@ Getting Started
- cd <directory containing this file>
-- $venv/bin/python setup.py develop
+- $VENV/bin/python setup.py develop
-- $venv/bin/initialize_tutorial_db development.ini
+- $VENV/bin/initialize_tutorial_db development.ini
-- $venv/bin/pserve development.ini
+- $VENV/bin/pserve development.ini
diff --git a/docs/tutorials/wiki2/src/views/setup.py b/docs/tutorials/wiki2/src/views/setup.py
index 36668dd33..e8fa8f396 100644
--- a/docs/tutorials/wiki2/src/views/setup.py
+++ b/docs/tutorials/wiki2/src/views/setup.py
@@ -3,8 +3,10 @@ import os
from setuptools import setup, find_packages
here = os.path.abspath(os.path.dirname(__file__))
-README = open(os.path.join(here, 'README.txt')).read()
-CHANGES = open(os.path.join(here, 'CHANGES.txt')).read()
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
requires = [
'pyramid',
diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt
index 3f2039cb6..5f962bbf5 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt
+++ b/docs/tutorials/wiki2/src/views/tutorial/templates/edit.pt
@@ -50,9 +50,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer"
- >&copy; Copyright 2008-2011, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt
index fbfa9870b..ca4e0af26 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt
+++ b/docs/tutorials/wiki2/src/views/tutorial/templates/mytemplate.pt
@@ -1,7 +1,7 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal">
<head>
- <title>The Pyramid Web Application Development Framework</title>
+ <title>The Pyramid Web Framework</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
<meta name="keywords" content="python web application" />
<meta name="description" content="pyramid web application" />
@@ -24,7 +24,7 @@
<div class="middle align-center">
<p class="app-welcome">
Welcome to <span class="app-name">${project}</span>, an application generated by<br/>
- the Pyramid web application development framework.
+ the Pyramid Web Framework.
</p>
</div>
</div>
@@ -69,8 +69,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer">&copy; Copyright 2008-2011, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt b/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt
index 423c1d5a1..78c0d2d4c 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt
+++ b/docs/tutorials/wiki2/src/views/tutorial/templates/view.pt
@@ -53,9 +53,5 @@
</div>
</div>
</div>
- <div id="footer">
- <div class="footer"
- >&copy; Copyright 2008-2011, Agendaless Consulting.</div>
- </div>
</body>
</html>
diff --git a/docs/tutorials/wiki2/tests.rst b/docs/tutorials/wiki2/tests.rst
index 83df86b27..33b5d35c1 100644
--- a/docs/tutorials/wiki2/tests.rst
+++ b/docs/tutorials/wiki2/tests.rst
@@ -54,7 +54,7 @@ Change the ``requires`` list in ``setup.py`` to include ``WebTest``.
.. literalinclude:: src/tests/setup.py
:linenos:
:language: python
- :lines: 9-20
+ :lines: 11-21
:emphasize-lines: 10
After we've added a dependency on WebTest in ``setup.py``, we need to rerun
@@ -66,13 +66,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py develop
+ $ $VENV/bin/python setup.py develop
On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py develop
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py develop
Once that command has completed successfully, we can run the tests
themselves:
@@ -81,13 +81,13 @@ On UNIX:
.. code-block:: text
- $ ../bin/python setup.py test -q
+ $ $VENV/bin/python setup.py test -q
On Windows:
.. code-block:: text
- c:\pyramidtut\tutorial> ..\Scripts\python setup.py test -q
+ c:\pyramidtut\tutorial> %VENV%\Scripts\python setup.py test -q
The expected result ends something like:
diff --git a/docs/whatsnew-1.0.rst b/docs/whatsnew-1.0.rst
index 66cb9be3a..d1f3046ca 100644
--- a/docs/whatsnew-1.0.rst
+++ b/docs/whatsnew-1.0.rst
@@ -249,7 +249,7 @@ ZCML Externalized
Pyramid core. Loading ZCML is now a feature of the :term:`pyramid_zcml`
package, which can be downloaded from PyPI. Documentation for the package
should be available via
- http://pylonsproject.org/projects/pyramid_zcml/dev/, which describes how to
+ http://docs.pylonsproject.org/projects/pyramid_zcml/en/latest/, which describes how to
add a configuration statement to your ``main`` block to reobtain this
method. You will also need to add an ``install_requires`` dependency upon
the ``pyramid_zcml`` distribution to your ``setup.py`` file.
diff --git a/docs/whatsnew-1.1.rst b/docs/whatsnew-1.1.rst
index 18d0aa0b1..cc63017df 100644
--- a/docs/whatsnew-1.1.rst
+++ b/docs/whatsnew-1.1.rst
@@ -13,7 +13,7 @@ Terminology Changes
The term "template" used by the Pyramid documentation used to refer to both
"paster templates" and "rendered templates" (templates created by a rendering
engine. i.e. Mako, Chameleon, Jinja, etc.). "Paster templates" will now be
-refered to as "scaffolds", whereas the name for "rendered templates" will
+referred to as "scaffolds", whereas the name for "rendered templates" will
remain as "templates."
Major Feature Additions
@@ -43,7 +43,7 @@ The major feature additions in Pyramid 1.1 are:
The object passed to a view callable as ``request`` is an instance of
:class:`pyramid.request.Request`. ``request.response`` is an instance of
- the class :class:`pyramid.request.Response`. View callables that are
+ the class :class:`pyramid.response.Response`. View callables that are
configured with a :term:`renderer` will return this response object to the
Pyramid router. Therefore, code in a renderer-using view callable can set
response attributes such as ``request.response.content_type`` (before they
@@ -95,7 +95,7 @@ Default HTTP Exception View
is passed for this value, an exception view for HTTP exceptions will not be
registered. Passing ``None`` returns the behavior of raising an HTTP
exception to that of Pyramid 1.0 (the exception will propagate to
- middleware and to the WSGI server).
+ :term:`middleware` and to the WSGI server).
``http_cache``
~~~~~~~~~~~~~~
@@ -289,7 +289,7 @@ Minor Feature Additions
when you want the static view to behave like the older deprecated version.
- A new api function :func:`pyramid.scripting.prepare` has been added. It is
- a lower-level analogue of :func:`pyramid.paster.boostrap` that accepts a
+ a lower-level analogue of :func:`pyramid.paster.bootstrap` that accepts a
request and a registry instead of a config file argument, and is used for
the same purpose:
@@ -313,7 +313,7 @@ Minor Feature Additions
- New API attribute :attr:`pyramid.config.global_registries` is an iterable
object that contains references to every Pyramid registry loaded into the
- current process via :meth:`pyramid.config.Configurator.make_app`. It also
+ current process via :meth:`pyramid.config.Configurator.make_wsgi_app`. It also
has a ``last`` attribute containing the last registry loaded. This is used
by the scripting machinery, and is available for introspection.
@@ -395,8 +395,9 @@ Deprecations and Behavior Differences
when porting your application from an older version of Pyramid. Use the
``PYTHONWARNINGS`` environment variable with the value ``all`` in the
shell you use to invoke ``paster serve`` to see these warnings, e.g. on
- UNIX, ``PYTHONWARNINGS=all bin/paster serve development.ini``. Python 2.5
- and 2.6 show deprecation warnings by default, so this is unecessary there.
+ UNIX, ``PYTHONWARNINGS=all $VENV/bin/paster serve development.ini``.
+ Python 2.5 and 2.6 show deprecation warnings by default,
+ so this is unnecessary there.
All deprecation warnings are emitted to the console.
- The :class:`pyramid.view.static` class has been deprecated in favor of the
diff --git a/docs/whatsnew-1.2.rst b/docs/whatsnew-1.2.rst
index ea56cf52d..a9fc38908 100644
--- a/docs/whatsnew-1.2.rst
+++ b/docs/whatsnew-1.2.rst
@@ -31,11 +31,11 @@ Tweens
~~~~~~
A :term:`tween` is used to wrap the Pyramid router's primary request handling
-function. This is a feature that can be used by Pyramid framework
-extensions, to provide, for example, view timing support and can provide a
-convenient place to hang bookkeeping code. Tweens are is a little like
-:term:`WSGI` middleware, but have access to Pyramid functionality such as
-renderers and a full-featured request object.
+function. This is a feature that can be used by Pyramid framework extensions,
+to provide, for example, view timing support and can provide a convenient
+place to hang bookkeeping code. Tweens are a little like :term:`WSGI`
+:term:`middleware`, but have access to Pyramid functionality such as renderers
+and a full-featured request object.
To support this feature, a new configurator directive exists named
:meth:`pyramid.config.Configurator.add_tween`. This directive adds a
@@ -51,7 +51,7 @@ Scaffolding Changes
~~~~~~~~~~~~~~~~~~~
- All scaffolds now use the ``pyramid_tm`` package rather than the
- ``repoze.tm2`` middleware to manage transaction management.
+ ``repoze.tm2`` :term:`middleware` to manage transaction management.
- The ZODB scaffold now uses the ``pyramid_zodbconn`` package rather than the
``repoze.zodbconn`` package to provide ZODB integration.
@@ -59,9 +59,9 @@ Scaffolding Changes
- All scaffolds now use the ``pyramid_debugtoolbar`` package rather than the
``WebError`` package to provide interactive debugging features.
-- Projects created via a scaffold no longer depend on the ``WebError``
- package at all; configuration in the ``production.ini`` file which used to
- require its ``error_catcher`` middleware has been removed. Configuring
+- Projects created via a scaffold no longer depend on the ``WebError`` package
+ at all; configuration in the ``production.ini`` file which used to require
+ its ``error_catcher`` :term:`middleware` has been removed. Configuring
error catching / email sending is now the domain of the ``pyramid_exclog``
package (see http://docs.pylonsproject.org/projects/pyramid_exclog/dev/).
@@ -160,7 +160,7 @@ Minor Feature Additions
a value of ``edit``.
- Support an ``onerror`` keyword argument to
- :meth:`pyramid.config.Configurator.scan``. This argument is passed to
+ :meth:`pyramid.config.Configurator.scan`. This argument is passed to
:meth:`venusian.Scanner.scan` to influence error behavior when an exception
is raised during scanning.
diff --git a/docs/whatsnew-1.3.rst b/docs/whatsnew-1.3.rst
index f32053202..2606c3df3 100644
--- a/docs/whatsnew-1.3.rst
+++ b/docs/whatsnew-1.3.rst
@@ -46,12 +46,12 @@ maintain them ourselves. As a result, we've had to make some changes.
Previously (in Pyramid 1.0, 1.1 and 1.2), you created a Pyramid application
using ``paster create``, like so::
- $ myvenv/bin/paster create -t pyramid_starter foo
+ $ $VENV/bin/paster create -t pyramid_starter foo
In 1.3, you're now instead required to create an application using
``pcreate`` like so::
- $ myvenv/bin/pcreate -s starter foo
+ $ $VENV/bin/pcreate -s starter foo
``pcreate`` is required to be used for internal Pyramid scaffolding;
externally distributed scaffolding may allow for both ``pcreate`` and/or
@@ -59,11 +59,11 @@ externally distributed scaffolding may allow for both ``pcreate`` and/or
In previous Pyramid versions, you ran a Pyramid application like so::
- $ myvenv/bin/paster serve development.ini
+ $ $VENV/bin/paster serve development.ini
Instead, you now must use the ``pserve`` command in 1.3::
- $ myvenv/bin/pserve development.ini
+ $ $VENV/bin/pserve development.ini
The ``ini`` configuration file format supported by Pyramid has not changed.
As a result, Python 2-only users can install PasteScript manually and use
@@ -210,13 +210,13 @@ Not Found and Forbidden View Helpers
Not Found helpers:
- New API: :meth:`pyramid.config.Configurator.add_notfound_view`. This is a
- wrapper for :meth:`pyramid.Config.configurator.add_view` which provides
+ wrapper for :meth:`pyramid.config.Configurator.add_view` which provides
support for an "append_slash" feature as well as doing the right thing when
- it comes to permissions (a not found view should always be public). It
+ it comes to permissions (a Not Found View should always be public). It
should be preferred over calling ``add_view`` directly with
``context=HTTPNotFound`` as was previously recommended.
-- New API: :class:`pyramid.view.notfound_view_config``. This is a decorator
+- New API: :class:`pyramid.view.notfound_view_config`. This is a decorator
constructor like :class:`pyramid.view.view_config` that calls
:meth:`pyramid.config.Configurator.add_notfound_view` when scanned. It
should be preferred over using ``pyramid.view.view_config`` with
@@ -225,7 +225,7 @@ Not Found helpers:
Forbidden helpers:
- New API: :meth:`pyramid.config.Configurator.add_forbidden_view`. This is a
- wrapper for :meth:`pyramid.Config.configurator.add_view` which does the
+ wrapper for :meth:`pyramid.config.Configurator.add_view` which does the
right thing about permissions. It should be preferred over calling
``add_view`` directly with ``context=HTTPForbidden`` as was previously
recommended.
@@ -267,7 +267,7 @@ Minor Feature Additions
- We allow extra keyword arguments to be passed to the
:meth:`pyramid.config.Configurator.action` method.
-- Responses generated by Pyramid's :class:`pyramid.views.static_view` now use
+- Responses generated by Pyramid's :class:`pyramid.static.static_view` now use
a ``wsgi.file_wrapper`` (see
http://www.python.org/dev/peps/pep-0333/#optional-platform-specific-file-handling)
when one is provided by the web server.
@@ -389,8 +389,8 @@ Backwards Incompatibilities
and upgrade Pyramid itself "in-place"; it may simply break instead
(particularly if you use ZCML's ``includeOverrides`` directive).
-- String values passed to :meth:`Pyramid.request.Request.route_url` or
- :meth:`Pyramid.request.Request.route_path` that are meant to replace
+- String values passed to :meth:`pyramid.request.Request.route_url` or
+ :meth:`pyramid.request.Request.route_path` that are meant to replace
"remainder" matches will now be URL-quoted except for embedded slashes. For
example::
@@ -492,7 +492,7 @@ Known Issues
develop`` on Python 3.2, it will quit with an installation error while
trying to install ``Pygments``. If this happens, please just rerun the
``setup.py develop`` command again, and it will complete successfully.
- This is due to a minor bug in SQLAlchemy 0.7.5 under Python 3, and will be
+ This is due to a minor bug in SQLAlchemy 0.7.5 under Python 3, and has been
fixed in a later SQLAlchemy release. Keep an eye on
http://www.sqlalchemy.org/trac/ticket/2421
@@ -524,7 +524,7 @@ Documentation Enhancements
- Removed the "Running Pyramid on Google App Engine" tutorial from the main
docs. It survives on in the Cookbook
- (http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/gae.html).
+ (http://docs.pylonsproject.org/projects/pyramid_cookbook/en/latest/deployment/gae.html).
Rationale: it provides the correct info for the Python 2.5 version of GAE
only, and this version of Pyramid does not support Python 2.5.
diff --git a/docs/whatsnew-1.4.rst b/docs/whatsnew-1.4.rst
index 34fda5f37..505b9d798 100644
--- a/docs/whatsnew-1.4.rst
+++ b/docs/whatsnew-1.4.rst
@@ -108,7 +108,7 @@ Minor Feature Additions
- 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).
+ be caught by the Not Found 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
@@ -184,11 +184,12 @@ Minor Feature Additions
returns the policy object it creates.
- The DummySecurityPolicy created by
- :meth:`pyramid.config.testing_securitypolicy` now sets a ``forgotten`` value
- on the policy (the value ``True``) when its ``forget`` method is called.
+ :meth:`pyramid.config.Configurator.testing_securitypolicy` now sets a
+ ``forgotten`` value on the policy (the value ``True``) when its ``forget``
+ method is called.
- The DummySecurityPolicy created by
- :meth:`pyramid.config.testing_securitypolicy` now sets a
+ :meth:`pyramid.config.Configurator.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.
@@ -301,7 +302,7 @@ Backwards Incompatibilities
:meth:`pyramid.config.Configurator.testing_add_subscriber` instead.
* ``registerTemplateRenderer`` (aka ``registerDummyRenderer``), use
- :meth:`pyramid.config.Configurator.testing_add_template` instead.
+ :meth:`pyramid.config.Configurator.testing_add_renderer` instead.
* ``registerView``, use :meth:`pyramid.config.Configurator.add_view` instead.
diff --git a/docs/whatsnew-1.5.rst b/docs/whatsnew-1.5.rst
new file mode 100644
index 000000000..445eb84ae
--- /dev/null
+++ b/docs/whatsnew-1.5.rst
@@ -0,0 +1,158 @@
+What's New In Pyramid 1.5
+=========================
+
+This article explains the new features in :app:`Pyramid` version 1.5 as
+compared to its predecessor, :app:`Pyramid` 1.4. It also documents backwards
+incompatibilities between the two versions and deprecations added to
+:app:`Pyramid` 1.5, as well as software dependency changes and notable
+documentation additions.
+
+Feature Additions
+-----------------
+
+The feature additions in Pyramid 1.5 follow.
+
+- Add ``pdistreport`` script, which prints the Python version in use, the
+ Pyramid version in use, and the version number and location of all Python
+ distributions currently installed.
+
+- Add the ability to invert the result of any view, route, or subscriber
+ predicate value using the ``not_`` class. For example:
+
+ .. code-block:: python
+
+ from pyramid.config import not_
+
+ @view_config(route_name='myroute', request_method=not_('POST'))
+ def myview(request): ...
+
+ The above example will ensure that the view is called if the request method
+ is not POST, at least if no other view is more specific.
+
+ The :class:`pyramid.config.not_` class can be used against any value that is
+ a predicate value passed in any of these contexts:
+
+ - :meth:`pyramid.config.Configurator.add_view`
+
+ - :meth:`pyramid.config.Configurator.add_route`
+
+ - :meth:`pyramid.config.Configurator.add_subscriber`
+
+ - :meth:`pyramid.view.view_config`
+
+ - :meth:`pyramid.events.subscriber`
+
+- View lookup will now search for valid views based on the inheritance
+ hierarchy of the context. It tries to find views based on the most specific
+ context first, and upon predicate failure, will move up the inheritance chain
+ to test views found by the super-type of the context. In the past, only the
+ most specific type containing views would be checked and if no matching view
+ could be found then a PredicateMismatch would be raised. Now predicate
+ mismatches don't hide valid views registered on super-types. Here's an
+ example that now works:
+
+ .. code-block:: python
+
+ class IResource(Interface):
+
+ ...
+
+ @view_config(context=IResource)
+ def get(context, request):
+
+ ...
+
+ @view_config(context=IResource, request_method='POST')
+ def post(context, request):
+
+ ...
+
+ @view_config(context=IResource, request_method='DELETE')
+ def delete(context, request):
+
+ ...
+
+ @implementor(IResource)
+ class MyResource:
+
+ ...
+
+ @view_config(context=MyResource, request_method='POST')
+ def override_post(context, request):
+
+ ...
+
+ Previously the override_post view registration would hide the get
+ and delete views in the context of MyResource -- leading to a
+ predicate mismatch error when trying to use GET or DELETE
+ methods. Now the views are found and no predicate mismatch is
+ raised.
+ See https://github.com/Pylons/pyramid/pull/786 and
+ https://github.com/Pylons/pyramid/pull/1004 and
+ https://github.com/Pylons/pyramid/pull/1046
+
+- ``scripts/prequest.py`` (aka the ``prequest`` console script): added support
+ for submitting ``PUT`` and ``PATCH`` requests. See
+ https://github.com/Pylons/pyramid/pull/1033. add support for submitting
+ ``OPTIONS`` and ``PROPFIND`` requests, and allow users to specify basic
+ authentication credentials in the request via a ``--login`` argument to the
+ script. See https://github.com/Pylons/pyramid/pull/1039.
+
+- :class:`pyramid.authorization.ACLAuthorizationPolicy` supports ``__acl__`` as
+ a callable. This removes the ambiguity between the potential
+ ``AttributeError`` that would be raised on the ``context`` when the property
+ was not defined and the ``AttributeError`` that could be raised from any
+ user-defined code within a dynamic property. It is recommended to define a
+ dynamic ACL as a callable to avoid this ambiguity. See
+ https://github.com/Pylons/pyramid/issues/735.
+
+- Allow a protocol-relative URL (e.g. ``//example.com/images``) to be passed to
+ :meth:`pyramid.config.Configurator.add_static_view`. This allows
+ externally-hosted static URLs to be generated based on the current protocol.
+
+- The :class:`pyramid.authentication.AuthTktAuthenticationPolicy` has a new
+ ``parent_domain`` option to set the authentication cookie as a wildcard
+ cookie on the parent domain. This is useful if you have multiple sites
+ sharing the same domain. It also now supports IPv6 addresses when using
+ the ``include_ip=True`` option. This is possibly incompatible with
+ alternative ``auth_tkt`` implementations, as the specification does not
+ define how to properly handle IPv6. See
+ https://github.com/Pylons/pyramid/issues/831.
+
+- Make it possible to use variable arguments via
+ :func:`pyramid.paster.get_appsettings`. This also allowed the generated
+ ``initialize_db`` script from the ``alchemy`` scaffold to grow support for
+ options in the form ``a=1 b=2`` so you can fill in values in a parameterized
+ ``.ini`` file, e.g. ``initialize_myapp_db etc/development.ini a=1 b=2``.
+ See https://github.com/Pylons/pyramid/pull/911
+
+- The ``request.session.check_csrf_token()`` method and the ``check_csrf`` view
+ predicate now take into account the value of the HTTP header named
+ ``X-CSRF-Token`` (as well as the ``csrf_token`` form parameter, which they
+ always did). The header is tried when the form parameter does not exist.
+
+Backwards Incompatibilities
+---------------------------
+
+- Modified the ``current_route_url`` method in pyramid.Request. The method
+ previously returned the URL without the query string by default, it now does
+ attach the query string unless it is overriden.
+
+
+Deprecations
+------------
+
+This release has no new deprecations as compared to Pyramid 1.4.X.
+
+
+Documentation Enhancements
+--------------------------
+
+Many documentation enhancements have been added, but we did not track them as
+they were added.
+
+Dependency Changes
+------------------
+
+No dependency changes from Pyramid 1.4.X were made in Pyramid 1.5.
+