summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcewing <cris@crisewing.com>2017-05-23 20:21:07 -0700
committercewing <cris@crisewing.com>2017-05-23 20:21:07 -0700
commitf20a018167a19d17527d40c027e6f9045749f065 (patch)
treec965d5dc2050111d4c90386c15b6b5ad5816b736
parent52ff50f75d265a4c7d04db538c26b61ab05677c6 (diff)
downloadpyramid-f20a018167a19d17527d40c027e6f9045749f065.tar.gz
pyramid-f20a018167a19d17527d40c027e6f9045749f065.tar.bz2
pyramid-f20a018167a19d17527d40c027e6f9045749f065.zip
fixes per code review, Thanks @stevepiercy.
-rw-r--r--docs/glossary.rst33
-rw-r--r--docs/narr/advanced-features.rst (renamed from docs/narr/advfeatures.rst)147
-rw-r--r--docs/narr/introduction.rst2
3 files changed, 116 insertions, 66 deletions
diff --git a/docs/glossary.rst b/docs/glossary.rst
index 2e5276554..9031ede04 100644
--- a/docs/glossary.rst
+++ b/docs/glossary.rst
@@ -751,7 +751,7 @@ Glossary
:ref:`Venusian` is a library which
allows framework authors to defer decorator actions. Instead of
taking actions when a function (or class) decorator is executed
- at import time, the action usually taken by the decorator is
+ at :term:`import time`, the action usually taken by the decorator is
deferred until a separate "scan" phase. :app:`Pyramid` relies
on Venusian to provide a basis for its :term:`scan` feature.
@@ -1172,3 +1172,34 @@ Glossary
A policy which wraps the :term:`router` by creating the request object
and sending it through the request pipeline.
See :class:`pyramid.config.Configurator.set_execution_policy`.
+
+ singleton
+ A singleton is a class which will only ever have one instance.
+ As there is only one, it is shared by all other code.
+ This makes it an example of :term:`global state`.
+
+ Using a singleton is `considered a poor design choice. <https://softwareengineering.stackexchange.com/questions/148108/why-is-global-state-so-evil>`_
+ As :term:`mutable` global state, it can be changed by any other code,
+ and so the values it represents cannot be reasoned about or tested properly.
+
+ global state
+ A set of values that are available to the entirety of a program.
+
+ mutable
+ In Python, a value is mutable if it can be changed *in place*.
+ The Python ``list`` and ``dict`` types are mutable.
+ When a value is added to or removed from an instance of either, the original object remains.
+ The opposite of mutable is :term:`immutable`.
+
+ immutable
+ In Python, a value is immutable if it cannot be changed.
+ The Python ``str``, ``int``, and ``tuple`` data types are all ``immutable``.
+
+ import time
+ In Python, the moment when a module is referred to in an ``import`` statement.
+ At this moment, all statements in that module at the module scope (at the left margin) are executed.
+ It is a bad design decision to put statements in a Python module that have :term:`side effect`\ s at import time.
+
+ side effect
+ A statement or function has a side effect when it changes a value outside its own scope.
+ Put another way, if one can observe the change made by a function from outside that function, it has a side effect.
diff --git a/docs/narr/advfeatures.rst b/docs/narr/advanced-features.rst
index 5c45cf61a..a97d4f3b1 100644
--- a/docs/narr/advfeatures.rst
+++ b/docs/narr/advanced-features.rst
@@ -8,44 +8,49 @@ frameworks can suffer.
You Don't Need Singletons
-------------------------
-Have you ever struggled with parametrizing Django's ``settings.py`` file for
+Have you ever struggled with parameterizing Django's ``settings.py`` file for
multiple installations of the same Django application? Have you ever needed to
monkey-patch a framework fixture to get it to behave properly for your
-use-case? Have you ever tried to deploy your application using an asynchronous
+use case? Have you ever tried to deploy your application using an asynchronous
server and failed?
-All these problems are symptoms of "mutable global state", also known as
-"import-time side effects" and arise from the use of "singleton" data structures.
+All these problems are symptoms of :term:`mutable` :term:`global state`, also
+known as :term:`import time` :term:`side effect`\ s and arise from the use of
+:term:`singleton` data structures.
:app:`Pyramid` is written so that you don't run into these types of problems.
It is even possible to run multiple copies of the *same* :app:`Pyramid`
application configured differently within a single Python process. This makes
-running Pyramid in shared hosting environments a snap.
+running :app:`Pyramid` in shared hosting environments a snap.
Simplify your View Code with Predicates
---------------------------------------
How many times have you found yourself beginning the logic of your view code
-with something like this::
+with something like this:
+
+.. code-block:: python
if request.user.is_authenticated:
# do one thing
else:
# do something else
-Unlike many other systems, Pyramid allows you to associate more than one view
+Unlike many other systems, :app:`Pyramid` allows you to associate more than one view
with a single route. For example, you can create a route with the pattern
``/items`` and when the route is matched, you can send the request to one view
if the request method is GET, another view if the request method is POST, and
so on.
-:app:`Pyramid` uses a system of "view predicates" to allow this. Matching the
-request method is one basic thing you can do with a view predicate. You can
-also associate views with other request parameters, such as elements in the
-query string, the Accept header, whether the request is an XHR request or not,
-and lots of other things.
+:app:`Pyramid` uses a system of :term:`view predicate`\ s to allow this.
+Matching the request method is one basic thing you can do with a
+:term:`view predicate`. You can also associate views with other request
+parameters, such as elements in the query string, the Accept header, whether
+the request is an AJAX (XHR) request or not, and lots of other things.
-For our example above, you can do this instead::
+For our example above, you can do this instead:
+
+.. code-block:: python
@view_config(route_name="items", effective_principals=pyramid.security.Authenticated)
def auth_view(request):
@@ -58,15 +63,17 @@ For our example above, you can do this instead::
This approach allows you to develop view code that is simpler, more easily
understandable, and more directly testable.
-Example: :ref:`view_configuration_parameters`.
+.. seealso::
+
+ See also :ref:`view_configuration_parameters`.
Stop Worrying About Transactions
--------------------------------
-Pyramid's :term:`scaffold` system renders projects that include a *transaction
+:app:`Pyramid`\ 's :term:`cookiecutter`\ s render projects that include a *transaction
management* system. When you use this system, you can stop worrying about when
to commit your changes, :app:`Pyramid` handles it for you. The system will
-commit at the end of a request or aborts if there was an exception.
+commit at the end of a request or abort if there was an exception.
Why is that a good thing? Imagine a situation where you manually commit a
change to your persistence layer. It's very likely that other framework code
@@ -74,16 +81,18 @@ will run *after* your changes are done. If an error happens in that other code,
you can easily wind up with inconsistent data if you're not extremely careful.
Using transaction management saves you from needing to think about this. Either
-a request completes successfully, and all changes are committed, or it does
-not, and all changes are aborted.
+a request completes successfully and all changes are committed, or it does
+not and all changes are aborted.
Pyramid's transaction management is extendable, so you can synchronize commits
-between multiple databases, or databases of different kinds. It also allows you
-to do things like conditionally send email if a transaction commits, but
+between multiple databases or databases of different kinds. It also allows you
+to do things like conditionally send email if a transaction is committed, but
otherwise keep quiet.
-Example: :ref:`bfg_sql_wiki_tutorial` (note the lack of commit statements
-anywhere in application code).
+.. seealso::
+
+ See also :ref:`bfg_sql_wiki_tutorial` (note the lack of commit statements
+ anywhere in application code).
Stop Worrying About Configuration
---------------------------------
@@ -92,17 +101,19 @@ When a system is small, it's reasonably easy to keep it all in your head. But
as systems grow large, configuration grows more complex. Your app may grow to
have hundreds or even thousands of configuration statements.
-Pyramid's configuration system keeps track of your configuration. If you
-accidentally add two that are identical, or Pyramid can't make sense out of
+:app:`Pyramid`\ 's configuration system keeps track of each of your statements. If you
+accidentally add two that are identical, or :app:`Pyramid` can't make sense out of
what it would mean to have both statements active at the same time, it will
complain loudly at startup time.
-Pyramid's configuration system is not dumb though. If you use the confugration
+:app:`Pyramid`\ 's configuration system is not dumb though. If you use the
:meth:`~pyramid.config.Configurator.include` system, it can automatically
-resolve conflicts on its own. "More local" statements are preferred over "less
-local" ones. So you can intelligently factor large systems into smaller ones.
+resolve conflicts on its own. More local statements are preferred over less
+local ones. So you can intelligently factor large systems into smaller ones.
-Example: :ref:`conflict_detection`.
+.. seealso::
+
+ See also :ref:`conflict_detection`.
Compose Powerful Apps From Simple Parts
----------------------------------------
@@ -110,7 +121,7 @@ Compose Powerful Apps From Simple Parts
Speaking of the :app:`Pyramid` structured "include" mechanism (see
:meth:`~pyramid.config.Configurator.include`), it allows you to compose complex
applications from multiple, simple Python packages. All the configuration
-statements that can be performed in your "main" Pyramid application can also be
+statements that can be performed in your main :app:`Pyramid` application can also be
used in included packages. You can add views, routes, and subscribers, and even
set authentication and authorization policies.
@@ -142,51 +153,58 @@ as you requested:
Authenticate Users Your Way
---------------------------
-:app:`Pyramid` ships with prebuilt well-tested authentication and authorization
+:app:`Pyramid` ships with prebuilt, well-tested authentication and authorization
schemes out of the box. Using a scheme is a matter of configuration. So if you
need to change approaches later, you need only update your configuration.
-In addition, the system that handles authentication an authorization is
+In addition, the system that handles authentication and authorization is
flexible and pluggable. If you want to use another security add-on, or define
your own, you can. And again, you need only update your application
configuration to make the change.
-Example: :ref:`enabling_authorization_policy`.
+.. seealso::
+
+ See also :ref:`enabling_authorization_policy`.
Build Trees of Resources
------------------------
-:app:`Pyramid` supports :term:`Traversal`, a way of mapping URLs to a concrete
-tree of resources. If your application naturally consists of an arbitrary
+:app:`Pyramid` supports :term:`traversal`, a way of mapping URLs to a concrete
+:term:`resource tree`. If your application naturally consists of an arbitrary
heirarchy of different types of content (like a CMS or a Document Management
System), traversal is for you. If you have a requirement for a highly granular
security model ("Jane can edit documents in *this* folder, but not *that*
one"), traversal can be a powerful approach.
-Examples: :ref:`hello_traversal_chapter` and
-:ref:`much_ado_about_traversal_chapter`.
+.. seealso::
+
+ See also :ref:`hello_traversal_chapter` and
+ :ref:`much_ado_about_traversal_chapter`.
Take Action on Each Request with Tweens
---------------------------------------
-Pyramid has a system for applying arbitrary actions to each request or response
-called *tweens*. The system is similar in concept to WSGI :term:`middleware`,
-but can be more useful since they run in the Pyramid context, and have access
-to templates, request objects, and other niceties.
+:app:`Pyramid` has a system for applying an arbitrary action to each request or
+response called a :term:`tween`. The system is similar in concept to WSGI
+:term:`middleware`, but can be more useful since :term:`tween`\ s run in the
+:app:`Pyramid` context, and have access to templates, request objects, and
+other niceties.
-The Pyramid debug toolbar is a "tween", as is the ``pyramid_tm`` transaction
-manager.
+The :app:`Pyramid` debug toolbar is a :term:`tween`, as is the ``pyramid_tm``
+transaction manager.
+
+.. seealso::
-Example: :ref:`registering_tweens`.
+ See also :ref:`registering_tweens`.
Return What You Want From Your Views
------------------------------------
-We have shown before (in the :doc:`introduction`) how using a :term:`renderer`
+We have shown elsewhere (in the :doc:`introduction`) how using a :term:`renderer`
allows you to return simple Python dictionaries from your view code. But some
frameworks allow you to return strings or tuples from view callables.
-When frameworks allow for this, code looks slightly prettier, because there are
-fewer imports, and less code. For example, compare this:
+When frameworks allow for this, code looks slightly prettier because there are
+fewer imports and less code. For example, compare this:
.. code-block:: python
:linenos:
@@ -206,12 +224,13 @@ To this:
Nicer to look at, right?
-Out of the box, Pyramid will raise an exception if you try to run the second
-example above. After all, a view should return a response, and "explicit is
-better than implicit".
+Out of the box, :app:`Pyramid` will raise an exception if you try to run the
+second example above. After all, a view should return a response, and "explicit
+is better than implicit".
-But if you're a developer who likes the aesthetics of simplicity, Pyramid
-provides an way to support this sort of thing, the *response adapter*:
+But if you're a developer who likes the aesthetics of simplicity,
+:app:`Pyramid` provides an way to support this sort of thing, the
+:term:`response adapter`\ :
.. code-block:: python
:linenos:
@@ -241,8 +260,8 @@ With that, you may return strings from any of your view callables, e.g.:
def goodbyeview(request):
return "Goodbye world!"
-You can even use a response adapter to allow for custom content types and
-return codes:
+You can even use a :term:`response adapter` to allow for custom content types
+and return codes:
.. code-block:: python
:linenos:
@@ -280,14 +299,14 @@ With this, both of these views will work as expected:
.. seealso::
- See also :ref:`using_iresponse`.
+ See also :ref:`using_iresponse`.
Use Global Response Objects
---------------------------
Views have to return responses. But constructing them in view code is a chore.
-And perhaps registering a response adapter as shown above is just too much
-work. :app:`Pyramid` provides a global response object as well. You can just
+And perhaps registering a :term:`response adapter` as shown above is just too
+much work. :app:`Pyramid` provides a global response object as well. You can
use it directly, if you prefer:
.. code-block:: python
@@ -301,17 +320,17 @@ use it directly, if you prefer:
.. seealso::
- See also :ref:`request_response_attr`.
+ See also :ref:`request_response_attr`.
Extend Configuration
--------------------
Perhaps the :app:`Pyramid` configurator's syntax feels a bit verbose to you. Or
possibly you would like to add a feature to configuration without asking the
-core developers to change Pyramid itself?
+core developers to change :app:`Pyramid` itself?
-You can extend Pyramid's :term:`Configurator` with your own directives. For
-example, let's say you find yourself calling
+You can extend :app:`Pyramid`\ 's :term:`configurator` with your own
+directives. For example, let's say you find yourself calling
:meth:`pyramid.config.Configurator.add_view` repetitively. Usually you can get
rid of the boring with existing shortcuts, but let's say that this is a case
where there is no such shortcut:
@@ -330,8 +349,8 @@ where there is no such shortcut:
config.add_view('my.package.HEAD_view', route_name='xhr_route',
xhr=True, permission='view', request_method='HEAD')
-Pretty tedious right? You can add a directive to the Pyramid configurator to
-automate some of the tedium away:
+Pretty tedious right? You can add a directive to the :app:`Pyramid`
+:term:`configurator` to automate some of the tedium away:
.. code-block:: python
:linenos:
@@ -344,13 +363,13 @@ automate some of the tedium away:
view = getattr(module, 'xhr_%s_view' % method, None)
if view is not None:
config.add_view(view, route_name='xhr_route', xhr=True,
- permission='view', request_method=method)
+ permission='view', request_method=method)
config = Configurator()
config.add_directive('add_protected_xhr_views', add_protected_xhr_views)
Once that's done, you can call the directive you've just added as a method of
-the Configurator object:
+the :term:`configurator` object:
.. code-block:: python
:linenos:
diff --git a/docs/narr/introduction.rst b/docs/narr/introduction.rst
index 63bc164fb..a8d417250 100644
--- a/docs/narr/introduction.rst
+++ b/docs/narr/introduction.rst
@@ -492,7 +492,7 @@ that make it adaptable. Read more about them below.
.. toctree::
:maxdepth: 2
- advfeatures
+ advanced-features