summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorSteve Piercy <web@stevepiercy.com>2016-04-16 14:07:28 -0700
committerSteve Piercy <web@stevepiercy.com>2016-04-16 14:52:37 -0700
commitd729f7d47b90d47d7e40fd5d1df449582f1c4eca (patch)
tree1ae26e5443801e881009a40169a394a9561bdacb /docs
parent1eea18ab7f1428ba8ac01a238f03ddbf8483593b (diff)
downloadpyramid-d729f7d47b90d47d7e40fd5d1df449582f1c4eca.tar.gz
pyramid-d729f7d47b90d47d7e40fd5d1df449582f1c4eca.tar.bz2
pyramid-d729f7d47b90d47d7e40fd5d1df449582f1c4eca.zip
Merge pull request #2505 from stevepiercy/docs/quick-tour-gotcher-nose
Docs/quick tour gotcher nose
Diffstat (limited to 'docs')
-rw-r--r--docs/conf.py1
-rw-r--r--docs/glossary.rst20
-rw-r--r--docs/quick_tutorial/authentication.rst89
-rw-r--r--docs/quick_tutorial/authorization.rst86
-rw-r--r--docs/quick_tutorial/databases.rst186
-rw-r--r--docs/quick_tutorial/databases/sqltutorial.sqlitebin12288 -> 0 bytes
-rw-r--r--docs/quick_tutorial/debugtoolbar.rst53
-rw-r--r--docs/quick_tutorial/forms.rst127
-rw-r--r--docs/quick_tutorial/functional_testing.rst52
-rw-r--r--docs/quick_tutorial/hello_world.rst81
-rw-r--r--docs/quick_tutorial/index.rst10
-rw-r--r--docs/quick_tutorial/ini.rst92
-rw-r--r--docs/quick_tutorial/jinja2.rst55
-rw-r--r--docs/quick_tutorial/json.rst87
-rw-r--r--docs/quick_tutorial/logging.rst52
-rw-r--r--docs/quick_tutorial/more_view_classes.rst131
-rw-r--r--docs/quick_tutorial/package.rst40
-rw-r--r--docs/quick_tutorial/request_response.rst71
-rw-r--r--docs/quick_tutorial/requirements.rst138
-rw-r--r--docs/quick_tutorial/routing.rst53
-rw-r--r--docs/quick_tutorial/scaffolds.rst48
-rw-r--r--docs/quick_tutorial/sessions.rst70
-rw-r--r--docs/quick_tutorial/static_assets.rst45
-rw-r--r--docs/quick_tutorial/templating.rst85
-rw-r--r--docs/quick_tutorial/tutorial_approach.rst66
-rw-r--r--docs/quick_tutorial/unit_testing.rst114
-rw-r--r--docs/quick_tutorial/view_classes.rst69
-rw-r--r--docs/quick_tutorial/views.rst85
28 files changed, 1018 insertions, 988 deletions
diff --git a/docs/conf.py b/docs/conf.py
index 1600e1f5c..c40f1c875 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -67,6 +67,7 @@ intersphinx_mapping = {
'jinja2': ('http://docs.pylonsproject.org/projects/pyramid-jinja2/en/latest/', None),
'pylonswebframework': ('http://docs.pylonsproject.org/projects/pylons-webframework/en/latest/', None),
'python': ('https://docs.python.org/3', None),
+ 'pytest': ('http://pytest.org/latest/', None),
'sqla': ('http://docs.sqlalchemy.org/en/latest', None),
'tm': ('http://docs.pylonsproject.org/projects/pyramid-tm/en/latest/', None),
'toolbar': ('http://docs.pylonsproject.org/projects/pyramid-debugtoolbar/en/latest', None),
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 486e94848..1d97bffe8 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -1108,14 +1108,15 @@ Glossary
``f``, ``false``, ``n``, ``no``, ``off`` and ``0``.
pip
- The `Python Packaging Authority's <https://www.pypa.io/>`_ recommended
- tool for installing Python packages.
+ The :term:`Python Packaging Authority`'s recommended tool for installing
+ Python packages.
pyvenv
- The Python Packaging Authority formerly recommended using this command
- for `creating virtual environments on Python 3.4 and 3.5
+ The :term:`Python Packaging Authority` formerly recommended using the
+ ``pyvenv`` command for `creating virtual environments on Python 3.4 and
+ 3.5
<https://packaging.python.org/en/latest/installing/#creating-virtual-environments>`_,
- but it is deprecated in 3.6 in favor of ``python3 -m venv`` on UNIX or
+ but it was deprecated in 3.6 in favor of ``python3 -m venv`` on UNIX or
``python -m venv`` on Windows, which is backward compatible on Python
3.3 and greater.
@@ -1124,9 +1125,14 @@ Glossary
use by a particular application, rather than being installed system wide.
venv
- The `Python Packaging Authority's <https://www.pypa.io/>`_ recommended
- tool for creating virtual environments on Python 3.3 and greater.
+ The :term:`Python Packaging Authority`'s recommended tool for creating
+ virtual environments on Python 3.3 and greater.
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.
+
+ Python Packaging Authority
+ The `Python Packaging Authority (PyPA) <https://www.pypa.io/en/latest/>`_
+ is a working group that maintains many of the relevant projects in Python
+ packaging. \ No newline at end of file
diff --git a/docs/quick_tutorial/authentication.rst b/docs/quick_tutorial/authentication.rst
index cb3839b08..acff97f3b 100644
--- a/docs/quick_tutorial/authentication.rst
+++ b/docs/quick_tutorial/authentication.rst
@@ -4,28 +4,27 @@
20: Logins With Authentication
==============================
-Login views that authenticate a username/password against a list of
-users.
+Login views that authenticate a username and password against a list of users.
+
Background
==========
-Most web applications have URLs that allow people to add/edit/delete
-content via a web browser. Time to add
-:ref:`security <security_chapter>`
-to the application. In this first step we introduce authentication.
-That is, logging in and logging out using Pyramid's rich facilities for
-pluggable user storages.
+Most web applications have URLs that allow people to add/edit/delete content
+via a web browser. Time to add :ref:`security <security_chapter>` to the
+application. In this first step we introduce authentication. That is, logging
+in and logging out, using Pyramid's rich facilities for pluggable user storage.
+
+In the next step we will introduce protection of resources with authorization
+security statements.
-In the next step we will introduce protection resources with
-authorization security statements.
Objectives
==========
-- Introduce the Pyramid concepts of authentication
+- Introduce the Pyramid concepts of authentication.
-- Create login/logout views
+- Create login and logout views.
Steps
=====
@@ -38,22 +37,20 @@ Steps
$ $VENV/bin/pip install -e .
#. Put the security hash in the ``authentication/development.ini``
- configuration file as ``tutorial.secret`` instead of putting it in
- the code:
+ configuration file as ``tutorial.secret`` instead of putting it in the code:
.. literalinclude:: authentication/development.ini
:language: ini
:linenos:
-#. Get authentication (and for now, authorization policies) and login
- route into the :term:`configurator` in
- ``authentication/tutorial/__init__.py``:
+#. Get authentication (and for now, authorization policies) and login route
+ into the :term:`configurator` in ``authentication/tutorial/__init__.py``:
.. literalinclude:: authentication/tutorial/__init__.py
:linenos:
-#. Create a ``authentication/tutorial/security.py`` module that can find
- our user information by providing an *authentication policy callback*:
+#. Create an ``authentication/tutorial/security.py`` module that can find our
+ user information by providing an *authentication policy callback*:
.. literalinclude:: authentication/tutorial/security.py
:linenos:
@@ -69,7 +66,7 @@ Steps
:language: html
:linenos:
-#. Provide a login/logout box in ``authentication/tutorial/home.pt``
+#. Provide a login/logout box in ``authentication/tutorial/home.pt``:
.. literalinclude:: authentication/tutorial/home.pt
:language: html
@@ -95,39 +92,37 @@ Steps
Analysis
========
-Unlike many web frameworks, Pyramid includes a built-in but optional
-security model for authentication and authorization. This security
-system is intended to be flexible and support many needs. In this
-security model, authentication (who are you) and authorization (what
-are you allowed to do) are not just pluggable, but de-coupled. To learn
-one step at a time, we provide a system that identifies users and lets
-them log out.
-
-In this example we chose to use the bundled
-:ref:`AuthTktAuthenticationPolicy <authentication_module>`
-policy. We enabled it in our configuration and provided a
-ticket-signing secret in our INI file.
-
-Our view class grew a login view. When you reached it via a GET,
-it returned a login form. When reached via POST, it processed the
-username and password against the "groupfinder" callable that we
-registered in the configuration.
-
-In our template, we fetched the ``logged_in`` value from the view
-class. We use this to calculate the logged-in user,
-if any. In the template we can then choose to show a login link to
-anonymous visitors or a logout link to logged-in users.
-
-Extra Credit
+Unlike many web frameworks, Pyramid includes a built-in but optional security
+model for authentication and authorization. This security system is intended to
+be flexible and support many needs. In this security model, authentication (who
+are you) and authorization (what are you allowed to do) are not just pluggable,
+but de-coupled. To learn one step at a time, we provide a system that
+identifies users and lets them log out.
+
+In this example we chose to use the bundled :ref:`AuthTktAuthenticationPolicy
+<authentication_module>` policy. We enabled it in our configuration and
+provided a ticket-signing secret in our INI file.
+
+Our view class grew a login view. When you reached it via a ``GET`` request, it
+returned a login form. When reached via ``POST``, it processed the submitted
+username and password against the "groupfinder" callable that we registered in
+the configuration.
+
+In our template, we fetched the ``logged_in`` value from the view class. We use
+this to calculate the logged-in user, if any. In the template we can then
+choose to show a login link to anonymous visitors or a logout link to logged-in
+users.
+
+
+Extra credit
============
#. What is the difference between a user and a principal?
#. Can I use a database behind my ``groupfinder`` to look up principals?
-#. Once I am logged in, does any user-centric information get jammed
- onto each request? Use ``import pdb; pdb.set_trace()`` to answer
- this.
+#. Once I am logged in, does any user-centric information get jammed onto each
+ request? Use ``import pdb; pdb.set_trace()`` to answer this.
.. seealso:: See also :ref:`security_chapter`,
:ref:`AuthTktAuthenticationPolicy <authentication_module>`.
diff --git a/docs/quick_tutorial/authorization.rst b/docs/quick_tutorial/authorization.rst
index a4a12774b..58c1d2582 100644
--- a/docs/quick_tutorial/authorization.rst
+++ b/docs/quick_tutorial/authorization.rst
@@ -4,33 +4,35 @@
21: Protecting Resources With Authorization
===========================================
-Assign security statements to resources describing the permissions
-required to perform an operation.
+Assign security statements to resources describing the permissions required to
+perform an operation.
+
Background
==========
-Our application has URLs that allow people to add/edit/delete content
-via a web browser. Time to add security to the application. Let's
-protect our add/edit views to require a login (username of
-``editor`` and password of ``editor``). We will allow the other views
-to continue working without a password.
+Our application has URLs that allow people to add/edit/delete content via a web
+browser. Time to add security to the application. Let's protect our add/edit
+views to require a login (username of ``editor`` and password of ``editor``).
+We will allow the other views to continue working without a password.
+
Objectives
==========
-- Introduce the Pyramid concepts of authentication, authorization,
- permissions, and access control lists (ACLs)
+- Introduce the Pyramid concepts of authentication, authorization, permissions,
+ and access control lists (ACLs).
+
+- Make a :term:`root factory` that returns an instance of our class for the top
+ of the application.
-- Make a :term:`root factory` that returns an instance of our
- class for the top of the application
+- Assign security statements to our root resource.
-- Assign security statements to our root resource
+- Add a permissions predicate on a view.
-- Add a permissions predicate on a view
+- Provide a :term:`Forbidden view` to handle visiting a URL without adequate
+ permissions.
-- Provide a :term:`Forbidden view` to handle visiting a URL without
- adequate permissions
Steps
=====
@@ -42,14 +44,13 @@ Steps
$ cd ..; cp -r authentication authorization; cd authorization
$ $VENV/bin/pip install -e .
-#. Start by changing ``authorization/tutorial/__init__.py`` to
- specify a root factory to the :term:`configurator`:
+#. Start by changing ``authorization/tutorial/__init__.py`` to specify a root
+ factory to the :term:`configurator`:
.. literalinclude:: authorization/tutorial/__init__.py
:linenos:
-#. That means we need to implement
- ``authorization/tutorial/resources.py``
+#. That means we need to implement ``authorization/tutorial/resources.py``:
.. literalinclude:: authorization/tutorial/resources.py
:linenos:
@@ -70,48 +71,47 @@ Steps
#. If you are still logged in, click the "Log Out" link.
-#. Visit http://localhost:6543/howdy in a browser. You should be
- asked to login.
+#. Visit http://localhost:6543/howdy in a browser. You should be asked to
+ login.
+
Analysis
========
This simple tutorial step can be boiled down to the following:
-- A view can require a *permission* (``edit``)
+- A view can require a *permission* (``edit``).
-- The context for our view (the ``Root``) has an access control list
- (ACL)
+- The context for our view (the ``Root``) has an access control list (ACL).
-- This ACL says that the ``edit`` permission is available on ``Root``
- to the ``group:editors`` *principal*
+- This ACL says that the ``edit`` permission is available on ``Root`` to the
+ ``group:editors`` *principal*.
-- The registered ``groupfinder`` answers whether a particular user
- (``editor``) has a particular group (``group:editors``)
+- The registered ``groupfinder`` answers whether a particular user (``editor``)
+ has a particular group (``group:editors``).
-In summary: ``hello`` wants ``edit`` permission, ``Root`` says
+In summary, ``hello`` wants ``edit`` permission, ``Root`` says
``group:editors`` has ``edit`` permission.
-Of course, this only applies on ``Root``. Some other part of the site
-(a.k.a. *context*) might have a different ACL.
+Of course, this only applies on ``Root``. Some other part of the site (a.k.a.
+*context*) might have a different ACL.
+
+If you are not logged in and visit ``/howdy``, you need to get shown the login
+screen. How does Pyramid know what is the login page to use? We explicitly told
+Pyramid that the ``login`` view should be used by decorating the view with
+``@forbidden_view_config``.
-If you are not logged in and visit ``/howdy``, you need to get
-shown the login screen. How does Pyramid know what is the login page to
-use? We explicitly told Pyramid that the ``login`` view should be used
-by decorating the view with ``@forbidden_view_config``.
-Extra Credit
+Extra credit
============
-#. Do I have to put a ``renderer`` in my ``@forbidden_view_config``
- decorator?
+#. Do I have to put a ``renderer`` in my ``@forbidden_view_config`` decorator?
#. Perhaps you would like the experience of not having enough permissions
(forbidden) to be richer. How could you change this?
-#. Perhaps we want to store security statements in a database and
- allow editing via a browser. How might this be done?
+#. Perhaps we want to store security statements in a database and allow editing
+ via a browser. How might this be done?
-#. What if we want different security statements on different kinds of
- objects? Or on the same kinds of objects, but in different parts of a
- URL hierarchy?
+#. What if we want different security statements on different kinds of objects?
+ Or on the same kinds of objects, but in different parts of a URL hierarchy?
diff --git a/docs/quick_tutorial/databases.rst b/docs/quick_tutorial/databases.rst
index f9f548585..c8d87c180 100644
--- a/docs/quick_tutorial/databases.rst
+++ b/docs/quick_tutorial/databases.rst
@@ -4,37 +4,39 @@
19: Databases Using SQLAlchemy
==============================
-Store/retrieve data using the SQLAlchemy ORM atop the SQLite database.
+Store and retrieve data using the SQLAlchemy ORM atop the SQLite database.
+
Background
==========
-Our Pyramid-based wiki application now needs database-backed storage of
-pages. This frequently means a SQL database. The Pyramid community
-strongly supports the
-:ref:`SQLAlchemy <sqla:index_toplevel>` project and its
-:ref:`object-relational mapper (ORM) <sqla:ormtutorial_toplevel>`
-as a convenient, Pythonic way to interface to databases.
+Our Pyramid-based wiki application now needs database-backed storage of pages.
+This frequently means an SQL database. The Pyramid community strongly supports
+the :ref:`SQLAlchemy <sqla:index_toplevel>` project and its
+:ref:`object-relational mapper (ORM) <sqla:ormtutorial_toplevel>` as a
+convenient, Pythonic way to interface to databases.
-In this step we hook up SQLAlchemy to a SQLite database table,
-providing storage and retrieval for the wikipages in the previous step.
+In this step we hook up SQLAlchemy to a SQLite database table, providing
+storage and retrieval for the wiki pages in the previous step.
.. note::
- The ``alchemy`` scaffold is really helpful for getting a
- SQLAlchemy project going, including generation of the console
- script. Since we want to see all the decisions, we will forgo
- convenience in this tutorial and wire it up ourselves.
+ The ``alchemy`` scaffold is really helpful for getting an SQLAlchemy
+ project going, including generation of the console script. Since we want to
+ see all the decisions, we will forgo convenience in this tutorial, and wire
+ it up ourselves.
+
Objectives
==========
-- Store pages in SQLite by using SQLAlchemy models
+- Store pages in SQLite by using SQLAlchemy models.
-- Use SQLAlchemy queries to list/add/view/edit pages
+- Use SQLAlchemy queries to list/add/view/edit pages.
+
+- Provide a database-initialize command by writing a Pyramid *console script*
+ which can be run from the command line.
-- Provide a database-initialize command by writing a Pyramid *console
- script* which can be run from the command line
Steps
=====
@@ -45,31 +47,31 @@ Steps
$ cd ..; cp -r forms databases; cd databases
-#. We need to add some dependencies in ``databases/setup.py`` as well
- as an "entry point" for the command-line script:
+#. We need to add some dependencies in ``databases/setup.py`` as well as an
+ "entry point" for the command-line script:
.. literalinclude:: databases/setup.py
:linenos:
.. note::
- We aren't yet doing ``$VENV/bin/pip install -e .`` as we
- will change it later.
+ We aren't yet doing ``$VENV/bin/pip install -e .`` as we will change it
+ later.
-#. Our configuration file at ``databases/development.ini`` wires
- together some new pieces:
+#. Our configuration file at ``databases/development.ini`` wires together some
+ new pieces:
.. literalinclude:: databases/development.ini
:language: ini
-#. This engine configuration now needs to be read into the application
- through changes in ``databases/tutorial/__init__.py``:
+#. This engine configuration now needs to be read into the application through
+ changes in ``databases/tutorial/__init__.py``:
.. literalinclude:: databases/tutorial/__init__.py
:linenos:
-#. Make a command-line script at ``databases/tutorial/initialize_db.py``
- to initialize the database:
+#. Make a command-line script at ``databases/tutorial/initialize_db.py`` to
+ initialize the database:
.. literalinclude:: databases/tutorial/initialize_db.py
:linenos:
@@ -90,51 +92,49 @@ Steps
.. code-block:: bash
$ $VENV/bin/initialize_tutorial_db development.ini
- 2015-06-01 11:22:52,650 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
- 2015-06-01 11:22:52,650 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
- 2015-06-01 11:22:52,651 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
- 2015-06-01 11:22:52,651 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
- 2015-06-01 11:22:52,652 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages")
- 2015-06-01 11:22:52,652 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
- 2015-06-01 11:22:52,653 INFO [sqlalchemy.engine.base.Engine][MainThread]
+
+ 2016-04-16 13:01:33,055 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
+ 2016-04-16 13:01:33,055 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
+ 2016-04-16 13:01:33,056 INFO [sqlalchemy.engine.base.Engine][MainThread] SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
+ 2016-04-16 13:01:33,056 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
+ 2016-04-16 13:01:33,057 INFO [sqlalchemy.engine.base.Engine][MainThread] PRAGMA table_info("wikipages")
+ 2016-04-16 13:01:33,057 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
+ 2016-04-16 13:01:33,058 INFO [sqlalchemy.engine.base.Engine][MainThread]
CREATE TABLE wikipages (
- uid INTEGER NOT NULL,
- title TEXT,
- body TEXT,
- PRIMARY KEY (uid),
- UNIQUE (title)
+ uid INTEGER NOT NULL,
+ title TEXT,
+ body TEXT,
+ PRIMARY KEY (uid),
+ UNIQUE (title)
)
- 2015-06-01 11:22:52,653 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
- 2015-06-01 11:22:52,655 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT
- 2015-06-01 11:22:52,658 INFO [sqlalchemy.engine.base.Engine][MainThread] BEGIN (implicit)
- 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] INSERT INTO wikipages (title, body) VALUES (?, ?)
- 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] ('Root', '<p>Root</p>')
- 2015-06-01 11:22:52,659 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT
+ 2016-04-16 13:01:33,058 INFO [sqlalchemy.engine.base.Engine][MainThread] ()
+ 2016-04-16 13:01:33,059 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT
+ 2016-04-16 13:01:33,062 INFO [sqlalchemy.engine.base.Engine][MainThread] BEGIN (implicit)
+ 2016-04-16 13:01:33,062 INFO [sqlalchemy.engine.base.Engine][MainThread] INSERT INTO wikipages (title, body) VALUES (?, ?)
+ 2016-04-16 13:01:33,063 INFO [sqlalchemy.engine.base.Engine][MainThread] ('Root', '<p>Root</p>')
+ 2016-04-16 13:01:33,063 INFO [sqlalchemy.engine.base.Engine][MainThread] COMMIT
-#. With our data now driven by SQLAlchemy queries, we need to update
- our ``databases/tutorial/views.py``:
+#. With our data now driven by SQLAlchemy queries, we need to update our
+ ``databases/tutorial/views.py``:
.. literalinclude:: databases/tutorial/views.py
:linenos:
-#. Our tests in ``databases/tutorial/tests.py`` changed to include
- SQLAlchemy bootstrapping:
+#. Our tests in ``databases/tutorial/tests.py`` changed to include SQLAlchemy
+ bootstrapping:
.. literalinclude:: databases/tutorial/tests.py
:linenos:
-#. Run the tests in your package using ``nose``:
+#. Run the tests in your package using ``py.test``:
- .. code-block:: bash
-
- $ $VENV/bin/nosetests tutorial
- ..
- -----------------------------------------------------------------
- Ran 2 tests in 1.141s
+ .. code-block:: bash
- OK
+ $ $VENV/bin/py.test tutorial/tests.py -q
+ ..
+ 2 passed in 1.41 seconds
#. Run your Pyramid application with:
@@ -144,57 +144,55 @@ Steps
#. Open http://localhost:6543/ in a browser.
+
Analysis
========
-Let's start with the dependencies. We made the decision to use
-``SQLAlchemy`` to talk to our database. We also, though, installed
-``pyramid_tm`` and ``zope.sqlalchemy``. Why?
+Let's start with the dependencies. We made the decision to use ``SQLAlchemy``
+to talk to our database. We also, though, installed ``pyramid_tm`` and
+``zope.sqlalchemy``. Why?
Pyramid has a strong orientation towards support for ``transactions``.
-Specifically, you can install a transaction manager into your
-application either as middleware or a Pyramid "tween". Then,
-just before you return the response, all transaction-aware parts of
-your application are executed.
+Specifically, you can install a transaction manager into your application
+either as middleware or a Pyramid "tween". Then, just before you return the
+response, all transaction-aware parts of your application are executed.
-This means Pyramid view code usually doesn't manage transactions. If
-your view code or a template generates an error, the transaction manager
-aborts the transaction. This is a very liberating way to write code.
+This means Pyramid view code usually doesn't manage transactions. If your view
+code or a template generates an error, the transaction manager aborts the
+transaction. This is a very liberating way to write code.
The ``pyramid_tm`` package provides a "tween" that is configured in the
-``development.ini`` configuration file. That installs it. We then need
-a package that makes SQLAlchemy, and thus the RDBMS transaction manager,
-integrate with the Pyramid transaction manager. That's what
-``zope.sqlalchemy`` does.
+``development.ini`` configuration file. That installs it. We then need a
+package that makes SQLAlchemy, and thus the RDBMS transaction manager,
+integrate with the Pyramid transaction manager. That's what ``zope.sqlalchemy``
+does.
Where do we point at the location on disk for the SQLite file? In the
-configuration file. This lets consumers of our package change the
-location in a safe (non-code) way. That is, in configuration. This
-configuration-oriented approach isn't required in Pyramid; you can
-still make such statements in your ``__init__.py`` or some companion
-module.
-
-The ``initialize_tutorial_db`` is a nice example of framework support.
-You point your setup at the location of some ``[console_scripts]`` and
-these get generated into your virtual environment's ``bin`` directory. Our
-console script follows the pattern of being fed a configuration file
-with all the bootstrapping. It then opens SQLAlchemy and creates the
-root of the wiki, which also makes the SQLite file. Note the
-``with transaction.manager`` part that puts the work in the scope of a
-transaction, as we aren't inside a web request where this is done
-automatically.
-
-The ``models.py`` does a little bit extra work to hook up SQLAlchemy
-into the Pyramid transaction manager. It then declares the model for a
-``Page``.
+configuration file. This lets consumers of our package change the location in a
+safe (non-code) way. That is, in configuration. This configuration-oriented
+approach isn't required in Pyramid; you can still make such statements in your
+``__init__.py`` or some companion module.
+
+The ``initialize_tutorial_db`` is a nice example of framework support. You
+point your setup at the location of some ``[console_scripts]``, and these get
+generated into your virtual environment's ``bin`` directory. Our console script
+follows the pattern of being fed a configuration file with all the
+bootstrapping. It then opens SQLAlchemy and creates the root of the wiki, which
+also makes the SQLite file. Note the ``with transaction.manager`` part that
+puts the work in the scope of a transaction, as we aren't inside a web request
+where this is done automatically.
+
+The ``models.py`` does a little bit of extra work to hook up SQLAlchemy into
+the Pyramid transaction manager. It then declares the model for a ``Page``.
Our views have changes primarily around replacing our dummy
-dictionary-of-dictionaries data with proper database support: list the
-rows, add a row, edit a row, and delete a row.
+dictionary-of-dictionaries data with proper database support: list the rows,
+add a row, edit a row, and delete a row.
+
-Extra Credit
+Extra credit
============
-#. Why all this code? Why can't I just type 2 lines and have magic ensue?
+#. Why all this code? Why can't I just type two lines and have magic ensue?
#. Give a try at a button that deletes a wiki page.
diff --git a/docs/quick_tutorial/databases/sqltutorial.sqlite b/docs/quick_tutorial/databases/sqltutorial.sqlite
deleted file mode 100644
index b8bd856fd..000000000
--- a/docs/quick_tutorial/databases/sqltutorial.sqlite
+++ /dev/null
Binary files differ
diff --git a/docs/quick_tutorial/debugtoolbar.rst b/docs/quick_tutorial/debugtoolbar.rst
index 1f89cd319..aaf904390 100644
--- a/docs/quick_tutorial/debugtoolbar.rst
+++ b/docs/quick_tutorial/debugtoolbar.rst
@@ -6,31 +6,34 @@
Error handling and introspection using the ``pyramid_debugtoolbar`` add-on.
+
Background
==========
-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.
+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.
-``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.
Objectives
==========
-- Install and enable the toolbar to help during development
+- Install and enable the toolbar to help during development.
+
+- Explain Pyramid add-ons.
-- Explain Pyramid add-ons
+- Show how an add-on gets configured into your application.
-- Show how an add-on gets configured into your application
Steps
=====
-#. First we copy the results of the previous step, as well as install
- the ``pyramid_debugtoolbar`` package:
+#. First we copy the results of the previous step, as well as install the
+ ``pyramid_debugtoolbar`` package:
.. code-block:: bash
@@ -54,6 +57,7 @@ Steps
#. Open http://localhost:6543/ in your browser. See the handy
toolbar on the right.
+
Analysis
========
@@ -66,16 +70,16 @@ The ``pyramid_debugtoolbar`` Python package is also a Pyramid add-on, which
means we need to include its add-on configuration into our web application. We
could do this with imperative configuration in ``tutorial/__init__.py`` by
using ``config.include``. Pyramid also supports wiring in add-on configuration
-via our ``development.ini`` using ``pyramid.includes``. We use this to load
-the configuration for the debugtoolbar.
+via our ``development.ini`` using ``pyramid.includes``. We use this to load the
+configuration for the debugtoolbar.
You'll now see an attractive button on the right side of your browser, which
-you may click to provide introspective access to debugging information in a
-new browser tab. 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, there's no need to change code: you can remove it from
-``pyramid.includes`` in the relevant ``.ini`` configuration file (thus showing
-why configuration files are handy.)
+you may click to provide introspective access to debugging information in a new
+rowser tab. 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,
+there's no need to change code: you can remove it from ``pyramid.includes`` in
+the relevant ``.ini`` configuration file (thus showing why configuration files
+are handy).
Note that the toolbar injects a small amount of HTML/CSS into your app just
before the closing ``</body>`` tag in order to display itself. If you start to
@@ -85,13 +89,14 @@ temporarily.
.. seealso:: See also :ref:`pyramid_debugtoolbar <toolbar:overview>`.
+
Extra Credit
============
#. Why don't we add ``pyramid_debugtoolbar`` to the list of
``install_requires`` dependencies in ``debugtoolbar/setup.py``?
-#. Introduce a bug into your application: Change:
+#. Introduce a bug into your application. Change:
.. code-block:: python
@@ -105,7 +110,7 @@ Extra Credit
def hello_world(request):
return xResponse('<body><h1>Hello World!</h1></body>')
- Save, and visit http://localhost:6543/ again. Notice the nice
- traceback display. On the lowest line, click the "screen" icon to the
- right, and try typing the variable names ``request`` and ``Response``.
- What else can you discover?
+ Save, and visit http://localhost:6543/ again. Notice the nice traceback
+ display. On the lowest line, click the "screen" icon to the right, and try
+ typing the variable names ``request`` and ``Response``. What else can you
+ discover?
diff --git a/docs/quick_tutorial/forms.rst b/docs/quick_tutorial/forms.rst
index 023e7127f..6b29833bd 100644
--- a/docs/quick_tutorial/forms.rst
+++ b/docs/quick_tutorial/forms.rst
@@ -6,30 +6,30 @@
Schema-driven, autogenerated forms with validation.
+
Background
==========
-Modern web applications deal extensively with forms. Developers,
-though, have a wide range of philosophies about how frameworks should
-help them with their forms. As such, Pyramid doesn't directly bundle
-one particular form library. Instead there are a variety of form
-libraries that are easy to use in Pyramid.
+Modern web applications deal extensively with forms. Developers, though, have a
+wide range of philosophies about how frameworks should help them with their
+forms. As such, Pyramid doesn't directly bundle one particular form library.
+Instead there are a variety of form libraries that are easy to use in Pyramid.
-:ref:`Deform <deform:overview>`
-is one such library. In this step, we introduce Deform for our
-forms and validation. This also gives us :ref:`Colander <colander:overview>`
+:ref:`Deform <deform:overview>` is one such library. In this step, we introduce
+Deform for our forms. This also gives us :ref:`Colander <colander:overview>`
for schemas and validation.
-Deform is getting a facelift, with styling from Twitter Bootstrap and
-advanced widgets from popular JavaScript projects. The work began in
-``deform_bootstrap`` and is being merged into an update to Deform.
+Deform uses styling from Twitter Bootstrap and advanced widgets from popular
+JavaScript projects.
+
Objectives
==========
-- Make a schema using Colander, the companion to Deform
+- Make a schema using Colander, the companion to Deform.
+
+- Create a form with Deform and change our views to handle validation.
-- Create a form with Deform and change our views to handle validation
Steps
=====
@@ -40,8 +40,8 @@ Steps
$ cd ..; cp -r view_classes forms; cd forms
-#. Let's edit ``forms/setup.py`` to declare a dependency on Deform
- (which then pulls in Colander as a dependency:
+#. Let's edit ``forms/setup.py`` to declare a dependency on Deform (which then
+ pulls in Colander as a dependency:
.. literalinclude:: forms/setup.py
:linenos:
@@ -52,21 +52,19 @@ Steps
$ $VENV/bin/pip install -e .
-#. Register a static view in ``forms/tutorial/__init__.py`` for
- Deform's CSS/JS etc. as well as our demo wikipage scenario's
- views:
+#. Register a static view in ``forms/tutorial/__init__.py`` for Deform's CSS,
+ JavaScript, etc., as well as our demo wiki page's views:
.. literalinclude:: forms/tutorial/__init__.py
:linenos:
-#. Implement the new views, as well as the form schemas and some
- dummy data, in ``forms/tutorial/views.py``:
+#. Implement the new views, as well as the form schemas and some dummy data, in
+ ``forms/tutorial/views.py``:
.. literalinclude:: forms/tutorial/views.py
:linenos:
-#. A template for the top of the "wiki" in
- ``forms/tutorial/wiki_view.pt``:
+#. A template for the top of the "wiki" in ``forms/tutorial/wiki_view.pt``:
.. literalinclude:: forms/tutorial/wiki_view.pt
:language: html
@@ -79,13 +77,21 @@ Steps
:language: html
:linenos:
-#. Finally, a template at ``forms/tutorial/wikipage_view.pt``
- for viewing a wiki page:
+#. Finally, a template at ``forms/tutorial/wikipage_view.pt`` for viewing a
+ wiki page:
.. literalinclude:: forms/tutorial/wikipage_view.pt
:language: html
:linenos:
+#. Run the tests:
+
+ .. code-block:: bash
+
+ $ $VENV/bin/py.test tutorial/tests.py -q
+ ..
+ 2 passed in 0.45 seconds
+
#. Run your Pyramid application with:
.. code-block:: bash
@@ -98,51 +104,50 @@ Steps
Analysis
========
-This step helps illustrate the utility of asset specifications for
-static assets. We have an outside package called Deform with static
-assets which need to be published. We don't have to know where on disk
-it is located. We point at the package, then the path inside the package.
-
-We just need to include a call to ``add_static_view`` to make that
-directory available at a URL. For Pyramid-specific packages,
-Pyramid provides a facility (``config.include()``) which even makes
-that unnecessary for consumers of a package. (Deform is not specific to
-Pyramid.)
-
-Our forms have rich widgets which need the static CSS and JS just
-mentioned. Deform has a :term:`resource registry` which allows widgets
-to specify which JS and CSS are needed. Our ``wikipage_addedit.pt``
-template shows how we iterated over that data to generate markup that
-includes the needed resources.
-
-Our add and edit views use a pattern called *self-posting forms*.
-Meaning, the same URL is used to ``GET`` the form as is used to
-``POST`` the form. The route, the view, and the template are the same
-whether you are walking up to it the first time or you clicked a button.
-
-Inside the view we do ``if 'submit' in self.request.params:`` to see if
-this form was a ``POST`` where the user clicked on a particular button
+This step helps illustrate the utility of asset specifications for static
+assets. We have an outside package called Deform with static assets which need
+to be published. We don't have to know where on disk it is located. We point at
+the package, then the path inside the package.
+
+We just need to include a call to ``add_static_view`` to make that directory
+available at a URL. For Pyramid-specific packages, Pyramid provides a facility
+(``config.include()``) which even makes that unnecessary for consumers of a
+package. (Deform is not specific to Pyramid.)
+
+Our forms have rich widgets which need the static CSS and JavaScript just
+mentioned. Deform has a :term:`resource registry` which allows widgets to
+specify which JavaScript and CSS are needed. Our ``wikipage_addedit.pt``
+template shows how we iterated over that data to generate markup that includes
+the needed resources.
+
+Our add and edit views use a pattern called *self-posting forms*. Meaning, the
+same URL is used to ``GET`` the form as is used to ``POST`` the form. The
+route, the view, and the template are the same URL whether you are walking up
+to it for the first time or you clicked a button.
+
+Inside the view we do ``if 'submit' in self.request.params:`` to see if this
+form was a ``POST`` where the user clicked on a particular button
``<input name="submit">``.
The form controller then follows a typical pattern:
-- If you are doing a GET, skip over and just return the form
+- If you are doing a ``GET``, skip over and just return the form.
+
+- If you are doing a ``POST``, validate the form contents.
-- If you are doing a POST, validate the form contents
+- If the form is invalid, bail out by re-rendering the form with the supplied
+ ``POST`` data.
-- If the form is invalid, bail out by re-rendering the form with the
- supplied ``POST`` data
+- If the validation succeeded, perform some action and issue a redirect via
+ ``HTTPFound``.
-- If the validation succeeded, perform some action and issue a
- redirect via ``HTTPFound``.
+We are, in essence, writing our own form controller. Other Pyramid-based
+systems, including ``pyramid_deform``, provide a form-centric view class which
+automates much of this branching and routing.
-We are, in essence, writing our own form controller. Other
-Pyramid-based systems, including ``pyramid_deform``, provide a
-form-centric view class which automates much of this branching and
-routing.
-Extra Credit
+Extra credit
============
-#. Give a try at a button that goes to a delete view for a
- particular wiki page.
+#. Give a try at a button that goes to a delete view for a particular wiki
+ page.
diff --git a/docs/quick_tutorial/functional_testing.rst b/docs/quick_tutorial/functional_testing.rst
index b8aa7e87d..33793578a 100644
--- a/docs/quick_tutorial/functional_testing.rst
+++ b/docs/quick_tutorial/functional_testing.rst
@@ -6,30 +6,33 @@
Write end-to-end full-stack testing using ``webtest``.
+
Background
==========
-Unit tests are a common and popular approach to test-driven development
-(TDD). In web applications, though, the templating and entire apparatus
-of a web site are important parts of the delivered quality. We'd like a
-way to test these.
+Unit tests are a common and popular approach to test-driven development (TDD).
+In web applications, though, the templating and entire apparatus of a web site
+are important parts of the delivered quality. We'd like a way to test these.
+
+`WebTest <http://docs.pylonsproject.org/projects/webtest/en/latest/>`_ is a
+Python package that does functional testing. With WebTest you can write tests
+which simulate a full HTTP request against a WSGI application, then test the
+information in the response. For speed purposes, WebTest skips the
+setup/teardown of an actual HTTP server, providing tests that run fast enough
+to be part of TDD.
-WebTest is a Python package that does functional testing. With WebTest
-you can write tests which simulate a full HTTP request against a WSGI
-application, then test the information in the response. For speed
-purposes, WebTest skips the setup/teardown of an actual HTTP server,
-providing tests that run fast enough to be part of TDD.
Objectives
==========
-- Write a test which checks the contents of the returned HTML
+- Write a test which checks the contents of the returned HTML.
+
Steps
=====
-#. First we copy the results of the previous step, as well as install
- the ``webtest`` package:
+#. First we copy the results of the previous step, as well as install the
+ ``webtest`` package:
.. code-block:: bash
@@ -43,31 +46,28 @@ Steps
.. literalinclude:: functional_testing/tutorial/tests.py
:linenos:
- Be sure this file is not executable, or ``nosetests`` may not
- include your tests.
+ Be sure this file is not executable, or ``pytest`` may not include your
+ tests.
#. Now run the tests:
.. code-block:: bash
+ $ $VENV/bin/py.test tutorial/tests.py -q
+ ..
+ 2 passed in 0.25 seconds
- $ $VENV/bin/nosetests tutorial
- .
- ----------------------------------------------------------------------
- Ran 2 tests in 0.141s
-
- OK
Analysis
========
-We now have the end-to-end testing we were looking for. WebTest lets us
-simply extend our existing ``nose``-based test approach with functional
-tests that are reported in the same output. These new tests not only
-cover our templating, but they didn't dramatically increase the
-execution time of our tests.
+We now have the end-to-end testing we were looking for. WebTest lets us simply
+extend our existing ``pytest``-based test approach with functional tests that
+are reported in the same output. These new tests not only cover our templating,
+but they didn't dramatically increase the execution time of our tests.
+
-Extra Credit
+Extra credit
============
#. Why do our functional tests use ``b''``?
diff --git a/docs/quick_tutorial/hello_world.rst b/docs/quick_tutorial/hello_world.rst
index fb661e9c5..4e35da7bb 100644
--- a/docs/quick_tutorial/hello_world.rst
+++ b/docs/quick_tutorial/hello_world.rst
@@ -4,40 +4,40 @@
01: Single-File Web Applications
================================
-What's the simplest way to get started in Pyramid? A single-file module.
-No Python packages, no ``pip install -e .``, no other machinery.
+What's the simplest way to get started in Pyramid? A single-file module. No
+Python packages, no ``pip install -e .``, no other machinery.
+
Background
==========
-Microframeworks are all the rage these days. "Microframework" is a
-marketing term, not a technical one. They have a low mental overhead:
-they do so little, the only things you have to worry about are *your
-things*.
+Microframeworks are all the rage these days. "Microframework" is a marketing
+term, not a technical one. They have a low mental overhead: they do so little,
+the only things you have to worry about are *your things*.
+
+Pyramid is special because it can act as a single-file module microframework.
+You can have a single Python file that can be executed directly by Python. But
+Pyramid also provides facilities to scale to the largest of applications.
-Pyramid is special because it can act as a single-file module
-microframework. You can have a single Python file that can be executed
-directly by Python. But Pyramid also provides facilities to scale to
-the largest of applications.
+Python has a standard called :term:`WSGI` that defines how Python web
+applications plug into standard servers, getting passed incoming requests, and
+returning responses. Most modern Python web frameworks obey an "MVC"
+(model-view-controller) application pattern, where the data in the model has a
+view that mediates interaction with outside systems.
-Python has a standard called :term:`WSGI` that defines how
-Python web applications plug into standard servers, getting passed
-incoming requests and returning responses. Most modern Python web
-frameworks obey an "MVC" (model-view-controller) application pattern,
-where the data in the model has a view that mediates interaction with
-outside systems.
+In this step we'll see a brief glimpse of WSGI servers, WSGI applications,
+requests, responses, and views.
-In this step we'll see a brief glimpse of WSGI servers, WSGI
-applications, requests, responses, and views.
Objectives
==========
-- Get a running Pyramid web application, as simply as possible
+- Get a running Pyramid web application, as simply as possible.
+
+- Use that as a well-understood base for adding each unit of complexity.
-- Use that as a well-understood base for adding each unit of complexity
+- Initial exposure to WSGI apps, requests, views, and responses.
-- Initial exposure to WSGI apps, requests, views, and responses
Steps
=====
@@ -64,30 +64,29 @@ Steps
#. Open http://localhost:6543/ in your browser.
+
Analysis
========
-New to Python web programming? If so, some lines in module merit
+New to Python web programming? If so, some lines in the module merit
explanation:
-#. *Line 11*. The ``if __name__ == '__main__':`` is Python's way of
- saying "Start here when running from the command line", rather than
- when this module is imported.
+#. *Line 11*. The ``if __name__ == '__main__':`` is Python's way of saying,
+ "Start here when running from the command line", rather than when this
+ module is imported.
+
+#. *Lines 12-14*. Use Pyramid's :term:`configurator` to connect :term:`view`
+ code to a particular URL :term:`route`.
-#. *Lines 12-14*. Use Pyramid's :term:`configurator` to connect
- :term:`view` code to a particular URL :term:`route`.
+#. *Lines 6-8*. Implement the view code that generates the :term:`response`.
-#. *Lines 6-8*. Implement the view code that generates the
- :term:`response`.
+#. *Lines 15-17*. Publish a :term:`WSGI` app using an HTTP server.
-#. *Lines 15-17*. 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
+:ref:`configuration_narr` is a central idea in Pyramid, one that we will
+revisit regularly in this *Quick Tutorial*.
-As shown in this example, the :term:`configurator` plays a
-central role in Pyramid development. Building an application from
-loosely-coupled parts via :ref:`configuration_narr` is a
-central idea in Pyramid, one that we will revisit regularly in this
-*Quick Tour*.
Extra Credit
============
@@ -106,9 +105,9 @@ Extra Credit
#. What happens if you return a string of HTML? A sequence of integers?
-#. Put something invalid, such as ``print xyz``, in the view function.
- Kill your ``python app.py`` with ``cntrl-c`` and restart,
- then reload your browser. See the exception in the console?
+#. Put something invalid, such as ``print xyz``, in the view function. Kill
+ your ``python app.py`` with ``ctrl-C`` and restart, then reload your
+ browser. See the exception in the console?
-#. The ``GI`` in ``WSGI`` stands for "Gateway Interface". What web
- standard is this modelled after?
+#. The ``GI`` in ``WSGI`` stands for "Gateway Interface". What web standard is
+ this modelled after?
diff --git a/docs/quick_tutorial/index.rst b/docs/quick_tutorial/index.rst
index 9373fe38a..29b4d8fb7 100644
--- a/docs/quick_tutorial/index.rst
+++ b/docs/quick_tutorial/index.rst
@@ -4,12 +4,12 @@
Quick Tutorial for Pyramid
==========================
-Pyramid is a web framework for Python 2 and 3. This tutorial gives a
-Python 3/2-compatible, high-level tour of the major features.
+Pyramid is a web framework for Python 2 and 3. This tutorial gives a Python
+3/2-compatible, high-level tour of the major features.
-This hands-on tutorial covers "a little about a lot": practical
-introductions to the most common facilities. Fun, fast-paced, and most
-certainly not aimed at experts of the Pyramid web framework.
+This hands-on tutorial covers "a little about a lot": practical introductions
+to the most common facilities. Fun, fast-paced, and most certainly not aimed at
+experts of the Pyramid web framework.
Contents
========
diff --git a/docs/quick_tutorial/ini.rst b/docs/quick_tutorial/ini.rst
index 0aed304df..fba5ce29e 100644
--- a/docs/quick_tutorial/ini.rst
+++ b/docs/quick_tutorial/ini.rst
@@ -7,28 +7,30 @@
Use Pyramid's ``pserve`` command with a ``.ini`` configuration file for
simpler, better application running.
+
Background
==========
-Pyramid has a first-class concept of
-:ref:`configuration <configuration_narr>` distinct from code.
-This approach is optional, but its presence makes it distinct from
-other Python web frameworks. It taps into Python's ``setuptools``
-library, which establishes conventions for installing and providing
-"entry points" for Python projects. Pyramid uses an entry point to
-let a Pyramid application know where to find the WSGI app.
+Pyramid has a first-class concept of :ref:`configuration <configuration_narr>`
+distinct from code. This approach is optional, but its presence makes it
+distinct from other Python web frameworks. It taps into Python's ``setuptools``
+library, which establishes conventions for installing and providing "entry
+points" for Python projects. Pyramid uses an entry point to let a Pyramid
+application know where to find the WSGI app.
+
Objectives
==========
-- Modify our ``setup.py`` to have an entry point telling Pyramid the
- location of the WSGI app
+- Modify our ``setup.py`` to have an entry point telling Pyramid the location
+ of the WSGI app.
+
+- Create an application driven by an ``.ini`` file.
-- Create an application driven by a ``.ini`` file
+- Start the application with Pyramid's ``pserve`` command.
-- Startup the application with Pyramid's ``pserve`` command
+- Move code into the package's ``__init__.py``.
-- Move code into the package's ``__init__.py``
Steps
=====
@@ -39,14 +41,14 @@ Steps
$ cd ..; cp -r package ini; cd ini
-#. Our ``ini/setup.py`` needs a setuptools "entry point" in the
- ``setup()`` function:
+#. Our ``ini/setup.py`` needs a setuptools "entry point" in the ``setup()``
+ function:
.. literalinclude:: ini/setup.py
:linenos:
-#. We can now install our project, thus generating (or re-generating) an
- "egg" at ``ini/tutorial.egg-info``:
+#. We can now install our project, thus generating (or re-generating) an "egg"
+ at ``ini/tutorial.egg-info``:
.. code-block:: bash
@@ -58,8 +60,8 @@ Steps
:language: ini
:linenos:
-#. We can refactor our startup code from the previous step's ``app.py``
- into ``ini/tutorial/__init__.py``:
+#. We can refactor our startup code from the previous step's ``app.py`` into
+ ``ini/tutorial/__init__.py``:
.. literalinclude:: ini/tutorial/__init__.py
:linenos:
@@ -81,27 +83,26 @@ Steps
Analysis
========
-Our ``development.ini`` file is read by ``pserve`` and serves to
-bootstrap our application. Processing then proceeds as described in
-the Pyramid chapter on
+Our ``development.ini`` file is read by ``pserve`` and serves to bootstrap our
+application. Processing then proceeds as described in the Pyramid chapter on
:ref:`application startup <startup_chapter>`:
-- ``pserve`` looks for ``[app:main]`` and finds ``use = egg:tutorial``
+- ``pserve`` looks for ``[app:main]`` and finds ``use = egg:tutorial``.
-- The projects's ``setup.py`` has defined an "entry point" (lines 9-12)
- for the project "main" entry point of ``tutorial:main``
+- The projects's ``setup.py`` has defined an "entry point" (lines 9-12) for the
+ project's "main" entry point of ``tutorial:main``.
-- The ``tutorial`` package's ``__init__`` has a ``main`` function
+- The ``tutorial`` package's ``__init__`` has a ``main`` function.
-- This function is invoked, with the values from certain ``.ini``
- sections passed in
+- This function is invoked, with the values from certain ``.ini`` sections
+ passed in.
The ``.ini`` file is also used for two other functions:
-- *Configuring the WSGI server*. ``[server:main]`` wires up the choice of
- which WSGI *server* for your WSGI *application*. In this case, we are using
- ``wsgiref`` bundled in the Python library. It also wires up the *port
- number*: ``port = 6543`` tells ``wsgiref`` to listen on port 6543.
+- *Configuring the WSGI server*. ``[server:main]`` wires up the choice of which
+ WSGI *server* for your WSGI *application*. In this case, we are using
+ ``wsgiref`` bundled in the Python library. It also wires up the *port
+ number*: ``port = 6543`` tells ``wsgiref`` to listen on port 6543.
- *Configuring Python logging*. Pyramid uses Python standard logging, which
needs a number of configuration values. The ``.ini`` serves this function.
@@ -109,27 +110,27 @@ The ``.ini`` file is also used for two other functions:
request.
We moved our startup code from ``app.py`` to the package's
-``tutorial/__init__.py``. This isn't necessary,
-but it is a common style in Pyramid to take the WSGI app bootstrapping
-out of your module's code and put it in the package's ``__init__.py``.
+``tutorial/__init__.py``. This isn't necessary, but it is a common style in
+Pyramid to take the WSGI app bootstrapping out of your module's code and put it
+in the package's ``__init__.py``.
+
+The ``pserve`` application runner has a number of command-line arguments and
+options. We are using ``--reload`` which tells ``pserve`` to watch the
+filesystem for changes to relevant code (Python files, the INI file, etc.) and,
+when something changes, restart the application. Very handy during development.
-The ``pserve`` application runner has a number of command-line arguments
-and options. We are using ``--reload`` which tells ``pserve`` to watch
-the filesystem for changes to relevant code (Python files, the INI file,
-etc.) and, when something changes, restart the application. Very handy
-during development.
Extra Credit
============
-#. If you don't like configuration and/or ``.ini`` files,
- could you do this yourself in Python code?
+#. If you don't like configuration and/or ``.ini`` files, could you do this
+ yourself in Python code?
-#. Can we have multiple ``.ini`` configuration files for a project? Why
- might you want to do that?
+#. Can we have multiple ``.ini`` configuration files for a project? Why might
+ you want to do that?
-#. The entry point in ``setup.py`` didn't mention ``__init__.py`` when
- it declared ``tutorial:main`` function. Why not?
+#. The entry point in ``setup.py`` didn't mention ``__init__.py`` when it
+ declared ``tutorial:main`` function. Why not?
#. What is the purpose of ``**settings``? What does the ``**`` signify?
@@ -139,4 +140,3 @@ Extra Credit
:ref:`what_is_this_pserve_thing`,
:ref:`environment_chapter`,
:ref:`paste_chapter`
-
diff --git a/docs/quick_tutorial/jinja2.rst b/docs/quick_tutorial/jinja2.rst
index 6b9d5feba..2fc68827b 100644
--- a/docs/quick_tutorial/jinja2.rst
+++ b/docs/quick_tutorial/jinja2.rst
@@ -4,24 +4,26 @@
12: 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,
-used in Flask and modeled 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.
+We just said Pyramid doesn't prefer one templating language over another. Time
+to prove it. Jinja2 is a popular templating system, used in Flask and modeled
+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.
+
Objectives
==========
-- Show Pyramid's support for different templating systems
+- Show Pyramid's support for different templating systems.
+
+- Learn about installing Pyramid add-ons.
-- Learn about installing Pyramid add-ons
Steps
=====
-#. In this step let's start by copying the ``view_class`` step's
- directory, and then installing the ``pyramid_jinja2`` add-on.
+#. In this step let's start by copying the ``view_class`` step's directory,
+ and then installing the ``pyramid_jinja2`` add-on.
.. code-block:: bash
@@ -29,8 +31,7 @@ Steps
$ $VENV/bin/pip install -e .
$ $VENV/bin/pip install pyramid_jinja2
-#. We need to include ``pyramid_jinja2`` in
- ``jinja2/tutorial/__init__.py``:
+#. We need to include ``pyramid_jinja2`` in ``jinja2/tutorial/__init__.py``:
.. literalinclude:: jinja2/tutorial/__init__.py
:linenos:
@@ -49,7 +50,9 @@ Steps
.. code-block:: bash
- $ $VENV/bin/nosetests tutorial
+ $ $VENV/bin/py.test tutorial/tests.py -q
+ ....
+ 4 passed in 0.40 seconds
#. Run your Pyramid application with:
@@ -59,30 +62,30 @@ Steps
#. Open http://localhost:6543/ in your browser.
+
Analysis
========
-Getting a Pyramid add-on into Pyramid is simple. First you use normal
-Python package installation tools to install the add-on package into
-your Python. You then tell Pyramid's configurator to run the setup code
+Getting a Pyramid add-on into Pyramid is simple. First you use normal Python
+package installation tools to install the add-on package into your Python
+virtual environment. You then tell Pyramid's configurator to run the setup code
in the add-on. In this case the setup code told Pyramid to make a new
"renderer" available that looked for ``.jinja2`` file extensions.
-Our view code stayed largely the same. We simply changed the file
-extension on the renderer. For the template, the syntax for Chameleon
-and Jinja2's basic variable insertion is very similar.
+Our view code stayed largely the same. We simply changed the file extension on
+the renderer. For the template, the syntax for Chameleon and Jinja2's basic
+variable insertion is very similar.
+
-Extra Credit
+Extra credit
============
-#. Our project now depends on ``pyramid_jinja2``. We installed that
- dependency manually. What is another way we could have made the
- association?
+#. Our project now depends on ``pyramid_jinja2``. We installed that dependency
+ manually. What is another way we could have made the association?
#. We used ``config.include`` which is an imperative configuration to get the
- :term:`Configurator` to load ``pyramid_jinja2``'s configuration.
- What is another way could include it into the config?
+ :term:`Configurator` to load ``pyramid_jinja2``'s configuration. What is
+ another way could include it into the config?
-.. seealso:: `Jinja2 homepage <http://jinja.pocoo.org/>`_,
- and
+.. seealso:: `Jinja2 homepage <http://jinja.pocoo.org/>`_, and
:ref:`pyramid_jinja2 Overview <jinja2:overview>`
diff --git a/docs/quick_tutorial/json.rst b/docs/quick_tutorial/json.rst
index 49421829b..ff153d2b5 100644
--- a/docs/quick_tutorial/json.rst
+++ b/docs/quick_tutorial/json.rst
@@ -1,27 +1,28 @@
.. _qtut_json:
========================================
-14: Ajax Development With JSON Renderers
+14: AJAX Development With JSON Renderers
========================================
-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*.
+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*.
+
Background
==========
-As we saw in :doc:`templating`, view declarations can specify a
-renderer. Output from the view is then run through the renderer,
-which generates and returns the ``Response``. We first used a Chameleon
-renderer, then a Jinja2 renderer.
+As we saw in :doc:`templating`, view declarations can specify a renderer.
+Output from the view is then run through the renderer, which generates and
+returns the response. We first used a Chameleon renderer, then a Jinja2
+renderer.
+
+Renderers aren't limited, however, to templates that generate HTML. Pyramid
+supplies a JSON renderer which takes Python data, serializes it to JSON, and
+performs some other functions such as setting the content type. In fact you can
+write your own renderer (or extend a built-in renderer) containing custom logic
+for your unique application.
-Renderers aren't limited, however, to templates that generate HTML.
-Pyramid supplies a JSON renderer which takes Python data,
-serializes it to JSON, and performs some other functions such as
-setting the content type. In fact, you can write your own renderer (or
-extend a built-in renderer) containing custom logic for your unique
-application.
Steps
=====
@@ -33,20 +34,18 @@ Steps
$ cd ..; cp -r view_classes json; cd json
$ $VENV/bin/pip install -e .
-#. We add a new route for ``hello_json`` in
- ``json/tutorial/__init__.py``:
+#. We add a new route for ``hello_json`` in ``json/tutorial/__init__.py``:
.. literalinclude:: json/tutorial/__init__.py
:linenos:
-#. Rather than implement a new view, we will "stack" another decorator
- on the ``hello`` view in ``views.py``:
+#. Rather than implement a new view, we will "stack" another decorator on the
+ ``hello`` view in ``views.py``:
.. literalinclude:: json/tutorial/views.py
:linenos:
-#. We need a new functional test at the end of
- ``json/tutorial/tests.py``:
+#. We need a new functional test at the end of ``json/tutorial/tests.py``:
.. literalinclude:: json/tutorial/tests.py
:linenos:
@@ -55,7 +54,10 @@ Steps
.. code-block:: bash
- $ $VENV/bin/nosetests tutorial
+ $ $VENV/bin/py.test tutorial/tests.py -q
+ .....
+ 5 passed in 0.47 seconds
+
#. Run your Pyramid application with:
@@ -63,40 +65,39 @@ Steps
$ $VENV/bin/pserve development.ini --reload
-#. Open http://localhost:6543/howdy.json in your browser and you
- will see the resulting JSON response.
+#. Open http://localhost:6543/howdy.json in your browser and you will see the
+ resulting JSON response.
+
Analysis
========
-Earlier we changed our view functions and methods to return Python
-data. This change to a data-oriented view layer made test writing
-easier, decoupling the templating from the view logic.
+Earlier we changed our view functions and methods to return Python data. This
+change to a data-oriented view layer made test writing easier, decoupling the
+templating from the view logic.
-Since Pyramid has a JSON renderer as well as the templating renderers,
-it is an easy step to return JSON. In this case we kept the exact same
-view and arranged to return a JSON encoding of the view data. We did
-this by:
+Since Pyramid has a JSON renderer as well as the templating renderers, it is an
+easy step to return JSON. In this case we kept the exact same view and arranged
+to return a JSON encoding of the view data. We did this by:
-- Adding a route to map ``/howdy.json`` to a route name
+- Adding a route to map ``/howdy.json`` to a route name.
-- Providing a ``@view_config`` that associated that route name with an
- existing view
+- Providing a ``@view_config`` that associated that route name with an existing
+ view.
-- *overriding* the view defaults in the view config that mentions the
- ``hello_json`` route, so that when the route is matched, we use the JSON
+- *Overriding* the view defaults in the view config that mentions the
+ ``hello_json`` route, so that when the route is matched, we use the JSON
renderer rather than the ``home.pt`` template renderer that would otherwise
be used.
-In fact, for pure Ajax-style web applications, we could re-use the existing
-route by using Pyramid's view predicates to match on the
-``Accepts:`` header sent by modern Ajax implementation.
+In fact, for pure AJAX-style web applications, we could re-use the existing
+route by using Pyramid's view predicates to match on the ``Accepts:`` header
+sent by modern AJAX implementations.
-Pyramid's JSON renderer uses the base Python JSON encoder,
-thus inheriting its strengths and weaknesses. For example,
-Python can't natively JSON encode DateTime objects. There are a number
-of solutions for this in Pyramid, including extending the JSON renderer
-with a custom renderer.
+Pyramid's JSON renderer uses the base Python JSON encoder, thus inheriting its
+strengths and weaknesses. For example, Python can't natively JSON encode
+DateTime objects. There are a number of solutions for this in Pyramid,
+including extending the JSON renderer with a custom renderer.
.. seealso:: :ref:`views_which_use_a_renderer`,
:ref:`json_renderer`, and
diff --git a/docs/quick_tutorial/logging.rst b/docs/quick_tutorial/logging.rst
index 556a09bf0..cbbf7860e 100644
--- a/docs/quick_tutorial/logging.rst
+++ b/docs/quick_tutorial/logging.rst
@@ -4,28 +4,30 @@
16: Collecting Application Info With Logging
============================================
-Capture debugging and error output from your web applications using
-standard Python logging.
+Capture debugging and error output from your web applications using standard
+Python logging.
+
Background
==========
-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 problems when other people use the site. We
-need *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 problems 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`` has 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.
-Fortunately Pyramid uses the normal Python approach to logging. The
-scaffold generated in your ``development.ini`` has 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.
Objectives
==========
-- Inspect the configuration setup used for logging
+- Inspect the configuration setup used for logging.
+
+- Add logging statements to your view code.
-- Add logging statements to your view code
Steps
=====
@@ -42,8 +44,8 @@ Steps
.. literalinclude:: logging/tutorial/views.py
:linenos:
-#. Finally let's edit ``development.ini`` configuration file
- to enable logging for our Pyramid application:
+#. Finally let's edit ``development.ini`` configuration file to enable logging
+ for our Pyramid application:
.. literalinclude:: logging/development.ini
:language: ini
@@ -52,7 +54,9 @@ Steps
.. code-block:: bash
- $ $VENV/bin/nosetests tutorial
+ $ $VENV/bin/py.test tutorial/tests.py -q
+ ....
+ 4 passed in 0.41 seconds
#. Run your Pyramid application with:
@@ -60,19 +64,21 @@ Steps
$ $VENV/bin/pserve development.ini --reload
-#. Open http://localhost:6543/ and http://localhost:6543/howdy
- in your browser. Note, both in the console and in the debug
- toolbar, the message that you logged.
+#. Open http://localhost:6543/ and http://localhost:6543/howdy in your browser.
+ Note, both in the console and in the debug toolbar, the message that you
+ logged.
+
Analysis
========
-In our configuration file ``development.ini``, our ``tutorial`` Python
-package 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::
+In our configuration file ``development.ini``, our ``tutorial`` Python package
+is set up 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:
+
+.. code-block:: text
- 2013-08-09 10:42:42,968 DEBUG [tutorial.views][MainThread] In home view
+ 2013-08-09 10:42:42,968 DEBUG [tutorial.views][MainThread] In home view
Also, if you have configured your Pyramid application to use the
``pyramid_debugtoolbar``, logging statements appear in one of its menus.
diff --git a/docs/quick_tutorial/more_view_classes.rst b/docs/quick_tutorial/more_view_classes.rst
index fb97cceb2..30234ea2e 100644
--- a/docs/quick_tutorial/more_view_classes.rst
+++ b/docs/quick_tutorial/more_view_classes.rst
@@ -6,48 +6,49 @@
Group views into a class, sharing configuration, state, and logic.
+
Background
==========
-As part of its mission to help build more ambitious web applications,
-Pyramid provides many more features for views and view classes.
+As part of its mission to help build more ambitious web applications, Pyramid
+provides many more features for views and view classes.
+
+The Pyramid documentation discusses views as a Python "callable". This callable
+can be a function, an object with a ``__call__``, or a Python class. In this
+last case, methods on the class can be decorated with ``@view_config`` to
+register the class methods with the :term:`configurator` as a view.
-The Pyramid documentation discusses views as a Python "callable". This
-callable can be a function, an object with an ``__call__``,
-or a Python class. In this last case, methods on the class can be
-decorated with ``@view_config`` to register the class methods with the
-:term:`configurator` as a view.
+At first, our views were 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:
-At first, our views were 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.
-- Group views
+- Centralize some repetitive defaults.
-- Centralize some repetitive defaults
+- Share some state and helpers.
-- Share some state and helpers
+Pyramid views have :ref:`view predicates <view_configuration_parameters>` that
+determine which view is matched to a request, based on factors such as the
+request method, the form parameters, and so on. These predicates provide many
+axes of flexibility.
-Pyramid views have :ref:`view predicates <view_configuration_parameters>`
-that determine which view is matched to a request, based on factors
-such as the request method, the form parameters, etc. These predicates
-provide many axes of flexibility.
+The following shows a simple example with four operations: view a home page
+which leads to a form, save a change, and press the delete button.
-The following shows a simple example with four operations:
-view a home page which leads to a form, save a change,
-and press the delete button.
Objectives
==========
-- Group related views into a view class
+- Group related views into a view class.
-- Centralize configuration with class-level ``@view_defaults``
+- Centralize configuration with class-level ``@view_defaults``.
-- Dispatch one route/URL to multiple views based on request data
+- Dispatch one route/URL to multiple views based on request data.
+
+- Share states and logic between views and templates via the view class.
-- Share states and logic between views and templates via the view class
Steps
=====
@@ -71,8 +72,7 @@ Steps
.. literalinclude:: more_view_classes/tutorial/views.py
:linenos:
-#. Our primary view needs a template at
- ``more_view_classes/tutorial/home.pt``:
+#. Our primary view needs a template at ``more_view_classes/tutorial/home.pt``:
.. literalinclude:: more_view_classes/tutorial/home.pt
:language: html
@@ -105,12 +105,9 @@ Steps
.. code-block:: bash
- $ $VENV/bin/nosetests tutorial
- .
- ----------------------------------------------------------------------
- Ran 2 tests in 0.248s
-
- OK
+ $ $VENV/bin/py.test tutorial/tests.py -q
+ ..
+ 2 passed in 0.40 seconds
#. Run your Pyramid application with:
@@ -118,29 +115,27 @@ Steps
$ $VENV/bin/pserve development.ini --reload
-#. Open http://localhost:6543/howdy/jane/doe in your browser. Click
- the ``Save`` and ``Delete`` buttons and watch the output in the
- console window.
+#. Open http://localhost:6543/howdy/jane/doe in your browser. Click the
+ ``Save`` and ``Delete`` buttons, and watch the output in the console window.
+
Analysis
========
-As you can see, the four views are logically grouped together.
-Specifically:
+As you can see, the four views are logically grouped together. Specifically:
-- We have a ``home`` view available at http://localhost:6543/ with
- a clickable link to the ``hello`` view.
+- We have a ``home`` view available at http://localhost:6543/ with a clickable
+ link to the ``hello`` view.
-- The second view is returned when you go to ``/howdy/jane/doe``. This
- URL is
+- The second view is returned when you go to ``/howdy/jane/doe``. This URL is
mapped to the ``hello`` route that we centrally set using the optional
``@view_defaults``.
-- The third view is returned when the form is submitted with a ``POST``
- method. This rule is specified in the ``@view_config`` for that view.
+- The third view is returned when the form is submitted with a ``POST`` method.
+ This rule is specified in the ``@view_config`` for that view.
-- The fourth view is returned when clicking on a button such
- as ``<input type="submit" name="form.delete" value="Delete"/>``.
+- The fourth view is returned when clicking on a button such as ``<input
+ type="submit" name="form.delete" value="Delete"/>``.
In this step we show, using the following information as criteria, how to
decide which view to use:
@@ -149,49 +144,53 @@ decide which view to use:
- Parameter information in the request (submitted form field names)
-We also centralize part of the view configuration to the class level
-with ``@view_defaults``, then in one view, override that default just
-for that one view. Finally, we put this commonality between views to
-work in the view class by sharing:
+We also centralize part of the view configuration to the class level with
+``@view_defaults``, then in one view, override that default just for that one
+view. Finally, we put this commonality between views to work in the view class
+by sharing:
- State assigned in ``TutorialViews.__init__``
- A computed value
-These are then available both in the view methods but also in the
-templates (e.g. ``${view.view_name}`` and ``${view.full_name}``.
+These are then available both in the view methods and in the templates (e.g.,
+``${view.view_name}`` and ``${view.full_name}``).
+
+As a note, we made a switch in our templates on how we generate URLs. We
+previously hardcoded the URLs, such as:
-As a note, we made a switch in our templates on how we generate URLs.
-We previously hardcode the URLs, such as::
+.. code-block:: html
<a href="/howdy/jane/doe">Howdy</a>
-In ``home.pt`` we switched to::
+In ``home.pt`` we switched to:
+
+.. code-block:: xml
<a href="${request.route_url('hello', first='jane',
last='doe')}">form</a>
-Pyramid has rich facilities to help generate URLs in a flexible,
-non-error-prone fashion.
+Pyramid has rich facilities to help generate URLs in a flexible, non-error
+prone fashion.
-Extra Credit
+Extra credit
============
#. Why could our template do ``${view.full_name}`` and not have to do
``${view.full_name()}``?
-#. The ``edit`` and ``delete`` views are both submitted to with
- ``POST``. Why does the ``edit`` view configuration not catch the
- ``POST`` used by ``delete``?
+#. The ``edit`` and ``delete`` views are both receive ``POST`` requests. Why
+ does the ``edit`` view configuration not catch the ``POST`` used by
+ ``delete``?
-#. We used Python ``@property`` on ``full_name``. If we reference this
- many times in a template or view code, it would re-compute this
- every time. Does Pyramid provide something that will cache the initial
- computation on a property?
+#. We used Python ``@property`` on ``full_name``. If we reference this many
+ times in a template or view code, it would re-compute this every time. Does
+ Pyramid provide something that will cache the initial computation on a
+ property?
#. Can you associate more than one route with the same view?
-#. There is also a ``request.route_path`` API. How does this differ from
+#. There is also a ``request.route_path`` API. How does this differ from
``request.route_url``?
.. seealso:: :ref:`class_as_view`, `Weird Stuff You Can Do With
diff --git a/docs/quick_tutorial/package.rst b/docs/quick_tutorial/package.rst
index 6a379032e..94cb39fc9 100644
--- a/docs/quick_tutorial/package.rst
+++ b/docs/quick_tutorial/package.rst
@@ -3,16 +3,17 @@
============================================
Most modern Python development is done using Python packages, an approach
-Pyramid puts to good use. In this step we redo "Hello World" as a
-minimum Python package inside a minimum Python project.
+Pyramid puts to good use. In this step we redo "Hello World" as a minimal
+Python package inside a minimal Python project.
+
Background
==========
Python developers can organize a collection of modules and files into a
-namespaced unit called a :ref:`package <python:tut-packages>`. If a
-directory is on ``sys.path`` and has a special file named
-``__init__.py``, it is treated as a Python package.
+namespaced unit called a :ref:`package <python:tut-packages>`. If a directory
+is on ``sys.path`` and has a special file named ``__init__.py``, it is treated
+as a Python package.
Packages can be bundled up, made available for installation, and installed
through a toolchain oriented around a ``setup.py`` file. For this tutorial,
@@ -34,6 +35,7 @@ In summary:
- That package will be part of a *project*.
+
Objectives
==========
@@ -43,6 +45,7 @@ Objectives
- Install our ``tutorial`` project in development mode.
+
Steps
=====
@@ -56,8 +59,8 @@ Steps
.. literalinclude:: package/setup.py
-#. Make the new project installed for development then make a directory
- for the actual code:
+#. Make the new project installed for development then make a directory for the
+ actual code:
.. code-block:: bash
@@ -80,26 +83,27 @@ Steps
#. Open http://localhost:6543/ in your browser.
+
Analysis
========
-Python packages give us an organized unit of project development.
-Python projects, via ``setup.py``, gives us special features when
-our package is installed (in this case, in local development mode.)
+Python packages give us an organized unit of project development. Python
+projects, via ``setup.py``, give us special features when our package is
+installed (in this case, in local development mode, also called local editable
+mode as indicated by ``-e .``).
-In this step we have a Python package called ``tutorial``. We use the
-same name in each step of the tutorial, to avoid unnecessary retyping.
+In this step we have a Python package called ``tutorial``. We use the same name
+in each step of the tutorial, to avoid unnecessary retyping.
-Above this ``tutorial`` directory we have the files that handle the
-packaging of this project. At the moment, all we need is a
-bare-bones ``setup.py``.
+Above this ``tutorial`` directory we have the files that handle the packaging
+of this project. At the moment, all we need is a bare-bones ``setup.py``.
-Everything else is the same about our application. We simply made a
-Python package with a ``setup.py`` and installed it in development mode.
+Everything else is the same about our application. We simply made a Python
+package with a ``setup.py`` and installed it in development mode.
Note that the way we're running the app (``python tutorial/app.py``) is a bit
of an odd duck. We would never do this unless we were writing a tutorial that
-tries to capture how this stuff works a step at a time. It's generally a bad
+tries to capture how this stuff works one step at a time. It's generally a bad
idea to run a Python module inside a package directly as a script.
.. seealso:: :ref:`Python Packages <python:tut-packages>` and `Working in
diff --git a/docs/quick_tutorial/request_response.rst b/docs/quick_tutorial/request_response.rst
index f42423de8..0ac9b4f6d 100644
--- a/docs/quick_tutorial/request_response.rst
+++ b/docs/quick_tutorial/request_response.rst
@@ -5,33 +5,32 @@
=======================================
Web applications handle incoming requests and return outgoing responses.
-Pyramid makes working with requests and responses convenient and
-reliable.
+Pyramid makes working with requests and responses convenient and reliable.
+
Objectives
==========
-- Learn the background on Pyramid's choices for requests and responses
+- Learn the background on Pyramid's choices for requests and responses.
+
+- Grab data out of the request.
-- Grab data out of the request
+- Change information in the response headers.
-- Change information in the response headers
Background
==========
-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 and returning web
-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 and returning web responses.
+
+Pyramid has always fit nicely into the existing world of Python web development
+(virtual environments, packaging, scaffolding, first to embrace Python 3, and
+so on). 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>`.
-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>`.
Steps
=====
@@ -62,7 +61,9 @@ Steps
.. code-block:: bash
- $ $VENV/bin/nosetests tutorial
+ $ $VENV/bin/py.test tutorial/tests.py -q
+ .....
+ 5 passed in 0.30 seconds
#. Run your Pyramid application with:
@@ -70,37 +71,39 @@ Steps
$ $VENV/bin/pserve development.ini --reload
-#. Open http://localhost:6543/ in your browser. You will be
- redirected to http://localhost:6543/plain
+#. Open http://localhost:6543/ in your browser. You will be redirected to
+ http://localhost:6543/plain.
#. Open http://localhost:6543/plain?name=alice in your browser.
+
Analysis
========
-In this view class we have two routes and two views, with the first
-leading to the second by an HTTP redirect. Pyramid can
-:ref:`generate redirects <http_redirect>` by returning a
-special object from a view or raising a special exception.
+In this view class, we have two routes and two views, with the first leading to
+the second by an HTTP redirect. Pyramid can :ref:`generate redirects
+<http_redirect>` by returning a special object from a view or raising a special
+exception.
+
+In this Pyramid view, we get the URL being visited from ``request.url``. Also,
+if you visited http://localhost:6543/plain?name=alice, the name is included in
+the body of the response:
-In this Pyramid view, we get the URL being visited from ``request.url``.
-Also, if you visited http://localhost:6543/plain?name=alice,
-the name is included in the body of the response::
+.. code-block:: text
URL http://localhost:6543/plain?name=alice with name: alice
-Finally, we set the response's content type and body, then return the
-Response.
+Finally, we set the response's content type and body, then return the response.
+
+We updated the unit and functional tests to prove that our code does the
+redirection, but also handles sending and not sending ``/plain?name``.
-We updated the unit and functional tests to prove that our code
-does the redirection, but also handles sending and not sending
-``/plain?name``.
-Extra Credit
+Extra credit
============
-#. Could we also ``raise HTTPFound(location='/plain')`` instead of
- returning it? If so, what's the difference?
+#. Could we also ``raise HTTPFound(location='/plain')`` instead of returning
+ it? If so, what's the difference?
.. seealso:: :ref:`webob_chapter`,
:ref:`generate redirects <http_redirect>`
diff --git a/docs/quick_tutorial/requirements.rst b/docs/quick_tutorial/requirements.rst
index 9e10e3ebe..1f2b4da97 100644
--- a/docs/quick_tutorial/requirements.rst
+++ b/docs/quick_tutorial/requirements.rst
@@ -6,41 +6,44 @@ Requirements
Let's get our tutorial environment set up. Most of the set up work is in
standard Python development practices (install Python and make an isolated
-environment.)
+virtual environment.)
.. note::
- Pyramid encourages standard Python development practices with
- packaging tools, virtual environments, logging, and so on. There
- are many variations, implementations, and opinions across the Python
- community. For consistency, ease of documentation maintenance,
- and to minimize confusion, the Pyramid *documentation* has adopted
- specific conventions.
+ Pyramid encourages standard Python development practices with packaging
+ tools, virtual environments, logging, and so on. There are many variations,
+ implementations, and opinions across the Python community. For consistency,
+ ease of documentation maintenance, and to minimize confusion, the Pyramid
+ *documentation* has adopted specific conventions that are consistent with the
+ :term:`Python Packaging Authority`.
This *Quick Tutorial* is based on:
-* **Python 3.5**. Pyramid fully supports Python 3.3+ and Python 2.6+. This
+* **Python 3.5**. Pyramid fully supports Python 3.3+ and Python 2.7+. This
tutorial uses **Python 3.5** but runs fine under Python 2.7.
* **venv**. We believe in virtual environments. For this tutorial, we use
- Python 3.5's built-in solution ``venv``. For Python 2.7, you can install
- ``virtualenv``.
+ Python 3.5's built-in solution :term:`venv`. For Python 2.7, you can install
+ :term:`virtualenv`.
-* **pip**. We use ``pip`` for package management.
+* **pip**. We use :term:`pip` for package management.
-* **Workspaces, projects, and packages.** Our home directory
- will contain a *tutorial workspace* with our Python virtual
- environment(s) and *Python projects* (a directory with packaging
- information and *Python packages* of working code.)
+* **Workspaces, projects, and packages.** Our home directory will contain a
+ *tutorial workspace* with our Python virtual environment and *Python
+ projects* (a directory with packaging information and *Python packages* of
+ working code.)
-* **Unix commands**. Commands in this tutorial use UNIX syntax and
- paths. Windows users should adjust commands accordingly.
+* **Unix commands**. Commands in this tutorial use UNIX syntax and paths.
+ Windows users should adjust commands accordingly.
.. note::
-
Pyramid was one of the first web frameworks to fully support Python 3 in
October 2011.
+.. note::
+ Windows commands use the plain old MSDOS shell. For PowerShell command
+ syntax, see its documentation.
+
Steps
=====
@@ -56,27 +59,12 @@ Steps
Install Python 3
----------------
-Windows and Mac OS X users can download and run an installer.
-
-Download the latest standard Python 3 release (not development release) from
-`python.org <https://www.python.org/downloads/>`_.
-
-Windows users should also 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.
+See the detailed recommendation for your operating system described under
+:ref:`installing_chapter`.
-Linux users can either use their package manager to install Python 3
-or may `build Python 3 from source
-<http://pyramid.readthedocs.org/en/master/narr/install.html#package-manager-
-method>`_.
-
-.. seealso:: See also :ref:`For Mac OS X Users <for-mac-os-x-users>`, :ref:`If
- You Don't Yet Have a Python Interpreter (UNIX)
- <if-you-don-t-yet-have-a-python-interpreter-unix>`, and :ref:`If You Don't
- Yet Have a Python Interpreter (Windows)
- <if-you-don-t-yet-have-a-python-interpreter-windows>`.
+- :ref:`for-mac-os-x-users`
+- :ref:`if-you-don-t-yet-have-a-python-interpreter-unix`
+- :ref:`if-you-don-t-yet-have-a-python-interpreter-windows`
.. _create-a-project-directory-structure:
@@ -84,11 +72,10 @@ method>`_.
Create a project directory structure
------------------------------------
-We will arrive at a directory structure of
-``workspace->project->package``, with our workspace named
-``quick_tutorial``. The following tree diagram shows how this will be
-structured and where our virtual environment will reside as we proceed through
-the tutorial:
+We will arrive at a directory structure of ``workspace -> project -> package``,
+where our workspace is named ``quick_tutorial``. The following tree diagram
+shows how this will be structured, and where our :term:`virtual environment`
+will reside as we proceed through the tutorial:
.. code-block:: text
@@ -113,49 +100,47 @@ For Linux, the commands to do so are as follows:
For Windows:
-.. code-block:: ps1con
+.. code-block:: doscon
# Windows
c:\> cd \
c:\> mkdir projects\quick_tutorial
c:\> cd projects\quick_tutorial
-In the above figure, your user home directory is represented by ``~``. In
-your home directory, all of your projects are in the ``projects`` directory.
-This is a general convention not specific to Pyramid that many developers use.
-Windows users will do well to use ``c:\`` as the location for ``projects`` in
-order to avoid spaces in any of the path names.
+In the above figure, your user home directory is represented by ``~``. In your
+home directory, all of your projects are in the ``projects`` directory. This is
+a general convention not specific to Pyramid that many developers use. Windows
+users will do well to use ``c:\`` as the location for ``projects`` in order to
+avoid spaces in any of the path names.
Next within ``projects`` is your workspace directory, here named
``quick_tutorial``. A workspace is a common term used by integrated
-development environments (IDE) like PyCharm and PyDev that stores
-isolated Python environments (virtual environments) and specific project files
-and repositories.
+development environments (IDE), like PyCharm and PyDev, where virtual
+environments, specific project files, and repositories are stored.
.. _set-an-environment-variable:
-Set an Environment Variable
+Set an environment variable
---------------------------
-This tutorial will refer frequently to the location of the virtual
-environment. We set an environment variable to save typing later.
+This tutorial will refer frequently to the location of the :term:`virtual
+environment`. We set an environment variable to save typing later.
.. code-block:: bash
# Mac and Linux
$ export VENV=~/projects/quick_tutorial/env
-.. code-block:: ps1con
+.. code-block:: doscon
# Windows
- # TODO: This command does not work
c:\> set VENV=c:\projects\quick_tutorial\env
.. _create-a-virtual-environment:
-Create a Virtual Environment
+Create a virtual environment
----------------------------
``venv`` is a tool to create isolated Python 3 environments, each with its own
@@ -168,7 +153,7 @@ environment variable.
# Mac and Linux
$ python3 -m venv $VENV
-.. code-block:: ps1con
+.. code-block:: doscon
# Windows
c:\> c:\Python35\python3 -m venv %VENV%
@@ -177,13 +162,31 @@ environment variable.
2's `virtualenv <https://virtualenv.pypa.io/en/latest/>`_ package.
+Update packaging tools in the virtual environment
+-------------------------------------------------
+
+It's always a good idea to update to the very latest version of packaging tools
+because the installed Python bundles only the version that was available at the
+time of its release.
+
+.. code-block:: bash
+
+ # Mac and Linux
+ $VENV/bin/pip install --upgrade pip setuptools
+
+.. code-block:: doscon
+
+ # Windows
+ c:\> %VENV%\Scripts\pip install --upgrade pip setuptools
+
+
.. _install-pyramid:
Install Pyramid
---------------
We have our Python standard prerequisites out of the way. The Pyramid
-part is pretty easy:
+part is pretty easy.
.. parsed-literal::
@@ -195,18 +198,17 @@ part is pretty easy:
Our Python virtual environment now has the Pyramid software available.
-You can optionally install some of the extra Python packages used
-during this tutorial:
+You can optionally install some of the extra Python packages used in this
+tutorial.
.. code-block:: bash
# Mac and Linux
- $ $VENV/bin/pip install nose webtest deform sqlalchemy \
- pyramid_chameleon pyramid_debugtoolbar waitress \
- pyramid_tm zope.sqlalchemy
+ $ $VENV/bin/pip install webtest pytest pytest-cov deform sqlalchemy \
+ pyramid_chameleon pyramid_debugtoolbar pyramid_jinja2 waitress \
+ pyramid_tm zope.sqlalchemy
-.. code-block:: ps1con
+.. code-block:: doscon
# Windows
- c:\> %VENV%\Scripts\pip install nose webtest deform sqlalchemy pyramid_chameleon pyramid_debugtoolbar waitress pyramid_tm zope.sqlalchemy
-
+ c:\> %VENV%\Scripts\pip install webtest deform sqlalchemy pyramid_chameleon pyramid_debugtoolbar pyramid_jinja2 waitress pyramid_tm zope.sqlalchemy
diff --git a/docs/quick_tutorial/routing.rst b/docs/quick_tutorial/routing.rst
index 7b6d0904d..27c8c2c22 100644
--- a/docs/quick_tutorial/routing.rst
+++ b/docs/quick_tutorial/routing.rst
@@ -4,22 +4,23 @@
11: Dispatching URLs To Views With Routing
==========================================
-Routing matches incoming URL patterns to view code. Pyramid's routing
-has a number of useful features.
+Routing matches incoming URL patterns to view code. Pyramid's routing has a
+number of useful features.
+
Background
==========
-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.
+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.
Previously 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
+- 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
+- Elsewhere a view is configured to be called for that route name.
.. note::
@@ -33,12 +34,14 @@ Previously we saw the basics of routing URLs to views in Pyramid.
<http://static.repoze.org/casts/videotags.html>`_ if you're interested in
doing so.
+
Objectives
==========
-- Define a route that extracts part of the URL into a Python dictionary
+- Define a route that extracts part of the URL into a Python dictionary.
+
+- Use that dictionary data in a view.
-- Use that dictionary data in a view
Steps
=====
@@ -76,7 +79,9 @@ Steps
.. code-block:: bash
- $ $VENV/bin/nosetests tutorial
+ $ $VENV/bin/$VENV/bin/py.test tutorial/tests.py -q
+ ..
+ 2 passed in 0.39 seconds
#. Run your Pyramid application with:
@@ -86,6 +91,7 @@ Steps
#. Open http://localhost:6543/howdy/amy/smith in your browser.
+
Analysis
========
@@ -95,27 +101,24 @@ In ``__init__.py`` we see an important change in our route declaration:
config.add_route('hello', '/howdy/{first}/{last}')
-With this we tell the :term:`configurator` that our URL has
-a "replacement pattern". 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:
+With this we tell the :term:`configurator` that our URL has a "replacement
+pattern". 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:
.. code-block:: python
self.request.matchdict['first']
self.request.matchdict['last']
-``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 anywhere in Pyramid that has access
-to the request.
+``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 anywhere in Pyramid that has access to the request.
-Extra Credit
+Extra credit
============
-#. What happens if you to go the URL
- http://localhost:6543/howdy? Is this the result that you
- expected?
+#. What happens if you to go the URL http://localhost:6543/howdy? Is this the
+ result that you expected?
-.. seealso:: `Weird Stuff You Can Do With URL
- Dispatch <http://www.plope.com/weird_pyramid_urldispatch>`_
+.. seealso:: `Weird Stuff You Can Do With URL Dispatch
+ <http://www.plope.com/weird_pyramid_urldispatch>`_
diff --git a/docs/quick_tutorial/scaffolds.rst b/docs/quick_tutorial/scaffolds.rst
index 319eb9d90..7845f2b71 100644
--- a/docs/quick_tutorial/scaffolds.rst
+++ b/docs/quick_tutorial/scaffolds.rst
@@ -4,29 +4,30 @@
Prelude: Quick Project Startup with Scaffolds
=============================================
-To ease the process of getting started, Pyramid provides *scaffolds*
-that generate sample projects from templates in Pyramid and Pyramid
-add-ons.
+To ease the process of getting started, Pyramid provides *scaffolds* that
+generate sample projects from templates in Pyramid and Pyramid add-ons.
+
Background
==========
-We're going to cover a lot in this tutorial, focusing on one topic at a
-time and writing everything from scratch. As a warm up, though,
-it sure would be nice to see some pixels on a screen.
+We're going to cover a lot in this tutorial, focusing on one topic at a time
+and writing everything from scratch. As a warm up, though, it sure would be
+nice to see some pixels on a screen.
+
+Like other web development frameworks, Pyramid provides a number of "scaffolds"
+that generate working Python, template, and CSS code for sample applications.
+In this step we'll use a built-in scaffold to let us preview a Pyramid
+application, before starting from scratch on Step 1.
-Like other web development frameworks, Pyramid provides a number of
-"scaffolds" that generate working Python, template, and CSS code for
-sample applications. In this step we'll use a built-in scaffold to let
-us preview a Pyramid application, before starting from scratch on Step 1.
Objectives
==========
-- Use Pyramid's ``pcreate`` command to list scaffolds and make a new
- project
+- Use Pyramid's ``pcreate`` command to list scaffolds and make a new project.
+
+- Start up a Pyramid application and visit it in a web browser.
-- Start up a Pyramid application and visit it in a web browser
Steps
=====
@@ -55,8 +56,8 @@ Steps
$ cd scaffolds
$ $VENV/bin/pip install -e .
-#. Start up the application by pointing Pyramid's ``pserve`` command at
- the project's (generated) configuration file:
+#. Start up the application by pointing Pyramid's ``pserve`` command at the
+ project's (generated) configuration file:
.. code-block:: bash
@@ -75,13 +76,12 @@ Steps
Analysis
========
-Rather than starting from scratch, ``pcreate`` can make getting a
-Python project containing a Pyramid application a quick matter.
-Pyramid ships with a few scaffolds. But installing a Pyramid add-on can
-give you new scaffolds from that add-on.
+Rather than starting from scratch, ``pcreate`` can make getting a Python
+project containing a Pyramid application a quick matter. Pyramid ships with a
+few scaffolds. But installing a Pyramid add-on can give you new scaffolds from
+that add-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 is passed a configuration
-file (in this case, ``development.ini``.)
+``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 is passed a configuration file (in this case, ``development.ini``).
diff --git a/docs/quick_tutorial/sessions.rst b/docs/quick_tutorial/sessions.rst
index 06176f2b6..df4887a4b 100644
--- a/docs/quick_tutorial/sessions.rst
+++ b/docs/quick_tutorial/sessions.rst
@@ -6,25 +6,28 @@
Store and retrieve non-permanent data in Pyramid sessions.
+
Background
==========
-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`.
+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. Third party packages such as
-``pyramid_redis_sessions`` provide richer session support. Or you can create
-your own custom sessioning engine. Let's take a look at the
-:doc:`built-in sessioning support <../narr/sessions>`.
+`pyramid_redis_sessions
+<https://github.com/ericrasmussen/pyramid_redis_sessions>`_ provide richer
+session support. Or you can create your own custom sessioning engine. Let's
+take a look at the :doc:`built-in sessioning support <../narr/sessions>`.
+
Objectives
==========
-- Make a session factory using a built-in, simple Pyramid sessioning
- system
+- Make a session factory using a built-in, simple Pyramid sessioning system.
+
+- Change our code to use a session.
-- Change our code to use a session
Steps
=====
@@ -36,14 +39,13 @@ Steps
$ cd ..; cp -r view_classes sessions; cd sessions
$ $VENV/bin/pip install -e .
-#. Our ``sessions/tutorial/__init__.py`` needs a choice of session
- factory to get registered with the :term:`configurator`:
+#. Our ``sessions/tutorial/__init__.py`` needs a choice of session factory to
+ get registered with the :term:`configurator`:
.. literalinclude:: sessions/tutorial/__init__.py
:linenos:
-#. Our views in ``sessions/tutorial/views.py`` can now use
- ``request.session``:
+#. Our views in ``sessions/tutorial/views.py`` can now use ``request.session``:
.. literalinclude:: sessions/tutorial/views.py
:linenos:
@@ -58,7 +60,9 @@ Steps
.. code-block:: bash
- $ $VENV/bin/nosetests tutorial
+ $ $VENV/bin/py.test tutorial/tests.py -q
+ ....
+ 4 passed in 0.42 seconds
#. Run your Pyramid application with:
@@ -66,33 +70,33 @@ Steps
$ $VENV/bin/pserve development.ini --reload
-#. Open http://localhost:6543/ and http://localhost:6543/howdy
- in your browser. As you reload and switch between those URLs, note
- that the counter increases and is *not* specific to the URL.
+#. Open http://localhost:6543/ and http://localhost:6543/howdy in your browser.
+ As you reload and switch between those URLs, note that the counter increases
+ and is *not* specific to the URL.
+
+#. Restart the application and revisit the page. Note that counter still
+ increases from where it left off.
-#. Restart the application and revisit the page. Note that counter
- still increases from where it left off.
Analysis
========
-Pyramid's :term:`request` object now has a ``session`` attribute
-that we can use in our view code. It acts like a dictionary.
+Pyramid's :term:`request` object now has a ``session`` attribute that we can
+use in our view code. It acts like a dictionary.
-Since all the views are using the same counter, we made the counter a
-Python property at the view class level. With this, each reload will
-increase the counter displayed in our template.
+Since all the views are using the same counter, we made the counter a Python
+property at the view class level. With this, each reload will increase the
+counter displayed in our template.
-In web development, "flash messages" are notes for the user that need
-to appear on a screen after a future web request. For example,
-when you add an item using a form ``POST``, the site usually issues a
-second HTTP Redirect web request to view the new item. You might want a
-message to appear after that second web request saying "Your item was
-added." You can't just return it in the web response for the POST,
-as it will be tossed out during the second web request.
+In web development, "flash messages" are notes for the user that need to appear
+on a screen after a future web request. For example, when you add an item using
+a form ``POST``, the site usually issues a second HTTP Redirect web request to
+view the new item. You might want a message to appear after that second web
+request saying "Your item was added." You can't just return it in the web
+response for the POST, as it will be tossed out during the second web request.
-Flash messages are a technique where messages can be stored between
-requests, using sessions, then removed when they finally get displayed.
+Flash messages are a technique where messages can be stored between requests,
+using sessions, then removed when they finally get displayed.
.. seealso::
:ref:`sessions_chapter`,
diff --git a/docs/quick_tutorial/static_assets.rst b/docs/quick_tutorial/static_assets.rst
index 61c5fbd50..65b34f8f9 100644
--- a/docs/quick_tutorial/static_assets.rst
+++ b/docs/quick_tutorial/static_assets.rst
@@ -4,16 +4,17 @@
13: CSS/JS/Images Files With 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.
+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.
Objectives
==========
-- Publish a directory of static assets at a URL
+- Publish a directory of static assets at a URL.
+
+- Use Pyramid to help generate URLs to files in that directory.
-- Use Pyramid to help generate URLs to files in that directory
Steps
=====
@@ -37,8 +38,7 @@ Steps
.. literalinclude:: static_assets/tutorial/home.pt
:language: html
-#. Add a CSS file at
- ``static_assets/tutorial/static/app.css``:
+#. Add a CSS file at ``static_assets/tutorial/static/app.css``:
.. literalinclude:: static_assets/tutorial/static/app.css
:language: css
@@ -47,7 +47,9 @@ Steps
.. code-block:: bash
- $ $VENV/bin/nosetests tutorial
+ $ $VENV/bin/$VENV/bin/py.test tutorial/tests.py -q
+ ....
+ 4 passed in 0.50 seconds
#. Run your Pyramid application with:
@@ -57,30 +59,31 @@ Steps
#. Open http://localhost:6543/ in your browser and note the new font.
+
Analysis
========
We changed our WSGI application to map requests under
-http://localhost:6543/static/ to files and directories inside a
-``static`` directory inside our ``tutorial`` package. This directory
-contained ``app.css``.
+http://localhost:6543/static/ to files and directories inside a ``static``
+directory inside our ``tutorial`` package. This directory contained
+``app.css``.
-We linked to the CSS in our template. We could have hard-coded this
-link to ``/static/app.css``. But what if the site is later moved under
-``/somesite/static/``? Or perhaps the web developer changes the
-arrangement on disk? Pyramid gives a helper that provides flexibility
-on URL generation:
+We linked to the CSS in our template. We could have hard-coded this link to
+``/static/app.css``. But what if the site is later moved under
+``/somesite/static/``? Or perhaps the web developer changes the arrangement on
+disk? Pyramid gives a helper that provides flexibility on URL generation:
.. code-block:: html
${request.static_url('tutorial:static/app.css')}
-This matches the ``path='tutorial:static'`` in our
-``config.add_static_view`` registration. 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.
+This matches the ``path='tutorial:static'`` in our ``config.add_static_view``
+registration. 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.
+
-Extra Credit
+Extra credit
============
#. There is also a ``request.static_path`` API. How does this differ from
diff --git a/docs/quick_tutorial/templating.rst b/docs/quick_tutorial/templating.rst
index a975d9ec2..ec6de98f8 100644
--- a/docs/quick_tutorial/templating.rst
+++ b/docs/quick_tutorial/templating.rst
@@ -4,50 +4,53 @@
08: HTML Generation With Templating
===================================
-Most web frameworks don't embed HTML in programming code. Instead,
-they pass data into a templating system. In this step we look at the
-basics of using HTML templates in Pyramid.
+Most web frameworks don't embed HTML in programming code. Instead, they pass
+data into a templating system. In this step we look at the basics of using HTML
+templates in Pyramid.
+
Background
==========
-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.
+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, and so on.
+It encourages replaceability. This applies equally to templating, which is
+fortunate: developers have strong views about template languages. As of
+Pyramid 1.5a2, Pyramid doesn't even bundle a template 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. As of Pyramid 1.5a2, Pyramid doesn't even bundle a template
-language!
+It does, however, have strong ties to Jinja2, Mako, and Chameleon. In this step
+we see how to add `pyramid_chameleon
+<https://github.com/Pylons/pyramid_chameleon>`_ to your project, then change
+your views to use templating.
-It does, however, have strong ties to Jinja2, Mako, and Chameleon. In
-this step we see how to add ``pyramid_chameleon`` to your project,
-then change your views to use templating.
Objectives
==========
-- Enable the ``pyramid_chameleon`` Pyramid add-on
+- Enable the ``pyramid_chameleon`` Pyramid add-on.
+
+- Generate HTML from template files.
-- Generate HTML from template files
+- Connect the templates as "renderers" for view code.
-- Connect the templates as "renderers" for view code
+- Change the view code to simply return data.
-- Change the view code to simply return data
Steps
=====
-#. Let's begin by using the previous package as a starting point for a
- new project:
+#. Let's begin by using the previous package as a starting point for a new
+ project:
.. code-block:: bash
$ cd ..; cp -r views templating; cd templating
-#. This step depends on ``pyramid_chameleon``, so add it as a dependency
- in ``templating/setup.py``:
+#. This step depends on ``pyramid_chameleon``, so add it as a dependency in
+ ``templating/setup.py``:
.. literalinclude:: templating/setup.py
:linenos:
@@ -58,8 +61,8 @@ Steps
$ $VENV/bin/pip install -e .
-#. We need to connect ``pyramid_chameleon`` as a renderer by making a
- call in the setup of ``templating/tutorial/__init__.py``:
+#. We need to connect ``pyramid_chameleon`` as a renderer by making a call in
+ the setup of ``templating/tutorial/__init__.py``:
.. literalinclude:: templating/tutorial/__init__.py
:linenos:
@@ -74,14 +77,13 @@ Steps
.. literalinclude:: templating/tutorial/home.pt
:language: html
-#. For convenience, change ``templating/development.ini`` to reload
- templates automatically with ``pyramid.reload_templates``:
+#. For convenience, change ``templating/development.ini`` to reload templates
+ automatically with ``pyramid.reload_templates``:
.. literalinclude:: templating/development.ini
:language: ini
-#. Our unit tests in ``templating/tutorial/tests.py`` can focus on
- data:
+#. Our unit tests in ``templating/tutorial/tests.py`` can focus on data:
.. literalinclude:: templating/tutorial/tests.py
:linenos:
@@ -90,13 +92,9 @@ Steps
.. code-block:: bash
-
- $ $VENV/bin/nosetests tutorial
- .
- ----------------------------------------------------------------------
- Ran 4 tests in 0.141s
-
- OK
+ $ $VENV/bin/py.test tutorial/tests.py -q
+ ....
+ 4 passed in 0.46 seconds
#. Run your Pyramid application with:
@@ -104,20 +102,19 @@ Steps
$ $VENV/bin/pserve development.ini --reload
-#. Open http://localhost:6543/ and http://localhost:6543/howdy
- in your browser.
+#. Open http://localhost:6543/ and http://localhost:6543/howdy in your browser.
+
Analysis
========
-Ahh, that looks better. We have a view that is focused on Python code.
-Our ``@view_config`` decorator specifies a :term:`renderer` that points
-to our template file. Our view then simply returns data which is then
-supplied to our template. Note that we used the same template for both
-views.
+Ahh, that looks better. We have a view that is focused on Python code. Our
+``@view_config`` decorator specifies a :term:`renderer` that points to our
+template file. Our view then simply returns data which is then supplied to our
+template. Note that we used the same template for both views.
-Note the effect on testing. We can focus on having a data-oriented
-contract with our view code.
+Note the effect on testing. We can focus on having a data-oriented contract
+with our view code.
.. seealso:: :ref:`templates_chapter`, :ref:`debugging_templates`, and
:ref:`available_template_system_bindings`.
diff --git a/docs/quick_tutorial/tutorial_approach.rst b/docs/quick_tutorial/tutorial_approach.rst
index 8298a4710..6d534fe13 100644
--- a/docs/quick_tutorial/tutorial_approach.rst
+++ b/docs/quick_tutorial/tutorial_approach.rst
@@ -2,44 +2,46 @@
Tutorial Approach
=================
-This tutorial uses conventions to keep the introduction focused and
-concise. Details, references, and deeper discussions are mentioned in
-"See also" notes.
+This tutorial uses conventions to keep the introduction focused and concise.
+Details, references, and deeper discussions are mentioned in "See also" notes.
.. seealso:: This is an example "See also" note.
-This "Getting Started" tutorial is broken into independent steps,
-starting with the smallest possible "single file WSGI app" example.
-Each of these steps introduce a topic and a very small set of concepts
-via working code. The steps each correspond to a directory in this
-repo, where each step/topic/directory is a Python package.
+This "Getting Started" tutorial is broken into independent steps, starting with
+the smallest possible "single file WSGI app" example. Each of these steps
+introduce a topic and a very small set of concepts via working code. The steps
+each correspond to a directory in this repo, where each step/topic/directory is
+a Python package.
-To successfully run each step::
+To successfully run each step:
- $ cd request_response
- $ $VENV/bin/pip install -e .
+.. code-block:: bash
-...and repeat for each step you would like to work on. In most cases we
-will start with the results of an earlier step.
+ $ cd request_response
+ $ $VENV/bin/pip install -e .
-Directory Tree
+...and repeat for each step you would like to work on. In most cases we will
+start with the results of an earlier step.
+
+Directory tree
==============
-As we develop our tutorial our directory tree will resemble the
-structure below::
-
- quicktutorial/
- request_response/
- development.ini
- setup.py
- tutorial/
- __init__.py
- home.pt
- tests.py
- views.py
-
-Each of the first-level directories (e.g. ``request_response``) is a
-*Python project* (except, as noted, the ``hello_world`` step.) The
-``tutorial`` directory is a *Python package*. At the end of each step,
-we copy a previous directory into a new directory to use as a starting
-point.
+As we develop our tutorial, our directory tree will resemble the structure
+below:
+
+.. code-block:: text
+
+ quick_tutorial
+ ├── env
+ └── request_response
+ ├── tutorial
+ │ ├── __init__.py
+ │ ├── tests.py
+ │ └── views.py
+ ├── development.ini
+ └── setup.py
+
+Each of the first-level directories (e.g., ``request_response``) is a *Python
+project* (except as noted for the ``hello_world`` step). The ``tutorial``
+directory is a *Python package*. At the end of each step, we copy a previous
+directory into a new directory to use as a starting point.
diff --git a/docs/quick_tutorial/unit_testing.rst b/docs/quick_tutorial/unit_testing.rst
index 58512d1cc..56fd2b297 100644
--- a/docs/quick_tutorial/unit_testing.rst
+++ b/docs/quick_tutorial/unit_testing.rst
@@ -1,55 +1,56 @@
.. _qtut_unit_testing:
-===========================
-05: Unit Tests and ``nose``
-===========================
+=============================
+05: Unit Tests and ``pytest``
+=============================
Provide unit testing for our project's Python code.
+
Background
==========
-As the mantra says, "Untested code is broken code." The Python
-community has had a long culture of writing test scripts which ensure
-that your code works correctly as you write it and maintain it in the
-future. Pyramid has always had a deep commitment to testing,
-with 100% test coverage from the earliest pre-releases.
-
-Python includes a
-:ref:`unit testing framework <python:unittest-minimal-example>` in its
-standard library. Over the years a number of Python projects, such as
-`nose <https://pypi.python.org/pypi/nose/>`_, have extended this
-framework with alternative test runners that provide more convenience
-and functionality. The Pyramid developers use ``nose``, which we'll thus
-use in this tutorial.
-
-Don't worry, this tutorial won't be pedantic about "test-driven
-development" (TDD). We'll do just enough to ensure that, in each step,
-we haven't majorly broken the code. As you're writing your code you
-might find this more convenient than changing to your browser
-constantly and clicking reload.
-
-We'll also leave discussion of
-`coverage <https://pypi.python.org/pypi/coverage>`_ for another section.
+As the mantra says, "Untested code is broken code." The Python community has
+had a long culture of writing test scripts which ensure that your code works
+correctly as you write it and maintain it in the future. Pyramid has always had
+a deep commitment to testing, with 100% test coverage from the earliest
+pre-releases.
+
+Python includes a :ref:`unit testing framework
+<python:unittest-minimal-example>` in its standard library. Over the years a
+number of Python projects, such as :ref:`pytest <pytest:features>`, have
+extended this framework with alternative test runners that provide more
+convenience and functionality. The Pyramid developers use ``pytest``, which
+we'll use in this tutorial.
+
+Don't worry, this tutorial won't be pedantic about "test-driven development"
+(TDD). We'll do just enough to ensure that, in each step, we haven't majorly
+broken the code. As you're writing your code, you might find this more
+convenient than changing to your browser constantly and clicking reload.
+
+We'll also leave discussion of `pytest-cov
+<http://pytest-cov.readthedocs.org/en/latest/>`_ for another section.
+
Objectives
==========
-- Write unit tests that ensure the quality of our code
+- Write unit tests that ensure the quality of our code.
+
+- Install a Python package (``pytest``) which helps in our testing.
-- Install a Python package (``nose``) which helps in our testing
Steps
=====
-#. First we copy the results of the previous step, as well as install
- the ``nose`` package:
+#. First we copy the results of the previous step, as well as install the
+ ``pytest`` package:
.. code-block:: bash
$ cd ..; cp -r debugtoolbar unit_testing; cd unit_testing
$ $VENV/bin/pip install -e .
- $ $VENV/bin/pip install nose
+ $ $VENV/bin/pip install pytest
#. Now we write a simple unit test in ``unit_testing/tutorial/tests.py``:
@@ -61,54 +62,51 @@ Steps
.. code-block:: bash
- $ $VENV/bin/nosetests tutorial
+ $ $VENV/bin/py.test tutorial/tests.py -q
.
- ----------------------------------------------------------------------
- Ran 1 test in 0.141s
+ 1 passed in 0.14 seconds
- OK
Analysis
========
-Our ``tests.py`` imports the Python standard unit testing framework. To
-make writing Pyramid-oriented tests more convenient, Pyramid supplies
-some ``pyramid.testing`` helpers 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.
+Our ``tests.py`` imports the Python standard unit testing framework. To make
+writing Pyramid-oriented tests more convenient, Pyramid supplies some
+``pyramid.testing`` helpers 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 expect.
-The ``tests.TutorialViewTests.test_hello_world`` test is a small
-example of a unit test. First, we import the view inside each test. Why
-not import at the top, like in normal Python code? Because imports can
-cause effects that break a test. We'd like our tests to be in *units*,
-hence the name *unit* testing. Each test should isolate itself to the
-correct degree.
+The ``tests.TutorialViewTests.test_hello_world`` test is a small example of a
+unit test. First, we import the view inside each test. Why not import at the
+top, like in normal Python code? Because imports can cause effects that break a
+test. We'd like our tests to be in *units*, hence the name *unit* testing. Each
+test should isolate itself to the correct degree.
-Our test then makes a fake incoming web request, then calls our Pyramid
-view. We test the HTTP status code on the response to make sure it
-matches our expectations.
+Our test then makes a fake incoming web request, then calls our Pyramid view.
+We test the HTTP status code on the response to make sure it matches our
+expectations.
Note that our use of ``pyramid.testing.setUp()`` and
``pyramid.testing.tearDown()`` aren't actually necessary here; they are only
necessary when your test needs to make use of the ``config`` object (it's a
Configurator) to add stuff to the configuration state before calling the view.
+
Extra Credit
============
-#. Change the test to assert that the response status code should be
- ``404`` (meaning, not found.) Run ``nosetests`` again. Read the
- error report and see if you can decipher what it is telling you.
+#. Change the test to assert that the response status code should be ``404``
+ (meaning, not found). Run ``py.test`` again. Read the error report and see
+ if you can decipher what it is telling you.
-#. As a more realistic example, put the ``tests.py`` back as you found
- it and put an error in your view, such as a reference to a
- non-existing variable. Run the tests and see how this is more
- convenient than reloading your browser and going back to your code.
+#. As a more realistic example, put the ``tests.py`` back as you found it, and
+ put an error in your view, such as a reference to a non-existing variable.
+ Run the tests and see how this is more convenient than reloading your
+ browser and going back to your code.
#. Finally, for the most realistic test, read about Pyramid ``Response``
- objects and see how to change the response code. Run the tests and
- see how testing confirms the "contract" that your code claims to
- support.
+ objects and see how to change the response code. Run the tests and see how
+ testing confirms the "contract" that your code claims to support.
#. How could we add a unit test assertion to test the HTML value of the
response body?
diff --git a/docs/quick_tutorial/view_classes.rst b/docs/quick_tutorial/view_classes.rst
index cc5337493..05d97a9b1 100644
--- a/docs/quick_tutorial/view_classes.rst
+++ b/docs/quick_tutorial/view_classes.rst
@@ -4,8 +4,9 @@
09: Organizing Views With View Classes
======================================
-Change our view functions to be methods on a view class,
-then move some declarations to the class level.
+Change our view functions to be methods on a view class, then move some
+declarations to the class level.
+
Background
==========
@@ -15,27 +16,27 @@ views are related to one another. They may be different ways to look at or work
on the same data, or be a REST API that handles multiple operations. Grouping
these views together as a :ref:`view class <class_as_view>` makes sense:
-- Group views
+- Group views.
+
+- Centralize some repetitive defaults.
-- Centralize some repetitive defaults
+- Share some state and helpers.
-- Share some state and helpers
+In this step we just do the absolute minimum to convert the existing views to a
+view class. In a later tutorial step, we'll examine view classes in depth.
-In this step we just do the absolute minimum to convert the existing
-views to a view class. In a later tutorial step we'll examine view
-classes in depth.
Objectives
==========
-- Group related views into a view class
+- Group related views into a view class.
+
+- Centralize configuration with class-level ``@view_defaults``.
-- Centralize configuration with class-level ``@view_defaults``
Steps
=====
-
#. First we copy the results of the previous step:
.. code-block:: bash
@@ -43,15 +44,15 @@ Steps
$ cd ..; cp -r templating view_classes; cd view_classes
$ $VENV/bin/pip install -e .
-#. Our ``view_classes/tutorial/views.py`` now has a view class with
- our two views:
+#. Our ``view_classes/tutorial/views.py`` now has a view class with our two
+ views:
.. literalinclude:: view_classes/tutorial/views.py
:linenos:
-#. Our unit tests in ``view_classes/tutorial/tests.py`` don't run,
- so let's modify them to import the view class and make an instance
- before getting a response:
+#. Our unit tests in ``view_classes/tutorial/tests.py`` don't run, so let's
+ modify them to import the view class, and make an instance before getting a
+ response:
.. literalinclude:: view_classes/tutorial/tests.py
:linenos:
@@ -61,12 +62,9 @@ Steps
.. code-block:: bash
- $ $VENV/bin/nosetests tutorial
- .
- ----------------------------------------------------------------------
- Ran 4 tests in 0.141s
-
- OK
+ $ $VENV/bin/py.test tutorial/tests.py -q
+ ....
+ 4 passed in 0.34 seconds
#. Run your Pyramid application with:
@@ -74,24 +72,23 @@ Steps
$ $VENV/bin/pserve development.ini --reload
-#. Open http://localhost:6543/ and http://localhost:6543/howdy
- in your browser.
+#. Open http://localhost:6543/ and http://localhost:6543/howdy in your browser.
+
Analysis
========
To ease the transition to view classes, we didn't introduce any new
-functionality. We simply changed the view functions to methods on a
-view class, then updated the tests.
-
-In our ``TutorialViews`` view class you can see that our two view
-classes are logically grouped together as methods on a common class.
-Since the two views shared the same template, we could move that to a
-``@view_defaults`` decorator at the class level.
-
-The tests needed to change. Obviously we needed to import the view
-class. But you can also see the pattern in the tests of instantiating
-the view class with the dummy request first, then calling the view
-method being tested.
+functionality. We simply changed the view functions to methods on a view class,
+then updated the tests.
+
+In our ``TutorialViews`` view class, you can see that our two view classes are
+logically grouped together as methods on a common class. Since the two views
+shared the same template, we could move that to a ``@view_defaults`` decorator
+at the class level.
+
+The tests needed to change. Obviously we needed to import the view class. But
+you can also see the pattern in the tests of instantiating the view class with
+the dummy request first, then calling the view method being tested.
.. seealso:: :ref:`class_as_view`
diff --git a/docs/quick_tutorial/views.rst b/docs/quick_tutorial/views.rst
index 5b6e2960b..edbe4b2ff 100644
--- a/docs/quick_tutorial/views.rst
+++ b/docs/quick_tutorial/views.rst
@@ -6,12 +6,12 @@
Organize a views module with decorators and multiple views.
+
Background
==========
-For the examples so far, the ``hello_world`` function is a "view". In
-Pyramid, views are the primary way to accept web requests and return
-responses.
+For the examples so far, 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:
@@ -23,22 +23,24 @@ So far our examples place everything in one file:
- The WSGI application launcher
-Let's move the views out to their own ``views.py`` module and change
-our startup code to scan that module, looking for decorators that setup
-the views. Let's also add a second view and update our tests.
+Let's move the views out to their own ``views.py`` module and change our
+startup code to scan that module, looking for decorators that set up the views.
+Let's also add a second view and update our tests.
+
Objectives
==========
-- Views in a module that is scanned by the configurator
+- Move views into a module that is scanned by the configurator.
+
+- Create decorators that do declarative configuration.
-- Decorators that do declarative configuration
Steps
=====
-#. Let's begin by using the previous package as a starting point for a
- new distribution, then making it active:
+#. Let's begin by using the previous package as a starting point for a new
+ distribution, then making it active:
.. code-block:: bash
@@ -66,12 +68,9 @@ Steps
.. code-block:: bash
- $ $VENV/bin/nosetests tutorial
- .
- ----------------------------------------------------------------------
- Ran 4 tests in 0.141s
-
- OK
+ $ $VENV/bin/py.test tutorial/tests.py -q
+ ....
+ 4 passed in 0.28 seconds
#. Run your Pyramid application with:
@@ -82,41 +81,41 @@ Steps
#. Open http://localhost:6543/ and http://localhost:6543/howdy
in your browser.
+
Analysis
========
-We added some more URLs, but we also removed the view code from the
-application startup code in ``tutorial/__init__.py``.
-Our views, and their view registrations (via decorators) are now in a
-module ``views.py`` which is scanned via ``config.scan('.views')``.
-
-We have 2 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
-back to the first view.
-
-This step also shows that the name appearing in the URL,
-the name of the "route" that maps a URL to a view,
-and the name of the view, can all be different. More on routes later.
-
-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:`python: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.
-
-Extra Credit
+We added some more URLs, but we also removed the view code from the application
+startup code in ``tutorial/__init__.py``. Our views, and their view
+registrations (via decorators) are now in a module ``views.py``, which is
+scanned via ``config.scan('.views')``.
+
+We have two 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 back to the first
+view.
+
+This step also shows that the name appearing in the URL, the name of the
+"route" that maps a URL to a view, and the name of the view, can all be
+different. More on routes later.
+
+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:`python: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.
+
+
+Extra credit
============
#. What does the dot in ``.views`` signify?
-#. Why might ``assertIn`` be a better choice in testing the text in
- responses than ``assertEqual``?
+#. Why might ``assertIn`` be a better choice in testing the text in responses
+ than ``assertEqual``?
.. seealso:: :ref:`views_chapter`,
:ref:`view_config_chapter`, and
:ref:`debugging_view_configuration`
-