summaryrefslogtreecommitdiff
path: root/docs/narr
diff options
context:
space:
mode:
authorcewing <cris@crisewing.com>2017-05-22 12:09:41 -0700
committercewing <cris@crisewing.com>2017-05-22 12:09:41 -0700
commitb033b966420b673bf0222c3576d3238773433d0f (patch)
treeba5d63e118ba5ebbad901b5c1558adff04224686 /docs/narr
parent7c680930d09d20bfa05249e01553e6488e61f1ca (diff)
parent8c4d422965b633f31967ceed1e6cc25cc616d0bf (diff)
downloadpyramid-b033b966420b673bf0222c3576d3238773433d0f.tar.gz
pyramid-b033b966420b673bf0222c3576d3238773433d0f.tar.bz2
pyramid-b033b966420b673bf0222c3576d3238773433d0f.zip
Merge branch 'master' into issue.2614
Diffstat (limited to 'docs/narr')
-rw-r--r--docs/narr/MyProject/CHANGES.txt4
-rw-r--r--docs/narr/MyProject/README.txt12
-rw-r--r--docs/narr/MyProject/setup.py49
-rw-r--r--docs/narr/assets.rst2
-rw-r--r--docs/narr/commandline.rst2
-rw-r--r--docs/narr/configuration.rst2
-rw-r--r--docs/narr/cookiecutters.rst22
-rw-r--r--docs/narr/extconfig.rst1
-rw-r--r--docs/narr/extending.rst2
-rw-r--r--docs/narr/hooks.rst28
-rw-r--r--docs/narr/install.rst60
-rw-r--r--docs/narr/introduction.rst43
-rw-r--r--docs/narr/logging.rst112
-rw-r--r--docs/narr/myproject/.coveragerc3
-rw-r--r--docs/narr/myproject/CHANGES.txt4
-rw-r--r--docs/narr/myproject/MANIFEST.in (renamed from docs/narr/MyProject/MANIFEST.in)2
-rw-r--r--docs/narr/myproject/README.txt29
-rw-r--r--docs/narr/myproject/development.ini (renamed from docs/narr/MyProject/development.ini)9
-rw-r--r--docs/narr/myproject/myproject/__init__.py (renamed from docs/narr/MyProject/myproject/__init__.py)2
-rw-r--r--docs/narr/myproject/myproject/static/pyramid-16x16.png (renamed from docs/narr/MyProject/myproject/static/pyramid-16x16.png)bin1319 -> 1319 bytes
-rw-r--r--docs/narr/myproject/myproject/static/pyramid.png (renamed from docs/narr/MyProject/myproject/static/pyramid.png)bin12901 -> 12901 bytes
-rw-r--r--docs/narr/myproject/myproject/static/theme.css (renamed from docs/narr/MyProject/myproject/static/theme.css)8
-rw-r--r--docs/narr/myproject/myproject/templates/layout.jinja2 (renamed from docs/narr/MyProject/myproject/templates/mytemplate.pt)21
-rw-r--r--docs/narr/myproject/myproject/templates/mytemplate.jinja28
-rw-r--r--docs/narr/myproject/myproject/tests.py (renamed from docs/narr/MyProject/myproject/tests.py)0
-rw-r--r--docs/narr/myproject/myproject/views.py (renamed from docs/narr/MyProject/myproject/views.py)2
-rw-r--r--docs/narr/myproject/production.ini (renamed from docs/narr/MyProject/production.ini)9
-rw-r--r--docs/narr/myproject/pytest.ini3
-rw-r--r--docs/narr/myproject/setup.py51
-rw-r--r--docs/narr/paste.rst40
-rw-r--r--docs/narr/project.pngbin133242 -> 98989 bytes
-rw-r--r--docs/narr/project.rst406
-rw-r--r--docs/narr/scaffolding.rst4
-rw-r--r--docs/narr/security.rst216
-rw-r--r--docs/narr/sessions.rst183
-rw-r--r--docs/narr/startup.rst32
-rw-r--r--docs/narr/templates.rst4
-rw-r--r--docs/narr/testing.rst12
-rw-r--r--docs/narr/upgrading.rst2
-rw-r--r--docs/narr/vhosting.rst14
-rw-r--r--docs/narr/viewconfig.rst8
-rw-r--r--docs/narr/views.rst7
-rw-r--r--docs/narr/webob.rst4
43 files changed, 777 insertions, 645 deletions
diff --git a/docs/narr/MyProject/CHANGES.txt b/docs/narr/MyProject/CHANGES.txt
deleted file mode 100644
index 35a34f332..000000000
--- a/docs/narr/MyProject/CHANGES.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-0.0
----
-
-- Initial version
diff --git a/docs/narr/MyProject/README.txt b/docs/narr/MyProject/README.txt
deleted file mode 100644
index 70759eba1..000000000
--- a/docs/narr/MyProject/README.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-MyProject README
-==================
-
-Getting Started
----------------
-
-- cd <directory containing this file>
-
-- $VENV/bin/pip install -e .
-
-- $VENV/bin/pserve development.ini
-
diff --git a/docs/narr/MyProject/setup.py b/docs/narr/MyProject/setup.py
deleted file mode 100644
index a911eff6d..000000000
--- a/docs/narr/MyProject/setup.py
+++ /dev/null
@@ -1,49 +0,0 @@
-import os
-
-from setuptools import setup, find_packages
-
-here = os.path.abspath(os.path.dirname(__file__))
-with open(os.path.join(here, 'README.txt')) as f:
- README = f.read()
-with open(os.path.join(here, 'CHANGES.txt')) as f:
- CHANGES = f.read()
-
-requires = [
- 'pyramid',
- 'pyramid_chameleon',
- 'pyramid_debugtoolbar',
- 'waitress',
- ]
-
-tests_require = [
- 'WebTest >= 1.3.1', # py3 compat
- 'pytest', # includes virtualenv
- 'pytest-cov',
- ]
-
-setup(name='MyProject',
- version='0.0',
- description='MyProject',
- long_description=README + '\n\n' + CHANGES,
- classifiers=[
- "Programming Language :: Python",
- "Framework :: Pyramid",
- "Topic :: Internet :: WWW/HTTP",
- "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
- ],
- author='',
- author_email='',
- url='',
- keywords='web pyramid pylons',
- packages=find_packages(),
- include_package_data=True,
- zip_safe=False,
- extras_require={
- 'testing': tests_require,
- },
- install_requires=requires,
- entry_points="""\
- [paste.app_factory]
- main = myproject:main
- """,
- )
diff --git a/docs/narr/assets.rst b/docs/narr/assets.rst
index 58f547fc9..f5a2f9684 100644
--- a/docs/narr/assets.rst
+++ b/docs/narr/assets.rst
@@ -28,7 +28,7 @@ asset:
The use of assets is quite common in most web development projects. For
example, when you create a :app:`Pyramid` application using one of the
-available scaffolds, as described in :ref:`creating_a_project`, the directory
+available :term:`cookiecutter`\ s, as described in :ref:`creating_a_project`, the directory
representing the application contains a Python :term:`package`. Within that
Python package, there are directories full of files which are static assets.
For example, there's a ``static`` directory which contains ``.css``, ``.js``,
diff --git a/docs/narr/commandline.rst b/docs/narr/commandline.rst
index 242bc7ec7..98663cca6 100644
--- a/docs/narr/commandline.rst
+++ b/docs/narr/commandline.rst
@@ -839,7 +839,7 @@ In general, you can make your script into a console script by doing the
following:
- Use an existing distribution (such as one you've already created via
- ``pcreate``) or create a new distribution that possesses at least one package
+ ``cookiecutter``) or create a new distribution that possesses at least one package
or module. It should, within any module within the distribution, house a
callable (usually a function) that takes no arguments and which runs any of
the code you wish to run.
diff --git a/docs/narr/configuration.rst b/docs/narr/configuration.rst
index cde166b21..ee54e3acd 100644
--- a/docs/narr/configuration.rst
+++ b/docs/narr/configuration.rst
@@ -54,7 +54,7 @@ configured imperatively:
server.serve_forever()
We won't talk much about what this application does yet. Just note that the
-"configuration' statements take place underneath the ``if __name__ ==
+configuration statements take place underneath the ``if __name__ ==
'__main__':`` stanza in the form of method calls on a :term:`Configurator`
object (e.g., ``config.add_view(...)``). These statements take place one after
the other, and are executed in order, so the full power of Python, including
diff --git a/docs/narr/cookiecutters.rst b/docs/narr/cookiecutters.rst
new file mode 100644
index 000000000..abedb25b9
--- /dev/null
+++ b/docs/narr/cookiecutters.rst
@@ -0,0 +1,22 @@
+.. _cookiecutters:
+
+Pyramid cookiecutters
+=====================
+
+.. versionadded:: 1.8
+
+A :term:`cookiecutter` is a command-line utility that creates projects from :ref:`cookiecutters <cookiecutter:readme>` (project templates), e.g., creating a Python package project from a Python package project template.
+
+Pyramid cookiecutters have replaced the now deprecated Pyramid scaffolds, and should be used going forward. Pyramid cookiecutters released under the Pylons Project include:
+
+* `pyramid-cookiecutter-alchemy <https://github.com/Pylons/pyramid-cookiecutter-alchemy>`_
+* `pyramid-cookiecutter-starter <https://github.com/Pylons/pyramid-cookiecutter-starter>`_
+* `pyramid-cookiecutter-zodb <https://github.com/Pylons/pyramid-cookiecutter-zodb>`_
+
+.. seealso::
+
+ See also `Cookiecutter Installation <https://cookiecutter.readthedocs.io/en/latest/installation.html>`_ and `Cookiecutter Features <https://cookiecutter.readthedocs.io/en/latest/readme.html#features>`_. Development of cookiecutters is documented under `Learn the Basics of Cookiecutter by Creating a Cookiecutter <https://cookiecutter.readthedocs.io/en/latest/first_steps.html>`_.
+
+.. seealso::
+
+ See also :term:`scaffold`.
diff --git a/docs/narr/extconfig.rst b/docs/narr/extconfig.rst
index babfa0a98..4009ec1dc 100644
--- a/docs/narr/extconfig.rst
+++ b/docs/narr/extconfig.rst
@@ -260,6 +260,7 @@ Pre-defined Phases
- :meth:`pyramid.config.Configurator.add_subscriber_predicate`
- :meth:`pyramid.config.Configurator.add_view_predicate`
- :meth:`pyramid.config.Configurator.add_view_deriver`
+- :meth:`pyramid.config.Configurator.override_asset`
- :meth:`pyramid.config.Configurator.set_authorization_policy`
- :meth:`pyramid.config.Configurator.set_default_csrf_options`
- :meth:`pyramid.config.Configurator.set_default_permission`
diff --git a/docs/narr/extending.rst b/docs/narr/extending.rst
index 9dc042024..bee30ec1a 100644
--- a/docs/narr/extending.rst
+++ b/docs/narr/extending.rst
@@ -190,7 +190,7 @@ The general pattern for extending an existing application looks something like
this:
- Create a new Python package. The easiest way to do this is to create a new
- :app:`Pyramid` application using the scaffold mechanism. See
+ :app:`Pyramid` application using a :term:`cookiecutter`. See
:ref:`creating_a_project` for more information.
- In the new package, create Python files containing views and other overridden
diff --git a/docs/narr/hooks.rst b/docs/narr/hooks.rst
index b22b31bf9..81c8e81d7 100644
--- a/docs/narr/hooks.rst
+++ b/docs/narr/hooks.rst
@@ -116,14 +116,6 @@ callable:
.. note::
- Both :meth:`pyramid.config.Configurator.add_notfound_view` and
- :class:`pyramid.view.notfound_view_config` are new as of Pyramid 1.3.
- Older Pyramid documentation instructed users to use ``add_view`` instead,
- with a ``context`` of ``HTTPNotFound``. This still works; the convenience
- method and decorator are just wrappers around this functionality.
-
-.. warning::
-
When a Not Found View callable accepts an argument list as described in
:ref:`request_and_context_view_definitions`, the ``context`` passed as the
first argument to the view callable will be the
@@ -131,6 +123,13 @@ callable:
available, the resource context will still be available as
``request.context``.
+.. warning::
+
+ The :term:`Not Found View` callables are only invoked when a
+ :exc:`~pyramid.httpexceptions.HTTPNotFound` exception is raised. If the
+ exception is returned from a view then it will be treated as a regular
+ response object and it will not trigger the custom view.
+
.. index::
single: forbidden view
@@ -161,7 +160,7 @@ forbidden view:
def main(globals, **settings):
config = Configurator()
- config.add_forbidden_view(forbidden_view)
+ config.add_forbidden_view(forbidden)
If instead you prefer to use decorators and a :term:`scan`, you can use the
:class:`pyramid.view.forbidden_view_config` decorator to mark a view callable
@@ -210,6 +209,13 @@ Here's some sample code that implements a minimal forbidden view:
whether the ``pyramid.debug_authorization`` environment setting is true or
false.
+.. warning::
+
+ The :term:`forbidden view` callables are only invoked when a
+ :exc:`~pyramid.httpexceptions.HTTPForbidden` exception is raised. If the
+ exception is returned from a view then it will be treated as a regular
+ response object and it will not trigger the custom view.
+
.. index::
single: request factory
@@ -744,7 +750,9 @@ The API that must be implemented by a class that provides
""" Accept the resource and request and set self.physical_path and
self.virtual_path """
self.virtual_path = some_function_of(resource, request)
+ self.virtual_path_tuple = some_function_of(resource, request)
self.physical_path = some_other_function_of(resource, request)
+ self.physical_path_tuple = some_function_of(resource, request)
The default context URL generator is available for perusal as the class
:class:`pyramid.traversal.ResourceURL` in the `traversal module
@@ -1561,7 +1569,7 @@ event type.
def __call__(self, event):
return event.request.path.startswith(self.val)
-Once you've created a subscriber predicate, it may registered via
+Once you've created a subscriber predicate, it may be registered via
:meth:`pyramid.config.Configurator.add_subscriber_predicate`. For example:
.. code-block:: python
diff --git a/docs/narr/install.rst b/docs/narr/install.rst
index 570cb2285..2a25ad84d 100644
--- a/docs/narr/install.rst
+++ b/docs/narr/install.rst
@@ -22,7 +22,7 @@ the following sections.
.. sidebar:: Python Versions
As of this writing, :app:`Pyramid` is tested against Python 2.7,
- Python 3.4, Python 3.5, PyPy.
+ Python 3.4, Python 3.5, Python 3.6, and PyPy.
:app:`Pyramid` is known to run on all popular UNIX-like systems such as Linux,
Mac OS X, and FreeBSD, as well as on Windows platforms. It is also known to
@@ -91,29 +91,22 @@ If your Windows system doesn't have a Python interpreter, you'll need to
install it by downloading a Python 3.x-series interpreter executable from
`python.org's download section <https://www.python.org/downloads/>`_ (the files
labeled "Windows Installer"). Once you've downloaded it, double click on the
-executable, and select appropriate options during the installation process. To
+executable and select appropriate options during the installation process. To
standardize this documentation, we used the GUI installer and selected the
following options:
- Screen 1: Install Python 3.x.x (32- or 64-bit)
- - Check "Install launcher for all users (recommended)"
- - Check "Add Python 3.x to PATH"
- - Click "Customize installation"
-- Screen 2: Optional Features
- - Check all options
- - Click "Next"
-- Screen 3: Advanced Options
- - Check all options
- - Customize install location: "C:\\Python3x", where "x" is the minor
- version of Python
- - Click "Next"
-
-You might also need to download and install the Python for Windows extensions.
+ - Check "Install launcher for all users (recommended)".
+ - Check "Add Python 3.x to PATH".
+ - Click "Install Now".
+- Screen 2: User Account Control
+ - Click "Yes".
.. seealso:: See the official Python documentation :ref:`Using Python on
Windows <python:using-on-windows>` for full details.
-.. seealso:: Download and install the `Python for Windows extensions
+.. seealso:: You might also need to download and install the `Python for
+ Windows extensions
<https://sourceforge.net/projects/pywin32/files/pywin32/>`_. Carefully read
the README.txt file at the end of the list of builds, and follow its
directions. Make sure you get the proper 32- or 64-bit build and Python
@@ -123,15 +116,26 @@ You might also need to download and install the Python for Windows extensions.
<https://docs.python.org/3/using/windows.html#launcher>`_ provides a command
``py`` that allows users to run any installed version of Python.
-.. warning::
+.. warning:: After you install Python on Windows, you might need to add the
+ directory where Python and other programs—such as pip, setuptools, and
+ cookiecutter—are installed to your environment's ``Path``. This will make it
+ possible to invoke them from a command prompt.
- After you install Python on Windows, you might need to add the
- ``c:\Python3x`` directory to your environment's ``Path``, where ``x`` is the
- minor version of installed Python, in order to make it possible to invoke
- Python from a command prompt by typing ``python``. To do so, right click
- ``My Computer``, select ``Properties`` --> ``Advanced Tab`` -->
- ``Environment Variables``, and add that directory to the end of the ``Path``
- environment variable.
+ To do so, search for "Environment Variables" on your computer (on Windows
+ 10, it is under ``System Properties`` --> ``Advanced``) and add that
+ directory to the ``Path`` environment variable, using the GUI to edit path
+ segments.
+
+ Example segments should look like
+ ``C:\Users\<username>\AppData\Local\Programs\Python3x-32``, where you have
+ your username instead of ``<username>``, and your version of Python and
+ whether it is 32- or 64-bit. Additionally ensure you have the path segment
+ ending with ``\Scripts``, i.e.,
+ ``C:\Users\<username>\AppData\Local\Programs\Python3x-32\Scripts``, and for
+ user-installed Python programs, ``%APPDATA%\Python\Python3x\Scripts``.
+
+ You may need to restart your command prompt session to load the environment
+ variables.
.. seealso:: See `Configuring Python (on Windows)
<https://docs.python.org/3/using/windows.html#configuring-python>`_ for
@@ -231,9 +235,9 @@ After installing Python as described previously in
.. code-block:: doscon
+ c:\> cd \
c:\> set VENV=c:\env
- # replace "x" with your minor version of Python 3
- c:\> c:\Python3x\python -m venv %VENV%
+ c:\> python -m venv %VENV%
c:\> cd %VENV%
You can either follow the use of the environment variable ``%VENV%``, or
@@ -260,5 +264,5 @@ What Gets Installed
When you install :app:`Pyramid`, various libraries such as WebOb, PasteDeploy,
and others are installed.
-Additionally, as chronicled in :ref:`project_narr`, scaffolds will be
-registered, which make it easy to start a new :app:`Pyramid` project.
+Additionally, as chronicled in :ref:`project_narr`, :term:`cookiecutter`\ s will be
+used, which make it easy to start a new :app:`Pyramid` project.
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index adf955a97..5eda0fcf4 100644
--- a/docs/narr/introduction.rst
+++ b/docs/narr/introduction.rst
@@ -213,6 +213,9 @@ packages, SQL queries, logging statements and more.
When your application has an error, an interactive debugger allows you to poke
around from your browser to find out what happened.
+To use the Pyramid debug toolbar, build your project with a Pyramid
+:term:`cookiecutter`.
+
Example: :ref:`debug_toolbar`.
Debug with power
@@ -376,7 +379,7 @@ By configuring your view to use a renderer, you tell Pyramid to use the
behalf.
The string passed as ``renderer=`` above is an :term:`asset specification`.
-Asset specifications are omnipresent in Pyramid. They allow for more reliable
+Asset specifications are widely used in Pyramid. They allow for more reliable
customization. See :ref:`intro_asset_specs` for more information.
Example: :ref:`renderers_chapter`.
@@ -412,27 +415,19 @@ Example: :ref:`events_chapter` and :ref:`event_types`.
Build international applications
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Pyramid ships with features that allow you to write applications for
-international audiences. You can mark text in your source files and templates
-and build catalogs of messages to be translated. You can translate these
-catalogs into other languages. Users may then indicate their preference, and
-see your application in their language.
-
-Many systems which offer internationalization suffer from a common problem. A
-message in your code may have the same text as one in some other package.
-Messages can conflict with each-other, leading to translation errors. Pyramid
-solves this problem by using translation *domains*. Each application can have
-its own translation domain. Messages in one domain cannot conflict with
-messages in another. Problem solved.
+Pyramid ships with internationalization-related features in its core:
+localization, pluralization, and creating message catalogs from source files
+and templates. Pyramid allows for a plurality of message catalogs via the use
+of translation domains. You can create a system that has its own translations
+without conflict with other translations in other domains.
Example: :ref:`i18n_chapter`.
Build efficient applications
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Views in dynamic web applications can be expensive or slow to build. Pyramid
-allows you to save the results of such a view by *caching* the rendered
-response. Indicate in configuration that you want a view to be cached::
+Pyramid provides an easy way to *cache* the results of slow or expensive views.
+You can indicate in view configuration that you want a view to be cached::
@view_config(http_cache=3600) # 60 minutes
def myview(request): ...
@@ -446,7 +441,7 @@ documentation for more information.
Build fast applications
~~~~~~~~~~~~~~~~~~~~~~~
-The Pyramid core is fast. It has been engineered from the ground up for speed.
+The Pyramid core is fast. It has been engineered from the ground up for speed.
It only does as much work as absolutely necessary when you ask it to get a job
done. If you need speed from your application, Pyramid is the right choice for
you.
@@ -456,15 +451,11 @@ Example: http://blog.curiasolutions.com/pages/the-great-web-framework-shootout.h
Store session data
~~~~~~~~~~~~~~~~~~
-HTTP is a *stateless* protocol. No request can have knowledge of any other
-request. But it is often desireable to associate data with a particular user.
-Think of a shopping cart that remembers the items you have added to it even as
-you move through the shopping site finding other items to add.
-
-Pyramid allows you to use *sessions* to solve this problem. Many other
-frameworks also support sessions. But Pyramid allows you to plug in your own
-custom sessioning system. So long as your system conforms to a documented
-interface, you can drop it in in place of the provided system.
+Pyramid has built-in support for HTTP sessions, so you can associate data with
+specific users between requests. Lots of other frameworks also support
+sessions. But Pyramid allows you to plug in your own custom sessioning system.
+So long as your system conforms to a documented interface, you can drop it in
+in place of the provided system.
Currently there is a binding package for the third-party Redis sessioning
system that does exactly this. But if you have a specialized need (perhaps you
diff --git a/docs/narr/logging.rst b/docs/narr/logging.rst
index c7b4b9d6f..9cc5b4ed8 100644
--- a/docs/narr/logging.rst
+++ b/docs/narr/logging.rst
@@ -9,14 +9,14 @@ to send log messages to loggers that you've configured.
.. warning::
- This chapter assumes you've used a :term:`scaffold` to create a project
+ This chapter assumes you've used a :term:`cookiecutter` to create a project
which contains ``development.ini`` and ``production.ini`` files which help
- configure logging. All of the scaffolds which ship with :app:`Pyramid` do
- this. If you're not using a scaffold, or if you've used a third-party
- scaffold which does not create these files, the configuration information in
+ configure logging. All of the Pyramid cookiecutters provided by the Pylons Project do
+ this. If you're not using a cookiecutter, or if you've used a third-party
+ cookiecutter which does not create these files, the configuration information in
this chapter may not be applicable.
-.. index:
+.. index::
pair: settings; logging
pair: .ini; logging
pair: logging; configuration
@@ -26,11 +26,11 @@ to send log messages to loggers that you've configured.
Logging Configuration
---------------------
-A :app:`Pyramid` project created from a :term:`scaffold` is configured to allow
+A :app:`Pyramid` project created from a :term:`cookiecutter` is configured to allow
you to send messages to :mod:`Python standard library logging package
<logging>` loggers from within your application. In particular, the
:term:`PasteDeploy` ``development.ini`` and ``production.ini`` files created
-when you use a scaffold include a basic configuration for the Python
+when you use a cookiecutter include a basic configuration for the Python
:mod:`logging` package.
PasteDeploy ``.ini`` files use the Python standard library :mod:`ConfigParser
@@ -43,94 +43,20 @@ from when you run ``pserve``.
The ``pserve`` command calls the :func:`pyramid.paster.setup_logging` function,
a thin wrapper around the :func:`logging.config.fileConfig` using the specified
``.ini`` file, if it contains a ``[loggers]`` section (all of the
-scaffold-generated ``.ini`` files do). ``setup_logging`` reads the logging
+cookiecutter-generated ``.ini`` files do). ``setup_logging`` reads the logging
configuration from the ini file upon which ``pserve`` was invoked.
Default logging configuration is provided in both the default
-``development.ini`` and the ``production.ini`` file. The logging configuration
+``development.ini`` and the ``production.ini`` files. If you use ``pyramid-cookiecutter-starter`` to generate a Pyramid project with the name of the package as ``hello_world``, then the logging configuration
in the ``development.ini`` file is as follows:
-.. code-block:: ini
- :linenos:
-
- # Begin logging configuration
-
- [loggers]
- keys = root, {{package_logger}}
-
- [handlers]
- keys = console
-
- [formatters]
- keys = generic
-
- [logger_root]
- level = INFO
- handlers = console
-
- [logger_{{package_logger}}]
- level = DEBUG
- handlers =
- qualname = {{package}}
-
- [handler_console]
- class = StreamHandler
- args = (sys.stderr,)
- level = NOTSET
- formatter = generic
-
- [formatter_generic]
- format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
-
- # End logging configuration
+.. literalinclude:: myproject/development.ini
+ :language: ini
+ :lineno-match:
+ :lines: 29-
The ``production.ini`` file uses the ``WARN`` level in its logger
-configuration, but it is otherwise identical.
-
-The name ``{{package_logger}}`` above will be replaced with the name of your
-project's :term:`package`, which is derived from the name you provide to your
-project. For instance, if you do:
-
-.. code-block:: text
- :linenos:
-
- pcreate -s starter MyApp
-
-The logging configuration will literally be:
-
-.. code-block:: ini
- :linenos:
-
- # Begin logging configuration
-
- [loggers]
- keys = root, myapp
-
- [handlers]
- keys = console
-
- [formatters]
- keys = generic
-
- [logger_root]
- level = INFO
- handlers = console
-
- [logger_myapp]
- level = DEBUG
- handlers =
- qualname = myapp
-
- [handler_console]
- class = StreamHandler
- args = (sys.stderr,)
- level = NOTSET
- formatter = generic
-
- [formatter_generic]
- format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
-
- # End logging configuration
+configuration instead of ``DEBUG``, but it is otherwise identical.
In this logging configuration:
@@ -149,7 +75,7 @@ that ask for a logger (via ``logging.getLogger``) that has a name which begins
with anything except your project's package name (e.g., ``myapp``). The logger
with the same name as your package name is reserved for your own usage in your
:app:`Pyramid` application. Its existence means that you can log to a known
-logging location from any :app:`Pyramid` application generated via a scaffold.
+logging location from any :app:`Pyramid` application generated via a cookiecutter.
:app:`Pyramid` and many other libraries (such as Beaker, SQLAlchemy, Paste) log
a number of messages to the root logger for debugging purposes. Switching the
@@ -162,9 +88,9 @@ root logger level to ``DEBUG`` reveals them:
level = DEBUG
handlers = console
-Some scaffolds configure additional loggers for additional subsystems they use
+Some cookiecutters configure additional loggers for additional subsystems they use
(such as SQLALchemy). Take a look at the ``production.ini`` and
-``development.ini`` files rendered when you create a project from a scaffold.
+``development.ini`` files rendered when you create a project from a cookiecutter.
Sending Logging Messages
------------------------
@@ -327,14 +253,14 @@ translogger and your application in it. For instance, change from this:
.. code-block:: ini
[app:main]
- use = egg:MyProject
+ use = egg:myproject
To this:
.. code-block:: ini
[app:mypyramidapp]
- use = egg:MyProject
+ use = egg:myproject
[filter:translogger]
use = egg:Paste#translogger
diff --git a/docs/narr/myproject/.coveragerc b/docs/narr/myproject/.coveragerc
new file mode 100644
index 000000000..f0c31d6d7
--- /dev/null
+++ b/docs/narr/myproject/.coveragerc
@@ -0,0 +1,3 @@
+[run]
+source = myproject
+omit = myproject/test*
diff --git a/docs/narr/myproject/CHANGES.txt b/docs/narr/myproject/CHANGES.txt
new file mode 100644
index 000000000..14b902fd1
--- /dev/null
+++ b/docs/narr/myproject/CHANGES.txt
@@ -0,0 +1,4 @@
+0.0
+---
+
+- Initial version.
diff --git a/docs/narr/MyProject/MANIFEST.in b/docs/narr/myproject/MANIFEST.in
index fa1692163..1c24b8c0c 100644
--- a/docs/narr/MyProject/MANIFEST.in
+++ b/docs/narr/myproject/MANIFEST.in
@@ -1,2 +1,2 @@
include *.txt *.ini *.cfg *.rst
-recursive-include myproject *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml
+recursive-include myproject *.ico *.png *.css *.gif *.jpg *.pt *.txt *.mak *.mako *.js *.html *.xml *.jinja2
diff --git a/docs/narr/myproject/README.txt b/docs/narr/myproject/README.txt
new file mode 100644
index 000000000..2ffc0acba
--- /dev/null
+++ b/docs/narr/myproject/README.txt
@@ -0,0 +1,29 @@
+MyProject
+=========
+
+Getting Started
+---------------
+
+- Change directory into your newly created project.
+
+ cd MyProject
+
+- Create a Python virtual environment.
+
+ python3 -m venv env
+
+- Upgrade packaging tools.
+
+ env/bin/pip install --upgrade pip setuptools
+
+- Install the project in editable mode with its testing requirements.
+
+ env/bin/pip install -e ".[testing]"
+
+- Run your project's tests.
+
+ env/bin/pytest
+
+- Run your project.
+
+ env/bin/pserve development.ini
diff --git a/docs/narr/MyProject/development.ini b/docs/narr/myproject/development.ini
index 94fece8ce..20a8a4868 100644
--- a/docs/narr/MyProject/development.ini
+++ b/docs/narr/myproject/development.ini
@@ -1,10 +1,10 @@
###
# app configuration
-# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
###
[app:main]
-use = egg:MyProject
+use = egg:myproject
pyramid.reload_templates = true
pyramid.debug_authorization = false
@@ -24,12 +24,11 @@ pyramid.includes =
[server:main]
use = egg:waitress#main
-host = 127.0.0.1
-port = 6543
+listen = localhost:6543
###
# logging configuration
-# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
###
[loggers]
diff --git a/docs/narr/MyProject/myproject/__init__.py b/docs/narr/myproject/myproject/__init__.py
index ad5ecbc6f..49dde36d4 100644
--- a/docs/narr/MyProject/myproject/__init__.py
+++ b/docs/narr/myproject/myproject/__init__.py
@@ -5,7 +5,7 @@ def main(global_config, **settings):
""" This function returns a Pyramid WSGI application.
"""
config = Configurator(settings=settings)
- config.include('pyramid_chameleon')
+ config.include('pyramid_jinja2')
config.add_static_view('static', 'static', cache_max_age=3600)
config.add_route('home', '/')
config.scan()
diff --git a/docs/narr/MyProject/myproject/static/pyramid-16x16.png b/docs/narr/myproject/myproject/static/pyramid-16x16.png
index 979203112..979203112 100644
--- a/docs/narr/MyProject/myproject/static/pyramid-16x16.png
+++ b/docs/narr/myproject/myproject/static/pyramid-16x16.png
Binary files differ
diff --git a/docs/narr/MyProject/myproject/static/pyramid.png b/docs/narr/myproject/myproject/static/pyramid.png
index 4ab837be9..4ab837be9 100644
--- a/docs/narr/MyProject/myproject/static/pyramid.png
+++ b/docs/narr/myproject/myproject/static/pyramid.png
Binary files differ
diff --git a/docs/narr/MyProject/myproject/static/theme.css b/docs/narr/myproject/myproject/static/theme.css
index be50ad420..0f4b1a4d4 100644
--- a/docs/narr/MyProject/myproject/static/theme.css
+++ b/docs/narr/myproject/myproject/static/theme.css
@@ -72,10 +72,12 @@ p {
color: #f2b7bd;
font-weight: 400;
}
-.starter-template .links ul li a {
- color: #ffffff;
+.starter-template .links ul li a, a {
+ color: #f2b7bd;
+ text-decoration: underline;
}
-.starter-template .links ul li a:hover {
+.starter-template .links ul li a:hover, a:hover {
+ color: #ffffff;
text-decoration: underline;
}
.starter-template .links ul li .icon-muted {
diff --git a/docs/narr/MyProject/myproject/templates/mytemplate.pt b/docs/narr/myproject/myproject/templates/layout.jinja2
index 543663fe8..bfac9e64e 100644
--- a/docs/narr/MyProject/myproject/templates/mytemplate.pt
+++ b/docs/narr/myproject/myproject/templates/layout.jinja2
@@ -1,20 +1,20 @@
<!DOCTYPE html>
-<html lang="${request.locale_name}">
+<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('myproject:static/pyramid-16x16.png')}">
+ <link rel="shortcut icon" href="{{request.static_url('myproject:static/pyramid-16x16.png')}}">
- <title>Starter Scaffold for The Pyramid Web Framework</title>
+ <title>Cookiecutter Starter project for the Pyramid Web Framework</title>
<!-- Bootstrap core CSS -->
<link href="//oss.maxcdn.com/libs/twitter-bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
<!-- Custom styles for this scaffold -->
- <link href="${request.static_url('myproject:static/theme.css')}" rel="stylesheet">
+ <link href="{{request.static_url('myproject:static/theme.css')}}" rel="stylesheet">
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
@@ -29,22 +29,19 @@
<div class="container">
<div class="row">
<div class="col-md-2">
- <img class="logo img-responsive" src="${request.static_url('myproject:static/pyramid.png')}" alt="pyramid web framework">
+ <img class="logo img-responsive" src="{{request.static_url('myproject: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">Starter 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>
+ {% block content %}
+ <p>No content</p>
+ {% endblock content %}
</div>
</div>
<div class="row">
<div class="links">
<ul>
- <li class="current-version">Generated by v1.7</li>
- <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.7-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-globe icon-muted"></i><a href="https://webchat.freenode.net/?channels=pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="http://pylonsproject.org">Pylons Project</a></li>
</ul>
</div>
diff --git a/docs/narr/myproject/myproject/templates/mytemplate.jinja2 b/docs/narr/myproject/myproject/templates/mytemplate.jinja2
new file mode 100644
index 000000000..ce042215d
--- /dev/null
+++ b/docs/narr/myproject/myproject/templates/mytemplate.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">Welcome to <span class="font-normal">MyProject</span>, a&nbsp;Pyramid application generated&nbsp;by<br><span class="font-normal">Cookiecutter</span>.</p>
+</div>
+{% endblock content %}
diff --git a/docs/narr/MyProject/myproject/tests.py b/docs/narr/myproject/myproject/tests.py
index fd414cced..fd414cced 100644
--- a/docs/narr/MyProject/myproject/tests.py
+++ b/docs/narr/myproject/myproject/tests.py
diff --git a/docs/narr/MyProject/myproject/views.py b/docs/narr/myproject/myproject/views.py
index c383c5716..9e9ec4320 100644
--- a/docs/narr/MyProject/myproject/views.py
+++ b/docs/narr/myproject/myproject/views.py
@@ -1,6 +1,6 @@
from pyramid.view import view_config
-@view_config(route_name='home', renderer='templates/mytemplate.pt')
+@view_config(route_name='home', renderer='templates/mytemplate.jinja2')
def my_view(request):
return {'project': 'MyProject'}
diff --git a/docs/narr/MyProject/production.ini b/docs/narr/myproject/production.ini
index 1174b1cc7..13be488e7 100644
--- a/docs/narr/MyProject/production.ini
+++ b/docs/narr/myproject/production.ini
@@ -1,10 +1,10 @@
###
# app configuration
-# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/environment.html
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/environment.html
###
[app:main]
-use = egg:MyProject
+use = egg:myproject
pyramid.reload_templates = false
pyramid.debug_authorization = false
@@ -18,12 +18,11 @@ pyramid.default_locale_name = en
[server:main]
use = egg:waitress#main
-host = 0.0.0.0
-port = 6543
+listen = *:6543
###
# logging configuration
-# http://docs.pylonsproject.org/projects/pyramid/en/1.7-branch/narr/logging.html
+# http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/logging.html
###
[loggers]
diff --git a/docs/narr/myproject/pytest.ini b/docs/narr/myproject/pytest.ini
new file mode 100644
index 000000000..b1b5f4c38
--- /dev/null
+++ b/docs/narr/myproject/pytest.ini
@@ -0,0 +1,3 @@
+[pytest]
+testpaths = myproject
+python_files = *.py
diff --git a/docs/narr/myproject/setup.py b/docs/narr/myproject/setup.py
new file mode 100644
index 000000000..00e377349
--- /dev/null
+++ b/docs/narr/myproject/setup.py
@@ -0,0 +1,51 @@
+import os
+
+from setuptools import setup, find_packages
+
+here = os.path.abspath(os.path.dirname(__file__))
+with open(os.path.join(here, 'README.txt')) as f:
+ README = f.read()
+with open(os.path.join(here, 'CHANGES.txt')) as f:
+ CHANGES = f.read()
+
+requires = [
+ 'pyramid',
+ 'pyramid_jinja2',
+ 'pyramid_debugtoolbar',
+ 'waitress',
+]
+
+tests_require = [
+ 'WebTest >= 1.3.1', # py3 compat
+ 'pytest',
+ 'pytest-cov',
+]
+
+setup(
+ name='myproject',
+ version='0.0',
+ description='MyProject',
+ long_description=README + '\n\n' + CHANGES,
+ classifiers=[
+ 'Programming Language :: Python',
+ 'Framework :: Pyramid',
+ 'Topic :: Internet :: WWW/HTTP',
+ 'Topic :: Internet :: WWW/HTTP :: WSGI :: Application',
+ ],
+ author='',
+ author_email='',
+ url='',
+ keywords='web pyramid pylons',
+ packages=find_packages(),
+ include_package_data=True,
+ zip_safe=False,
+ extras_require={
+ 'testing': tests_require,
+ },
+ install_requires=requires,
+ entry_points={
+ 'paste.app_factory': [
+ 'main = myproject:main',
+ ],
+ },
+)
diff --git a/docs/narr/paste.rst b/docs/narr/paste.rst
index 0a217e6e3..26cb1bfa5 100644
--- a/docs/narr/paste.rst
+++ b/docs/narr/paste.rst
@@ -3,7 +3,7 @@
PasteDeploy Configuration Files
===============================
-Packages generated via a :term:`scaffold` make use of a system created by Ian
+Packages generated via a :term:`cookiecutter` make use of a system created by Ian
Bicking named :term:`PasteDeploy`. PasteDeploy defines a way to declare
:term:`WSGI` application configuration in an ``.ini`` file.
@@ -14,7 +14,7 @@ runner ``pserve``, as well as other commands such as ``pviews``, ``pshell``,
PasteDeploy is not a particularly integral part of Pyramid. It's possible to
create a Pyramid application which does not use PasteDeploy at all. We show a
Pyramid application that doesn't use PasteDeploy in :ref:`firstapp_chapter`.
-However, all Pyramid scaffolds render PasteDeploy configuration files, to
+However, all Pyramid cookiecutters render PasteDeploy configuration files, to
provide new developers with a standardized way of setting deployment values,
and to provide new users with a standardized way of starting, stopping, and
debugging an application.
@@ -26,12 +26,7 @@ documentation, see http://pythonpaste.org/deploy/.
PasteDeploy
-----------
-:term:`PasteDeploy` is the system that Pyramid uses to allow :term:`deployment
-settings` to be specified using an ``.ini`` configuration file format. It also
-allows the ``pserve`` command to work. Its configuration format provides a
-convenient place to define application :term:`deployment settings` and WSGI
-server settings, and its server runner allows you to stop and start a Pyramid
-application easily.
+:term:`plaster` is the system that Pyramid uses to load settings from configuration files. The most common format for these files is an ``.ini`` format structured in a way defined by :term:`PasteDeploy`. The format supports mechanisms to define WSGI app :term:`deployment settings`, WSGI server settings and logging. This allows the ``pserve`` command to work, allowing you to stop and start a Pyramid application easily.
.. _pastedeploy_entry_points:
@@ -40,25 +35,25 @@ Entry Points and PasteDeploy ``.ini`` Files
In the :ref:`project_narr` chapter, we breezed over the meaning of a
configuration line in the ``deployment.ini`` file. This was the ``use =
-egg:MyProject`` line in the ``[app:main]`` section. We breezed over it because
+egg:myproject`` line in the ``[app:main]`` section. We breezed over it because
it's pretty confusing and "too much information" for an introduction to the
system. We'll try to give it a bit of attention here. Let's see the config
file again:
-.. literalinclude:: MyProject/development.ini
+.. literalinclude:: myproject/development.ini
:language: ini
:linenos:
-The line in ``[app:main]`` above that says ``use = egg:MyProject`` is actually
-shorthand for a longer spelling: ``use = egg:MyProject#main``. The ``#main``
+The line in ``[app:main]`` above that says ``use = egg:myproject`` is actually
+shorthand for a longer spelling: ``use = egg:myproject#main``. The ``#main``
part is omitted for brevity, as ``#main`` is a default defined by PasteDeploy.
-``egg:MyProject#main`` is a string which has meaning to PasteDeploy. It points
+``egg:myproject#main`` is a string which has meaning to PasteDeploy. It points
at a :term:`setuptools` :term:`entry point` named ``main`` defined in the
-``MyProject`` project.
+``myproject`` project.
Take a look at the generated ``setup.py`` file for this project.
-.. literalinclude:: MyProject/setup.py
+.. literalinclude:: myproject/setup.py
:language: python
:linenos:
@@ -66,21 +61,21 @@ Note that ``entry_points`` is assigned a string which looks a lot like an
``.ini`` file. This string representation of an ``.ini`` file has a section
named ``[paste.app_factory]``. Within this section, there is a key named
``main`` (the entry point name) which has a value ``myproject:main``. The
-*key* ``main`` is what our ``egg:MyProject#main`` value of the ``use`` section
+*key* ``main`` is what our ``egg:myproject#main`` value of the ``use`` section
in our config file is pointing at, although it is actually shortened to
-``egg:MyProject`` there. The value represents a :term:`dotted Python name`
+``egg:myproject`` there. The value represents a :term:`dotted Python name`
path, which refers to a callable in our ``myproject`` package's ``__init__.py``
module.
-The ``egg:`` prefix in ``egg:MyProject`` indicates that this is an entry point
+The ``egg:`` prefix in ``egg:myproject`` indicates that this is an entry point
*URI* specifier, where the "scheme" is "egg". An "egg" is created when you run
``setup.py install`` or ``setup.py develop`` within your project.
In English, this entry point can thus be referred to as a "PasteDeploy
-application factory in the ``MyProject`` project which has the entry point
+application factory in the ``myproject`` project which has the entry point
named ``main`` where the entry point refers to a ``main`` function in the
``mypackage`` module". Indeed, if you open up the ``__init__.py`` module
-generated within any scaffold-generated package, you'll see a ``main``
+generated within any cookiecutter-generated package, you'll see a ``main``
function. This is the function called by :term:`PasteDeploy` when the
``pserve`` command is invoked against our application. It accepts a global
configuration object and *returns* an instance of our application.
@@ -96,3 +91,8 @@ applications, servers, and :term:`middleware` defined within the configuration
file. The values in a ``[DEFAULT]`` section will be passed to your
application's ``main`` function as ``global_config`` (see the reference to the
``main`` function in :ref:`init_py`).
+
+Alternative Configuration File Formats
+--------------------------------------
+
+It is possible to use different file formats with :app:`Pyramid` if you do not like :term:`PasteDeploy`. Under the hood all command-line scripts such as ``pserve`` and ``pshell`` pass the ``config_uri`` (e.g. ``development.ini`` or ``production.ini``) to the :term:`plaster` library which performs a lookup for an appropriate parser. For ``.ini`` files it uses PasteDeploy but you can register your own configuration formats that plaster will find instead.
diff --git a/docs/narr/project.png b/docs/narr/project.png
index e1afd97d4..0e17e57ab 100644
--- a/docs/narr/project.png
+++ b/docs/narr/project.png
Binary files differ
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index 71bd176f6..a150afc6b 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -5,94 +5,132 @@ 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`.
+a :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
+You'll use a 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
+The Pylons Project provides several :app:`Pyramid` cookiecutters that you can use to generate a
+project. Each cookiecutter makes different configuration assumptions about what
type of application you're trying to construct.
-These scaffolds are rendered using the ``pcreate`` command that is installed as
-part of Pyramid.
+These cookiecutters are rendered using the ``cookiecutter`` command that you may install.
+
+.. seealso::
+
+ See also `Cookiecutter Installation <https://cookiecutter.readthedocs.io/en/latest/installation.html>`_.
+
.. index::
- single: scaffolds
- single: starter scaffold
- single: zodb scaffold
- single: alchemy scaffold
+ single: cookiecutters
+ single: pyramid-cookiecutter-starter
+ single: pyramid-cookiecutter-zodb
+ single: pyramid-cookiecutter-alchemy
-.. _additional_paster_scaffolds:
+.. _additional_cookiecutters:
-Scaffolds Included with :app:`Pyramid`
---------------------------------------
+:app:`Pyramid` cookiecutters
+----------------------------
+
+Pyramid cookiecutters released under the Pylons Project differ from each other on a number of axes:
+
+- the persistence mechanism they offer (no persistence mechanism, :term:`SQLAlchemy` with SQLite, or :term:`ZODB`)
-The convenience scaffolds included with :app:`Pyramid` differ from each other
-on a number of axes:
+- the mechanism they use to map URLs to code (:term:`URL dispatch` or :term:`traversal`)
-- the persistence mechanism they offer (no persistence mechanism, :term:`ZODB`,
- or :term:`SQLAlchemy`)
+- templating libraries (:term:`Jinja2`, :term:`Chameleon`, or :term:`Mako`)
-- 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>`_
+* `pyramid-cookiecutter-alchemy <https://github.com/Pylons/pyramid-cookiecutter-alchemy>`_
+* `pyramid-cookiecutter-zodb <https://github.com/Pylons/pyramid-cookiecutter-zodb>`_
-The included scaffolds are these:
+These cookiecutters include:
-``starter``
- URL mapping via :term:`URL dispatch` and no persistence mechanism
+``pyramid-cookiecutter-starter``
+ :term:`URL dispatch` for routing and either :term:`Jinja2`, :term:`Chameleon`, or :term:`Mako` for templating
-``zodb``
- URL mapping via :term:`traversal` and persistence via :term:`ZODB`
+``pyramid-cookiecutter-alchemy``
+ SQLite for persistent storage, :term:`SQLAlchemy` for an ORM, :term:`URL dispatch` for routing, and :term:`Jinja2` for templating.
-``alchemy``
- URL mapping via :term:`URL dispatch` and persistence via :term:`SQLAlchemy`
+``pyramid-cookiecutter-zodb``
+ :term:`ZODB` for persistent storage, :term:`traversal` for routing, and :term:`Chameleon` for templating
.. index::
single: creating a project
single: project
- single: pcreate
+ single: cookiecutter
.. _creating_a_project:
Creating the Project
--------------------
-.. seealso:: See also the output of :ref:`pcreate --help <pcreate_script>`.
-
In :ref:`installing_chapter`, you created a virtual Python environment via the
-``venv`` command. To start a :app:`Pyramid` :term:`project`, use the
-``pcreate`` command installed within the virtual environment. We'll choose the
-``starter`` scaffold for this purpose. When we invoke ``pcreate``, it will
-create a directory that represents our project.
+``venv`` command. We called the virtual environment directory
+``env`` and set an environment variable ``VENV`` to its path.
+
+We assume that you :ref:`previously installed cookiecutter <cookiecutters>`, following its installation instructions.
+
+We'll choose ``pyramid-cookiecutter-starter`` to start the project. When we invoke ``cookiecutter``, it will create a directory that represents our project.
-In :ref:`installing_chapter` we called the virtual environment directory
-``env``. The following commands assume that our current working directory is
-the ``env`` directory.
+We assume our current working directory is the value of ``VENV``.
+
+On all platforms, generate a project using cookiecutter.
+
+.. code-block:: bash
-The below example uses the ``pcreate`` command to create a project with the
-``starter`` scaffold.
+ $ cookiecutter https://github.com/Pylons/pyramid-cookiecutter-starter
+
+If prompted for the first item, accept the default ``yes`` by hitting return.
+
+.. code-block:: text
+
+ 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
+
+We then run through the following commands.
On UNIX:
.. code-block:: bash
- $ $VENV/bin/pcreate -s starter MyProject
+ # 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
Or on Windows:
.. code-block:: doscon
- c:\> %VENV%\Scripts\pcreate -s starter MyProject
-
-As a result of invoking the ``pcreate`` command, a directory named
-``MyProject`` is created. That directory is a :term:`project` directory. The
+ # Reset our environment variable for a new virtual environment.
+ c:\> set VENV=c:\env\myproject\env
+ # Change directory into your newly created project.
+ c:\> cd myproject
+ # Create a new virtual environment...
+ c:\myproject> python -m venv %VENV%
+ # ...where we upgrade packaging tools.
+ c:\myproject> %VENV%\Scripts\pip install --upgrade pip setuptools
+
+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.
@@ -107,15 +145,15 @@ 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
+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`` virtual environment directory.
+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, and you don't need to put it within a virtual environment
+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
@@ -125,7 +163,7 @@ 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
@@ -144,7 +182,7 @@ newly created project directory and use the Python interpreter from the
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
+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
@@ -154,25 +192,24 @@ On UNIX:
.. code-block:: bash
- $ cd MyProject
- $ $VENV/bin/pip install -e .
+ $ $VENV/bin/pip install -e .
Or on Windows:
.. code-block:: doscon
- c:\> cd MyProject
- c:\> %VENV%\Scripts\pip install -e .
+ c:\env\myproject> %VENV%\Scripts\pip install -e .
Elided output from a run of this command on UNIX is shown below:
.. code-block:: bash
- $ cd MyProject
- $ $VENV/bin/pip install -e .
- ...
- Successfully installed Chameleon-2.24 Mako-1.0.4 MyProject \
- pyramid-chameleon-0.3 pyramid-debugtoolbar-2.4.2 pyramid-mako-1.0.2
+ 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``
@@ -199,7 +236,7 @@ On Windows:
.. code-block:: doscon
- c:\> %VENV%\Scripts\pip install -e ".[testing]"
+ c:\env\myproject> %VENV%\Scripts\pip install -e ".[testing]"
Once the testing requirements are installed, then you can run the tests using
the ``py.test`` command that was just installed in the ``bin`` directory of
@@ -215,7 +252,7 @@ On Windows:
.. code-block:: doscon
- c:\> %VENV%\Scripts\py.test -q
+ c:\env\myproject> %VENV%\Scripts\py.test -q
Here's sample output from a test run on UNIX:
@@ -225,9 +262,7 @@ Here's sample output from a test run on UNIX:
..
2 passed in 0.47 seconds
-The tests themselves are found in the ``tests.py`` module in your ``pcreate``
-generated project. Within a project generated by the ``starter`` scaffold,
-only two sample tests exist.
+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::
@@ -242,7 +277,7 @@ to ``py.test``:
$ $VENV/bin/py.test --cov -q
-Scaffolds include configuration defaults for ``py.test`` and test coverage.
+Cookiecutters include configuration defaults for ``py.test`` 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.
@@ -280,31 +315,31 @@ On UNIX:
On Windows:
-.. code-block:: text
+.. code-block:: doscon
- c:\> %VENV%\Scripts\pserve development.ini
+ c:\env\myproject> %VENV%\Scripts\pserve development.ini
Here's sample output from a run of ``pserve`` on UNIX:
.. code-block:: bash
$ $VENV/bin/pserve development.ini
- Starting server in PID 16208.
- serving on http://127.0.0.1:6543
+ Starting server in PID 77171.
+ Serving on http://localhost:6543
+ Serving on http://localhost:6543
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 ``host`` value in the
-``[server:main]`` section, changing it from ``127.0.0.1`` to ``0.0.0.0``. For
-example:
+``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 = 0.0.0.0
- port = 6543
+ 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
@@ -316,19 +351,20 @@ 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/``.
+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`` (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
+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,
@@ -365,7 +401,8 @@ For example, on UNIX:
$ $VENV/bin/pserve development.ini --reload
Starting subprocess with file monitor
Starting server in PID 16601.
- serving on http://127.0.0.1:6543
+ 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:
@@ -375,12 +412,13 @@ files, you'll see the server restart automatically:
development.ini changed; reloading...
-------------------- Restarting --------------------
Starting server in PID 16602.
- serving on http://127.0.0.1:6543
+ 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
+file is ``true``. Changes made to template files when this setting is ``true``
will take effect immediately without a server restart.
.. index::
@@ -395,8 +433,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
@@ -477,48 +515,57 @@ 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
+ ├── CHANGES.txt
+ ├── MANIFEST.in
+ ├── myproject
+ │   ├── __init__.py
+ │   ├── static
+ │   │   ├── pyramid-16x16.png
+ │   │   ├── pyramid.png
+ │   │   └── theme.css
+ │   ├── templates
+ │   │   ├── layout.jinja2
+ │   │   └── mytemplate.jinja2
+ │   ├── tests.py
+ │   └── views.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
+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.
+#. ``.coveragerc`` configures coverage when running tests.
+
#. ``CHANGES.txt`` describes the changes you've made to the application. It is
- conventionally written in :term:`ReStructuredText` format.
+ 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.
#. ``README.txt`` describes the application in general. It is conventionally
- written in :term:`ReStructuredText` format.
+ written in :term:`reStructuredText` format.
#. ``development.ini`` is a :term:`PasteDeploy` configuration file that can be
used to execute your application during development.
@@ -526,9 +573,7 @@ describe, run, and test your application.
#. ``production.ini`` is a :term:`PasteDeploy` configuration file that can be
used to execute your application in a production configuration.
-#. ``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.
+#. ``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.
@@ -537,7 +582,7 @@ describe, run, and test your application.
single: PasteDeploy
single: ini file
-.. _MyProject_ini:
+.. _myproject_ini:
``development.ini``
~~~~~~~~~~~~~~~~~~~
@@ -548,7 +593,7 @@ 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:
@@ -557,15 +602,15 @@ This file contains several sections including ``[app:main]``,
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.
+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.
.. seealso:: See :ref:`pastedeploy_entry_points` for more information about the
- meaning of the ``use = egg:MyProject`` value in this section.
+ 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
@@ -599,7 +644,7 @@ The ``[server:main]`` section of the configuration file configures a WSGI
server which listens on TCP port 6543. It is configured to listen on localhost
only (``127.0.0.1``).
-.. _MyProject_ini_logging:
+.. _myproject_ini_logging:
The sections after ``# logging configuration`` represent Python's standard
library :mod:`logging` module configuration for your application. These
@@ -660,7 +705,7 @@ 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.
+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
@@ -700,7 +745,7 @@ testing, as well as distributing your application.
Our generated ``setup.py`` looks like this:
-.. literalinclude:: MyProject/setup.py
+.. literalinclude:: myproject/setup.py
:language: python
:linenos:
@@ -743,7 +788,7 @@ you can try this command now:
$ $VENV/bin/python setup.py sdist
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
+``myproject-0.0.tar.gz``. You can send this tarball to other people who want
to install and use your application.
.. index::
@@ -752,7 +797,7 @@ 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
@@ -760,14 +805,14 @@ The ``myproject`` :term:`package` lives inside the ``MyProject``
``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
+#. 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 ``views.py`` module, which contains view code for the application.
-These are purely conventions established by the scaffold. :app:`Pyramid`
+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.
@@ -785,7 +830,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:
@@ -800,8 +845,8 @@ also informs Python that the directory which contains it is a *package*.
Line 7 creates 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
@@ -827,7 +872,7 @@ 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
+.. literalinclude:: myproject/myproject/views.py
:language: python
:linenos:
@@ -844,8 +889,8 @@ result of the view callable. This particular view declaration points at
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``).
+optional. The template file pointed to is a :term:`Jinja2` template
+file (``templates/my_template.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``
@@ -858,9 +903,9 @@ 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,
+.. 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
@@ -869,7 +914,7 @@ the HTML in a :term:`response`.
.. 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.
@@ -900,31 +945,46 @@ 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``
~~~~~~~~~~~~~~~~~~~~~~~~~~~
-This is 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``
+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.py`` file. See
-:ref:`views_which_use_a_renderer` for more information about renderers.
+: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`.
+
.. 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:
@@ -946,16 +1006,16 @@ 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
+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 scaffold are
+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
-scaffold, you can decide to lay your code out any way you see fit.
+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
+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.
@@ -997,7 +1057,7 @@ Pyramid application via ``pserve``. This can be a useful debugging tool. See
What Is This ``pserve`` Thing
-----------------------------
-The code generated by a :app:`Pyramid` scaffold assumes that you will be using
+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`
@@ -1007,7 +1067,7 @@ application based on the data in the file.
application. As we saw in :ref:`firstapp_chapter`, ``pserve`` needn't be
invoked at all to run a :app:`Pyramid` application. The use of ``pserve`` to
run a :app:`Pyramid` application is purely conventional based on the output of
-its scaffolding. But we strongly recommend using ``pserve`` while developing
+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
@@ -1019,7 +1079,7 @@ restarting of the server when code changes.
Using an Alternate WSGI Server
------------------------------
-Pyramid scaffolds generate projects which use the :term:`Waitress` WSGI server.
+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,
@@ -1036,12 +1096,54 @@ 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
+: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
+``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 <http://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 <http://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 =
+ myapp/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.
diff --git a/docs/narr/scaffolding.rst b/docs/narr/scaffolding.rst
index 164ceb3bf..27239d34e 100644
--- a/docs/narr/scaffolding.rst
+++ b/docs/narr/scaffolding.rst
@@ -3,6 +3,10 @@
Creating Pyramid Scaffolds
==========================
+.. deprecated:: 1.8
+
+ Scaffolds and the ``pcreate`` script used to generate :app:`Pyramid` projects from scaffolds have been deprecated. Use :ref:`cookiecutters` instead.
+
You can extend Pyramid by creating a :term:`scaffold` template. A scaffold
template is useful if you'd like to distribute a customizable configuration of
Pyramid to other users. Once you've created a scaffold, and someone has
diff --git a/docs/narr/security.rst b/docs/narr/security.rst
index 77e7fd707..3a6bfa5e5 100644
--- a/docs/narr/security.rst
+++ b/docs/narr/security.rst
@@ -146,7 +146,7 @@ For example, the following view declaration protects the view named
# config is an instance of pyramid.config.Configurator
config.add_view('mypackage.views.blog_entry_add_view',
- name='add_entry.html',
+ name='add_entry.html',
context='mypackage.resources.Blog',
permission='add')
@@ -725,7 +725,7 @@ object that implements the following interface:
""" Return ``True`` if any of the ``principals`` is allowed the
``permission`` in the current ``context``, else return ``False``
"""
-
+
def principals_allowed_by_permission(self, context, permission):
""" Return a set of principal identifiers allowed by the
``permission`` in ``context``. This behavior is optional; if you
@@ -765,3 +765,215 @@ which would allow the attacker to control the content of the payload. Re-using
a secret across two different subsystems might drop the security of signing to
zero. Keys should not be re-used across different contexts where an attacker
has the possibility of providing a chosen plaintext.
+
+.. index::
+ single: preventing cross-site request forgery attacks
+ single: cross-site request forgery attacks, prevention
+
+Preventing Cross-Site Request Forgery Attacks
+---------------------------------------------
+
+`Cross-site request forgery
+<https://en.wikipedia.org/wiki/Cross-site_request_forgery>`_ attacks are a
+phenomenon whereby a user who is logged in to your website might inadvertantly
+load a URL because it is linked from, or embedded in, an attacker's website.
+If the URL is one that may modify or delete data, the consequences can be dire.
+
+You can avoid most of these attacks by issuing a unique token to the browser
+and then requiring that it be present in all potentially unsafe requests.
+:app:`Pyramid` provides facilities to create and check CSRF tokens.
+
+By default :app:`Pyramid` comes with a session-based CSRF implementation
+:class:`pyramid.csrf.SessionCSRFStoragePolicy`. To use it, you must first enable
+a :term:`session factory` as described in
+:ref:`using_the_default_session_factory` or
+:ref:`using_alternate_session_factories`. Alternatively, you can use
+a cookie-based implementation :class:`pyramid.csrf.CookieCSRFStoragePolicy` which gives
+some additional flexibility as it does not require a session for each user.
+You can also define your own implementation of
+:class:`pyramid.interfaces.ICSRFStoragePolicy` and register it with the
+:meth:`pyramid.config.Configurator.set_csrf_storage_policy` directive.
+
+For example:
+
+.. code-block:: python
+
+ from pyramid.config import Configurator
+
+ config = Configurator()
+ config.set_csrf_storage_policy(MyCustomCSRFPolicy())
+
+.. index::
+ single: csrf.get_csrf_token
+
+Using the ``csrf.get_csrf_token`` Method
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To get the current CSRF token, use the
+:data:`pyramid.csrf.get_csrf_token` method.
+
+.. code-block:: python
+
+ from pyramid.csrf import get_csrf_token
+ token = get_csrf_token(request)
+
+The ``get_csrf_token()`` method accepts a single argument: the request. It
+returns a CSRF *token* string. If ``get_csrf_token()`` or ``new_csrf_token()``
+was invoked previously for this user, then the existing token will be returned.
+If no CSRF token previously existed for this user, then a new token will be set
+into the session and returned. The newly created token will be opaque and
+randomized.
+
+.. _get_csrf_token_in_templates:
+
+Using the ``get_csrf_token`` global in templates
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Templates have a ``get_csrf_token()`` method inserted into their globals, which
+allows you to get the current token without modifying the view code. This
+method takes no arguments and returns a CSRF token string. You can use the
+returned token as the value of a hidden field in a form that posts to a method
+that requires elevated privileges, or supply it as a request header in AJAX
+requests.
+
+For example, include the CSRF token as a hidden field:
+
+.. code-block:: html
+
+ <form method="post" action="/myview">
+ <input type="hidden" name="csrf_token" value="${get_csrf_token()}">
+ <input type="submit" value="Delete Everything">
+ </form>
+
+Or include it as a header in a jQuery AJAX request:
+
+.. code-block:: javascript
+
+ var csrfToken = "${get_csrf_token()}";
+ $.ajax({
+ type: "POST",
+ url: "/myview",
+ headers: { 'X-CSRF-Token': csrfToken }
+ }).done(function() {
+ alert("Deleted");
+ });
+
+The handler for the URL that receives the request should then require that the
+correct CSRF token is supplied.
+
+.. index::
+ single: csrf.new_csrf_token
+
+Using the ``csrf.new_csrf_token`` Method
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To explicitly create a new CSRF token, use the ``csrf.new_csrf_token()``
+method. This differs only from ``csrf.get_csrf_token()`` inasmuch as it
+clears any existing CSRF token, creates a new CSRF token, sets the token into
+the user, and returns the token.
+
+.. code-block:: python
+
+ from pyramid.csrf import get_csrf_token
+ token = new_csrf_token()
+
+.. note::
+
+ It is not possible to force a new CSRF token from a template. If you
+ want to regenerate your CSRF token then do it in the view code and return
+ the new token as part of the context.
+
+Checking CSRF Tokens Manually
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In request handling code, you can check the presence and validity of a CSRF
+token with :func:`pyramid.csrf.check_csrf_token`. If the token is valid, it
+will return ``True``, otherwise it will raise ``HTTPBadRequest``. Optionally,
+you can specify ``raises=False`` to have the check return ``False`` instead of
+raising an exception.
+
+By default, it checks for a POST parameter named ``csrf_token`` or a header
+named ``X-CSRF-Token``.
+
+.. code-block:: python
+
+ from pyramid.csrf import check_csrf_token
+
+ def myview(request):
+ # Require CSRF Token
+ check_csrf_token(request)
+
+ # ...
+
+.. _auto_csrf_checking:
+
+Checking CSRF Tokens Automatically
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. versionadded:: 1.7
+
+:app:`Pyramid` supports automatically checking CSRF tokens on requests with an
+unsafe method as defined by RFC2616. Any other request may be checked manually.
+This feature can be turned on globally for an application using the
+:meth:`pyramid.config.Configurator.set_default_csrf_options` directive.
+For example:
+
+.. code-block:: python
+
+ from pyramid.config import Configurator
+
+ config = Configurator()
+ config.set_default_csrf_options(require_csrf=True)
+
+CSRF checking may be explicitly enabled or disabled on a per-view basis using
+the ``require_csrf`` view option. A value of ``True`` or ``False`` will
+override the default set by ``set_default_csrf_options``. For example:
+
+.. code-block:: python
+
+ @view_config(route_name='hello', require_csrf=False)
+ def myview(request):
+ # ...
+
+When CSRF checking is active, the token and header used to find the
+supplied CSRF token will be ``csrf_token`` and ``X-CSRF-Token``, respectively,
+unless otherwise overridden by ``set_default_csrf_options``. The token is
+checked against the value in ``request.POST`` which is the submitted form body.
+If this value is not present, then the header will be checked.
+
+In addition to token based CSRF checks, if the request is using HTTPS then the
+automatic CSRF checking will also check the referrer of the request to ensure
+that it matches one of the trusted origins. By default the only trusted origin
+is the current host, however additional origins may be configured by setting
+``pyramid.csrf_trusted_origins`` to a list of domain names (and ports if they
+are non-standard). If a host in the list of domains starts with a ``.`` then
+that will allow all subdomains as well as the domain without the ``.``.
+
+If CSRF checks fail then a :class:`pyramid.exceptions.BadCSRFToken` or
+:class:`pyramid.exceptions.BadCSRFOrigin` exception will be raised. This
+exception may be caught and handled by an :term:`exception view` but, by
+default, will result in a ``400 Bad Request`` response being sent to the
+client.
+
+Checking CSRF Tokens with a View Predicate
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+.. deprecated:: 1.7
+ Use the ``require_csrf`` option or read :ref:`auto_csrf_checking` instead
+ to have :class:`pyramid.exceptions.BadCSRFToken` exceptions raised.
+
+A convenient way to require a valid CSRF token for a particular view is to
+include ``check_csrf=True`` as a view predicate. See
+:meth:`pyramid.config.Configurator.add_view`.
+
+.. code-block:: python
+
+ @view_config(request_method='POST', check_csrf=True, ...)
+ def myview(request):
+ ...
+
+.. note::
+ A mismatch of a CSRF token is treated like any other predicate miss, and the
+ predicate system, when it doesn't find a view, raises ``HTTPNotFound``
+ instead of ``HTTPBadRequest``, so ``check_csrf=True`` behavior is different
+ from calling :func:`pyramid.csrf.check_csrf_token`.
diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst
index 5b24201a9..7e2469d54 100644
--- a/docs/narr/sessions.rst
+++ b/docs/narr/sessions.rst
@@ -12,8 +12,7 @@ application.
This chapter describes how to configure sessions, what session implementations
:app:`Pyramid` provides out of the box, how to store and retrieve data from
-sessions, and two session-specific features: flash messages, and cross-site
-request forgery attack prevention.
+sessions, and a session-specific feature: flash messages.
.. index::
single: session factory (default)
@@ -316,183 +315,3 @@ flash storage.
['info message']
>>> request.session.peek_flash()
[]
-
-.. index::
- single: preventing cross-site request forgery attacks
- single: cross-site request forgery attacks, prevention
-
-Preventing Cross-Site Request Forgery Attacks
----------------------------------------------
-
-`Cross-site request forgery
-<https://en.wikipedia.org/wiki/Cross-site_request_forgery>`_ attacks are a
-phenomenon whereby a user who is logged in to your website might inadvertantly
-load a URL because it is linked from, or embedded in, an attacker's website.
-If the URL is one that may modify or delete data, the consequences can be dire.
-
-You can avoid most of these attacks by issuing a unique token to the browser
-and then requiring that it be present in all potentially unsafe requests.
-:app:`Pyramid` sessions provide facilities to create and check CSRF tokens.
-
-To use CSRF tokens, you must first enable a :term:`session factory` as
-described in :ref:`using_the_default_session_factory` or
-:ref:`using_alternate_session_factories`.
-
-.. index::
- single: session.get_csrf_token
-
-Using the ``session.get_csrf_token`` Method
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To get the current CSRF token from the session, use the
-``session.get_csrf_token()`` method.
-
-.. code-block:: python
-
- token = request.session.get_csrf_token()
-
-The ``session.get_csrf_token()`` method accepts no arguments. It returns a
-CSRF *token* string. If ``session.get_csrf_token()`` or
-``session.new_csrf_token()`` was invoked previously for this session, then the
-existing token will be returned. If no CSRF token previously existed for this
-session, then a new token will be set into the session and returned. The newly
-created token will be opaque and randomized.
-
-You can use the returned token as the value of a hidden field in a form that
-posts to a method that requires elevated privileges, or supply it as a request
-header in AJAX requests.
-
-For example, include the CSRF token as a hidden field:
-
-.. code-block:: html
-
- <form method="post" action="/myview">
- <input type="hidden" name="csrf_token" value="${request.session.get_csrf_token()}">
- <input type="submit" value="Delete Everything">
- </form>
-
-Or include it as a header in a jQuery AJAX request:
-
-.. code-block:: javascript
-
- var csrfToken = ${request.session.get_csrf_token()};
- $.ajax({
- type: "POST",
- url: "/myview",
- headers: { 'X-CSRF-Token': csrfToken }
- }).done(function() {
- alert("Deleted");
- });
-
-The handler for the URL that receives the request should then require that the
-correct CSRF token is supplied.
-
-.. index::
- single: session.new_csrf_token
-
-Using the ``session.new_csrf_token`` Method
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-To explicitly create a new CSRF token, use the ``session.new_csrf_token()``
-method. This differs only from ``session.get_csrf_token()`` inasmuch as it
-clears any existing CSRF token, creates a new CSRF token, sets the token into
-the session, and returns the token.
-
-.. code-block:: python
-
- token = request.session.new_csrf_token()
-
-Checking CSRF Tokens Manually
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-In request handling code, you can check the presence and validity of a CSRF
-token with :func:`pyramid.session.check_csrf_token`. If the token is valid, it
-will return ``True``, otherwise it will raise ``HTTPBadRequest``. Optionally,
-you can specify ``raises=False`` to have the check return ``False`` instead of
-raising an exception.
-
-By default, it checks for a POST parameter named ``csrf_token`` or a header
-named ``X-CSRF-Token``.
-
-.. code-block:: python
-
- from pyramid.session import check_csrf_token
-
- def myview(request):
- # Require CSRF Token
- check_csrf_token(request)
-
- # ...
-
-.. _auto_csrf_checking:
-
-Checking CSRF Tokens Automatically
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. versionadded:: 1.7
-
-:app:`Pyramid` supports automatically checking CSRF tokens on requests with an
-unsafe method as defined by RFC2616. Any other request may be checked manually.
-This feature can be turned on globally for an application using the
-:meth:`pyramid.config.Configurator.set_default_csrf_options` directive.
-For example:
-
-.. code-block:: python
-
- from pyramid.config import Configurator
-
- config = Configurator()
- config.set_default_csrf_options(require_csrf=True)
-
-CSRF checking may be explicitly enabled or disabled on a per-view basis using
-the ``require_csrf`` view option. A value of ``True`` or ``False`` will
-override the default set by ``set_default_csrf_options``. For example:
-
-.. code-block:: python
-
- @view_config(route_name='hello', require_csrf=False)
- def myview(request):
- # ...
-
-When CSRF checking is active, the token and header used to find the
-supplied CSRF token will be ``csrf_token`` and ``X-CSRF-Token``, respectively,
-unless otherwise overridden by ``set_default_csrf_options``. The token is
-checked against the value in ``request.POST`` which is the submitted form body.
-If this value is not present, then the header will be checked.
-
-In addition to token based CSRF checks, if the request is using HTTPS then the
-automatic CSRF checking will also check the referrer of the request to ensure
-that it matches one of the trusted origins. By default the only trusted origin
-is the current host, however additional origins may be configured by setting
-``pyramid.csrf_trusted_origins`` to a list of domain names (and ports if they
-are non standard). If a host in the list of domains starts with a ``.`` then
-that will allow all subdomains as well as the domain without the ``.``.
-
-If CSRF checks fail then a :class:`pyramid.exceptions.BadCSRFToken` or
-:class:`pyramid.exceptions.BadCSRFOrigin` exception will be raised. This
-exception may be caught and handled by an :term:`exception view` but, by
-default, will result in a ``400 Bad Request`` response being sent to the
-client.
-
-Checking CSRF Tokens with a View Predicate
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-.. deprecated:: 1.7
- Use the ``require_csrf`` option or read :ref:`auto_csrf_checking` instead
- to have :class:`pyramid.exceptions.BadCSRFToken` exceptions raised.
-
-A convenient way to require a valid CSRF token for a particular view is to
-include ``check_csrf=True`` as a view predicate. See
-:meth:`pyramid.config.Configurator.add_view`.
-
-.. code-block:: python
-
- @view_config(request_method='POST', check_csrf=True, ...)
- def myview(request):
- ...
-
-.. note::
- A mismatch of a CSRF token is treated like any other predicate miss, and the
- predicate system, when it doesn't find a view, raises ``HTTPNotFound``
- instead of ``HTTPBadRequest``, so ``check_csrf=True`` behavior is different
- from calling :func:`pyramid.session.check_csrf_token`.
diff --git a/docs/narr/startup.rst b/docs/narr/startup.rst
index 3e168eaea..5e7c7c871 100644
--- a/docs/narr/startup.rst
+++ b/docs/narr/startup.rst
@@ -10,11 +10,12 @@ you'll see something much like this show up on the console:
$ $VENV/bin/pserve development.ini
Starting server in PID 16305.
- serving on http://127.0.0.1:6543
+ Serving on http://localhost:6543
+ Serving on http://localhost:6543
This chapter explains what happens between the time you press the "Return" key
-on your keyboard after typing ``pserve development.ini`` and the time the line
-``serving on http://127.0.0.1:6543`` is output to your console.
+on your keyboard after typing ``pserve development.ini`` and the time the lines
+``Serving on http://localhost:6543`` are output to your console.
.. index::
single: startup process
@@ -37,7 +38,14 @@ Here's a high-level time-ordered overview of what happens when you press
begin to run and serve an application using the information contained
within the ``development.ini`` file.
-#. The framework finds a section named either ``[app:main]``,
+#. ``pserve`` passes the ``development.ini`` path to :term:`plaster` which
+ finds an available configuration loader that recognizes the ``ini`` format.
+
+#. :term:`plaster` finds the ``plaster_pastedeploy`` library which binds
+ the :term:`PasteDeploy` library and returns a parser that can understand
+ the format.
+
+#. The :term:`PasteDeploy` finds a section named either ``[app:main]``,
``[pipeline:main]``, or ``[composite:main]`` in the ``.ini`` file. This
section represents the configuration of a :term:`WSGI` application that will
be served. If you're using a simple application (e.g., ``[app:main]``), the
@@ -49,7 +57,7 @@ Here's a high-level time-ordered overview of what happens when you press
application or a pipeline, you're using a "composite" (e.g.,
``[composite:main]``), refer to the documentation for that particular
composite to understand how to make it refer to your :app:`Pyramid`
- application. In most cases, a Pyramid application built from a scaffold
+ application. In most cases, a Pyramid application built from a cookiecutter
will have a single ``[app:main]`` section in it, and this will be the
application served.
@@ -69,7 +77,7 @@ Here's a high-level time-ordered overview of what happens when you press
:app:`Pyramid` :term:`router` instance. Here's the contents of an example
``__init__.py`` module:
- .. literalinclude:: MyProject/myproject/__init__.py
+ .. literalinclude:: myproject/myproject/__init__.py
:language: python
:linenos:
@@ -85,12 +93,12 @@ Here's a high-level time-ordered overview of what happens when you press
Our generated ``development.ini`` file looks like so:
- .. literalinclude:: MyProject/development.ini
+ .. literalinclude:: myproject/development.ini
:language: ini
:linenos:
In this case, the ``myproject.__init__:main`` function referred to by the
- entry point URI ``egg:MyProject`` (see :ref:`MyProject_ini` for more
+ entry point URI ``egg:myproject`` (see :ref:`myproject_ini` for more
information about entry point URIs, and how they relate to callables) will
receive the key/value pairs ``{pyramid.reload_templates = true,
pyramid.debug_authorization = false, pyramid.debug_notfound = false,
@@ -130,10 +138,10 @@ Here's a high-level time-ordered overview of what happens when you press
#. ``pserve`` starts the WSGI *server* defined within the ``[server:main]``
section. In our case, this is the Waitress server (``use =
- egg:waitress#main``), and it will listen on all interfaces (``host =
- 127.0.0.1``), on port number 6543 (``port = 6543``). The server code itself
- is what prints ``serving on http://127.0.0.1:6543``. The server serves the
- application, and the application is running, waiting to receive requests.
+ egg:waitress#main``), and it will listen on all interfaces on port 6543
+ for both IPv4 and IPv6 (``listen = localhost:6543``). The server
+ code itself is what prints ``Serving on http://localhost:6543``. The server
+ serves the application, and the application is running, waiting to receive requests.
.. seealso::
Logging configuration is described in the :ref:`logging_chapter` chapter.
diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst
index 6b3b5fcce..4eadbd2f0 100644
--- a/docs/narr/templates.rst
+++ b/docs/narr/templates.rst
@@ -228,6 +228,10 @@ These values are provided to the template:
provided if the template is rendered as the result of a ``renderer=``
argument to the view configuration being used.
+``get_csrf_token()``
+ A convenience function to access the current CSRF token. See
+ :ref:`get_csrf_token_in_templates` for more information.
+
``renderer_name``
The renderer name used to perform the rendering, e.g.,
``mypackage:templates/foo.pt``.
diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst
index 354a462d4..406383bbd 100644
--- a/docs/narr/testing.rst
+++ b/docs/narr/testing.rst
@@ -370,11 +370,11 @@ coverage reports.
Regardless of which testing :term:`package` you use, be sure to add a
``tests_require`` dependency on that package to your application's ``setup.py``
-file. Using the project ``MyProject`` generated by the starter scaffold as
+file. Using the project ``myproject`` generated by the starter cookiecutter as
described in :doc:`project`, we would insert the following code immediately
-following the ``requires`` block in the file ``MyProject/setup.py``.
+following the ``requires`` block in the file ``myproject/setup.py``.
-.. literalinclude:: MyProject/setup.py
+.. literalinclude:: myproject/setup.py
:language: python
:linenos:
:lines: 11-22
@@ -383,7 +383,7 @@ following the ``requires`` block in the file ``MyProject/setup.py``.
Remember to change the dependency.
-.. literalinclude:: MyProject/setup.py
+.. literalinclude:: myproject/setup.py
:language: python
:linenos:
:lines: 40-44
@@ -401,14 +401,14 @@ In your ``MyPackage`` project, your :term:`package` is named ``myproject``
which contains a ``views`` 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.py
:linenos:
:language: python
The following example functional test demonstrates invoking the above
:term:`view`:
- .. literalinclude:: MyProject/myproject/tests.py
+ .. literalinclude:: myproject/myproject/tests.py
:linenos:
:pyobject: FunctionalTests
:language: python
diff --git a/docs/narr/upgrading.rst b/docs/narr/upgrading.rst
index 4e434c3c6..e0482d5a2 100644
--- a/docs/narr/upgrading.rst
+++ b/docs/narr/upgrading.rst
@@ -208,7 +208,7 @@ On Windows, you need to issue two commands:
.. code-block:: doscon
c:\> set PYTHONWARNINGS=default
- c:\> Scripts/pserve.exe development.ini
+ c:\> Scripts\pserve development.ini
At this point, it's ensured that deprecation warnings will be printed to the
console whenever a codepath is hit that generates one. You can then click
diff --git a/docs/narr/vhosting.rst b/docs/narr/vhosting.rst
index 0edf03353..e4cee9882 100644
--- a/docs/narr/vhosting.rst
+++ b/docs/narr/vhosting.rst
@@ -26,20 +26,20 @@ Hosting an Application Under a URL Prefix
``http://example.com/``).
If you use a "pure Python" environment, this functionality can be provided by
-Paste's `urlmap <http://pythonpaste.org/modules/urlmap.html>`_ "composite" WSGI
-application. Alternatively, you can use :term:`mod_wsgi` to serve your
+`rutter <http://rutter.readthedocs.io/en/latest/>`_, forming a "composite"
+WSGI application. Alternatively, you can use :term:`mod_wsgi` to serve your
application, which handles this virtual hosting translation for you "under the
hood".
-If you use the ``urlmap`` composite application "in front" of a :app:`Pyramid`
+If you use the ``rutter`` composite application "in front" of a :app:`Pyramid`
application or if you use :term:`mod_wsgi` to serve up a :app:`Pyramid`
application, nothing special needs to be done within the application for URLs
-to be generated that contain a prefix. :mod:`paste.urlmap` and :term:`mod_wsgi`
+to be generated that contain a prefix. Rutter and :term:`mod_wsgi`
manipulate the :term:`WSGI` environment in such a way that the ``PATH_INFO``
and ``SCRIPT_NAME`` variables are correct for some given prefix.
Here's an example of a PasteDeploy configuration snippet that includes a
-``urlmap`` composite.
+``rutter`` composite.
.. code-block:: ini
:linenos:
@@ -48,13 +48,13 @@ Here's an example of a PasteDeploy configuration snippet that includes a
use = egg:mypyramidapp
[composite:main]
- use = egg:Paste#urlmap
+ use = egg:rutter#urlmap
/pyramidapp = mypyramidapp
This "roots" the :app:`Pyramid` application at the prefix ``/pyramidapp`` and
serves up the composite as the "main" application in the file.
-.. note:: If you're using an Apache server to proxy to a Paste ``urlmap``
+.. note:: If you're using an Apache server to proxy to a ``urlmap``
composite, you may have to use the `ProxyPreserveHost
<http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxypreservehost>`_
directive to pass the original ``HTTP_HOST`` header along to the
diff --git a/docs/narr/viewconfig.rst b/docs/narr/viewconfig.rst
index 7cb8e0306..3b683ff79 100644
--- a/docs/narr/viewconfig.rst
+++ b/docs/narr/viewconfig.rst
@@ -252,7 +252,7 @@ Non-Predicate Arguments
def myview(request):
...
- Is similar to doing::
+ Is similar to decorating the view callable directly::
@view_config(...)
@decorator2
@@ -260,8 +260,10 @@ Non-Predicate Arguments
def myview(request):
...
- All view callables in the decorator chain must return a response object
- implementing :class:`pyramid.interfaces.IResponse` or raise an exception:
+ An important distinction is that each decorator will receive a response
+ object implementing :class:`pyramid.interfaces.IResponse` instead of the
+ raw value returned from the view callable. All decorators in the chain must
+ return a response object or raise an exception:
.. code-block:: python
diff --git a/docs/narr/views.rst b/docs/narr/views.rst
index ab139ea19..e8a07202e 100644
--- a/docs/narr/views.rst
+++ b/docs/narr/views.rst
@@ -52,7 +52,7 @@ of exceptions from within the body of a view callable.
Defining a View Callable as a Function
--------------------------------------
-One of the easiest way to define a view callable is to create a function that
+One of the easiest ways to define a view callable is to create a function that
accepts a single argument named ``request``, and which returns a
:term:`Response` object. For example, this is a "hello world" view callable
implemented as a function:
@@ -246,7 +246,7 @@ within view code, the result of the :term:`Not Found View` will be returned to
the user agent which performed the request.
If :exc:`~pyramid.httpexceptions.HTTPForbidden` is raised by Pyramid itself
-within view code, the result of the :term:`Forbidden View` will be returned to
+or within view code, the result of the :term:`Forbidden View` will be returned to
the user agent which performed the request.
.. index::
@@ -523,8 +523,7 @@ Alternate View Callable Argument/Calling Conventions
----------------------------------------------------
Usually view callables are defined to accept only a single argument:
-``request``. However, view callables may alternately be defined as classes,
-functions, or any callable that accept *two* positional arguments: a
+``request``. However, a view callable may alternately be defined as any class, function, or callable that accepts *two* positional arguments: a
:term:`context` resource as the first argument and a :term:`request` as the
second argument.
diff --git a/docs/narr/webob.rst b/docs/narr/webob.rst
index ce1586834..578fdeb51 100644
--- a/docs/narr/webob.rst
+++ b/docs/narr/webob.rst
@@ -345,8 +345,8 @@ against your ``mypackage`` package during application initialization.
.. note::
This is only an example. In particular, it is not necessary to cause
- ``DBSession.remove`` to be called in an application generated from any
- :app:`Pyramid` scaffold, because these all use the ``pyramid_tm`` package.
+ ``DBSession.remove`` to be called in an application generated from a
+ :app:`Pyramid` cookiecutter, because these all use the ``pyramid_tm`` package.
The cleanup done by ``DBSession.remove`` is unnecessary when ``pyramid_tm``
:term:`middleware` is configured into the application.