summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2016-12-16 00:48:52 -0600
committerMichael Merickel <michael@merickel.org>2017-04-02 20:08:22 -0500
commit134ef7e8d17842e286528aeb8d2936579ed81053 (patch)
tree7bc97527b0de63ecbd7be01aef3e9b766a714bf4
parentb536bd9db1c435586c476c6d03e3d314979af3ab (diff)
downloadpyramid-134ef7e8d17842e286528aeb8d2936579ed81053.tar.gz
pyramid-134ef7e8d17842e286528aeb8d2936579ed81053.tar.bz2
pyramid-134ef7e8d17842e286528aeb8d2936579ed81053.zip
turn the Configurator into a context manager
fixes #2872
-rw-r--r--README.rst8
-rw-r--r--pyramid/config/__init__.py40
-rw-r--r--pyramid/tests/test_config/test_init.py16
3 files changed, 58 insertions, 6 deletions
diff --git a/README.rst b/README.rst
index f05dd8bbf..302590fe1 100644
--- a/README.rst
+++ b/README.rst
@@ -31,10 +31,10 @@ and deployment more fun, more predictable, and more productive.
return Response('Hello %(name)s!' % request.matchdict)
if __name__ == '__main__':
- config = Configurator()
- config.add_route('hello', '/hello/{name}')
- config.add_view(hello_world, route_name='hello')
- app = config.make_wsgi_app()
+ with Configurator() as config:
+ config.add_route('hello', '/hello/{name}')
+ config.add_view(hello_world, route_name='hello')
+ app = config.make_wsgi_app()
server = make_server('0.0.0.0', 8080, app)
server.serve_forever()
diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py
index 6c661aa59..bcd4b3904 100644
--- a/pyramid/config/__init__.py
+++ b/pyramid/config/__init__.py
@@ -110,6 +110,17 @@ class Configurator(
A Configurator is used to configure a :app:`Pyramid`
:term:`application registry`.
+ The Configurator lifecycle can be managed by using a context manager to
+ automatically handle calling :meth:`pyramid.config.Configurator.begin` and
+ :meth:`pyramid.config.Configurator.end` as well as
+ :meth:`pyramid.config.Configurator.commit`.
+
+ .. code-block:: python
+
+ with Configurator(settings=settings) as config:
+ config.add_route('home', '/')
+ app = config.make_wsgi_app()
+
If the ``registry`` argument is not ``None``, it must
be an instance of the :class:`pyramid.registry.Registry` class
representing the registry to configure. If ``registry`` is ``None``, the
@@ -265,6 +276,11 @@ class Configurator(
.. versionadded:: 1.6
The ``root_package`` argument.
The ``response_factory`` argument.
+
+ .. versionadded:: 1.9
+ The ability to use the configurator as a context manager with the
+ ``with``-statement to make threadlocal configuration available for
+ further configuration with an implicit commit.
"""
manager = manager # for testing injection
venusian = venusian # for testing injection
@@ -646,12 +662,22 @@ class Configurator(
_ctx = action_state # bw compat
def commit(self):
- """ Commit any pending configuration actions. If a configuration
+ """
+ Commit any pending configuration actions. If a configuration
conflict is detected in the pending configuration actions, this method
will raise a :exc:`ConfigurationConflictError`; within the traceback
of this error will be information about the source of the conflict,
usually including file names and line numbers of the cause of the
- configuration conflicts."""
+ configuration conflicts.
+
+ .. warning::
+ You should think very carefully before manually invoking
+ ``commit()``. Especially not as part of any reusable configuration
+ methods. Normally it should only be done by an application author at
+ the end of configuration in order to override certain aspects of an
+ addon.
+
+ """
self.begin()
try:
self.action_state.execute_actions(introspector=self.introspector)
@@ -933,6 +959,16 @@ class Configurator(
"""
return self.manager.pop()
+ def __enter__(self):
+ self.begin()
+ return self
+
+ def __exit__(self, exc_type, exc_value, exc_traceback):
+ self.end()
+
+ if exc_value is None:
+ self.commit()
+
# this is *not* an action method (uses caller_package)
def scan(self, package=None, categories=None, onerror=None, ignore=None,
**kw):
diff --git a/pyramid/tests/test_config/test_init.py b/pyramid/tests/test_config/test_init.py
index 53c601537..ab584cc3d 100644
--- a/pyramid/tests/test_config/test_init.py
+++ b/pyramid/tests/test_config/test_init.py
@@ -141,6 +141,22 @@ class ConfiguratorTests(unittest.TestCase):
self.assertEqual(manager.pushed, pushed)
self.assertEqual(manager.popped, True)
+ def test_context_manager(self):
+ from pyramid.config import Configurator
+ config = Configurator()
+ manager = DummyThreadLocalManager()
+ config.manager = manager
+ view = lambda r: None
+ with config as ctx:
+ self.assertTrue(config is ctx)
+ self.assertEqual(manager.pushed,
+ {'registry': config.registry, 'request': None})
+ self.assertFalse(manager.popped)
+ config.add_view(view)
+ self.assertTrue(manager.popped)
+ config.add_view(view) # did not raise a conflict because of commit
+ config.commit()
+
def test_ctor_with_package_registry(self):
import sys
from pyramid.config import Configurator