From 44bc118a61e2e9d93a65b8edd5be9118fb478741 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 30 Jun 2010 02:47:16 +0000 Subject: - In earlier versions, a custom route predicate associated with a url dispatch route (each of the predicate functions fed to the ``custom_predicates`` argument of ``repoze.bfg.configuration.Configurator.add_route``) has always required a 2-positional argument signature, e.g. ``(context, request)``. Before this release, the ``context`` argument was always ``None``. As of this release, the first argument passed to a predicate is now a dictionary conventionally named ``info`` consisting of ``match``, ``route``, and ``mapper``. ``match`` is a dictionary: it represents the arguments matched in the URL by the route. ``route`` is an object representing the route that matched. ``mapper`` is the url dispatch route mapper object. This is useful when predicates need access to the route match. For example:: def any_of(segment_name, *args): def predicate(info, request): if info['match'][segment_name] in args: return True num_one_two_or_three = any_of('num, 'one', 'two', 'three') add_route('/:num', custom_predicates=(num_one_two_or_three,)) --- CHANGES.txt | 27 +++++++++++++++++++++++++++ repoze/bfg/tests/test_urldispatch.py | 10 ++++++++++ repoze/bfg/urldispatch.py | 5 +++-- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index 65690e73e..8eb1b57c7 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -8,6 +8,33 @@ Features ``repoze.bfg.paster.BFGShellCommand`` hookable in cases where endware may interfere with the default versions. +- In earlier versions, a custom route predicate associated with a url + dispatch route (each of the predicate functions fed to the + ``custom_predicates`` argument of + ``repoze.bfg.configuration.Configurator.add_route``) has always + required a 2-positional argument signature, e.g. ``(context, + request)``. Before this release, the ``context`` argument was + always ``None``. + + As of this release, the first argument passed to a predicate is now + a dictionary conventionally named ``info`` consisting of ``match``, + ``route``, and ``mapper``. ``match`` is a dictionary: it represents + the arguments matched in the URL by the route. ``route`` is an + object representing the route that matched. ``mapper`` is the url + dispatch route mapper object. + + This is useful when predicates need access to the route match. For + example:: + + def any_of(segment_name, *args): + def predicate(info, request): + if info['match'][segment_name] in args: + return True + + num_one_two_or_three = any_of('num, 'one', 'two', 'three') + + add_route('/:num', custom_predicates=(num_one_two_or_three,)) + Documentation ------------- diff --git a/repoze/bfg/tests/test_urldispatch.py b/repoze/bfg/tests/test_urldispatch.py index c1fa66aa7..69bd3d971 100644 --- a/repoze/bfg/tests/test_urldispatch.py +++ b/repoze/bfg/tests/test_urldispatch.py @@ -108,6 +108,16 @@ class RoutesMapperTests(unittest.TestCase): self.assertEqual(result['match']['action'], 'action1') self.assertEqual(result['match']['article'], 'article1') + def test_custom_predicate_gets_info(self): + mapper = self._makeOne() + def pred(info, request): + self.assertEqual(info['match'], {'action':u'action1'}) + self.assertEqual(info['route'], mapper.routes['foo']) + return True + mapper.connect('archives/:action/article1', 'foo', predicates=[pred]) + request = self._getRequest(PATH_INFO='/archives/action1/article1') + mapper(request) + def test_cc_bug(self): # "unordered" as reported in IRC by author of # http://labs.creativecommons.org/2010/01/13/cc-engine-and-web-non-frameworks/ diff --git a/repoze/bfg/urldispatch.py b/repoze/bfg/urldispatch.py index becde3ea2..458f1a7a5 100644 --- a/repoze/bfg/urldispatch.py +++ b/repoze/bfg/urldispatch.py @@ -51,9 +51,10 @@ class RoutesMapper(object): match = route.match(path) if match is not None: preds = route.predicates - if preds and not all((p(None, request) for p in preds)): + info = {'route':route, 'match':match} + if preds and not all((p(info, request) for p in preds)): continue - return {'route':route, 'match':match} + return info return {'route':None, 'match':None} -- cgit v1.2.3