Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Support multiple request_param args. #492

Closed
wants to merge 5 commits into from

3 participants

@rpatterson

Fixes #465, I think. :-)

I think I've got this done right, but, again, it's very naive since I don't know what any of this is for. Can someone review this pull request and educate me if I'm missing something. Then I'll add commits to address.

One of the things that may need some discussion is the difference between how the predicate __text__ was generated for request_param and match_param before my changes. match_param only had coverage for foo=bar style params, not for foo params without values and does not have coverage for multiple params. request_param had coverage for both with and without values but, obviously, had no coverage for multiple params.

match_param would format a single foo=bar param as ['foo=bar'] in __text__ while request_param would use foo = bar for a param with a value and foo for a param without a value. My fork currently supports the foo style for both match_param and request_param when there is only one param without a value. Since there was no coverage on the previous request_param foo = bar behavior for params with values but there was coverage for the match_param ['foo=bar'] behavior, I left the match_param ['foo=bar'] style for request_param as well. I've added coverage for this behavior as well. I've also added coverage for multiple params in the __text__.

Will someone review this discussion and my commits and help me understand if I'm misunderstanding things.

@mcdonc
Owner

I'm going to review/merge this after we release 1.3 final as it's a new feature.

@mmerickel
Owner

this is going to need some massaging now that @mcdonc rewrote the predicate machinery

@mcdonc
Owner

Superseded by pull #705

@mcdonc mcdonc closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
65 pyramid/config/util.py
@@ -152,22 +152,8 @@ def path_info_predicate(context, request):
h.update(bytes_('path_info:%r' % path_info))
if request_param is not None:
- request_param_val = None
- if '=' in request_param:
- request_param, request_param_val = request_param.split('=', 1)
- if request_param_val is None:
- text = "request_param %s" % request_param
- else:
- text = "request_param %s = %s" % (request_param, request_param_val)
- def request_param_predicate(context, request):
- if request_param_val is None:
- return request_param in request.params
- return request.params.get(request_param) == request_param_val
- request_param_predicate.__text__ = text
- weights.append(1 << 4)
- predicates.append(request_param_predicate)
- h.update(
- bytes_('request_param:%r=%r' % (request_param, request_param_val)))
+ make_param_predicates("request", request_param, 'params',
+ weights, 4, predicates, h)
if header is not None:
header_name = header
@@ -221,21 +207,8 @@ def request_type_predicate(context, request):
h.update(bytes_('request_type:%r' % hash(request_type)))
if match_param is not None:
- if not is_nonstr_iter(match_param):
- match_param = (match_param,)
- match_param = sorted(match_param)
- text = "match_param %s" % repr(match_param)
- reqs = [p.split('=', 1) for p in match_param]
- def match_param_predicate(context, request):
- for k, v in reqs:
- if request.matchdict.get(k) != v:
- return False
- return True
- match_param_predicate.__text__ = text
- weights.append(1 << 9)
- predicates.append(match_param_predicate)
- for p in match_param:
- h.update(bytes_('match_param:%r' % p))
+ make_param_predicates("match", match_param, 'matchdict',
+ weights, 9, predicates, h)
if custom:
for num, predicate in enumerate(custom):
@@ -287,6 +260,36 @@ def traverse_predicate(context, request):
phash = h.hexdigest()
return order, predicates, phash
+
+def make_param_predicates(param_type, param, params_attr,
+ weights, weight, predicates, hash):
+ if not is_nonstr_iter(param):
+ param = (param,)
+ param = sorted(param)
+ text = "%s_param %r" % (param_type, param)
+ reqs = []
+ for p in param:
+ pair = p.split('=', 1)
+ if len(pair) == 1:
+ pair = pair+[None]
+ reqs.append(pair)
+ if len(reqs) == 1 and reqs[0][1] is None:
+ text = "%s_param %s" % (param_type, param[0])
+ def param_predicate(context, request):
+ params = getattr(request, params_attr)
+ for k, v in reqs:
+ if v is None:
+ return k in params
+ if params.get(k) != v:
+ return False
+ return True
+ param_predicate.__text__ = text
+ weights.append(1 << weight)
+ predicates.append(param_predicate)
+ for p in param:
+ hash.update(bytes_('%s_param:%r' % (param_type, p)))
+
+
def as_sorted_tuple(val):
if not is_nonstr_iter(val):
val = (val,)
View
7 pyramid/tests/test_config/test_util.py
@@ -286,6 +286,13 @@ def test_predicate_text_is_correct(self):
self.assertEqual(predicates[10].__text__, 'classmethod predicate')
self.assertEqual(predicates[11].__text__, '<unknown custom predicate>')
+ def test_predicate_text_for_params_is_correct(self):
+ _, predicates, _ = self._callFUT(request_param='abc=123',
+ match_param=('foo=bar', 'qux'))
+ self.assertEqual(predicates[0].__text__, "request_param ['abc=123']")
+ self.assertEqual(predicates[1].__text__,
+ "match_param ['foo=bar', 'qux']")
+
def test_match_param_from_string(self):
_, predicates, _ = self._callFUT(match_param='foo=bar')
request = DummyRequest()
View
20 pyramid/tests/test_config/test_views.py
@@ -1173,6 +1173,26 @@ def test_add_view_with_request_param_val_false(self):
request.params = {'abc':''}
self._assertNotFound(wrapper, None, request)
+ def test_add_view_with_request_param_multi_true(self):
+ from pyramid.renderers import null_renderer
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, request_param=('abc=123', 'foo'),
+ renderer=null_renderer)
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.params = {'abc':'123', 'foo':''}
+ self.assertEqual(wrapper(None, request), 'OK')
+
+ def test_add_view_with_request_param_multi_false(self):
+ view = lambda *arg: 'OK'
+ config = self._makeOne(autocommit=True)
+ config.add_view(view=view, request_param=('abc=123', 'foo'))
+ wrapper = self._getViewCallable(config)
+ request = self._makeRequest(config)
+ request.params = {'abc':''}
+ self._assertNotFound(wrapper, None, request)
+
def test_add_view_with_xhr_true(self):
from pyramid.renderers import null_renderer
view = lambda *arg: 'OK'
Something went wrong with that request. Please try again.