summaryrefslogtreecommitdiff
path: root/docs/narr/project.rst
diff options
context:
space:
mode:
Diffstat (limited to 'docs/narr/project.rst')
-rw-r--r--docs/narr/project.rst1284
1 files changed, 711 insertions, 573 deletions
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index 0ada1a379..725263407 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -1,115 +1,146 @@
.. _project_narr:
Creating a :app:`Pyramid` Project
-====================================
+=================================
-As we saw in :ref:`firstapp_chapter`, it's possible to create a
-:app:`Pyramid` application completely manually. However, it's usually more
-convenient to use a :term:`scaffold` to generate a basic :app:`Pyramid`
-:term:`project`.
+As we saw in :ref:`firstapp_chapter`, it's possible to create a :app:`Pyramid`
+application completely manually. However, it's usually more convenient to use
+our :term:`cookiecutter` to generate a basic :app:`Pyramid` :term:`project`.
A project is a directory that contains at least one Python :term:`package`.
-You'll use a scaffold to create a project, and you'll create your application
-logic within a package that lives inside the project. Even if your
-application is extremely simple, it is useful to place code that drives the
-application within a package, because: 1) a package is more easily extended
-with new code and 2) an application that lives inside a package can also be
-distributed more easily than one which does not live within a package.
+You'll use the :app:`Pyramid` cookiecutter to create a project, and you'll
+create your application logic within a package that lives inside the project.
+Even if your application is extremely simple, it is useful to place code that
+drives the application within a package, because (1) a package is more easily
+extended with new code, and (2) an application that lives inside a package can
+also be distributed more easily than one which does not live within a package.
-:app:`Pyramid` comes with a variety of scaffolds that you can use to generate
-a project. Each scaffold makes different configuration assumptions about
-what type of application you're trying to construct.
+The Pylons Project provides a :app:`Pyramid` cookiecutter that you can use to
+generate a project. Our cookiecutter allows several configuration options
+to generate the type of application you're trying to construct.
+
+This cookiecutter is rendered using the ``cookiecutter`` command that you may install.
+
+.. seealso::
+
+ See also `Cookiecutter Installation <https://cookiecutter.readthedocs.io/en/latest/installation.html>`_.
-These scaffolds are rendered using the ``pcreate`` command that is installed
-as part of Pyramid.
.. index::
- single: scaffolds
- single: starter scaffold
- single: zodb scaffold
- single: alchemy scaffold
+ single: cookiecutters
+ single: pyramid-cookiecutter-starter
+
+.. _additional_cookiecutters:
+
+:app:`Pyramid` cookiecutters
+----------------------------
-.. _additional_paster_scaffolds:
+The Pyramid cookiecutter released under the Pylons Project offers the following configuration options:
-Scaffolds Included with :app:`Pyramid`
-------------------------------------------------
+- templating libraries (:term:`Jinja2`, :term:`Chameleon`, or :term:`Mako`)
-The convenience scaffolds included with :app:`Pyramid` differ from
-each other on a number of axes:
+- the persistence mechanism (no persistence mechanism, :term:`SQLAlchemy` with SQLite, or :term:`ZODB`)
-- the persistence mechanism they offer (no persistence mechanism,
- :term:`ZODB`, or :term:`SQLAlchemy`).
+- the mechanism of mapping URLs to code (:term:`URL dispatch` or :term:`traversal`)
-- the mechanism they use to map URLs to code (:term:`traversal` or :term:`URL
- dispatch`).
+* `pyramid-cookiecutter-starter <https://github.com/Pylons/pyramid-cookiecutter-starter>`_
-The included scaffolds are these:
+All configuration options offer a choice of templating language.
-``starter``
- URL mapping via :term:`URL dispatch` and no persistence mechanism.
+The configuration of mapping URLs to code (routing) depends on the backend option selected, with additional variations as follows.
+
+``none``
+ :term:`URL dispatch` for routing
+
+``sqlalchemy``
+ SQLite for persistent storage, :term:`SQLAlchemy` for an ORM, :term:`URL dispatch` for routing, and :term:`Alembic` for database migrations
``zodb``
- URL mapping via :term:`traversal` and persistence via :term:`ZODB`.
+ :term:`ZODB` for persistent storage and :term:`traversal` for routing
-``alchemy``
- URL mapping via :term:`URL dispatch` and persistence via
- :term:`SQLAlchemy`
.. index::
single: creating a project
single: project
+ single: cookiecutter
.. _creating_a_project:
Creating the Project
--------------------
-In :ref:`installing_chapter`, you created a virtual Python environment via
-the ``virtualenv`` command. To start a :app:`Pyramid` :term:`project`, use
-the ``pcreate`` command installed within the virtualenv. We'll choose the
-``starter`` scaffold for this purpose. When we invoke ``pcreate``, it will
-create a directory that represents our project.
+In :ref:`installing_chapter`, you created a virtual Python environment via the
+``venv`` command. We called the virtual environment directory
+``env`` and set an environment variable ``VENV`` to its path.
-In :ref:`installing_chapter` we called the virtualenv directory ``env``; the
-following commands assume that our current working directory is the ``env``
-directory.
+We assume that you :ref:`previously installed cookiecutter <cookiecutters>`, following its installation instructions.
-The below example uses the ``pcreate`` command to create a project with the
-``starter`` scaffold.
+When we invoke ``cookiecutter``, it will create a directory that represents our project.
-On UNIX:
+We assume our current working directory is the value of ``VENV``.
-.. code-block:: text
+On all platforms, generate a project using cookiecutter.
- $ $VENV/bin/pcreate -s starter MyProject
+.. code-block:: bash
-Or on Windows:
+ cookiecutter gh:Pylons/pyramid-cookiecutter-starter --checkout master
+
+If prompted for the first item, accept the default ``yes`` by hitting return.
.. code-block:: text
- > %VENV%\Scripts\pcreate -s starter MyProject
-
+ You've cloned ~/.cookiecutters/pyramid-cookiecutter-starter before.
+ Is it okay to delete and re-clone it? [yes]: yes
+ project_name [Pyramid Scaffold]: myproject
+ repo_name [myproject]: myproject
+ Select template_language:
+ 1 - jinja2
+ 2 - chameleon
+ 3 - mako
+ Choose from 1, 2, 3 [1]: 1
+ Select backend:
+ 1 - none
+ 2 - sqlalchemy
+ 3 - zodb
+ Choose from 1, 2, 3 [1]: 1
+
+We then run through the following commands.
+
+On Unix:
+
+.. code-block:: bash
+
+ # Reset our environment variable for a new virtual environment.
+ export VENV=~/env/myproject/env
+ # Change directory into your newly created project.
+ cd myproject
+ # Create a new virtual environment...
+ python3 -m venv $VENV
+ # ...where we upgrade packaging tools.
+ env/bin/pip install --upgrade pip setuptools
-Here's sample output from a run of ``pcreate`` on UNIX for a project we name
-``MyProject``:
+Or on Windows:
-.. code-block:: text
+.. code-block:: doscon
- $ $VENV/bin/pcreate -s starter MyProject
- Creating template pyramid
- Creating directory ./MyProject
- # ... more output ...
- Running /Users/chrism/projects/pyramid/bin/python setup.py egg_info
+ # Reset our environment variable for a new virtual environment.
+ set VENV=c:\env\myproject\env
+ # Change directory into your newly created project.
+ cd myproject
+ # Create a new virtual environment...
+ python -m venv %VENV%
+ # ...where we upgrade packaging tools.
+ %VENV%\Scripts\pip install --upgrade pip setuptools
-As a result of invoking the ``pcreate`` command, a directory named
-``MyProject`` is created. That directory is a :term:`project` directory.
-The ``setup.py`` file in that directory can be used to distribute your
-application, or install your application for deployment or development.
+As a result of invoking the ``cookiecutter`` command, a directory named
+``myproject`` is created. That directory is a :term:`project` directory. The
+``setup.py`` file in that directory can be used to distribute your application,
+or install your application for deployment or development.
-A ``.ini`` file named ``development.ini`` will be created in the project
-directory. You will use this ``.ini`` file to configure a server, to run
-your application, and to debug your application. It contains configuration
-that enables an interactive debugger and settings optimized for development.
+An ``.ini`` file named ``development.ini`` will be created in the project
+directory. You will use this ``.ini`` file to configure a server, to run your
+application, and to debug your application. It contains configuration that
+enables an interactive debugger and settings optimized for development.
Another ``.ini`` file named ``production.ini`` will also be created in the
project directory. It contains configuration that disables any interactive
@@ -117,29 +148,29 @@ debugger (to prevent inappropriate access and disclosure), and turns off a
number of debugging settings. You can use this file to put your application
into production.
-The ``MyProject`` project directory contains an additional subdirectory named
-``myproject`` (note the case difference) representing a Python
-:term:`package` which holds very simple :app:`Pyramid` sample code. This is
-where you'll edit your application's Python code and templates.
-
-We created this project within an ``env`` virtualenv directory. However,
-note that this is not mandatory. The project directory can go more or less
-anywhere on your filesystem. You don't need to put it in a special "web
-server" directory, and you don't need to put it within a virtualenv
-directory. The author uses Linux mainly, and tends to put project
-directories which he creates within his ``~/projects`` directory. On
-Windows, it's a good idea to put project directories within a directory that
-contains no space characters, so it's wise to *avoid* a path that contains
-i.e. ``My Documents``. As a result, the author, when he uses Windows, just
-puts his projects in ``C:\projects``.
+The ``myproject`` project directory contains an additional subdirectory named
+``myproject`` (note the case difference) representing a Python :term:`package`
+which holds very simple :app:`Pyramid` sample code. This is where you'll edit
+your application's Python code and templates.
+
+We created this project in a directory next to its virtual environment directory.
+However, note that this is not mandatory. The project directory can go more or
+less anywhere on your filesystem. You don't need to put it in a special "web
+server" directory. You could put it within a virtual environment
+directory. The author uses Linux mainly, and tends to put project directories
+which he creates within his ``~/projects`` directory. On Windows, it's a good
+idea to put project directories within a directory that contains no space
+characters, so it's wise to *avoid* a path that contains, i.e., ``My
+Documents``. As a result, the author, when he uses Windows, just puts his
+projects in ``C:\projects``.
.. warning::
- You'll need to avoid using ``pcreate`` to create a project with the same
+ You'll need to avoid using ``cookiecutter`` to create a project with the same
name as a Python standard library component. In particular, this means you
- should avoid using the names ``site`` or ``test``, both of which
- conflict with Python standard library packages. You should also avoid
- using the name ``pyramid``, which will conflict with Pyramid itself.
+ should avoid using the names ``site`` or ``test``, both of which conflict
+ with Python standard library packages. You should also avoid using the name
+ ``pyramid``, which will conflict with Pyramid itself.
.. index::
single: setup.py develop
@@ -150,97 +181,117 @@ Installing your Newly Created Project for Development
To install a newly created project for development, you should ``cd`` to the
newly created project directory and use the Python interpreter from the
-:term:`virtualenv` you created during :ref:`installing_chapter` to invoke the
-command ``python setup.py develop``
+:term:`virtual environment` you created during :ref:`installing_chapter` to
+invoke the command ``pip install -e .``, which installs the project in
+development mode (``-e`` is for "editable") into the current directory (``.``).
-The file named ``setup.py`` will be in the root of the pcreate-generated
-project directory. The ``python`` you're invoking should be the one that
-lives in the ``bin`` (or ``Scripts`` on Windows) directory of your virtual
-Python environment. Your terminal's current working directory *must* be the
-newly created project directory.
+The file named ``setup.py`` will be in the root of the cookiecutter-generated
+project directory. The ``python`` you're invoking should be the one that lives
+in the ``bin`` (or ``Scripts`` on Windows) directory of your virtual Python
+environment. Your terminal's current working directory *must* be the newly
+created project directory.
-On UNIX:
+On Unix:
-.. code-block:: text
+.. code-block:: bash
- $ cd MyProject
- $ $VENV/bin/python setup.py develop
+ $VENV/bin/pip install -e .
Or on Windows:
-.. code-block:: text
+.. code-block:: doscon
- > cd MyProject
- > %VENV%\Scripts\python.exe setup.py develop
+ %VENV%\Scripts\pip install -e .
-Elided output from a run of this command on UNIX is shown below:
+Elided output from a run of this command on Unix is shown below:
-.. code-block:: text
+.. code-block:: bash
- $ cd MyProject
- $ $VENV/bin/python setup.py develop
- ...
- Finished processing dependencies for MyProject==0.0
+ Running setup.py develop for myproject
+ Successfully installed Jinja2-2.8 Mako-1.0.6 MarkupSafe-0.23 \
+ PasteDeploy-1.5.2 Pygments-2.1.3 WebOb-1.7.0 myproject pyramid-1.7.3 \
+ pyramid-debugtoolbar-3.0.5 pyramid-jinja2-2.7 pyramid-mako-1.0.2 \
+ repoze.lru-0.6 translationstring-1.3 venusian-1.0 waitress-1.0.1 \
+ zope.deprecation-4.2.0 zope.interface-4.3.3
-This will install a :term:`distribution` representing your project
-into the virtual environment interpreter's library set so it can be
-found by ``import`` statements and by other console scripts such as
-``pserve``, ``pshell``, ``proutes`` and ``pviews``.
+This will install a :term:`distribution` representing your project into the
+virtual environment interpreter's library set so it can be found by ``import``
+statements and by other console scripts such as ``pserve``, ``pshell``,
+``proutes``, and ``pviews``.
.. index::
single: running tests
single: tests (running)
-Running The Tests For Your Application
+Running the Tests for Your Application
--------------------------------------
-To run unit tests for your application, you should invoke them using the
-Python interpreter from the :term:`virtualenv` you created during
-:ref:`installing_chapter` (the ``python`` command that lives in the ``bin``
-directory of your virtualenv).
+To run unit tests for your application, you must first install the testing
+dependencies.
-On UNIX:
+On Unix:
-.. code-block:: text
+.. code-block:: bash
- $ $VENV/bin/python setup.py test -q
+ $VENV/bin/pip install -e ".[testing]"
-Or on Windows:
+On Windows:
-.. code-block:: text
+.. code-block:: doscon
- > %VENV%\Scripts\python.exe setup.py test -q
+ %VENV%\Scripts\pip install -e ".[testing]"
-Here's sample output from a test run on UNIX:
+Once the testing requirements are installed, then you can run the tests using
+the ``pytest`` command that was just installed in the ``bin`` directory of
+your virtual environment.
-.. code-block:: text
+On Unix:
+
+.. code-block:: bash
+
+ $VENV/bin/pytest -q
+
+On Windows:
+
+.. code-block:: doscon
+
+ %VENV%\Scripts\pytest -q
- $ $VENV/bin/python setup.py test -q
- running test
- running egg_info
- writing requirements to MyProject.egg-info/requires.txt
- writing MyProject.egg-info/PKG-INFO
- writing top-level names to MyProject.egg-info/top_level.txt
- writing dependency_links to MyProject.egg-info/dependency_links.txt
- writing entry points to MyProject.egg-info/entry_points.txt
- reading manifest file 'MyProject.egg-info/SOURCES.txt'
- writing manifest file 'MyProject.egg-info/SOURCES.txt'
- running build_ext
- ..
- ----------------------------------------------------------------------
- Ran 1 test in 0.108s
-
- OK
-
-The tests themselves are found in the ``tests.py`` module in your ``pcreate``
-generated project. Within a project generated by the ``starter`` scaffold, a
-single sample test exists.
+Here's sample output from a test run on Unix:
+
+.. code-block:: bash
+
+ $VENV/bin/pytest -q
+ ..
+ 2 passed in 0.47 seconds
+
+The tests themselves are found in the ``tests.py`` module in your ``cookiecutter``-generated project. Within a project generated by the ``pyramid-cookiecutter-starter`` cookiecutter, only two sample tests exist.
.. note::
- The ``-q`` option is passed to the ``setup.py test`` command to limit the
- output to a stream of dots. If you don't pass ``-q``, you'll see more
- verbose test result output (which normally isn't very useful).
+ The ``-q`` option is passed to the ``pytest`` command to limit the output
+ to a stream of dots. If you don't pass ``-q``, you'll see verbose test
+ result output (which normally isn't very useful).
+
+Alternatively, if you'd like to see test coverage, pass the ``--cov`` option
+to ``pytest``:
+
+.. code-block:: bash
+
+ $VENV/bin/pytest --cov -q
+
+Cookiecutters include configuration defaults for ``pytest`` and test coverage.
+These configuration files are ``pytest.ini`` and ``.coveragerc``, located at
+the root of your package. Without these defaults, we would need to specify the
+path to the module on which we want to run tests and coverage.
+
+.. code-block:: bash
+
+ $VENV/bin/pytest --cov=myproject myproject/tests.py -q
+
+.. seealso:: See ``pytest``'s documentation for :ref:`pytest:usage` or invoke
+ ``pytest -h`` to see its full set of options.
+
.. index::
single: running an application
@@ -250,83 +301,85 @@ single sample test exists.
.. _running_the_project_application:
-Running The Project Application
+Running the Project Application
-------------------------------
+.. seealso:: See also the output of :ref:`pserve --help <pserve_script>`.
+
Once a project is installed for development, you can run the application it
represents using the ``pserve`` command against the generated configuration
file. In our case, this file is named ``development.ini``.
-On UNIX:
+On Unix:
-.. code-block:: text
+.. code-block:: bash
- $ $VENV/bin/pserve development.ini
+ $VENV/bin/pserve development.ini
On Windows:
-.. code-block:: text
+.. code-block:: doscon
- > %VENV%\Scripts\pserve development.ini
+ %VENV%\Scripts\pserve development.ini
-Here's sample output from a run of ``pserve`` on UNIX:
+Here's sample output from a run of ``pserve`` on Unix:
-.. code-block:: text
+.. code-block:: bash
- $ $VENV/bin/pserve development.ini
- Starting server in PID 16601.
- serving on http://0.0.0.0:6543
-
-When you use ``pserve`` to start the application implied by the default
-rendering of a scaffold, it will respond to requests on *all* IP addresses
-possessed by your system, not just requests to ``localhost``. This is what
-the ``0.0.0.0`` in ``serving on http://0.0.0.0:6543`` means. The server will
-respond to requests made to ``127.0.0.1`` and on any external IP address.
-For example, your system might be configured to have an external IP address
-``192.168.1.50``. If that's the case, if you use a browser running on the
-same system as Pyramid, it will be able to access the application via
-``http://127.0.0.1:6543/`` as well as via
-``http://192.168.1.50:6543/``. However, *other people* on other computers on
-the same network will also be able to visit your Pyramid application in their
-browser by visiting ``http://192.168.1.50:6543/``.
+ $VENV/bin/pserve development.ini
+ Starting server in PID 77171.
+ Serving on http://localhost:6543
+ Serving on http://localhost:6543
-If you want to restrict access such that only a browser running on the same
-machine as Pyramid will be able to access your Pyramid application, edit the
-``development.ini`` file, and replace the ``host`` value in the
-``[server:main]`` section. Change it from ``0.0.0.0`` to ``127.0.0.1``. For
-example:
+Access is restricted such that only a browser running on the same machine as
+Pyramid will be able to access your Pyramid application. However, if you want
+to open access to other machines on the same network, then edit the
+``development.ini`` file, and replace the ``listen`` value in the
+``[server:main]`` section, changing it from ``localhost:6543`` to ``*:6543``
+(this is equivalent to ``0.0.0.0:6543 [::]:6543``). For example:
.. code-block:: ini
- [server:main]
- use = egg:waitress#main
- host = 127.0.0.1
- port = 6543
+ [server:main]
+ use = egg:waitress#main
+ listen = *:6543
+
+Now when you use ``pserve`` to start the application, it will respond to
+requests on *all* IP addresses possessed by your system, not just requests to
+``localhost``. This is what the ``0.0.0.0`` in
+``serving on http://0.0.0.0:6543`` means. The server will respond to requests
+made to ``127.0.0.1`` and on any external IP address. For example, your system
+might be configured to have an external IP address ``192.168.1.50``. If that's
+the case, if you use a browser running on the same system as Pyramid, it will
+be able to access the application via ``http://127.0.0.1:6543/`` as well as via
+``http://192.168.1.50:6543/``. However, *other people* on other computers on
+the same network will also be able to visit your Pyramid application in their
+browser by visiting ``http://192.168.1.50:6543/``. The same holds true if you use
+IPv6. ``[::]`` means the same as ``0.0.0.0`` but for IPv6 protocol.
You can change the port on which the server runs on by changing the same
portion of the ``development.ini`` file. For example, you can change the
-``port = 6543`` line in the ``development.ini`` file's ``[server:main]``
-section to ``port = 8080`` to run the server on port 8080 instead of
-port 6543.
+``listen = localhost:6543`` line in the ``development.ini`` file's ``[server:main]``
+section to ``listen = localhost:8080`` to run the server on port 8080 instead of port 6543.
-You can shut down a server started this way by pressing ``Ctrl-C``.
+You can shut down a server started this way by pressing ``Ctrl-C`` (or
+``Ctrl-Break`` on Windows).
The default server used to run your Pyramid application when a project is
-created from a scaffold is named :term:`Waitress`. This server is what
-prints the ``serving on...`` line when you run ``pserve``. It's a good idea
-to use this server during development, because it's very simple. It can also
-be used for light production. Setting your application up under a different
-server is not advised until you've done some development work under the
-default server, particularly if you're not yet experienced with Python web
-development. Python web server setup can be complex, and you should get some
-confidence that your application works in a default environment before trying
-to optimize it or make it "more like production". It's awfully easy to get
-sidetracked trying to set up a nondefault server for hours without actually
-starting to do any development. One of the nice things about Python web
-servers is that they're largely interchangeable, so if your application works
-under the default server, it will almost certainly work under any other
-server in production if you eventually choose to use a different one. Don't
-worry about it right now.
+created from a cookiecutter is named :term:`Waitress`. This server is what prints
+the ``Serving on...`` line when you run ``pserve``. It's a good idea to use
+this server during development because it's very simple. It can also be used
+for light production. Setting your application up under a different server is
+not advised until you've done some development work under the default server,
+particularly if you're not yet experienced with Python web development. Python
+web server setup can be complex, and you should get some confidence that your
+application works in a default environment before trying to optimize it or make
+it "more like production". It's awfully easy to get sidetracked trying to set
+up a non-default server for hours without actually starting to do any
+development. One of the nice things about Python web servers is that they're
+largely interchangeable, so if your application works under the default server,
+it will almost certainly work under any other server in production if you
+eventually choose to use a different one. Don't worry about it right now.
For more detailed information about the startup process, see
:ref:`startup_chapter`. For more information about environment variables and
@@ -338,36 +391,38 @@ configuration file settings that influence startup and runtime behavior, see
Reloading Code
~~~~~~~~~~~~~~
-During development, it's often useful to run ``pserve`` using its
-``--reload`` option. When ``--reload`` is passed to ``pserve``, changes to
-any Python module your project uses will cause the server to restart. This
-typically makes development easier, as changes to Python code made within a
+During development, it's often useful to run ``pserve`` using its ``--reload``
+option. When ``--reload`` is passed to ``pserve``, changes to any Python
+module your project uses will cause the server to restart. This typically
+makes development easier, as changes to Python code made within a
:app:`Pyramid` application is not put into effect until the server restarts.
-For example, on UNIX:
+For example, on Unix:
.. code-block:: text
- $ $VENV/bin/pserve development.ini --reload
- Starting subprocess with file monitor
- Starting server in PID 16601.
- serving on http://0.0.0.0:6543
+ $VENV/bin/pserve development.ini --reload
+ Starting subprocess with file monitor
+ Starting server in PID 16601.
+ Serving on http://localhost:6543
+ Serving on http://localhost:6543
Now if you make a change to any of your project's ``.py`` files or ``.ini``
files, you'll see the server restart automatically:
.. code-block:: text
- development.ini changed; reloading...
- -------------------- Restarting --------------------
- Starting server in PID 16602.
- serving on http://0.0.0.0:6543
+ development.ini changed; reloading...
+ -------------------- Restarting --------------------
+ Starting server in PID 16602.
+ Serving on http://localhost:6543
+ Serving on http://localhost:6543
Changes to template files (such as ``.pt`` or ``.mak`` files) won't cause the
-server to restart. Changes to template files don't require a server restart
-as long as the ``pyramid.reload_templates`` setting in the
-``development.ini`` file is ``true``. Changes made to template files when
-this setting is true will take effect immediately without a server restart.
+server to restart. Changes to template files don't require a server restart as
+long as the ``pyramid.reload_templates`` setting in the ``development.ini``
+file is ``true``. Changes made to template files when this setting is ``true``
+will take effect immediately without a server restart.
.. index::
single: WSGI
@@ -381,8 +436,8 @@ browser like what is displayed in the following image:
.. image:: project.png
-This is the page shown by default when you visit an unmodified ``pcreate``
-generated ``starter`` application in a browser.
+This is the page shown by default when you visit an unmodified ``cookiecutter``
+generated ``pyramid-cookiecutter-starter`` application in a browser.
.. index::
single: debug toolbar
@@ -392,71 +447,70 @@ generated ``starter`` application in a browser.
The Debug Toolbar
~~~~~~~~~~~~~~~~~
-If you click on the image shown at the right hand top of the page ("^DT"),
-you'll be presented with a debug toolbar that provides various niceties while
-you're developing. This image will float above every HTML page served by
-:app:`Pyramid` while you develop an application, and allows you show the
-toolbar as necessary. Click on ``Hide`` to hide the toolbar and show the
-image again.
+.. image:: project-show-toolbar.png
+
+If you click on the :app:`Pyramid` logo at the top right of the page, a new
+target window will open to present a debug toolbar that provides various
+niceties while you're developing. This logo will float above every HTML page
+served by :app:`Pyramid` while you develop an application, and allows you to
+show the toolbar as necessary.
.. image:: project-debug.png
-If you don't see the debug toolbar image on the right hand top of the page,
-it means you're browsing from a system that does not have debugging access.
-By default, for security reasons, only a browser originating from
-``localhost`` (``127.0.0.1``) can see the debug toolbar. To allow your
-browser on a remote system to access the server, add a line within the
-``[app:main]`` section of the ``development.ini`` file in the form
-``debugtoolbar.hosts = X.X.X.X``. For example, if your Pyramid application
-is running on a remote system, and you're browsing from a host with the IP
-address ``192.168.1.1``, you'd add something like this to enable the toolbar
-when your system contacts Pyramid:
+If you don't see the Pyramid logo on the top right of the page, it means you're
+browsing from a system that does not have debugging access. By default, for
+security reasons, only a browser originating from ``localhost`` (``127.0.0.1``)
+can see the debug toolbar. To allow your browser on a remote system to access
+the server, add a line within the ``[app:main]`` section of the
+``development.ini`` file in the form ``debugtoolbar.hosts = X .X.X.X``. For
+example, if your Pyramid application is running on a remote system, and you're
+browsing from a host with the IP address ``192.168.1.1``, you'd add something
+like this to enable the toolbar when your system contacts Pyramid:
.. code-block:: ini
- [app:main]
- # .. other settings ...
- debugtoolbar.hosts = 192.168.1.1
+ [app:main]
+ # .. other settings ...
+ debugtoolbar.hosts = 192.168.1.1
-For more information about what the debug toolbar allows you to do, see `the
-documentation for pyramid_debugtoolbar
-<http://docs.pylonsproject.org/projects/pyramid_debugtoolbar/en/latest/>`_.
+For more information about what the debug toolbar allows you to do, see the
+:ref:`documentation for pyramid_debugtoolbar <toolbar:overview>`.
-The debug toolbar will not be shown (and all debugging will be turned off)
-when you use the ``production.ini`` file instead of the ``development.ini``
-ini file to run the application.
+The debug toolbar will not be shown (and all debugging will be turned off) when
+you use the ``production.ini`` file instead of the ``development.ini`` ini file
+to run the application.
You can also turn the debug toolbar off by editing ``development.ini`` and
commenting out a line. For example, instead of:
.. code-block:: ini
- :linenos:
+ :linenos:
- [app:main]
- ...
- pyramid.includes =
- pyramid_debugtoolbar
+ [app:main]
+ # ... elided configuration
+ pyramid.includes =
+ pyramid_debugtoolbar
Put a hash mark at the beginning of the ``pyramid_debugtoolbar`` line:
.. code-block:: ini
- :linenos:
+ :linenos:
- [app:main]
- ...
- pyramid.includes =
- # pyramid_debugtoolbar
+ [app:main]
+ # ... elided configuration
+ pyramid.includes =
+ # pyramid_debugtoolbar
Then restart the application to see that the toolbar has been turned off.
Note that if you comment out the ``pyramid_debugtoolbar`` line, the ``#``
-*must* be in the first column. If you put it anywhere else,
-and then attempt to restart the application,
-you'll receive an error that ends something like this:
+*must* be in the first column. If you put it anywhere else, and then attempt
+to restart the application, you'll receive an error that ends something like
+this:
.. code-block:: text
- ImportError: No module named #pyramid_debugtoolbar
+ ImportError: No module named #pyramid_debugtoolbar
.. index::
single: project structure
@@ -464,168 +518,178 @@ you'll receive an error that ends something like this:
The Project Structure
---------------------
-The ``starter`` scaffold generated a :term:`project` (named ``MyProject``),
+The ``pyramid-cookiecutter-starter`` cookiecutter generated a :term:`project` (named ``myproject``),
which contains a Python :term:`package`. The package is *also* named
-``myproject``, but it's lowercased; the scaffold generates a project which
-contains a package that shares its name except for case.
+``myproject``; the cookiecutter generates a project which
+contains a package that shares its name.
-All :app:`Pyramid` ``pcreate`` -generated projects share a similar structure.
-The ``MyProject`` project we've generated has the following directory
-structure:
+All :app:`Pyramid` ``cookiecutter``-generated projects share a similar structure.
+The ``myproject`` project we've generated has the following directory structure:
.. code-block:: text
- MyProject/
- |-- CHANGES.txt
- |-- development.ini
- |-- MANIFEST.in
- |-- myproject
- | |-- __init__.py
- | |-- static
- | | |-- pyramid-16x16.png
- | | |-- pyramid.png
- | | |-- theme.css
- | | `-- theme.min.css
- | |-- templates
- | | `-- mytemplate.pt
- | |-- tests.py
- | `-- views.py
- |-- production.ini
- |-- README.txt
- `-- setup.py
-
-The ``MyProject`` :term:`Project`
+ 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
+ │   ├── __init__.py
+ │   ├── default.py
+ │   └── notfound.py
+ ├── README.txt
+ ├── development.ini
+ ├── production.ini
+ ├── pytest.ini
+ └── setup.py
+
+
+The ``myproject`` :term:`Project`
---------------------------------
-The ``MyProject`` :term:`project` directory is the distribution and
-deployment wrapper for your application. It contains both the ``myproject``
+The ``myproject`` :term:`project` directory is the distribution and deployment
+wrapper for your application. It contains both the ``myproject``
:term:`package` representing your application as well as files used to
describe, run, and test your application.
-#. ``CHANGES.txt`` describes the changes you've made to the application. It
- is conventionally written in :term:`ReStructuredText` format.
-
-#. ``README.txt`` describes the application in general. It is conventionally
- written in :term:`ReStructuredText` format.
+#. ``.coveragerc`` configures coverage when running tests.
-#. ``development.ini`` is a :term:`PasteDeploy` configuration file that can
- be used to execute your application during development.
+#. ``.gitignore`` tells git which files and directories to ignore from source code version control.
-#. ``production.ini`` is a :term:`PasteDeploy` configuration file that can
- be used to execute your application in a production configuration.
+#. ``CHANGES.txt`` describes the changes you've made to the application. It is
+ conventionally written in :term:`reStructuredText` format.
#. ``MANIFEST.in`` is a :term:`distutils` "manifest" file, naming which files
should be included in a source distribution of the package when ``python
setup.py sdist`` is run.
-#. ``setup.py`` is the file you'll use to test and distribute your
- application. It is a standard :term:`setuptools` ``setup.py`` file.
+#. ``README.txt`` describes the application in general. It is conventionally
+ written in :term:`reStructuredText` format.
+
+#. ``development.ini`` is a :term:`PasteDeploy` configuration file that can be
+ used to execute your application during development.
+
+#. ``production.ini`` is a :term:`PasteDeploy` configuration file that can be
+ used to execute your application in a production configuration.
+
+#. ``pytest.ini`` is a configuration file for running tests.
+
+#. ``setup.py`` is the file you'll use to test and distribute your application.
+ It is a standard :term:`Setuptools` ``setup.py`` file.
.. index::
single: PasteDeploy
single: ini file
-.. _MyProject_ini:
+.. _myproject_ini:
``development.ini``
~~~~~~~~~~~~~~~~~~~
-The ``development.ini`` file is a :term:`PasteDeploy` configuration file.
-Its purpose is to specify an application to run when you invoke ``pserve``,
-as well as the deployment settings provided to that application.
+The ``development.ini`` file is a :term:`PasteDeploy` configuration file. Its
+purpose is to specify an application to run when you invoke ``pserve``, as well
+as the deployment settings provided to that application.
The generated ``development.ini`` file looks like so:
-.. literalinclude:: MyProject/development.ini
+.. literalinclude:: myproject/development.ini
:language: ini
:linenos:
This file contains several sections including ``[app:main]``,
-``[server:main]`` and several other sections related to logging
-configuration.
+``[server:main]``, and several other sections related to logging configuration.
The ``[app:main]`` section represents configuration for your :app:`Pyramid`
-application. The ``use`` setting is the only setting required to be present
-in the ``[app:main]`` section. Its default value, ``egg:MyProject``,
-indicates that our MyProject project contains the application that should be
-served. Other settings added to this section are passed as keyword arguments
-to the function named ``main`` in our package's ``__init__.py`` module. You
-can provide startup-time configuration parameters to your application by
-adding more settings to this section.
+application. The ``use`` setting is the only setting required to be present in
+the ``[app:main]`` section. Its default value, ``egg:myproject``, indicates
+that our myproject project contains the application that should be served.
+Other settings added to this section are passed as keyword arguments to the
+function named ``main`` in our package's ``__init__.py`` module. You can
+provide startup-time configuration parameters to your application by adding
+more settings to this section.
-.. note:: See :ref:`pastedeploy_entry_points` for more information about the
- meaning of the ``use = egg:MyProject`` value in this section.
+.. seealso:: See :ref:`pastedeploy_entry_points` for more information about the
+ meaning of the ``use = egg:myproject`` value in this section.
The ``pyramid.reload_templates`` setting in the ``[app:main]`` section is a
-:app:`Pyramid` -specific setting which is passed into the framework. If it
-exists, and its value is ``true``, supported template changes will not
-require an application restart to be detected. See
-:ref:`reload_templates_section` for more information.
+:app:`Pyramid`-specific setting which is passed into the framework. If it
+exists, and its value is ``true``, supported template changes will not require
+an application restart to be detected. See :ref:`reload_templates_section` for
+more information.
.. warning:: The ``pyramid.reload_templates`` option should be turned off for
production applications, as template rendering is slowed when it is turned
on.
-The ``pyramid.includes`` setting in the ``[app:main]`` section tells Pyramid
-to "include" configuration from another package. In this case, the line
+The ``pyramid.includes`` setting in the ``[app:main]`` section tells Pyramid to
+"include" configuration from another package. In this case, the line
``pyramid.includes = pyramid_debugtoolbar`` tells Pyramid to include
configuration from the ``pyramid_debugtoolbar`` package. This turns on a
-debugging panel in development mode which will be shown on the right hand
-side of the screen. Including the debug toolbar will also make it possible
-to interactively debug exceptions when an error occurs.
+debugging panel in development mode which can be opened by clicking on the
+:app:`Pyramid` logo on the top right of the screen. Including the debug
+toolbar will also make it possible to interactively debug exceptions when an
+error occurs.
-Various other settings may exist in this section having to do with debugging
-or influencing runtime behavior of a :app:`Pyramid` application. See
+Various other settings may exist in this section having to do with debugging or
+influencing runtime behavior of a :app:`Pyramid` application. See
:ref:`environment_chapter` for more information about these settings.
The name ``main`` in ``[app:main]`` signifies that this is the default
application run by ``pserve`` when it is invoked against this configuration
-file. The name ``main`` is a convention used by PasteDeploy signifying that
-it is the default application.
+file. The name ``main`` is a convention used by PasteDeploy signifying that it
+is the default application.
The ``[server:main]`` section of the configuration file configures a WSGI
-server which listens on TCP port 6543. It is configured to listen on all
-interfaces (``0.0.0.0``). This means that any remote system which has TCP
-access to your system can see your Pyramid application.
-
-.. _MyProject_ini_logging:
-
-The sections that live between the markers ``# Begin logging configuration``
-and ``# End logging configuration`` represent Python's standard library
-:mod:`logging` module configuration for your application. The sections
-between these two markers are passed to the `logging module's config file
-configuration engine
-<http://docs.python.org/howto/logging.html#configuring-logging>`_ when the
-``pserve`` or ``pshell`` commands are executed. The default
-configuration sends application logging output to the standard error output
-of your terminal. For more information about logging configuration, see
-:ref:`logging_chapter`.
+server which listens on TCP port 6543. It is configured to listen on localhost
+only (``127.0.0.1``).
+
+.. _myproject_ini_logging:
+
+The sections after ``# logging configuration`` represent Python's standard
+library :mod:`logging` module configuration for your application. These
+sections are passed to the `logging module's config file configuration engine
+<https://docs.python.org/2/howto/logging.html#configuring-logging>`_ when the
+``pserve`` or ``pshell`` commands are executed. The default configuration
+sends application logging output to the standard error output of your terminal.
+For more information about logging configuration, see :ref:`logging_chapter`.
See the :term:`PasteDeploy` documentation for more information about other
types of things you can put into this ``.ini`` file, such as other
-applications, :term:`middleware` and alternate :term:`WSGI` server
+applications, :term:`middleware`, and alternate :term:`WSGI` server
implementations.
.. index::
single: production.ini
``production.ini``
-~~~~~~~~~~~~~~~~~~~
+~~~~~~~~~~~~~~~~~~
-The ``production.ini`` file is a :term:`PasteDeploy` configuration file with
-a purpose much like that of ``development.ini``. However, it disables the
-debug toolbar, and filters all log messages except those above the WARN
-level. It also turns off template development options such that templates
-are not automatically reloaded when changed, and turns off all debugging
-options. This file is appropriate to use instead of ``development.ini`` when
-you put your application into production.
+The ``production.ini`` file is a :term:`PasteDeploy` configuration file with a
+purpose much like that of ``development.ini``. However, it disables the debug
+toolbar, and filters all log messages except those above the WARN level. It
+also turns off template development options such that templates are not
+automatically reloaded when changed, and turns off all debugging options. This
+file is appropriate to use instead of ``development.ini`` when you put your
+application into production.
It's important to use ``production.ini`` (and *not* ``development.ini``) to
benchmark your application and put it into production. ``development.ini``
configures your system with a debug toolbar that helps development, but the
inclusion of this toolbar slows down page rendering times by over an order of
-magnitude. The debug toolbar is also a potential security risk if you have
-it configured incorrectly.
+magnitude. The debug toolbar is also a potential security risk if you have it
+configured incorrectly.
.. index::
single: MANIFEST.in
@@ -637,42 +701,40 @@ The ``MANIFEST.in`` file is a :term:`distutils` configuration file which
specifies the non-Python files that should be included when a
:term:`distribution` of your Pyramid project is created when you run ``python
setup.py sdist``. Due to the information contained in the default
-``MANIFEST.in``, an sdist of your Pyramid project will include ``.txt``
-files, ``.ini`` files, ``.rst`` files, graphics files, and template files, as
-well as ``.py`` files. See
-http://docs.python.org/distutils/sourcedist.html#the-manifest-in-template for
-more information about the syntax and usage of ``MANIFEST.in``.
-
-Without the presence of a ``MANIFEST.in`` file or without checking your
-source code into a version control repository, ``setup.py sdist`` places only
-*Python source files* (files ending with a ``.py`` extension) into tarballs
-generated by ``python setup.py sdist``. This means, for example, if your
-project was not checked into a setuptools-compatible source control system,
-and your project directory didn't contain a ``MANIFEST.in`` file that told
-the ``sdist`` machinery to include ``*.pt`` files, the
-``myproject/templates/mytemplate.pt`` file would not be included in the
-generated tarball.
-
-Projects generated by Pyramid scaffolds include a default ``MANIFEST.in``
-file. The ``MANIFEST.in`` file contains declarations which tell it to
-include files like ``*.pt``, ``*.css`` and ``*.js`` in the generated tarball.
-If you include files with extensions other than the files named in the
-project's ``MANIFEST.in`` and you don't make use of a setuptools-compatible
-version control system, you'll need to edit the ``MANIFEST.in`` file and
-include the statements necessary to include your new files. See
-http://docs.python.org/distutils/sourcedist.html#principle for more
+``MANIFEST.in``, an sdist of your Pyramid project will include ``.txt`` files,
+``.ini`` files, ``.rst`` files, graphics files, and template files, as well as
+``.py`` files. See
+https://docs.python.org/2/distutils/sourcedist.html#the-manifest-in-template
+for more information about the syntax and usage of ``MANIFEST.in``.
+
+Without the presence of a ``MANIFEST.in`` file or without checking your source
+code into a version control repository, ``setup.py sdist`` places only *Python
+source files* (files ending with a ``.py`` extension) into tarballs generated
+by ``python setup.py sdist``. This means, for example, if your project was not
+checked into a Setuptools-compatible source control system, and your project
+directory didn't contain a ``MANIFEST.in`` file that told the ``sdist``
+machinery to include ``*.pt`` files, the ``myproject/templates/mytemplate.pt``
+file would not be included in the generated tarball.
+
+Projects generated by Pyramid cookiecutters include a default ``MANIFEST.in`` file.
+The ``MANIFEST.in`` file contains declarations which tell it to include files
+like ``*.pt``, ``*.css`` and ``*.js`` in the generated tarball. If you include
+files with extensions other than the files named in the project's
+``MANIFEST.in`` and you don't make use of a Setuptools-compatible version
+control system, you'll need to edit the ``MANIFEST.in`` file and include the
+statements necessary to include your new files. See
+https://docs.python.org/2/distutils/sourcedist.html#principle for more
information about how to do this.
-You can also delete ``MANIFEST.in`` from your project and rely on a
-setuptools feature which simply causes all files checked into a version
-control system to be put into the generated tarball. To allow this to
-happen, check all the files that you'd like to be distributed along with your
-application's Python files into Subversion. After you do this, when you
-rerun ``setup.py sdist``, all files checked into the version control system
-will be included in the tarball. If you don't use Subversion, and instead
-use a different version control system, you may need to install a setuptools
-add-on such as ``setuptools-git`` or ``setuptools-hg`` for this behavior to
-work properly.
+You can also delete ``MANIFEST.in`` from your project and rely on a :term:`Setuptools`
+feature which simply causes all files checked into a version control system to
+be put into the generated tarball. To allow this to happen, check all the
+files that you'd like to be distributed along with your application's Python
+files into Subversion. After you do this, when you rerun ``setup.py sdist``,
+all files checked into the version control system will be included in the
+tarball. If you don't use Subversion, and instead use a different version
+control system, you may need to install a :term:`Setuptools` add-on such as
+``setuptools-git`` or ``setuptools-hg`` for this behavior to work properly.
.. index::
single: setup.py
@@ -680,66 +742,65 @@ work properly.
``setup.py``
~~~~~~~~~~~~
-The ``setup.py`` file is a :term:`setuptools` setup file. It is meant to be
-run directly from the command line to perform a variety of functions, such as
-testing, packaging, and distributing your application.
+The ``setup.py`` file is a :term:`Setuptools` setup file. It is meant to be
+used to define requirements for installing dependencies for your package and
+testing, as well as distributing your application.
.. note::
- ``setup.py`` is the de facto standard which Python developers use to
- distribute their reusable code. You can read more about ``setup.py`` files
- and their usage in the `Setuptools documentation
- <http://peak.telecommunity.com/DevCenter/setuptools>`_ and `The
- Hitchhiker's Guide to Packaging <http://guide.python-distribute.org/>`_.
+ ``setup.py`` is the de facto standard which Python developers use to
+ distribute their reusable code. You can read more about ``setup.py`` files
+ and their usage in the `Python Packaging User Guide
+ <https://packaging.python.org/>`_ and `Setuptools documentation
+ <https://setuptools.readthedocs.io/en/latest/>`_.
Our generated ``setup.py`` looks like this:
-.. literalinclude:: MyProject/setup.py
+.. literalinclude:: myproject/setup.py
:language: python
:linenos:
-The ``setup.py`` file calls the setuptools ``setup`` function, which does
-various things depending on the arguments passed to ``setup.py`` on the
-command line.
+The ``setup.py`` file calls the :term:`Setuptools` ``setup`` function, which does
+various things depending on the arguments passed to ``pip`` on the command
+line.
-Within the arguments to this function call, information about your
-application is kept. While it's beyond the scope of this documentation to
-explain everything about setuptools setup files, we'll provide a whirlwind
-tour of what exists in this file in this section.
+Within the arguments to this function call, information about your application
+is kept. While it's beyond the scope of this documentation to explain
+everything about :term:`Setuptools` setup files, we'll provide a whirlwind tour of what
+exists in this file in this section.
Your application's name can be any string; it is specified in the ``name``
field. The version number is specified in the ``version`` value. A short
-description is provided in the ``description`` field. The
-``long_description`` is conventionally the content of the README and CHANGES
-file appended together. The ``classifiers`` field is a list of `Trove
-<http://pypi.python.org/pypi?%3Aaction=list_classifiers>`_ classifiers
-describing your application. ``author`` and ``author_email`` are text fields
-which probably don't need any description. ``url`` is a field that should
-point at your application project's URL (if any).
-``packages=find_packages()`` causes all packages within the project to be
-found when packaging the application. ``include_package_data`` will include
-non-Python files when the application is packaged if those files are checked
-into version control. ``zip_safe`` indicates that this package is not safe
-to use as a zipped egg; instead it will always unpack as a directory, which
-is more convenient. ``install_requires`` and ``tests_require`` indicate that
-this package depends on the ``pyramid`` package. ``test_suite`` points at
-the package for our application, which means all tests found in the package
-will be run when ``setup.py test`` is invoked. We examined ``entry_points``
-in our discussion of the ``development.ini`` file; this file defines the
-``main`` entry point that represents our project's application.
-
-Usually you only need to think about the contents of the ``setup.py`` file
-when distributing your application to other people, when adding Python
-package dependencies, or when versioning your application for your own use.
-For fun, you can try this command now:
+description is provided in the ``description`` field. The ``long_description``
+is conventionally the content of the ``README`` and ``CHANGES`` files appended
+together. The ``classifiers`` field is a list of `Trove classifiers
+<https://pypi.org/pypi?%3Aaction=list_classifiers>`_ describing your
+application. ``author`` and ``author_email`` are text fields which probably
+don't need any description. ``url`` is a field that should point at your
+application project's URL (if any). ``packages=find_packages()`` causes all
+packages within the project to be found when packaging the application.
+``include_package_data`` will include non-Python files when the application is
+packaged if those files are checked into version control. ``zip_safe=False``
+indicates that this package is not safe to use as a zipped egg; instead it will
+always unpack as a directory, which is more convenient. ``install_requires``
+indicates that this package depends on the ``pyramid`` package.
+``extras_require`` is a Python dictionary that defines what is required to be
+installed for running tests. We examined ``entry_points`` in our discussion of
+the ``development.ini`` file; this file defines the ``main`` entry point that
+represents our project's application.
+
+Usually you only need to think about the contents of the ``setup.py`` file when
+distributing your application to other people, when adding Python package
+dependencies, or when versioning your application for your own use. For fun,
+you can try this command now:
.. code-block:: text
- $ python setup.py sdist
+ $VENV/bin/python setup.py sdist
-This will create a tarball of your application in a ``dist`` subdirectory
-named ``MyProject-0.1.tar.gz``. You can send this tarball to other people
-who want to install and use your application.
+This will create a tarball of your application in a ``dist`` subdirectory named
+``myproject-0.0.tar.gz``. You can send this tarball to other people who want
+to install and use your application.
.. index::
single: package
@@ -747,28 +808,29 @@ who want to install and use your application.
The ``myproject`` :term:`Package`
---------------------------------
-The ``myproject`` :term:`package` lives inside the ``MyProject``
+The ``myproject`` :term:`package` lives inside the ``myproject``
:term:`project`. It contains:
-#. An ``__init__.py`` file signifies that this is a Python :term:`package`.
- It also contains code that helps users run the application, including a
+#. An ``__init__.py`` file signifies that this is a Python :term:`package`. It
+ also contains code that helps users run the application, including a
``main`` function which is used as a entry point for commands such as
``pserve``, ``pshell``, ``pviews``, and others.
-#. A ``templates`` directory, which contains :term:`Chameleon` (or
- other types of) templates.
+#. A ``templates`` directory, which contains :term:`Jinja2` (or other types
+ of) templates.
+
+#. A ``tests.py`` module, which contains unit test code for the application.
+
+#. A ``routes.py`` module, which contains routing code for the application.
-#. A ``tests.py`` module, which contains unit test code for the
- application.
+#. A ``views`` package, which contains view code for the application.
-#. A ``views.py`` module, 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 scaffold:
-:app:`Pyramid` doesn't insist that you name things in any particular way.
-However, it's generally a good idea to follow Pyramid standards for naming,
-so that other Pyramid developers can get up to speed quickly on your code
-when you need help.
+These are purely conventions established by the cookiecutter. :app:`Pyramid`
+doesn't insist that you name things in any particular way. However, it's
+generally a good idea to follow Pyramid standards for naming, so that other
+Pyramid developers can get up to speed quickly on your code when you need help.
.. index::
single: __init__.py
@@ -783,7 +845,7 @@ advertises an entry point for use by our :term:`PasteDeploy` ``.ini`` file.
This is the file named ``__init__.py``. The presence of an ``__init__.py``
also informs Python that the directory which contains it is a *package*.
-.. literalinclude:: MyProject/myproject/__init__.py
+.. literalinclude:: myproject/myproject/__init__.py
:language: python
:linenos:
@@ -796,90 +858,120 @@ also informs Python that the directory which contains it is a *package*.
Within this function, application configuration is performed.
- Line 7 creates an instance of a :term:`Configurator`.
+ Line 7 opens a context manager with an instance of a :term:`Configurator`.
- Line 8 adds support for Chameleon templating bindings, allowing us to
- specify renderers with the ``.pt`` extension.
+ 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`.
+application developer; it is a bit of code which accepts a :term:`request` and
+which returns a :term:`response`.
+
+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.
-.. literalinclude:: MyProject/myproject/views.py
+We have two view modules in the ``views`` package.
+Let's look at ``default.py``.
+
+.. literalinclude:: myproject/myproject/views/default.py
:language: python
:linenos:
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 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 a :term:`asset
-specification` that specifies the ``mytemplate.pt`` 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
-optional. The template file pointed to is a :term:`Chameleon` ZPT
-template file (``templates/my_template.pt``).
+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 ``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.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.jinja2``; the leading package name and colon is
+optional. The template file pointed to is a :term:`Jinja2` template
+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`` class representing the browser's request to our server.
+:term:`request`. The *request* is an instance of the :term:`WebOb` ``Request``
+class representing the browser's request to our server.
This view is configured to invoke a :term:`renderer` on a template. The
dictionary the view returns (on line 6) provides the value the renderer
-substitutes into the template when generating HTML. The renderer then
-returns the HTML in a :term:`response`.
+substitutes into the template when generating HTML. The renderer then returns
+the HTML in a :term:`response`.
.. note:: Dictionaries provide values to :term:`template`\s.
-.. note:: When the application is run with the scaffold's :ref:`default
- development.ini <MyProject_ini>` configuration :ref:`logging is set up
- <MyProject_ini_logging>` to aid debugging. If an exception is raised,
+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,
uncaught tracebacks are displayed after the startup messages on :ref:`the
console running the server <running_the_project_application>`. Also
- ``print()`` statements may be inserted into the application for debugging
- to send output to this console.
+ ``print()`` statements may be inserted into the application for debugging to
+ send output to this console.
.. note:: ``development.ini`` has a setting that controls how templates are
reloaded, ``pyramid.reload_templates``.
- - When set to ``True`` (as in the scaffold ``development.ini``) changed
+ - When set to ``True`` (as in the cookiecutter ``development.ini``), changed
templates automatically reload without a server restart. This is
convenient while developing, but slows template rendering speed.
- - When set to ``False`` (the default value), changing templates requires
- a server restart to reload them. Production applications should use
+ - When set to ``False`` (the default value), changing templates requires a
+ server restart to reload them. Production applications should use
``pyramid.reload_templates = False``.
.. seealso::
- See also :ref:`views_which_use_a_renderer` for more information
- about how views, renderers, and templates relate and cooperate.
+ See also :ref:`views_which_use_a_renderer` for more information about how
+ views, renderers, and templates relate and cooperate.
.. seealso::
@@ -899,38 +991,65 @@ returns the HTML in a :term:`response`.
``static``
~~~~~~~~~~
-This directory contains static assets which support the ``mytemplate.pt``
+This directory contains static assets which support the ``layout.jinja2``
template. It includes CSS and images.
-``templates/mytemplate.pt``
+
+``templates/layout.jinja2``
~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The single :term:`Chameleon` template that exists in the project. Its
-contents are too long to show here, but it displays a default page when
-rendered. It is referenced by the call to ``@view_config`` as the
-``renderer`` of the ``my_view`` view callable in the ``views.py`` file. See
-:ref:`views_which_use_a_renderer` for more information about renderers.
+This is the base layout content. It contains a single marker for content block. Other templates inherit its content, providing layout for the web application. Its contents are too long to show here, but here is an excerpt:
+
+.. literalinclude:: myproject/myproject/templates/layout.jinja2
+ :language: jinja
+ :lines: 34-38
+ :lineno-match:
+
+
+``templates/mytemplate.jinja2``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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/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
+ :language: jinja
+ :linenos:
Templates are accessed and used by view configurations and sometimes by view
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
``tests.py``
~~~~~~~~~~~~
-The ``tests.py`` module includes unit tests for your application.
+The ``tests.py`` module includes tests for your application.
-.. literalinclude:: MyProject/myproject/tests.py
+.. literalinclude:: myproject/myproject/tests.py
:language: python
:linenos:
-This sample ``tests.py`` file has a single unit test defined within it. This
-test is executed when you run ``python setup.py test``. You may add more
-tests here as you build your application. You are not required to write
-tests to use :app:`Pyramid`, this file is simply provided as convenience and
+This sample ``tests.py`` file has one unit test and one functional test defined
+within it. These tests are executed when you run ``pytest -q``. You may add
+more tests here as you build your application. You are not required to write
+tests to use :app:`Pyramid`. This file is simply provided for convenience and
example.
See :ref:`testing_chapter` for more information about writing :app:`Pyramid`
@@ -942,107 +1061,126 @@ unit tests.
.. _modifying_package_structure:
Modifying Package Structure
-----------------------------
+---------------------------
It is best practice for your application's code layout to not stray too much
-from accepted Pyramid scaffold defaults. If you refrain from changing
-things very much, other Pyramid coders will be able to more quickly
-understand your application. However, the code layout choices made for you
-by a scaffold are in no way magical or required. Despite the choices
-made for you by any scaffold, you can decide to lay your code out any
-way you see fit.
+from accepted Pyramid cookiecutter defaults. If you refrain from changing things
+very much, other Pyramid coders will be able to more quickly understand your
+application. However, the code layout choices made for you by a cookiecutter are
+in no way magical or required. Despite the choices made for you by any
+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`` scaffold 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:
-
-- 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 to register views in conjunction with
-``config.scan()`` they will be picked up automatically when the application
-is restarted.
+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.
Using the Interactive Shell
---------------------------
It is possible to use the ``pshell`` command to load a Python interpreter
-prompt with a similar configuration as would be loaded if you were running
-your Pyramid application via ``pserve``. This can be a useful debugging tool.
-See :ref:`interactive_shell` for more details.
+prompt with a similar configuration as would be loaded if you were running your
+Pyramid application via ``pserve``. This can be a useful debugging tool. See
+:ref:`interactive_shell` for more details.
.. _what_is_this_pserve_thing:
What Is This ``pserve`` Thing
-----------------------------
-The code generated by an :app:`Pyramid` scaffold assumes that you will be
-using the ``pserve`` command to start your application while you do
-development. ``pserve`` is a command that reads a :term:`PasteDeploy`
-``.ini`` file (e.g. ``development.ini``) and configures a server to serve a
-Pyramid application based on the data in the file.
+The code generated by a :app:`Pyramid` cookiecutter assumes that you will be using
+the ``pserve`` command to start your application while you do development.
+``pserve`` is a command that reads a :term:`PasteDeploy` ``.ini`` file (e.g.,
+``development.ini``), and configures a server to serve a :app:`Pyramid`
+application based on the data in the file.
``pserve`` is by no means the only way to start up and serve a :app:`Pyramid`
application. As we saw in :ref:`firstapp_chapter`, ``pserve`` needn't be
invoked at all to run a :app:`Pyramid` application. The use of ``pserve`` to
-run a :app:`Pyramid` application is purely conventional based on the output
-of its scaffolding. But we strongly recommend using ``pserve`` while
-developing your application, because many other convenience introspection
-commands (such as ``pviews``, ``prequest``, ``proutes`` and others) are also
-implemented in terms of configuration availability of this ``.ini`` file
-format. It also configures Pyramid logging and provides the ``--reload``
-switch for convenient restarting of the server when code changes.
+run a :app:`Pyramid` application is purely conventional based on the output of
+its cookiecutter. But we strongly recommend using ``pserve`` while developing
+your application because many other convenience introspection commands (such as
+``pviews``, ``prequest``, ``proutes``, and others) are also implemented in
+terms of configuration availability of this ``.ini`` file format. It also
+configures Pyramid logging and provides the ``--reload`` switch for convenient
+restarting of the server when code changes.
.. _alternate_wsgi_server:
Using an Alternate WSGI Server
------------------------------
-Pyramid scaffolds generate projects which use the :term:`Waitress` WSGI
-server. Waitress is a server that is suited for development and light
-production usage. It's not the fastest nor the most featureful WSGI server.
-Instead, its main feature is that it works on all platforms that Pyramid
-needs to run on, making it a good choice as a default server from the
-perspective of Pyramid's developers.
+Pyramid cookiecutters generate projects which use the :term:`Waitress` WSGI server.
+Waitress is a server that is suited for development and light production
+usage. It's not the fastest nor the most featureful WSGI server. Instead, its
+main feature is that it works on all platforms that Pyramid needs to run on,
+making it a good choice as a default server from the perspective of Pyramid's
+developers.
Any WSGI server is capable of running a :app:`Pyramid` application. But we
-suggest you stick with the default server for development, and that you wait
-to investigate other server options until you're ready to deploy your
-application to production. Unless for some reason you need to develop on a
-non-local system, investigating alternate server options is usually a
-distraction until you're ready to deploy. But we recommend developing using
-the default configuration on a local system that you have complete control
-over; it will provide the best development experience.
+suggest you stick with the default server for development, and that you wait to
+investigate other server options until you're ready to deploy your application
+to production. Unless for some reason you need to develop on a non-local
+system, investigating alternate server options is usually a distraction until
+you're ready to deploy. But we recommend developing using the default
+configuration on a local system that you have complete control over; it will
+provide the best development experience.
One popular production alternative to the default Waitress server is
-:term:`mod_wsgi`. You can use mod_wsgi to serve your :app:`Pyramid`
-application using the Apache web server rather than any "pure-Python" server
-like Waitress. It is fast and featureful. See :ref:`modwsgi_tutorial` for
-details.
+:term:`mod_wsgi`. You can use ``mod_wsgi`` to serve your :app:`Pyramid` application
+using the Apache web server rather than any "pure-Python" server like Waitress.
+It is fast and featureful. See :ref:`modwsgi_tutorial` for details.
Another good production alternative is :term:`Green Unicorn` (aka
-``gunicorn``). It's faster than Waitress and slightly easier to configure
-than mod_wsgi, although it depends, in its default configuration, on having a
-buffering HTTP proxy in front of it. It does not, as of this writing, work
-on Windows.
+``gunicorn``). It's faster than Waitress and slightly easier to configure than
+``mod_wsgi``, although it depends, in its default configuration, on having a
+buffering HTTP proxy in front of it. It does not, as of this writing, work on
+Windows.
+
+Automatically Reloading Your Code
+---------------------------------
+
+During development, it can be really useful to automatically have the
+webserver restart when you make changes. ``pserve`` has a ``--reload`` switch
+to enable this. It uses the
+`hupper <https://docs.pylonsproject.org/projects/hupper/en/latest/>`_ package
+to enable this behavior. When your code crashes, ``hupper`` will wait for
+another change or the ``SIGHUP`` signal before restarting again.
+
+inotify support
+~~~~~~~~~~~~~~~
+
+By default ``hupper`` will poll the filesystem for changes to all Python
+code. This can be pretty inefficient in larger projects. To be nicer to your
+hard drive, you should install the
+`watchdog <https://pythonhosted.org/watchdog/>`_ package in development.
+``hupper`` will automatically use ``watchdog`` to more efficiently poll the
+filesystem.
+
+Monitoring Custom Files
+~~~~~~~~~~~~~~~~~~~~~~~
+
+By default, ``pserve --reload`` will monitor all imported Python code
+(everything in ``sys.modules``) as well as the config file passed to
+``pserve`` (e.g., ``development.ini``). You can instruct ``pserve`` to watch
+other files for changes as well by defining a ``[pserve]`` section in your
+configuration file. For example, let's say your application loads the
+``favicon.ico`` file at startup and stores it in memory to efficiently
+serve it many times. When you change it, you want ``pserve`` to restart:
+
+.. code-block:: ini
+
+ [pserve]
+ watch_files =
+ myproject/static/favicon.ico
+
+Paths may be absolute or relative to the configuration file. They may also
+be an :term:`asset specification`. These paths are passed to ``hupper``, which
+has some basic support for globbing. Acceptable glob patterns depend on the
+version of Python being used.