diff options
| author | Chris McDonough <chrism@plope.com> | 2011-09-03 21:44:27 -0400 |
|---|---|---|
| committer | Chris McDonough <chrism@plope.com> | 2011-09-03 21:44:27 -0400 |
| commit | b86fa95c850130e1b21b804f9fb87666a80dbe18 (patch) | |
| tree | e1f270f128dc1369214eec702a47c1e974a01798 | |
| parent | 940ab0d43fd38588da3b5d7937e8787287b7c000 (diff) | |
| download | pyramid-b86fa95c850130e1b21b804f9fb87666a80dbe18.tar.gz pyramid-b86fa95c850130e1b21b804f9fb87666a80dbe18.tar.bz2 pyramid-b86fa95c850130e1b21b804f9fb87666a80dbe18.zip | |
all tests pass; pyramid_zcml still broken with this branch
| -rw-r--r-- | pyramid/config/__init__.py | 159 | ||||
| -rw-r--r-- | pyramid/tests/test_config/test_init.py | 179 | ||||
| -rw-r--r-- | pyramid/tests/test_config/test_routes.py | 2 |
3 files changed, 163 insertions, 177 deletions
diff --git a/pyramid/config/__init__.py b/pyramid/config/__init__.py index a3cec37fe..067448c9a 100644 --- a/pyramid/config/__init__.py +++ b/pyramid/config/__init__.py @@ -205,8 +205,10 @@ class Configurator( manager = manager # for testing injection venusian = venusian # for testing injection - _ctx = None _ainfo = None + basepath = None + includepath = () + info = '' def __init__(self, registry=None, @@ -442,20 +444,14 @@ class Configurator( if kw is None: kw = {} - context = self._ctx - - if context is None: - autocommit = self.autocommit - else: - autocommit = context.autocommit + autocommit = self.autocommit if autocommit: if callable is not None: callable(*args, **kw) + else: - if context is None: # defer expensive creation of context - context = self._ctx = self._make_context(self.autocommit) - info = context.info + info = self.info if not info: # Try to provide more accurate info for conflict reports by # wrapping the context in a decorator and attaching caller info @@ -465,7 +461,29 @@ class Configurator( info = self._ainfo[0] else: info = '' - context.action(discriminator, callable, args, kw, order, info=info) + self.action_state.action( + discriminator, + callable, + args, + kw, + order, + info=info, + includepath=self.includepath, + ) + + def _get_action_state(self): + registry = self.registry + try: + state = registry.action_state + except AttributeError: + state = ActionState() + registry.action_state = state + return state + + def _set_action_state(self, state): + self.registry.action_state = state + + action_state = property(_get_action_state, _set_action_state) def commit(self): """ Commit any pending configuration actions. If a configuration @@ -474,11 +492,8 @@ class Configurator( 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.""" - if self._ctx is None: - return - self._ctx.execute_actions() - # unwrap and reset the context - self._ctx = None + self.action_state.execute_actions() + self.action_state = ActionState() # old actions have been processed def include(self, callable, route_prefix=None): """Include a configuration callables, to support imperative @@ -502,7 +517,7 @@ class Configurator( Python :term:`module`, in which case, the module will be searched for a callable named ``includeme``, which will be treated as the configuration callable. - + For example, if the ``includeme`` function below lives in a module named ``myapp.myconfig``: @@ -573,10 +588,9 @@ class Configurator( The ``route_prefix`` parameter is new as of Pyramid 1.2. """ + ## """ <-- emacs gets confused if this isn't here - _context = self._ctx - if _context is None: - _context = self._ctx = self._make_context(self.autocommit) + action_state = self.action_state if self.route_prefix: old_prefix = self.route_prefix.rstrip('/') + '/' @@ -592,15 +606,18 @@ class Configurator( c = getattr(module, 'includeme') spec = module.__name__ + ':' + c.__name__ sourcefile = inspect.getsourcefile(c) - if _context.processSpec(spec): - context = ActionStateWrapper(_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) + if action_state.processSpec(spec): + configurator = self.__class__( + registry=self.registry, + package=package_of(module), + autocommit=self.autocommit, + route_prefix=route_prefix, + ) + configurator.basepath = os.path.dirname(sourcefile) + configurator.includepath = self.includepath + (spec,) + c(configurator) + def add_directive(self, name, directive, action_wrap=True): """ Add a directive method to the configurator. @@ -650,10 +667,15 @@ class Configurator( :meth:`pyramid.config.Configurator.with_package`, and :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, - route_prefix=context.route_prefix) - configurator._ctx = context + configurator = cls( + registry=context.registry, + package=context.package, + autocommit=context.autocommit, + route_prefix=context.route_prefix + ) + configurator.basepath = context.basepath + configurator.includepath = context.includepath + configurator.info = context.info return configurator def with_package(self, package): @@ -662,12 +684,16 @@ class Configurator( ``package`` argument to the new configurator. ``package`` may be an actual Python package object or a :term:`dotted Python name` representing a package.""" - context = self._ctx - if context is None: - context = self._ctx = self._make_context(self.autocommit) - context = ActionStateWrapper(context) - context.package = package - return self.__class__.with_context(context) + configurator = self.__class__( + registry=self.registry, + package=package, + autocommit=self.autocommit, + route_prefix=self.route_prefix, + ) + configurator.basepath = self.basepath + configurator.includepath = self.includepath + configurator.info = self.info + return configurator def maybe_dotted(self, dotted): """ Resolve the :term:`dotted Python name` ``dotted`` to a @@ -788,8 +814,9 @@ class Configurator( return app -class ActionStateBase(object): +class ActionState(object): def __init__(self): + self.actions = [] self._seen_files = set() def processSpec(self, spec): @@ -806,8 +833,8 @@ class ActionStateBase(object): self._seen_files.add(spec) return True - def action(self, discriminator, callable=None, args=(), kw={}, order=0, - includepath=None, info=None): + def action(self, discriminator, callable=None, args=(), kw=None, order=0, + includepath=(), info=''): """Add an action with the given discriminator, callable and arguments For testing purposes, the callable and arguments may be omitted. @@ -869,45 +896,14 @@ class ActionStateBase(object): (None, None, (), {}, ('foo.zcml',), 'abc') """ - if info is None: - info = getattr(self, 'info', '') - - if includepath is None: - includepath = getattr(self, 'includepath', ()) - + if kw is None: + kw = {} action = (discriminator, callable, args, kw, includepath, info, order) - # remove trailing false items while (len(action) > 2) and not action[-1]: action = action[:-1] - self.actions.append(action) - -class ActionStateWrapper(ActionStateBase): - """ Wrap an action state. - """ - def __init__(self, state): - self.state = state - - def __getattr__(self, name): - v = getattr(self.state, name) - # cache result in self - setattr(self, name, v) - return v - -class ActionState(ActionStateBase): - autocommit = False - route_prefix = None - package = None - basepath = None - includepath = () - info = '' - - def __init__(self): - super(ActionState, self).__init__() - self.actions = [] - def execute_actions(self, clear=True): """Execute the configuration actions @@ -959,8 +955,7 @@ class ActionState(ActionStateBase): """ try: for action in resolveConflicts(self.actions): - (discriminator, callable, args, kw, includepath, info, order - ) = expand_action(*action) + _, callable, args, kw, _, info, _ = expand_action(*action) if callable is None: continue try: @@ -969,7 +964,10 @@ class ActionState(ActionStateBase): raise except: t, v, tb = sys.exc_info() - raise ConfigurationExecutionError(t, v, info), None, tb + try: + raise ConfigurationExecutionError(t, v, info), None, tb + finally: + del t, v, tb finally: if clear: del self.actions[:] @@ -1082,10 +1080,11 @@ def resolveConflicts(actions): return r -def expand_action(discriminator, callable=None, args=(), kw={}, +def expand_action(discriminator, callable=None, args=(), kw=None, includepath=(), info='', order=0): - return (discriminator, callable, args, kw, - includepath, info, order) + if kw is None: + kw = {} + return (discriminator, callable, args, kw, includepath, info, order) global_registries = WeakOrderedSet() diff --git a/pyramid/tests/test_config/test_init.py b/pyramid/tests/test_config/test_init.py index 0df96af40..9422f7dfe 100644 --- a/pyramid/tests/test_config/test_init.py +++ b/pyramid/tests/test_config/test_init.py @@ -243,23 +243,22 @@ class ConfiguratorTests(unittest.TestCase): newconfig = config.with_package(pyramid.tests.test_config) self.assertEqual(newconfig.package, pyramid.tests.test_config) - def test_with_package_context_is_not_None(self): - import pyramid.tests.test_config - config = self._makeOne() - config._ctx = DummyContext() - config._ctx.registry = None - config._ctx.autocommit = True - config._ctx.route_prefix = None - newconfig = config.with_package(pyramid.tests.test_config) - self.assertEqual(newconfig.package, pyramid.tests.test_config) - - def test_with_package_context_is_None(self): - import pyramid.tests.test_config + def test_with_package(self): + import pyramid.tests config = self._makeOne() - config._ctx = None - newconfig = config.with_package(pyramid.tests.test_config) - self.assertEqual(newconfig.package, pyramid.tests.test_config) - self.assertEqual(config._ctx.package, None) + config.basepath = 'basepath' + config.info = 'info' + config.includepath = ('spec',) + config.autocommit = True + config.route_prefix = 'prefix' + newconfig = config.with_package(pyramid.tests) + self.assertEqual(newconfig.package, pyramid.tests) + self.assertEqual(newconfig.registry, config.registry) + self.assertEqual(newconfig.autocommit, True) + self.assertEqual(newconfig.route_prefix, 'prefix') + self.assertEqual(newconfig.info, 'info') + self.assertEqual(newconfig.basepath, 'basepath') + self.assertEqual(newconfig.includepath, ('spec',)) def test_maybe_dotted_string_success(self): import pyramid.tests.test_config @@ -659,53 +658,38 @@ pyramid.tests.test_config.dummy_include2""", def test_include_with_dotted_name(self): from pyramid.tests import test_config config = self._makeOne() - context_before = config._make_context() - config._ctx = context_before config.include('pyramid.tests.test_config.dummy_include') - context_after = config._ctx - actions = context_after.actions + after = config.action_state + actions = after.actions self.assertEqual(len(actions), 1) self.assertEqual( - context_after.actions[0][:3], + after.actions[0][:3], ('discrim', None, test_config), ) - self.assertEqual(context_after.basepath, None) - self.assertEqual(context_after.includepath, ()) - self.assertTrue(context_after is context_before) def test_include_with_python_callable(self): from pyramid.tests import test_config config = self._makeOne() - context_before = config._make_context() - config._ctx = context_before config.include(dummy_include) - context_after = config._ctx - actions = context_after.actions + after = config.action_state + actions = after.actions self.assertEqual(len(actions), 1) self.assertEqual( actions[0][:3], ('discrim', None, test_config), ) - self.assertEqual(context_after.basepath, None) - self.assertEqual(context_after.includepath, ()) - self.assertTrue(context_after is context_before) def test_include_with_module_defaults_to_includeme(self): from pyramid.tests import test_config config = self._makeOne() - context_before = config._make_context() - config._ctx = context_before config.include('pyramid.tests.test_config') - context_after = config._ctx - actions = context_after.actions + after = config.action_state + actions = after.actions self.assertEqual(len(actions), 1) self.assertEqual( actions[0][:3], ('discrim', None, test_config), ) - self.assertEqual(context_after.basepath, None) - 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) @@ -721,9 +705,22 @@ pyramid.tests.test_config.dummy_include2""", def test_with_context(self): config = self._makeOne() - ctx = config._make_context() - newconfig = config.with_context(ctx) - self.assertEqual(newconfig._ctx, ctx) + context = DummyZCMLContext() + context.basepath = 'basepath' + context.includepath = ('spec',) + context.package = 'pyramid' + context.autocommit = True + context.registry = 'abc' + context.route_prefix = 'buz' + context.info = 'info' + newconfig = config.with_context(context) + self.assertEqual(newconfig.package_name, 'pyramid') + self.assertEqual(newconfig.autocommit, True) + self.assertEqual(newconfig.registry, 'abc') + self.assertEqual(newconfig.route_prefix, 'buz') + self.assertEqual(newconfig.basepath, 'basepath') + self.assertEqual(newconfig.includepath, ('spec',)) + self.assertEqual(newconfig.info, 'info') def test_action_branching_kw_is_None(self): config = self._makeOne(autocommit=True) @@ -733,29 +730,31 @@ pyramid.tests.test_config.dummy_include2""", config = self._makeOne(autocommit=True) self.assertEqual(config.action('discrim', kw={'a':1}), None) - def test_action_branching_nonautocommit_with_context_info(self): + def test_action_branching_nonautocommit_with_config_info(self): config = self._makeOne(autocommit=False) + config.info = 'abc' state = DummyActionState() state.autocommit = False - state.info = 'abc' - config._ctx = state + config.action_state = state config.action('discrim', kw={'a':1}) self.assertEqual( state.actions, - [(('discrim', None, (), {'a': 1}, 0), {'info': 'abc'})] + [(('discrim', None, (), {'a': 1}, 0), + {'info': 'abc', 'includepath':()})] ) - def test_action_branching_nonautocommit_without_context_info(self): + def test_action_branching_nonautocommit_without_config_info(self): config = self._makeOne(autocommit=False) + config.info = '' + config._ainfo = ['z'] state = DummyActionState() + config.action_state = state state.autocommit = False - state.info = '' - config._ctx = state - config._ainfo = ['z'] config.action('discrim', kw={'a':1}) self.assertEqual( state.actions, - [(('discrim', None, (), {'a': 1}, 0), {'info': 'z'})] + [(('discrim', None, (), {'a': 1}, 0), + {'info': 'z', 'includepath':()})] ) def test_scan_integration(self): @@ -1301,9 +1300,9 @@ class TestConfigurator_add_directive(unittest.TestCase): 'dummy_extend', 'pyramid.tests.test_config.dummy_extend') self.assert_(hasattr(config, 'dummy_extend')) config.dummy_extend('discrim') - context_after = config._ctx + after = config.action_state self.assertEqual( - context_after.actions[-1][:3], + after.actions[-1][:3], ('discrim', None, test_config), ) @@ -1314,9 +1313,9 @@ class TestConfigurator_add_directive(unittest.TestCase): 'dummy_extend', dummy_extend) self.assert_(hasattr(config, 'dummy_extend')) config.dummy_extend('discrim') - context_after = config._ctx + after = config.action_state self.assertEqual( - context_after.actions[-1][:3], + after.actions[-1][:3], ('discrim', None, test_config), ) @@ -1328,9 +1327,9 @@ class TestConfigurator_add_directive(unittest.TestCase): 'dummy_extend', dummy_extend2) self.assert_(hasattr(config, 'dummy_extend')) config.dummy_extend('discrim') - context_after = config._ctx + after = config.action_state self.assertEqual( - context_after.actions[-1][:3], + after.actions[-1][:3], ('discrim', None, config.registry), ) @@ -1343,18 +1342,15 @@ class TestConfigurator_add_directive(unittest.TestCase): self.assertRaises(ConfigurationConflictError, config.commit) def test_directive_persists_across_configurator_creations(self): - from pyramid.config import ActionStateWrapper config = self.config config.add_directive('dummy_extend', dummy_extend) - context = config._make_context(autocommit=False) - context = ActionStateWrapper(context) - config2 = config.with_context(context) + config2 = config.with_package('pyramid.tests') config2.dummy_extend('discrim') - context_after = config2._ctx - actions = context_after.actions + after = config2.action_state + actions = after.actions self.assertEqual(len(actions), 1) self.assertEqual( - context_after.actions[0][:3], + after.actions[0][:3], ('discrim', None, config2.package), ) @@ -1365,8 +1361,7 @@ class TestActionState(unittest.TestCase): def test_it(self): c = self._makeOne() - self.assertEqual(c.autocommit, False) - self.assertEqual(c.route_prefix, None) + self.assertEqual(c.actions, []) def test_action_simple(self): from pyramid.tests.test_config import dummyfactory as f @@ -1377,32 +1372,28 @@ class TestActionState(unittest.TestCase): c.action(None) self.assertEqual(c.actions, [(1, f, (1,), {'x': 1}), (None, None)]) - def test_action_with_includepath_and_info(self): + def test_action_with_includepath(self): c = self._makeOne() c.actions = [] - c.includepath = ('foo.zcml',) - c.info = '?' - c.action(None) - self.assertEqual(c.actions, - [(None, None, (), {}, ('foo.zcml',), '?')]) + c.action(None, includepath=('abc',)) + self.assertEqual(c.actions, [(None, None, (), {}, ('abc',))]) - def test_action_with_order(self): + def test_action_with_info(self): c = self._makeOne() - c.actions = [] - c.action(None, order=99999) - self.assertEqual(c.actions, [(None, None, (), {}, (), '', 99999)]) + c.action(None, info='abc') + self.assertEqual(c.actions, [(None, None, (), {}, (), 'abc')]) - def test_action_with_includepath_dynamic(self): + def test_action_with_includepath_and_info(self): c = self._makeOne() - c.actions = [] - c.action(None, includepath=('abc',)) - self.assertEqual(c.actions, [(None, None, (), {}, ('abc',))]) + c.action(None, includepath=('spec',), info='bleh') + self.assertEqual(c.actions, + [(None, None, (), {}, ('spec',), 'bleh')]) - def test_action_with_info_dynamic(self): + def test_action_with_order(self): c = self._makeOne() c.actions = [] - c.action(None, info='abc') - self.assertEqual(c.actions, [(None, None, (), {}, (), 'abc')]) + c.action(None, order=99999) + self.assertEqual(c.actions, [(None, None, (), {}, (), '', 99999)]) def test_processSpec(self): c = self._makeOne() @@ -1439,20 +1430,6 @@ class TestActionState(unittest.TestCase): self.assertRaises(ConfigurationExecutionError, c.execute_actions) self.assertEqual(output, [('f', (1,), {}), ('f', (2,), {})]) -class TestActionStateWrapper(unittest.TestCase): - def _makeOne(self, state): - from pyramid.config import ActionStateWrapper - return ActionStateWrapper(state) - - def test___getattr__(self): - state = DummyContext() - state.foo = 1 - state.bar = 2 - wrapper = self._makeOne(state) - self.assertEqual(wrapper.foo, 1) - wrapper.bar = 2 - self.assertEqual(state.bar, 2) - class Test_resolveConflicts(unittest.TestCase): def _callFUT(self, actions): from pyramid.config import resolveConflicts @@ -1583,3 +1560,13 @@ class DummyActionState(object): self.actions = [] def action(self, *arg, **kw): self.actions.append((arg, kw)) + +class DummyZCMLContext(object): + package = None + registry = None + autocommit = False + route_prefix = None + basepath = None + includepath = () + info = '' + diff --git a/pyramid/tests/test_config/test_routes.py b/pyramid/tests/test_config/test_routes.py index 6eea92a70..1646561cd 100644 --- a/pyramid/tests/test_config/test_routes.py +++ b/pyramid/tests/test_config/test_routes.py @@ -52,7 +52,7 @@ class RoutesConfiguratorMixinTests(unittest.TestCase): def test_add_route_discriminator(self): config = self._makeOne() config.add_route('name', 'path') - self.assertEqual(config._ctx.actions[-1][0], ('route', 'name')) + self.assertEqual(config.action_state.actions[-1][0], ('route', 'name')) def test_add_route_with_factory(self): config = self._makeOne(autocommit=True) |
