diff options
Diffstat (limited to 'docs')
27 files changed, 269 insertions, 111 deletions
diff --git a/docs/api/configuration.rst b/docs/api/configuration.rst index 376ff3e40..5e16ac13b 100644 --- a/docs/api/configuration.rst +++ b/docs/api/configuration.rst @@ -7,6 +7,10 @@ .. autoclass:: Configurator(registry=None, package=None, settings=None, root_factory=None, authentication_policy=None, authorization_policy=None, renderers=DEFAULT_RENDERERS, debug_logger=None) + .. automethod:: begin + + .. automethod:: end + .. automethod:: add_renderer(name, factory) .. automethod:: add_route diff --git a/docs/glossary.rst b/docs/glossary.rst index 0fa827188..fab733878 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -509,3 +509,15 @@ Glossary :mod:`repoze.bfg` provides a default implementation of a forbidden view; it can be overridden. See :ref:`changing_the_forbidden_view`. + Thread Local + A thread-local variable is one which is essentially a global + variable in terms of how it is accessed and treated, however, + each `thread + <http://en.wikipedia.org/wiki/Thread_(computer_science)>` used by + the application may have a different value for this same "global" + variable. :mod:`repoze.bfg` uses a small number of thread local + variables, as described in :ref:`threadlocals_chapter`. See also + the `threading.local documentation + <http://docs.python.org/library/threading.html#threading.local>` + for more information. + 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 diff --git a/docs/tutorials/bfgwiki/src/authorization/tutorial/run.py b/docs/tutorials/bfgwiki/src/authorization/tutorial/run.py index 98baa440b..c80fce02a 100644 --- a/docs/tutorials/bfgwiki/src/authorization/tutorial/run.py +++ b/docs/tutorials/bfgwiki/src/authorization/tutorial/run.py @@ -15,6 +15,8 @@ def app(global_config, **settings): def get_root(request): return finder(request.environ) config = Configurator(root_factory=get_root, settings=settings) + config.begin() config.load_zcml('configure.zcml') + config.end() return config.make_wsgi_app() diff --git a/docs/tutorials/bfgwiki/src/authorization/tutorial/tests.py b/docs/tutorials/bfgwiki/src/authorization/tutorial/tests.py index fa025787e..6853bc376 100644 --- a/docs/tutorials/bfgwiki/src/authorization/tutorial/tests.py +++ b/docs/tutorials/bfgwiki/src/authorization/tutorial/tests.py @@ -94,7 +94,7 @@ class AddPageTests(unittest.TestCase): request = testing.DummyRequest({'form.submitted':True, 'body':'Hello yo!'}) request.subpath = ['AnotherPage'] - response = self._callFUT(context, request) + self._callFUT(context, request) page = context['AnotherPage'] self.assertEqual(page.data, 'Hello yo!') self.assertEqual(page.__name__, 'AnotherPage') diff --git a/docs/tutorials/bfgwiki/src/basiclayout/tutorial/run.py b/docs/tutorials/bfgwiki/src/basiclayout/tutorial/run.py index 748b13eef..7d4220717 100644 --- a/docs/tutorials/bfgwiki/src/basiclayout/tutorial/run.py +++ b/docs/tutorials/bfgwiki/src/basiclayout/tutorial/run.py @@ -15,5 +15,7 @@ def app(global_config, **settings): def get_root(request): return finder(request.environ) config = Configurator(root_factory=get_root, settings=settings) + config.begin() config.load_zcml('configure.zcml') + config.end() return config.make_wsgi_app() diff --git a/docs/tutorials/bfgwiki/src/basiclayout/tutorial/tests.py b/docs/tutorials/bfgwiki/src/basiclayout/tutorial/tests.py index 849e75ad4..32821ce0e 100644 --- a/docs/tutorials/bfgwiki/src/basiclayout/tutorial/tests.py +++ b/docs/tutorials/bfgwiki/src/basiclayout/tutorial/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 tutorial.views import my_view diff --git a/docs/tutorials/bfgwiki/src/models/tutorial/run.py b/docs/tutorials/bfgwiki/src/models/tutorial/run.py index 748b13eef..7d4220717 100644 --- a/docs/tutorials/bfgwiki/src/models/tutorial/run.py +++ b/docs/tutorials/bfgwiki/src/models/tutorial/run.py @@ -15,5 +15,7 @@ def app(global_config, **settings): def get_root(request): return finder(request.environ) config = Configurator(root_factory=get_root, settings=settings) + config.begin() config.load_zcml('configure.zcml') + config.end() return config.make_wsgi_app() diff --git a/docs/tutorials/bfgwiki/src/models/tutorial/tests.py b/docs/tutorials/bfgwiki/src/models/tutorial/tests.py index 1c1faf855..1eee68e7f 100644 --- a/docs/tutorials/bfgwiki/src/models/tutorial/tests.py +++ b/docs/tutorials/bfgwiki/src/models/tutorial/tests.py @@ -1,5 +1,6 @@ import unittest +from repoze.bfg.configuration import Configurator from repoze.bfg import testing class PageModelTests(unittest.TestCase): @@ -49,10 +50,11 @@ class AppmakerTests(unittest.TestCase): 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 tutorial.views import my_view diff --git a/docs/tutorials/bfgwiki/src/viewdecorators/tutorial/run.py b/docs/tutorials/bfgwiki/src/viewdecorators/tutorial/run.py index 748b13eef..7d4220717 100644 --- a/docs/tutorials/bfgwiki/src/viewdecorators/tutorial/run.py +++ b/docs/tutorials/bfgwiki/src/viewdecorators/tutorial/run.py @@ -15,5 +15,7 @@ def app(global_config, **settings): def get_root(request): return finder(request.environ) config = Configurator(root_factory=get_root, settings=settings) + config.begin() config.load_zcml('configure.zcml') + config.end() return config.make_wsgi_app() diff --git a/docs/tutorials/bfgwiki/src/viewdecorators/tutorial/tests.py b/docs/tutorials/bfgwiki/src/viewdecorators/tutorial/tests.py index fa025787e..6853bc376 100644 --- a/docs/tutorials/bfgwiki/src/viewdecorators/tutorial/tests.py +++ b/docs/tutorials/bfgwiki/src/viewdecorators/tutorial/tests.py @@ -94,7 +94,7 @@ class AddPageTests(unittest.TestCase): request = testing.DummyRequest({'form.submitted':True, 'body':'Hello yo!'}) request.subpath = ['AnotherPage'] - response = self._callFUT(context, request) + self._callFUT(context, request) page = context['AnotherPage'] self.assertEqual(page.data, 'Hello yo!') self.assertEqual(page.__name__, 'AnotherPage') diff --git a/docs/tutorials/bfgwiki/src/views/tutorial/run.py b/docs/tutorials/bfgwiki/src/views/tutorial/run.py index 748b13eef..7d4220717 100644 --- a/docs/tutorials/bfgwiki/src/views/tutorial/run.py +++ b/docs/tutorials/bfgwiki/src/views/tutorial/run.py @@ -15,5 +15,7 @@ def app(global_config, **settings): def get_root(request): return finder(request.environ) config = Configurator(root_factory=get_root, settings=settings) + config.begin() config.load_zcml('configure.zcml') + config.end() return config.make_wsgi_app() diff --git a/docs/tutorials/bfgwiki/src/views/tutorial/tests.py b/docs/tutorials/bfgwiki/src/views/tutorial/tests.py index 1b2ea972a..bbf86633a 100644 --- a/docs/tutorials/bfgwiki/src/views/tutorial/tests.py +++ b/docs/tutorials/bfgwiki/src/views/tutorial/tests.py @@ -94,7 +94,7 @@ class AddPageTests(unittest.TestCase): request = testing.DummyRequest({'form.submitted':True, 'body':'Hello yo!'}) request.subpath = ['AnotherPage'] - response = self._callFUT(context, request) + self._callFUT(context, request) page = context['AnotherPage'] self.assertEqual(page.data, 'Hello yo!') self.assertEqual(page.__name__, 'AnotherPage') diff --git a/docs/tutorials/bfgwiki2/src/authorization/tutorial/run.py b/docs/tutorials/bfgwiki2/src/authorization/tutorial/run.py index 9ca9fe71e..332f0408f 100644 --- a/docs/tutorials/bfgwiki2/src/authorization/tutorial/run.py +++ b/docs/tutorials/bfgwiki2/src/authorization/tutorial/run.py @@ -23,5 +23,7 @@ def app(global_config, **settings): raise ValueError("No 'db_string' value in application configuration.") initialize_sql(db_string) config = Configurator(settings=settings) + config.begin() config.load_zcml('configure.zcml') + config.end() return config.make_wsgi_app() diff --git a/docs/tutorials/bfgwiki2/src/authorization/tutorial/tests.py b/docs/tutorials/bfgwiki2/src/authorization/tutorial/tests.py index 52d2fed86..7bc8e11ce 100644 --- a/docs/tutorials/bfgwiki2/src/authorization/tutorial/tests.py +++ b/docs/tutorials/bfgwiki2/src/authorization/tutorial/tests.py @@ -1,4 +1,6 @@ import unittest + +from repoze.bfg.configuration import Configurator from repoze.bfg import testing def _initTestingDB(): @@ -11,21 +13,22 @@ def _initTestingDB(): Base.metadata.create_all(engine) return DBSession -def _registerRoutes(): - testing.registerRoute(':pagename', 'view_page') - testing.registerRoute(':pagename/edit_page', 'edit_page') - testing.registerRoute('add_page/:pagename', 'add_page') +def _registerRoutes(config): + config.add_route('view_page', ':pagename') + config.add_route('edit_page', ':pagename/edit_page') + config.add_route('add_page', 'add_page/:pagename') class ViewWikiTests(unittest.TestCase): def setUp(self): - testing.setUp() + self.config = Configurator() + self.config.begin() def tearDown(self): - testing.tearDown() + self.config.end() def test_it(self): from tutorial.views import view_wiki - testing.registerRoute(':pagename', 'view_page') + self.config.add_route('view_page', ':pagename') request = testing.DummyRequest() response = view_wiki(request) self.assertEqual(response.location, 'http://example.com/FrontPage') @@ -33,11 +36,12 @@ class ViewWikiTests(unittest.TestCase): class ViewPageTests(unittest.TestCase): def setUp(self): self.session = _initTestingDB() - testing.setUp() + self.config = Configurator() + self.config.begin() def tearDown(self): self.session.remove() - testing.tearDown() + self.config.end() def _callFUT(self, request): from tutorial.views import view_page @@ -49,7 +53,7 @@ class ViewPageTests(unittest.TestCase): request.matchdict['pagename'] = 'IDoExist' page = Page('IDoExist', 'Hello CruelWorld IDoExist') self.session.add(page) - _registerRoutes() + _registerRoutes(self.config) info = self._callFUT(request) self.assertEqual(info['page'], page) self.assertEqual( @@ -67,18 +71,19 @@ class ViewPageTests(unittest.TestCase): class AddPageTests(unittest.TestCase): def setUp(self): self.session = _initTestingDB() - testing.setUp() + self.config = Configurator() + self.config.begin() def tearDown(self): self.session.remove() - testing.tearDown() + self.config.end() def _callFUT(self, request): from tutorial.views import add_page return add_page(request) def test_it_notsubmitted(self): - _registerRoutes() + _registerRoutes(self.config) request = testing.DummyRequest() request.matchdict = {'pagename':'AnotherPage'} info = self._callFUT(request) @@ -88,22 +93,23 @@ class AddPageTests(unittest.TestCase): def test_it_submitted(self): from tutorial.models import Page - _registerRoutes() + _registerRoutes(self.config) request = testing.DummyRequest({'form.submitted':True, 'body':'Hello yo!'}) request.matchdict = {'pagename':'AnotherPage'} - response = self._callFUT(request) + self._callFUT(request) page = self.session.query(Page).filter_by(name='AnotherPage').one() self.assertEqual(page.data, 'Hello yo!') class EditPageTests(unittest.TestCase): def setUp(self): self.session = _initTestingDB() - testing.setUp() + self.config = Configurator() + self.config.begin() def tearDown(self): self.session.remove() - testing.tearDown() + self.config.end() def _callFUT(self, request): from tutorial.views import edit_page @@ -111,7 +117,7 @@ class EditPageTests(unittest.TestCase): def test_it_notsubmitted(self): from tutorial.models import Page - _registerRoutes() + _registerRoutes(self.config) request = testing.DummyRequest() request.matchdict = {'pagename':'abc'} page = Page('abc', 'hello') @@ -122,7 +128,7 @@ class EditPageTests(unittest.TestCase): def test_it_submitted(self): from tutorial.models import Page - _registerRoutes() + _registerRoutes(self.config) request = testing.DummyRequest({'form.submitted':True, 'body':'Hello yo!'}) request.matchdict = {'pagename':'abc'} diff --git a/docs/tutorials/bfgwiki2/src/basiclayout/tutorial/run.py b/docs/tutorials/bfgwiki2/src/basiclayout/tutorial/run.py index 9ca9fe71e..332f0408f 100644 --- a/docs/tutorials/bfgwiki2/src/basiclayout/tutorial/run.py +++ b/docs/tutorials/bfgwiki2/src/basiclayout/tutorial/run.py @@ -23,5 +23,7 @@ def app(global_config, **settings): raise ValueError("No 'db_string' value in application configuration.") initialize_sql(db_string) config = Configurator(settings=settings) + config.begin() config.load_zcml('configure.zcml') + config.end() return config.make_wsgi_app() diff --git a/docs/tutorials/bfgwiki2/src/basiclayout/tutorial/tests.py b/docs/tutorials/bfgwiki2/src/basiclayout/tutorial/tests.py index 0c44baf16..2ef74cce7 100644 --- a/docs/tutorials/bfgwiki2/src/basiclayout/tutorial/tests.py +++ b/docs/tutorials/bfgwiki2/src/basiclayout/tutorial/tests.py @@ -1,4 +1,5 @@ import unittest +from repoze.bfg.configuration import Configurator from repoze.bfg import testing def _initTestingDB(): @@ -8,11 +9,12 @@ def _initTestingDB(): class TestMyView(unittest.TestCase): def setUp(self): - testing.setUp() + self.config = Configurator() + self.config.begin() _initTestingDB() def tearDown(self): - testing.tearDown() + self.config.end() def test_it(self): from tutorial.views import my_view diff --git a/docs/tutorials/bfgwiki2/src/models/tutorial/run.py b/docs/tutorials/bfgwiki2/src/models/tutorial/run.py index 9ca9fe71e..332f0408f 100644 --- a/docs/tutorials/bfgwiki2/src/models/tutorial/run.py +++ b/docs/tutorials/bfgwiki2/src/models/tutorial/run.py @@ -23,5 +23,7 @@ def app(global_config, **settings): raise ValueError("No 'db_string' value in application configuration.") initialize_sql(db_string) config = Configurator(settings=settings) + config.begin() config.load_zcml('configure.zcml') + config.end() return config.make_wsgi_app() diff --git a/docs/tutorials/bfgwiki2/src/models/tutorial/tests.py b/docs/tutorials/bfgwiki2/src/models/tutorial/tests.py index 0c44baf16..2ef74cce7 100644 --- a/docs/tutorials/bfgwiki2/src/models/tutorial/tests.py +++ b/docs/tutorials/bfgwiki2/src/models/tutorial/tests.py @@ -1,4 +1,5 @@ import unittest +from repoze.bfg.configuration import Configurator from repoze.bfg import testing def _initTestingDB(): @@ -8,11 +9,12 @@ def _initTestingDB(): class TestMyView(unittest.TestCase): def setUp(self): - testing.setUp() + self.config = Configurator() + self.config.begin() _initTestingDB() def tearDown(self): - testing.tearDown() + self.config.end() def test_it(self): from tutorial.views import my_view diff --git a/docs/tutorials/bfgwiki2/src/views/tutorial/run.py b/docs/tutorials/bfgwiki2/src/views/tutorial/run.py index 9ca9fe71e..332f0408f 100644 --- a/docs/tutorials/bfgwiki2/src/views/tutorial/run.py +++ b/docs/tutorials/bfgwiki2/src/views/tutorial/run.py @@ -23,5 +23,7 @@ def app(global_config, **settings): raise ValueError("No 'db_string' value in application configuration.") initialize_sql(db_string) config = Configurator(settings=settings) + config.begin() config.load_zcml('configure.zcml') + config.end() return config.make_wsgi_app() diff --git a/docs/tutorials/bfgwiki2/src/views/tutorial/tests.py b/docs/tutorials/bfgwiki2/src/views/tutorial/tests.py index 52d2fed86..7bc8e11ce 100644 --- a/docs/tutorials/bfgwiki2/src/views/tutorial/tests.py +++ b/docs/tutorials/bfgwiki2/src/views/tutorial/tests.py @@ -1,4 +1,6 @@ import unittest + +from repoze.bfg.configuration import Configurator from repoze.bfg import testing def _initTestingDB(): @@ -11,21 +13,22 @@ def _initTestingDB(): Base.metadata.create_all(engine) return DBSession -def _registerRoutes(): - testing.registerRoute(':pagename', 'view_page') - testing.registerRoute(':pagename/edit_page', 'edit_page') - testing.registerRoute('add_page/:pagename', 'add_page') +def _registerRoutes(config): + config.add_route('view_page', ':pagename') + config.add_route('edit_page', ':pagename/edit_page') + config.add_route('add_page', 'add_page/:pagename') class ViewWikiTests(unittest.TestCase): def setUp(self): - testing.setUp() + self.config = Configurator() + self.config.begin() def tearDown(self): - testing.tearDown() + self.config.end() def test_it(self): from tutorial.views import view_wiki - testing.registerRoute(':pagename', 'view_page') + self.config.add_route('view_page', ':pagename') request = testing.DummyRequest() response = view_wiki(request) self.assertEqual(response.location, 'http://example.com/FrontPage') @@ -33,11 +36,12 @@ class ViewWikiTests(unittest.TestCase): class ViewPageTests(unittest.TestCase): def setUp(self): self.session = _initTestingDB() - testing.setUp() + self.config = Configurator() + self.config.begin() def tearDown(self): self.session.remove() - testing.tearDown() + self.config.end() def _callFUT(self, request): from tutorial.views import view_page @@ -49,7 +53,7 @@ class ViewPageTests(unittest.TestCase): request.matchdict['pagename'] = 'IDoExist' page = Page('IDoExist', 'Hello CruelWorld IDoExist') self.session.add(page) - _registerRoutes() + _registerRoutes(self.config) info = self._callFUT(request) self.assertEqual(info['page'], page) self.assertEqual( @@ -67,18 +71,19 @@ class ViewPageTests(unittest.TestCase): class AddPageTests(unittest.TestCase): def setUp(self): self.session = _initTestingDB() - testing.setUp() + self.config = Configurator() + self.config.begin() def tearDown(self): self.session.remove() - testing.tearDown() + self.config.end() def _callFUT(self, request): from tutorial.views import add_page return add_page(request) def test_it_notsubmitted(self): - _registerRoutes() + _registerRoutes(self.config) request = testing.DummyRequest() request.matchdict = {'pagename':'AnotherPage'} info = self._callFUT(request) @@ -88,22 +93,23 @@ class AddPageTests(unittest.TestCase): def test_it_submitted(self): from tutorial.models import Page - _registerRoutes() + _registerRoutes(self.config) request = testing.DummyRequest({'form.submitted':True, 'body':'Hello yo!'}) request.matchdict = {'pagename':'AnotherPage'} - response = self._callFUT(request) + self._callFUT(request) page = self.session.query(Page).filter_by(name='AnotherPage').one() self.assertEqual(page.data, 'Hello yo!') class EditPageTests(unittest.TestCase): def setUp(self): self.session = _initTestingDB() - testing.setUp() + self.config = Configurator() + self.config.begin() def tearDown(self): self.session.remove() - testing.tearDown() + self.config.end() def _callFUT(self, request): from tutorial.views import edit_page @@ -111,7 +117,7 @@ class EditPageTests(unittest.TestCase): def test_it_notsubmitted(self): from tutorial.models import Page - _registerRoutes() + _registerRoutes(self.config) request = testing.DummyRequest() request.matchdict = {'pagename':'abc'} page = Page('abc', 'hello') @@ -122,7 +128,7 @@ class EditPageTests(unittest.TestCase): def test_it_submitted(self): from tutorial.models import Page - _registerRoutes() + _registerRoutes(self.config) request = testing.DummyRequest({'form.submitted':True, 'body':'Hello yo!'}) request.matchdict = {'pagename':'abc'} diff --git a/docs/whatsnew-1.2.rst b/docs/whatsnew-1.2.rst index c417ba3ae..4332c9948 100644 --- a/docs/whatsnew-1.2.rst +++ b/docs/whatsnew-1.2.rst @@ -41,7 +41,9 @@ The simplest possible :mod:`repoze.bfg` application is now: if __name__ == '__main__': config = Configurator() + config.begin() config.add_view(hello_world) + config.end() app = config.make_wsgi_app() simple_server.make_server('', 8080, app).serve_forever() @@ -141,10 +143,11 @@ Backwards Incompatibilites - When there is no "current registry" in the ``repoze.bfg.threadlocal.manager`` threadlocal data structure (this is the case when there is no "current request" or we're not in the - midst of a ``r.b.testing.setUp``-bounded unit test), the ``.get`` - method of the manager returns a data structure containing a *global* - registry. In previous releases, this function returned the global - Zope "base" registry: the result of + midst of a ``r.b.testing.setUp`` or + ``r.b.configuration.Configurator.begin`` bounded unit test), the + ``.get`` method of the manager returns a data structure containing a + *global* registry. In previous releases, this function returned the + global Zope "base" registry: the result of ``zope.component.getGlobalSiteManager``, which is an instance of the ``zope.component.registry.Component`` class. In this release, however, the global registry returns a globally importable instance @@ -153,8 +156,8 @@ Backwards Incompatibilites ``repoze.bfg.registry.global_registry``. Effectively, this means that when you call - ``repoze.bfg.threadlocal.get_current_registry`` when no request or - ``setUp`` bounded unit test is in effect, you will always get back + ``repoze.bfg.threadlocal.get_current_registry`` when no "real" + request or bounded unit test is in effect, you will always get back the global registry that lives in ``repoze.bfg.registry.global_registry``. It also means that :mod:`repoze.bfg` APIs that *call* ``get_current_registry`` will use |
