summaryrefslogtreecommitdiff
path: root/docs/narr
diff options
context:
space:
mode:
Diffstat (limited to 'docs/narr')
-rw-r--r--docs/narr/MyProject/myproject/run.py2
-rw-r--r--docs/narr/MyProject/myproject/tests.py6
-rw-r--r--docs/narr/configuration.rst67
-rw-r--r--docs/narr/project.rst2
-rw-r--r--docs/narr/threadlocals.rst14
-rw-r--r--docs/narr/unittesting.rst122
6 files changed, 157 insertions, 56 deletions
diff --git a/docs/narr/MyProject/myproject/run.py b/docs/narr/MyProject/myproject/run.py
index 0d7647aa7..6a3671c1e 100644
--- a/docs/narr/MyProject/myproject/run.py
+++ b/docs/narr/MyProject/myproject/run.py
@@ -6,8 +6,10 @@ def app(global_config, **settings):
is usually called by the PasteDeploy framework during ``paster
serve``"""
config = Configurator(root_factory=get_root, settings=settings)
+ config.begin()
zcml_file = settings.get('configure_zcml', 'configure.zcml')
config.load_zcml(zcml_file)
+ config.end()
return config.make_wsgi_app()
diff --git a/docs/narr/MyProject/myproject/tests.py b/docs/narr/MyProject/myproject/tests.py
index 7c3caac74..498bd96e8 100644
--- a/docs/narr/MyProject/myproject/tests.py
+++ b/docs/narr/MyProject/myproject/tests.py
@@ -1,13 +1,15 @@
import unittest
+from repoze.bfg.configuration import Configurator
from repoze.bfg import testing
class ViewTests(unittest.TestCase):
def setUp(self):
- testing.setUp()
+ self.config = Configurator()
+ self.config.begin()
def tearDown(self):
- testing.tearDown()
+ self.config.end()
def test_my_view(self):
from myproject.views import my_view
diff --git a/docs/narr/configuration.rst b/docs/narr/configuration.rst
index 9e7c75005..367df2a2d 100644
--- a/docs/narr/configuration.rst
+++ b/docs/narr/configuration.rst
@@ -86,8 +86,10 @@ imperatively:
if __name__ == '__main__':
config = Configurator()
+ config.begin()
config.add_view(hello_world)
config.add_view(goodbye_world, name='goodbye')
+ config.end()
app = config.make_wsgi_app()
serve(app)
@@ -274,12 +276,17 @@ imports and function definitions is placed within the confines of an
if __name__ == '__main__':
config = Configurator()
+ config.begin()
config.add_view(hello_world)
config.add_view(goodbye_world, name='goodbye')
+ config.end()
app = config.make_wsgi_app()
simple_server.make_server('', 8080, app).serve_forever()
-Let's break this down this piece-by-piece:
+Let's break this down this piece-by-piece.
+
+Configurator Construction
+~~~~~~~~~~~~~~~~~~~~~~~~~
.. code-block:: python
:linenos:
@@ -315,6 +322,27 @@ this particular :mod:`repoze.bfg` application.
registry object being configured by a ``Configurator`` is available
as its ``registry`` attribute.
+Beginning Configuration
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: python
+ :linenos:
+
+ config.begin()
+
+The ``begin`` method of a Configurator tells the the system that
+application configuration has begun. In particular, this causes the
+:term:`application registry` associated with this configurator to
+become the "current" application registry, meaning that code which
+attempts to use the application registry :term:`thread local` will
+obtain the registry associated with the configurator. This is an
+explicit step because it's sometimes convenient to use a configurator
+without causing the registry associated with the configurator to
+become "current".
+
+Adding Configuration
+~~~~~~~~~~~~~~~~~~~~
+
.. code-block:: python
:linenos:
@@ -411,6 +439,22 @@ the best view configuration for any request, the ``goodbye_world``
view callable will be used when the URL contains path information that
ends with ``/goodbye``.
+Ending Configuration
+~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: python
+ :linenos:
+
+ config.end()
+
+The ``end`` method of a Configurator tells the the system that
+application configuration has ended. It is the inverse of
+``config.begin``. In particular, this causes the :term:`application
+registry` associated with this configurator to no longer be the
+"current" application registry, meaning that code which attempts to
+use the application registry :term:`thread local` will no longer
+obtain the registry associated with the configurator.
+
WSGI Application Creation
~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -419,13 +463,14 @@ WSGI Application Creation
app = config.make_wsgi_app()
-After configuring views, the script creates a WSGI *application* via
-the ``config.make_wsgi_app`` method. A call to ``make_wsgi_app``
-implies that all configuration is finished (meaning all method calls
-to the configurator which set up views, and various other
-configuration settings have been performed). The ``make_wsgi_app``
-method returns a :term:`WSGI` application object that can be used by
-any WSGI server to present an application to a requestor.
+After configuring views and ending configuration, the script creates a
+WSGI *application* via the ``config.make_wsgi_app`` method. A call to
+``make_wsgi_app`` implies that all configuration is finished (meaning
+all method calls to the configurator which set up views, and various
+other configuration settings have been performed). The
+``make_wsgi_app`` method returns a :term:`WSGI` application object
+that can be used by any WSGI server to present an application to a
+requestor.
The :mod:`repoze.bfg` application object, in particular, is an
instance of the ``repoze.bfg.router.Router`` class. It has a
@@ -510,7 +555,9 @@ In a file named ``helloworld.py``:
if __name__ == '__main__':
config = Configurator()
+ config.begin()
config.load_zcml('configure.zcml)
+ config.end()
app = config.make_wsgi_app()
serve(app)
@@ -547,8 +594,10 @@ within the ``if __name__ == '__main__'`` section of ``helloworld.py``:
if __name__ == '__main__':
config = Configurator()
+ config.begin()
config.add_view(hello_world)
config.add_view(goodbye_world, name='goodbye')
+ config.end()
app = config.make_wsgi_app()
simple_server.make_server('', 8080, app).serve_forever()
@@ -563,7 +612,9 @@ reads as:
if __name__ == '__main__':
config = Configurator()
+ config.begin()
config.load_zcml('configure.zcml')
+ config.end()
app = config.make_wsgi_app()
simple_server.make_server('', 8080, app).serve_forever()
diff --git a/docs/narr/project.rst b/docs/narr/project.rst
index 81e570e36..16879b69b 100644
--- a/docs/narr/project.rst
+++ b/docs/narr/project.rst
@@ -724,7 +724,7 @@ without the PasteDeploy configuration file:
#. Line 2 imports the ``get_root`` function from
:mod:`myproject.models` that we use later.
-#. Lines 4-11 define a function that returns a :mod:`repoze.bfg`
+#. Lines 4-13 define a function that returns a :mod:`repoze.bfg`
WSGI application. This function is meant to be called
by the :term:`PasteDeploy` framework as a result of running
``paster serve``.
diff --git a/docs/narr/threadlocals.rst b/docs/narr/threadlocals.rst
index 476b179ec..b97d9e4f2 100644
--- a/docs/narr/threadlocals.rst
+++ b/docs/narr/threadlocals.rst
@@ -69,10 +69,11 @@ defined entirely by the behavior of a repoze.bfg :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 ``repoze.bfg.testing.setUp`` and ``repoze.bfg.testing.tearDown``.
-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.
+the ``begin`` and ``end`` methods of a :term:`Configurator` (or,
+pre-1.2a6, between calls to the ``repoze.bfg.testing.setUp`` and
+``repoze.bfg.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 :mod:`repoze.bfg` machinery but never actually start
a WSGI server or receive requests via HTTP such as scripts which use
@@ -142,7 +143,8 @@ and the hack that uses ``get_current_request`` is removed. This would
be an appropriate place to use the ``get_current_request`` function.
Use of the ``get_current_registry`` function should be limited to
-testing scenarios. The registry created by
-``repoze.bfg.testing.setUp`` when you do not pass one in is available
+testing scenarios. The registry made current by use of a
+Configurator's ``begin`` method during a test (or pre-1.2a6, via
+``repoze.bfg.testing.setUp``) when you do not pass one in is available
to you via this API.
diff --git a/docs/narr/unittesting.rst b/docs/narr/unittesting.rst
index cc8ab6e32..790c0577d 100644
--- a/docs/narr/unittesting.rst
+++ b/docs/narr/unittesting.rst
@@ -56,7 +56,7 @@ functions.
Test Set Up and Tear Down
--------------------------
-:mod:`repoze.bfg` uses a "global" (actually thread-local) data
+:mod:`repoze.bfg` uses a "global" (actually :term:`thread local`) data
structure to hold on to two items: the current :term:`request` and the
current :term:`application registry`. These data structures are
available via the ``repoze.bfg.threadlocal.get_current_request`` and
@@ -65,42 +65,84 @@ respectively. See :ref:`threadlocals_chapter` for information about
these functions and the data structures they return.
If your code uses these ``get_current_*`` functions or calls
-:mod:`repoze.bfg` code which uses the ``get_current_*`` functions, you
-will need to use the ``repoze.bfg.testing.setUp`` and
-``repoze.bfg.testing.tearDown`` functions within the ``setUp`` and
-``tearDown`` methods of your unit tests, respectively.
+:mod:`repoze.bfg` code which uses ``get_current_*`` functions, you
+will need to construct at :term:`Configurator` and call its ``begin``
+method within the ``setUp`` method of your unit test and call the same
+configurator's ``end`` method within the ``tearDown`` method of your
+unit test.
-The ``repoze.bfg.testing.setUp`` and ``repoze.bfg.testing.tearDown``
-functions allow you to supply a unit test with an environment that has
-a default registry and a default request for the duration of a single
-test. Here's an example of using both:
+The use of a Configurator and its ``begin`` and ``end`` methods allows
+you to supply each unit test method in a test case with an environment
+that has a isolated registry and an isolated request for the duration
+of a single test. Here's an example of using this feature:
.. code-block:: python
:linenos:
import unittest
- from repoze.bfg import testing
+ from repoze.bfg.configuration import Configurator
+
+ class MyTest(unittest.TestCase):
+ def setUp(self):
+ self.config = Configurator()
+ self.config.begin()
+
+ def tearDown(self):
+ self.config.end()
+
+The above will make sure that
+``repoze.bfg.threadlocal.get_current_registry`` will return the
+:term:`application registry` associated with the ``config``
+Configurator instance when ``get_current_registry`` is called in a
+test case method attached to ``MyTest``. Each test case method
+attached to ``MyTest`` will use an isolated registry.
+
+The ``begin`` method of a Configurator accepts various arguments that
+influence the code run during the test. See the
+:ref:`configuration_module` chapter for information about the API of a
+:term:`Configurator`, including its ``begin`` and ``end`` methods.
+
+If you also want to make ``repoze.bfg.get_current_registry`` return
+something other than ``None`` during the course of a single test, you
+can pass a :term:`request` object into the ``begin`` method of the
+Configurator within the ``setUp`` method of your test:
+
+.. code-block:: python
+ :linenos:
+
+ import unittest
+ from repoze.bfg.configuration import Configurator
+ from repoze.bfg.request import Request
class MyTest(unittest.TestCase):
def setUp(self):
- testing.setUp()
+ self.config = Configurator()
+ request = Request()
+ self.config.begin(request=request)
def tearDown(self):
- testing.tearDown()
-
-If you don't *know* whether you're calling code that uses these
-functions, a rule of thumb applies: just always use the
-``repoze.bfg.testing.setUp`` and ``repoze.bfg.testing.tearDown``
-functions in the ``setUp`` and ``tearDown`` respectively of unit tests
-that test :mod:`repoze.bfg` application code, unless it's obvious
-you're not calling any :mod:`repoze.bfg` APIs which might make use of
-the any "current" global.
-
-The ``repoze.bfg.testing.setUp`` and ``repoze.bfg.testing.tearDown``
-functions accept various arguments that influence the code run during
-the test. See the :ref:`testing_module` chapter for information about
-the APIs of ``repoze.bfg.testing.setUp`` and
-``repoze.bfg.testing.tearDown``.
+ self.config.end()
+
+If you pass a term:`Request` object into the ``begin`` method of the
+configurator within your test case's ``setUp``, any test method
+attached to the ``MyTest`` test case that directly or indirectly calls
+``get_current_request`` will receive the request you passed into the
+``begin`` method. Otherwise, during testing, ``get_current_request``
+will return ``None``.
+
+What?
+~~~~~
+
+Thread local data structures are always a bit confusing, especially
+when used by frameworks. Sorry. So here's a rule of thumb: if you
+don't *know* whether you're calling code that uses the
+``get_current_registry`` or ``get_current_request`` functions, or you
+don't care about any of this, but you still want to write test code,
+just always create a configurator instance and call its ``begin``
+method within the ``setUp`` of a unit test, then subsequently call its
+``end`` method in the test's ``tearDown``. This won't really hurt
+anything if the application you're testing does not call any
+``get_current*`` function.
Using the ``repoze.bfg.testing`` API in Unit Tests
--------------------------------------------------
@@ -148,14 +190,16 @@ you could write a unittest TestCase that used the testing API.
:linenos:
import unittest
+ from repoze.bfg.configuration import Configurator
from repoze.bfg import testing
class MyTest(unittest.TestCase):
def setUp(self):
- testing.setUp()
+ self.config = Configurator()
+ self.config.begin()
def tearDown(self):
- testing.tearDown()
+ self.config.end()
def test_view_fn_not_submitted(self):
from my.package import view_fn
@@ -204,12 +248,12 @@ assertion. We assert at the end of this that the renderer's ``say``
attribute is ``Yo``, as this is what is expected of the view function
in the branch it's testing.
-Note that the test calls the ``repoze.bfg.testing.setUp`` function in
-its ``setUp`` method and the ``repoze.bfg.testing.tearDown`` function
-in its ``tearDown`` method. Use of this pattern is required to
-perform cleanup between the test runs. If you use any of the testing
-API, be sure to call ``repoze.bfg.testing.setUp`` in the test setup
-and ``repoze.bfg.testing.tearDown`` in the test teardown.
+Note that the test calls the ``begin`` method of a
+:term:`Configurator` in its ``setUp`` method and the ``end`` method of
+the same in its ``tearDown`` method. If you use any of the
+``repoze.bfg.testing`` APIs, be sure to use this pattern in your test
+setUp and tearDown; these methods make sure you're using a "fresh"
+:term:`application registry` per test run.
See the :ref:`testing_module` chapter for the entire :mod:`repoze.bfg`
-specific testing API. This chapter describes APIs for registering a
@@ -251,6 +295,7 @@ environment.
import unittest
+ from repoze.bfg.configuration import Configurator
from repoze.bfg import testing
class ViewIntegrationTests(unittest.TestCase):
@@ -259,15 +304,14 @@ environment.
registrations your application declares in its configure.zcml
(including dependent registrations for repoze.bfg itself).
"""
- from repoze.bfg.configuration import Configurator
import myapp
- configurator = Configurator(package=myapp)
- configurator.load_zcml('myapp:configure.zcml')
- testing.setUp(registry=configurator.registry)
+ self.config = Configurator(package=myapp)
+ self.config.begin()
+ self.config.load_zcml('myapp:configure.zcml')
def tearDown(self):
""" Clear out the application registry """
- testing.tearDown()
+ self.config.end()
def test_my_view(self):
from myapp.views import my_view