summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2016-02-22 21:36:00 -0600
committerMichael Merickel <michael@merickel.org>2016-02-22 21:36:00 -0600
commit605a6eb8ca75caa27ea6cb445624628d99bf2c0b (patch)
tree6df997a45a234d7ac6c0898d0a8a1cfdebfb76f0 /docs
parent252fa52ee7628253dfec7636f4e55b8124efea2a (diff)
parentaa6e5fe4f1190e6df123e3f6ccde9deb789eb344 (diff)
downloadpyramid-605a6eb8ca75caa27ea6cb445624628d99bf2c0b.tar.gz
pyramid-605a6eb8ca75caa27ea6cb445624628d99bf2c0b.tar.bz2
pyramid-605a6eb8ca75caa27ea6cb445624628d99bf2c0b.zip
Merge branch 'master' into feature.invoke_exception_view
Diffstat (limited to 'docs')
-rw-r--r--docs/designdefense.rst188
-rw-r--r--docs/glossary.rst23
-rw-r--r--docs/narr/i18n.rst8
3 files changed, 112 insertions, 107 deletions
diff --git a/docs/designdefense.rst b/docs/designdefense.rst
index d33ae2fd8..28da84368 100644
--- a/docs/designdefense.rst
+++ b/docs/designdefense.rst
@@ -1283,7 +1283,7 @@ predictability.
.. _routes_need_ordering:
-Routes Need Relative Ordering
+Routes need relative ordering
+++++++++++++++++++++++++++++
Consider the following simple `Groundhog
@@ -1311,8 +1311,8 @@ Consider the following simple `Groundhog
app.run()
If you run this application and visit the URL ``/admin``, you will see the
-"admin" page. This is the intended result. However, what if you rearrange
-the order of the function definitions in the file?
+"admin" page. This is the intended result. However, what if you rearrange the
+order of the function definitions in the file?
.. code-block:: python
:linenos:
@@ -1335,11 +1335,11 @@ the order of the function definitions in the file?
if __name__ == '__main__':
app.run()
-If you run this application and visit the URL ``/admin``, you will now be
-returned a 404 error. This is probably not what you intended. The reason
-you see a 404 error when you rearrange function definition ordering is that
-routing declarations expressed via our microframework's routing decorators
-have an *ordering*, and that ordering matters.
+If you run this application and visit the URL ``/admin``, your app will now
+return a 404 error. This is probably not what you intended. The reason you see
+a 404 error when you rearrange function definition ordering is that routing
+declarations expressed via our microframework's routing decorators have an
+*ordering*, and that ordering matters.
In the first case, where we achieved the expected result, we first added a
route with the pattern ``/admin``, then we added a route with the pattern
@@ -1347,65 +1347,67 @@ route with the pattern ``/admin``, then we added a route with the pattern
scope. When a request with a ``PATH_INFO`` of ``/admin`` enters our
application, the web framework loops over each of our application's route
patterns in the order in which they were defined in our module. As a result,
-the view associated with the ``/admin`` routing pattern will be invoked: it
-matches first. All is right with the world.
+the view associated with the ``/admin`` routing pattern will be invoked because
+it matches first. All is right with the world.
In the second case, where we did not achieve the expected result, we first
added a route with the pattern ``/:action``, then we added a route with the
pattern ``/admin``. When a request with a ``PATH_INFO`` of ``/admin`` enters
our application, the web framework loops over each of our application's route
patterns in the order in which they were defined in our module. As a result,
-the view associated with the ``/:action`` routing pattern will be invoked: it
-matches first. A 404 error is raised. This is not what we wanted; it just
-happened due to the order in which we defined our view functions.
-
-This is because Groundhog routes are added to the routing map in import
-order, and matched in the same order when a request comes in. Bottle, like
-Groundhog, as of this writing, matches routes in the order in which they're
-defined at Python execution time. Flask, on the other hand, does not order
-route matching based on import order; it reorders the routes you add to your
-application based on their "complexity". Other microframeworks have varying
+the view associated with the ``/:action`` routing pattern will be invoked
+because it matches first. A 404 error is raised. This is not what we wanted; it
+just happened due to the order in which we defined our view functions.
+
+This is because Groundhog routes are added to the routing map in import order,
+and matched in the same order when a request comes in. Bottle, like Groundhog,
+as of this writing, matches routes in the order in which they're defined at
+Python execution time. Flask, on the other hand, does not order route matching
+based on import order. Instead it reorders the routes you add to your
+application based on their "complexity". Other microframeworks have varying
strategies to do route ordering.
Your application may be small enough where route ordering will never cause an
-issue. If your application becomes large enough, however, being able to
-specify or predict that ordering as your application grows larger will be
-difficult. At some point, you will likely need to more explicitly start
-controlling route ordering, especially in applications that require
-extensibility.
+issue. If your application becomes large enough, however, being able to specify
+or predict that ordering as your application grows larger will be difficult.
+At some point, you will likely need to start controlling route ordering more
+explicitly, especially in applications that require extensibility.
If your microframework orders route matching based on complexity, you'll need
to understand what is meant by "complexity", and you'll need to attempt to
-inject a "less complex" route to have it get matched before any "more
-complex" one to ensure that it's tried first.
+inject a "less complex" route to have it get matched before any "more complex"
+one to ensure that it's tried first.
If your microframework orders its route matching based on relative
import/execution of function decorator definitions, you will need to ensure
-you execute all of these statements in the "right" order, and you'll need to
-be cognizant of this import/execution ordering as you grow your application
-or try to extend it. This is a difficult invariant to maintain for all but
-the smallest applications.
-
-In either case, your application must import the non-``__main__`` modules
-which contain configuration decorations somehow for their configuration to be
-executed. Does that make you a little uncomfortable? It should, because
+that you execute all of these statements in the "right" order, and you'll need
+to be cognizant of this import/execution ordering as you grow your application
+or try to extend it. This is a difficult invariant to maintain for all but the
+smallest applications.
+
+In either case, your application must import the non-``__main__`` modules which
+contain configuration decorations somehow for their configuration to be
+executed. Does that make you a little uncomfortable? It should, because
:ref:`you_dont_own_modulescope`.
Pyramid uses neither decorator import time ordering nor does it attempt to
-divine the relative complexity of one route to another in order to define a
-route match ordering. In Pyramid, you have to maintain relative route
-ordering imperatively via the chronology of multiple executions of the
-:meth:`pyramid.config.Configurator.add_route` method. The order in which you
+divine the relative complexity of one route to another as a means to define a
+route match ordering. In Pyramid, you have to maintain relative route ordering
+imperatively via the chronology of multiple executions of the
+:meth:`pyramid.config.Configurator.add_route` method. The order in which you
repeatedly call ``add_route`` becomes the order of route matching.
If needing to maintain this imperative ordering truly bugs you, you can use
-:term:`traversal` instead of route matching, which is a completely
-declarative (and completely predictable) mechanism to map code to URLs.
-While URL dispatch is easier to understand for small non-extensible
-applications, traversal is a great fit for very large applications and
-applications that need to be arbitrarily extensible.
+:term:`traversal` instead of route matching, which is a completely declarative
+(and completely predictable) mechanism to map code to URLs. While URL dispatch
+is easier to understand for small non-extensible applications, traversal is a
+great fit for very large applications and applications that need to be
+arbitrarily extensible.
-"Stacked Object Proxies" Are Too Clever / Thread Locals Are A Nuisance
+
+.. _thread_local_nuisance:
+
+"Stacked object proxies" are too clever / thread locals are a nuisance
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Some microframeworks use the ``import`` statement to get a handle to an
@@ -1448,32 +1450,35 @@ code below:
for i in range(10):
print(i)
-By its nature, the *request* object created as the result of a WSGI server's
-call into a long-lived web framework cannot be global, because the lifetime
-of a single request will be much shorter than the lifetime of the process
-running the framework. A request object created by a web framework actually
-has more similarity to the ``i`` loop counter in our example above than it
-has to any comparable importable object defined in the Python standard
+By its nature, the *request* object that is created as the result of a WSGI
+server's call into a long-lived web framework cannot be global, because the
+lifetime of a single request will be much shorter than the lifetime of the
+process running the framework. A request object created by a web framework
+actually has more similarity to the ``i`` loop counter in our example above
+than it has to any comparable importable object defined in the Python standard
library or in normal library code.
However, systems which use stacked object proxies promote locally scoped
-objects such as ``request`` out to module scope, for the purpose of being
+objects, such as ``request``, out to module scope, for the purpose of being
able to offer users a nice spelling involving ``import``. They, for what I
-consider dubious reasons, would rather present to their users the canonical
-way of getting at a ``request`` as ``from framework import request`` instead
-of a saner ``from myframework.threadlocals import get_request; request =
-get_request()`` even though the latter is more explicit.
+consider dubious reasons, would rather present to their users the canonical way
+of getting at a ``request`` as ``from framework import request`` instead of a
+saner ``from myframework.threadlocals import get_request; request =
+get_request()``, even though the latter is more explicit.
It would be *most* explicit if the microframeworks did not use thread local
-variables at all. Pyramid view functions are passed a request object; many
-of Pyramid's APIs require that an explicit request object be passed to them.
-It is *possible* to retrieve the current Pyramid request as a threadlocal
-variable but it is a "in case of emergency, break glass" type of activity.
-This explicitness makes Pyramid view functions more easily unit testable, as
-you don't need to rely on the framework to manufacture suitable "dummy"
-request (and other similarly-scoped) objects during test setup. It also
-makes them more likely to work on arbitrary systems, such as async servers
-that do no monkeypatching.
+variables at all. Pyramid view functions are passed a request object. Many of
+Pyramid's APIs require that an explicit request object be passed to them. It is
+*possible* to retrieve the current Pyramid request as a threadlocal variable,
+but it is an "in case of emergency, break glass" type of activity. This
+explicitness makes Pyramid view functions more easily unit testable, as you
+don't need to rely on the framework to manufacture suitable "dummy" request
+(and other similarly-scoped) objects during test setup. It also makes them
+more likely to work on arbitrary systems, such as async servers, that do no
+monkeypatching.
+
+
+.. _explicitly_wsgi:
Explicitly WSGI
+++++++++++++++
@@ -1487,35 +1492,35 @@ import a WSGI server and use it to serve up their Pyramid application as per
the documentation of that WSGI server.
The extra lines saved by abstracting away the serving step behind ``run()``
-seem to have driven dubious second-order decisions related to API in some
-microframeworks. For example, Bottle contains a ``ServerAdapter`` subclass
-for each type of WSGI server it supports via its ``app.run()`` mechanism.
-This means that there exists code in ``bottle.py`` that depends on the
-following modules: ``wsgiref``, ``flup``, ``paste``, ``cherrypy``, ``fapws``,
+seems to have driven dubious second-order decisions related to its API in some
+microframeworks. For example, Bottle contains a ``ServerAdapter`` subclass for
+each type of WSGI server it supports via its ``app.run()`` mechanism. This
+means that there exists code in ``bottle.py`` that depends on the following
+modules: ``wsgiref``, ``flup``, ``paste``, ``cherrypy``, ``fapws``,
``tornado``, ``google.appengine``, ``twisted.web``, ``diesel``, ``gevent``,
-``gunicorn``, ``eventlet``, and ``rocket``. You choose the kind of server
-you want to run by passing its name into the ``run`` method. In theory, this
-sounds great: I can try Bottle out on ``gunicorn`` just by passing in a name!
-However, to fully test Bottle, all of these third-party systems must be
-installed and functional; the Bottle developers must monitor changes to each
-of these packages and make sure their code still interfaces properly with
-them. This expands the packages required for testing greatly; this is a
-*lot* of requirements. It is likely difficult to fully automate these tests
-due to requirements conflicts and build issues.
+``gunicorn``, ``eventlet``, and ``rocket``. You choose the kind of server you
+want to run by passing its name into the ``run`` method. In theory, this sounds
+great: I can try out Bottle on ``gunicorn`` just by passing in a name! However,
+to fully test Bottle, all of these third-party systems must be installed and
+functional. The Bottle developers must monitor changes to each of these
+packages and make sure their code still interfaces properly with them. This
+increases the number of packages required for testing greatly; this is a *lot*
+of requirements. It is likely difficult to fully automate these tests due to
+requirements conflicts and build issues.
As a result, for single-file apps, we currently don't bother to offer a
-``run()`` shortcut; we tell folks to import their WSGI server of choice and
-run it by hand. For the people who want a server abstraction layer, we
-suggest that they use PasteDeploy. In PasteDeploy-based systems, the onus
-for making sure that the server can interface with a WSGI application is
-placed on the server developer, not the web framework developer, making it
-more likely to be timely and correct.
-
-Wrapping Up
+``run()`` shortcut. We tell folks to import their WSGI server of choice and run
+it by hand. For the people who want a server abstraction layer, we suggest that
+they use PasteDeploy. In PasteDeploy-based systems, the onus for making sure
+that the server can interface with a WSGI application is placed on the server
+developer, not the web framework developer, making it more likely to be timely
+and correct.
+
+Wrapping up
+++++++++++
-Here's a diagrammed version of the simplest pyramid application, where
-comments take into account what we've discussed in the
+Here's a diagrammed version of the simplest pyramid application, where the
+inlined comments take into account what we've discussed in the
:ref:`microframeworks_smaller_hello_world` section.
.. code-block:: python
@@ -1526,16 +1531,17 @@ comments take into account what we've discussed in the
def hello_world(request): # accepts a request; no request thread local reqd
# explicit response object means no response threadlocal
- return Response('Hello world!')
+ return Response('Hello world!')
if __name__ == '__main__':
from pyramid.config import Configurator
- config = Configurator() # no global application object.
+ config = Configurator() # no global application object
config.add_view(hello_world) # explicit non-decorator registration
app = config.make_wsgi_app() # explicitly WSGI
server = make_server('0.0.0.0', 8080, app)
server.serve_forever() # explicitly WSGI
+
Pyramid Doesn't Offer Pluggable Apps
------------------------------------
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 2683ff369..bbc86db41 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -367,13 +367,13 @@ Glossary
file. It was developed by Ian Bicking.
Chameleon
- `chameleon <http://chameleon.repoze.org>`_ is an attribute language
- template compiler which supports the :term:`ZPT` templating
- specification. It is written and maintained by Malthe Borch. It has
- several extensions, such as the ability to use bracketed (Mako-style)
- ``${name}`` syntax. It is also much faster than the reference
- implementation of ZPT. :app:`Pyramid` offers Chameleon templating out
- of the box in ZPT and text flavors.
+ `chameleon <https://chameleon.readthedocs.org/en/latest/>`_ is an
+ attribute language template compiler which supports the :term:`ZPT`
+ templating specification. It is written and maintained by Malthe Borch. It
+ has several extensions, such as the ability to use bracketed (Mako-style)
+ ``${name}`` syntax. It is also much faster than the reference
+ implementation of ZPT. :app:`Pyramid` offers Chameleon templating out of
+ the box in ZPT and text flavors.
ZPT
The `Zope Page Template <http://wiki.zope.org/ZPT/FrontPage>`_
@@ -815,11 +815,10 @@ Glossary
library, used by the :app:`Pyramid` translation machinery.
Babel
- A `collection of tools <http://babel.edgewall.org/>`_ for
- internationalizing Python applications. :app:`Pyramid` does
- not depend on Babel to operate, but if Babel is installed,
- additional locale functionality becomes available to your
- application.
+ A `collection of tools <http://babel.pocoo.org/en/latest/>`_ for
+ internationalizing Python applications. :app:`Pyramid` does not depend on
+ Babel to operate, but if Babel is installed, additional locale
+ functionality becomes available to your application.
Lingua
A package by Wichert Akkerman which provides the ``pot-create``
diff --git a/docs/narr/i18n.rst b/docs/narr/i18n.rst
index ecc48aa2b..839a48df4 100644
--- a/docs/narr/i18n.rst
+++ b/docs/narr/i18n.rst
@@ -585,10 +585,10 @@ Performing Date Formatting and Currency Formatting
:app:`Pyramid` does not itself perform date and currency formatting for
different locales. However, :term:`Babel` can help you do this via the
:class:`babel.core.Locale` class. The `Babel documentation for this class
-<http://babel.edgewall.org/wiki/ApiDocs/babel.core#babel.core:Locale>`_
-provides minimal information about how to perform date and currency related
-locale operations. See :ref:`installing_babel` for information about how to
-install Babel.
+<http://babel.pocoo.org/en/latest/api/core.html#basic-interface>`_ provides
+minimal information about how to perform date and currency related locale
+operations. See :ref:`installing_babel` for information about how to install
+Babel.
The :class:`babel.core.Locale` class requires a :term:`locale name` as an
argument to its constructor. You can use :app:`Pyramid` APIs to obtain the