diff options
| author | Steve Piercy <web@stevepiercy.com> | 2015-11-15 05:46:47 -0800 |
|---|---|---|
| committer | Steve Piercy <web@stevepiercy.com> | 2015-11-15 05:46:47 -0800 |
| commit | bdc3f28699c5fc6b127a1aa502b8372b149429f2 (patch) | |
| tree | 4c539755b66022655361563ebeaa57934fa1f8af | |
| parent | b999ecbf975d15ad1dbb769ef351a247e1790543 (diff) | |
| download | pyramid-bdc3f28699c5fc6b127a1aa502b8372b149429f2.tar.gz pyramid-bdc3f28699c5fc6b127a1aa502b8372b149429f2.tar.bz2 pyramid-bdc3f28699c5fc6b127a1aa502b8372b149429f2.zip | |
minor grammar, .rst syntax fixes, rewrap 79 cols
| -rw-r--r-- | docs/narr/threadlocals.rst | 226 |
1 files changed, 106 insertions, 120 deletions
diff --git a/docs/narr/threadlocals.rst b/docs/narr/threadlocals.rst index afe56de3e..7437a3a76 100644 --- a/docs/narr/threadlocals.rst +++ b/docs/narr/threadlocals.rst @@ -8,26 +8,24 @@ Thread Locals ============= -A :term:`thread local` variable is a variable that appears to be a -"global" variable to an application which uses it. However, unlike a -true global variable, one thread or process serving the application -may receive a different value than another thread or process when that -variable is "thread local". +A :term:`thread local` variable is a variable that appears to be a "global" +variable to an application which uses it. However, unlike a true global +variable, one thread or process serving the application may receive a different +value than another thread or process when that variable is "thread local". -When a request is processed, :app:`Pyramid` makes two :term:`thread -local` variables available to the application: a "registry" and a -"request". +When a request is processed, :app:`Pyramid` makes two :term:`thread local` +variables available to the application: a "registry" and a "request". Why and How :app:`Pyramid` Uses Thread Local Variables ---------------------------------------------------------- +------------------------------------------------------ -How are thread locals beneficial to :app:`Pyramid` and application -developers who use :app:`Pyramid`? Well, usually they're decidedly -**not**. Using a global or a thread local variable in any application -usually makes it a lot harder to understand for a casual reader. Use -of a thread local or a global is usually just a way to avoid passing -some value around between functions, which is itself usually a very -bad idea, at least if code readability counts as an important concern. +How are thread locals beneficial to :app:`Pyramid` and application developers +who use :app:`Pyramid`? Well, usually they're decidedly **not**. Using a +global or a thread local variable in any application usually makes it a lot +harder to understand for a casual reader. Use of a thread local or a global is +usually just a way to avoid passing some value around between functions, which +is itself usually a very bad idea, at least if code readability counts as an +important concern. For historical reasons, however, thread local variables are indeed consulted by various :app:`Pyramid` API functions. For example, the implementation of the @@ -40,119 +38,107 @@ application registry, from which it looks up the authentication policy; it then uses the authentication policy to retrieve the authenticated user id. This is how :app:`Pyramid` allows arbitrary authentication policies to be "plugged in". -When they need to do so, :app:`Pyramid` internals use two API -functions to retrieve the :term:`request` and :term:`application -registry`: :func:`~pyramid.threadlocal.get_current_request` and -:func:`~pyramid.threadlocal.get_current_registry`. The former -returns the "current" request; the latter returns the "current" -registry. Both ``get_current_*`` functions retrieve an object from a -thread-local data structure. These API functions are documented in -:ref:`threadlocal_module`. - -These values are thread locals rather than true globals because one -Python process may be handling multiple simultaneous requests or even -multiple :app:`Pyramid` applications. If they were true globals, -:app:`Pyramid` could not handle multiple simultaneous requests or -allow more than one :app:`Pyramid` application instance to exist in -a single Python process. - -Because one :app:`Pyramid` application is permitted to call -*another* :app:`Pyramid` application from its own :term:`view` code -(perhaps as a :term:`WSGI` app with help from the -:func:`pyramid.wsgi.wsgiapp2` decorator), these variables are -managed in a *stack* during normal system operations. The stack -instance itself is a :class:`threading.local`. +When they need to do so, :app:`Pyramid` internals use two API functions to +retrieve the :term:`request` and :term:`application registry`: +:func:`~pyramid.threadlocal.get_current_request` and +:func:`~pyramid.threadlocal.get_current_registry`. The former returns the +"current" request; the latter returns the "current" registry. Both +``get_current_*`` functions retrieve an object from a thread-local data +structure. These API functions are documented in :ref:`threadlocal_module`. + +These values are thread locals rather than true globals because one Python +process may be handling multiple simultaneous requests or even multiple +:app:`Pyramid` applications. If they were true globals, :app:`Pyramid` could +not handle multiple simultaneous requests or allow more than one :app:`Pyramid` +application instance to exist in a single Python process. + +Because one :app:`Pyramid` application is permitted to call *another* +:app:`Pyramid` application from its own :term:`view` code (perhaps as a +:term:`WSGI` app with help from the :func:`pyramid.wsgi.wsgiapp2` decorator), +these variables are managed in a *stack* during normal system operations. The +stack instance itself is a :class:`threading.local`. During normal operations, the thread locals stack is managed by a -:term:`Router` object. At the beginning of a request, the Router -pushes the application's registry and the request on to the stack. At -the end of a request, the stack is popped. The topmost request and -registry on the stack are considered "current". Therefore, when the -system is operating normally, the very definition of "current" is -defined entirely by the behavior of a pyramid :term:`Router`. +:term:`Router` object. At the beginning of a request, the Router pushes the +application's registry and the request on to the stack. At the end of a +request, the stack is popped. The topmost request and registry on the stack +are considered "current". Therefore, when the system is operating normally, +the very definition of "current" is defined entirely by the behavior of a +pyramid :term:`Router`. However, during unit testing, no Router code is ever invoked, and the -definition of "current" is defined by the boundary between calls to -the :meth:`pyramid.config.Configurator.begin` and -:meth:`pyramid.config.Configurator.end` methods (or between -calls to the :func:`pyramid.testing.setUp` and -:func:`pyramid.testing.tearDown` functions). These functions push -and pop the threadlocal stack when the system is under test. See -:ref:`test_setup_and_teardown` for the definitions of these functions. - -Scripts which use :app:`Pyramid` machinery but never actually start -a WSGI server or receive requests via HTTP such as scripts which use -the :mod:`pyramid.scripting` API will never cause any Router code -to be executed. However, the :mod:`pyramid.scripting` APIs also -push some values on to the thread locals stack as a matter of course. -Such scripts should expect the -:func:`~pyramid.threadlocal.get_current_request` function to always -return ``None``, and should expect the -:func:`~pyramid.threadlocal.get_current_registry` function to return -exactly the same :term:`application registry` for every request. +definition of "current" is defined by the boundary between calls to the +:meth:`pyramid.config.Configurator.begin` and +:meth:`pyramid.config.Configurator.end` methods (or between calls to the +:func:`pyramid.testing.setUp` and :func:`pyramid.testing.tearDown` functions). +These functions push and pop the threadlocal stack when the system is under +test. See :ref:`test_setup_and_teardown` for the definitions of these +functions. + +Scripts which use :app:`Pyramid` machinery but never actually start a WSGI +server or receive requests via HTTP, such as scripts which use the +:mod:`pyramid.scripting` API, will never cause any Router code to be executed. +However, the :mod:`pyramid.scripting` APIs also push some values on to the +thread locals stack as a matter of course. Such scripts should expect the +:func:`~pyramid.threadlocal.get_current_request` function to always return +``None``, and should expect the +:func:`~pyramid.threadlocal.get_current_registry` function to return exactly +the same :term:`application registry` for every request. Why You Shouldn't Abuse Thread Locals ------------------------------------- You probably should almost never use the :func:`~pyramid.threadlocal.get_current_request` or -:func:`~pyramid.threadlocal.get_current_registry` functions, except -perhaps in tests. In particular, it's almost always a mistake to use -``get_current_request`` or ``get_current_registry`` in application -code because its usage makes it possible to write code that can be -neither easily tested nor scripted. Inappropriate usage is defined as -follows: +:func:`~pyramid.threadlocal.get_current_registry` functions, except perhaps in +tests. In particular, it's almost always a mistake to use +``get_current_request`` or ``get_current_registry`` in application code because +its usage makes it possible to write code that can be neither easily tested nor +scripted. Inappropriate usage is defined as follows: - ``get_current_request`` should never be called within the body of a - :term:`view callable`, or within code called by a view callable. - View callables already have access to the request (it's passed in to - each as ``request``). - -- ``get_current_request`` should never be called in :term:`resource` code. - If a resource needs access to the request, it should be passed the request - by a :term:`view callable`. - -- ``get_current_request`` function should never be called because it's - "easier" or "more elegant" to think about calling it than to pass a - request through a series of function calls when creating some API - design. Your application should instead almost certainly pass data - derived from the request around rather than relying on being able to - call this function to obtain the request in places that actually - have no business knowing about it. Parameters are *meant* to be - passed around as function arguments, this is why they exist. Don't - try to "save typing" or create "nicer APIs" by using this function - in the place where a request is required; this will only lead to - sadness later. - -- Neither ``get_current_request`` nor ``get_current_registry`` should - ever be called within application-specific forks of third-party - library code. The library you've forked almost certainly has - nothing to do with :app:`Pyramid`, and making it dependent on - :app:`Pyramid` (rather than making your :app:`pyramid` - application depend upon it) means you're forming a dependency in the - wrong direction. - -Use of the :func:`~pyramid.threadlocal.get_current_request` function -in application code *is* still useful in very limited circumstances. -As a rule of thumb, usage of ``get_current_request`` is useful -**within code which is meant to eventually be removed**. For -instance, you may find yourself wanting to deprecate some API that -expects to be passed a request object in favor of one that does not -expect to be passed a request object. But you need to keep -implementations of the old API working for some period of time while -you deprecate the older API. So you write a "facade" implementation -of the new API which calls into the code which implements the older -API. Since the new API does not require the request, your facade -implementation doesn't have local access to the request when it needs -to pass it into the older API implementation. After some period of -time, the older implementation code is disused and the hack that uses -``get_current_request`` is removed. This would be an appropriate -place to use the ``get_current_request``. - -Use of the :func:`~pyramid.threadlocal.get_current_registry` -function should be limited to testing scenarios. The registry made -current by use of the -:meth:`pyramid.config.Configurator.begin` method during a -test (or via :func:`pyramid.testing.setUp`) when you do not pass -one in is available to you via this API. - + :term:`view callable`, or within code called by a view callable. View + callables already have access to the request (it's passed in to each as + ``request``). + +- ``get_current_request`` should never be called in :term:`resource` code. If a + resource needs access to the request, it should be passed the request by a + :term:`view callable`. + +- ``get_current_request`` function should never be called because it's "easier" + or "more elegant" to think about calling it than to pass a request through a + series of function calls when creating some API design. Your application + should instead, almost certainly, pass around data derived from the request + rather than relying on being able to call this function to obtain the request + in places that actually have no business knowing about it. Parameters are + *meant* to be passed around as function arguments; this is why they exist. + Don't try to "save typing" or create "nicer APIs" by using this function in + the place where a request is required; this will only lead to sadness later. + +- Neither ``get_current_request`` nor ``get_current_registry`` should ever be + called within application-specific forks of third-party library code. The + library you've forked almost certainly has nothing to do with :app:`Pyramid`, + and making it dependent on :app:`Pyramid` (rather than making your + :app:`pyramid` application depend upon it) means you're forming a dependency + in the wrong direction. + +Use of the :func:`~pyramid.threadlocal.get_current_request` function in +application code *is* still useful in very limited circumstances. As a rule of +thumb, usage of ``get_current_request`` is useful **within code which is meant +to eventually be removed**. For instance, you may find yourself wanting to +deprecate some API that expects to be passed a request object in favor of one +that does not expect to be passed a request object. But you need to keep +implementations of the old API working for some period of time while you +deprecate the older API. So you write a "facade" implementation of the new API +which calls into the code which implements the older API. Since the new API +does not require the request, your facade implementation doesn't have local +access to the request when it needs to pass it into the older API +implementation. After some period of time, the older implementation code is +disused and the hack that uses ``get_current_request`` is removed. This would +be an appropriate place to use the ``get_current_request``. + +Use of the :func:`~pyramid.threadlocal.get_current_registry` function should be +limited to testing scenarios. The registry made current by use of the +:meth:`pyramid.config.Configurator.begin` method during a test (or via +:func:`pyramid.testing.setUp`) when you do not pass one in is available to you +via this API. |
