Chris McDonough
2011-08-23 f1db0884ec6d4e55d5136cb67c9581907280f9c9
merge master to branch
5 files modified
109 ■■■■■ changed files
CHANGES.txt 5 ●●●●● patch | view | raw | blame | history
docs/whatsnew-1.2.rst 5 ●●●●● patch | view | raw | blame | history
pyramid/config/util.py 19 ●●●● patch | view | raw | blame | history
pyramid/config/views.py 25 ●●●● patch | view | raw | blame | history
pyramid/tests/test_config/test_util.py 55 ●●●●● patch | view | raw | blame | history
CHANGES.txt
@@ -98,6 +98,11 @@
  output produced can be useful when trying to diagnose
  authentication-related problems.
- New view predicate: ``match_param``.  Example: a view added via
  ``config.add_view(aview, match_param='action=edit')`` will be called only
  when the ``request.matchdict`` has a value inside it named ``action`` with
  a value of ``edit``.
Internal
--------
docs/whatsnew-1.2.rst
@@ -144,6 +144,11 @@
  any of these policies.  The output produced can be useful when trying to
  diagnose authentication-related problems.
- New view predicate: ``match_param``.  Example: a view added via
  ``config.add_view(aview, match_param='action=edit')`` will be called only
  when the ``request.matchdict`` has a value inside it named ``action`` with
  a value of ``edit``.
Deprecations
------------
pyramid/config/util.py
@@ -35,8 +35,8 @@
    return wrapper
def make_predicates(xhr=None, request_method=None, path_info=None,
                    request_param=None, header=None, accept=None,
                    containment=None, request_type=None,
                    request_param=None, match_param=None, header=None,
                    accept=None, containment=None, request_type=None,
                    traverse=None, custom=()):
    # PREDICATES
@@ -184,6 +184,21 @@
        predicates.append(request_type_predicate)
        h.update('request_type:%r' % hash(request_type))
    if match_param is not None:
        if isinstance(match_param, basestring):
            match_param, match_param_val = match_param.split('=', 1)
            match_param = {match_param: match_param_val}
        text = "match_param %s" % match_param
        def match_param_predicate(context, request):
            for k, v in match_param.iteritems():
                if request.matchdict.get(k) != v:
                    return False
            return True
        match_param_predicate.__text__ = text
        weights.append(1 << 9)
        predicates.append(match_param_predicate)
        h.update('match_param:%r' % match_param)
    if traverse is not None:
        # ``traverse`` can only be used as a *route* "predicate"; it
        # adds 'traverse' to the matchdict if it's specified in the
