summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Merickel <michael@merickel.org>2011-08-12 02:32:36 -0500
committerMichael Merickel <michael@merickel.org>2011-08-12 02:32:36 -0500
commitc45737397842359010b3d517a1d5f9f34c6d1e53 (patch)
treeeb2f6d1c81eb97dd55e46b9f1f8ea15147910ab3
parent292656e9a07eadb7ee12f5830c75304d8cb13660 (diff)
downloadpyramid-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.py3
-rw-r--r--pyramid/tests/test_tweens.py94
-rw-r--r--pyramid/tweens.py43
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 = []