summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorAtsushi Odagiri <aodagx@gmail.com>2010-11-27 15:08:31 +0900
committerAtsushi Odagiri <aodagx@gmail.com>2010-11-27 15:08:31 +0900
commitcd2f78c893ce6ae98004189a1a0a649fac96d033 (patch)
tree5ab84f72e6bf0476d7d40841f3341aaf9a4e54a4 /docs
parentba32a8d0dcee7f3cef231e08ed60d52fbf60ed4f (diff)
parent4d76ed6f46304d43a6b95da7a4d5388527bf6c1e (diff)
downloadpyramid-cd2f78c893ce6ae98004189a1a0a649fac96d033.tar.gz
pyramid-cd2f78c893ce6ae98004189a1a0a649fac96d033.tar.bz2
pyramid-cd2f78c893ce6ae98004189a1a0a649fac96d033.zip
Merge remote branch 'remotes/upstream/master'
Diffstat (limited to 'docs')
-rw-r--r--docs/Makefile7
-rw-r--r--docs/_static/pylons.png (renamed from docs/_static/pyramid.png)bin4063 -> 4063 bytes
-rw-r--r--docs/_static/pylons_small.pngbin0 -> 4063 bytes
-rw-r--r--docs/api/interfaces.rst1
-rw-r--r--docs/api/url.rst2
-rw-r--r--docs/conf.py11
-rw-r--r--docs/copyright.rst3
-rw-r--r--docs/designdefense.rst37
-rw-r--r--docs/index.rst52
-rw-r--r--docs/latexindex.rst1
-rw-r--r--docs/narr/MyProject/development.ini26
-rw-r--r--docs/narr/MyProject/myproject/__init__.py3
-rw-r--r--docs/narr/configuration.rst18
-rw-r--r--docs/narr/contextfinding.rst2
-rw-r--r--docs/narr/declarative.rst2
-rw-r--r--docs/narr/environment.rst66
-rw-r--r--docs/narr/firstapp.rst49
-rw-r--r--docs/narr/handlers.rst14
-rw-r--r--docs/narr/hybrid.rst32
-rw-r--r--docs/narr/i18n.rst9
-rw-r--r--docs/narr/introduction.rst2
-rw-r--r--docs/narr/project.rst19
-rw-r--r--docs/narr/startup.rst6
-rw-r--r--docs/narr/static.rst31
-rw-r--r--docs/narr/unittesting.rst2
-rw-r--r--docs/narr/urldispatch.rst159
-rw-r--r--docs/tutorials/gae/index.rst4
-rw-r--r--docs/tutorials/wiki/basiclayout.rst9
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/__init__.py2
-rw-r--r--docs/tutorials/wiki/src/basiclayout/tutorial/__init__.py2
-rw-r--r--docs/tutorials/wiki/src/models/tutorial/__init__.py2
-rw-r--r--docs/tutorials/wiki/src/viewdecorators/tutorial/__init__.py2
-rw-r--r--docs/tutorials/wiki/src/views/tutorial/__init__.py2
-rw-r--r--docs/tutorials/wiki2/basiclayout.rst47
-rw-r--r--docs/tutorials/wiki2/definingviews.rst8
-rw-r--r--docs/tutorials/wiki2/src/authorization/development.ini37
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/__init__.py17
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/models.py4
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/tests.py8
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/development.ini37
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py11
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/models.py4
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py3
-rw-r--r--docs/tutorials/wiki2/src/models/development.ini37
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/__init__.py11
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/models.py4
-rw-r--r--docs/tutorials/wiki2/src/views/development.ini37
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/__init__.py17
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/models.py4
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/tests.py8
-rw-r--r--docs/tutorials/zodbsessions/index.rst189
-rw-r--r--docs/zcml/route.rst6
52 files changed, 511 insertions, 555 deletions
diff --git a/docs/Makefile b/docs/Makefile
index 768efb9df..b74c55bd5 100644
--- a/docs/Makefile
+++ b/docs/Makefile
@@ -25,7 +25,7 @@ help:
clean:
-rm -rf _build/*
-html:
+html: _themes/
mkdir -p _build/html _build/doctrees
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
@echo
@@ -47,7 +47,7 @@ pickle:
web: pickle
-htmlhelp:
+htmlhelp: _themes
mkdir -p _build/htmlhelp _build/doctrees
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
@echo
@@ -83,3 +83,6 @@ epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) _build/epub
@echo
@echo "Build finished. The epub file is in _build/epub."
+
+_themes:
+ git clone git://github.com/Pylons/pylons_sphinx_theme.git _themes
diff --git a/docs/_static/pyramid.png b/docs/_static/pylons.png
index 53f83e4d0..53f83e4d0 100644
--- a/docs/_static/pyramid.png
+++ b/docs/_static/pylons.png
Binary files differ
diff --git a/docs/_static/pylons_small.png b/docs/_static/pylons_small.png
new file mode 100644
index 000000000..53f83e4d0
--- /dev/null
+++ b/docs/_static/pylons_small.png
Binary files differ
diff --git a/docs/api/interfaces.rst b/docs/api/interfaces.rst
index b27428d89..b3c14e5f7 100644
--- a/docs/api/interfaces.rst
+++ b/docs/api/interfaces.rst
@@ -33,4 +33,5 @@ Other Interfaces
.. autointerface:: IRendererInfo
+ .. autointerface:: ITemplateRenderer
diff --git a/docs/api/url.rst b/docs/api/url.rst
index 71987498a..8c702a3fb 100644
--- a/docs/api/url.rst
+++ b/docs/api/url.rst
@@ -9,6 +9,8 @@
.. autofunction:: route_url
+ .. autofunction:: route_path
+
.. autofunction:: static_url
.. autofunction:: urlencode
diff --git a/docs/conf.py b/docs/conf.py
index c2ecb1e8d..653f7ab15 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -13,6 +13,9 @@
import sys, os
import datetime
+import warnings
+
+warnings.simplefilter('ignore', DeprecationWarning)
# skip raw nodes
from sphinx.writers.text import TextTranslator
@@ -73,7 +76,7 @@ copyright = '%s, Agendaless Consulting' % datetime.datetime.now().year
# other places throughout the built documents.
#
# The short X.Y version.
-version = '1.0a2'
+version = '1.0a4'
# The full version, including alpha/beta/rc tags.
release = version
@@ -125,11 +128,11 @@ html_theme = 'pylons'
html_title = 'The Pyramid Web Application Development Framework v%s' % release
# A shorter title for the navigation bar. Default is the same as html_title.
-#html_short_title = None
+html_short_title = 'Home'
# The name of an image file (within the static path) to place at the top of
# the sidebar.
-#html_logo = '_static/pylons.png'
+html_logo = '_static/pyramid.png'
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
@@ -198,7 +201,7 @@ latex_documents = [
# The name of an image file (relative to this directory) to place at the top of
# the title page.
-latex_logo = '_static/pyramid.png'
+latex_logo = '_static/pylons_small.png'
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
diff --git a/docs/copyright.rst b/docs/copyright.rst
index 64a0f819b..fa564a785 100644
--- a/docs/copyright.rst
+++ b/docs/copyright.rst
@@ -49,7 +49,8 @@ Attributions
------------
Contributors:
- Ben Bangert, Blaise Laflamme, Carlos de la Guardia, Paul Everitt
+ Ben Bangert, Blaise Laflamme, Carlos de la Guardia, Paul Everitt,
+ Marius Gedminas
.. Cover Designer:
.. Nat Hardwick of `Electrosoup <http://www.electrosoup.co.uk>`_.
diff --git a/docs/designdefense.rst b/docs/designdefense.rst
index 92facf13c..e3a816269 100644
--- a/docs/designdefense.rst
+++ b/docs/designdefense.rst
@@ -40,9 +40,7 @@ Too Complex
if __name__ == '__main__':
config = Configurator()
- config.begin()
config.add_view(hello_world)
- config.end()
app = config.make_wsgi_app()
serve(app)
@@ -549,9 +547,7 @@ everything done completely imperatively. For example, the very most basic
if __name__ == '__main__':
config = Configurator()
- config.begin()
config.add_view(hello_world)
- config.end()
app = config.make_wsgi_app()
serve(app)
@@ -1674,37 +1670,6 @@ can interface with a WSGI application is placed on the server
developer, not the web framework developer, making it more likely to
be timely and correct.
-:meth:`pyramid.configuration.Configurator.begin` and :meth:`pyramid.configuration.Configurator.end` methods
-+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
-The methods :meth:`pyramid.configuration.Configurator.begin` and
-:meth:`pyramid.configuration.Configurator.end` are used to bracket
-the configuration phase of a :app:`Pyramid` application.
-
-These exist because existing legacy third party *configuration* (not
-runtime) code relies on a threadlocal stack being populated. The
-``begin`` method pushes data on to a threadlocal stack. The ``end``
-method pops it back off.
-
-For the simplest applications, these lines are actually not required.
-I *could* omit them from every Pyramid hello world app without ill
-effect. However, when users use certain configuration methods (ones
-not represented in the hello world app), calling code will begin to
-fail when it is not bracketed between a ``begin()`` and an ``end()``.
-It is just easier to tell users that this bracketing is required than
-to try to explain to them which circumstances it is actually required
-and which it is not, because the explanation is often torturous.
-
-The effectively-required execution of these two methods is a wholly
-bogus artifact of an early bad design decision which encouraged
-application developers to use threadlocal data structures during the
-execution of configuration plugins. However, I don't hate my
-framework's users enough to break backwards compatibility for the sake
-of removing two boilerplate lines of code, so it stays, at least for
-the foreseeable future. If I eventually figure out a way to remove
-the requirement, these methods will turn into no-ops and they will be
-removed from the documenation.
-
Wrapping Up
+++++++++++
@@ -1724,9 +1689,7 @@ where comments take into account what we've discussed in the
if __name__ == '__main__':
from pyramid.configuration import Configurator
config = Configurator() # no global application object.
- config.begin() # bogus, but required.
config.add_view(hello_world) # explicit non-decorator registration
- config.end() # bogus, but required.
app = config.make_wsgi_app() # explicitly WSGI
serve(app, host='0.0.0.0') # explicitly WSGI
diff --git a/docs/index.rst b/docs/index.rst
index 4efb25dde..72c21bbc8 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -80,7 +80,6 @@ applications to various platforms.
tutorials/gae/index.rst
tutorials/modwsgi/index.rst
tutorials/zeo/index.rst
- tutorials/zodbsessions/index.rst
tutorials/catalog/index.rst
Reference Material
@@ -114,38 +113,39 @@ Design Documentation
Sample Applications
===================
-.. warning::
+`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::
- These applications are for an older version of :app:`Pyramid`,
- which was named :mod:`repoze.bfg`. We'll be updating them soon to
- use :app:`Pyramid`.
+ git clone git://github.com/Pylons/cluegun.git
-`repoze.cluegun <http://svn.repoze.org/repoze.cluegun/trunk/>`_ 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
-:mod:`repoze.bfg` application. It also has very simple
-:term:`repoze.who` integration. Check this application out of
-Subversion via::
+`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. An
+earlier version of this application runs the `repoze.org
+<http://repoze.org>`_ website. Check this application out via::
- svn co http://svn.repoze.org/repoze.cluegun/trunk repoze.cluegun
+ git clone git://github.com/Pylons/virginia.git
-`repoze.virginia <http://svn.repoze.org/repoze.virginia/trunk/>`_ is a
-very simple dynamic file rendering application. It is willing to
-render structured text documents, HTML documents, and images from a
-filesystem directory. This application runs the `repoze.org
-<http://repoze.org>`_ website. Check this application out of
-Subversion via::
+`shootout <https://github.com/Pylons/shootout>`_ is an example "idea
+competition" application by Carlos de la Guardia. It demonstrates a hybrid
+of :term:`URL dispatch` and :term:`traversal` and integration with
+`SQLAlchemy <http://www.sqlalchemy.org/>`_, :term:`repoze.who`, and
+`Deliverance <http://www.deliveranceproject.org/>`_. Check this application
+out of version control via::
- svn co http://svn.repoze.org/repoze.virginia/trunk repoze.virginia
+ git clone git://github.com/Pylons/shootout.git
-`repoze.shootout <http://svn.repoze.org/repoze.shootout/trunk/>`_ is
-an example "idea competition" application by Carlos de la Guardia. It
-demonstrates a hybrid of :term:`URL dispatch` and :term:`traversal`
-and integration with `SQLAlchemy <http://www.sqlalchemy.org/>`_ and
-:term:`repoze.who`. Check this application out of Subversion via::
+Older Sample Applications (repoze.bfg)
+======================================
+
+.. note::
- svn co http://svn.repoze.org/repoze.shootout/trunk repoze.shootout
+ These applications are for an older version of :app:`Pyramid`, which was
+ named :mod:`repoze.bfg`. They won't work unmodified under Pyramid, but
+ might provide useful clues.
`bfgsite <http://svn.repoze.org/bfgsite/trunk>`_ is the software which
runs the `bfg.repoze.org <http://bfg.repoze.org>`_ website. It
diff --git a/docs/latexindex.rst b/docs/latexindex.rst
index 4efb193bd..388297de7 100644
--- a/docs/latexindex.rst
+++ b/docs/latexindex.rst
@@ -71,7 +71,6 @@ Tutorials
tutorials/gae/index.rst
tutorials/modwsgi/index.rst
tutorials/zeo/index.rst
- tutorials/zodbsessions/index.rst
tutorials/catalog/index.rst
.. _api_reference:
diff --git a/docs/narr/MyProject/development.ini b/docs/narr/MyProject/development.ini
index 9c51cfe6e..80d89e46a 100644
--- a/docs/narr/MyProject/development.ini
+++ b/docs/narr/MyProject/development.ini
@@ -15,3 +15,29 @@ pipeline =
use = egg:Paste#http
host = 0.0.0.0
port = 6543
+
+# Begin logging configuration
+
+[loggers]
+keys = root
+
+[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/narr/MyProject/myproject/__init__.py b/docs/narr/MyProject/myproject/__init__.py
index bfbbfd4df..580dfe546 100644
--- a/docs/narr/MyProject/myproject/__init__.py
+++ b/docs/narr/MyProject/myproject/__init__.py
@@ -5,11 +5,8 @@ def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
config = Configurator(root_factory=get_root, settings=settings)
- config.begin()
config.add_view('myproject.views.my_view',
context='myproject.models.MyModel',
renderer='myproject:templates/mytemplate.pt')
config.add_static_view('static', 'myproject:static')
- config.end()
return config.make_wsgi_app()
-
diff --git a/docs/narr/configuration.rst b/docs/narr/configuration.rst
index 6a91cbf75..ae02a5a6c 100644
--- a/docs/narr/configuration.rst
+++ b/docs/narr/configuration.rst
@@ -47,20 +47,16 @@ imperatively:
if __name__ == '__main__':
config = Configurator()
- config.begin()
config.add_view(hello_world)
- config.end()
app = config.make_wsgi_app()
serve(app, host='0.0.0.0')
-We won't talk much about what this application does yet. Just note
-that the "configuration' statements take place underneath the ``if
-__name__ == '__main__':`` stanza in the form of method calls on a
-:term:`Configurator` object (e.g. ``config.begin()``,
-``config.add_view(...)``, and ``config.end()``. These statements take
-place one after the other, and are executed in order, so the full
-power of Python, including conditionals, can be employed in this mode
-of configuration.
+We won't talk much about what this application does yet. Just note that the
+"configuration' statements take place underneath the ``if __name__ ==
+'__main__':`` stanza in the form of method calls on a :term:`Configurator`
+object (e.g. ``config.add_view(...)``). These statements take place one
+after the other, and are executed in order, so the full power of Python,
+including conditionals, can be employed in this mode of configuration.
.. index::
single: view_config
@@ -123,9 +119,7 @@ and its subpackages. For example:
if __name__ == '__main__':
from pyramid.configuration import Configurator
config = Configurator()
- config.begin()
config.scan()
- config.end()
app = config.make_wsgi_app()
serve(app, host='0.0.0.0')
diff --git a/docs/narr/contextfinding.rst b/docs/narr/contextfinding.rst
index c3fbe7f5a..770f97d15 100644
--- a/docs/narr/contextfinding.rst
+++ b/docs/narr/contextfinding.rst
@@ -75,7 +75,7 @@ URL dispatch can easily handle URLs such as
``http://example.com/members/Chris``, where it's assumed that each
item "below" ``members`` in the URL represents a single member in some
system. You just match everything "below" ``members`` to a particular
-:term:`view callable`, e.g. ``/members/:memberid``.
+:term:`view callable`, e.g. ``/members/{memberid}``.
However, URL dispatch is not very convenient if you'd like your URLs
to represent an arbitrary hierarchy. For example, if you need to
diff --git a/docs/narr/declarative.rst b/docs/narr/declarative.rst
index 48a3ea134..b9dbcab7d 100644
--- a/docs/narr/declarative.rst
+++ b/docs/narr/declarative.rst
@@ -655,7 +655,7 @@ declaration` causes a route to be added to the application.
<route
name="myroute"
- pattern="/prefix/:one/:two"
+ pattern="/prefix/{one}/{two}"
view=".views.myview"
/>
diff --git a/docs/narr/environment.rst b/docs/narr/environment.rst
index 2aa4064cd..c3fe401ec 100644
--- a/docs/narr/environment.rst
+++ b/docs/narr/environment.rst
@@ -201,6 +201,72 @@ should be changed accordingly.
| |
+-----------------------------+
+Mako Error Handler
+++++++++++++++++++
+
+Python callable which is called whenever Mako compile or runtime exceptions
+occur. The callable is passed the current context as well as the exception. If
+the callable returns True, the exception is considered to be handled, else it
+is re-raised after the function completes. Is used to provide custom
+error-rendering functions.
+
++-----------------------------+
+| Config File Setting Name |
++=============================+
+| ``mako.error_handler`` |
+| |
+| |
+| |
++-----------------------------+
+
+Mako Default Filters
+++++++++++++++++++++
+
+List of string filter names that will be applied to all Mako expressions.
+
++-----------------------------+
+| Config File Setting Name |
++=============================+
+| ``mako.default_filters`` |
+| |
+| |
+| |
++-----------------------------+
+
+Mako Import
++++++++++++
+
+String list of Python statements, typically individual “import” lines, which
+will be placed into the module level preamble of all generated Python modules.
+
+
++-----------------------------+
+| Config File Setting Name |
++=============================+
+| ``mako.imports`` |
+| |
+| |
+| |
++-----------------------------+
+
+
+Mako Strict Undefined
++++++++++++++++++++++
+
+``true`` or ``false``, representing the "strict undefined" behavior of Mako
+(see `Mako Context Variables
+<http://www.makotemplates.org/docs/runtime.html#context-variables>`_). By
+default, this is ``false``.
+
++-----------------------------+
+| Config File Setting Name |
++=============================+
+| ``mako.strict_undefined`` |
+| |
+| |
+| |
++-----------------------------+
+
Examples
--------
diff --git a/docs/narr/firstapp.rst b/docs/narr/firstapp.rst
index bc21bf29f..9d3cad13c 100644
--- a/docs/narr/firstapp.rst
+++ b/docs/narr/firstapp.rst
@@ -38,10 +38,8 @@ configured imperatively:
if __name__ == '__main__':
config = Configurator()
- config.begin()
config.add_view(hello_world)
config.add_view(goodbye_world, name='goodbye')
- config.end()
app = config.make_wsgi_app()
serve(app, host='0.0.0.0')
@@ -149,10 +147,8 @@ imports and function definitions is placed within the confines of an
if __name__ == '__main__':
config = Configurator()
- config.begin()
config.add_view(hello_world)
config.add_view(goodbye_world, name='goodbye')
- config.end()
app = config.make_wsgi_app()
serve(app, host='0.0.0.0')
@@ -190,29 +186,6 @@ this particular :app:`Pyramid` application. Methods called on the
Configurator will cause registrations to be made in a
:term:`application registry` associated with the application.
-Beginning Configuration
-~~~~~~~~~~~~~~~~~~~~~~~
-
-.. ignore-next-block
-.. code-block:: python
-
- config.begin()
-
-The :meth:`pyramid.configuration.Configurator.begin` method tells
-the system that application configuration has begun. In particular,
-this causes the :term:`application registry` associated with this
-configurator to become the "current" application registry, meaning
-that code which attempts to use the application registry :term:`thread
-local` will obtain the registry associated with the configurator.
-This is an explicit step because it's sometimes convenient to use a
-configurator without causing the registry associated with the
-configurator to become "current".
-
-.. note::
-
- See :ref:`threadlocals_chapter` for a discussion about what it
- means for an application registry to be "current".
-
.. _adding_configuration:
Adding Configuration
@@ -281,28 +254,6 @@ important. We can register ``goodbye_world`` first and
``hello_world`` second; :app:`Pyramid` will still give us the most
specific callable when a request is dispatched to it.
-Ending Configuration
-~~~~~~~~~~~~~~~~~~~~
-
-.. ignore-next-block
-.. code-block:: python
-
- config.end()
-
-The :meth:`pyramid.configuration.Configurator.end` method tells the
-system that application configuration has ended. It is the inverse of
-:meth:`pyramid.configuration.Configurator.begin`. In particular,
-this causes the :term:`application registry` associated with this
-configurator to no longer be the "current" application registry,
-meaning that code which attempts to use the application registry
-:term:`thread local` will no longer obtain the registry associated
-with the configurator.
-
-.. note::
-
- See :ref:`threadlocals_chapter` for a discussion about what it
- means for an application registry to be "current".
-
.. index::
single: make_wsgi_app
single: WSGI application
diff --git a/docs/narr/handlers.rst b/docs/narr/handlers.rst
index b8e7b5d9b..d82f42bdb 100644
--- a/docs/narr/handlers.rst
+++ b/docs/narr/handlers.rst
@@ -59,11 +59,11 @@ be performed in order to register it with the system:
.. code-block:: python
- config.add_handler('hello', '/hello/:action', handler=Hello)
+ config.add_handler('hello', '/hello/{action}', handler=Hello)
This example will result in a route being added for the pattern
-``/hello/:action``, each method of the ``Hello`` class will then be examined
-to register the views. The value of ``:action`` in the route pattern will be
+``/hello/{action}``, each method of the ``Hello`` class will then be examined
+to register the views. The value of ``{action}`` in the route pattern will be
used to determine which view should be called, and each view in the class will
be setup with a view predicate that requires a specific ``action`` name.
@@ -98,7 +98,7 @@ For example:
.. code-block:: python
- config.add_handler('hello', '/hello/:action',
+ config.add_handler('hello', '/hello/{action}',
handler='mypackage.handlers:MyHandler')
In larger applications, it is advised to use a :term:`resource specification`
@@ -168,8 +168,8 @@ information on the handler method which is used by
configuration.
All keyword arguments are recorded, and passed to
-:meth:`!pyramid.configuration.Configurator.add_view`. Any valid keyword
-arguments for :meth:`!pyramid.configuration.Configurator.add_view` can thus be
+:meth:`~pyramid.configuration.Configurator.add_view`. Any valid keyword
+arguments for :meth:`~pyramid.configuration.Configurator.add_view` can thus be
used with the :class:`~pyramid.view.action` decorator to further restrict when
the view will be called.
@@ -219,7 +219,7 @@ Example:
return {}
# in the config
- config.add_handler('hello', '/hello/:action', handler=Hello)
+ config.add_handler('hello', '/hello/{action}', handler=Hello)
With this configuration, the url ``/hello/home`` will find a view configuration
that results in calling the ``show_template`` method, then rendering the
diff --git a/docs/narr/hybrid.rst b/docs/narr/hybrid.rst
index 61ac68d5d..e704463c7 100644
--- a/docs/narr/hybrid.rst
+++ b/docs/narr/hybrid.rst
@@ -42,8 +42,8 @@ configuration:
# config is an instance of pyramid.configuration.Configurator
- config.add_route('foobar', ':foo/:bar', view='myproject.views.foobar')
- config.add_route('bazbuz', ':baz/:buz', view='myproject.views.bazbuz')
+ config.add_route('foobar', '{foo}/{bar}', view='myproject.views.foobar')
+ config.add_route('bazbuz', '{baz}/{buz}', view='myproject.views.bazbuz')
Each :term:`route` typically corresponds to a single view callable,
and when that route is matched during a request, the view callable
@@ -185,7 +185,7 @@ of a route's pattern:
.. code-block:: python
:linenos:
- config.add_route('home', ':foo/:bar/*traverse')
+ config.add_route('home', '{foo}/{bar}/*traverse')
A ``*traverse`` token at the end of the pattern in a route's
configuration implies a "remainder" *capture* value. When it is used,
@@ -243,7 +243,7 @@ route configuration statement:
.. code-block:: python
:linenos:
- config.add_route('home', ':foo/:bar/*traverse',
+ config.add_route('home', '{foo}/{bar}/*traverse',
factory='mypackage.routes.root_factory')
The ``factory`` above points at the function we've defined. It
@@ -267,14 +267,14 @@ to do.
When the route configuration named ``home`` above is matched during a
request, the matchdict generated will be based on its pattern:
-``:foo/:bar/*traverse``. The "capture value" implied by the
+``{foo}/{bar}/*traverse``. The "capture value" implied by the
``*traverse`` element in the pattern will be used to traverse the
graph in order to find a context, starting from the root object
returned from the root factory. In the above example, the
:term:`root` object found will be the instance named ``root`` in
``routes.py``.
-If the URL that matched a route with the pattern ``:foo/:bar/*traverse``,
+If the URL that matched a route with the pattern ``{foo}/{bar}/*traverse``,
is ``http://example.com/one/two/a/b/c``, the traversal path used
against the root object will be ``a/b/c``. As a result,
:app:`Pyramid` will attempt to traverse through the edges ``a``,
@@ -296,7 +296,7 @@ invoked after a route matches:
.. code-block:: python
:linenos:
- config.add_route('home', ':foo/:bar/*traverse',
+ config.add_route('home', '{foo}/{bar}/*traverse',
factory='mypackage.routes.root_factory')
config.add_view('mypackage.views.myview', route_name='home')
@@ -326,7 +326,7 @@ when a hybrid route is matched:
.. code-block:: python
:linenos:
- config.add_route('home', ':foo/:bar/*traverse',
+ config.add_route('home', '{foo}/{bar}/*traverse',
factory='mypackage.routes.root_factory')
config.add_view('mypackage.views.myview', name='home')
config.add_view('mypackage.views.another_view', name='another',
@@ -358,7 +358,7 @@ Using the ``traverse`` Argument In a Route Definition
Rather than using the ``*traverse`` remainder marker in a pattern, you
can use the ``traverse`` argument to the
-:meth:`pyramid.configuration.Configurator.add_route`` method.
+:meth:`pyramid.configuration.Configurator.add_route` method.
When you use the ``*traverse`` remainder marker, the traversal path is
limited to being the remainder segments of a request URL when a route
@@ -371,14 +371,14 @@ Here's a use of the ``traverse`` pattern in a call to
.. code-block:: python
:linenos:
- config.add_route('abc', '/articles/:article/edit',
- traverse='/articles/:article')
+ config.add_route('abc', '/articles/{article}/edit',
+ traverse='/articles/{article}')
The syntax of the ``traverse`` argument is the same as it is for
``pattern``.
-If, as above, the ``pattern`` provided is ``articles/:article/edit``,
-and the ``traverse`` argument provided is ``/:article``, when a
+If, as above, the ``pattern`` provided is ``articles/{article}/edit``,
+and the ``traverse`` argument provided is ``/{article}``, when a
request comes in that causes the route to match in such a way that the
``article`` match value is ``1`` (when the request URI is
``/articles/1/edit``), the traversal path will be generated as ``/1``.
@@ -467,7 +467,7 @@ startup time.
.. code-block:: python
:linenos:
- config.add_route('home', ':foo/:bar/*traverse',
+ config.add_route('home', '{foo}/{bar}/*traverse',
view='myproject.views.home')
config.add_view('myproject.views.another', route_name='home')
@@ -479,7 +479,7 @@ supply a view attribute. For example, this ``add_route`` call:
.. code-block:: python
:linenos:
- config.add_route('home', ':foo/:bar/*traverse',
+ config.add_route('home', '{foo}/{bar}/*traverse',
view='myproject.views.home')
Can also be spelled like so:
@@ -487,7 +487,7 @@ Can also be spelled like so:
.. code-block:: python
:linenos:
- config.add_route('home', ':foo/:bar/*traverse')
+ config.add_route('home', '{foo}/{bar}/*traverse')
config.add_view('myproject.views.home', route_name='home')
The two spellings are logically equivalent. In fact, the former is
diff --git a/docs/narr/i18n.rst b/docs/narr/i18n.rst
index 703883fb2..9e2071872 100644
--- a/docs/narr/i18n.rst
+++ b/docs/narr/i18n.rst
@@ -773,8 +773,8 @@ If this setting is supplied within the :app:`Pyramid` application
.. code-block:: python
:linenos:
- from pyramid.setttings import get_settings
- settings = get_settings()
+ from pyramid.threadlocal import get_current_registry
+ settings = get_current_registry().settings
default_locale_name = settings['default_locale_name']
"Detecting" Available Languages
@@ -822,8 +822,9 @@ Then as a part of the code of a custom :term:`locale negotiator`:
.. code-block:: py
- from pyramid.settings import get_settings
- languages = get_settings()['available_languages'].split()
+ from pyramid.threadlocal import get_current_registry
+ settings = get_current_registry().settings
+ languages = settings['available_languages'].split()
This is only a suggestion. You can create your own "available
languages" configuration scheme as necessary.
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index 725d32725..7c725690d 100644
--- a/docs/narr/introduction.rst
+++ b/docs/narr/introduction.rst
@@ -103,7 +103,7 @@ What Is The Pylons Project?
---------------------------
:app:`Pyramid` is a member of the collection of software published under the
-Pylons Project. :Pylons software is written by a loose-knit community of
+Pylons Project. Pylons software is written by a loose-knit community of
contributors. The `Pylons Project website <http://docs.pylonshq.com>`_
includes details about how :app:`Pyramid` relates to the Pylons Project.
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index f47e9f293..aef134ff7 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -316,12 +316,13 @@ Python interpreter shell unconditionally.
[pipeline:main]
pipeline = egg:WebError#evalerror
- myapp
+ MyProject
- If you use ``main`` as the section name argument instead of ``myapp``
- against the above ``.ini`` file, an error will occur. Use the most
- specific reference to your application within the ``.ini`` file possible
- as the section name argument.
+ Use ``MyProject`` instead of ``main`` as the section name argument to
+ ``pshell`` against the above ``.ini`` file (e.g. ``paster pshell
+ development.ini MyProject``). If you use ``main`` instead, an error will
+ occur. Use the most specific reference to your application within the
+ ``.ini`` file possible as the section name argument.
Press ``Ctrl-D`` to exit the interactive shell (or ``Ctrl-Z`` on Windows).
@@ -740,14 +741,14 @@ also informs Python that the directory which contains it is a *package*.
#. Line 2 imports the ``get_root`` function from
:mod:`myproject.models` that we use later.
-#. Lines 4-14 define a function that returns a :app:`Pyramid`
+#. Lines 4-12 define a function that returns a :app:`Pyramid`
WSGI application. This function is meant to be called
by the :term:`PasteDeploy` framework as a result of running
``paster serve``.
Within this function, configuration is performed.
- Lines 9-11 register a "default view" (a view that has no ``name``
+ Lines 8-10 register a "default view" (a view that has no ``name``
attribute). It is registered so that it will be found when the
:term:`context` of the request is an instance of the
:class:`myproject.models.MyModel` class. The first argument to
@@ -761,11 +762,11 @@ also informs Python that the directory which contains it is a *package*.
``templates`` directory of the ``myproject`` package. The template file
it actually points to is a :term:`Chameleon` ZPT template file.
- Line 12 registers a static view, which will serve up the files from the
+ Line 11 registers a static view, which will serve up the files from the
``mypackage:static`` :term:`resource specification` (the ``static``
directory of the ``mypackage`` package).
- Line 14 returns a :term:`WSGI` application to the caller of the function
+ Line 12 returns a :term:`WSGI` application to the caller of the function
(Paste).
``views.py``
diff --git a/docs/narr/startup.rst b/docs/narr/startup.rst
index c57525f4c..427acc319 100644
--- a/docs/narr/startup.rst
+++ b/docs/narr/startup.rst
@@ -86,9 +86,9 @@ press ``return`` after running ``paster serve development.ini``.
:linenos:
In this case, the ``myproject.run:app`` function referred to by the entry
- point URI ``egg:MyProject#app`` (see :ref:`MyProject_ini` for more
- information about entry point URIs, and how they relate to callables),
- will receive the key/value pairs ``{'reload_templates':'true',
+ point URI ``egg:MyProject`` (see :ref:`MyProject_ini` for more information
+ about entry point URIs, and how they relate to callables), will receive
+ the key/value pairs ``{'reload_templates':'true',
'debug_authorization':'false', 'debug_notfound':'false',
'debug_templates':'true', 'default_locale_name':'en'}``.
diff --git a/docs/narr/static.rst b/docs/narr/static.rst
index efeabd012..a01cbbabf 100644
--- a/docs/narr/static.rst
+++ b/docs/narr/static.rst
@@ -69,22 +69,21 @@ when generating a URL using :func:`pyramid.url.static_url`.
.. note::
Using :func:`pyramid.url.static_url` in conjunction with a
- :meth:`pyramid.configuration.Configurator.add_static_view` makes
- it possible to put static media on a separate webserver during
- production (if the ``name`` argument to
- :meth:`pyramid.configuration.Configurator.add_static_view` is a
- URL), while keeping static media package-internal and served by the
- development webserver during development (if the ``name`` argument
- to :meth:`pyramid.configuration.Configurator.add_static_view` is
- a view name). To create such a circumstance, we suggest using the
- :func:`pyramid.settings.get_settings` API in conjunction with a
- setting in the application ``.ini`` file named ``media_location``.
- Then set the value of ``media_location`` to either a view name or a
- URL depending on whether the application is being run in
- development or in production (use a different `.ini`` file for
- production than you do for development). This is just a suggestion
- for a pattern; any setting name other than ``media_location`` could
- be used.
+ :meth:`pyramid.configuration.Configurator.add_static_view` makes it
+ possible to put static media on a separate webserver during production (if
+ the ``name`` argument to
+ :meth:`pyramid.configuration.Configurator.add_static_view` is a URL),
+ while keeping static media package-internal and served by the development
+ webserver during development (if the ``name`` argument to
+ :meth:`pyramid.configuration.Configurator.add_static_view` is a view
+ name). To create such a circumstance, we suggest using the
+ :attr:`pyramid.registry.Registry.settings` API in conjunction with a
+ setting in the application ``.ini`` file named ``media_location``. Then
+ set the value of ``media_location`` to either a view name or a URL
+ depending on whether the application is being run in development or in
+ production (use a different `.ini`` file for production than you do for
+ development). This is just a suggestion for a pattern; any setting name
+ other than ``media_location`` could be used.
For example, :meth:`pyramid.configuration.Configurator.add_static_view` may
be fed a ``name`` argument which is ``http://example.com/images``:
diff --git a/docs/narr/unittesting.rst b/docs/narr/unittesting.rst
index 5cd8a0683..26035726b 100644
--- a/docs/narr/unittesting.rst
+++ b/docs/narr/unittesting.rst
@@ -1,4 +1,4 @@
-.. index::
+\.. index::
single: unit testing
single: integration testing
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst
index 4442be355..df7d592f9 100644
--- a/docs/narr/urldispatch.rst
+++ b/docs/narr/urldispatch.rst
@@ -92,7 +92,12 @@ registry`. Here's an example:
# pyramid.configuration.Configurator class; "myview" is assumed
# to be a "view callable" function
from views import myview
- config.add_route('myroute', '/prefix/:one/:two', view=myview)
+ config.add_route('myroute', '/prefix/{one}/{two}', view=myview)
+
+.. versionchanged:: 1.0a4
+ Prior to 1.0a4, routes allow for a marker starting with a ``:``, for
+ example ``/prefix/{one}``. Starting in 1.0a4, this style is deprecated
+ in favor or ``{}`` usage which allows for additional functionality.
.. index::
single: route configuration; view callable
@@ -116,7 +121,7 @@ Here's an example route configuration that references a view callable:
# pyramid.configuration.Configurator class; "myview" is assumed
# to be a "view callable" function
from myproject.views import myview
- config.add_route('myroute', '/prefix/:one/:two', view=myview)
+ config.add_route('myroute', '/prefix/{one}/{two}', view=myview)
You can also pass a :term:`dotted Python name` as the ``view`` argument
rather than an actual callable:
@@ -128,7 +133,7 @@ rather than an actual callable:
# pyramid.configuration.Configurator class; "myview" is assumed
# to be a "view callable" function
from myproject.views import myview
- config.add_route('myroute', '/prefix/:one/:two',
+ config.add_route('myroute', '/prefix/{one}/{two}',
view='myproject.views.myview')
When a route configuration names a ``view`` attribute, the :term:`view
@@ -200,28 +205,28 @@ the following patterns are equivalent:
.. code-block:: text
- :foo/bar/baz
+ {foo}/bar/baz
and:
.. code-block:: text
- /:foo/bar/baz
+ /{foo}/bar/baz
-A patttern segment (an individual item between ``/`` characters in the
-pattern) may either be a literal string (e.g. ``foo``) *or* it may be
-a segment replacement marker (e.g. ``:foo``) or a certain combination
-of both.
+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 replacement marker
+does not need to be preceded by a ``/`` character.
-A segment replacement marker is in the format ``:name``, where this
-means "accept any characters up to the next nonalphaunumeric character
+A replacement marker is in the format ``{name}``, where this
+means "accept any characters up to the next non-alphanumeric character
and use this as the ``name`` matchdict value." For example, the
following pattern defines one literal segment ("foo") and two dynamic
-segments ("baz", and "bar"):
+replacement markers ("baz", and "bar"):
.. code-block:: text
- foo/:baz/:bar
+ foo/{baz}/{bar}
The above pattern will match these URLs, generating the following
matchdicts:
@@ -244,24 +249,36 @@ pattern. So, for instance, if this route pattern was used:
.. code-block:: text
- foo/:name.html
+ foo/{name}.html
The literal path ``/foo/biz.html`` will match the above route pattern,
and the match result will be ``{'name':u'biz'}``. However, the
literal path ``/foo/biz`` will not match, because it does not contain
a literal ``.html`` at the end of the segment represented by
-``:name.html`` (it only contains ``biz``, not ``biz.html``).
+``{name}.html`` (it only contains ``biz``, not ``biz.html``).
+
+To capture both segments, two replacement markers can be used:
+
+.. code-block:: text
+
+ foo/{name}.{ext}
-This does not mean, however, that you can use two segment replacement
-markers in the same segment. For instance, ``/:foo:bar`` is a
-nonsensical route pattern. It will never match anything.
+The literal path ``/foo/biz.html`` will match the above route pattern, and the
+match result will be ``{'name': 'biz', 'ext': 'html'}``. This occurs because
+the replacement marker ``{name}`` has a literal part of ``.`` between the other
+replacement marker ``:ext``.
+
+It is possible to use two replacement markers without any literal characters
+between them, for instance ``/{foo}{bar}``. This would be a nonsensical pattern
+without specifying a custom regular expression to restrict what a marker
+captures.
Segments must contain at least one character in order to match a
segment replacement marker. For example, for the URL ``/abc/``:
-- ``/abc/:foo`` will not match.
+- ``/abc/{foo}`` will not match.
-- ``/:foo/`` will match.
+- ``/{foo}/`` will match.
Note that values representing path segments matched with a
``:segment`` match will be url-unquoted and decoded from UTF-8 into
@@ -270,7 +287,7 @@ pattern:
.. code-block:: text
- foo/:bar
+ foo/{bar}
When matching the following URL:
@@ -292,7 +309,7 @@ need to be preceded by a slash. For example:
.. code-block:: text
- foo/:baz/:bar*fizzle
+ foo/{baz}/{bar}*fizzle
The above pattern will match these URLs, generating the following
matchdicts:
@@ -324,6 +341,25 @@ Will generate the following matchdict:
{'fizzle':(u'La Pe\xf1a', u'a', u'b', u'c')}
+By default, the ``*stararg`` will parse the remainder sections into a tuple
+split by segment. Changing the regular expression used to match a marker can
+also capture the remainder of the URL, for example:
+
+.. code-block:: text
+
+ foo/{baz}/{bar}{fizzle:.*}
+
+The above pattern will match these URLs, generating the following
+matchdicts::
+
+ foo/1/2/ -> {'baz':'1', 'bar':'2', 'fizzle':()}
+ foo/abc/def/a/b/c -> {'baz':'abc', 'bar':'def', 'fizzle': 'a/b/c')}
+
+This occurs because the default regular expression for a marker is ``[^/]+``
+which will match everything up to the first ``/``, while ``{filzzle:.*}`` will
+result in a regular expression match of ``.*`` capturing the remainder into
+a single value.
+
.. index::
single: route ordering
@@ -348,12 +384,12 @@ be added in the following order:
.. code-block:: text
- members/:def
+ members/{def}
members/abc
In such a configuration, the ``members/abc`` pattern would *never* be
matched; this is because the match ordering will always match
-``members/:def`` first; the route configuration with ``members/abc``
+``members/{def}`` first; the route configuration with ``members/abc``
will never be evaluated.
.. index::
@@ -434,8 +470,8 @@ represent neither predicates nor view configuration information.
The syntax of the ``traverse`` argument is the same as it is for
``pattern``. For example, if the ``pattern`` provided is
- ``articles/:article/edit``, and the ``traverse`` argument provided
- is ``/:article``, when a request comes in that causes the route to
+ ``articles/{article}/edit``, and the ``traverse`` argument provided
+ is ``/{article}``, when a request comes in that causes the route to
match in such a way that the ``article`` match value is '1' (when
the request URI is ``/articles/1/edit``), the traversal path will be
generated as ``/1``. This means that the root object's
@@ -462,7 +498,7 @@ represent neither predicates nor view configuration information.
**Predicate Arguments**
``pattern``
- The path of the route e.g. ``ideas/:idea``. This argument is
+ The path of the route e.g. ``ideas/{idea}``. This argument is
required. See :ref:`route_path_pattern_syntax` for information
about the syntax of route paths. If the path doesn't match the
current URL, route matching continues.
@@ -470,7 +506,7 @@ represent neither predicates nor view configuration information.
.. note:: In earlier releases of this framework, this argument existed
as ``path``. ``path`` continues to work as an alias for
``pattern``.
-
+
``xhr``
This value should be either ``True`` or ``False``. If this value is
specified and is ``True``, the :term:`request` must possess an
@@ -644,7 +680,7 @@ match. For example:
num_one_two_or_three = any_of('num', 'one', 'two', 'three')
- config.add_route('num', '/:num',
+ config.add_route('num', '/{num}',
custom_predicates=(num_one_two_or_three,))
The above ``any_of`` function generates a predicate which ensures that
@@ -675,7 +711,7 @@ For instance, a predicate might do some type conversion of values:
ymd_to_int = integers('year', 'month', 'day')
- config.add_route('num', '/:year/:month/:day',
+ config.add_route('num', '/{year}/{month}/{day}',
custom_predicates=(ymd_to_int,))
Note that a conversion predicate is still a predicate so it must
@@ -683,6 +719,29 @@ return ``True`` or ``False``; a predicate that does *only* conversion,
such as the one we demonstrate above should unconditionally return
``True``.
+To avoid the try/except uncertainty, the route pattern can contain regular
+expressions specifying requirements for that marker. For instance:
+
+.. code-block:: python
+ :linenos:
+
+ def integers(*segment_names):
+ def predicate(info, request):
+ match = info['match']
+ for segment_name in segment_names:
+ match[segment_name] = int(match[segment_name])
+ return True
+ return predicate
+
+ ymd_to_int = integers('year', 'month', 'day')
+
+ config.add_route('num', '/{year:\d+}/{month:\d+}/{day:\d+}',
+ custom_predicates=(ymd_to_int,))
+
+Now the try/except is no longer needed because the route will not match at
+all unless these markers match ``\d+`` which requires them to be valid digits
+for an ``int`` type conversion.
+
The ``match`` dictionary passed within ``info`` to each predicate
attached to a route will be the same dictionary. Therefore, when
registering a custom predicate which modifies the ``match`` dict, the
@@ -713,9 +772,9 @@ An example of using the route in a set of route predicates:
if info['route'].name in ('ymd', 'ym', 'y'):
return info['match']['year'] == '2010'
- config.add_route('y', '/:year', custom_predicates=(twenty_ten,))
- config.add_route('ym', '/:year/:month', custom_predicates=(twenty_ten,))
- config.add_route('ymd', '/:year/:month:/day',
+ config.add_route('y', '/{year}', custom_predicates=(twenty_ten,))
+ config.add_route('ym', '/{year}/{month}', custom_predicates=(twenty_ten,))
+ config.add_route('ymd', '/{year}/{month}/{day}',
custom_predicates=(twenty_ten,))
The above predicate, when added to a number of route configurations
@@ -814,7 +873,7 @@ The simplest route declaration which configures a route match to
.. code-block:: python
:linenos:
- config.add_route('idea', 'site/:id', view='mypackage.views.site_view')
+ config.add_route('idea', 'site/{id}', view='mypackage.views.site_view')
When a route configuration with a ``view`` attribute is added to the
system, and an incoming request matches the *pattern* of the route
@@ -822,12 +881,12 @@ configuration, the :term:`view callable` named as the ``view``
attribute of the route configuration will be invoked.
In the case of the above example, when the URL of a request matches
-``/site/:id``, the view callable at the Python dotted path name
+``/site/{id}``, the view callable at the Python dotted path name
``mypackage.views.site_view`` will be called with the request. In
other words, we've associated a view callable directly with a route
pattern.
-When the ``/site/:id`` route pattern matches during a request, the
+When the ``/site/{id}`` route pattern matches during a request, the
``site_view`` view callable is invoked with that request as its sole
argument. When this route matches, a ``matchdict`` will be generated
and attached to the request as ``request.matchdict``. If the specific
@@ -860,30 +919,30 @@ might add to your application:
.. code-block:: python
:linenos:
- config.add_route('idea', 'ideas/:idea', view='mypackage.views.idea_view')
- config.add_route('user', 'users/:user', view='mypackage.views.user_view')
- config.add_route('tag', 'tags/:tags', view='mypackage.views.tag_view')
+ config.add_route('idea', 'ideas/{idea}', view='mypackage.views.idea_view')
+ config.add_route('user', 'users/{user}', view='mypackage.views.user_view')
+ config.add_route('tag', 'tags/{tags}', view='mypackage.views.tag_view')
The above configuration will allow :app:`Pyramid` to service URLs
in these forms:
.. code-block:: text
- /ideas/:idea
- /users/:user
- /tags/:tag
+ /ideas/{idea}
+ /users/{user}
+ /tags/{tag}
-- When a URL matches the pattern ``/ideas/:idea``, the view callable
+- When a URL matches the pattern ``/ideas/{idea}``, the view callable
available at the dotted Python pathname ``mypackage.views.idea_view`` will
be called. For the specific URL ``/ideas/1``, the ``matchdict`` generated
and attached to the :term:`request` will consist of ``{'idea':'1'}``.
-- When a URL matches the pattern ``/users/:user``, the view callable
+- When a URL matches the pattern ``/users/{user}``, the view callable
available at the dotted Python pathname ``mypackage.views.user_view`` will
be called. For the specific URL ``/users/1``, the ``matchdict`` generated
and attached to the :term:`request` will consist of ``{'user':'1'}``.
-- When a URL matches the pattern ``/tags/:tag``, the view callable available
+- When a URL matches the pattern ``/tags/{tag}``, the view callable available
at the dotted Python pathname ``mypackage.views.tag_view`` will be called.
For the specific URL ``/tags/1``, the ``matchdict`` generated and attached
to the :term:`request` will consist of ``{'tag':'1'}``.
@@ -911,7 +970,7 @@ An example of using a route with a factory:
.. code-block:: python
:linenos:
- config.add_route('idea', 'ideas/:idea',
+ config.add_route('idea', 'ideas/{idea}',
view='myproject.views.idea_view',
factory='myproject.models.Idea')
@@ -939,7 +998,7 @@ a ``view`` declaration.
.. code-block:: python
:linenos:
- config.add_route('idea', 'site/:id')
+ config.add_route('idea', 'site/{id}')
config.add_view(route_name='idea', view='mypackage.views.site_view')
This set of configuration parameters creates a configuration
@@ -949,7 +1008,7 @@ completely equivalent to this example provided in
.. code-block:: python
:linenos:
- config.add_route('idea', 'site/:id', view='mypackage.views.site_view')
+ config.add_route('idea', 'site/{id}', view='mypackage.views.site_view')
In fact, the spelling which names a ``view`` attribute is just
syntactic sugar for the more verbose spelling which contains separate
@@ -990,7 +1049,7 @@ Generating Route URLs
Use the :func:`pyramid.url.route_url` function to generate URLs based on
route patterns. For example, if you've configured a route with the ``name``
-"foo" and the ``pattern`` ":a/:b/:c", you might do this.
+"foo" and the ``pattern`` "{a}/{b}/{c}", you might do this.
.. ignore-next-block
.. code-block:: python
@@ -1184,7 +1243,7 @@ Such a ``factory`` might look like so:
if article == '1':
self.__acl__ = [ (Allow, 'editor', 'view') ]
-If the route ``archives/:article`` is matched, and the article number
+If the route ``archives/{article}`` is matched, and the article number
is ``1``, :app:`Pyramid` will generate an ``Article``
:term:`context` with an ACL on it that allows the ``editor`` principal
the ``view`` permission. Obviously you can do more generic things
diff --git a/docs/tutorials/gae/index.rst b/docs/tutorials/gae/index.rst
index a2b190a31..9c8e8c07e 100644
--- a/docs/tutorials/gae/index.rst
+++ b/docs/tutorials/gae/index.rst
@@ -72,13 +72,13 @@ system.
#. Edit ``config.py``
Edit the ``APP_NAME`` and ``APP_ARGS`` settings within
- ``config.py``. The ``APP_NAME`` must be ``pyramidapp:app``, and
+ ``config.py``. The ``APP_NAME`` must be ``pyramidapp:main``, and
the APP_ARGS must be ``({},)``. Any other settings in
``config.py`` should remain the same.
.. code-block:: python
- APP_NAME = 'pyramidapp:app'
+ APP_NAME = 'pyramidapp:main'
APP_ARGS = ({},)
#. Edit ``runner.py``
diff --git a/docs/tutorials/wiki/basiclayout.rst b/docs/tutorials/wiki/basiclayout.rst
index c05a53831..a94a1632d 100644
--- a/docs/tutorials/wiki/basiclayout.rst
+++ b/docs/tutorials/wiki/basiclayout.rst
@@ -48,14 +48,11 @@ entry point happens to be the ``app`` function within the file named
factory` and the settings keywords parsed by PasteDeploy. The root
factory is named ``get_root``.
-#. *Lines 16-18*. Begin configuration using the ``begin`` method of
- the :meth:`pyramid.configuration.Configurator` class, load the
+#. *Line 16*. Load the
``configure.zcml`` file from our package using the
- :meth:`pyramid.configuration.Configurator.load_zcml` method, and
- end configuration using the
- :meth:`pyramid.configuration.Configurator.end` method.
+ :meth:`pyramid.configuration.Configurator.load_zcml` method.
-#. *Line 19*. Use the
+#. *Line 17*. Use the
:meth:`pyramid.configuration.Configurator.make_wsgi_app` method
to return a :term:`WSGI` application.
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/__init__.py b/docs/tutorials/wiki/src/authorization/tutorial/__init__.py
index 124647ba9..a8a3c513e 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/__init__.py
+++ b/docs/tutorials/wiki/src/authorization/tutorial/__init__.py
@@ -16,7 +16,5 @@ def main(global_config, **settings):
def get_root(request):
return finder(request.environ)
config = Configurator(root_factory=get_root, settings=settings)
- config.begin()
config.load_zcml('configure.zcml')
- config.end()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki/src/basiclayout/tutorial/__init__.py b/docs/tutorials/wiki/src/basiclayout/tutorial/__init__.py
index f6cf8b479..45e4d722b 100644
--- a/docs/tutorials/wiki/src/basiclayout/tutorial/__init__.py
+++ b/docs/tutorials/wiki/src/basiclayout/tutorial/__init__.py
@@ -13,8 +13,6 @@ def main(global_config, **settings):
def get_root(request):
return finder(request.environ)
config = Configurator(root_factory=get_root, settings=settings)
- config.begin()
config.load_zcml('configure.zcml')
- config.end()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki/src/models/tutorial/__init__.py b/docs/tutorials/wiki/src/models/tutorial/__init__.py
index 7ef07e767..66e2f05ee 100644
--- a/docs/tutorials/wiki/src/models/tutorial/__init__.py
+++ b/docs/tutorials/wiki/src/models/tutorial/__init__.py
@@ -16,8 +16,6 @@ def main(global_config, **settings):
def get_root(request):
return finder(request.environ)
config = Configurator(root_factory=get_root, settings=settings)
- config.begin()
config.load_zcml('configure.zcml')
- config.end()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki/src/viewdecorators/tutorial/__init__.py b/docs/tutorials/wiki/src/viewdecorators/tutorial/__init__.py
index 7ef07e767..66e2f05ee 100644
--- a/docs/tutorials/wiki/src/viewdecorators/tutorial/__init__.py
+++ b/docs/tutorials/wiki/src/viewdecorators/tutorial/__init__.py
@@ -16,8 +16,6 @@ def main(global_config, **settings):
def get_root(request):
return finder(request.environ)
config = Configurator(root_factory=get_root, settings=settings)
- config.begin()
config.load_zcml('configure.zcml')
- config.end()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki/src/views/tutorial/__init__.py b/docs/tutorials/wiki/src/views/tutorial/__init__.py
index 7ef07e767..66e2f05ee 100644
--- a/docs/tutorials/wiki/src/views/tutorial/__init__.py
+++ b/docs/tutorials/wiki/src/views/tutorial/__init__.py
@@ -16,8 +16,6 @@ def main(global_config, **settings):
def get_root(request):
return finder(request.environ)
config = Configurator(root_factory=get_root, settings=settings)
- config.begin()
config.load_zcml('configure.zcml')
- config.end()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst
index 9aca94fe5..01fdd351e 100644
--- a/docs/tutorials/wiki2/basiclayout.rst
+++ b/docs/tutorials/wiki2/basiclayout.rst
@@ -32,30 +32,21 @@ entry point happens to be the ``app`` function within the file named
#. *Lines 1-4*. Imports to support later code.
-#. *Lines 9-11*. Get the database configuration string from the
- ``development.ini`` file's ``[app:sqlalchemy]`` section. This will be a
- URI (something like ``sqlite://``).
+#. *Line 9*. Create a SQLAlchemy database engine from the ``sqlalchemy.``
+ prefixed settings in the ``development.ini`` file's ``[app:tutorial]``
+ section. This will be a URI (something like ``sqlite://``).
-#. *Line 12*. Get the database echo setting from ``development.ini``
- file's ``[app:sqlalchemy]`` section. This will either be ``true``
- or ``false``. If ``true``, the application will print SQL to the
- console as it is generated and run by SQLAlchemy. By default, it
- is false.
+#. *Line 10*. We initialize our SQL database using SQLAlchemy, passing
+ it the engine
-#. Line *13*. We initialize our SQL database using SQLAlchemy, passing
- it the db string and a variant of the db_echo value.
-
-#. *Line 14*. We construct a :term:`Configurator`. ``settings`` is
+#. *Line 11*. We construct a :term:`Configurator`. ``settings`` is
passed as a keyword argument with the dictionary values passed by
PasteDeploy as the ``settings`` argument. This will be a
dictionary of settings parsed by PasteDeploy, which contains
deployment-related values such as ``reload_templates``,
``db_string``, etc.
-#. *Line 15*. We call :meth:`pyramid.configuration.Configurator.begin` which
- tells the configuration machinery we are starting configuration.
-
-#. *Line 16*. We call
+#. *Line 12*. We call
:meth:`pyramid.configuration.Configurator.add_static_view` with the
arguments ``static`` (the name), and ``tutorial:static`` (the path). This
registers a static resource view which will match any URL that starts with
@@ -67,7 +58,7 @@ entry point happens to be the ``app`` function within the file named
``/static/foo``) will be used to compose a path to a static file resource,
such as a CSS file.
-#. *Lines 17-18*. Register a :term:`route configuration` via the
+#. *Lines 13-14*. Register a :term:`route configuration` via the
:meth:`pyramid.configuration.Configurator.add_route` method that will be
used when the URL is ``/``. Since this route has an ``pattern`` equalling
``/`` it is the "default" route. The argument named ``view`` with the
@@ -81,10 +72,7 @@ entry point happens to be the ``app`` function within the file named
``tutorial.views.my_view`` view returns a dictionary, a :term:`renderer`
will use this template to create a response.
-#. *Line 19*. We call :meth:`pyramid.configuration.Configurator.end` which
- tells the configuration machinery we are ending configuration.
-
-#. *Line 20*. We use the
+#. *Line 15*. We use the
:meth:`pyramid.configuration.Configurator.make_wsgi_app` method to return
a :term:`WSGI` application.
@@ -103,29 +91,28 @@ Here is the source for ``models.py``:
:linenos:
:language: py
-#. *Lines 1-14*. Imports to support later code.
+#. *Lines 1-13*. Imports to support later code.
-#. *Line 16*. We set up a SQLAlchemy "DBSession" object here. We
+#. *Line 15*. We set up a SQLAlchemy "DBSession" object here. We
specify that we'd like to use the "ZopeTransactionExtension". This
extension is an extension which allows us to use a *transaction
manager* instead of controlling commits and aborts to database
operations by hand.
-#. *Line 17*. We create a declarative ``Base`` object to use as a
+#. *Line 16*. We create a declarative ``Base`` object to use as a
base class for our model.
-#. *Lines 19-27*. A model class named ``MyModel``. It has an
+#. *Lines 18-26*. A model class named ``MyModel``. It has an
``__init__`` that takes a 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.
-#. *Lines 29-34*. A function named ``populate`` which adds a single
+#. *Lines 28-33*. A function named ``populate`` which adds a single
model instance into our SQL storage and commits a transaction.
-#. *Lines 36-44*. A function named ``initialize_sql`` which sets up
- an actual SQL database and binds it to our SQLAlchemy DBSession
- object. It also calls the ``populate`` function, to do initial
- database population.
+#. *Lines 35-42*. A function named ``initialize_sql`` which receives a SQL
+ database engine and binds it to our SQLAlchemy DBSession object. It also
+ calls the ``populate`` function, to do initial database population.
diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst
index b87cd6a64..0f446bb4e 100644
--- a/docs/tutorials/wiki2/definingviews.rst
+++ b/docs/tutorials/wiki2/definingviews.rst
@@ -24,7 +24,7 @@ The request 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.configuration.Configurator.add_route` in
-``__init__.py`` had the pattern ``:one/:two``, and the URL at
+``__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``.
@@ -277,16 +277,16 @@ the order they're found in the ``__init__.py`` file.
to the view named ``view_wiki`` in our ``views.py`` file with the name
``view_wiki``. This is the :term:`default view` for the wiki.
-#. Add a declaration which maps the pattern ``/:pagename`` to the view named
+#. Add a declaration which maps the pattern ``/{pagename}`` to the view named
``view_page`` in our ``views.py`` file with the view name ``view_page``.
This is the regular view for a page.
#. Add a declaration which maps the pattern
- ``/add_page/:pagename`` to the view named ``add_page`` in our
+ ``/add_page/{pagename}`` to the view named ``add_page`` in our
``views.py`` file with the name ``add_page``. This is the add view
for a new page.
-#. Add a declaration which maps the pattern ``/:pagename/edit_page`` to the
+#. Add a declaration which maps the pattern ``/{pagename}/edit_page`` to the
view named ``edit_page`` in our ``views.py`` file with the name
``edit_page``. This is the edit view for a page.
diff --git a/docs/tutorials/wiki2/src/authorization/development.ini b/docs/tutorials/wiki2/src/authorization/development.ini
index e1d0ab598..23b01a338 100644
--- a/docs/tutorials/wiki2/src/authorization/development.ini
+++ b/docs/tutorials/wiki2/src/authorization/development.ini
@@ -5,8 +5,7 @@ debug_authorization = false
debug_notfound = false
debug_templates = true
default_locale_name = en
-db_string = sqlite:///%(here)s/tutorial.db
-db_echo = false
+sqlalchemy.url = sqlite:///%(here)s/tutorial.db
[pipeline:main]
pipeline =
@@ -18,3 +17,37 @@ pipeline =
use = egg:Paste#http
host = 0.0.0.0
port = 6543
+
+# Begin logging configuration
+
+[loggers]
+keys = root, sqlalchemy
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[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
+
+# End logging configuration
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py b/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py
index 4bddea74c..dbac349b9 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py
@@ -2,7 +2,7 @@ from pyramid.configuration import Configurator
from pyramid.authentication import AuthTktAuthenticationPolicy
from pyramid.authorization import ACLAuthorizationPolicy
-from pyramid.settings import asbool
+from sqlalchemy import engine_from_config
from tutorial.models import initialize_sql
from tutorial.security import groupfinder
@@ -10,11 +10,8 @@ from tutorial.security import groupfinder
def main(global_config, **settings):
""" This function returns a WSGI application.
"""
- db_string = settings.get('db_string')
- if db_string is None:
- raise ValueError("No 'db_string' value in application configuration.")
- db_echo = settings.get('db_echo', 'false')
- initialize_sql(db_string, asbool(db_echo))
+ engine = engine_from_config(settings, 'sqlalchemy.')
+ initialize_sql(engine)
authn_policy = AuthTktAuthenticationPolicy(
'sosecret', callback=groupfinder)
authz_policy = ACLAuthorizationPolicy()
@@ -22,7 +19,6 @@ def main(global_config, **settings):
root_factory='tutorial.models.RootFactory',
authentication_policy=authn_policy,
authorization_policy=authz_policy)
- config.begin()
config.add_static_view('static', 'tutorial:static')
config.add_route('view_wiki', '/', view='tutorial.views.view_wiki')
config.add_route('login', '/login',
@@ -30,20 +26,19 @@ def main(global_config, **settings):
view_renderer='tutorial:templates/login.pt')
config.add_route('logout', '/logout',
view='tutorial.login.logout')
- config.add_route('view_page', '/:pagename',
+ config.add_route('view_page', '/{pagename}',
view='tutorial.views.view_page',
view_renderer='tutorial:templates/view.pt')
- config.add_route('add_page', '/add_page/:pagename',
+ config.add_route('add_page', '/add_page/{pagename}',
view='tutorial.views.add_page',
view_renderer='tutorial:templates/edit.pt',
view_permission='edit')
- config.add_route('edit_page', '/:pagename/edit_page',
+ config.add_route('edit_page', '/{pagename}/edit_page',
view='tutorial.views.edit_page',
view_renderer='tutorial:templates/edit.pt',
view_permission='edit')
config.add_view('tutorial.login.login',
renderer='tutorial:templates/login.pt',
context='pyramid.exceptions.Forbidden')
- config.end()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/models.py b/docs/tutorials/wiki2/src/authorization/tutorial/models.py
index 7580220b6..487299c4c 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/models.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/models.py
@@ -3,7 +3,6 @@ import transaction
from pyramid.security import Allow
from pyramid.security import Everyone
-from sqlalchemy import create_engine
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import Text
@@ -30,8 +29,7 @@ class Page(Base):
self.name = name
self.data = data
-def initialize_sql(db_string, echo=False):
- engine = create_engine(db_string, echo=echo)
+def initialize_sql(engine):
DBSession.configure(bind=engine)
Base.metadata.bind = engine
Base.metadata.create_all(engine)
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/tests.py b/docs/tutorials/wiki2/src/authorization/tutorial/tests.py
index 65330ce17..c78899797 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/tests.py
@@ -14,9 +14,9 @@ def _initTestingDB():
return DBSession
def _registerRoutes(config):
- config.add_route('view_page', ':pagename')
- config.add_route('edit_page', ':pagename/edit_page')
- config.add_route('add_page', 'add_page/:pagename')
+ config.add_route('view_page', '{pagename}')
+ config.add_route('edit_page', '{pagename}/edit_page')
+ config.add_route('add_page', 'add_page/{pagename}')
class ViewWikiTests(unittest.TestCase):
def setUp(self):
@@ -28,7 +28,7 @@ class ViewWikiTests(unittest.TestCase):
def test_it(self):
from tutorial.views import view_wiki
- self.config.add_route('view_page', ':pagename')
+ self.config.add_route('view_page', '{pagename}')
request = testing.DummyRequest()
response = view_wiki(request)
self.assertEqual(response.location, 'http://example.com/FrontPage')
diff --git a/docs/tutorials/wiki2/src/basiclayout/development.ini b/docs/tutorials/wiki2/src/basiclayout/development.ini
index e1d0ab598..23b01a338 100644
--- a/docs/tutorials/wiki2/src/basiclayout/development.ini
+++ b/docs/tutorials/wiki2/src/basiclayout/development.ini
@@ -5,8 +5,7 @@ debug_authorization = false
debug_notfound = false
debug_templates = true
default_locale_name = en
-db_string = sqlite:///%(here)s/tutorial.db
-db_echo = false
+sqlalchemy.url = sqlite:///%(here)s/tutorial.db
[pipeline:main]
pipeline =
@@ -18,3 +17,37 @@ pipeline =
use = egg:Paste#http
host = 0.0.0.0
port = 6543
+
+# Begin logging configuration
+
+[loggers]
+keys = root, sqlalchemy
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[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
+
+# End logging configuration
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py
index 7a701fc02..5236a538d 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py
@@ -1,22 +1,17 @@
from pyramid.configuration import Configurator
-from pyramid.settings import asbool
+from sqlalchemy import engine_from_config
from tutorial.models import initialize_sql
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- db_string = settings.get('db_string')
- if db_string is None:
- raise ValueError("No 'db_string' value in application configuration.")
- db_echo = settings.get('db_echo', 'false')
- initialize_sql(db_string, asbool(db_echo))
+ engine = engine_from_config(settings, 'sqlalchemy.')
+ initialize_sql(engine)
config = Configurator(settings=settings)
- config.begin()
config.add_static_view('static', 'tutorial:static')
config.add_route('home', '/', view='tutorial.views.my_view',
view_renderer='templates/mytemplate.pt')
- config.end()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py
index a1726ebf4..9da906752 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/models.py
@@ -1,6 +1,5 @@
import transaction
-from sqlalchemy import create_engine
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import Unicode
@@ -33,8 +32,7 @@ def populate():
session.flush()
transaction.commit()
-def initialize_sql(db_string, db_echo=False):
- engine = create_engine(db_string, echo=db_echo)
+def initialize_sql(engine):
DBSession.configure(bind=engine)
Base.metadata.bind = engine
Base.metadata.create_all(engine)
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py
index 72f0c89d8..2db1bc5b6 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/tests.py
@@ -3,8 +3,9 @@ from pyramid.configuration import Configurator
from pyramid import testing
def _initTestingDB():
+ from sqlalchemy import create_engine
from tutorial.models import initialize_sql
- session = initialize_sql('sqlite://')
+ session = initialize_sql(create_engine('sqlite://'))
return session
class TestMyView(unittest.TestCase):
diff --git a/docs/tutorials/wiki2/src/models/development.ini b/docs/tutorials/wiki2/src/models/development.ini
index e1d0ab598..23b01a338 100644
--- a/docs/tutorials/wiki2/src/models/development.ini
+++ b/docs/tutorials/wiki2/src/models/development.ini
@@ -5,8 +5,7 @@ debug_authorization = false
debug_notfound = false
debug_templates = true
default_locale_name = en
-db_string = sqlite:///%(here)s/tutorial.db
-db_echo = false
+sqlalchemy.url = sqlite:///%(here)s/tutorial.db
[pipeline:main]
pipeline =
@@ -18,3 +17,37 @@ pipeline =
use = egg:Paste#http
host = 0.0.0.0
port = 6543
+
+# Begin logging configuration
+
+[loggers]
+keys = root, sqlalchemy
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[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
+
+# End logging configuration
diff --git a/docs/tutorials/wiki2/src/models/tutorial/__init__.py b/docs/tutorials/wiki2/src/models/tutorial/__init__.py
index 10fcd0cbc..e1baa2d64 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/__init__.py
@@ -1,20 +1,15 @@
from pyramid.configuration import Configurator
-from pyramid.settings import asbool
+from sqlalchemy import engine_from_config
from tutorial.models import initialize_sql
def main(global_config, **settings):
""" This function returns a WSGI application.
"""
- db_string = settings.get('db_string')
- if db_string is None:
- raise ValueError("No 'db_string' value in application configuration.")
- db_echo = settings.get('db_echo', 'false')
- initialize_sql(db_string, asbool(db_echo))
+ engine = engine_from_config(settings, 'sqlalchemy.')
+ initialize_sql(engine)
config = Configurator(settings=settings)
- config.begin()
config.add_static_view('static', 'tutorial:static')
config.add_route('home', '/', view='tutorial.views.my_view',
view_renderer='templates/mytemplate.pt')
- config.end()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/src/models/tutorial/models.py b/docs/tutorials/wiki2/src/models/tutorial/models.py
index ec9d2b25c..23b8afab8 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/models.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/models.py
@@ -1,6 +1,5 @@
import transaction
-from sqlalchemy import create_engine
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import Text
@@ -27,8 +26,7 @@ class Page(Base):
self.name = name
self.data = data
-def initialize_sql(db_string, echo=False):
- engine = create_engine(db_string, echo=echo)
+def initialize_sql(engine):
DBSession.configure(bind=engine)
Base.metadata.bind = engine
Base.metadata.create_all(engine)
diff --git a/docs/tutorials/wiki2/src/views/development.ini b/docs/tutorials/wiki2/src/views/development.ini
index e1d0ab598..23b01a338 100644
--- a/docs/tutorials/wiki2/src/views/development.ini
+++ b/docs/tutorials/wiki2/src/views/development.ini
@@ -5,8 +5,7 @@ debug_authorization = false
debug_notfound = false
debug_templates = true
default_locale_name = en
-db_string = sqlite:///%(here)s/tutorial.db
-db_echo = false
+sqlalchemy.url = sqlite:///%(here)s/tutorial.db
[pipeline:main]
pipeline =
@@ -18,3 +17,37 @@ pipeline =
use = egg:Paste#http
host = 0.0.0.0
port = 6543
+
+# Begin logging configuration
+
+[loggers]
+keys = root, sqlalchemy
+
+[handlers]
+keys = console
+
+[formatters]
+keys = generic
+
+[logger_root]
+level = INFO
+handlers = console
+
+[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
+
+# End logging configuration
diff --git a/docs/tutorials/wiki2/src/views/tutorial/__init__.py b/docs/tutorials/wiki2/src/views/tutorial/__init__.py
index 9ef923e0b..91c299e24 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/__init__.py
@@ -1,29 +1,24 @@
from pyramid.configuration import Configurator
-from pyramid.settings import asbool
+from sqlalchemy import engine_from_config
from tutorial.models import initialize_sql
def main(global_config, **settings):
""" This function returns a WSGI application.
"""
- db_string = settings.get('db_string')
- if db_string is None:
- raise ValueError("No 'db_string' value in application configuration.")
- db_echo = settings.get('db_echo', 'false')
- initialize_sql(db_string, asbool(db_echo))
+ engine = engine_from_config(settings, 'sqlalchemy.')
+ initialize_sql(engine)
config = Configurator(settings=settings)
- config.begin()
config.add_static_view('static', 'tutorial:static')
config.add_route('home', '/', view='tutorial.views.view_wiki')
- config.add_route('view_page', '/:pagename',
+ config.add_route('view_page', '/{pagename}',
view='tutorial.views.view_page',
view_renderer='tutorial:templates/view.pt')
- config.add_route('add_page', '/add_page/:pagename',
+ config.add_route('add_page', '/add_page/{pagename}',
view='tutorial.views.add_page',
view_renderer='tutorial:templates/edit.pt')
- config.add_route('edit_page', '/:pagename/edit_page',
+ config.add_route('edit_page', '/{pagename}/edit_page',
view='tutorial.views.edit_page',
view_renderer='tutorial:templates/edit.pt')
- config.end()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/src/views/tutorial/models.py b/docs/tutorials/wiki2/src/views/tutorial/models.py
index ec9d2b25c..23b8afab8 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/models.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/models.py
@@ -1,6 +1,5 @@
import transaction
-from sqlalchemy import create_engine
from sqlalchemy import Column
from sqlalchemy import Integer
from sqlalchemy import Text
@@ -27,8 +26,7 @@ class Page(Base):
self.name = name
self.data = data
-def initialize_sql(db_string, echo=False):
- engine = create_engine(db_string, echo=echo)
+def initialize_sql(engine):
DBSession.configure(bind=engine)
Base.metadata.bind = engine
Base.metadata.create_all(engine)
diff --git a/docs/tutorials/wiki2/src/views/tutorial/tests.py b/docs/tutorials/wiki2/src/views/tutorial/tests.py
index 40336fca4..435e4b588 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/tests.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/tests.py
@@ -14,9 +14,9 @@ def _initTestingDB():
return DBSession
def _registerRoutes(config):
- config.add_route('view_page', ':pagename')
- config.add_route('edit_page', ':pagename/edit_page')
- config.add_route('add_page', 'add_page/:pagename')
+ config.add_route('view_page', '{pagename}')
+ config.add_route('edit_page', '{pagename}/edit_page')
+ config.add_route('add_page', 'add_page/{pagename}')
class ViewWikiTests(unittest.TestCase):
def setUp(self):
@@ -28,7 +28,7 @@ class ViewWikiTests(unittest.TestCase):
def test_it(self):
from tutorial.views import view_wiki
- self.config.add_route('view_page', ':pagename')
+ self.config.add_route('view_page', '{pagename}')
request = testing.DummyRequest()
response = view_wiki(request)
self.assertEqual(response.location, 'http://example.com/FrontPage')
diff --git a/docs/tutorials/zodbsessions/index.rst b/docs/tutorials/zodbsessions/index.rst
deleted file mode 100644
index 9582e5de4..000000000
--- a/docs/tutorials/zodbsessions/index.rst
+++ /dev/null
@@ -1,189 +0,0 @@
-.. _zodb_sessions:
-
-Using ZODB-Based Sessions
-=========================
-
-Sessions are server-side namespaces which are associated with a site
-user that expire automatically after some period of disuse.
-
-If your application is ZODB-based (e.g. you've created an application
-from the ``bfg_zodb`` paster template, or you've followed the
-instructions in :ref:`zodb_with_zeo`), you can make use of the
-``repoze.session`` and ``repoze.browserid`` packages to add
-sessioning to your application.
-
-.. note:: You can use the ``repoze.session`` package even if your
- application is not ZODB-based, but its backing store requires ZODB,
- so it makes the most sense to use this package if your application
- already uses ZODB. This tutorial does not cover usage of
- ``repoze.session``-based sessions in applications that don't
- already use ZODB. For this, see `the standalone repoze.session
- usage documentation <http://docs.repoze.org/session/usage.html>`_.
- If you don't want to use ZODB to do sessioning, you might choose to
- use a relational/filestorage sessioning system such as `Beaker
- <http://pypi.python.org/pypi/Beaker>`_. :app:`Pyramid` is fully
- compatible with this system too.
-
-Installing Dependencies
------------------------
-
-#. Edit your :app:`Pyramid` application's ``setup.py`` file, adding
- the following packages to the ``install_requires`` of the
- application:
-
- - ``repoze.session``
-
- - ``repoze.browserid``
-
- For example, the relevant portion of your application's
- ``setup.py`` file might look like so when you're finished adding
- the dependencies.
-
- .. code-block:: python
- :linenos:
-
- setup(
- # ... other elements left out for brevity
- install_requires=[
- 'pyramid',
- 'repoze.folder',
- 'repoze.retry',
- 'repoze.tm2',
- 'repoze.zodbconn',
- 'repoze.session'
- 'repoze.browserid',
- ],
- # ... other elements left out for brevity
- )
-
-#. Rerun your application's ``setup.py`` file (e.g. using ``python
- setup.py develop``) to get these packages installed.
-
-Configuration
--------------
-
-#. Edit your application's Paste ``.ini`` file.
-
- If you already have an ``app`` section in the ``.ini`` file named
- ``main``, rename this section to ``myapp`` (e.g. ``app:main`` ->
- ``app:myapp``). Add a key to it named ``zodb_uri``, e.g.
-
- .. code-block:: python
- :linenos:
-
- [app:myapp]
- use = egg:myapp#app
- zodb_uri = zeo://%(here)s/zeo.sock
- reload_templates = true
- debug_authorization = false
- debug_notfound = false
-
- Add a ``filter`` section to the ``.ini`` file named "browserid":
-
- .. code-block:: python
- :linenos:
-
- [filter:browserid]
- use = egg:repoze.browserid#browserid
- secret_key = my-secret-key
-
- Replace ``my-secret-key`` with any random string. This string
- represents the value which the client-side "browser id" cookie is
- encrypted with, to prevent tampering.
-
- If a ``pipeline`` named ``main`` does not already exist in the
- paste ``.ini`` file , add a ``pipeline`` section named ``main``.
- Put the names ``connector``, ``egg:repoze.retry#retry``, and
- ``egg:repoze.tm2#tm`` to the top of the pipeline.
-
- .. code-block:: python
- :linenos:
-
- [pipeline:main]
- pipeline =
- browserid
- egg:repoze.retry#retry
- egg:repoze.tm2#tm
- myapp
-
- When you're finished, your ``.ini`` file might look like so:
-
- .. code-block:: ini
- :linenos:
-
- [DEFAULT]
- debug = true
-
- [app:myapp]
- use = egg:myapp#app
- zodb_uri = zeo://%(here)s/zeo.sock
- reload_templates = true
- debug_authorization = false
- debug_notfound = false
-
- [filter:browserid]
- use = egg:repoze.browserid#browserid
- secret_key = my-secret-key
-
- [pipeline:main]
- pipeline =
- browserid
- egg:repoze.retry#retry
- egg:repoze.tm2#tm
- myapp
-
- [server:main]
- use = egg:Paste#http
- host = 0.0.0.0
- port = 6543
-
- See :ref:`MyProject_ini` for more information about project Paste
- ``.ini`` files.
-
-#. Add a ``get_session`` API to your application. I've chosen to add
- it directly to my ``views.py`` file, although it can live anywhere.
-
- .. code-block:: python
- :linenos:
-
- from repoze.session.manager import SessionDataManager
- from pyramid.traversal import find_root
-
- def get_session(context, request):
- root = find_root(context)
- if not hasattr(root, '_sessions'):
- root._sessions = SessionDataManager(3600, 5)
- session = root._sessions.get(request.environ['repoze.browserid'])
- return session
-
- Note in the call to ``SessionDataManager`` that '3600' represents
- the disuse timeout (60 minutes == 3600 seconds), and '5' represents
- a write granularity time (the session will be marked as active at
- most every five seconds). Vary these values as necessary.
-
-#. Whenever you want to use a session in your application, call this API:
-
- .. code-block:: python
- :linenos:
-
- from repoze.session.manager import SessionDataManager
- from pyramid.traversal import find_root
- from pyramid.chameleon_zpt import render_template_to_response
-
- def my_view(context, request):
- session = get_session(context, request)
- session['abc'] = '123'
- return render_template_to_response('templates/mytemplate.pt',
- request = request,
- project = 'sess')
-
- def get_session(context, request):
- root = find_root(context)
- if not hasattr(root, '_sessions'):
- root._sessions = SessionDataManager(3600, 5)
- session = root._sessions.get(request.environ['repoze.browserid'])
- return session
-
-For more information, see the `repoze.session documentation
-<http://docs.repoze.org/session/>`_ and the `repoze.browserid
-documentation <http://pypi.python.org/pypi/repoze.browserid>`_.
diff --git a/docs/zcml/route.rst b/docs/zcml/route.rst
index ed849e3c1..c3bec72df 100644
--- a/docs/zcml/route.rst
+++ b/docs/zcml/route.rst
@@ -10,7 +10,7 @@ Attributes
~~~~~~~~~~
``pattern``
- The pattern of the route e.g. ``ideas/:idea``. This attribute is
+ The pattern of the route e.g. ``ideas/{idea}``. This attribute is
required. See :ref:`route_pattern_syntax` for information
about the syntax of route patterns.
@@ -51,9 +51,9 @@ Attributes
The syntax of the ``traverse`` argument is the same as it is for
``pattern``. For example, if the ``pattern`` provided to the
- ``route`` directive is ``articles/:article/edit``, and the
+ ``route`` directive is ``articles/{article}/edit``, and the
``traverse`` argument provided to the ``route`` directive is
- ``/:article``, when a request comes in that causes the route to
+ ``/{article}``, when a request comes in that causes the route to
match in such a way that the ``article`` match value is '1' (when
the request URI is ``/articles/1/edit``), the traversal path will be
generated as ``/1``. This means that the root object's