diff options
| author | Michael Merickel <michael@merickel.org> | 2011-08-12 02:32:36 -0500 |
|---|---|---|
| committer | Michael Merickel <michael@merickel.org> | 2011-08-12 02:32:36 -0500 |
| commit | c45737397842359010b3d517a1d5f9f34c6d1e53 (patch) | |
| tree | eb2f6d1c81eb97dd55e46b9f1f8ea15147910ab3 | |
| parent | 292656e9a07eadb7ee12f5830c75304d8cb13660 (diff) | |
| download | pyramid-c45737397842359010b3d517a1d5f9f34c6d1e53.tar.gz pyramid-c45737397842359010b3d517a1d5f9f34c6d1e53.tar.bz2 pyramid-c45737397842359010b3d517a1d5f9f34c6d1e53.zip | |
Added support for specifying tuples in over/under.
This change means that errors are now raised if no tween is found from
either an over or an under specification.
| -rw-r--r-- | pyramid/config.py | 3 | ||||
| -rw-r--r-- | pyramid/tests/test_tweens.py | 94 | ||||
| -rw-r--r-- | pyramid/tweens.py | 43 |
3 files changed, 107 insertions, 33 deletions
diff --git a/pyramid/config.py b/pyramid/config.py index a6d1a6fc5..d6e9fd11c 100644 --- a/pyramid/config.py +++ b/pyramid/config.py @@ -995,6 +995,9 @@ class Configurator(object): - One of the constants :attr:`pyramid.tweens.MAIN`, :attr:`pyramid.tweens.INGRESS`, or :attr:`pyramid.tweens.EXCVIEW`. + + - A tuple of any combination of the above. This allows the user + to specify fallbacks if the desired tween is not included. ``under`` means 'closer to the main Pyramid application than', ``over`` means 'closer to the request ingress than'. diff --git a/pyramid/tests/test_tweens.py b/pyramid/tests/test_tweens.py index a16fdad57..67cfee8a9 100644 --- a/pyramid/tests/test_tweens.py +++ b/pyramid/tests/test_tweens.py @@ -2,7 +2,7 @@ import unittest class TestTweens(unittest.TestCase): def _makeOne(self): - from pyramid.config import Tweens + from pyramid.tweens import Tweens return Tweens() def test_add_explicit(self): @@ -83,6 +83,7 @@ class TestTweens(unittest.TestCase): self.assertEqual(tweens(None, None), '123') def test___call___implicit(self): + from pyramid.tweens import INGRESS tweens = self._makeOne() def factory1(handler, registry): return handler @@ -91,10 +92,13 @@ class TestTweens(unittest.TestCase): tweens.names = ['name', 'name2'] tweens.alias_to_name = {'name':'name', 'name2':'name2'} tweens.name_to_alias = {'name':'name', 'name2':'name2'} + tweens.req_under = set(['name', 'name2']) + tweens.order = [(INGRESS, 'name'), (INGRESS, 'name2')] tweens.factories = {'name':factory1, 'name2':factory2} self.assertEqual(tweens(None, None), '123') def test___call___implicit_with_aliasnames_different_than_names(self): + from pyramid.tweens import INGRESS tweens = self._makeOne() def factory1(handler, registry): return handler @@ -103,6 +107,8 @@ class TestTweens(unittest.TestCase): tweens.names = ['name', 'name2'] tweens.alias_to_name = {'foo1':'name', 'foo2':'name2'} tweens.name_to_alias = {'name':'foo1', 'name2':'foo2'} + tweens.req_under = set(['foo1', 'foo2']) + tweens.order = [(INGRESS, 'name'), (INGRESS, 'name2')] tweens.factories = {'name':factory1, 'name2':factory2} self.assertEqual(tweens(None, None), '123') @@ -227,13 +233,44 @@ class TestTweens(unittest.TestCase): ('txnmgr', 'txnmgr_factory'), ]) - def test_implicit_ordering_missing_partial(self): + def test_implicit_ordering_missing_over_partial(self): + from pyramid.exceptions import ConfigurationError + tweens = self._makeOne() + add = tweens.add_implicit + add('dbt', 'dbt_factory') + add('auth', 'auth_factory', under='browserid') + add('retry', 'retry_factory', over='txnmgr', under='exceptionview') + add('browserid', 'browserid_factory') + self.assertRaises(ConfigurationError, tweens.implicit) + + def test_implicit_ordering_missing_under_partial(self): + from pyramid.exceptions import ConfigurationError + tweens = self._makeOne() + add = tweens.add_implicit + add('dbt', 'dbt_factory') + add('auth', 'auth_factory', under='txnmgr') + add('retry', 'retry_factory', over='dbt', under='exceptionview') + add('browserid', 'browserid_factory') + self.assertRaises(ConfigurationError, tweens.implicit) + + def test_implicit_ordering_missing_over_and_under_partials(self): + from pyramid.exceptions import ConfigurationError + tweens = self._makeOne() + add = tweens.add_implicit + add('dbt', 'dbt_factory') + add('auth', 'auth_factory', under='browserid') + add('retry', 'retry_factory', over='foo', under='txnmgr') + add('browserid', 'browserid_factory') + self.assertRaises(ConfigurationError, tweens.implicit) + + def test_implicit_ordering_missing_over_partial_with_fallback(self): from pyramid.tweens import MAIN tweens = self._makeOne() add = tweens.add_implicit add('exceptionview', 'excview_factory', over=MAIN) add('auth', 'auth_factory', under='browserid') - add('retry', 'retry_factory', over='txnmgr', under='exceptionview') + add('retry', 'retry_factory', over=('txnmgr',MAIN), + under='exceptionview') add('browserid', 'browserid_factory') add('dbt', 'dbt_factory') self.assertEqual(tweens.implicit(), @@ -245,27 +282,30 @@ class TestTweens(unittest.TestCase): ('retry', 'retry_factory'), ]) - def test_implicit_ordering_missing_partial2(self): + def test_implicit_ordering_missing_under_partial_with_fallback(self): + from pyramid.tweens import MAIN tweens = self._makeOne() add = tweens.add_implicit - add('dbt', 'dbt_factory') - add('auth', 'auth_factory', under='browserid') - add('retry', 'retry_factory', over='txnmgr', under='exceptionview') + add('exceptionview', 'excview_factory', over=MAIN) + add('auth', 'auth_factory', under=('txnmgr','browserid')) + add('retry', 'retry_factory', under='exceptionview') add('browserid', 'browserid_factory') + add('dbt', 'dbt_factory') self.assertEqual(tweens.implicit(), [ - ('retry', 'retry_factory'), + ('dbt', 'dbt_factory'), ('browserid', 'browserid_factory'), ('auth', 'auth_factory'), - ('dbt', 'dbt_factory'), + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), ]) - def test_implicit_ordering_missing_partial3(self): + def test_implicit_ordering_missing_partial_with_aliases(self): from pyramid.tweens import MAIN tweens = self._makeOne() add = tweens.add_implicit - add('exceptionview', 'excview_factory', over=MAIN) - add('retry', 'retry_factory', over='txnmgr', under='exceptionview') + add('exceptionview', 'excview_factory', alias='e', over=MAIN) + add('retry', 'retry_factory', over=('txnmgr',MAIN), under='e') add('browserid', 'browserid_factory') self.assertEqual(tweens.implicit(), [ @@ -274,13 +314,27 @@ class TestTweens(unittest.TestCase): ('retry', 'retry_factory'), ]) - def test_implicit_ordering_missing_partial_with_aliases(self): + def test_implicit_ordering_with_partial_fallbacks(self): + from pyramid.tweens import MAIN + tweens = self._makeOne() + add = tweens.add_implicit + add('exceptionview', 'excview_factory', alias='e', over=('b', MAIN)) + add('retry', 'retry_factory', under='e') + add('browserid', 'browserid_factory', over=('txnmgr', 'e')) + self.assertEqual(tweens.implicit(), + [ + ('browserid', 'browserid_factory'), + ('exceptionview', 'excview_factory'), + ('retry', 'retry_factory'), + ]) + + def test_implicit_ordering_with_multiple_matching_fallbacks(self): from pyramid.tweens import MAIN tweens = self._makeOne() add = tweens.add_implicit add('exceptionview', 'excview_factory', alias='e', over=MAIN) - add('retry', 'retry_factory', over='txnmgr', under='e') - add('browserid', 'browserid_factory') + add('retry', 'retry_factory', under='e') + add('browserid', 'browserid_factory', over=('retry', 'e')) self.assertEqual(tweens.implicit(), [ ('browserid', 'browserid_factory'), @@ -288,6 +342,16 @@ class TestTweens(unittest.TestCase): ('retry', 'retry_factory'), ]) + def test_implicit_ordering_with_missing_fallbacks(self): + from pyramid.exceptions import ConfigurationError + from pyramid.tweens import MAIN + tweens = self._makeOne() + add = tweens.add_implicit + add('exceptionview', 'excview_factory', alias='e', over=MAIN) + add('retry', 'retry_factory', under='e') + add('browserid', 'browserid_factory', over=('txnmgr', 'auth')) + self.assertRaises(ConfigurationError, tweens.implicit) + def test_implicit_ordering_conflict_direct(self): from pyramid.tweens import CyclicDependencyError tweens = self._makeOne() diff --git a/pyramid/tweens.py b/pyramid/tweens.py index 339b06275..73b96d375 100644 --- a/pyramid/tweens.py +++ b/pyramid/tweens.py @@ -65,6 +65,8 @@ class Tweens(object): def __init__(self): self.explicit = [] self.names = [] + self.req_over = set() + self.req_under = set() self.factories = {} self.order = [] self.alias_to_name = {INGRESS:INGRESS, MAIN:MAIN} @@ -83,15 +85,20 @@ class Tweens(object): if under is None and over is None: under = INGRESS if under is not None: - self.order.append((under, alias)) + if not hasattr(under, '__iter__'): + under = (under,) + self.order += [(u, alias) for u in under] + self.req_under.add(alias) if over is not None: - self.order.append((alias, over)) + if not hasattr(over, '__iter__'): + over = (over,) + self.order += [(alias, o) for o in over] + self.req_over.add(alias) def implicit(self): order = [(INGRESS, MAIN)] roots = [] graph = {} - has_order = {} aliases = [INGRESS, MAIN] for name in self.names: @@ -114,26 +121,26 @@ class Tweens(object): if tonode in roots: roots.remove(tonode) - # remove ordering information that mentions unknown names/aliases - for pos, (first, second) in enumerate(order): - has_first = first in aliases - has_second = second in aliases - if (not has_first) or (not has_second): - order[pos] = None, None - else: - has_order[first] = has_order[second] = True - for alias in aliases: - # any alias that doesn't have an ordering after we detect all - # nodes with orders should get an ordering relative to INGRESS, - # as if it were added with no under or over in add_implicit - if (not alias in has_order) and (alias not in (INGRESS, MAIN)): - order.append((INGRESS, alias)) add_node(alias) + has_over, has_under = set(), set() for a, b in order: - if a is not None and b is not None: # deal with removed orders + if a in aliases and b in aliases: # deal with missing dependencies add_arc(a, b) + has_over.add(a) + has_under.add(b) + + if not self.req_over.issubset(has_over): + raise ConfigurationError( + 'Detected tweens with no satisfied over dependencies: %s' + % (', '.join(sorted(self.req_over - has_over))) + ) + if not self.req_under.issubset(has_under): + raise ConfigurationError( + 'Detected tweens with no satisfied under dependencies: %s' + % (', '.join(sorted(self.req_under - has_under))) + ) sorted_aliases = [] |
