summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@plope.com>2012-08-02 00:37:32 -0400
committerChris McDonough <chrism@plope.com>2012-08-02 00:37:32 -0400
commit1bbe668972a6ac3b116f44e50825c66ae5813326 (patch)
tree147ed65503684a0ab1edb7a333f66755e52e439c
parentb4f193258837f94d6e4d069f37538dc6f55af709 (diff)
parent92b456610438bdd94b7906683f8b2049fe5765bd (diff)
downloadpyramid-1bbe668972a6ac3b116f44e50825c66ae5813326.tar.gz
pyramid-1bbe668972a6ac3b116f44e50825c66ae5813326.tar.bz2
pyramid-1bbe668972a6ac3b116f44e50825c66ae5813326.zip
Merge branch 'master' of github.com:Pylons/pyramid
-rw-r--r--CHANGES.txt4
-rw-r--r--pyramid/config/util.py7
-rw-r--r--pyramid/config/views.py12
-rw-r--r--pyramid/tests/test_config/test_views.py31
4 files changed, 47 insertions, 7 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index c6afaf0c7..ecb2bf659 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -54,3 +54,7 @@ Features
result for the view being called. The uri format using an asset spec is
package:path/to/template#defname.mako. The old way of returning a tuple
from the view is supported for backward compatibility, ('defname', {}).
+
+- When there is a predicate mismatch exception (seen when no view matches for
+ a given request due to predicates not working), the exception now contains
+ a textual description of the predicate which didn't match.
diff --git a/pyramid/config/util.py b/pyramid/config/util.py
index b8d0f2319..4e4c93be3 100644
--- a/pyramid/config/util.py
+++ b/pyramid/config/util.py
@@ -113,6 +113,12 @@ def make_predicates(xhr=None, request_method=None, path_info=None,
# any predicates get an order of MAX_ORDER, meaning that they will
# be tried very last.
+ # NB: each predicate callable constructed by this function (or examined
+ # by this function, in the case of custom predicates) must leave this
+ # function with a ``__text__`` attribute. The subsystem which reports
+ # errors when no predicates match depends upon the existence of this
+ # attribute on each predicate callable.
+
predicates = []
weights = []
h = md5()
@@ -273,6 +279,7 @@ def make_predicates(xhr=None, request_method=None, path_info=None,
tvalue = tgenerate(m) # tvalue will be urlquoted string
m['traverse'] = traversal_path(tvalue) # will be seq of unicode
return True
+ traverse_predicate.__text__ = 'traverse matchdict pseudo-predicate'
# This isn't actually a predicate, it's just a infodict
# modifier that injects ``traverse`` into the matchdict. As a
# result, the ``traverse_predicate`` function above always
diff --git a/pyramid/config/views.py b/pyramid/config/views.py
index 9e9b5321b..4354b4691 100644
--- a/pyramid/config/views.py
+++ b/pyramid/config/views.py
@@ -276,11 +276,13 @@ class ViewDeriver(object):
if not predicates:
return view
def predicate_wrapper(context, request):
- if all((predicate(context, request) for predicate in predicates)):
- return view(context, request)
- view_name = getattr(view, '__name__', view)
- raise PredicateMismatch(
- 'predicate mismatch for view %s' % view_name)
+ for predicate in predicates:
+ if not predicate(context, request):
+ view_name = getattr(view, '__name__', view)
+ raise PredicateMismatch(
+ 'predicate mismatch for view %s (%s)' % (
+ view_name, predicate.__text__))
+ return view(context, request)
def checker(context, request):
return all((predicate(context, request) for predicate in
predicates))
diff --git a/pyramid/tests/test_config/test_views.py b/pyramid/tests/test_config/test_views.py
index 9b46f83c9..ebf1dfb39 100644
--- a/pyramid/tests/test_config/test_views.py
+++ b/pyramid/tests/test_config/test_views.py
@@ -2905,6 +2905,7 @@ class TestViewDeriver(unittest.TestCase):
view = lambda *arg: response
def predicate1(context, request):
return False
+ predicate1.__text__ = 'text'
deriver = self._makeOne(predicates=[predicate1])
result = deriver(view)
request = self._makeRequest()
@@ -2912,7 +2913,8 @@ class TestViewDeriver(unittest.TestCase):
try:
result(None, None)
except PredicateMismatch as e:
- self.assertEqual(e.detail, 'predicate mismatch for view <lambda>')
+ self.assertEqual(e.detail,
+ 'predicate mismatch for view <lambda> (text)')
else: # pragma: no cover
raise AssertionError
@@ -2921,6 +2923,7 @@ class TestViewDeriver(unittest.TestCase):
def myview(request): pass
def predicate1(context, request):
return False
+ predicate1.__text__ = 'text'
deriver = self._makeOne(predicates=[predicate1])
result = deriver(myview)
request = self._makeRequest()
@@ -2928,7 +2931,29 @@ class TestViewDeriver(unittest.TestCase):
try:
result(None, None)
except PredicateMismatch as e:
- self.assertEqual(e.detail, 'predicate mismatch for view myview')
+ self.assertEqual(e.detail,
+ 'predicate mismatch for view myview (text)')
+ else: # pragma: no cover
+ raise AssertionError
+
+ def test_predicate_mismatch_exception_has_text_in_detail(self):
+ from pyramid.exceptions import PredicateMismatch
+ def myview(request): pass
+ def predicate1(context, request):
+ return True
+ predicate1.__text__ = 'pred1'
+ def predicate2(context, request):
+ return False
+ predicate2.__text__ = 'pred2'
+ deriver = self._makeOne(predicates=[predicate1, predicate2])
+ result = deriver(myview)
+ request = self._makeRequest()
+ request.method = 'POST'
+ try:
+ result(None, None)
+ except PredicateMismatch as e:
+ self.assertEqual(e.detail,
+ 'predicate mismatch for view myview (pred2)')
else: # pragma: no cover
raise AssertionError
@@ -2974,9 +2999,11 @@ class TestViewDeriver(unittest.TestCase):
def predicate1(context, request):
predicates.append(True)
return True
+ predicate1.__text__ = 'text'
def predicate2(context, request):
predicates.append(True)
return False
+ predicate2.__text__ = 'text'
deriver = self._makeOne(predicates=[predicate1, predicate2])
result = deriver(view)
request = self._makeRequest()