summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/designdefense.rst142
-rw-r--r--docs/narr/MyProject/development.ini6
-rw-r--r--docs/narr/MyProject/myproject/templates/mytemplate.pt13
-rw-r--r--docs/narr/MyProject/myproject/tests.py25
-rw-r--r--docs/narr/MyProject/production.ini2
-rw-r--r--docs/narr/MyProject/setup.py45
-rw-r--r--docs/narr/project.rst98
-rw-r--r--docs/narr/scaffolding.rst8
-rw-r--r--docs/narr/startup.rst27
-rw-r--r--docs/narr/testing.rst73
-rw-r--r--docs/narr/zca.rst257
11 files changed, 331 insertions, 365 deletions
diff --git a/docs/designdefense.rst b/docs/designdefense.rst
index ee6d5a317..478289c2b 100644
--- a/docs/designdefense.rst
+++ b/docs/designdefense.rst
@@ -7,98 +7,94 @@ From time to time, challenges to various aspects of :app:`Pyramid` design are
lodged. To give context to discussions that follow, we detail some of the
design decisions and trade-offs here. In some cases, we acknowledge that the
framework can be made better and we describe future steps which will be taken
-to improve it; in some cases we just file the challenge as noted, as
-obviously you can't please everyone all of the time.
+to improve it. In others we just file the challenge as noted, as obviously you
+can't please everyone all of the time.
Pyramid Provides More Than One Way to Do It
-------------------------------------------
A canon of Python popular culture is "TIOOWTDI" ("there is only one way to do
-it", a slighting, tongue-in-cheek reference to Perl's "TIMTOWTDI", which is
-an acronym for "there is more than one way to do it").
-
-:app:`Pyramid` is, for better or worse, a "TIMTOWTDI" system. For example,
-it includes more than one way to resolve a URL to a :term:`view callable`:
-via :term:`url dispatch` or :term:`traversal`. Multiple methods of
-configuration exist: :term:`imperative configuration`, :term:`configuration
-decoration`, and :term:`ZCML` (optionally via :term:`pyramid_zcml`). It works
-with multiple different kinds of persistence and templating systems. And so
-on. However, the existence of most of these overlapping ways to do things
-are not without reason and purpose: we have a number of audiences to serve,
-and we believe that TIMTOWTI at the web framework level actually *prevents* a
-much more insidious and harmful set of duplication at higher levels in the
-Python web community.
-
-:app:`Pyramid` began its life as :mod:`repoze.bfg`, written by a team of
-people with many years of prior :term:`Zope` experience. The idea of
+it", a slighting, tongue-in-cheek reference to Perl's "TIMTOWTDI", which is an
+acronym for "there is more than one way to do it").
+
+:app:`Pyramid` is, for better or worse, a "TIMTOWTDI" system. For example, it
+includes more than one way to resolve a URL to a :term:`view callable`: via
+:term:`url dispatch` or :term:`traversal`. Multiple methods of configuration
+exist: :term:`imperative configuration`, :term:`configuration decoration`, and
+:term:`ZCML` (optionally via :term:`pyramid_zcml`). It works with multiple
+different kinds of persistence and templating systems. And so on. However, the
+existence of most of these overlapping ways to do things are not without reason
+and purpose: we have a number of audiences to serve, and we believe that
+TIMTOWTDI at the web framework level actually *prevents* a much more insidious
+and harmful set of duplication at higher levels in the Python web community.
+
+:app:`Pyramid` began its life as :mod:`repoze.bfg`, written by a team of people
+with many years of prior :term:`Zope` experience. The idea of
:term:`traversal` and the way :term:`view lookup` works was stolen entirely
from Zope. The authorization subsystem provided by :app:`Pyramid` is a
derivative of Zope's. The idea that an application can be *extended* without
forking is also a Zope derivative.
Implementations of these features were *required* to allow the :app:`Pyramid`
-authors to build the bread-and-butter CMS-type systems for customers in the
-way in which they were accustomed. No other system, save for Zope itself,
-had such features, and Zope itself was beginning to show signs of its age.
-We were becoming hampered by consequences of its early design mistakes.
-Zope's lack of documentation was also difficult to work around: it was hard
-to hire smart people to work on Zope applications, because there was no
-comprehensive documentation set to point them at which explained "it all" in
-one consumable place, and it was too large and self-inconsistent to document
-properly. Before :mod:`repoze.bfg` went under development, its authors
-obviously looked around for other frameworks that fit the bill. But no
-non-Zope framework did. So we embarked on building :mod:`repoze.bfg`.
+authors to build the bread-and-butter CMS-type systems for customers in the way
+in which they were accustomed. No other system, save for Zope itself, had such
+features, and Zope itself was beginning to show signs of its age. We were
+becoming hampered by consequences of its early design mistakes. Zope's lack of
+documentation was also difficult to work around. It was hard to hire smart
+people to work on Zope applications because there was no comprehensive
+documentation set which explained "it all" in one consumable place, and it was
+too large and self-inconsistent to document properly. Before :mod:`repoze.bfg`
+went under development, its authors obviously looked around for other
+frameworks that fit the bill. But no non-Zope framework did. So we embarked on
+building :mod:`repoze.bfg`.
As the result of our research, however, it became apparent that, despite the
-fact that no *one* framework had all the features we required, lots of
-existing frameworks had good, and sometimes very compelling ideas. In
-particular, :term:`URL dispatch` is a more direct mechanism to map URLs to
-code.
+fact that no *one* framework had all the features we required, lots of existing
+frameworks had good, and sometimes very compelling ideas. In particular,
+:term:`URL dispatch` is a more direct mechanism to map URLs to code.
So, although we couldn't find a framework, save for Zope, that fit our needs,
and while we incorporated a lot of Zope ideas into BFG, we also emulated the
features we found compelling in other frameworks (such as :term:`url
-dispatch`). After the initial public release of BFG, as time went on,
-features were added to support people allergic to various Zope-isms in the
-system, such as the ability to configure the application using
-:term:`imperative configuration` and :term:`configuration decoration` rather
-than solely using :term:`ZCML`, and the elimination of the required use of
-:term:`interface` objects. It soon became clear that we had a system that
-was very generic, and was beginning to appeal to non-Zope users as well as
-ex-Zope users.
+dispatch`). After the initial public release of BFG, as time went on, features
+were added to support people allergic to various Zope-isms in the system, such
+as the ability to configure the application using :term:`imperative
+configuration` and :term:`configuration decoration`, rather than solely using
+:term:`ZCML`, and the elimination of the required use of :term:`interface`
+objects. It soon became clear that we had a system that was very generic, and
+was beginning to appeal to non-Zope users as well as ex-Zope users.
As the result of this generalization, it became obvious BFG shared 90% of its
-featureset with the featureset of Pylons 1, and thus had a very similar
-target market. Because they were so similar, choosing between the two
-systems was an exercise in frustration for an otherwise non-partisan
-developer. It was also strange for the Pylons and BFG development
-communities to be in competition for the same set of users, given how similar
-the two frameworks were. So the Pylons and BFG teams began to work together
-to form a plan to merge. The features missing from BFG (notably :term:`view
-handler` classes, flash messaging, and other minor missing bits), were added,
-to provide familiarity to ex-Pylons users. The result is :app:`Pyramid`.
-
-The Python web framework space is currently notoriously balkanized. We're
-truly hoping that the amalgamation of components in :app:`Pyramid` will
-appeal to at least two currently very distinct sets of users: Pylons and BFG
-users. By unifying the best concepts from Pylons and BFG into a single
-codebase and leaving the bad concepts from their ancestors behind, we'll be
-able to consolidate our efforts better, share more code, and promote our
-efforts as a unit rather than competing pointlessly. We hope to be able to
-shortcut the pack mentality which results in a *much larger* duplication of
-effort, represented by competing but incredibly similar applications and
-libraries, each built upon a specific low level stack that is incompatible
-with the other. We'll also shrink the choice of credible Python web
-frameworks down by at least one. We're also hoping to attract users from
-other communities (such as Zope's and TurboGears') by providing the features
-they require, while allowing enough flexibility to do things in a familiar
-fashion. Some overlap of functionality to achieve these goals is expected
-and unavoidable, at least if we aim to prevent pointless duplication at
-higher levels. If we've done our job well enough, the various audiences will
-be able to coexist and cooperate rather than firing at each other across some
-imaginary web framework DMZ.
-
-Pyramid Uses A Zope Component Architecture ("ZCA") Registry
+feature set with the feature set of Pylons 1, and thus had a very similar
+target market. Because they were so similar, choosing between the two systems
+was an exercise in frustration for an otherwise non-partisan developer. It was
+also strange for the Pylons and BFG development communities to be in
+competition for the same set of users, given how similar the two frameworks
+were. So the Pylons and BFG teams began to work together to form a plan to
+merge. The features missing from BFG (notably :term:`view handler` classes,
+flash messaging, and other minor missing bits), were added to provide
+familiarity to ex-Pylons users. The result is :app:`Pyramid`.
+
+The Python web framework space is currently notoriously balkanized. We're truly
+hoping that the amalgamation of components in :app:`Pyramid` will appeal to at
+least two currently very distinct sets of users: Pylons and BFG users. By
+unifying the best concepts from Pylons and BFG into a single codebase, and
+leaving the bad concepts from their ancestors behind, we'll be able to
+consolidate our efforts better, share more code, and promote our efforts as a
+unit rather than competing pointlessly. We hope to be able to shortcut the pack
+mentality which results in a *much larger* duplication of effort, represented
+by competing but incredibly similar applications and libraries, each built upon
+a specific low level stack that is incompatible with the other. We'll also
+shrink the choice of credible Python web frameworks down by at least one. We're
+also hoping to attract users from other communities (such as Zope's and
+TurboGears') by providing the features they require, while allowing enough
+flexibility to do things in a familiar fashion. Some overlap of functionality
+to achieve these goals is expected and unavoidable, at least if we aim to
+prevent pointless duplication at higher levels. If we've done our job well
+enough, the various audiences will be able to coexist and cooperate rather than
+firing at each other across some imaginary web framework DMZ.
+
+Pyramid Uses a Zope Component Architecture ("ZCA") Registry
-----------------------------------------------------------
:app:`Pyramid` uses a :term:`Zope Component Architecture` (ZCA) "component
diff --git a/docs/narr/MyProject/development.ini b/docs/narr/MyProject/development.ini
index a9a26e56b..749e574eb 100644
--- a/docs/narr/MyProject/development.ini
+++ b/docs/narr/MyProject/development.ini
@@ -11,7 +11,7 @@ pyramid.debug_authorization = false
pyramid.debug_notfound = false
pyramid.debug_routematch = false
pyramid.default_locale_name = en
-pyramid.includes =
+pyramid.includes =
pyramid_debugtoolbar
# By default, the toolbar only appears for clients from IP addresses
@@ -24,7 +24,7 @@ pyramid.includes =
[server:main]
use = egg:waitress#main
-host = 0.0.0.0
+host = 127.0.0.1
port = 6543
###
@@ -57,4 +57,4 @@ level = NOTSET
formatter = generic
[formatter_generic]
-format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
+format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
diff --git a/docs/narr/MyProject/myproject/templates/mytemplate.pt b/docs/narr/MyProject/myproject/templates/mytemplate.pt
index e6b00a145..65d7f0609 100644
--- a/docs/narr/MyProject/myproject/templates/mytemplate.pt
+++ b/docs/narr/MyProject/myproject/templates/mytemplate.pt
@@ -8,12 +8,12 @@
<meta name="author" content="Pylons Project">
<link rel="shortcut icon" href="${request.static_url('myproject:static/pyramid-16x16.png')}">
- <title>Starter Template for The Pyramid Web Framework</title>
+ <title>Starter Scaffold 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 template -->
+ <!-- Custom styles for this scaffold -->
<link href="${request.static_url('myproject:static/theme.css')}" rel="stylesheet">
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
@@ -33,19 +33,20 @@
</div>
<div class="col-md-10">
<div class="content">
- <h1><span class="font-semi-bold">Pyramid</span> <span class="smaller">starter template</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</span>.</p>
+ <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.6b2</span>.</p>
</div>
</div>
</div>
<div class="row">
<div class="links">
<ul>
- <li class="current-version">Currently v1.5</li>
- <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org">Docs</a></li>
+ <li class="current-version">Generated by v1.6b2</li>
+ <li><i class="glyphicon glyphicon-bookmark icon-muted"></i><a href="http://docs.pylonsproject.org/projects/pyramid/en/1.6-branch/">Docs</a></li>
<li><i class="glyphicon glyphicon-cog icon-muted"></i><a href="https://github.com/Pylons/pyramid">Github Project</a></li>
<li><i class="glyphicon glyphicon-globe icon-muted"></i><a href="irc://irc.freenode.net#pyramid">IRC Channel</a></li>
<li><i class="glyphicon glyphicon-home icon-muted"></i><a href="http://pylonsproject.org">Pylons Project</a></li>
+ </ul>
</div>
</div>
<div class="row">
diff --git a/docs/narr/MyProject/myproject/tests.py b/docs/narr/MyProject/myproject/tests.py
index 8c60407e5..37df08a2a 100644
--- a/docs/narr/MyProject/myproject/tests.py
+++ b/docs/narr/MyProject/myproject/tests.py
@@ -16,31 +16,6 @@ class ViewTests(unittest.TestCase):
info = my_view(request)
self.assertEqual(info['project'], 'MyProject')
-class ViewIntegrationTests(unittest.TestCase):
- def setUp(self):
- """ This sets up the application registry with the
- registrations your application declares in its ``includeme``
- function.
- """
- self.config = testing.setUp()
- self.config.include('myproject')
-
- def tearDown(self):
- """ Clear out the application registry """
- testing.tearDown()
-
- def test_my_view(self):
- from myproject.views import my_view
- request = testing.DummyRequest()
- result = my_view(request)
- self.assertEqual(result.status, '200 OK')
- body = result.app_iter[0]
- self.assertTrue('Welcome to' in body)
- self.assertEqual(len(result.headerlist), 2)
- self.assertEqual(result.headerlist[0],
- ('Content-Type', 'text/html; charset=UTF-8'))
- self.assertEqual(result.headerlist[1], ('Content-Length',
- str(len(body))))
class FunctionalTests(unittest.TestCase):
def setUp(self):
diff --git a/docs/narr/MyProject/production.ini b/docs/narr/MyProject/production.ini
index 9eae9e03f..3ccbe6619 100644
--- a/docs/narr/MyProject/production.ini
+++ b/docs/narr/MyProject/production.ini
@@ -51,4 +51,4 @@ level = NOTSET
formatter = generic
[formatter_generic]
-format = %(asctime)s %(levelname)-5.5s [%(name)s][%(threadName)s] %(message)s
+format = %(asctime)s %(levelname)-5.5s [%(name)s:%(lineno)s][%(threadName)s] %(message)s
diff --git a/docs/narr/MyProject/setup.py b/docs/narr/MyProject/setup.py
index 9f34540a7..8c019af51 100644
--- a/docs/narr/MyProject/setup.py
+++ b/docs/narr/MyProject/setup.py
@@ -1,42 +1,30 @@
-"""Setup for the MyProject package.
-
-"""
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 fp:
- README = fp.read()
-
-
-with open(os.path.join(HERE, 'CHANGES.txt')) as fp:
- CHANGES = fp.read()
+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 = [
+requires = [
'pyramid',
'pyramid_chameleon',
'pyramid_debugtoolbar',
'waitress',
]
-TESTS_REQUIRE = [
- 'webtest'
- ]
-
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',
- ],
+ "Programming Language :: Python",
+ "Framework :: Pyramid",
+ "Topic :: Internet :: WWW/HTTP",
+ "Topic :: Internet :: WWW/HTTP :: WSGI :: Application",
+ ],
author='',
author_email='',
url='',
@@ -44,10 +32,11 @@ setup(name='MyProject',
packages=find_packages(),
include_package_data=True,
zip_safe=False,
- install_requires=REQUIRES,
- tests_require=TESTS_REQUIRE,
- test_suite='myproject',
+ install_requires=requires,
+ tests_require=requires,
+ test_suite="myproject",
entry_points="""\
[paste.app_factory]
main = myproject:main
- """)
+ """,
+ )
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index 25f3931e9..4785b60c4 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -77,7 +77,7 @@ The below example uses the ``pcreate`` command to create a project with the
On UNIX:
-.. code-block:: text
+.. code-block:: bash
$ $VENV/bin/pcreate -s starter MyProject
@@ -90,7 +90,7 @@ Or on Windows:
Here's sample output from a run of ``pcreate`` on UNIX for a project we name
``MyProject``:
-.. code-block:: text
+.. code-block:: bash
$ $VENV/bin/pcreate -s starter MyProject
Creating template pyramid
@@ -158,7 +158,7 @@ created project directory.
On UNIX:
-.. code-block:: text
+.. code-block:: bash
$ cd MyProject
$ $VENV/bin/python setup.py develop
@@ -172,7 +172,7 @@ Or on Windows:
Elided output from a run of this command on UNIX is shown below:
-.. code-block:: text
+.. code-block:: bash
$ cd MyProject
$ $VENV/bin/python setup.py develop
@@ -198,7 +198,7 @@ directory of your virtualenv).
On UNIX:
-.. code-block:: text
+.. code-block:: bash
$ $VENV/bin/python setup.py test -q
@@ -210,7 +210,7 @@ Or on Windows:
Here's sample output from a test run on UNIX:
-.. code-block:: text
+.. code-block:: bash
$ $VENV/bin/python setup.py test -q
running test
@@ -221,11 +221,23 @@ Here's sample output from a test run on UNIX:
writing dependency_links to MyProject.egg-info/dependency_links.txt
writing entry points to MyProject.egg-info/entry_points.txt
reading manifest file 'MyProject.egg-info/SOURCES.txt'
+ reading manifest template 'MANIFEST.in'
+ warning: no files found matching '*.cfg'
+ warning: no files found matching '*.rst'
+ warning: no files found matching '*.ico' under directory 'myproject'
+ warning: no files found matching '*.gif' under directory 'myproject'
+ warning: no files found matching '*.jpg' under directory 'myproject'
+ warning: no files found matching '*.txt' under directory 'myproject'
+ warning: no files found matching '*.mak' under directory 'myproject'
+ warning: no files found matching '*.mako' under directory 'myproject'
+ warning: no files found matching '*.js' under directory 'myproject'
+ warning: no files found matching '*.html' under directory 'myproject'
+ warning: no files found matching '*.xml' under directory 'myproject'
writing manifest file 'MyProject.egg-info/SOURCES.txt'
running build_ext
- ..
+ .
----------------------------------------------------------------------
- Ran 1 test in 0.108s
+ Ran 1 test in 0.008s
OK
@@ -256,7 +268,7 @@ file. In our case, this file is named ``development.ini``.
On UNIX:
-.. code-block:: text
+.. code-block:: bash
$ $VENV/bin/pserve development.ini
@@ -268,38 +280,38 @@ On Windows:
Here's sample output from a run of ``pserve`` on UNIX:
-.. code-block:: text
+.. code-block:: bash
$ $VENV/bin/pserve development.ini
- Starting server in PID 16601.
- serving on http://0.0.0.0:6543
-
-When you use ``pserve`` to start the application implied by the default
-rendering of a scaffold, it will respond to requests on *all* IP addresses
-possessed by your system, not just requests to ``localhost``. This is what the
-``0.0.0.0`` in ``serving on http://0.0.0.0:6543`` means. The server will
-respond to requests made to ``127.0.0.1`` and on any external IP address. For
-example, your system might be configured to have an external IP address
-``192.168.1.50``. If that's the case, if you use a browser running on the same
-system as Pyramid, it will be able to access the application via
-``http://127.0.0.1:6543/`` as well as via ``http://192.168.1.50:6543/``.
-However, *other people* on other computers on the same network will also be
-able to visit your Pyramid application in their browser by visiting
-``http://192.168.1.50:6543/``.
-
-If you want to restrict access such that only a browser running on the same
-machine as Pyramid will be able to access your Pyramid application, edit the
+ Starting server in PID 16208.
+ serving on http://127.0.0.1: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. Change it from ``0.0.0.0`` to ``127.0.0.1``. For
+``[server:main]`` section, changing it from ``127.0.0.1`` to ``0.0.0.0``. For
example:
.. code-block:: ini
[server:main]
use = egg:waitress#main
- host = 127.0.0.1
+ host = 0.0.0.0
port = 6543
+Now when you use ``pserve`` to start the application, it will respond to
+requests on *all* IP addresses possessed by your system, not just requests to
+``localhost``. This is what the ``0.0.0.0`` in
+``serving on http://0.0.0.0:6543`` means. The server will respond to requests
+made to ``127.0.0.1`` and on any external IP address. For example, your system
+might be configured to have an external IP address ``192.168.1.50``. If that's
+the case, if you use a browser running on the same system as Pyramid, it will
+be able to access the application via ``http://127.0.0.1:6543/`` as well as via
+``http://192.168.1.50:6543/``. However, *other people* on other computers on
+the same network will also be able to visit your Pyramid application in their
+browser by visiting ``http://192.168.1.50:6543/``.
+
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]``
@@ -347,7 +359,7 @@ For example, on UNIX:
$ $VENV/bin/pserve development.ini --reload
Starting subprocess with file monitor
Starting server in PID 16601.
- serving on http://0.0.0.0:6543
+ serving on http://127.0.0.1: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:
@@ -357,7 +369,7 @@ files, you'll see the server restart automatically:
development.ini changed; reloading...
-------------------- Restarting --------------------
Starting server in PID 16602.
- serving on http://0.0.0.0:6543
+ serving on http://127.0.0.1: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
@@ -579,18 +591,16 @@ file. The name ``main`` is a convention used by PasteDeploy signifying that it
is the default application.
The ``[server:main]`` section of the configuration file configures a WSGI
-server which listens on TCP port 6543. It is configured to listen on all
-interfaces (``0.0.0.0``). This means that any remote system which has TCP
-access to your system can see your Pyramid application.
+server which listens on TCP port 6543. It is configured to listen on localhost
+only (``127.0.0.1``).
.. _MyProject_ini_logging:
-The sections that live between the markers ``# Begin logging configuration``
-and ``# End logging configuration`` represent Python's standard library
-:mod:`logging` module configuration for your application. The sections between
-these two markers are passed to the `logging module's config file configuration
-engine <http://docs.python.org/howto/logging.html#configuring-logging>`_ when
-the ``pserve`` or ``pshell`` commands are executed. The default configuration
+The sections after ``# logging configuration`` represent Python's standard
+library :mod:`logging` module configuration for your application. These
+sections are passed to the `logging module's config file configuration engine
+<http://docs.python.org/howto/logging.html#configuring-logging>`_ when the
+``pserve`` or ``pshell`` commands are executed. The default configuration
sends application logging output to the standard error output of your terminal.
For more information about logging configuration, see :ref:`logging_chapter`.
@@ -680,8 +690,8 @@ testing, packaging, and distributing your application.
``setup.py`` is the de facto standard which Python developers use to
distribute their reusable code. You can read more about ``setup.py`` files
and their usage in the `Setuptools documentation
- <http://peak.telecommunity.com/DevCenter/setuptools>`_ and `The Hitchhiker's
- Guide to Packaging <http://guide.python-distribute.org/>`_.
+ <http://peak.telecommunity.com/DevCenter/setuptools>`_ and `Python Packaging
+ User Guide <https://packaging.python.org/en/latest/>`_.
Our generated ``setup.py`` looks like this:
@@ -912,7 +922,7 @@ The ``tests.py`` module includes unit tests for your application.
.. literalinclude:: MyProject/myproject/tests.py
:language: python
- :lines: 1-18
+ :lines: 1-17
:linenos:
This sample ``tests.py`` file has a single unit test defined within it. This
diff --git a/docs/narr/scaffolding.rst b/docs/narr/scaffolding.rst
index 8677359de..164ceb3bf 100644
--- a/docs/narr/scaffolding.rst
+++ b/docs/narr/scaffolding.rst
@@ -22,10 +22,10 @@ found by the ``pcreate`` command.
To create a scaffold template, create a Python :term:`distribution` to house
the scaffold which includes a ``setup.py`` that relies on the ``setuptools``
-package. See `Creating a Package
-<http://guide.python-distribute.org/creation.html>`_ for more information about
-how to do this. For example, we'll pretend the distribution you create is
-named ``CoolExtension``, and it has a package directory within it named
+package. See `Packaging and Distributing Projects
+<https://packaging.python.org/en/latest/distributing/>`_ for more information
+about how to do this. For example, we'll pretend the distribution you create
+is named ``CoolExtension``, and it has a package directory within it named
``coolextension``.
Once you've created the distribution, put a "scaffolds" directory within your
diff --git a/docs/narr/startup.rst b/docs/narr/startup.rst
index 485f6b181..3e168eaea 100644
--- a/docs/narr/startup.rst
+++ b/docs/narr/startup.rst
@@ -6,15 +6,15 @@ Startup
When you cause a :app:`Pyramid` application to start up in a console window,
you'll see something much like this show up on the console:
-.. code-block:: text
+.. code-block:: bash
- $ pserve development.ini
- Starting server in PID 16601.
- serving on 0.0.0.0:6543 view at http://127.0.0.1:6543
+ $ $VENV/bin/pserve development.ini
+ Starting server in PID 16305.
+ serving on http://127.0.0.1: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 0.0.0.0:6543 ...`` is output to your console.
+``serving on http://127.0.0.1:6543`` is output to your console.
.. index::
single: startup process
@@ -92,11 +92,11 @@ Here's a high-level time-ordered overview of what happens when you press
In this case, the ``myproject.__init__:main`` function referred to by the
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',
- 'pyramid.debug_routematch':'false', 'pyramid.debug_templates':'true',
- 'pyramid.default_locale_name':'en'}``. See :ref:`environment_chapter` for
- the meanings of these keys.
+ receive the key/value pairs ``{pyramid.reload_templates = true,
+ pyramid.debug_authorization = false, pyramid.debug_notfound = false,
+ pyramid.debug_routematch = false, pyramid.default_locale_name = en, and
+ pyramid.includes = pyramid_debugtoolbar}``. See :ref:`environment_chapter`
+ for the meanings of these keys.
#. The ``main`` function first constructs a
:class:`~pyramid.config.Configurator` instance, passing the ``settings``
@@ -131,10 +131,9 @@ 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 =
- 0.0.0.0``), on port number 6543 (``port = 6543``). The server code itself
- is what prints ``serving on 0.0.0.0:6543 view at http://127.0.0.1:6543``.
- The server serves the application, and the application is running, waiting
- to receive requests.
+ 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.
.. seealso::
Logging configuration is described in the :ref:`logging_chapter` chapter.
diff --git a/docs/narr/testing.rst b/docs/narr/testing.rst
index c05ee41ad..a3f62058b 100644
--- a/docs/narr/testing.rst
+++ b/docs/narr/testing.rst
@@ -348,26 +348,6 @@ code's integration with the rest of :app:`Pyramid`.
See also :ref:`including_configuration`
-Let's demonstrate this by showing an integration test for a view.
-
-Given the following view definition, which assumes that your application's
-:term:`package` name is ``myproject``, and within that :term:`package` there
-exists a module ``views``, which in turn contains a :term:`view` function named
-``my_view``:
-
- .. literalinclude:: MyProject/myproject/views.py
- :linenos:
- :lines: 1-6
- :language: python
-
-You'd then create a ``tests`` module within your ``myproject`` package,
-containing the following test code:
-
- .. literalinclude:: MyProject/myproject/tests.py
- :linenos:
- :pyobject: ViewIntegrationTests
- :language: python
-
Writing unit tests that use the :class:`~pyramid.config.Configurator` API to
set up the right "mock" registrations is often preferred to creating
integration tests. Unit tests will run faster (because they do less for each
@@ -388,22 +368,53 @@ package, which provides APIs for invoking HTTP(S) requests to your application.
Regardless of which testing :term:`package` you use, ensure to add a
``tests_require`` dependency on that package to your application's
-``setup.py`` file:
+``setup.py`` file. Using the project ``MyProject`` generated by the starter
+scaffold as described in :doc:`project`, we would insert the following code immediately following the
+``requires`` block in the file ``MyProject/setup.py``.
- .. literalinclude:: MyProject/setup.py
- :linenos:
- :emphasize-lines: 26-28,48
- :language: python
+.. code-block:: ini
+ :linenos:
+ :lineno-start: 11
+ :emphasize-lines: 8-
+
+ requires = [
+ 'pyramid',
+ 'pyramid_chameleon',
+ 'pyramid_debugtoolbar',
+ 'waitress',
+ ]
+
+ test_requires = [
+ 'webtest',
+ ]
+
+Remember to change the dependency.
+
+.. code-block:: ini
+ :linenos:
+ :lineno-start: 39
+ :emphasize-lines: 2
+
+ install_requires=requires,
+ tests_require=test_requires,
+ test_suite="myproject",
+
+As always, whenever you change your dependencies, make sure to run the
+following command.
+
+.. code-block:: bash
+
+ $VENV/bin/python setup.py develop
-Let us assume your :term:`package` is named ``myproject`` which contains a
-``views`` module, which in turn contains a :term:`view` function ``my_view``
-that returns a HTML body when the root URL is invoked:
+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
:linenos:
:language: python
-Then the following example functional test demonstrates invoking the above
+The following example functional test demonstrates invoking the above
:term:`view`:
.. literalinclude:: MyProject/myproject/tests.py
@@ -414,9 +425,9 @@ Then the following example functional test demonstrates invoking the above
When this test is run, each test method creates a "real" :term:`WSGI`
application using the ``main`` function in your ``myproject.__init__`` module,
using :term:`WebTest` to wrap that WSGI application. It assigns the result to
-``self.testapp``. In the test named ``test_root``. The ``TestApp``'s ``GET``
+``self.testapp``. In the test named ``test_root``, the ``TestApp``'s ``GET``
method is used to invoke the root URL. Finally, an assertion is made that the
-returned HTML contains the text ``MyProject``.
+returned HTML contains the text ``Pyramid``.
See the :term:`WebTest` documentation for further information about the methods
available to a :class:`webtest.app.TestApp` instance.
diff --git a/docs/narr/zca.rst b/docs/narr/zca.rst
index b0e9b1709..784886563 100644
--- a/docs/narr/zca.rst
+++ b/docs/narr/zca.rst
@@ -9,17 +9,16 @@
.. _zca_chapter:
Using the Zope Component Architecture in :app:`Pyramid`
-==========================================================
+=======================================================
-Under the hood, :app:`Pyramid` uses a :term:`Zope Component
-Architecture` component registry as its :term:`application registry`.
-The Zope Component Architecture is referred to colloquially as the
-"ZCA."
+Under the hood, :app:`Pyramid` uses a :term:`Zope Component Architecture`
+component registry as its :term:`application registry`. The Zope Component
+Architecture is referred to colloquially as the "ZCA."
The ``zope.component`` API used to access data in a traditional Zope
-application can be opaque. For example, here is a typical "unnamed
-utility" lookup using the :func:`zope.component.getUtility` global API
-as it might appear in a traditional Zope application:
+application can be opaque. For example, here is a typical "unnamed utility"
+lookup using the :func:`zope.component.getUtility` global API as it might
+appear in a traditional Zope application:
.. code-block:: python
:linenos:
@@ -28,23 +27,21 @@ as it might appear in a traditional Zope application:
from zope.component import getUtility
settings = getUtility(ISettings)
-After this code runs, ``settings`` will be a Python dictionary. But
-it's unlikely that any "civilian" will be able to figure this out just
-by reading the code casually. When the ``zope.component.getUtility``
-API is used by a developer, the conceptual load on a casual reader of
-code is high.
+After this code runs, ``settings`` will be a Python dictionary. But it's
+unlikely that any "civilian" will be able to figure this out just by reading
+the code casually. When the ``zope.component.getUtility`` API is used by a
+developer, the conceptual load on a casual reader of code is high.
-While the ZCA is an excellent tool with which to build a *framework*
-such as :app:`Pyramid`, it is not always the best tool with which
-to build an *application* due to the opacity of the ``zope.component``
-APIs. Accordingly, :app:`Pyramid` tends to hide the presence of the
-ZCA from application developers. You needn't understand the ZCA to
-create a :app:`Pyramid` application; its use is effectively only a
-framework implementation detail.
+While the ZCA is an excellent tool with which to build a *framework* such as
+:app:`Pyramid`, it is not always the best tool with which to build an
+*application* due to the opacity of the ``zope.component`` APIs. Accordingly,
+:app:`Pyramid` tends to hide the presence of the ZCA from application
+developers. You needn't understand the ZCA to create a :app:`Pyramid`
+application; its use is effectively only a framework implementation detail.
-However, developers who are already used to writing :term:`Zope`
-applications often still wish to use the ZCA while building a
-:app:`Pyramid` application; :app:`Pyramid` makes this possible.
+However, developers who are already used to writing :term:`Zope` applications
+often still wish to use the ZCA while building a :app:`Pyramid` application.
+:app:`Pyramid` makes this possible.
.. index::
single: get_current_registry
@@ -52,87 +49,81 @@ applications often still wish to use the ZCA while building a
single: getSiteManager
single: ZCA global API
-Using the ZCA Global API in a :app:`Pyramid` Application
------------------------------------------------------------
-
-:term:`Zope` uses a single ZCA registry -- the "global" ZCA registry
--- for all Zope applications that run in the same Python process,
-effectively making it impossible to run more than one Zope application
-in a single process.
-
-However, for ease of deployment, it's often useful to be able to run more
-than a single application per process. For example, use of a
-:term:`PasteDeploy` "composite" allows you to run separate individual WSGI
-applications in the same process, each answering requests for some URL
-prefix. This makes it possible to run, for example, a TurboGears application
-at ``/turbogears`` and a :app:`Pyramid` application at ``/pyramid``, both
-served up using the same :term:`WSGI` server within a single Python process.
-
-Most production Zope applications are relatively large, making it
-impractical due to memory constraints to run more than one Zope
-application per Python process. However, a :app:`Pyramid` application
-may be very small and consume very little memory, so it's a reasonable
-goal to be able to run more than one :app:`Pyramid` application per
-process.
-
-In order to make it possible to run more than one :app:`Pyramid`
-application in a single process, :app:`Pyramid` defaults to using a
-separate ZCA registry *per application*.
-
-While this services a reasonable goal, it causes some issues when
-trying to use patterns which you might use to build a typical
-:term:`Zope` application to build a :app:`Pyramid` application.
-Without special help, ZCA "global" APIs such as
-:func:`zope.component.getUtility` and :func:`zope.component.getSiteManager`
-will use the ZCA "global" registry. Therefore, these APIs
-will appear to fail when used in a :app:`Pyramid` application,
-because they'll be consulting the ZCA global registry rather than the
-component registry associated with your :app:`Pyramid` application.
-
-There are three ways to fix this: by disusing the ZCA global API
-entirely, by using
-:meth:`pyramid.config.Configurator.hook_zca` or by passing
-the ZCA global registry to the :term:`Configurator` constructor at
-startup time. We'll describe all three methods in this section.
+Using the ZCA global API in a :app:`Pyramid` application
+--------------------------------------------------------
+
+:term:`Zope` uses a single ZCA registry—the "global" ZCA registry—for all Zope
+applications that run in the same Python process, effectively making it
+impossible to run more than one Zope application in a single process.
+
+However, for ease of deployment, it's often useful to be able to run more than
+a single application per process. For example, use of a :term:`PasteDeploy`
+"composite" allows you to run separate individual WSGI applications in the same
+process, each answering requests for some URL prefix. This makes it possible
+to run, for example, a TurboGears application at ``/turbogears`` and a
+:app:`Pyramid` application at ``/pyramid``, both served up using the same
+:term:`WSGI` server within a single Python process.
+
+Most production Zope applications are relatively large, making it impractical
+due to memory constraints to run more than one Zope application per Python
+process. However, a :app:`Pyramid` application may be very small and consume
+very little memory, so it's a reasonable goal to be able to run more than one
+:app:`Pyramid` application per process.
+
+In order to make it possible to run more than one :app:`Pyramid` application in
+a single process, :app:`Pyramid` defaults to using a separate ZCA registry *per
+application*.
+
+While this services a reasonable goal, it causes some issues when trying to use
+patterns which you might use to build a typical :term:`Zope` application to
+build a :app:`Pyramid` application. Without special help, ZCA "global" APIs
+such as :func:`zope.component.getUtility` and
+:func:`zope.component.getSiteManager` will use the ZCA "global" registry.
+Therefore, these APIs will appear to fail when used in a :app:`Pyramid`
+application, because they'll be consulting the ZCA global registry rather than
+the component registry associated with your :app:`Pyramid` application.
+
+There are three ways to fix this: by disusing the ZCA global API entirely, by
+using :meth:`pyramid.config.Configurator.hook_zca` or by passing the ZCA global
+registry to the :term:`Configurator` constructor at startup time. We'll
+describe all three methods in this section.
.. index::
single: request.registry
.. _disusing_the_global_zca_api:
-Disusing the Global ZCA API
+Disusing the global ZCA API
+++++++++++++++++++++++++++
ZCA "global" API functions such as ``zope.component.getSiteManager``,
``zope.component.getUtility``, :func:`zope.component.getAdapter`, and
:func:`zope.component.getMultiAdapter` aren't strictly necessary. Every
-component registry has a method API that offers the same
-functionality; it can be used instead. For example, presuming the
-``registry`` value below is a Zope Component Architecture component
-registry, the following bit of code is equivalent to
-``zope.component.getUtility(IFoo)``:
+component registry has a method API that offers the same functionality; it can
+be used instead. For example, presuming the ``registry`` value below is a Zope
+Component Architecture component registry, the following bit of code is
+equivalent to ``zope.component.getUtility(IFoo)``:
.. code-block:: python
registry.getUtility(IFoo)
-The full method API is documented in the ``zope.component`` package,
-but it largely mirrors the "global" API almost exactly.
+The full method API is documented in the ``zope.component`` package, but it
+largely mirrors the "global" API almost exactly.
-If you are willing to disuse the "global" ZCA APIs and use the method
-interface of a registry instead, you need only know how to obtain the
-:app:`Pyramid` component registry.
+If you are willing to disuse the "global" ZCA APIs and use the method interface
+of a registry instead, you need only know how to obtain the :app:`Pyramid`
+component registry.
There are two ways of doing so:
-- use the :func:`pyramid.threadlocal.get_current_registry`
- function within :app:`Pyramid` view or resource code. This will
- always return the "current" :app:`Pyramid` application registry.
+- use the :func:`pyramid.threadlocal.get_current_registry` function within
+ :app:`Pyramid` view or resource code. This will always return the "current"
+ :app:`Pyramid` application registry.
-- use the attribute of the :term:`request` object named ``registry``
- in your :app:`Pyramid` view code, eg. ``request.registry``. This
- is the ZCA component registry related to the running
- :app:`Pyramid` application.
+- use the attribute of the :term:`request` object named ``registry`` in your
+ :app:`Pyramid` view code, e.g., ``request.registry``. This is the ZCA
+ component registry related to the running :app:`Pyramid` application.
See :ref:`threadlocals_chapter` for more information about
:func:`pyramid.threadlocal.get_current_registry`.
@@ -142,7 +133,7 @@ See :ref:`threadlocals_chapter` for more information about
.. _hook_zca:
-Enabling the ZCA Global API by Using ``hook_zca``
+Enabling the ZCA global API by using ``hook_zca``
+++++++++++++++++++++++++++++++++++++++++++++++++
Consider the following bit of idiomatic :app:`Pyramid` startup code:
@@ -157,34 +148,31 @@ Consider the following bit of idiomatic :app:`Pyramid` startup code:
config.include('some.other.package')
return config.make_wsgi_app()
-When the ``app`` function above is run, a :term:`Configurator` is
-constructed. When the configurator is created, it creates a *new*
-:term:`application registry` (a ZCA component registry). A new
-registry is constructed whenever the ``registry`` argument is omitted
-when a :term:`Configurator` constructor is called, or when a
-``registry`` argument with a value of ``None`` is passed to a
-:term:`Configurator` constructor.
-
-During a request, the application registry created by the Configurator
-is "made current". This means calls to
-:func:`~pyramid.threadlocal.get_current_registry` in the thread
-handling the request will return the component registry associated
-with the application.
-
-As a result, application developers can use ``get_current_registry``
-to get the registry and thus get access to utilities and such, as per
-:ref:`disusing_the_global_zca_api`. But they still cannot use the
-global ZCA API. Without special treatment, the ZCA global APIs will
-always return the global ZCA registry (the one in
-``zope.component.globalregistry.base``).
-
-To "fix" this and make the ZCA global APIs use the "current"
-:app:`Pyramid` registry, you need to call
-:meth:`~pyramid.config.Configurator.hook_zca` within your setup code.
-For example:
+When the ``app`` function above is run, a :term:`Configurator` is constructed.
+When the configurator is created, it creates a *new* :term:`application
+registry` (a ZCA component registry). A new registry is constructed whenever
+the ``registry`` argument is omitted, when a :term:`Configurator` constructor
+is called, or when a ``registry`` argument with a value of ``None`` is passed
+to a :term:`Configurator` constructor.
+
+During a request, the application registry created by the Configurator is "made
+current". This means calls to
+:func:`~pyramid.threadlocal.get_current_registry` in the thread handling the
+request will return the component registry associated with the application.
+
+As a result, application developers can use ``get_current_registry`` to get the
+registry and thus get access to utilities and such, as per
+:ref:`disusing_the_global_zca_api`. But they still cannot use the global ZCA
+API. Without special treatment, the ZCA global APIs will always return the
+global ZCA registry (the one in ``zope.component.globalregistry.base``).
+
+To "fix" this and make the ZCA global APIs use the "current" :app:`Pyramid`
+registry, you need to call :meth:`~pyramid.config.Configurator.hook_zca` within
+your setup code. For example:
.. code-block:: python
:linenos:
+ :emphasize-lines: 5
from pyramid.config import Configurator
@@ -194,9 +182,9 @@ For example:
config.include('some.other.application')
return config.make_wsgi_app()
-We've added a line to our original startup code, line number 6, which
-calls ``config.hook_zca()``. The effect of this line under the hood
-is that an analogue of the following code is executed:
+We've added a line to our original startup code, line number 5, which calls
+``config.hook_zca()``. The effect of this line under the hood is that an
+analogue of the following code is executed:
.. code-block:: python
:linenos:
@@ -205,17 +193,15 @@ is that an analogue of the following code is executed:
from pyramid.threadlocal import get_current_registry
getSiteManager.sethook(get_current_registry)
-This causes the ZCA global API to start using the :app:`Pyramid`
-application registry in threads which are running a :app:`Pyramid`
-request.
+This causes the ZCA global API to start using the :app:`Pyramid` application
+registry in threads which are running a :app:`Pyramid` request.
-Calling ``hook_zca`` is usually sufficient to "fix" the problem of
-being able to use the global ZCA API within a :app:`Pyramid`
-application. However, it also means that a Zope application that is
-running in the same process may start using the :app:`Pyramid`
-global registry instead of the Zope global registry, effectively
-inverting the original problem. In such a case, follow the steps in
-the next section, :ref:`using_the_zca_global_registry`.
+Calling ``hook_zca`` is usually sufficient to "fix" the problem of being able
+to use the global ZCA API within a :app:`Pyramid` application. However, it
+also means that a Zope application that is running in the same process may
+start using the :app:`Pyramid` global registry instead of the Zope global
+registry, effectively inverting the original problem. In such a case, follow
+the steps in the next section, :ref:`using_the_zca_global_registry`.
.. index::
single: get_current_registry
@@ -224,14 +210,15 @@ the next section, :ref:`using_the_zca_global_registry`.
.. _using_the_zca_global_registry:
-Enabling the ZCA Global API by Using The ZCA Global Registry
+Enabling the ZCA global API by using the ZCA global registry
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-You can tell your :app:`Pyramid` application to use the ZCA global
-registry at startup time instead of constructing a new one:
+You can tell your :app:`Pyramid` application to use the ZCA global registry at
+startup time instead of constructing a new one:
.. code-block:: python
:linenos:
+ :emphasize-lines: 5-7
from zope.component import getGlobalSiteManager
from pyramid.config import Configurator
@@ -243,16 +230,14 @@ registry at startup time instead of constructing a new one:
config.include('some.other.application')
return config.make_wsgi_app()
-Lines 5, 6, and 7 above are the interesting ones. Line 5 retrieves
-the global ZCA component registry. Line 6 creates a
-:term:`Configurator`, passing the global ZCA registry into its
-constructor as the ``registry`` argument. Line 7 "sets up" the global
-registry with Pyramid-specific registrations; this is code that is
-normally executed when a registry is constructed rather than created,
+Lines 5, 6, and 7 above are the interesting ones. Line 5 retrieves the global
+ZCA component registry. Line 6 creates a :term:`Configurator`, passing the
+global ZCA registry into its constructor as the ``registry`` argument. Line 7
+"sets up" the global registry with Pyramid-specific registrations; this is code
+that is normally executed when a registry is constructed rather than created,
but we must call it "by hand" when we pass an explicit registry.
-At this point, :app:`Pyramid` will use the ZCA global registry
-rather than creating a new application-specific registry; since by
-default the ZCA global API will use this registry, things will work as
-you might expect a Zope app to when you use the global ZCA API.
-
+At this point, :app:`Pyramid` will use the ZCA global registry rather than
+creating a new application-specific registry. Since by default the ZCA global
+API will use this registry, things will work as you might expect in a Zope app
+when you use the global ZCA API.