Browse Source

Added notes on proxies

pull/112/head
Armin Ronacher 15 years ago
parent
commit
3b0eb0f3ca
  1. 35
      docs/api.rst
  2. 46
      docs/signals.rst

35
docs/api.rst

@ -38,6 +38,8 @@ Incoming Request Data
sure that you always get the correct data for the active thread if you
are in a multithreaded environment.
This is a proxy. See :ref:`notes-on-proxies` for more information.
The request object is an instance of a :class:`~werkzeug.Request`
subclass and provides all of the attributes Werkzeug defines. This
just shows a quick overview of the most important ones.
@ -164,6 +166,8 @@ To access the current session you can use the :class:`session` object:
The session object works pretty much like an ordinary dict, with the
difference that it keeps track on modifications.
This is a proxy. See :ref:`notes-on-proxies` for more information.
The following attributes are interesting:
.. attribute:: new
@ -206,6 +210,8 @@ thing, like it does for :class:`request` and :class:`session`.
Just store on this whatever you want. For example a database
connection or the user that is currently logged in.
This is a proxy. See :ref:`notes-on-proxies` for more information.
Useful Functions and Classes
----------------------------
@ -216,6 +222,8 @@ Useful Functions and Classes
extensions that want to support multiple applications running side
by side.
This is a proxy. See :ref:`notes-on-proxies` for more information.
.. autofunction:: url_for
.. function:: abort(code)
@ -389,6 +397,8 @@ Signals
in debug mode, where no exception handling happens. The exception
itself is passed to the subscriber as `exception`.
.. currentmodule:: None
.. class:: flask.signals.Namespace
An alias for :class:`blinker.base.Namespace` if blinker is available,
@ -404,3 +414,28 @@ Signals
operations, including connecting.
.. _blinker: http://pypi.python.org/pypi/blinker
.. _notes-on-proxies:
Notes On Proxies
----------------
Some of the objects provided by Flask are proxies to other objects. The
reason behind this is, that these proxies are shared between threads and
they have to dispatch to the actual object bound to a thread behind the
scenes as necessary.
Most of the time you don't have to care about that, but there are some
exceptions where it is good to know that this object is an actual proxy:
- The proxy objects do not fake their inherited types, so if you want to
perform actual instance checks, you have to do that on the instance
that
- if the object reference is important (so for example for sending
:ref:`signals`)
If you need to get access to the underlying object that is proxied, you
can use the :meth:`~werkzeug.LocalProxy._get_current_object` method::
app = current_app._get_current_object()
my_signal.send(app)

46
docs/signals.rst

@ -41,13 +41,9 @@ the optional second argument specifies a sender. To unsubscribe from a
signal, you can use the :meth:`~blinker.base.Signal.disconnect` method.
For all core Flask signals, the sender is the application that issued the
signal. This however might not be true for Flask extensions, so consult
the documentation when subscribing to signals.
Additionally there is a convenient helper method that allows you to
temporarily subscribe a function to a signal. This is especially helpful
for unittests (:meth:`~blinker.base.Signal.temporarily_connected_to`).
This has to be used in combination with the `with` statement.
signal. When you subscribe to a signal, be sure to also provide a sender
unless you really want to listen for signals of all applications. This is
especially true if you are developing an extension.
Here for example a helper context manager that can be used to figure out
in a unittest which templates were rendered and what variables were passed
@ -57,19 +53,19 @@ to the template::
from contextlib import contextmanager
@contextmanager
def captured_templates():
def captured_templates(app):
recorded = []
def record(template, context):
recorded.append((template, context))
template_rendered.connect(record)
template_rendered.connect(record, app)
try:
yield recorded
finally:
template_rendered.disconnect(record)
template_rendered.disconnect(record, app)
This can now easily be paired with a test client::
with captured_templates() as templates:
with captured_templates(app) as templates:
rv = app.test_client().get('/')
assert rv.status_code == 200
assert len(templates) == 1
@ -77,9 +73,23 @@ This can now easily be paired with a test client::
assert template.name == 'index.html'
assert len(context['items']) == 10
All the template rendering in the code, the `with` block wraps will now be
recorded in the `templates` variable. Whenever a template is rendered,
the template object as well as context is appended to it.
All the template rendering in the code issued by the application `app`
in the body of the `with` block will now be recorded in the `templates`
variable. Whenever a template is rendered, the template object as well as
context are appended to it.
Additionally there is a convenient helper method
(:meth:`~blinker.base.Signal.temporarily_connected_to`). that allows you
to temporarily subscribe a function to a signal with is a context manager
on its own which simplifies the example above::
from flask import template_rendered
def captured_templates(app):
recorded = []
def record(template, context):
recorded.append((template, context))
return template_rendered.temporarily_connected_to(record, app)
Creating Signals
----------------
@ -153,7 +163,7 @@ The following signals exist in Flask:
context)
from flask import request_started
request_started.connect(log_template_renders)
request_started.connect(log_template_renders, app)
.. data:: flask.request_started
:noindex:
@ -169,7 +179,7 @@ The following signals exist in Flask:
sender.logger.debug('Request context is set up')
from flask import request_started
request_started.connect(log_request)
request_started.connect(log_request, app)
.. data:: flask.request_finished
:noindex:
@ -184,7 +194,7 @@ The following signals exist in Flask:
'Response: %s', response)
from flask import request_finished
request_finished.connect(log_response)
request_finished.connect(log_response, app)
.. data:: flask.got_request_exception
:noindex:
@ -200,6 +210,6 @@ The following signals exist in Flask:
sender.logger.debug('Got exception during processing: %s', exception)
from flask import got_request_exception
got_request_exception.connect(log_exception)
got_request_exception.connect(log_exception, app)
.. _blinker: http://pypi.python.org/pypi/blinker

Loading…
Cancel
Save