From 446967a9e2f682ca523cbcaa1e8ac4b009331ec5 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Tue, 7 Dec 2010 21:43:04 -0500 Subject: add an integration test for include, make sure the same callable is not processed more than once --- pyramid/configuration.py | 27 +++++++++++++++++----- pyramid/tests/includeapp1/__init__.py | 1 + pyramid/tests/includeapp1/root.py | 10 +++++++++ pyramid/tests/includeapp1/three.py | 9 ++++++++ pyramid/tests/includeapp1/two.py | 9 ++++++++ pyramid/tests/test_configuration.py | 42 +++++++++++++++++++++++++++++++++++ pyramid/tests/test_integration.py | 26 ++++++++++++++++++++++ 7 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 pyramid/tests/includeapp1/__init__.py create mode 100644 pyramid/tests/includeapp1/root.py create mode 100644 pyramid/tests/includeapp1/three.py create mode 100644 pyramid/tests/includeapp1/two.py diff --git a/pyramid/configuration.py b/pyramid/configuration.py index 2135c6d57..8cdb7512b 100644 --- a/pyramid/configuration.py +++ b/pyramid/configuration.py @@ -389,6 +389,7 @@ class Configurator(object): def _make_context(self): context = PyramidConfigurationMachine() registerCommonDirectives(context) + context.registry = self.registry return context # API @@ -397,7 +398,6 @@ class Configurator(object): """ Commit pending configuration actions. """ self._ctx.execute_actions() self._ctx = self._make_context() - self._ctx.registry = self.registry def with_package(self, package, _ctx=None): """ Return a new Configurator instance with the same registry @@ -746,11 +746,13 @@ class Configurator(object): _context = self._ctx for filename, func, module in sourcefiles: - context = GroupingContextDecorator(_context) - context.basepath = os.path.dirname(filename) - context.includepath = _context.includepath + (filename,) - context.package = package_of(module) - func(Configurator.with_context(context)) + spec = module.__name__ + ':' + func.__name__ + if _context.processSpec(spec): + context = GroupingContextDecorator(_context) + context.basepath = os.path.dirname(filename) + context.includepath = _context.includepath + (spec,) + context.package = package_of(module) + func(Configurator.with_context(context)) def add_handler(self, route_name, pattern, handler, action=None, **kw): @@ -2894,3 +2896,16 @@ class PyramidConfigurationMachine(ConfigurationMachine): except: return '' + def processSpec(self, spec): + """Check whether a callable needs to be processed. The ``spec`` + refers to a unique identifier for the callable. + + Return True if processing is needed and False otherwise. If + the callablke needs to be processed, it will be marked as + processed, assuming that the caller will procces the callable if + it needs to be processed. + """ + if spec in self._seen_files: + return False + self._seen_files.add(spec) + return True diff --git a/pyramid/tests/includeapp1/__init__.py b/pyramid/tests/includeapp1/__init__.py new file mode 100644 index 000000000..eaeeb7ef6 --- /dev/null +++ b/pyramid/tests/includeapp1/__init__.py @@ -0,0 +1 @@ +# include app diff --git a/pyramid/tests/includeapp1/root.py b/pyramid/tests/includeapp1/root.py new file mode 100644 index 000000000..3b042c8c2 --- /dev/null +++ b/pyramid/tests/includeapp1/root.py @@ -0,0 +1,10 @@ +from pyramid.response import Response + +def aview(request): + return Response('root') + +def configure(config): + config.add_view(aview) + config.include('pyramid.tests.includeapp1.two.configure') + config.commit() + diff --git a/pyramid/tests/includeapp1/three.py b/pyramid/tests/includeapp1/three.py new file mode 100644 index 000000000..a921bcd10 --- /dev/null +++ b/pyramid/tests/includeapp1/three.py @@ -0,0 +1,9 @@ +from pyramid.response import Response + +def aview(request): + return Response('three') + +def configure(config): + config.add_view(aview, name='three') + config.add_view(aview) # will be overridden by root when resolved + diff --git a/pyramid/tests/includeapp1/two.py b/pyramid/tests/includeapp1/two.py new file mode 100644 index 000000000..960d77e3d --- /dev/null +++ b/pyramid/tests/includeapp1/two.py @@ -0,0 +1,9 @@ +from pyramid.response import Response + +def aview(request): + return Response('two') + +def configure(config): + config.add_view(aview, name='two') + config.include('pyramid.tests.includeapp1.three.configure') + config.add_view(aview) # will be overridden by root when resolved diff --git a/pyramid/tests/test_configuration.py b/pyramid/tests/test_configuration.py index 488be73eb..21f6a4f44 100644 --- a/pyramid/tests/test_configuration.py +++ b/pyramid/tests/test_configuration.py @@ -3442,6 +3442,48 @@ class ConfiguratorTests(unittest.TestCase): config.add_view(view2) self.assertRaises(ConfigurationConflictError, config.commit) + def test_commit_conflict_resolved_with_include(self): + config = self._makeOne() + def view1(request): pass + def view2(request): pass + def includeme(config): + config.add_view(view2) + config.add_view(view1) + config.include(includeme) + config.commit() + registeredview = self._getViewCallable(config) + self.assertEqual(registeredview.__name__, 'view1') + + def test_commit_conflict_with_two_includes(self): + from zope.configuration.config import ConfigurationConflictError + config = self._makeOne() + def view1(request): pass + def view2(request): pass + def includeme1(config): + config.add_view(view1) + def includeme2(config): + config.add_view(view2) + config.include(includeme1) + config.include(includeme2) + self.assertRaises(ConfigurationConflictError, config.commit) + + def test_commit_conflict_resolved_with_two_includes_and_local(self): + from zope.configuration.config import ConfigurationConflictError + config = self._makeOne() + def view1(request): pass + def view2(request): pass + def view3(request): pass + def includeme1(config): + config.add_view(view1) + def includeme2(config): + config.add_view(view2) + config.include(includeme1) + config.include(includeme2) + config.add_view(view3) + config.commit() + registeredview = self._getViewCallable(config) + self.assertEqual(registeredview.__name__, 'view3') + class Test__map_view(unittest.TestCase): def setUp(self): from pyramid.registry import Registry diff --git a/pyramid/tests/test_integration.py b/pyramid/tests/test_integration.py index 9e9ea78b2..7dc74aaf8 100644 --- a/pyramid/tests/test_integration.py +++ b/pyramid/tests/test_integration.py @@ -241,6 +241,32 @@ class TestExceptionViewsApp(IntegrationBase): res = self.testapp.get('/route_raise_exception4', status=200) self.failUnless('whoa' in res.body) +class ImperativeIncludeConfigurationTest(unittest.TestCase): + def setUp(self): + from pyramid.configuration import Configurator + config = Configurator() + from pyramid.tests.includeapp1.root import configure + configure(config) + app = config.make_wsgi_app() + from webtest import TestApp + self.testapp = TestApp(app) + self.config = config + + def tearDown(self): + self.config.end() + + def test_root(self): + res = self.testapp.get('/', status=200) + self.failUnless('root' in res.body) + + def test_two(self): + res = self.testapp.get('/two', status=200) + self.failUnless('two' in res.body) + + def test_three(self): + res = self.testapp.get('/three', status=200) + self.failUnless('three' in res.body) + class DummyContext(object): pass -- cgit v1.2.3