summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2018-09-27 21:54:04 -0500
committerMichael Merickel <michael@merickel.org>2018-09-27 21:54:04 -0500
commit58d2a5f14bb787defefe7a2b1b36665c4991c0da (patch)
tree3eff83e38ad641e7285ce6788cad47a12fa14262 /docs
parentf081ae991a9107363fceeeeccd361c2f85bdd046 (diff)
parent279ee00fff1894b3451d84a8eeafae42e8638776 (diff)
downloadpyramid-58d2a5f14bb787defefe7a2b1b36665c4991c0da.tar.gz
pyramid-58d2a5f14bb787defefe7a2b1b36665c4991c0da.tar.bz2
pyramid-58d2a5f14bb787defefe7a2b1b36665c4991c0da.zip
Merge branch 'master' into fix-deprecated-accept-predicate
Diffstat (limited to 'docs')
-rw-r--r--docs/api/session.rst8
-rw-r--r--docs/conf.py9
-rw-r--r--docs/glossary.rst6
-rw-r--r--docs/index.rst2
-rw-r--r--docs/narr/commandline.rst167
-rw-r--r--docs/narr/introduction.rst4
-rw-r--r--docs/narr/myproject/.gitignore21
-rw-r--r--docs/narr/myproject/myproject/__init__.py9
-rw-r--r--docs/narr/myproject/myproject/routes.py3
-rw-r--r--docs/narr/myproject/myproject/templates/404.jinja28
-rw-r--r--docs/narr/myproject/myproject/tests.py2
-rw-r--r--docs/narr/myproject/myproject/views.py6
-rw-r--r--docs/narr/myproject/myproject/views/__init__.py0
-rw-r--r--docs/narr/myproject/myproject/views/default.py6
-rw-r--r--docs/narr/myproject/myproject/views/notfound.py7
-rw-r--r--docs/narr/myproject/setup.py2
-rw-r--r--docs/narr/project.rst124
-rw-r--r--docs/narr/sessions.rst78
-rw-r--r--docs/narr/testing.rst4
-rw-r--r--docs/pscripts/pcreate.rst2
-rw-r--r--docs/pscripts/pdistreport.rst2
-rw-r--r--docs/pscripts/prequest.rst2
-rw-r--r--docs/pscripts/proutes.rst2
-rw-r--r--docs/pscripts/pserve.rst2
-rw-r--r--docs/pscripts/pshell.rst2
-rw-r--r--docs/pscripts/ptweens.rst2
-rw-r--r--docs/pscripts/pviews.rst2
-rw-r--r--docs/quick_tour.rst8
-rw-r--r--docs/quick_tour/logging/.gitignore21
-rw-r--r--docs/quick_tour/logging/hello_world/__init__.py9
-rw-r--r--docs/quick_tour/logging/hello_world/routes.py3
-rw-r--r--docs/quick_tour/logging/hello_world/templates/404.jinja28
-rw-r--r--docs/quick_tour/logging/hello_world/tests.py2
-rw-r--r--docs/quick_tour/logging/hello_world/views/__init__.py0
-rw-r--r--docs/quick_tour/logging/hello_world/views/default.py (renamed from docs/quick_tour/logging/hello_world/views.py)2
-rw-r--r--docs/quick_tour/logging/hello_world/views/notfound.py7
-rw-r--r--docs/quick_tour/logging/setup.py2
-rw-r--r--docs/quick_tour/package/.gitignore21
-rw-r--r--docs/quick_tour/package/hello_world/__init__.py9
-rw-r--r--docs/quick_tour/package/hello_world/routes.py3
-rw-r--r--docs/quick_tour/package/hello_world/templates/404.jinja28
-rw-r--r--docs/quick_tour/package/hello_world/tests.py2
-rw-r--r--docs/quick_tour/package/hello_world/views/__init__.py0
-rw-r--r--docs/quick_tour/package/hello_world/views/default.py (renamed from docs/quick_tour/package/hello_world/views.py)2
-rw-r--r--docs/quick_tour/package/hello_world/views/notfound.py7
-rw-r--r--docs/quick_tour/package/setup.py2
-rw-r--r--docs/quick_tour/sessions/.gitignore21
-rw-r--r--docs/quick_tour/sessions/hello_world/__init__.py13
-rw-r--r--docs/quick_tour/sessions/hello_world/routes.py3
-rw-r--r--docs/quick_tour/sessions/hello_world/templates/404.jinja28
-rw-r--r--docs/quick_tour/sessions/hello_world/tests.py2
-rw-r--r--docs/quick_tour/sessions/hello_world/views/__init__.py0
-rw-r--r--docs/quick_tour/sessions/hello_world/views/default.py (renamed from docs/quick_tour/sessions/hello_world/views.py)2
-rw-r--r--docs/quick_tour/sessions/hello_world/views/notfound.py7
-rw-r--r--docs/quick_tour/sessions/setup.py2
-rw-r--r--docs/quick_tour/sqla_demo/.gitignore21
-rw-r--r--docs/quick_tour/sqla_demo/README.txt12
-rw-r--r--docs/quick_tour/sqla_demo/development.ini11
-rw-r--r--docs/quick_tour/sqla_demo/production.ini9
-rw-r--r--docs/quick_tour/sqla_demo/pytest.ini2
-rw-r--r--docs/quick_tour/sqla_demo/setup.py7
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/__init__.py10
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/alembic/env.py58
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/alembic/script.py.mako24
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/alembic/versions/README.txt1
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/pshell.py12
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/scripts/initialize_db.py48
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/scripts/initializedb.py45
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.jinja22
-rw-r--r--docs/quick_tour/sqla_demo/sqla_demo/views/default.py11
-rw-r--r--docs/quick_tutorial/cookiecutters/.gitignore21
-rw-r--r--docs/quick_tutorial/cookiecutters/cc_starter/__init__.py9
-rw-r--r--docs/quick_tutorial/cookiecutters/cc_starter/routes.py3
-rw-r--r--docs/quick_tutorial/cookiecutters/cc_starter/templates/404.jinja28
-rw-r--r--docs/quick_tutorial/cookiecutters/cc_starter/tests.py2
-rw-r--r--docs/quick_tutorial/cookiecutters/cc_starter/views/__init__.py0
-rw-r--r--docs/quick_tutorial/cookiecutters/cc_starter/views/default.py (renamed from docs/quick_tutorial/cookiecutters/cc_starter/views.py)2
-rw-r--r--docs/quick_tutorial/cookiecutters/cc_starter/views/notfound.py7
-rw-r--r--docs/quick_tutorial/cookiecutters/setup.py5
-rw-r--r--docs/quick_tutorial/package/setup.py3
-rw-r--r--docs/tutorials/wiki/authorization.rst6
-rw-r--r--docs/tutorials/wiki/src/authorization/.gitignore21
-rw-r--r--docs/tutorials/wiki/src/authorization/README.txt2
-rw-r--r--docs/tutorials/wiki/src/authorization/development.ini3
-rw-r--r--docs/tutorials/wiki/src/authorization/production.ini3
-rw-r--r--docs/tutorials/wiki/src/authorization/setup.py2
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/pshell.py11
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt1
-rw-r--r--docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt1
-rw-r--r--docs/tutorials/wiki/src/basiclayout/.gitignore21
-rw-r--r--docs/tutorials/wiki/src/basiclayout/development.ini3
-rw-r--r--docs/tutorials/wiki/src/basiclayout/production.ini3
-rw-r--r--docs/tutorials/wiki/src/basiclayout/setup.py2
-rw-r--r--docs/tutorials/wiki/src/basiclayout/tutorial/pshell.py11
-rw-r--r--docs/tutorials/wiki/src/installation/.gitignore21
-rw-r--r--docs/tutorials/wiki/src/installation/development.ini3
-rw-r--r--docs/tutorials/wiki/src/installation/production.ini3
-rw-r--r--docs/tutorials/wiki/src/installation/setup.py2
-rw-r--r--docs/tutorials/wiki/src/installation/tutorial/pshell.py11
-rw-r--r--docs/tutorials/wiki/src/models/.gitignore21
-rw-r--r--docs/tutorials/wiki/src/models/development.ini3
-rw-r--r--docs/tutorials/wiki/src/models/production.ini3
-rw-r--r--docs/tutorials/wiki/src/models/setup.py2
-rw-r--r--docs/tutorials/wiki/src/models/tutorial/pshell.py11
-rw-r--r--docs/tutorials/wiki/src/tests/.gitignore21
-rw-r--r--docs/tutorials/wiki/src/tests/README.txt2
-rw-r--r--docs/tutorials/wiki/src/tests/development.ini3
-rw-r--r--docs/tutorials/wiki/src/tests/production.ini3
-rw-r--r--docs/tutorials/wiki/src/tests/setup.py2
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/pshell.py11
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt1
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt67
-rw-r--r--docs/tutorials/wiki/src/tests/tutorial/templates/view.pt1
-rw-r--r--docs/tutorials/wiki/src/views/.gitignore21
-rw-r--r--docs/tutorials/wiki/src/views/README.txt2
-rw-r--r--docs/tutorials/wiki/src/views/development.ini3
-rw-r--r--docs/tutorials/wiki/src/views/production.ini3
-rw-r--r--docs/tutorials/wiki/src/views/setup.py2
-rw-r--r--docs/tutorials/wiki/src/views/tutorial/pshell.py11
-rw-r--r--docs/tutorials/wiki2/basiclayout.rst4
-rw-r--r--docs/tutorials/wiki2/definingviews.rst2
-rw-r--r--docs/tutorials/wiki2/src/authentication/development.ini5
-rw-r--r--docs/tutorials/wiki2/src/authentication/production.ini3
-rw-r--r--docs/tutorials/wiki2/src/authentication/setup.py2
-rw-r--r--docs/tutorials/wiki2/src/authentication/tutorial/__init__.py12
-rw-r--r--docs/tutorials/wiki2/src/authentication/tutorial/pshell.py12
-rw-r--r--docs/tutorials/wiki2/src/authentication/tutorial/scripts/initialize_db.py22
-rw-r--r--docs/tutorials/wiki2/src/authorization/development.ini5
-rw-r--r--docs/tutorials/wiki2/src/authorization/production.ini3
-rw-r--r--docs/tutorials/wiki2/src/authorization/setup.py2
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/__init__.py12
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/pshell.py12
-rw-r--r--docs/tutorials/wiki2/src/authorization/tutorial/scripts/initialize_db.py22
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/development.ini5
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/production.ini3
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/setup.py2
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py10
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/pshell.py12
-rw-r--r--docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initialize_db.py26
-rw-r--r--docs/tutorials/wiki2/src/installation/development.ini5
-rw-r--r--docs/tutorials/wiki2/src/installation/production.ini3
-rw-r--r--docs/tutorials/wiki2/src/installation/setup.py2
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/__init__.py10
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/pshell.py12
-rw-r--r--docs/tutorials/wiki2/src/installation/tutorial/scripts/initialize_db.py26
-rw-r--r--docs/tutorials/wiki2/src/models/development.ini5
-rw-r--r--docs/tutorials/wiki2/src/models/production.ini3
-rw-r--r--docs/tutorials/wiki2/src/models/setup.py2
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/__init__.py10
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/pshell.py12
-rw-r--r--docs/tutorials/wiki2/src/models/tutorial/scripts/initialize_db.py22
-rw-r--r--docs/tutorials/wiki2/src/tests/development.ini5
-rw-r--r--docs/tutorials/wiki2/src/tests/production.ini3
-rw-r--r--docs/tutorials/wiki2/src/tests/setup.py2
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/__init__.py12
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/pshell.py12
-rw-r--r--docs/tutorials/wiki2/src/tests/tutorial/scripts/initialize_db.py22
-rw-r--r--docs/tutorials/wiki2/src/views/development.ini5
-rw-r--r--docs/tutorials/wiki2/src/views/production.ini3
-rw-r--r--docs/tutorials/wiki2/src/views/setup.py2
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/__init__.py10
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/pshell.py12
-rw-r--r--docs/tutorials/wiki2/src/views/tutorial/scripts/initialize_db.py22
163 files changed, 1243 insertions, 467 deletions
diff --git a/docs/api/session.rst b/docs/api/session.rst
index 53bae7c52..d0cb112ec 100644
--- a/docs/api/session.rst
+++ b/docs/api/session.rst
@@ -5,15 +5,11 @@
.. automodule:: pyramid.session
- .. autofunction:: signed_serialize
-
- .. autofunction:: signed_deserialize
-
.. autofunction:: SignedCookieSessionFactory
- .. autofunction:: UnencryptedCookieSessionFactoryConfig
-
.. autofunction:: BaseCookieSessionFactory
.. autoclass:: PickleSerializer
+ .. autoclass:: JSONSerializer
+
diff --git a/docs/conf.py b/docs/conf.py
index 8fe7108ff..6e3d41240 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -161,6 +161,15 @@ html_theme_options = dict(
outdated='false',
)
+# Control display of sidebars
+html_sidebars = {'**': [
+ 'localtoc.html',
+ 'ethicalads.html',
+ 'relations.html',
+ 'sourcelink.html',
+ 'searchbox.html',
+]}
+
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
html_title = 'The Pyramid Web Framework v%s' % release
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 7244aeb8d..7a9c91668 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -343,7 +343,7 @@ Glossary
full-featured Python web framework.
Grok
- `A web framework based on Zope 3 <http://grok.zope.org>`_.
+ `A web framework based on Zope 3 <https://web.archive.org/web/20180615015013/http://grok.zope.org>`_.
Django
`A full-featured Python web framework <https://www.djangoproject.com/>`_.
@@ -853,7 +853,7 @@ Glossary
Localization
The process of displaying the user interface of an
internationalized application in a particular language or
- cultural context. Often shortened to "l10" (because the word
+ cultural context. Often shortened to "l10n" (because the word
"localization" is L, 10 letters, then N).
.. seealso::
@@ -1083,7 +1083,7 @@ Glossary
Green Unicorn
Aka ``gunicorn``, a fast :term:`WSGI` server that runs on Unix under
- Python 2.6+ or Python 3.1+. See http://gunicorn.org/ for detailed
+ Python 2.6+ or Python 3.1+. See https://gunicorn.org/ for detailed
information.
predicate factory
diff --git a/docs/index.rst b/docs/index.rst
index 76d23b4f4..19cff9414 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -66,7 +66,7 @@ Official tutorials provide a quick overview of :app:`Pyramid`'s features in more
Support and Development
=======================
-The `Pyramid website <https://trypyramid.com/resources.html>`_ is the main
+The `Pyramid website <https://trypyramid.com/documentation.html>`_ is the main
entry point to :app:`Pyramid` web framework resources for support and
development information.
diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst
index 9e0310c29..98e34fea2 100644
--- a/docs/narr/commandline.rst
+++ b/docs/narr/commandline.rst
@@ -6,6 +6,65 @@ Command-Line Pyramid
Your :app:`Pyramid` application can be controlled and inspected using a variety
of command-line utilities. These utilities are documented in this chapter.
+We commonly refer to this collection of utilities as "p-scripts", which is short for "Pyramid console scripts".
+
+Each p-script's command line usage details is available in the :ref:`pscripts_documentation`.
+
+
+.. index::
+ single: running p-scripts
+ pair: running; p-scripts
+
+.. _running-pscripts:
+
+Running p-scripts
+-----------------
+
+All of the Pyramid console scripts may be run either:
+
+* by its name
+* as a Python module
+
+
+.. index::
+ single: running p-script by name
+ triple: p-script; running; name
+
+.. _running-pscripts-by-name:
+
+Running by ``p*`` script name
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Each of Pyramid's console scripts may be run by its name. For example:
+
+.. code-block:: bash
+
+ $VENV/bin/pserve development.ini --reload
+
+.. note:: ``$VENV/bin/`` is a convention we use to simplify Pyramid documentation.
+ It represents the ``bin`` directory in a virtual environment, where ``$VENV`` is an environment variable representing its path.
+ See :ref:`installing_unix` and :ref:`Why use $VENV/bin/pip instead of source bin/activate, then pip <venv-bin-pip-vs-source-bin-activate>` for more information.
+
+
+.. index::
+ single: running p-scripts via Python
+ triple: p-script; running; Python
+
+.. _custom-arguments-to-python:
+
+Using Custom Arguments to Python when Running ``p*`` Scripts
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. versionadded:: 1.5
+
+Each of Pyramid's console scripts (``pserve``, ``pviews``, etc.) can be run
+using ``python3 -m``, allowing custom arguments to be sent to the
+Python interpreter at runtime. For example:
+
+.. code-block:: bash
+
+ python3 -m pyramid.scripts.pserve development.ini --reload
+
.. index::
pair: matching views; printing
@@ -13,8 +72,8 @@ of command-line utilities. These utilities are documented in this chapter.
.. _displaying_matching_views:
-Displaying Matching Views for a Given URL
------------------------------------------
+``pviews``: Displaying Matching Views for a Given URL
+-----------------------------------------------------
.. seealso:: See also the output of :ref:`pviews --help <pviews_script>`.
@@ -31,7 +90,7 @@ to be ``main``.
Here is an example for a simple view configuration using :term:`traversal`:
-.. code-block:: text
+.. code-block:: bash
:linenos:
$VENV/bin/pviews development.ini#tutorial /FrontPage
@@ -54,7 +113,7 @@ permissions and predicates that are part of that view configuration.
A more complex configuration might generate something like this:
-.. code-block:: text
+.. code-block:: bash
:linenos:
$VENV/bin/pviews development.ini#shootout /about
@@ -114,8 +173,8 @@ found* message.
.. _interactive_shell:
-The Interactive Shell
----------------------
+``pshell``: The Interactive Shell
+---------------------------------
.. seealso:: See also the output of :ref:`pshell --help <pshell_script>`.
@@ -144,7 +203,7 @@ have an ``[app:main]`` section that looks like so:
If so, you can use the following command to invoke a debug shell using the name
``main`` as a section name:
-.. code-block:: text
+.. code-block:: bash
$VENV/bin/pshell starter/development.ini#main
Python 2.6.5 (r265:79063, Apr 29 2010, 00:31:32)
@@ -178,7 +237,7 @@ default :term:`root factory`, ``registry``, and ``request`` will be available.
You can also simply rely on the ``main`` default section name by omitting any
hash after the filename:
-.. code-block:: text
+.. code-block:: bash
$VENV/bin/pshell starter/development.ini
@@ -252,7 +311,7 @@ By defining the ``setup`` callable, we will create the module ``myapp.lib.pshell
When this ``.ini`` file is loaded, the extra variable ``models`` will be available for use immediately. Since a ``setup`` callable was also specified, it is executed and new variables ``testapp``, ``tm``, and ``dbsession`` are exposed, and the request is configured to generate URLs from the host ``http://www.example.com``. For example:
-.. code-block:: text
+.. code-block:: bash
$VENV/bin/pshell starter/development.ini
Python 2.6.5 (r265:79063, Apr 29 2010, 00:31:32)
@@ -296,13 +355,13 @@ installed such as ``pyramid_ipython`` it will normally be auto-selected and
used. You may also specifically invoke your choice with the ``-p choice`` or
``--python-shell choice`` option.
-.. code-block:: text
+.. code-block:: bash
$VENV/bin/pshell -p ipython development.ini#MyProject
You may use the ``--list-shells`` option to see the available shells.
-.. code-block:: text
+.. code-block:: bash
$VENV/bin/pshell --list-shells
Available shells:
@@ -363,8 +422,8 @@ specify a list of preferred shells.
.. _displaying_application_routes:
-Displaying All Application Routes
----------------------------------
+``proutes``: Displaying All Application Routes
+----------------------------------------------
.. seealso:: See also the output of :ref:`proutes --help <proutes_script>`.
@@ -378,7 +437,7 @@ the ``section_name`` is ``main`` and can be omitted.
For example:
-.. code-block:: text
+.. code-block:: bash
:linenos:
$VENV/bin/proutes development.ini
@@ -415,7 +474,7 @@ and use those as defaults.
For example you may remove the request method and place the view first:
-.. code-block:: text
+.. code-block:: ini
:linenos:
[proutes]
@@ -425,7 +484,7 @@ For example you may remove the request method and place the view first:
You can also separate the formats with commas or spaces:
-.. code-block:: text
+.. code-block:: ini
:linenos:
[proutes]
@@ -446,8 +505,8 @@ include. The current available formats are ``name``, ``pattern``, ``view``, and
.. _displaying_tweens:
-Displaying "Tweens"
--------------------
+``ptweens``: Displaying "Tweens"
+--------------------------------
.. seealso:: See also the output of :ref:`ptweens --help <ptweens_script>`.
@@ -462,7 +521,7 @@ standard Python dotted name in the ``ptweens`` output.
For example, here's the ``ptweens`` command run against a system configured
without any explicit tweens:
-.. code-block:: text
+.. code-block:: bash
:linenos:
$VENV/bin/ptweens development.ini
@@ -480,10 +539,10 @@ without any explicit tweens:
Here's the ``ptweens`` command run against a system configured *with* explicit
tweens defined in its ``development.ini`` file:
-.. code-block:: text
+.. code-block:: bash
:linenos:
- ptweens development.ini
+ $VENV/bin/ptweens development.ini
"pyramid.tweens" config value set (explicitly ordered tweens used)
Explicit Tween Chain (used)
@@ -534,8 +593,8 @@ See :ref:`registering_tweens` for more information about tweens.
.. _invoking_a_request:
-Invoking a Request
-------------------
+``prequest``: Invoking a Request
+--------------------------------
.. seealso:: See also the output of :ref:`prequest --help <prequest_script>`.
@@ -553,9 +612,11 @@ There are two required arguments to ``prequest``:
- The path: this should be the non-URL-quoted path element of the URL to the
resource you'd like to be rendered on the server. For example, ``/``.
-For example::
+For example:
+
+.. code-block:: bash
- $ $VENV/bin/prequest development.ini /
+ $VENV/bin/prequest development.ini /
This will print the body of the response to the console on which it was
invoked.
@@ -564,16 +625,20 @@ Several options are supported by ``prequest``. These should precede any config
file name or URL.
``prequest`` has a ``-d`` (i.e., ``--display-headers``) option which prints the
-status and headers returned by the server before the output::
+status and headers returned by the server before the output:
+
+.. code-block:: bash
- $ $VENV/bin/prequest -d development.ini /
+ $VENV/bin/prequest -d development.ini /
This will print the status, headers, and the body of the response to the
console.
-You can add request header values by using the ``--header`` option::
+You can add request header values by using the ``--header`` option:
+
+.. code-block:: bash
- $ $VENV/bin/prequest --header=Host:example.com development.ini /
+ $VENV/bin/prequest --header=Host:example.com development.ini /
Headers are added to the WSGI environment by converting them to their CGI/WSGI
equivalents (e.g., ``Host=example.com`` will insert the ``HTTP_HOST`` header
@@ -584,21 +649,11 @@ in the WSGI environment.
By default, ``prequest`` sends a ``GET`` request. You can change this by using
the ``-m`` (aka ``--method``) option. ``GET``, ``HEAD``, ``POST``, and
``DELETE`` are currently supported. When you use ``POST``, the standard input
-of the ``prequest`` process is used as the ``POST`` body::
-
- $ $VENV/bin/prequest -mPOST development.ini / < somefile
-
-
-Using Custom Arguments to Python when Running ``p*`` Scripts
-------------------------------------------------------------
-
-.. versionadded:: 1.5
+of the ``prequest`` process is used as the ``POST`` body:
-Each of Pyramid's console scripts (``pserve``, ``pviews``, etc.) can be run
-directly using ``python3 -m``, allowing custom arguments to be sent to the
-Python interpreter at runtime. For example::
+.. code-block:: bash
- python3 -m pyramid.scripts.pserve development.ini
+ $VENV/bin/prequest -mPOST development.ini / < somefile
.. index::
@@ -608,8 +663,8 @@ Python interpreter at runtime. For example::
.. _showing_distributions:
-Showing All Installed Distributions and Their Versions
-------------------------------------------------------
+``pdistreport``: Showing All Installed Distributions and Their Versions
+-----------------------------------------------------------------------
.. versionadded:: 1.5
@@ -618,17 +673,19 @@ Showing All Installed Distributions and Their Versions
You can use the ``pdistreport`` command to show the :app:`Pyramid` version in
use, the Python version in use, and all installed versions of Python
-distributions in your Python environment::
-
- $ $VENV/bin/pdistreport
- Pyramid version: 1.5dev
- Platform Linux-3.2.0-51-generic-x86_64-with-debian-wheezy-sid
- Packages:
- authapp 0.0
- /home/chrism/projects/foo/src/authapp
- beautifulsoup4 4.1.3
- /home/chrism/projects/foo/lib/python2.7/site-packages/beautifulsoup4-4.1.3-py2.7.egg
- ... more output ...
+distributions in your Python environment:
+
+.. code-block:: bash
+
+ $VENV/bin/pdistreport
+ Pyramid version: 1.5dev
+ Platform Linux-3.2.0-51-generic-x86_64-with-debian-wheezy-sid
+ Packages:
+ authapp 0.0
+ /home/chrism/projects/foo/src/authapp
+ beautifulsoup4 4.1.3
+ /home/chrism/projects/foo/lib/python2.7/site-packages/beautifulsoup4-4.1.3-py2.7.egg
+ # ... more output ...
``pdistreport`` takes no options. Its output is useful to paste into a
pastebin when you are having problems and need someone with more familiarity
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index 3ee6b5367..9293386f2 100644
--- a/docs/narr/introduction.rst
+++ b/docs/narr/introduction.rst
@@ -52,7 +52,7 @@ Modern
Tested
~~~~~~
-Untested code is broken by design. The :app:`Pyramid` community has a strong testing culture and our framework reflects that. Every release of :app:`Pyramid` has 100% statement coverage (as measured by `coverage <https://coverage.readthedocs.io/en/latest/>`_) and 95% decision/condition coverage. (as measured by `instrumental <https://instrumental.readthedocs.io/en/latest/intro.html>`_) It is automatically tested using `Travis <https://travis-ci.org/Pylons/pyramid>`_ and `Jenkins <http://jenkins.pylonsproject.org/job/pyramid/>`_ on supported versions of Python after each commit to its GitHub repository. `Official Pyramid add-ons <https://trypyramid.com/resources-extending-pyramid.html>`_ are held to a similar testing standard.
+Untested code is broken by design. The :app:`Pyramid` community has a strong testing culture and our framework reflects that. Every release of :app:`Pyramid` has 100% statement coverage (as measured by `coverage <https://coverage.readthedocs.io/en/latest/>`_) and 95% decision/condition coverage. (as measured by `instrumental <https://instrumental.readthedocs.io/en/latest/intro.html>`_) It is automatically tested using `Travis <https://travis-ci.org/Pylons/pyramid>`_ and `Jenkins <http://jenkins.pylonsproject.org/job/pyramid/>`_ on supported versions of Python after each commit to its GitHub repository. `Official Pyramid add-ons <https://trypyramid.com/extending-pyramid.html>`_ are held to a similar testing standard.
We still find bugs in :app:`Pyramid`, but we've noticed we find a lot fewer of them while working on projects with a solid testing regime.
@@ -173,7 +173,7 @@ Supported :app:`Pyramid` add-ons are held to the same demanding standards as the
.. seealso::
- See also https://trypyramid.com/resources-extending-pyramid.html
+ See also https://trypyramid.com/extending-pyramid.html
Write your views, *your* way
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/docs/narr/myproject/.gitignore b/docs/narr/myproject/.gitignore
new file mode 100644
index 000000000..1853d983c
--- /dev/null
+++ b/docs/narr/myproject/.gitignore
@@ -0,0 +1,21 @@
+*.egg
+*.egg-info
+*.pyc
+*$py.class
+*~
+.coverage
+coverage.xml
+build/
+dist/
+.tox/
+nosetests.xml
+env*/
+tmp/
+Data.fs*
+*.sublime-project
+*.sublime-workspace
+.*.sw?
+.sw?
+.DS_Store
+coverage
+test
diff --git a/docs/narr/myproject/myproject/__init__.py b/docs/narr/myproject/myproject/__init__.py
index 49dde36d4..a3d5a6469 100644
--- a/docs/narr/myproject/myproject/__init__.py
+++ b/docs/narr/myproject/myproject/__init__.py
@@ -4,9 +4,8 @@ from pyramid.config import Configurator
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- config = Configurator(settings=settings)
- config.include('pyramid_jinja2')
- config.add_static_view('static', 'static', cache_max_age=3600)
- config.add_route('home', '/')
- config.scan()
+ with Configurator(settings=settings) as config:
+ config.include('pyramid_jinja2')
+ config.include('.routes')
+ config.scan()
return config.make_wsgi_app()
diff --git a/docs/narr/myproject/myproject/routes.py b/docs/narr/myproject/myproject/routes.py
new file mode 100644
index 000000000..25504ad4d
--- /dev/null
+++ b/docs/narr/myproject/myproject/routes.py
@@ -0,0 +1,3 @@
+def includeme(config):
+ config.add_static_view('static', 'static', cache_max_age=3600)
+ config.add_route('home', '/')
diff --git a/docs/narr/myproject/myproject/templates/404.jinja2 b/docs/narr/myproject/myproject/templates/404.jinja2
new file mode 100644
index 000000000..aaf12413f
--- /dev/null
+++ b/docs/narr/myproject/myproject/templates/404.jinja2
@@ -0,0 +1,8 @@
+{% extends "layout.jinja2" %}
+
+{% block content %}
+<div class="content">
+ <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Starter project</span></h1>
+ <p class="lead"><span class="font-semi-bold">404</span> Page Not Found</p>
+</div>
+{% endblock content %}
diff --git a/docs/narr/myproject/myproject/tests.py b/docs/narr/myproject/myproject/tests.py
index fd414cced..05ccadcfb 100644
--- a/docs/narr/myproject/myproject/tests.py
+++ b/docs/narr/myproject/myproject/tests.py
@@ -11,7 +11,7 @@ class ViewTests(unittest.TestCase):
testing.tearDown()
def test_my_view(self):
- from .views import my_view
+ from .views.default import my_view
request = testing.DummyRequest()
info = my_view(request)
self.assertEqual(info['project'], 'MyProject')
diff --git a/docs/narr/myproject/myproject/views.py b/docs/narr/myproject/myproject/views.py
deleted file mode 100644
index 9e9ec4320..000000000
--- a/docs/narr/myproject/myproject/views.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from pyramid.view import view_config
-
-
-@view_config(route_name='home', renderer='templates/mytemplate.jinja2')
-def my_view(request):
- return {'project': 'MyProject'}
diff --git a/docs/narr/myproject/myproject/views/__init__.py b/docs/narr/myproject/myproject/views/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/docs/narr/myproject/myproject/views/__init__.py
diff --git a/docs/narr/myproject/myproject/views/default.py b/docs/narr/myproject/myproject/views/default.py
new file mode 100644
index 000000000..8324cfe32
--- /dev/null
+++ b/docs/narr/myproject/myproject/views/default.py
@@ -0,0 +1,6 @@
+from pyramid.view import view_config
+
+
+@view_config(route_name='home', renderer='../templates/mytemplate.jinja2')
+def my_view(request):
+ return {'project': 'myproject'}
diff --git a/docs/narr/myproject/myproject/views/notfound.py b/docs/narr/myproject/myproject/views/notfound.py
new file mode 100644
index 000000000..69d6e2804
--- /dev/null
+++ b/docs/narr/myproject/myproject/views/notfound.py
@@ -0,0 +1,7 @@
+from pyramid.view import notfound_view_config
+
+
+@notfound_view_config(renderer='../templates/404.jinja2')
+def notfound_view(request):
+ request.response.status = 404
+ return {}
diff --git a/docs/narr/myproject/setup.py b/docs/narr/myproject/setup.py
index 153a659ba..cf626880f 100644
--- a/docs/narr/myproject/setup.py
+++ b/docs/narr/myproject/setup.py
@@ -18,7 +18,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index f41e155e7..fb5a241db 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -525,21 +525,27 @@ The ``myproject`` project we've generated has the following directory structure:
.. code-block:: text
- myproject/
+ myproject
├── .coveragerc
+ ├── .gitignore
├── CHANGES.txt
├── MANIFEST.in
├── myproject
│   ├── __init__.py
+ │   ├── routes.py
│   ├── static
│   │   ├── pyramid-16x16.png
│   │   ├── pyramid.png
│   │   └── theme.css
│   ├── templates
+ │   │   ├── 404.jinja2
│   │   ├── layout.jinja2
│   │   └── mytemplate.jinja2
│   ├── tests.py
- │   └── views.py
+ │   └── views
+ │   ├── __init__.py
+ │   ├── default.py
+ │   └── notfound.py
├── README.txt
├── development.ini
├── production.ini
@@ -557,6 +563,8 @@ describe, run, and test your application.
#. ``.coveragerc`` configures coverage when running tests.
+#. ``.gitignore`` tells git which files and directories to ignore from source code version control.
+
#. ``CHANGES.txt`` describes the changes you've made to the application. It is
conventionally written in :term:`reStructuredText` format.
@@ -810,7 +818,9 @@ The ``myproject`` :term:`package` lives inside the ``myproject``
#. A ``tests.py`` module, which contains unit test code for the application.
-#. A ``views.py`` module, which contains view code for the application.
+#. A ``views`` package, which contains view code for the application.
+
+#. A ``static`` directory, which contains static files, including images and CSS.
These are purely conventions established by the cookiecutter. :app:`Pyramid`
doesn't insist that you name things in any particular way. However, it's
@@ -848,31 +858,53 @@ also informs Python that the directory which contains it is a *package*.
Line 8 adds support for Jinja2 templating bindings, allowing us to
specify renderers with the ``.jinja2`` extension.
- Line 9 registers a static view, which will serve up the files from the
- ``myproject:static`` :term:`asset specification` (the ``static`` directory
- of the ``myproject`` package).
+ Line 9 includes the ``routes.py`` module.
- Line 10 adds a :term:`route` to the configuration. This route is later used
- by a view in the ``views`` module.
-
- Line 11 calls ``config.scan()``, which picks up view registrations declared
+ Line 10 calls ``config.scan()``, which picks up view registrations declared
elsewhere in the package (in this case, in the ``views.py`` module).
- Line 12 returns a :term:`WSGI` application to the caller of the function
+ Line 11 returns a :term:`WSGI` application to the caller of the function
(Pyramid's pserve).
+
+.. index::
+ single: routes.py
+
+.. _routes_py:
+
+``routes.py``
+~~~~~~~~~~~~~
+
+The ``routes.py`` module gets included by the ``main`` function in our ``__init__.py``.
+It registers a view and a route.
+
+.. literalinclude:: myproject/myproject/routes.py
+ :language: python
+ :linenos:
+
+Line 2 registers a static view, which will serve up the files from the ``myproject:static`` :term:`asset specification` (the ``static`` directory of the ``myproject`` package).
+
+Line 3 adds a :term:`route` to the configuration. This route is later used by a view in the ``views`` module.
+
+
.. index::
single: views.py
-``views.py``
-~~~~~~~~~~~~
+``views`` package
+~~~~~~~~~~~~~~~~~
Much of the heavy lifting in a :app:`Pyramid` application is done by *view
callables*. A :term:`view callable` is the main tool of a :app:`Pyramid` web
application developer; it is a bit of code which accepts a :term:`request` and
which returns a :term:`response`.
-.. literalinclude:: myproject/myproject/views.py
+Our project has a ``views`` package by virtue of it being a directory containing an ``__init__.py`` file.
+This ``__init__.py`` file happens to have no content, although it could as a project develops.
+
+We have two view modules in the ``views`` package.
+Let's look at ``default.py``.
+
+.. literalinclude:: myproject/myproject/views/default.py
:language: python
:linenos:
@@ -880,17 +912,17 @@ Lines 4-6 define and register a :term:`view callable` named ``my_view``. The
function named ``my_view`` is decorated with a ``view_config`` decorator (which
is processed by the ``config.scan()`` line in our ``__init__.py``). The
view_config decorator asserts that this view be found when a :term:`route`
-named ``home`` is matched. In our case, because our ``__init__.py`` maps the
+named ``home`` is matched. In our case, because our ``routes.py`` maps the
route named ``home`` to the URL pattern ``/``, this route will match when a
visitor visits the root URL. The view_config decorator also names a
``renderer``, which in this case is a template that will be used to render the
result of the view callable. This particular view declaration points at
-``templates/mytemplate.pt``, which is an :term:`asset specification` that
-specifies the ``mytemplate.pt`` file within the ``templates`` directory of the
+``../templates/mytemplate.jinja2``, which is an :term:`asset specification` that
+specifies the ``mytemplate.jinja2`` file within the ``templates`` directory of the
``myproject`` package. The asset specification could have also been specified
-as ``myproject:templates/mytemplate.pt``; the leading package name and colon is
+as ``myproject:templates/mytemplate.jinja2``; the leading package name and colon is
optional. The template file pointed to is a :term:`Jinja2` template
-file (``templates/my_template.jinja2``).
+file (``templates/mytemplate.jinja2``).
This view callable function is handed a single piece of information: the
:term:`request`. The *request* is an instance of the :term:`WebOb` ``Request``
@@ -903,6 +935,15 @@ the HTML in a :term:`response`.
.. note:: Dictionaries provide values to :term:`template`\s.
+Now let's look at ``notfound.py``.
+
+.. literalinclude:: myproject/myproject/views/notfound.py
+ :language: python
+ :linenos:
+
+This file is similar to ``default.py``.
+It merely returns a ``404`` response status and an empty dictionary to the template at ``../templates/404.jinja2``.
+
.. note:: When the application is run with the cookiecutter's :ref:`default
development.ini <myproject_ini>` configuration, :ref:`logging is set up
<myproject_ini_logging>` to aid debugging. If an exception is raised,
@@ -964,7 +1005,7 @@ This is the base layout content. It contains a single marker for content block.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is the content :term:`Jinja2` template that exists in the project. It is referenced by the call to ``@view_config`` as the ``renderer``
-of the ``my_view`` view callable in the ``views.py`` file. See
+of the ``my_view`` view callable in the ``views/default.py`` file. See
:ref:`views_which_use_a_renderer` for more information about renderers. It inherits ("extends") the HTML provided by ``layout.jinja2``, replacing the content block with its own content.
.. literalinclude:: myproject/myproject/templates/mytemplate.jinja2
@@ -976,6 +1017,18 @@ functions themselves. See :ref:`templates_used_directly` and
:ref:`templates_used_as_renderers`.
+``templates/404.jinja2``
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+This template is similar to ``mytemplate.jinja2``, but with a few differences.
+It is referenced by the call to ``@notfound_view_config`` as the ``renderer`` of the ``notfound_view`` view callable in the ``views/notfound.py`` file.
+It inherits the HTML provided by ``layout.jinja2``, replacing the content block with its own content.
+
+.. literalinclude:: myproject/myproject/templates/404.jinja2
+ :language: jinja
+ :linenos:
+
+
.. index::
single: tests.py
@@ -1015,32 +1068,11 @@ cookiecutter, you can decide to lay your code out any way you see fit.
For example, the configuration method named
:meth:`~pyramid.config.Configurator.add_view` requires you to pass a
:term:`dotted Python name` or a direct object reference as the class or
-function to be used as a view. By default, the ``starter`` cookiecutter would have
-you add view functions to the ``views.py`` module in your package. However, you
-might be more comfortable creating a ``views`` *directory*, and adding a single
-file for each view.
-
-If your project package name was ``myproject`` and you wanted to arrange all
-your views in a Python subpackage within the ``myproject`` :term:`package`
-named ``views`` instead of within a single ``views.py`` file, you might do the
-following.
-
-- Create a ``views`` directory inside your ``myproject`` package directory (the
- same directory which holds ``views.py``).
-
-- Create a file within the new ``views`` directory named ``__init__.py``. (It
- can be empty. This just tells Python that the ``views`` directory is a
- *package*.)
-
-- *Move* the content from the existing ``views.py`` file to a file inside the
- new ``views`` directory named, say, ``blog.py``. Because the ``templates``
- directory remains in the ``myproject`` package, the template :term:`asset
- specification` values in ``blog.py`` must now be fully qualified with the
- project's package name (``myproject:templates/blog.pt``).
-
-You can then continue to add view callable functions to the ``blog.py`` module,
-but you can also add other ``.py`` files which contain view callable functions
-to the ``views`` directory. As long as you use the ``@view_config`` directive
+function to be used as a view.
+By default, the ``starter`` cookiecutter would have you create a ``views`` directory, and add a single file for each view or collection of related views.
+However, you might be more comfortable creating a single ``views.py`` module in your package and add view functions to it.
+
+Whatever structure you prefer, as long as you use the ``@view_config`` directive
to register views in conjunction with ``config.scan()``, they will be picked up
automatically when the application is restarted.
diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst
index 6c88dcec5..ded7e87e3 100644
--- a/docs/narr/sessions.rst
+++ b/docs/narr/sessions.rst
@@ -57,18 +57,70 @@ using the :meth:`pyramid.config.Configurator.set_session_factory` method.
.. warning::
By default the :func:`~pyramid.session.SignedCookieSessionFactory`
- implementation is *unencrypted*. You should not use it when you keep
- sensitive information in the session object, as the information can be
- easily read by both users of your application and third parties who have
- access to your users' network traffic. And, if you use this sessioning
- implementation, and you inadvertently create a cross-site scripting
- vulnerability in your application, because the session data is stored
- unencrypted in a cookie, it will also be easier for evildoers to obtain the
- current user's cross-site scripting token. In short, use a different
- session factory implementation (preferably one which keeps session data on
- the server) for anything but the most basic of applications where "session
- security doesn't matter", and you are sure your application has no
- cross-site scripting vulnerabilities.
+ implementation contains the following security concerns:
+
+ - Session data is *unencrypted* (but it is signed / authenticated).
+
+ This means an attacker cannot change the session data, but they can view it.
+ You should not use it when you keep sensitive information in the session object, as the information can be easily read by both users of your application and third parties who have access to your users' network traffic.
+
+ At the very least, use TLS and set ``secure=True`` to avoid arbitrary users on the network from viewing the session contents.
+
+ - If you use this sessioning implementation, and you inadvertently create a cross-site scripting vulnerability in your application, because the session data is stored unencrypted in a cookie, it will also be easier for evildoers to obtain the current user's cross-site scripting token.
+
+ Set ``httponly=True`` to mitigate this vulnerability by hiding the cookie from client-side JavaScript.
+
+ - The default serialization method, while replaceable with something like JSON, is implemented using pickle which can lead to remote code execution if your secret key is compromised.
+
+ To mitigate this, set ``serializer=pyramid.session.JSONSerializer()`` to use :class:`pyramid.session.JSONSerializer`. This option will be the default in :app:`Pyramid` 2.0.
+ See :ref:`pickle_session_deprecation` for more information about this change.
+
+ In short, use a different session factory implementation (preferably one which keeps session data on the server) for anything but the most basic of applications where "session security doesn't matter", you are sure your application has no cross-site scripting vulnerabilities, and you are confident your secret key will not be exposed.
+
+.. index::
+ triple: pickle deprecation; JSON-serializable; ISession interface
+
+.. _pickle_session_deprecation:
+
+Upcoming Changes to ISession in Pyramid 2.0
+-------------------------------------------
+
+In :app:`Pyramid` 2.0 the :class:`pyramid.interfaces.ISession` interface will be changing to require that session implementations only need to support JSON-serializable data types.
+This is a stricter contract than the current requirement that all objects be pickleable and it is being done for security purposes.
+This is a backward-incompatible change.
+Currently, if a client-side session implementation is compromised, it leaves the application vulnerable to remote code execution attacks using specially-crafted sessions that execute code when deserialized.
+
+For users with compatibility concerns, it's possible to craft a serializer that can handle both formats until you are satisfied that clients have had time to reasonably upgrade.
+Remember that sessions should be short-lived and thus the number of clients affected should be small (no longer than an auth token, at a maximum). An example serializer:
+
+.. code-block:: python
+ :linenos:
+
+ from pyramid.session import JSONSerializer
+ from pyramid.session import PickleSerializer
+ from pyramid.session import SignedCookieSessionFactory
+
+ class JSONSerializerWithPickleFallback(object):
+ def __init__(self):
+ self.json = JSONSerializer()
+ self.pickle = PickleSerializer()
+
+ def dumps(self, value):
+ # maybe catch serialization errors here and keep using pickle
+ # while finding spots in your app that are not storing
+ # JSON-serializable objects, falling back to pickle
+ return self.json.dumps(value)
+
+ def loads(self, value):
+ try:
+ return self.json.loads(value)
+ except ValueError:
+ return self.pickle.loads(value)
+
+ # somewhere in your configuration code
+ serializer = JSONSerializerWithPickleFallback()
+ session_factory = SignedCookieSessionFactory(..., serializer=serializer)
+ config.set_session_factory(session_factory)
.. index::
single: session object
@@ -130,7 +182,7 @@ Some gotchas:
that they are instances of basic types of objects, such as strings, lists,
dictionaries, tuples, integers, etc. If you place an object in a session
data key or value that is not pickleable, an error will be raised when the
- session is serialized.
+ session is serialized. Please also see :ref:`pickle_session_deprecation`.
- If you place a mutable value (for example, a list or a dictionary) in a
session object, and you subsequently mutate that value, you must call the
diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst
index 8f4d806e6..ad4ba2186 100644
--- a/docs/narr/testing.rst
+++ b/docs/narr/testing.rst
@@ -396,10 +396,10 @@ As always, whenever you change your dependencies, make sure to run the correct
$VENV/bin/pip install -e ".[testing]"
In your ``MyPackage`` project, your :term:`package` is named ``myproject``
-which contains a ``views`` module, which in turn contains a :term:`view`
+which contains a ``views`` package containing a ``default.py`` module, which in turn contains a :term:`view`
function ``my_view`` that returns an HTML body when the root URL is invoked:
- .. literalinclude:: myproject/myproject/views.py
+ .. literalinclude:: myproject/myproject/views/default.py
:linenos:
:language: python
diff --git a/docs/pscripts/pcreate.rst b/docs/pscripts/pcreate.rst
index c48a70acd..e2c45626a 100644
--- a/docs/pscripts/pcreate.rst
+++ b/docs/pscripts/pcreate.rst
@@ -6,4 +6,4 @@
.. autoprogram:: pyramid.scripts.pcreate:PCreateCommand.parser
:prog: pcreate
-.. seealso:: :ref:`creating_a_project`
+.. seealso:: :ref:`creating_a_project` and :ref:`running-pscripts`.
diff --git a/docs/pscripts/pdistreport.rst b/docs/pscripts/pdistreport.rst
index b3c9dffd8..fa07f53ad 100644
--- a/docs/pscripts/pdistreport.rst
+++ b/docs/pscripts/pdistreport.rst
@@ -6,4 +6,4 @@
.. autoprogram:: pyramid.scripts.pdistreport:get_parser()
:prog: pdistreport
-.. seealso:: :ref:`showing_distributions`
+.. seealso:: :ref:`showing_distributions` and :ref:`running-pscripts`.
diff --git a/docs/pscripts/prequest.rst b/docs/pscripts/prequest.rst
index 64ed01739..3767506fb 100644
--- a/docs/pscripts/prequest.rst
+++ b/docs/pscripts/prequest.rst
@@ -6,4 +6,4 @@
.. autoprogram:: pyramid.scripts.prequest:PRequestCommand.parser
:prog: prequest
-.. seealso:: :ref:`invoking_a_request`
+.. seealso:: :ref:`invoking_a_request` and :ref:`running-pscripts`.
diff --git a/docs/pscripts/proutes.rst b/docs/pscripts/proutes.rst
index ee7c209e3..282ef327f 100644
--- a/docs/pscripts/proutes.rst
+++ b/docs/pscripts/proutes.rst
@@ -6,4 +6,4 @@
.. autoprogram:: pyramid.scripts.proutes:PRoutesCommand.parser
:prog: proutes
-.. seealso:: :ref:`displaying_application_routes`
+.. seealso:: :ref:`displaying_application_routes` and :ref:`running-pscripts`.
diff --git a/docs/pscripts/pserve.rst b/docs/pscripts/pserve.rst
index 991976aea..cc3c80c91 100644
--- a/docs/pscripts/pserve.rst
+++ b/docs/pscripts/pserve.rst
@@ -6,4 +6,4 @@
.. autoprogram:: pyramid.scripts.pserve:PServeCommand.parser
:prog: pserve
-.. seealso:: :ref:`running_the_project_application`
+.. seealso:: :ref:`running_the_project_application` and :ref:`running-pscripts`.
diff --git a/docs/pscripts/pshell.rst b/docs/pscripts/pshell.rst
index 4e2ce74cb..7c9050826 100644
--- a/docs/pscripts/pshell.rst
+++ b/docs/pscripts/pshell.rst
@@ -6,4 +6,4 @@
.. autoprogram:: pyramid.scripts.pshell:PShellCommand.parser
:prog: pshell
-.. seealso:: :ref:`interactive_shell`
+.. seealso:: :ref:`interactive_shell` and :ref:`running-pscripts`.
diff --git a/docs/pscripts/ptweens.rst b/docs/pscripts/ptweens.rst
index f586e1467..fe9c27abd 100644
--- a/docs/pscripts/ptweens.rst
+++ b/docs/pscripts/ptweens.rst
@@ -6,4 +6,4 @@
.. autoprogram:: pyramid.scripts.ptweens:PTweensCommand.parser
:prog: ptweens
-.. seealso:: :ref:`displaying_tweens`
+.. seealso:: :ref:`displaying_tweens` and :ref:`running-pscripts`.
diff --git a/docs/pscripts/pviews.rst b/docs/pscripts/pviews.rst
index da4660779..0726cb6aa 100644
--- a/docs/pscripts/pviews.rst
+++ b/docs/pscripts/pviews.rst
@@ -6,4 +6,4 @@
.. autoprogram:: pyramid.scripts.pviews:PViewsCommand.parser
:prog: pviews
-.. seealso:: :ref:`displaying_matching_views`
+.. seealso:: :ref:`displaying_matching_views` and :ref:`running-pscripts`.
diff --git a/docs/quick_tour.rst b/docs/quick_tour.rst
index c61cbfdfd..26195a701 100644
--- a/docs/quick_tour.rst
+++ b/docs/quick_tour.rst
@@ -755,14 +755,14 @@ Pyramid (for example, when a new request comes in).
Maybe you would like to log messages in your code? In your Python module,
import and set up the logging in your ``views.py``:
-.. literalinclude:: quick_tour/logging/hello_world/views.py
+.. literalinclude:: quick_tour/logging/hello_world/views/default.py
:language: python
:lineno-match:
:lines: 3-4
You can now, in your code, log messages:
-.. literalinclude:: quick_tour/logging/hello_world/views.py
+.. literalinclude:: quick_tour/logging/hello_world/views/default.py
:language: python
:lineno-match:
:lines: 7-8
@@ -819,13 +819,13 @@ Now make a "factory" and pass it to the :term:`configurator`'s
.. literalinclude:: quick_tour/sessions/hello_world/__init__.py
:language: python
:lineno-match:
- :lines: 10-13
+ :lines: 9-12
:emphasize-lines: 2-3
Pyramid's :term:`request` object now has a ``session`` attribute that we can
use in our view code in ``views.py``:
-.. literalinclude:: quick_tour/sessions/hello_world/views.py
+.. literalinclude:: quick_tour/sessions/hello_world/views/default.py
:language: python
:lineno-match:
:lines: 7-
diff --git a/docs/quick_tour/logging/.gitignore b/docs/quick_tour/logging/.gitignore
new file mode 100644
index 000000000..1853d983c
--- /dev/null
+++ b/docs/quick_tour/logging/.gitignore
@@ -0,0 +1,21 @@
+*.egg
+*.egg-info
+*.pyc
+*$py.class
+*~
+.coverage
+coverage.xml
+build/
+dist/
+.tox/
+nosetests.xml
+env*/
+tmp/
+Data.fs*
+*.sublime-project
+*.sublime-workspace
+.*.sw?
+.sw?
+.DS_Store
+coverage
+test
diff --git a/docs/quick_tour/logging/hello_world/__init__.py b/docs/quick_tour/logging/hello_world/__init__.py
index 49dde36d4..a3d5a6469 100644
--- a/docs/quick_tour/logging/hello_world/__init__.py
+++ b/docs/quick_tour/logging/hello_world/__init__.py
@@ -4,9 +4,8 @@ from pyramid.config import Configurator
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- config = Configurator(settings=settings)
- config.include('pyramid_jinja2')
- config.add_static_view('static', 'static', cache_max_age=3600)
- config.add_route('home', '/')
- config.scan()
+ with Configurator(settings=settings) as config:
+ config.include('pyramid_jinja2')
+ config.include('.routes')
+ config.scan()
return config.make_wsgi_app()
diff --git a/docs/quick_tour/logging/hello_world/routes.py b/docs/quick_tour/logging/hello_world/routes.py
new file mode 100644
index 000000000..25504ad4d
--- /dev/null
+++ b/docs/quick_tour/logging/hello_world/routes.py
@@ -0,0 +1,3 @@
+def includeme(config):
+ config.add_static_view('static', 'static', cache_max_age=3600)
+ config.add_route('home', '/')
diff --git a/docs/quick_tour/logging/hello_world/templates/404.jinja2 b/docs/quick_tour/logging/hello_world/templates/404.jinja2
new file mode 100644
index 000000000..aaf12413f
--- /dev/null
+++ b/docs/quick_tour/logging/hello_world/templates/404.jinja2
@@ -0,0 +1,8 @@
+{% extends "layout.jinja2" %}
+
+{% block content %}
+<div class="content">
+ <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Starter project</span></h1>
+ <p class="lead"><span class="font-semi-bold">404</span> Page Not Found</p>
+</div>
+{% endblock content %}
diff --git a/docs/quick_tour/logging/hello_world/tests.py b/docs/quick_tour/logging/hello_world/tests.py
index ee9745685..f01ae2a3c 100644
--- a/docs/quick_tour/logging/hello_world/tests.py
+++ b/docs/quick_tour/logging/hello_world/tests.py
@@ -11,7 +11,7 @@ class ViewTests(unittest.TestCase):
testing.tearDown()
def test_my_view(self):
- from .views import my_view
+ from .views.default import my_view
request = testing.DummyRequest()
info = my_view(request)
self.assertEqual(info['project'], 'hello_world')
diff --git a/docs/quick_tour/logging/hello_world/views/__init__.py b/docs/quick_tour/logging/hello_world/views/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/docs/quick_tour/logging/hello_world/views/__init__.py
diff --git a/docs/quick_tour/logging/hello_world/views.py b/docs/quick_tour/logging/hello_world/views/default.py
index a648d6ba3..bbb99d78c 100644
--- a/docs/quick_tour/logging/hello_world/views.py
+++ b/docs/quick_tour/logging/hello_world/views/default.py
@@ -3,7 +3,7 @@ from pyramid.view import view_config
import logging
log = logging.getLogger(__name__)
-@view_config(route_name='home', renderer='templates/mytemplate.jinja2')
+@view_config(route_name='home', renderer='../templates/mytemplate.jinja2')
def my_view(request):
log.debug('Some Message')
return {'project': 'hello_world'}
diff --git a/docs/quick_tour/logging/hello_world/views/notfound.py b/docs/quick_tour/logging/hello_world/views/notfound.py
new file mode 100644
index 000000000..69d6e2804
--- /dev/null
+++ b/docs/quick_tour/logging/hello_world/views/notfound.py
@@ -0,0 +1,7 @@
+from pyramid.view import notfound_view_config
+
+
+@notfound_view_config(renderer='../templates/404.jinja2')
+def notfound_view(request):
+ request.response.status = 404
+ return {}
diff --git a/docs/quick_tour/logging/setup.py b/docs/quick_tour/logging/setup.py
index 44d90b990..27b025384 100644
--- a/docs/quick_tour/logging/setup.py
+++ b/docs/quick_tour/logging/setup.py
@@ -18,7 +18,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/quick_tour/package/.gitignore b/docs/quick_tour/package/.gitignore
new file mode 100644
index 000000000..1853d983c
--- /dev/null
+++ b/docs/quick_tour/package/.gitignore
@@ -0,0 +1,21 @@
+*.egg
+*.egg-info
+*.pyc
+*$py.class
+*~
+.coverage
+coverage.xml
+build/
+dist/
+.tox/
+nosetests.xml
+env*/
+tmp/
+Data.fs*
+*.sublime-project
+*.sublime-workspace
+.*.sw?
+.sw?
+.DS_Store
+coverage
+test
diff --git a/docs/quick_tour/package/hello_world/__init__.py b/docs/quick_tour/package/hello_world/__init__.py
index 49dde36d4..a3d5a6469 100644
--- a/docs/quick_tour/package/hello_world/__init__.py
+++ b/docs/quick_tour/package/hello_world/__init__.py
@@ -4,9 +4,8 @@ from pyramid.config import Configurator
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- config = Configurator(settings=settings)
- config.include('pyramid_jinja2')
- config.add_static_view('static', 'static', cache_max_age=3600)
- config.add_route('home', '/')
- config.scan()
+ with Configurator(settings=settings) as config:
+ config.include('pyramid_jinja2')
+ config.include('.routes')
+ config.scan()
return config.make_wsgi_app()
diff --git a/docs/quick_tour/package/hello_world/routes.py b/docs/quick_tour/package/hello_world/routes.py
new file mode 100644
index 000000000..25504ad4d
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/routes.py
@@ -0,0 +1,3 @@
+def includeme(config):
+ config.add_static_view('static', 'static', cache_max_age=3600)
+ config.add_route('home', '/')
diff --git a/docs/quick_tour/package/hello_world/templates/404.jinja2 b/docs/quick_tour/package/hello_world/templates/404.jinja2
new file mode 100644
index 000000000..aaf12413f
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/templates/404.jinja2
@@ -0,0 +1,8 @@
+{% extends "layout.jinja2" %}
+
+{% block content %}
+<div class="content">
+ <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Starter project</span></h1>
+ <p class="lead"><span class="font-semi-bold">404</span> Page Not Found</p>
+</div>
+{% endblock content %}
diff --git a/docs/quick_tour/package/hello_world/tests.py b/docs/quick_tour/package/hello_world/tests.py
index ee9745685..f01ae2a3c 100644
--- a/docs/quick_tour/package/hello_world/tests.py
+++ b/docs/quick_tour/package/hello_world/tests.py
@@ -11,7 +11,7 @@ class ViewTests(unittest.TestCase):
testing.tearDown()
def test_my_view(self):
- from .views import my_view
+ from .views.default import my_view
request = testing.DummyRequest()
info = my_view(request)
self.assertEqual(info['project'], 'hello_world')
diff --git a/docs/quick_tour/package/hello_world/views/__init__.py b/docs/quick_tour/package/hello_world/views/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/views/__init__.py
diff --git a/docs/quick_tour/package/hello_world/views.py b/docs/quick_tour/package/hello_world/views/default.py
index 67f78dad7..7458da006 100644
--- a/docs/quick_tour/package/hello_world/views.py
+++ b/docs/quick_tour/package/hello_world/views/default.py
@@ -1,6 +1,6 @@
from pyramid.view import view_config
-@view_config(route_name='home', renderer='templates/mytemplate.jinja2')
+@view_config(route_name='home', renderer='../templates/mytemplate.jinja2')
def my_view(request):
return {'project': 'hello_world'}
diff --git a/docs/quick_tour/package/hello_world/views/notfound.py b/docs/quick_tour/package/hello_world/views/notfound.py
new file mode 100644
index 000000000..69d6e2804
--- /dev/null
+++ b/docs/quick_tour/package/hello_world/views/notfound.py
@@ -0,0 +1,7 @@
+from pyramid.view import notfound_view_config
+
+
+@notfound_view_config(renderer='../templates/404.jinja2')
+def notfound_view(request):
+ request.response.status = 404
+ return {}
diff --git a/docs/quick_tour/package/setup.py b/docs/quick_tour/package/setup.py
index 44d90b990..27b025384 100644
--- a/docs/quick_tour/package/setup.py
+++ b/docs/quick_tour/package/setup.py
@@ -18,7 +18,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/quick_tour/sessions/.gitignore b/docs/quick_tour/sessions/.gitignore
new file mode 100644
index 000000000..1853d983c
--- /dev/null
+++ b/docs/quick_tour/sessions/.gitignore
@@ -0,0 +1,21 @@
+*.egg
+*.egg-info
+*.pyc
+*$py.class
+*~
+.coverage
+coverage.xml
+build/
+dist/
+.tox/
+nosetests.xml
+env*/
+tmp/
+Data.fs*
+*.sublime-project
+*.sublime-workspace
+.*.sw?
+.sw?
+.DS_Store
+coverage
+test
diff --git a/docs/quick_tour/sessions/hello_world/__init__.py b/docs/quick_tour/sessions/hello_world/__init__.py
index 7cdc55ebe..c2b9f68c7 100644
--- a/docs/quick_tour/sessions/hello_world/__init__.py
+++ b/docs/quick_tour/sessions/hello_world/__init__.py
@@ -4,11 +4,10 @@ from pyramid.session import SignedCookieSessionFactory
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- config = Configurator(settings=settings)
- config.include('pyramid_jinja2')
- config.add_static_view('static', 'static', cache_max_age=3600)
- config.add_route('home', '/')
- my_session_factory = SignedCookieSessionFactory('itsaseekreet')
- config.set_session_factory(my_session_factory)
- config.scan()
+ with Configurator(settings=settings) as config:
+ config.include('pyramid_jinja2')
+ config.include('.routes')
+ my_session_factory = SignedCookieSessionFactory('itsaseekreet')
+ config.set_session_factory(my_session_factory)
+ config.scan()
return config.make_wsgi_app()
diff --git a/docs/quick_tour/sessions/hello_world/routes.py b/docs/quick_tour/sessions/hello_world/routes.py
new file mode 100644
index 000000000..25504ad4d
--- /dev/null
+++ b/docs/quick_tour/sessions/hello_world/routes.py
@@ -0,0 +1,3 @@
+def includeme(config):
+ config.add_static_view('static', 'static', cache_max_age=3600)
+ config.add_route('home', '/')
diff --git a/docs/quick_tour/sessions/hello_world/templates/404.jinja2 b/docs/quick_tour/sessions/hello_world/templates/404.jinja2
new file mode 100644
index 000000000..aaf12413f
--- /dev/null
+++ b/docs/quick_tour/sessions/hello_world/templates/404.jinja2
@@ -0,0 +1,8 @@
+{% extends "layout.jinja2" %}
+
+{% block content %}
+<div class="content">
+ <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Starter project</span></h1>
+ <p class="lead"><span class="font-semi-bold">404</span> Page Not Found</p>
+</div>
+{% endblock content %}
diff --git a/docs/quick_tour/sessions/hello_world/tests.py b/docs/quick_tour/sessions/hello_world/tests.py
index ee9745685..f01ae2a3c 100644
--- a/docs/quick_tour/sessions/hello_world/tests.py
+++ b/docs/quick_tour/sessions/hello_world/tests.py
@@ -11,7 +11,7 @@ class ViewTests(unittest.TestCase):
testing.tearDown()
def test_my_view(self):
- from .views import my_view
+ from .views.default import my_view
request = testing.DummyRequest()
info = my_view(request)
self.assertEqual(info['project'], 'hello_world')
diff --git a/docs/quick_tour/sessions/hello_world/views/__init__.py b/docs/quick_tour/sessions/hello_world/views/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/docs/quick_tour/sessions/hello_world/views/__init__.py
diff --git a/docs/quick_tour/sessions/hello_world/views.py b/docs/quick_tour/sessions/hello_world/views/default.py
index 9716f854e..33b8d8ded 100644
--- a/docs/quick_tour/sessions/hello_world/views.py
+++ b/docs/quick_tour/sessions/hello_world/views/default.py
@@ -3,7 +3,7 @@ from pyramid.view import view_config
import logging
log = logging.getLogger(__name__)
-@view_config(route_name='home', renderer='templates/mytemplate.jinja2')
+@view_config(route_name='home', renderer='../templates/mytemplate.jinja2')
def my_view(request):
log.debug('Some Message')
session = request.session
diff --git a/docs/quick_tour/sessions/hello_world/views/notfound.py b/docs/quick_tour/sessions/hello_world/views/notfound.py
new file mode 100644
index 000000000..69d6e2804
--- /dev/null
+++ b/docs/quick_tour/sessions/hello_world/views/notfound.py
@@ -0,0 +1,7 @@
+from pyramid.view import notfound_view_config
+
+
+@notfound_view_config(renderer='../templates/404.jinja2')
+def notfound_view(request):
+ request.response.status = 404
+ return {}
diff --git a/docs/quick_tour/sessions/setup.py b/docs/quick_tour/sessions/setup.py
index 44d90b990..27b025384 100644
--- a/docs/quick_tour/sessions/setup.py
+++ b/docs/quick_tour/sessions/setup.py
@@ -18,7 +18,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/quick_tour/sqla_demo/.gitignore b/docs/quick_tour/sqla_demo/.gitignore
new file mode 100644
index 000000000..1853d983c
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/.gitignore
@@ -0,0 +1,21 @@
+*.egg
+*.egg-info
+*.pyc
+*$py.class
+*~
+.coverage
+coverage.xml
+build/
+dist/
+.tox/
+nosetests.xml
+env*/
+tmp/
+Data.fs*
+*.sublime-project
+*.sublime-workspace
+.*.sw?
+.sw?
+.DS_Store
+coverage
+test
diff --git a/docs/quick_tour/sqla_demo/README.txt b/docs/quick_tour/sqla_demo/README.txt
index 27bbff5a7..d00790492 100644
--- a/docs/quick_tour/sqla_demo/README.txt
+++ b/docs/quick_tour/sqla_demo/README.txt
@@ -20,7 +20,17 @@ Getting Started
env/bin/pip install -e ".[testing]"
-- Configure the database.
+- Initialize and upgrade the database using Alembic.
+
+ - Generate your first revision.
+
+ env/bin/alembic -c development.ini revision --autogenerate -m "init"
+
+ - Upgrade to that revision.
+
+ env/bin/alembic -c development.ini upgrade head
+
+- Load default data into the database using a script.
env/bin/initialize_sqla_demo_db development.ini
diff --git a/docs/quick_tour/sqla_demo/development.ini b/docs/quick_tour/sqla_demo/development.ini
index 8836a846e..056a672e4 100644
--- a/docs/quick_tour/sqla_demo/development.ini
+++ b/docs/quick_tour/sqla_demo/development.ini
@@ -22,10 +22,19 @@ retry.attempts = 3
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
+[pshell]
+setup = sqla_demo.pshell.setup
+
###
# wsgi server configuration
###
+[alembic]
+# path to migration scripts
+script_location = sqla_demo/alembic
+file_template = %%(year)d%%(month).2d%%(day).2d_%%(rev)s
+# file_template = %%(rev)s_%%(slug)s
+
[server:main]
use = egg:waitress#main
listen = localhost:6543
@@ -54,7 +63,7 @@ handlers =
qualname = sqla_demo
[logger_sqlalchemy]
-level = INFO
+level = WARN
handlers =
qualname = sqlalchemy.engine
# "level = INFO" logs SQL queries.
diff --git a/docs/quick_tour/sqla_demo/production.ini b/docs/quick_tour/sqla_demo/production.ini
index 4566e02a0..fe7f946bd 100644
--- a/docs/quick_tour/sqla_demo/production.ini
+++ b/docs/quick_tour/sqla_demo/production.ini
@@ -16,10 +16,19 @@ sqlalchemy.url = sqlite:///%(here)s/sqla_demo.sqlite
retry.attempts = 3
+[pshell]
+setup = sqla_demo.pshell.setup
+
###
# wsgi server configuration
###
+[alembic]
+# path to migration scripts
+script_location = sqla_demo/alembic
+file_template = %%(year)d%%(month).2d%%(day).2d_%%(rev)s
+# file_template = %%(rev)s_%%(slug)s
+
[server:main]
use = egg:waitress#main
listen = *:6543
diff --git a/docs/quick_tour/sqla_demo/pytest.ini b/docs/quick_tour/sqla_demo/pytest.ini
index 2d7535841..b4b690a0f 100644
--- a/docs/quick_tour/sqla_demo/pytest.ini
+++ b/docs/quick_tour/sqla_demo/pytest.ini
@@ -1,3 +1,3 @@
[pytest]
testpaths = sqla_demo
-python_files = *.py
+python_files = test*.py
diff --git a/docs/quick_tour/sqla_demo/setup.py b/docs/quick_tour/sqla_demo/setup.py
index 855a15d58..76cd518ca 100644
--- a/docs/quick_tour/sqla_demo/setup.py
+++ b/docs/quick_tour/sqla_demo/setup.py
@@ -9,8 +9,9 @@ with open(os.path.join(here, 'CHANGES.txt')) as f:
CHANGES = f.read()
requires = [
+ 'alembic',
'plaster_pastedeploy',
- 'pyramid >= 1.9a',
+ 'pyramid >= 1.9',
'pyramid_debugtoolbar',
'pyramid_jinja2',
'pyramid_retry',
@@ -23,7 +24,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
@@ -54,7 +55,7 @@ setup(
'main = sqla_demo:main',
],
'console_scripts': [
- 'initialize_sqla_demo_db = sqla_demo.scripts.initializedb:main',
+ 'initialize_sqla_demo_db = sqla_demo.scripts.initialize_db:main',
],
},
)
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/__init__.py b/docs/quick_tour/sqla_demo/sqla_demo/__init__.py
index 4dab44823..28bd1f80d 100644
--- a/docs/quick_tour/sqla_demo/sqla_demo/__init__.py
+++ b/docs/quick_tour/sqla_demo/sqla_demo/__init__.py
@@ -4,9 +4,9 @@ from pyramid.config import Configurator
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- config = Configurator(settings=settings)
- config.include('pyramid_jinja2')
- config.include('.models')
- config.include('.routes')
- config.scan()
+ with Configurator(settings=settings) as config:
+ config.include('pyramid_jinja2')
+ config.include('.models')
+ config.include('.routes')
+ config.scan()
return config.make_wsgi_app()
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/alembic/env.py b/docs/quick_tour/sqla_demo/sqla_demo/alembic/env.py
new file mode 100644
index 000000000..46ce86a4e
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/alembic/env.py
@@ -0,0 +1,58 @@
+"""Pyramid bootstrap environment. """
+from alembic import context
+from pyramid.paster import get_appsettings, setup_logging
+from sqlalchemy import engine_from_config
+
+from sqla_demo.models.meta import Base
+
+config = context.config
+
+setup_logging(config.config_file_name)
+
+settings = get_appsettings(config.config_file_name)
+target_metadata = Base.metadata
+
+
+def run_migrations_offline():
+ """Run migrations in 'offline' mode.
+
+ This configures the context with just a URL
+ and not an Engine, though an Engine is acceptable
+ here as well. By skipping the Engine creation
+ we don't even need a DBAPI to be available.
+
+ Calls to context.execute() here emit the given string to the
+ script output.
+
+ """
+ context.configure(url=settings['sqlalchemy.url'])
+ with context.begin_transaction():
+ context.run_migrations()
+
+
+def run_migrations_online():
+ """Run migrations in 'online' mode.
+
+ In this scenario we need to create an Engine
+ and associate a connection with the context.
+
+ """
+ engine = engine_from_config(settings, prefix='sqlalchemy.')
+
+ connection = engine.connect()
+ context.configure(
+ connection=connection,
+ target_metadata=target_metadata
+ )
+
+ try:
+ with context.begin_transaction():
+ context.run_migrations()
+ finally:
+ connection.close()
+
+
+if context.is_offline_mode():
+ run_migrations_offline()
+else:
+ run_migrations_online()
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/alembic/script.py.mako b/docs/quick_tour/sqla_demo/sqla_demo/alembic/script.py.mako
new file mode 100644
index 000000000..2c0156303
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/alembic/script.py.mako
@@ -0,0 +1,24 @@
+"""${message}
+
+Revision ID: ${up_revision}
+Revises: ${down_revision | comma,n}
+Create Date: ${create_date}
+
+"""
+from alembic import op
+import sqlalchemy as sa
+${imports if imports else ""}
+
+# revision identifiers, used by Alembic.
+revision = ${repr(up_revision)}
+down_revision = ${repr(down_revision)}
+branch_labels = ${repr(branch_labels)}
+depends_on = ${repr(depends_on)}
+
+
+def upgrade():
+ ${upgrades if upgrades else "pass"}
+
+
+def downgrade():
+ ${downgrades if downgrades else "pass"}
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/alembic/versions/README.txt b/docs/quick_tour/sqla_demo/sqla_demo/alembic/versions/README.txt
new file mode 100644
index 000000000..09ed32c8d
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/alembic/versions/README.txt
@@ -0,0 +1 @@
+Placeholder for alembic versions \ No newline at end of file
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/pshell.py b/docs/quick_tour/sqla_demo/sqla_demo/pshell.py
new file mode 100644
index 000000000..108c04d5e
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/pshell.py
@@ -0,0 +1,12 @@
+from . import models
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['dbsession'] = request.dbsession
+ env['models'] = models
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/scripts/initialize_db.py b/docs/quick_tour/sqla_demo/sqla_demo/scripts/initialize_db.py
new file mode 100644
index 000000000..c629d1780
--- /dev/null
+++ b/docs/quick_tour/sqla_demo/sqla_demo/scripts/initialize_db.py
@@ -0,0 +1,48 @@
+import argparse
+import sys
+
+from pyramid.paster import bootstrap, setup_logging
+from sqlalchemy.exc import OperationalError
+
+from .. import models
+
+
+def setup_models(dbsession):
+ """
+ Add or update models / fixtures in the database.
+
+ """
+ model = models.mymodel.MyModel(name='one', value=1)
+ dbsession.add(model)
+
+
+def parse_args(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ 'config_uri',
+ help='Configuration file, e.g., development.ini',
+ )
+ return parser.parse_args(argv[1:])
+
+
+def main(argv=sys.argv):
+ args = parse_args(argv)
+ setup_logging(args.config_uri)
+ env = bootstrap(args.config_uri)
+
+ try:
+ with env['request'].tm:
+ dbsession = env['request'].dbsession
+ setup_models(dbsession)
+ except OperationalError:
+ print('''
+Pyramid is having a problem using your SQL database. The problem
+might be caused by one of the following things:
+
+1. You may need to initialize your database tables with `alembic`.
+ Check your README.txt for description and try to run it.
+
+2. Your database server may not be running. Check that the
+ database server referred to by the "sqlalchemy.url" setting in
+ your "development.ini" file is running.
+ ''')
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/scripts/initializedb.py b/docs/quick_tour/sqla_demo/sqla_demo/scripts/initializedb.py
deleted file mode 100644
index 7307ecc5c..000000000
--- a/docs/quick_tour/sqla_demo/sqla_demo/scripts/initializedb.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import os
-import sys
-import transaction
-
-from pyramid.paster import (
- get_appsettings,
- setup_logging,
- )
-
-from pyramid.scripts.common import parse_vars
-
-from ..models.meta import Base
-from ..models import (
- get_engine,
- get_session_factory,
- get_tm_session,
- )
-from ..models import MyModel
-
-
-def usage(argv):
- cmd = os.path.basename(argv[0])
- print('usage: %s <config_uri> [var=value]\n'
- '(example: "%s development.ini")' % (cmd, cmd))
- sys.exit(1)
-
-
-def main(argv=sys.argv):
- if len(argv) < 2:
- usage(argv)
- config_uri = argv[1]
- options = parse_vars(argv[2:])
- setup_logging(config_uri)
- settings = get_appsettings(config_uri, options=options)
-
- engine = get_engine(settings)
- Base.metadata.create_all(engine)
-
- session_factory = get_session_factory(engine)
-
- with transaction.manager:
- dbsession = get_tm_session(session_factory, transaction.manager)
-
- model = MyModel(name='one', value=1)
- dbsession.add(model)
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.jinja2 b/docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.jinja2
index 26d72c0a6..d8b0a4232 100644
--- a/docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.jinja2
+++ b/docs/quick_tour/sqla_demo/sqla_demo/templates/mytemplate.jinja2
@@ -5,4 +5,4 @@
<h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Alchemy project</span></h1>
<p class="lead">Welcome to <span class="font-normal">{{project}}</span>, a&nbsp;Pyramid application generated&nbsp;by<br><span class="font-normal">Cookiecutter</span>.</p>
</div>
-{% endblock content %}
+{% endblock content %} \ No newline at end of file
diff --git a/docs/quick_tour/sqla_demo/sqla_demo/views/default.py b/docs/quick_tour/sqla_demo/sqla_demo/views/default.py
index d4afb1b0b..f7ad4c8f2 100644
--- a/docs/quick_tour/sqla_demo/sqla_demo/views/default.py
+++ b/docs/quick_tour/sqla_demo/sqla_demo/views/default.py
@@ -3,14 +3,14 @@ from pyramid.view import view_config
from sqlalchemy.exc import DBAPIError
-from ..models import MyModel
+from .. import models
@view_config(route_name='home', renderer='../templates/mytemplate.jinja2')
def my_view(request):
try:
- query = request.dbsession.query(MyModel)
- one = query.filter(MyModel.name == 'one').first()
+ query = request.dbsession.query(models.MyModel)
+ one = query.filter(models.MyModel.name == 'one').first()
except DBAPIError:
return Response(db_err_msg, content_type='text/plain', status=500)
return {'one': one, 'project': 'sqla_demo'}
@@ -20,9 +20,8 @@ db_err_msg = """\
Pyramid is having a problem using your SQL database. The problem
might be caused by one of the following things:
-1. You may need to run the "initialize_sqla_demo_db" script
- to initialize your database tables. Check your virtual
- environment's "bin" directory for this script and try to run it.
+1. You may need to initialize your database tables with `alembic`.
+ Check your README.txt for description and try to run it.
2. Your database server may not be running. Check that the
database server referred to by the "sqlalchemy.url" setting in
diff --git a/docs/quick_tutorial/cookiecutters/.gitignore b/docs/quick_tutorial/cookiecutters/.gitignore
new file mode 100644
index 000000000..1853d983c
--- /dev/null
+++ b/docs/quick_tutorial/cookiecutters/.gitignore
@@ -0,0 +1,21 @@
+*.egg
+*.egg-info
+*.pyc
+*$py.class
+*~
+.coverage
+coverage.xml
+build/
+dist/
+.tox/
+nosetests.xml
+env*/
+tmp/
+Data.fs*
+*.sublime-project
+*.sublime-workspace
+.*.sw?
+.sw?
+.DS_Store
+coverage
+test
diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/__init__.py b/docs/quick_tutorial/cookiecutters/cc_starter/__init__.py
index 49dde36d4..a3d5a6469 100644
--- a/docs/quick_tutorial/cookiecutters/cc_starter/__init__.py
+++ b/docs/quick_tutorial/cookiecutters/cc_starter/__init__.py
@@ -4,9 +4,8 @@ from pyramid.config import Configurator
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- config = Configurator(settings=settings)
- config.include('pyramid_jinja2')
- config.add_static_view('static', 'static', cache_max_age=3600)
- config.add_route('home', '/')
- config.scan()
+ with Configurator(settings=settings) as config:
+ config.include('pyramid_jinja2')
+ config.include('.routes')
+ config.scan()
return config.make_wsgi_app()
diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/routes.py b/docs/quick_tutorial/cookiecutters/cc_starter/routes.py
new file mode 100644
index 000000000..25504ad4d
--- /dev/null
+++ b/docs/quick_tutorial/cookiecutters/cc_starter/routes.py
@@ -0,0 +1,3 @@
+def includeme(config):
+ config.add_static_view('static', 'static', cache_max_age=3600)
+ config.add_route('home', '/')
diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/templates/404.jinja2 b/docs/quick_tutorial/cookiecutters/cc_starter/templates/404.jinja2
new file mode 100644
index 000000000..aaf12413f
--- /dev/null
+++ b/docs/quick_tutorial/cookiecutters/cc_starter/templates/404.jinja2
@@ -0,0 +1,8 @@
+{% extends "layout.jinja2" %}
+
+{% block content %}
+<div class="content">
+ <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">Starter project</span></h1>
+ <p class="lead"><span class="font-semi-bold">404</span> Page Not Found</p>
+</div>
+{% endblock content %}
diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/tests.py b/docs/quick_tutorial/cookiecutters/cc_starter/tests.py
index 2f553bbb4..f3886be84 100644
--- a/docs/quick_tutorial/cookiecutters/cc_starter/tests.py
+++ b/docs/quick_tutorial/cookiecutters/cc_starter/tests.py
@@ -11,7 +11,7 @@ class ViewTests(unittest.TestCase):
testing.tearDown()
def test_my_view(self):
- from .views import my_view
+ from .views.default import my_view
request = testing.DummyRequest()
info = my_view(request)
self.assertEqual(info['project'], 'cc_starter')
diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/views/__init__.py b/docs/quick_tutorial/cookiecutters/cc_starter/views/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/docs/quick_tutorial/cookiecutters/cc_starter/views/__init__.py
diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/views.py b/docs/quick_tutorial/cookiecutters/cc_starter/views/default.py
index deedd53b8..47af359b5 100644
--- a/docs/quick_tutorial/cookiecutters/cc_starter/views.py
+++ b/docs/quick_tutorial/cookiecutters/cc_starter/views/default.py
@@ -1,6 +1,6 @@
from pyramid.view import view_config
-@view_config(route_name='home', renderer='templates/mytemplate.jinja2')
+@view_config(route_name='home', renderer='../templates/mytemplate.jinja2')
def my_view(request):
return {'project': 'cc_starter'}
diff --git a/docs/quick_tutorial/cookiecutters/cc_starter/views/notfound.py b/docs/quick_tutorial/cookiecutters/cc_starter/views/notfound.py
new file mode 100644
index 000000000..69d6e2804
--- /dev/null
+++ b/docs/quick_tutorial/cookiecutters/cc_starter/views/notfound.py
@@ -0,0 +1,7 @@
+from pyramid.view import notfound_view_config
+
+
+@notfound_view_config(renderer='../templates/404.jinja2')
+def notfound_view(request):
+ request.response.status = 404
+ return {}
diff --git a/docs/quick_tutorial/cookiecutters/setup.py b/docs/quick_tutorial/cookiecutters/setup.py
index 0d1b3f70e..9482e7c32 100644
--- a/docs/quick_tutorial/cookiecutters/setup.py
+++ b/docs/quick_tutorial/cookiecutters/setup.py
@@ -9,15 +9,16 @@ with open(os.path.join(here, 'CHANGES.txt')) as f:
CHANGES = f.read()
requires = [
+ 'plaster_pastedeploy',
'pyramid',
- 'pyramid_debugtoolbar',
'pyramid_jinja2',
+ 'pyramid_debugtoolbar',
'waitress',
]
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/quick_tutorial/package/setup.py b/docs/quick_tutorial/package/setup.py
index bcfcfa684..77fedee2d 100644
--- a/docs/quick_tutorial/package/setup.py
+++ b/docs/quick_tutorial/package/setup.py
@@ -2,8 +2,9 @@ from setuptools import setup
requires = [
'pyramid',
+ 'waitress',
]
setup(name='tutorial',
install_requires=requires,
-) \ No newline at end of file
+)
diff --git a/docs/tutorials/wiki/authorization.rst b/docs/tutorials/wiki/authorization.rst
index a2e61e632..b7eeb19ae 100644
--- a/docs/tutorials/wiki/authorization.rst
+++ b/docs/tutorials/wiki/authorization.rst
@@ -312,7 +312,7 @@ indicated by the highlighted lines.
.. literalinclude:: src/authorization/tutorial/templates/edit.pt
:lines: 35-39
- :emphasize-lines: 3-5
+ :emphasize-lines: 2-4
:language: html
The attribute ``tal:condition="logged_in"`` will make the element be included
@@ -355,7 +355,7 @@ we're done:
.. literalinclude:: src/authorization/tutorial/templates/edit.pt
:linenos:
- :emphasize-lines: 37-39
+ :emphasize-lines: 36-38
:language: html
Only the highlighted lines need to be added or edited.
@@ -365,7 +365,7 @@ we're done:
.. literalinclude:: src/authorization/tutorial/templates/view.pt
:linenos:
- :emphasize-lines: 37-39
+ :emphasize-lines: 36-38
:language: html
Only the highlighted lines need to be added or edited.
diff --git a/docs/tutorials/wiki/src/authorization/.gitignore b/docs/tutorials/wiki/src/authorization/.gitignore
new file mode 100644
index 000000000..1853d983c
--- /dev/null
+++ b/docs/tutorials/wiki/src/authorization/.gitignore
@@ -0,0 +1,21 @@
+*.egg
+*.egg-info
+*.pyc
+*$py.class
+*~
+.coverage
+coverage.xml
+build/
+dist/
+.tox/
+nosetests.xml
+env*/
+tmp/
+Data.fs*
+*.sublime-project
+*.sublime-workspace
+.*.sw?
+.sw?
+.DS_Store
+coverage
+test
diff --git a/docs/tutorials/wiki/src/authorization/README.txt b/docs/tutorials/wiki/src/authorization/README.txt
index 5ec53bf9d..8a56d14af 100644
--- a/docs/tutorials/wiki/src/authorization/README.txt
+++ b/docs/tutorials/wiki/src/authorization/README.txt
@@ -14,7 +14,7 @@ Getting Started
- Upgrade packaging tools.
- env/bin/pip install --upgrade pip setuptools wheel
+ env/bin/pip install --upgrade pip setuptools
- Install the project in editable mode with its testing requirements.
diff --git a/docs/tutorials/wiki/src/authorization/development.ini b/docs/tutorials/wiki/src/authorization/development.ini
index fec08941d..228f18f36 100644
--- a/docs/tutorials/wiki/src/authorization/development.ini
+++ b/docs/tutorials/wiki/src/authorization/development.ini
@@ -22,6 +22,9 @@ retry.attempts = 3
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki/src/authorization/production.ini b/docs/tutorials/wiki/src/authorization/production.ini
index f2fa8d6d5..46b1e331b 100644
--- a/docs/tutorials/wiki/src/authorization/production.ini
+++ b/docs/tutorials/wiki/src/authorization/production.ini
@@ -16,6 +16,9 @@ zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000
retry.attempts = 3
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki/src/authorization/setup.py b/docs/tutorials/wiki/src/authorization/setup.py
index 3f0b1317c..7011387f6 100644
--- a/docs/tutorials/wiki/src/authorization/setup.py
+++ b/docs/tutorials/wiki/src/authorization/setup.py
@@ -25,7 +25,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/pshell.py b/docs/tutorials/wiki/src/authorization/tutorial/pshell.py
new file mode 100644
index 000000000..3d026291b
--- /dev/null
+++ b/docs/tutorials/wiki/src/authorization/tutorial/pshell.py
@@ -0,0 +1,11 @@
+from . import models
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['models'] = models
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt
index 3ef0c7e0e..eedb83da4 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt
+++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/edit.pt
@@ -23,7 +23,6 @@
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
<![endif]-->
</head>
-
<body>
<div class="starter-template">
diff --git a/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt b/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt
index 5d9478fb9..f2a9249ef 100644
--- a/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt
+++ b/docs/tutorials/wiki/src/authorization/tutorial/templates/view.pt
@@ -23,7 +23,6 @@
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
<![endif]-->
</head>
-
<body>
<div class="starter-template">
diff --git a/docs/tutorials/wiki/src/basiclayout/.gitignore b/docs/tutorials/wiki/src/basiclayout/.gitignore
new file mode 100644
index 000000000..1853d983c
--- /dev/null
+++ b/docs/tutorials/wiki/src/basiclayout/.gitignore
@@ -0,0 +1,21 @@
+*.egg
+*.egg-info
+*.pyc
+*$py.class
+*~
+.coverage
+coverage.xml
+build/
+dist/
+.tox/
+nosetests.xml
+env*/
+tmp/
+Data.fs*
+*.sublime-project
+*.sublime-workspace
+.*.sw?
+.sw?
+.DS_Store
+coverage
+test
diff --git a/docs/tutorials/wiki/src/basiclayout/development.ini b/docs/tutorials/wiki/src/basiclayout/development.ini
index fec08941d..228f18f36 100644
--- a/docs/tutorials/wiki/src/basiclayout/development.ini
+++ b/docs/tutorials/wiki/src/basiclayout/development.ini
@@ -22,6 +22,9 @@ retry.attempts = 3
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki/src/basiclayout/production.ini b/docs/tutorials/wiki/src/basiclayout/production.ini
index f2fa8d6d5..46b1e331b 100644
--- a/docs/tutorials/wiki/src/basiclayout/production.ini
+++ b/docs/tutorials/wiki/src/basiclayout/production.ini
@@ -16,6 +16,9 @@ zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000
retry.attempts = 3
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki/src/basiclayout/setup.py b/docs/tutorials/wiki/src/basiclayout/setup.py
index d743c984f..e05e279e2 100644
--- a/docs/tutorials/wiki/src/basiclayout/setup.py
+++ b/docs/tutorials/wiki/src/basiclayout/setup.py
@@ -23,7 +23,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/tutorials/wiki/src/basiclayout/tutorial/pshell.py b/docs/tutorials/wiki/src/basiclayout/tutorial/pshell.py
new file mode 100644
index 000000000..3d026291b
--- /dev/null
+++ b/docs/tutorials/wiki/src/basiclayout/tutorial/pshell.py
@@ -0,0 +1,11 @@
+from . import models
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['models'] = models
diff --git a/docs/tutorials/wiki/src/installation/.gitignore b/docs/tutorials/wiki/src/installation/.gitignore
new file mode 100644
index 000000000..1853d983c
--- /dev/null
+++ b/docs/tutorials/wiki/src/installation/.gitignore
@@ -0,0 +1,21 @@
+*.egg
+*.egg-info
+*.pyc
+*$py.class
+*~
+.coverage
+coverage.xml
+build/
+dist/
+.tox/
+nosetests.xml
+env*/
+tmp/
+Data.fs*
+*.sublime-project
+*.sublime-workspace
+.*.sw?
+.sw?
+.DS_Store
+coverage
+test
diff --git a/docs/tutorials/wiki/src/installation/development.ini b/docs/tutorials/wiki/src/installation/development.ini
index fec08941d..228f18f36 100644
--- a/docs/tutorials/wiki/src/installation/development.ini
+++ b/docs/tutorials/wiki/src/installation/development.ini
@@ -22,6 +22,9 @@ retry.attempts = 3
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki/src/installation/production.ini b/docs/tutorials/wiki/src/installation/production.ini
index f2fa8d6d5..46b1e331b 100644
--- a/docs/tutorials/wiki/src/installation/production.ini
+++ b/docs/tutorials/wiki/src/installation/production.ini
@@ -16,6 +16,9 @@ zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000
retry.attempts = 3
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki/src/installation/setup.py b/docs/tutorials/wiki/src/installation/setup.py
index d743c984f..e05e279e2 100644
--- a/docs/tutorials/wiki/src/installation/setup.py
+++ b/docs/tutorials/wiki/src/installation/setup.py
@@ -23,7 +23,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/tutorials/wiki/src/installation/tutorial/pshell.py b/docs/tutorials/wiki/src/installation/tutorial/pshell.py
new file mode 100644
index 000000000..3d026291b
--- /dev/null
+++ b/docs/tutorials/wiki/src/installation/tutorial/pshell.py
@@ -0,0 +1,11 @@
+from . import models
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['models'] = models
diff --git a/docs/tutorials/wiki/src/models/.gitignore b/docs/tutorials/wiki/src/models/.gitignore
new file mode 100644
index 000000000..1853d983c
--- /dev/null
+++ b/docs/tutorials/wiki/src/models/.gitignore
@@ -0,0 +1,21 @@
+*.egg
+*.egg-info
+*.pyc
+*$py.class
+*~
+.coverage
+coverage.xml
+build/
+dist/
+.tox/
+nosetests.xml
+env*/
+tmp/
+Data.fs*
+*.sublime-project
+*.sublime-workspace
+.*.sw?
+.sw?
+.DS_Store
+coverage
+test
diff --git a/docs/tutorials/wiki/src/models/development.ini b/docs/tutorials/wiki/src/models/development.ini
index fec08941d..228f18f36 100644
--- a/docs/tutorials/wiki/src/models/development.ini
+++ b/docs/tutorials/wiki/src/models/development.ini
@@ -22,6 +22,9 @@ retry.attempts = 3
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki/src/models/production.ini b/docs/tutorials/wiki/src/models/production.ini
index f2fa8d6d5..46b1e331b 100644
--- a/docs/tutorials/wiki/src/models/production.ini
+++ b/docs/tutorials/wiki/src/models/production.ini
@@ -16,6 +16,9 @@ zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000
retry.attempts = 3
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki/src/models/setup.py b/docs/tutorials/wiki/src/models/setup.py
index d743c984f..e05e279e2 100644
--- a/docs/tutorials/wiki/src/models/setup.py
+++ b/docs/tutorials/wiki/src/models/setup.py
@@ -23,7 +23,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/tutorials/wiki/src/models/tutorial/pshell.py b/docs/tutorials/wiki/src/models/tutorial/pshell.py
new file mode 100644
index 000000000..3d026291b
--- /dev/null
+++ b/docs/tutorials/wiki/src/models/tutorial/pshell.py
@@ -0,0 +1,11 @@
+from . import models
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['models'] = models
diff --git a/docs/tutorials/wiki/src/tests/.gitignore b/docs/tutorials/wiki/src/tests/.gitignore
new file mode 100644
index 000000000..1853d983c
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/.gitignore
@@ -0,0 +1,21 @@
+*.egg
+*.egg-info
+*.pyc
+*$py.class
+*~
+.coverage
+coverage.xml
+build/
+dist/
+.tox/
+nosetests.xml
+env*/
+tmp/
+Data.fs*
+*.sublime-project
+*.sublime-workspace
+.*.sw?
+.sw?
+.DS_Store
+coverage
+test
diff --git a/docs/tutorials/wiki/src/tests/README.txt b/docs/tutorials/wiki/src/tests/README.txt
index 5ec53bf9d..8a56d14af 100644
--- a/docs/tutorials/wiki/src/tests/README.txt
+++ b/docs/tutorials/wiki/src/tests/README.txt
@@ -14,7 +14,7 @@ Getting Started
- Upgrade packaging tools.
- env/bin/pip install --upgrade pip setuptools wheel
+ env/bin/pip install --upgrade pip setuptools
- Install the project in editable mode with its testing requirements.
diff --git a/docs/tutorials/wiki/src/tests/development.ini b/docs/tutorials/wiki/src/tests/development.ini
index fec08941d..228f18f36 100644
--- a/docs/tutorials/wiki/src/tests/development.ini
+++ b/docs/tutorials/wiki/src/tests/development.ini
@@ -22,6 +22,9 @@ retry.attempts = 3
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki/src/tests/production.ini b/docs/tutorials/wiki/src/tests/production.ini
index f2fa8d6d5..46b1e331b 100644
--- a/docs/tutorials/wiki/src/tests/production.ini
+++ b/docs/tutorials/wiki/src/tests/production.ini
@@ -16,6 +16,9 @@ zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000
retry.attempts = 3
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki/src/tests/setup.py b/docs/tutorials/wiki/src/tests/setup.py
index 3f0b1317c..7011387f6 100644
--- a/docs/tutorials/wiki/src/tests/setup.py
+++ b/docs/tutorials/wiki/src/tests/setup.py
@@ -25,7 +25,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/tutorials/wiki/src/tests/tutorial/pshell.py b/docs/tutorials/wiki/src/tests/tutorial/pshell.py
new file mode 100644
index 000000000..3d026291b
--- /dev/null
+++ b/docs/tutorials/wiki/src/tests/tutorial/pshell.py
@@ -0,0 +1,11 @@
+from . import models
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['models'] = models
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt
index 3ef0c7e0e..eedb83da4 100644
--- a/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/edit.pt
@@ -23,7 +23,6 @@
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
<![endif]-->
</head>
-
<body>
<div class="starter-template">
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt
deleted file mode 100644
index 1d33787d9..000000000
--- a/docs/tutorials/wiki/src/tests/tutorial/templates/mytemplate.pt
+++ /dev/null
@@ -1,67 +0,0 @@
-<!DOCTYPE html>
-<html lang="${request.locale_name}">
- <head>
- <meta charset="utf-8">
- <meta http-equiv="X-UA-Compatible" content="IE=edge">
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
- <meta name="description" content="pyramid web application">
- <meta name="author" content="Pylons Project">
- <link rel="shortcut icon" href="${request.static_url('tutorial:static/pyramid-16x16.png')}">
-
- <title>ZODB Scaffold for The Pyramid Web Framework</title>
-
- <!-- Bootstrap core CSS -->
- <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
-
- <!-- Custom styles for this scaffold -->
- <link href="${request.static_url('tutorial:static/theme.css')}" rel="stylesheet">
-
- <!-- HTML5 shiv and Respond.js IE8 support of HTML5 elements and media queries -->
- <!--[if lt IE 9]>
- <script src="//oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js" integrity="sha384-0s5Pv64cNZJieYFkXYOTId2HMA2Lfb6q2nAcx2n0RTLUnCAoTTsS0nKEO27XyKcY" crossorigin="anonymous"></script>
- <script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
- <![endif]-->
- </head>
-
- <body>
-
- <div class="starter-template">
- <div class="container">
- <div class="row">
- <div class="col-md-2">
- <img class="logo img-responsive" src="${request.static_url('tutorial:static/pyramid.png')}" alt="pyramid web framework">
- </div>
- <div class="col-md-10">
- <div class="content">
- <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">ZODB scaffold</span></h1>
- <p class="lead">Welcome to <span class="font-normal">${project}</span>, an&nbsp;application generated&nbsp;by<br>the <span class="font-normal">Pyramid Web Framework 1.7</span>.</p>
- </div>
- </div>
- </div>
- <div class="row">
- <div class="links">
- <ul>
- <li class="current-version">Generated by v1.9</li>
- <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="https://docs.pylonsproject.org/projects/pyramid/en/1.9-branch/">Docs</a></li>
- <li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
- <li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="irc://irc.freenode.net#pyramid">IRC Channel</a></li>
- <li><i class="glyphicon glyphicon-home icon-muted"></i><a href="https://pylonsproject.org">Pylons Project</a></li>
- </ul>
- </div>
- </div>
- <div class="row">
- <div class="copyright">
- Copyright &copy; Pylons Project
- </div>
- </div>
- </div>
- </div>
-
-
- <!-- Bootstrap core JavaScript
- ================================================== -->
- <!-- Placed at the end of the document so the pages load faster -->
- <script src="//code.jquery.com/jquery-1.12.4.min.js" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
- <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
- </body>
-</html>
diff --git a/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt b/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt
index 5d9478fb9..f2a9249ef 100644
--- a/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt
+++ b/docs/tutorials/wiki/src/tests/tutorial/templates/view.pt
@@ -23,7 +23,6 @@
<script src="//oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js" integrity="sha384-ZoaMbDF+4LeFxg6WdScQ9nnR1QC2MIRxA1O9KWEXQwns1G8UNyIEZIQidzb0T1fo" crossorigin="anonymous"></script>
<![endif]-->
</head>
-
<body>
<div class="starter-template">
diff --git a/docs/tutorials/wiki/src/views/.gitignore b/docs/tutorials/wiki/src/views/.gitignore
new file mode 100644
index 000000000..1853d983c
--- /dev/null
+++ b/docs/tutorials/wiki/src/views/.gitignore
@@ -0,0 +1,21 @@
+*.egg
+*.egg-info
+*.pyc
+*$py.class
+*~
+.coverage
+coverage.xml
+build/
+dist/
+.tox/
+nosetests.xml
+env*/
+tmp/
+Data.fs*
+*.sublime-project
+*.sublime-workspace
+.*.sw?
+.sw?
+.DS_Store
+coverage
+test
diff --git a/docs/tutorials/wiki/src/views/README.txt b/docs/tutorials/wiki/src/views/README.txt
index 5ec53bf9d..8a56d14af 100644
--- a/docs/tutorials/wiki/src/views/README.txt
+++ b/docs/tutorials/wiki/src/views/README.txt
@@ -14,7 +14,7 @@ Getting Started
- Upgrade packaging tools.
- env/bin/pip install --upgrade pip setuptools wheel
+ env/bin/pip install --upgrade pip setuptools
- Install the project in editable mode with its testing requirements.
diff --git a/docs/tutorials/wiki/src/views/development.ini b/docs/tutorials/wiki/src/views/development.ini
index fec08941d..228f18f36 100644
--- a/docs/tutorials/wiki/src/views/development.ini
+++ b/docs/tutorials/wiki/src/views/development.ini
@@ -22,6 +22,9 @@ retry.attempts = 3
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki/src/views/production.ini b/docs/tutorials/wiki/src/views/production.ini
index f2fa8d6d5..46b1e331b 100644
--- a/docs/tutorials/wiki/src/views/production.ini
+++ b/docs/tutorials/wiki/src/views/production.ini
@@ -16,6 +16,9 @@ zodbconn.uri = file://%(here)s/Data.fs?connection_cache_size=20000
retry.attempts = 3
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki/src/views/setup.py b/docs/tutorials/wiki/src/views/setup.py
index bd3d15af1..a11ae6c8f 100644
--- a/docs/tutorials/wiki/src/views/setup.py
+++ b/docs/tutorials/wiki/src/views/setup.py
@@ -24,7 +24,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/tutorials/wiki/src/views/tutorial/pshell.py b/docs/tutorials/wiki/src/views/tutorial/pshell.py
new file mode 100644
index 000000000..3d026291b
--- /dev/null
+++ b/docs/tutorials/wiki/src/views/tutorial/pshell.py
@@ -0,0 +1,11 @@
+from . import models
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['models'] = models
diff --git a/docs/tutorials/wiki2/basiclayout.rst b/docs/tutorials/wiki2/basiclayout.rst
index 313b5998e..315aca29e 100644
--- a/docs/tutorials/wiki2/basiclayout.rst
+++ b/docs/tutorials/wiki2/basiclayout.rst
@@ -44,7 +44,7 @@ When you invoke the ``pserve development.ini`` command, the ``main`` function
above is executed. It accepts some settings and returns a :term:`WSGI`
application. (See :ref:`startup_chapter` for more about ``pserve``.)
-Next in ``main``, construct a :term:`Configurator` object:
+Next in ``main``, construct a :term:`Configurator` object using a context manager:
.. literalinclude:: src/basiclayout/tutorial/__init__.py
:lines: 7
@@ -65,7 +65,7 @@ with the ``.jinja2`` extension within our project.
:lineno-match:
:language: py
-Next include the the package ``models`` using a dotted Python path. The exact
+Next include the package ``models`` using a dotted Python path. The exact
setup of the models will be covered later.
.. literalinclude:: src/basiclayout/tutorial/__init__.py
diff --git a/docs/tutorials/wiki2/definingviews.rst b/docs/tutorials/wiki2/definingviews.rst
index 700a105b1..fe539eca6 100644
--- a/docs/tutorials/wiki2/definingviews.rst
+++ b/docs/tutorials/wiki2/definingviews.rst
@@ -149,7 +149,7 @@ We'll describe each one briefly in the following sections.
.. note::
- There is nothing special about the filename ``default.py`` exept that it is a
+ There is nothing special about the filename ``default.py`` except that it is a
Python module. A project may have many view callables throughout its codebase
in arbitrarily named modules. Modules implementing view callables often have
``view`` in their name (or may live in a Python subpackage of your
diff --git a/docs/tutorials/wiki2/src/authentication/development.ini b/docs/tutorials/wiki2/src/authentication/development.ini
index d76a6cd72..8fbb5fd38 100644
--- a/docs/tutorials/wiki2/src/authentication/development.ini
+++ b/docs/tutorials/wiki2/src/authentication/development.ini
@@ -24,6 +24,9 @@ auth.secret = seekrit
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
@@ -62,7 +65,7 @@ handlers =
qualname = tutorial
[logger_sqlalchemy]
-level = INFO
+level = WARN
handlers =
qualname = sqlalchemy.engine
# "level = INFO" logs SQL queries.
diff --git a/docs/tutorials/wiki2/src/authentication/production.ini b/docs/tutorials/wiki2/src/authentication/production.ini
index c46adb7b5..9fef64f83 100644
--- a/docs/tutorials/wiki2/src/authentication/production.ini
+++ b/docs/tutorials/wiki2/src/authentication/production.ini
@@ -18,6 +18,9 @@ retry.attempts = 3
auth.secret = real-seekrit
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki2/src/authentication/setup.py b/docs/tutorials/wiki2/src/authentication/setup.py
index 28b766cbe..e2a30c0e7 100644
--- a/docs/tutorials/wiki2/src/authentication/setup.py
+++ b/docs/tutorials/wiki2/src/authentication/setup.py
@@ -26,7 +26,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/tutorials/wiki2/src/authentication/tutorial/__init__.py b/docs/tutorials/wiki2/src/authentication/tutorial/__init__.py
index f5c033b8b..5d4bae3d7 100644
--- a/docs/tutorials/wiki2/src/authentication/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/authentication/tutorial/__init__.py
@@ -4,10 +4,10 @@ from pyramid.config import Configurator
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- config = Configurator(settings=settings)
- config.include('pyramid_jinja2')
- config.include('.models')
- config.include('.routes')
- config.include('.security')
- config.scan()
+ with Configurator(settings=settings) as config:
+ config.include('pyramid_jinja2')
+ config.include('.models')
+ config.include('.routes')
+ config.include('.security')
+ config.scan()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/src/authentication/tutorial/pshell.py b/docs/tutorials/wiki2/src/authentication/tutorial/pshell.py
new file mode 100644
index 000000000..108c04d5e
--- /dev/null
+++ b/docs/tutorials/wiki2/src/authentication/tutorial/pshell.py
@@ -0,0 +1,12 @@
+from . import models
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['dbsession'] = request.dbsession
+ env['models'] = models
diff --git a/docs/tutorials/wiki2/src/authentication/tutorial/scripts/initialize_db.py b/docs/tutorials/wiki2/src/authentication/tutorial/scripts/initialize_db.py
index 231d5d44b..e6350fb36 100644
--- a/docs/tutorials/wiki2/src/authentication/tutorial/scripts/initialize_db.py
+++ b/docs/tutorials/wiki2/src/authentication/tutorial/scripts/initialize_db.py
@@ -1,4 +1,4 @@
-import os
+import argparse
import sys
from pyramid.paster import bootstrap, setup_logging
@@ -24,19 +24,19 @@ def setup_models(dbsession):
dbsession.add(page)
-def usage(argv):
- cmd = os.path.basename(argv[0])
- print('usage: %s <config_uri>\n'
- '(example: "%s development.ini")' % (cmd, cmd))
- sys.exit(1)
+def parse_args(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ 'config_uri',
+ help='Configuration file, e.g., development.ini',
+ )
+ return parser.parse_args(argv[1:])
def main(argv=sys.argv):
- if len(argv) != 2:
- usage(argv)
- config_uri = argv[1]
- setup_logging(config_uri)
- env = bootstrap(config_uri)
+ args = parse_args(argv)
+ setup_logging(args.config_uri)
+ env = bootstrap(args.config_uri)
try:
with env['request'].tm:
diff --git a/docs/tutorials/wiki2/src/authorization/development.ini b/docs/tutorials/wiki2/src/authorization/development.ini
index d76a6cd72..8fbb5fd38 100644
--- a/docs/tutorials/wiki2/src/authorization/development.ini
+++ b/docs/tutorials/wiki2/src/authorization/development.ini
@@ -24,6 +24,9 @@ auth.secret = seekrit
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
@@ -62,7 +65,7 @@ handlers =
qualname = tutorial
[logger_sqlalchemy]
-level = INFO
+level = WARN
handlers =
qualname = sqlalchemy.engine
# "level = INFO" logs SQL queries.
diff --git a/docs/tutorials/wiki2/src/authorization/production.ini b/docs/tutorials/wiki2/src/authorization/production.ini
index c46adb7b5..9fef64f83 100644
--- a/docs/tutorials/wiki2/src/authorization/production.ini
+++ b/docs/tutorials/wiki2/src/authorization/production.ini
@@ -18,6 +18,9 @@ retry.attempts = 3
auth.secret = real-seekrit
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki2/src/authorization/setup.py b/docs/tutorials/wiki2/src/authorization/setup.py
index 28b766cbe..e2a30c0e7 100644
--- a/docs/tutorials/wiki2/src/authorization/setup.py
+++ b/docs/tutorials/wiki2/src/authorization/setup.py
@@ -26,7 +26,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py b/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py
index f5c033b8b..5d4bae3d7 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/__init__.py
@@ -4,10 +4,10 @@ from pyramid.config import Configurator
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- config = Configurator(settings=settings)
- config.include('pyramid_jinja2')
- config.include('.models')
- config.include('.routes')
- config.include('.security')
- config.scan()
+ with Configurator(settings=settings) as config:
+ config.include('pyramid_jinja2')
+ config.include('.models')
+ config.include('.routes')
+ config.include('.security')
+ config.scan()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/pshell.py b/docs/tutorials/wiki2/src/authorization/tutorial/pshell.py
new file mode 100644
index 000000000..108c04d5e
--- /dev/null
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/pshell.py
@@ -0,0 +1,12 @@
+from . import models
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['dbsession'] = request.dbsession
+ env['models'] = models
diff --git a/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initialize_db.py b/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initialize_db.py
index 231d5d44b..e6350fb36 100644
--- a/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initialize_db.py
+++ b/docs/tutorials/wiki2/src/authorization/tutorial/scripts/initialize_db.py
@@ -1,4 +1,4 @@
-import os
+import argparse
import sys
from pyramid.paster import bootstrap, setup_logging
@@ -24,19 +24,19 @@ def setup_models(dbsession):
dbsession.add(page)
-def usage(argv):
- cmd = os.path.basename(argv[0])
- print('usage: %s <config_uri>\n'
- '(example: "%s development.ini")' % (cmd, cmd))
- sys.exit(1)
+def parse_args(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ 'config_uri',
+ help='Configuration file, e.g., development.ini',
+ )
+ return parser.parse_args(argv[1:])
def main(argv=sys.argv):
- if len(argv) != 2:
- usage(argv)
- config_uri = argv[1]
- setup_logging(config_uri)
- env = bootstrap(config_uri)
+ args = parse_args(argv)
+ setup_logging(args.config_uri)
+ env = bootstrap(args.config_uri)
try:
with env['request'].tm:
diff --git a/docs/tutorials/wiki2/src/basiclayout/development.ini b/docs/tutorials/wiki2/src/basiclayout/development.ini
index ee050c0ea..564aefb56 100644
--- a/docs/tutorials/wiki2/src/basiclayout/development.ini
+++ b/docs/tutorials/wiki2/src/basiclayout/development.ini
@@ -22,6 +22,9 @@ retry.attempts = 3
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
@@ -60,7 +63,7 @@ handlers =
qualname = tutorial
[logger_sqlalchemy]
-level = INFO
+level = WARN
handlers =
qualname = sqlalchemy.engine
# "level = INFO" logs SQL queries.
diff --git a/docs/tutorials/wiki2/src/basiclayout/production.ini b/docs/tutorials/wiki2/src/basiclayout/production.ini
index 91d0f5ddb..29cdda1e1 100644
--- a/docs/tutorials/wiki2/src/basiclayout/production.ini
+++ b/docs/tutorials/wiki2/src/basiclayout/production.ini
@@ -16,6 +16,9 @@ sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
retry.attempts = 3
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki2/src/basiclayout/setup.py b/docs/tutorials/wiki2/src/basiclayout/setup.py
index e0cc964fe..11725dd51 100644
--- a/docs/tutorials/wiki2/src/basiclayout/setup.py
+++ b/docs/tutorials/wiki2/src/basiclayout/setup.py
@@ -24,7 +24,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py
index 4dab44823..28bd1f80d 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/__init__.py
@@ -4,9 +4,9 @@ from pyramid.config import Configurator
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- config = Configurator(settings=settings)
- config.include('pyramid_jinja2')
- config.include('.models')
- config.include('.routes')
- config.scan()
+ with Configurator(settings=settings) as config:
+ config.include('pyramid_jinja2')
+ config.include('.models')
+ config.include('.routes')
+ config.scan()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/pshell.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/pshell.py
new file mode 100644
index 000000000..108c04d5e
--- /dev/null
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/pshell.py
@@ -0,0 +1,12 @@
+from . import models
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['dbsession'] = request.dbsession
+ env['models'] = models
diff --git a/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initialize_db.py b/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initialize_db.py
index b882f9bf7..c629d1780 100644
--- a/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initialize_db.py
+++ b/docs/tutorials/wiki2/src/basiclayout/tutorial/scripts/initialize_db.py
@@ -1,4 +1,4 @@
-import os
+import argparse
import sys
from pyramid.paster import bootstrap, setup_logging
@@ -8,23 +8,27 @@ from .. import models
def setup_models(dbsession):
+ """
+ Add or update models / fixtures in the database.
+
+ """
model = models.mymodel.MyModel(name='one', value=1)
dbsession.add(model)
-def usage(argv):
- cmd = os.path.basename(argv[0])
- print('usage: %s <config_uri>\n'
- '(example: "%s development.ini")' % (cmd, cmd))
- sys.exit(1)
+def parse_args(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ 'config_uri',
+ help='Configuration file, e.g., development.ini',
+ )
+ return parser.parse_args(argv[1:])
def main(argv=sys.argv):
- if len(argv) != 2:
- usage(argv)
- config_uri = argv[1]
- setup_logging(config_uri)
- env = bootstrap(config_uri)
+ args = parse_args(argv)
+ setup_logging(args.config_uri)
+ env = bootstrap(args.config_uri)
try:
with env['request'].tm:
diff --git a/docs/tutorials/wiki2/src/installation/development.ini b/docs/tutorials/wiki2/src/installation/development.ini
index ee050c0ea..564aefb56 100644
--- a/docs/tutorials/wiki2/src/installation/development.ini
+++ b/docs/tutorials/wiki2/src/installation/development.ini
@@ -22,6 +22,9 @@ retry.attempts = 3
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
@@ -60,7 +63,7 @@ handlers =
qualname = tutorial
[logger_sqlalchemy]
-level = INFO
+level = WARN
handlers =
qualname = sqlalchemy.engine
# "level = INFO" logs SQL queries.
diff --git a/docs/tutorials/wiki2/src/installation/production.ini b/docs/tutorials/wiki2/src/installation/production.ini
index 91d0f5ddb..29cdda1e1 100644
--- a/docs/tutorials/wiki2/src/installation/production.ini
+++ b/docs/tutorials/wiki2/src/installation/production.ini
@@ -16,6 +16,9 @@ sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
retry.attempts = 3
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki2/src/installation/setup.py b/docs/tutorials/wiki2/src/installation/setup.py
index e0cc964fe..11725dd51 100644
--- a/docs/tutorials/wiki2/src/installation/setup.py
+++ b/docs/tutorials/wiki2/src/installation/setup.py
@@ -24,7 +24,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/__init__.py b/docs/tutorials/wiki2/src/installation/tutorial/__init__.py
index 4dab44823..28bd1f80d 100644
--- a/docs/tutorials/wiki2/src/installation/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/installation/tutorial/__init__.py
@@ -4,9 +4,9 @@ from pyramid.config import Configurator
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- config = Configurator(settings=settings)
- config.include('pyramid_jinja2')
- config.include('.models')
- config.include('.routes')
- config.scan()
+ with Configurator(settings=settings) as config:
+ config.include('pyramid_jinja2')
+ config.include('.models')
+ config.include('.routes')
+ config.scan()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/pshell.py b/docs/tutorials/wiki2/src/installation/tutorial/pshell.py
new file mode 100644
index 000000000..108c04d5e
--- /dev/null
+++ b/docs/tutorials/wiki2/src/installation/tutorial/pshell.py
@@ -0,0 +1,12 @@
+from . import models
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['dbsession'] = request.dbsession
+ env['models'] = models
diff --git a/docs/tutorials/wiki2/src/installation/tutorial/scripts/initialize_db.py b/docs/tutorials/wiki2/src/installation/tutorial/scripts/initialize_db.py
index b882f9bf7..c629d1780 100644
--- a/docs/tutorials/wiki2/src/installation/tutorial/scripts/initialize_db.py
+++ b/docs/tutorials/wiki2/src/installation/tutorial/scripts/initialize_db.py
@@ -1,4 +1,4 @@
-import os
+import argparse
import sys
from pyramid.paster import bootstrap, setup_logging
@@ -8,23 +8,27 @@ from .. import models
def setup_models(dbsession):
+ """
+ Add or update models / fixtures in the database.
+
+ """
model = models.mymodel.MyModel(name='one', value=1)
dbsession.add(model)
-def usage(argv):
- cmd = os.path.basename(argv[0])
- print('usage: %s <config_uri>\n'
- '(example: "%s development.ini")' % (cmd, cmd))
- sys.exit(1)
+def parse_args(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ 'config_uri',
+ help='Configuration file, e.g., development.ini',
+ )
+ return parser.parse_args(argv[1:])
def main(argv=sys.argv):
- if len(argv) != 2:
- usage(argv)
- config_uri = argv[1]
- setup_logging(config_uri)
- env = bootstrap(config_uri)
+ args = parse_args(argv)
+ setup_logging(args.config_uri)
+ env = bootstrap(args.config_uri)
try:
with env['request'].tm:
diff --git a/docs/tutorials/wiki2/src/models/development.ini b/docs/tutorials/wiki2/src/models/development.ini
index ee050c0ea..564aefb56 100644
--- a/docs/tutorials/wiki2/src/models/development.ini
+++ b/docs/tutorials/wiki2/src/models/development.ini
@@ -22,6 +22,9 @@ retry.attempts = 3
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
@@ -60,7 +63,7 @@ handlers =
qualname = tutorial
[logger_sqlalchemy]
-level = INFO
+level = WARN
handlers =
qualname = sqlalchemy.engine
# "level = INFO" logs SQL queries.
diff --git a/docs/tutorials/wiki2/src/models/production.ini b/docs/tutorials/wiki2/src/models/production.ini
index 91d0f5ddb..29cdda1e1 100644
--- a/docs/tutorials/wiki2/src/models/production.ini
+++ b/docs/tutorials/wiki2/src/models/production.ini
@@ -16,6 +16,9 @@ sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
retry.attempts = 3
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki2/src/models/setup.py b/docs/tutorials/wiki2/src/models/setup.py
index 2576cc848..09e3126ea 100644
--- a/docs/tutorials/wiki2/src/models/setup.py
+++ b/docs/tutorials/wiki2/src/models/setup.py
@@ -25,7 +25,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/tutorials/wiki2/src/models/tutorial/__init__.py b/docs/tutorials/wiki2/src/models/tutorial/__init__.py
index 4dab44823..28bd1f80d 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/__init__.py
@@ -4,9 +4,9 @@ from pyramid.config import Configurator
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- config = Configurator(settings=settings)
- config.include('pyramid_jinja2')
- config.include('.models')
- config.include('.routes')
- config.scan()
+ with Configurator(settings=settings) as config:
+ config.include('pyramid_jinja2')
+ config.include('.models')
+ config.include('.routes')
+ config.scan()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/src/models/tutorial/pshell.py b/docs/tutorials/wiki2/src/models/tutorial/pshell.py
new file mode 100644
index 000000000..108c04d5e
--- /dev/null
+++ b/docs/tutorials/wiki2/src/models/tutorial/pshell.py
@@ -0,0 +1,12 @@
+from . import models
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['dbsession'] = request.dbsession
+ env['models'] = models
diff --git a/docs/tutorials/wiki2/src/models/tutorial/scripts/initialize_db.py b/docs/tutorials/wiki2/src/models/tutorial/scripts/initialize_db.py
index 231d5d44b..e6350fb36 100644
--- a/docs/tutorials/wiki2/src/models/tutorial/scripts/initialize_db.py
+++ b/docs/tutorials/wiki2/src/models/tutorial/scripts/initialize_db.py
@@ -1,4 +1,4 @@
-import os
+import argparse
import sys
from pyramid.paster import bootstrap, setup_logging
@@ -24,19 +24,19 @@ def setup_models(dbsession):
dbsession.add(page)
-def usage(argv):
- cmd = os.path.basename(argv[0])
- print('usage: %s <config_uri>\n'
- '(example: "%s development.ini")' % (cmd, cmd))
- sys.exit(1)
+def parse_args(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ 'config_uri',
+ help='Configuration file, e.g., development.ini',
+ )
+ return parser.parse_args(argv[1:])
def main(argv=sys.argv):
- if len(argv) != 2:
- usage(argv)
- config_uri = argv[1]
- setup_logging(config_uri)
- env = bootstrap(config_uri)
+ args = parse_args(argv)
+ setup_logging(args.config_uri)
+ env = bootstrap(args.config_uri)
try:
with env['request'].tm:
diff --git a/docs/tutorials/wiki2/src/tests/development.ini b/docs/tutorials/wiki2/src/tests/development.ini
index d76a6cd72..8fbb5fd38 100644
--- a/docs/tutorials/wiki2/src/tests/development.ini
+++ b/docs/tutorials/wiki2/src/tests/development.ini
@@ -24,6 +24,9 @@ auth.secret = seekrit
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
@@ -62,7 +65,7 @@ handlers =
qualname = tutorial
[logger_sqlalchemy]
-level = INFO
+level = WARN
handlers =
qualname = sqlalchemy.engine
# "level = INFO" logs SQL queries.
diff --git a/docs/tutorials/wiki2/src/tests/production.ini b/docs/tutorials/wiki2/src/tests/production.ini
index c46adb7b5..9fef64f83 100644
--- a/docs/tutorials/wiki2/src/tests/production.ini
+++ b/docs/tutorials/wiki2/src/tests/production.ini
@@ -18,6 +18,9 @@ retry.attempts = 3
auth.secret = real-seekrit
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki2/src/tests/setup.py b/docs/tutorials/wiki2/src/tests/setup.py
index 28b766cbe..e2a30c0e7 100644
--- a/docs/tutorials/wiki2/src/tests/setup.py
+++ b/docs/tutorials/wiki2/src/tests/setup.py
@@ -26,7 +26,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/__init__.py b/docs/tutorials/wiki2/src/tests/tutorial/__init__.py
index f5c033b8b..5d4bae3d7 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/tests/tutorial/__init__.py
@@ -4,10 +4,10 @@ from pyramid.config import Configurator
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- config = Configurator(settings=settings)
- config.include('pyramid_jinja2')
- config.include('.models')
- config.include('.routes')
- config.include('.security')
- config.scan()
+ with Configurator(settings=settings) as config:
+ config.include('pyramid_jinja2')
+ config.include('.models')
+ config.include('.routes')
+ config.include('.security')
+ config.scan()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/pshell.py b/docs/tutorials/wiki2/src/tests/tutorial/pshell.py
new file mode 100644
index 000000000..108c04d5e
--- /dev/null
+++ b/docs/tutorials/wiki2/src/tests/tutorial/pshell.py
@@ -0,0 +1,12 @@
+from . import models
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['dbsession'] = request.dbsession
+ env['models'] = models
diff --git a/docs/tutorials/wiki2/src/tests/tutorial/scripts/initialize_db.py b/docs/tutorials/wiki2/src/tests/tutorial/scripts/initialize_db.py
index 231d5d44b..e6350fb36 100644
--- a/docs/tutorials/wiki2/src/tests/tutorial/scripts/initialize_db.py
+++ b/docs/tutorials/wiki2/src/tests/tutorial/scripts/initialize_db.py
@@ -1,4 +1,4 @@
-import os
+import argparse
import sys
from pyramid.paster import bootstrap, setup_logging
@@ -24,19 +24,19 @@ def setup_models(dbsession):
dbsession.add(page)
-def usage(argv):
- cmd = os.path.basename(argv[0])
- print('usage: %s <config_uri>\n'
- '(example: "%s development.ini")' % (cmd, cmd))
- sys.exit(1)
+def parse_args(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ 'config_uri',
+ help='Configuration file, e.g., development.ini',
+ )
+ return parser.parse_args(argv[1:])
def main(argv=sys.argv):
- if len(argv) != 2:
- usage(argv)
- config_uri = argv[1]
- setup_logging(config_uri)
- env = bootstrap(config_uri)
+ args = parse_args(argv)
+ setup_logging(args.config_uri)
+ env = bootstrap(args.config_uri)
try:
with env['request'].tm:
diff --git a/docs/tutorials/wiki2/src/views/development.ini b/docs/tutorials/wiki2/src/views/development.ini
index ee050c0ea..564aefb56 100644
--- a/docs/tutorials/wiki2/src/views/development.ini
+++ b/docs/tutorials/wiki2/src/views/development.ini
@@ -22,6 +22,9 @@ retry.attempts = 3
# '127.0.0.1' and '::1'.
# debugtoolbar.hosts = 127.0.0.1 ::1
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
@@ -60,7 +63,7 @@ handlers =
qualname = tutorial
[logger_sqlalchemy]
-level = INFO
+level = WARN
handlers =
qualname = sqlalchemy.engine
# "level = INFO" logs SQL queries.
diff --git a/docs/tutorials/wiki2/src/views/production.ini b/docs/tutorials/wiki2/src/views/production.ini
index 91d0f5ddb..29cdda1e1 100644
--- a/docs/tutorials/wiki2/src/views/production.ini
+++ b/docs/tutorials/wiki2/src/views/production.ini
@@ -16,6 +16,9 @@ sqlalchemy.url = sqlite:///%(here)s/tutorial.sqlite
retry.attempts = 3
+[pshell]
+setup = tutorial.pshell.setup
+
###
# wsgi server configuration
###
diff --git a/docs/tutorials/wiki2/src/views/setup.py b/docs/tutorials/wiki2/src/views/setup.py
index 28b766cbe..e2a30c0e7 100644
--- a/docs/tutorials/wiki2/src/views/setup.py
+++ b/docs/tutorials/wiki2/src/views/setup.py
@@ -26,7 +26,7 @@ requires = [
tests_require = [
'WebTest >= 1.3.1', # py3 compat
- 'pytest',
+ 'pytest>=3.7.4',
'pytest-cov',
]
diff --git a/docs/tutorials/wiki2/src/views/tutorial/__init__.py b/docs/tutorials/wiki2/src/views/tutorial/__init__.py
index 4dab44823..28bd1f80d 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/__init__.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/__init__.py
@@ -4,9 +4,9 @@ from pyramid.config import Configurator
def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
- config = Configurator(settings=settings)
- config.include('pyramid_jinja2')
- config.include('.models')
- config.include('.routes')
- config.scan()
+ with Configurator(settings=settings) as config:
+ config.include('pyramid_jinja2')
+ config.include('.models')
+ config.include('.routes')
+ config.scan()
return config.make_wsgi_app()
diff --git a/docs/tutorials/wiki2/src/views/tutorial/pshell.py b/docs/tutorials/wiki2/src/views/tutorial/pshell.py
new file mode 100644
index 000000000..108c04d5e
--- /dev/null
+++ b/docs/tutorials/wiki2/src/views/tutorial/pshell.py
@@ -0,0 +1,12 @@
+from . import models
+
+def setup(env):
+ request = env['request']
+
+ # start a transaction
+ request.tm.begin()
+
+ # inject some vars into the shell builtins
+ env['tm'] = request.tm
+ env['dbsession'] = request.dbsession
+ env['models'] = models
diff --git a/docs/tutorials/wiki2/src/views/tutorial/scripts/initialize_db.py b/docs/tutorials/wiki2/src/views/tutorial/scripts/initialize_db.py
index 231d5d44b..e6350fb36 100644
--- a/docs/tutorials/wiki2/src/views/tutorial/scripts/initialize_db.py
+++ b/docs/tutorials/wiki2/src/views/tutorial/scripts/initialize_db.py
@@ -1,4 +1,4 @@
-import os
+import argparse
import sys
from pyramid.paster import bootstrap, setup_logging
@@ -24,19 +24,19 @@ def setup_models(dbsession):
dbsession.add(page)
-def usage(argv):
- cmd = os.path.basename(argv[0])
- print('usage: %s <config_uri>\n'
- '(example: "%s development.ini")' % (cmd, cmd))
- sys.exit(1)
+def parse_args(argv):
+ parser = argparse.ArgumentParser()
+ parser.add_argument(
+ 'config_uri',
+ help='Configuration file, e.g., development.ini',
+ )
+ return parser.parse_args(argv[1:])
def main(argv=sys.argv):
- if len(argv) != 2:
- usage(argv)
- config_uri = argv[1]
- setup_logging(config_uri)
- env = bootstrap(config_uri)
+ args = parse_args(argv)
+ setup_logging(args.config_uri)
+ env = bootstrap(args.config_uri)
try:
with env['request'].tm: