summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHunter Senft-Grupp <huntcsg@gmail.com>2018-05-14 17:13:30 -0400
committerHunter Senft-Grupp <huntcsg@gmail.com>2018-05-15 13:40:26 -0400
commitefd61eb501a29970a3728a026ad0400eaff7e52d (patch)
tree538314ef99faf6c41c41bb4f4a9514bedf0b171f
parent21a9376b6c8535432eca527598013a0fbac9a461 (diff)
downloadpyramid-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.rst18
-rw-r--r--pyramid/config/__init__.py45
-rw-r--r--pyramid/config/routes.py51
-rw-r--r--pyramid/tests/test_url.py64
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