diff options
| author | Hunter Senft-Grupp <huntcsg@gmail.com> | 2018-05-14 17:13:30 -0400 |
|---|---|---|
| committer | Hunter Senft-Grupp <huntcsg@gmail.com> | 2018-05-15 13:40:26 -0400 |
| commit | efd61eb501a29970a3728a026ad0400eaff7e52d (patch) | |
| tree | 538314ef99faf6c41c41bb4f4a9514bedf0b171f | |
| parent | 21a9376b6c8535432eca527598013a0fbac9a461 (diff) | |
| download | pyramid-efd61eb501a29970a3728a026ad0400eaff7e52d.tar.gz pyramid-efd61eb501a29970a3728a026ad0400eaff7e52d.tar.bz2 pyramid-efd61eb501a29970a3728a026ad0400eaff7e52d.zip | |
Add Configurator context manager 'route_prefix_context' to allow for adding routes and including configuration callables with a particular route prefix.
| -rw-r--r-- | docs/narr/urldispatch.rst | 18 | ||||
| -rw-r--r-- | pyramid/config/__init__.py | 45 | ||||
| -rw-r--r-- | pyramid/config/routes.py | 51 | ||||
| -rw-r--r-- | pyramid/tests/test_url.py | 64 |
4 files changed, 149 insertions, 29 deletions
diff --git a/docs/narr/urldispatch.rst b/docs/narr/urldispatch.rst index 9ac01e24a..00c7bd3bf 100644 --- a/docs/narr/urldispatch.rst +++ b/docs/narr/urldispatch.rst @@ -1045,6 +1045,24 @@ may be added in the future. For example: config = Configurator() config.include(users_include, route_prefix='/users') +A convenience context manager exists to set the route prefix for any +:meth:`pyramid.config.Configurator.add_route` or +:meth:`pyramid.config.Configurator.include` calls within the context. + +.. code-block:: python + :linenos: + + from pyramid.config import Configurator + + def timing_include(config): + config.add_route('timing.show_times', '/times') + + def main(global_config, **settings) + config = Configurator() + with config.route_prefix_context('/timing'): + config.include(timing_include) + config.add_route('timing.average', '/average') + .. index:: single: route predicates (custom) diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py index a34f0b4db..886eec0df 100644 --- a/pyramid/config/__init__.py +++ b/pyramid/config/__init__.py @@ -790,21 +790,6 @@ class Configurator( action_state = self.action_state - if route_prefix is None: - route_prefix = '' - - old_route_prefix = self.route_prefix - if old_route_prefix is None: - old_route_prefix = '' - - route_prefix = '%s/%s' % ( - old_route_prefix.rstrip('/'), - route_prefix.lstrip('/') - ) - route_prefix = route_prefix.strip('/') - if not route_prefix: - route_prefix = None - c = self.maybe_dotted(callable) module = self.inspect.getmodule(c) if module is c: @@ -825,20 +810,22 @@ class Configurator( if action_state.processSpec(spec): - configurator = self.__class__( - registry=self.registry, - package=package_of(module), - root_package=self.root_package, - autocommit=self.autocommit, - route_prefix=route_prefix, - ) - configurator.basepath = os.path.dirname(sourcefile) - configurator.includepath = self.includepath + (spec,) - self.begin() - try: - c(configurator) - finally: - self.end() + with self.route_prefix_context(route_prefix): + configurator = self.__class__( + registry=self.registry, + package=package_of(module), + root_package=self.root_package, + autocommit=self.autocommit, + route_prefix=self.route_prefix, + ) + configurator.basepath = os.path.dirname(sourcefile) + configurator.includepath = self.includepath + (spec,) + + self.begin() + try: + c(configurator) + finally: + self.end() def add_directive(self, name, directive, action_wrap=True): """ diff --git a/pyramid/config/routes.py b/pyramid/config/routes.py index 203baa128..a83b424b6 100644 --- a/pyramid/config/routes.py +++ b/pyramid/config/routes.py @@ -1,3 +1,4 @@ +import contextlib import warnings from pyramid.compat import urlparse @@ -467,3 +468,53 @@ class RoutesConfiguratorMixin(object): self.registry.registerUtility(mapper, IRoutesMapper) return mapper + @contextlib.contextmanager + def route_prefix_context(self, route_prefix): + """ Return this configurator with the + :attr:`pyramid.config.Configurator.route_prefix` attribute mutated to + include the new ``route_prefix``. + + When the context exits, the ``route_prefix`` is reset to the original. + + Example Usage: + + >>> config = Configurator() + >>> with config.route_prefix_context('foo'): + ... config.add_route('bar', '/bar') + + Arguments + + route_prefix + + A string suitable to be used as a route prefix, or ``None``. + + .. versionadded:: 1.9.10 + """ + + original_route_prefix = self.route_prefix + + if route_prefix is None: + route_prefix = '' + + old_route_prefix = self.route_prefix + if old_route_prefix is None: + old_route_prefix = '' + + route_prefix = '{}/{}'.format( + old_route_prefix.rstrip('/'), + route_prefix.lstrip('/'), + ) + + route_prefix = route_prefix.strip('/') + + if not route_prefix: + route_prefix = None + + self.begin() + try: + self.route_prefix = route_prefix + yield + + finally: + self.route_prefix = original_route_prefix + self.end() diff --git a/pyramid/tests/test_url.py b/pyramid/tests/test_url.py index af2e5405c..31b3dd571 100644 --- a/pyramid/tests/test_url.py +++ b/pyramid/tests/test_url.py @@ -1251,6 +1251,70 @@ class Test_external_static_url_integration(unittest.TestCase): request.route_url('acme', foo='bar'), 'http://acme.org/bar') +class Test_with_route_prefix(unittest.TestCase): + + def setUp(self): + self.config = testing.setUp() + + def tearDown(self): + testing.tearDown() + + def _makeRequest(self, route): + from pyramid.request import Request + return Request.blank(route) + + def test_old_route_is_preserved(self): + self.config.route_prefix = 'old_prefix' + with self.config.route_prefix_context('new_addon'): + assert 'new_addon' in self.config.route_prefix + + assert 'old_prefix' == self.config.route_prefix + + def test_route_prefix_none(self): + self.config.route_prefix = 'old_prefix' + with self.config.route_prefix_context(None): + assert 'old_prefix' == self.config.route_prefix + + assert 'old_prefix' == self.config.route_prefix + + def test_route_prefix_empty(self): + self.config.route_prefix = 'old_prefix' + with self.config.route_prefix_context(''): + assert 'old_prefix' == self.config.route_prefix + + assert 'old_prefix' == self.config.route_prefix + + def test_route_has_prefix(self): + with self.config.route_prefix_context('bar'): + self.config.add_route('acme', '/foo') + request = self._makeRequest('/') + self.assertEqual( + request.route_url('acme'), + 'http://localhost/bar/foo', + ) + + def test_route_does_not_have_prefix(self): + with self.config.route_prefix_context('bar'): + pass + + self.config.add_route('acme', '/foo') + request = self._makeRequest('/') + self.assertEqual( + request.route_url('acme'), + 'http://localhost/foo', + ) + + def test_error_reset_prefix(self): + self.config.route_prefix = 'old_prefix' + + try: + with self.config.route_prefix_context('new_prefix'): + raise RuntimeError + except RuntimeError: + pass + + assert self.config.route_prefix == 'old_prefix' + class DummyContext(object): def __init__(self, next=None): self.next = next |
