summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAtsushi Odagiri <aodagx@gmail.com>2011-07-07 06:06:01 -0700
committerAtsushi Odagiri <aodagx@gmail.com>2011-07-07 06:06:01 -0700
commit9a8ba2f09fe3791febbfec2ac383c091aacfbf5b (patch)
tree62883da3a7131003814a1ebaf04c1d185ac9e571
parent8be2e08bfe7fdf527a6fde74bb7544b312e28897 (diff)
parent4880e19588da868f6075fc73d1f6ee1eb1e6ba6e (diff)
downloadpyramid-9a8ba2f09fe3791febbfec2ac383c091aacfbf5b.tar.gz
pyramid-9a8ba2f09fe3791febbfec2ac383c091aacfbf5b.tar.bz2
pyramid-9a8ba2f09fe3791febbfec2ac383c091aacfbf5b.zip
Merge pull request #1 from mmerickel/feature.mount
Refactored the subapp mounting into config.include()
-rw-r--r--pyramid/config.py110
-rw-r--r--pyramid/tests/test_config.py28
2 files changed, 61 insertions, 77 deletions
diff --git a/pyramid/config.py b/pyramid/config.py
index 61463eb86..bad12fc20 100644
--- a/pyramid/config.py
+++ b/pyramid/config.py
@@ -269,7 +269,11 @@ class Configurator(object):
Pyramid's caller. By
default, the ``pyramid.httpexceptions.default_exceptionresponse_view``
function is used as the ``exceptionresponse_view``. This argument is new
- in Pyramid 1.1. """
+ in Pyramid 1.1.
+
+ If ``route_prefix`` is passed, all routes added with
+ :meth:`pyramid.config.Configurator.add_route` will have the specified path
+ prepended to their pattern. This parameter is new in Pyramid 1.x."""
manager = manager # for testing injection
venusian = venusian # for testing injection
@@ -293,7 +297,7 @@ class Configurator(object):
default_view_mapper=None,
autocommit=False,
exceptionresponse_view=default_exceptionresponse_view,
- root_route_name=None,
+ route_prefix=None,
):
if package is None:
package = caller_package()
@@ -303,7 +307,7 @@ class Configurator(object):
self.package = name_resolver.package
self.registry = registry
self.autocommit = autocommit
- self.root_route_name = root_route_name
+ self.route_prefix = route_prefix
if registry is None:
registry = Registry(self.package_name)
self.registry = registry
@@ -455,6 +459,7 @@ class Configurator(object):
registerCommonDirectives(context)
context.registry = self.registry
context.autocommit = autocommit
+ context.route_prefix = self.route_prefix
return context
# API
@@ -522,10 +527,14 @@ class Configurator(object):
# unwrap and reset the context
self._ctx = None
- def include(self, *callables):
- """Include one or more configuration callables, to support imperative
+ def include(self, callable, route_prefix=None):
+ """Include a configuration callables, to support imperative
application extensibility.
+ .. warning:: In versions of :app:`Pyramid` prior to 1.x, this
+ function accepted ``*callables``, but this has been changed
+ to support only a single callable.
+
A configuration callable should be a callable that accepts a single
argument named ``config``, which will be an instance of a
:term:`Configurator` (be warned that it will not be the same
@@ -534,7 +543,7 @@ class Configurator(object):
methods on the configurator passed to it which add configuration
state. The return value of a callable will be ignored.
- Values allowed to be presented via the ``*callables`` argument to
+ Values allowed to be presented via the ``callable`` argument to
this method: any callable Python object or any :term:`dotted Python
name` which resolves to a callable Python object. It may also be a
Python :term:`module`, in which case, the module will be searched for
@@ -583,65 +592,41 @@ class Configurator(object):
Included configuration statements will be overridden by local
configuration statements if an included callable causes a
configuration conflict by registering something with the same
- configuration parameters."""
+ configuration parameters.
+
+ If the ``route_prefix`` is supplied, any calls to
+ :meth:`pyramid.config.Configurator.add_route` within the ``callable``
+ will have their pattern prefixed with ``route_prefix``. This can
+ be used to help mount a set of routes at a different location than
+ the ``callable``-author intended while still maintaining the same
+ route names. This parameter is new as of Pyramid 1.x."""
_context = self._ctx
if _context is None:
_context = self._ctx = self._make_context(self.autocommit)
- for c in callables:
- c = self.maybe_dotted(c)
- module = inspect.getmodule(c)
- if module is c:
- c = getattr(module, 'includeme')
- spec = module.__name__ + ':' + c.__name__
- sourcefile = inspect.getsourcefile(c)
- if _context.processSpec(spec):
- context = GroupingContextDecorator(_context)
- context.basepath = os.path.dirname(sourcefile)
- context.includepath = _context.includepath + (spec,)
- context.package = package_of(module)
- config = self.__class__.with_context(context)
- c(config)
-
- def with_route_prefix(self, route_prefix):
- configurator = self.__class__(registry=self.registry,
- package=self.package,
- autocommit=self.autocommit)
- configurator.route_prefix = route_prefix
- return configurator
-
- def mount_subapplication(self, function, route_prefix):
- """ mount subapplication with ``route_prefix``
-
-
- .. code-block:: python
- :linenos:
-
- from pyramid.config import Configurator
-
- def main(global_config, **settings):
- config = Configurator()
- config.mount('myapp.myconfig.includeme', '/admin')
-
- ``myapp.myconfig`` is subapplication
- and ``includeme`` is that mount point.
-
- .. code-block:: python
- :linenos:
-
- from pyramid.config import Configurator
-
- def includeme(config):
- config.add_route('projects', '/projects')
-
-
- Subapplication's routes are registerd with the ``route_prefix``
- In this case, ``projects`` route is registered with ``/admin/projects`` pattern.
- """
- function = self.maybe_dotted(function)
- config = self.with_route_prefix(route_prefix)
- function(config)
+ if self.route_prefix:
+ old_prefix = self.route_prefix.rstrip('/') + '/'
+ else:
+ old_prefix = ''
+
+ if route_prefix:
+ route_prefix = old_prefix + route_prefix.lstrip('/')
+
+ c = self.maybe_dotted(callable)
+ module = inspect.getmodule(c)
+ if module is c:
+ c = getattr(module, 'includeme')
+ spec = module.__name__ + ':' + c.__name__
+ sourcefile = inspect.getsourcefile(c)
+ if _context.processSpec(spec):
+ context = GroupingContextDecorator(_context)
+ context.basepath = os.path.dirname(sourcefile)
+ context.includepath = _context.includepath + (spec,)
+ context.package = package_of(module)
+ context.route_prefix = route_prefix
+ config = self.__class__.with_context(context)
+ c(config)
def add_directive(self, name, directive, action_wrap=True):
"""
@@ -689,7 +674,8 @@ class Configurator(object):
:meth:`pyramid.config.Configurator.include` to obtain a configurator
with 'the right' context. Returns a new Configurator instance."""
configurator = cls(registry=context.registry, package=context.package,
- autocommit=context.autocommit)
+ autocommit=context.autocommit,
+ route_prefix=context.route_prefix)
configurator._ctx = context
return configurator
@@ -1972,7 +1958,7 @@ class Configurator(object):
if pattern is None:
raise ConfigurationError('"pattern" argument may not be None')
- if hasattr(self, "route_prefix"):
+ if self.route_prefix:
pattern = self.route_prefix.rstrip('/') + '/' + pattern.lstrip('/')
discriminator = ['route', name, xhr, request_method, path_info,
diff --git a/pyramid/tests/test_config.py b/pyramid/tests/test_config.py
index 3423b9784..9a92cd052 100644
--- a/pyramid/tests/test_config.py
+++ b/pyramid/tests/test_config.py
@@ -251,6 +251,7 @@ class ConfiguratorTests(unittest.TestCase):
config._ctx = DummyContext()
config._ctx.registry = None
config._ctx.autocommit = True
+ config._ctx.route_prefix = None
newconfig = config.with_package(pyramid.tests)
self.assertEqual(newconfig.package, pyramid.tests)
@@ -735,6 +736,18 @@ class ConfiguratorTests(unittest.TestCase):
self.assertEqual(context_after.includepath, ())
self.assertTrue(context_after is context_before)
+ def test_include_with_route_prefix(self):
+ root_config = self._makeOne(autocommit=True)
+ def dummy_subapp(config):
+ self.assertEqual(config.route_prefix, 'root')
+ root_config.include(dummy_subapp, route_prefix='root')
+
+ def test_include_with_nested_route_prefix(self):
+ root_config = self._makeOne(autocommit=True, route_prefix='root')
+ def dummy_subapp(config):
+ self.assertEqual(config.route_prefix, 'root/nested')
+ root_config.include(dummy_subapp, route_prefix='nested')
+
def test_with_context(self):
config = self._makeOne()
ctx = config._make_context()
@@ -1997,7 +2010,6 @@ class ConfiguratorTests(unittest.TestCase):
self.assertEqual(route.name, 'name')
def test_add_route_with_route_prefix(self):
- from pyramid.interfaces import IRoutesMapper
config = self._makeOne(autocommit=True)
config.route_prefix = 'root'
route = config.add_route('name', 'path')
@@ -2006,20 +2018,6 @@ class ConfiguratorTests(unittest.TestCase):
self._assertRoute(config, 'name', 'root/path')
- def test_with_route_prefix(self):
- root_config = self._makeOne(autocommit=True)
- config = root_config.with_route_prefix('root')
- self.assertEqual(config.registry, root_config.registry)
- self.assertEqual(config.package, root_config.package)
- self.assertEqual(config.route_prefix, 'root')
-
- def test_mount_subapplication(self):
- root_config = self._makeOne(autocommit=True)
- def dummy_subapp(config):
- self.assertEqual(config.route_prefix, 'root')
- root_config.mount_subapplication(dummy_subapp,
- route_prefix='root')
-
def test_add_route_with_factory(self):
config = self._makeOne(autocommit=True)
factory = object()