Skip to content

Commit

Permalink
Merge branch 'master' of github.com:Pylons/pyramid
Browse files Browse the repository at this point in the history
  • Loading branch information
mcdonc committed Aug 2, 2012
2 parents b4f1932 + 92b4566 commit 1bbe668
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 7 deletions.
4 changes: 4 additions & 0 deletions CHANGES.txt
Expand Up @@ -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.
7 changes: 7 additions & 0 deletions pyramid/config/util.py
Expand Up @@ -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()
Expand Down Expand Up @@ -273,6 +279,7 @@ def traverse_predicate(context, request):
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
Expand Down
12 changes: 7 additions & 5 deletions pyramid/config/views.py
Expand Up @@ -276,11 +276,13 @@ def predicated_view(self, view):
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))
Expand Down
31 changes: 29 additions & 2 deletions pyramid/tests/test_config/test_views.py
Expand Up @@ -2905,14 +2905,16 @@ def test_predicate_mismatch_view_has_no_name(self):
view = lambda *arg: response
def predicate1(context, request):
return False
predicate1.__text__ = 'text'
deriver = self._makeOne(predicates=[predicate1])
result = deriver(view)
request = self._makeRequest()
request.method = 'POST'
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

Expand All @@ -2921,14 +2923,37 @@ def test_predicate_mismatch_view_has_name(self):
def myview(request): pass
def predicate1(context, request):
return False
predicate1.__text__ = 'text'
deriver = self._makeOne(predicates=[predicate1])
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')
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

Expand Down Expand Up @@ -2974,9 +2999,11 @@ def test_with_predicates_notall(self):
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()
Expand Down

0 comments on commit 1bbe668

Please sign in to comment.