pyramid/config/views.py
@@ -533,7 +533,8 @@
                 request_param=None, containment=None, attr=None,
                 renderer=None, wrapper=None, xhr=False, accept=None,
                 header=None, path_info=None, custom_predicates=(),
                 context=None, decorator=None, mapper=None, http_cache=None):
                 context=None, decorator=None, mapper=None, http_cache=None,
                 match_param=None):
        """ Add a :term:`view configuration` to the current
        configuration state.  Arguments to ``add_view`` are broken
        down below into *predicate* arguments and *non-predicate*
@@ -777,6 +778,23 @@
          the value must match the right hand side of the expression
          (``123``) for the view to "match" the current request.
        match_param
          .. note:: This feature is new as of :app:`Pyramid` 1.2.
          This param may be either a single string of the format "key=value"
          or a dict of key/value pairs.
          A view declaration with this argument ensures that the view will
          only be called when the :term:`request` has key/value pairs in
          the ``matchdict`` that equal those supplied in the predicate.
          e.g. ``match_param="action=edit" would require the ``action``
          parameter in the ``matchdict`` match the right hande side of the
          expression (``edit``) for the view to "match" the current request.
          If the ``match_param`` is a dict, every key/value pair must match
          for the predicate to pass.
        containment
          This value should be a Python class or :term:`interface` (or a
@@ -834,7 +852,6 @@
          variable.  If the regex matches, this predicate will be
          ``True``.
        custom_predicates
          This value should be a sequence of references to custom
@@ -874,7 +891,7 @@
            request_method=request_method, path_info=path_info,
            request_param=request_param, header=header, accept=accept,
            containment=containment, request_type=request_type,
            custom=custom_predicates)
            match_param=match_param, custom=custom_predicates)
        if context is None:
            context = for_
@@ -1030,7 +1047,7 @@
        discriminator = [
            'view', context, name, request_type, IView, containment,
            request_param, request_method, route_name, attr,
            request_param, request_method, match_param, route_name, attr,
            xhr, accept, header, path_info]
        discriminator.extend(sorted(custom_predicates))
        discriminator = tuple(discriminator)
pyramid/tests/test_config/test_util.py
@@ -16,6 +16,7 @@
            request_method='request_method',
            path_info='path_info',
            request_param='param',
            match_param='foo=bar',
            header='header',
            accept='accept',
            containment='containment',
@@ -27,6 +28,7 @@
            request_method='request_method',
            path_info='path_info',
            request_param='param',
            match_param='foo=bar',
            header='header',
            accept='accept',
            containment='containment',
@@ -38,6 +40,7 @@
            request_method='request_method',
            path_info='path_info',
            request_param='param',
            match_param='foo=bar',
            header='header',
            accept='accept',
            containment='containment',
@@ -48,6 +51,7 @@
            request_method='request_method',
            path_info='path_info',
            request_param='param',
            match_param='foo=bar',
            header='header',
            accept='accept',
            containment='containment',
@@ -57,6 +61,7 @@
            request_method='request_method',
            path_info='path_info',
            request_param='param',
            match_param='foo=bar',
            header='header',
            accept='accept',
            )
@@ -65,6 +70,7 @@
            request_method='request_method',
            path_info='path_info',
            request_param='param',
            match_param='foo=bar',
            header='header',
            )
        order7, _, _ = self._callFUT(
@@ -72,20 +78,27 @@
            request_method='request_method',
            path_info='path_info',
            request_param='param',
            match_param='foo=bar',
            )
        order8, _, _ = self._callFUT(
            xhr='xhr',
            request_method='request_method',
            path_info='path_info',
            request_param='param',
            )
        order9, _, _ = self._callFUT(
            xhr='xhr',
            request_method='request_method',
            path_info='path_info',
            )
        order10, _, _ = self._callFUT(
            xhr='xhr',
            request_method='request_method',
            )
        order11, _, _ = self._callFUT(
            xhr='xhr',
            )
        order12, _, _ = self._callFUT(
            )
        self.assertEqual(order1, order2)
        self.assertTrue(order3 > order2)
@@ -97,6 +110,7 @@
        self.assertTrue(order9 > order8)
        self.assertTrue(order10 > order9)
        self.assertTrue(order11 > order10)
        self.assertTrue(order12 > order10)
    def test_ordering_importance_of_predicates(self):
        order1, _, _ = self._callFUT(
@@ -124,6 +138,9 @@
            request_type='request_type',
            )
        order9, _, _ = self._callFUT(
            match_param='foo=bar',
            )
        order10, _, _ = self._callFUT(
            custom=(DummyCustomPredicate(),),
            )
        self.assertTrue(order1 > order2)
@@ -134,6 +151,7 @@
        self.assertTrue(order6 > order7)
        self.assertTrue(order7 > order8)
        self.assertTrue(order8 > order9)
        self.assertTrue(order9 > order10)
    def test_ordering_importance_and_number(self):
        order1, _, _ = self._callFUT(
@@ -221,7 +239,8 @@
            request_type='request_type',
            custom=(DummyCustomPredicate(),
                    DummyCustomPredicate.classmethod_predicate,
                    DummyCustomPredicate.classmethod_predicate_no_text))
                    DummyCustomPredicate.classmethod_predicate_no_text),
            match_param='foo=bar')
        self.assertEqual(predicates[0].__text__, 'xhr = True')
        self.assertEqual(predicates[1].__text__,
                         'request method = request_method')
@@ -231,9 +250,34 @@
        self.assertEqual(predicates[5].__text__, 'accept = accept')
        self.assertEqual(predicates[6].__text__, 'containment = containment')
        self.assertEqual(predicates[7].__text__, 'request_type = request_type')
        self.assertEqual(predicates[8].__text__, 'custom predicate')
        self.assertEqual(predicates[9].__text__, 'classmethod predicate')
        self.assertEqual(predicates[10].__text__, '<unknown custom predicate>')
        self.assertEqual(predicates[8].__text__, "match_param {'foo': 'bar'}")
        self.assertEqual(predicates[9].__text__, 'custom predicate')
        self.assertEqual(predicates[10].__text__, 'classmethod predicate')
        self.assertEqual(predicates[11].__text__, '<unknown custom predicate>')
    def test_match_param_from_string(self):
        _, predicates, _ = self._callFUT(match_param='foo=bar')
        request = DummyRequest()
        request.matchdict = {'foo':'bar', 'baz':'bum'}
        self.assertTrue(predicates[0](Dummy(), request))
    def test_match_param_from_string_fails(self):
        _, predicates, _ = self._callFUT(match_param='foo=bar')
        request = DummyRequest()
        request.matchdict = {'foo':'bum', 'baz':'bum'}
        self.assertFalse(predicates[0](Dummy(), request))
    def test_match_param_from_dict(self):
        _, predicates, _ = self._callFUT(match_param={'foo':'bar','baz':'bum'})
        request = DummyRequest()
        request.matchdict = {'foo':'bar', 'baz':'bum'}
        self.assertTrue(predicates[0](Dummy(), request))
    def test_match_param_from_dict_fails(self):
        _, predicates, _ = self._callFUT(match_param={'foo':'bar','baz':'bum'})
        request = DummyRequest()
        request.matchdict = {'foo':'bar', 'baz':'foo'}
        self.assertFalse(predicates[0](Dummy(), request))
class DummyCustomPredicate(object):
    def __init__(self):
@@ -246,6 +290,9 @@
    @classmethod
    def classmethod_predicate_no_text(*args): pass # pragma: no cover
class Dummy:
    pass
class DummyRequest:
    subpath = ()
    matchdict = None