Michael Merickel
2017-07-10 e7fcb190cc0a6bf5631cee7dad78ff8c0490403d
commit | author | age
5bf23f 1 import unittest
d6ff99 2 from pyramid.compat import text_
5bf23f 3
9c8ec5 4 class TestPredicateList(unittest.TestCase):
CM 5
6     def _makeOne(self):
7         from pyramid.config.util import PredicateList
c7974f 8         from pyramid import predicates
9c8ec5 9         inst = PredicateList()
CM 10         for name, factory in (
11             ('xhr', predicates.XHRPredicate),
12             ('request_method', predicates.RequestMethodPredicate),
13             ('path_info', predicates.PathInfoPredicate),
14             ('request_param', predicates.RequestParamPredicate),
15             ('header', predicates.HeaderPredicate),
16             ('accept', predicates.AcceptPredicate),
17             ('containment', predicates.ContainmentPredicate),
18             ('request_type', predicates.RequestTypePredicate),
19             ('match_param', predicates.MatchParamPredicate),
20             ('custom', predicates.CustomPredicate),
21             ('traverse', predicates.TraversePredicate),
22             ):
23             inst.add(name, factory)
24         return inst
25
5bf23f 26     def _callFUT(self, **kw):
9c8ec5 27         inst = self._makeOne()
CM 28         config = DummyConfigurator()
29         return inst.make(config, **kw)
5bf23f 30
CM 31     def test_ordering_xhr_and_request_method_trump_only_containment(self):
32         order1, _, _ = self._callFUT(xhr=True, request_method='GET')
33         order2, _, _ = self._callFUT(containment=True)
34         self.assertTrue(order1 < order2)
35
36     def test_ordering_number_of_predicates(self):
9c8ec5 37         from pyramid.config.util import predvalseq
5bf23f 38         order1, _, _ = self._callFUT(
CM 39             xhr='xhr',
40             request_method='request_method',
41             path_info='path_info',
42             request_param='param',
718a44 43             match_param='foo=bar',
5bf23f 44             header='header',
CM 45             accept='accept',
46             containment='containment',
47             request_type='request_type',
9c8ec5 48             custom=predvalseq([DummyCustomPredicate()]),
5bf23f 49             )
CM 50         order2, _, _ = self._callFUT(
51             xhr='xhr',
52             request_method='request_method',
53             path_info='path_info',
54             request_param='param',
718a44 55             match_param='foo=bar',
5bf23f 56             header='header',
CM 57             accept='accept',
58             containment='containment',
59             request_type='request_type',
9c8ec5 60             custom=predvalseq([DummyCustomPredicate()]),
5bf23f 61             )
CM 62         order3, _, _ = self._callFUT(
63             xhr='xhr',
64             request_method='request_method',
65             path_info='path_info',
66             request_param='param',
718a44 67             match_param='foo=bar',
5bf23f 68             header='header',
CM 69             accept='accept',
70             containment='containment',
71             request_type='request_type',
72             )
73         order4, _, _ = self._callFUT(
74             xhr='xhr',
75             request_method='request_method',
76             path_info='path_info',
77             request_param='param',
718a44 78             match_param='foo=bar',
5bf23f 79             header='header',
CM 80             accept='accept',
81             containment='containment',
82             )
83         order5, _, _ = self._callFUT(
84             xhr='xhr',
85             request_method='request_method',
86             path_info='path_info',
87             request_param='param',
718a44 88             match_param='foo=bar',
5bf23f 89             header='header',
CM 90             accept='accept',
91             )
92         order6, _, _ = self._callFUT(
93             xhr='xhr',
94             request_method='request_method',
95             path_info='path_info',
96             request_param='param',
718a44 97             match_param='foo=bar',
5bf23f 98             header='header',
CM 99             )
100         order7, _, _ = self._callFUT(
101             xhr='xhr',
102             request_method='request_method',
103             path_info='path_info',
104             request_param='param',
718a44 105             match_param='foo=bar',
5bf23f 106             )
CM 107         order8, _, _ = self._callFUT(
108             xhr='xhr',
109             request_method='request_method',
110             path_info='path_info',
718a44 111             request_param='param',
5bf23f 112             )
CM 113         order9, _, _ = self._callFUT(
114             xhr='xhr',
115             request_method='request_method',
718a44 116             path_info='path_info',
5bf23f 117             )
CM 118         order10, _, _ = self._callFUT(
119             xhr='xhr',
718a44 120             request_method='request_method',
5bf23f 121             )
CM 122         order11, _, _ = self._callFUT(
718a44 123             xhr='xhr',
MM 124             )
125         order12, _, _ = self._callFUT(
5bf23f 126             )
CM 127         self.assertEqual(order1, order2)
128         self.assertTrue(order3 > order2)
129         self.assertTrue(order4 > order3)
130         self.assertTrue(order5 > order4)
131         self.assertTrue(order6 > order5)
132         self.assertTrue(order7 > order6)
133         self.assertTrue(order8 > order7)
134         self.assertTrue(order9 > order8)
135         self.assertTrue(order10 > order9)
136         self.assertTrue(order11 > order10)
718a44 137         self.assertTrue(order12 > order10)
5bf23f 138
CM 139     def test_ordering_importance_of_predicates(self):
9c8ec5 140         from pyramid.config.util import predvalseq
5bf23f 141         order1, _, _ = self._callFUT(
CM 142             xhr='xhr',
143             )
144         order2, _, _ = self._callFUT(
145             request_method='request_method',
146             )
147         order3, _, _ = self._callFUT(
148             path_info='path_info',
149             )
150         order4, _, _ = self._callFUT(
151             request_param='param',
152             )
153         order5, _, _ = self._callFUT(
154             header='header',
155             )
156         order6, _, _ = self._callFUT(
157             accept='accept',
158             )
159         order7, _, _ = self._callFUT(
160             containment='containment',
161             )
162         order8, _, _ = self._callFUT(
163             request_type='request_type',
164             )
165         order9, _, _ = self._callFUT(
718a44 166             match_param='foo=bar',
MM 167             )
168         order10, _, _ = self._callFUT(
9c8ec5 169             custom=predvalseq([DummyCustomPredicate()]),
5bf23f 170             )
CM 171         self.assertTrue(order1 > order2)
172         self.assertTrue(order2 > order3)
173         self.assertTrue(order3 > order4)
174         self.assertTrue(order4 > order5)
175         self.assertTrue(order5 > order6)
176         self.assertTrue(order6 > order7)
177         self.assertTrue(order7 > order8)
178         self.assertTrue(order8 > order9)
718a44 179         self.assertTrue(order9 > order10)
5bf23f 180
CM 181     def test_ordering_importance_and_number(self):
9c8ec5 182         from pyramid.config.util import predvalseq
5bf23f 183         order1, _, _ = self._callFUT(
CM 184             xhr='xhr',
185             request_method='request_method',
186             )
187         order2, _, _ = self._callFUT(
9c8ec5 188             custom=predvalseq([DummyCustomPredicate()]),
5bf23f 189             )
CM 190         self.assertTrue(order1 < order2)
191
192         order1, _, _ = self._callFUT(
193             xhr='xhr',
194             request_method='request_method',
195             )
196         order2, _, _ = self._callFUT(
197             request_method='request_method',
9c8ec5 198             custom=predvalseq([DummyCustomPredicate()]),
5bf23f 199             )
CM 200         self.assertTrue(order1 > order2)
201
202         order1, _, _ = self._callFUT(
203             xhr='xhr',
204             request_method='request_method',
205             path_info='path_info',
206             )
207         order2, _, _ = self._callFUT(
208             request_method='request_method',
9c8ec5 209             custom=predvalseq([DummyCustomPredicate()]),
5bf23f 210             )
CM 211         self.assertTrue(order1 < order2)
212
213         order1, _, _ = self._callFUT(
214             xhr='xhr',
215             request_method='request_method',
216             path_info='path_info',
217             )
218         order2, _, _ = self._callFUT(
219             xhr='xhr',
220             request_method='request_method',
9c8ec5 221             custom=predvalseq([DummyCustomPredicate()]),
5bf23f 222             )
CM 223         self.assertTrue(order1 > order2)
224
225     def test_different_custom_predicates_with_same_hash(self):
9c8ec5 226         from pyramid.config.util import predvalseq
5bf23f 227         class PredicateWithHash(object):
CM 228             def __hash__(self):
229                 return 1
230         a = PredicateWithHash()
231         b = PredicateWithHash()
9c8ec5 232         _, _, a_phash = self._callFUT(custom=predvalseq([a]))
CM 233         _, _, b_phash = self._callFUT(custom=predvalseq([b]))
5bf23f 234         self.assertEqual(a_phash, b_phash)
CM 235
236     def test_traverse_has_remainder_already(self):
237         order, predicates, phash = self._callFUT(traverse='/1/:a/:b')
238         self.assertEqual(len(predicates), 1)
239         pred = predicates[0]
240         info = {'traverse':'abc'}
241         request = DummyRequest()
242         result = pred(info, request)
243         self.assertEqual(result, True)
244         self.assertEqual(info, {'traverse':'abc'})
245
246     def test_traverse_matches(self):
247         order, predicates, phash = self._callFUT(traverse='/1/:a/:b')
248         self.assertEqual(len(predicates), 1)
249         pred = predicates[0]
250         info = {'match':{'a':'a', 'b':'b'}}
251         request = DummyRequest()
252         result = pred(info, request)
253         self.assertEqual(result, True)
254         self.assertEqual(info, {'match':
255                                 {'a':'a', 'b':'b', 'traverse':('1', 'a', 'b')}})
256
586401 257     def test_traverse_matches_with_highorder_chars(self):
CM 258         order, predicates, phash = self._callFUT(
403dc9 259             traverse=text_(b'/La Pe\xc3\xb1a/{x}', 'utf-8'))
586401 260         self.assertEqual(len(predicates), 1)
CM 261         pred = predicates[0]
262         info = {'match':{'x':text_(b'Qu\xc3\xa9bec', 'utf-8')}}
263         request = DummyRequest()
264         result = pred(info, request)
265         self.assertEqual(result, True)
266         self.assertEqual(
267             info['match']['traverse'],
268             (text_(b'La Pe\xc3\xb1a', 'utf-8'),
269              text_(b'Qu\xc3\xa9bec', 'utf-8'))
270              )
271
c81dbd 272     def test_custom_predicates_can_affect_traversal(self):
9c8ec5 273         from pyramid.config.util import predvalseq
c81dbd 274         def custom(info, request):
MM 275             m = info['match']
276             m['dummy'] = 'foo'
277             return True
9c8ec5 278         _, predicates, _ = self._callFUT(
CM 279             custom=predvalseq([custom]),
280             traverse='/1/:dummy/:a')
c81dbd 281         self.assertEqual(len(predicates), 2)
MM 282         info = {'match':{'a':'a'}}
283         request = DummyRequest()
284         self.assertTrue(all([p(info, request) for p in predicates]))
285         self.assertEqual(info, {'match':
286                                 {'a':'a', 'dummy':'foo',
287                                  'traverse':('1', 'foo', 'a')}})
288
5bf23f 289     def test_predicate_text_is_correct(self):
9c8ec5 290         from pyramid.config.util import predvalseq
5bf23f 291         _, predicates, _ = self._callFUT(
CM 292             xhr='xhr',
293             request_method='request_method',
294             path_info='path_info',
295             request_param='param',
296             header='header',
297             accept='accept',
298             containment='containment',
299             request_type='request_type',
9c8ec5 300             custom=predvalseq(
CM 301                 [
302                     DummyCustomPredicate(),
5bf23f 303                     DummyCustomPredicate.classmethod_predicate,
9c8ec5 304                     DummyCustomPredicate.classmethod_predicate_no_text,
CM 305                 ]
306             ),
718a44 307             match_param='foo=bar')
9c8ec5 308         self.assertEqual(predicates[0].text(), 'xhr = True')
CM 309         self.assertEqual(predicates[1].text(),
310                          "request_method = request_method")
311         self.assertEqual(predicates[2].text(), 'path_info = path_info')
312         self.assertEqual(predicates[3].text(), 'request_param param')
313         self.assertEqual(predicates[4].text(), 'header header')
314         self.assertEqual(predicates[5].text(), 'accept = accept')
315         self.assertEqual(predicates[6].text(), 'containment = containment')
316         self.assertEqual(predicates[7].text(), 'request_type = request_type')
317         self.assertEqual(predicates[8].text(), "match_param foo=bar")
318         self.assertEqual(predicates[9].text(), 'custom predicate')
319         self.assertEqual(predicates[10].text(), 'classmethod predicate')
320         self.assertTrue(predicates[11].text().startswith('custom predicate'))
718a44 321
MM 322     def test_match_param_from_string(self):
323         _, predicates, _ = self._callFUT(match_param='foo=bar')
324         request = DummyRequest()
325         request.matchdict = {'foo':'bar', 'baz':'bum'}
326         self.assertTrue(predicates[0](Dummy(), request))
327
328     def test_match_param_from_string_fails(self):
329         _, predicates, _ = self._callFUT(match_param='foo=bar')
330         request = DummyRequest()
331         request.matchdict = {'foo':'bum', 'baz':'bum'}
332         self.assertFalse(predicates[0](Dummy(), request))
333
334     def test_match_param_from_dict(self):
835d48 335         _, predicates, _ = self._callFUT(match_param=('foo=bar','baz=bum'))
718a44 336         request = DummyRequest()
MM 337         request.matchdict = {'foo':'bar', 'baz':'bum'}
338         self.assertTrue(predicates[0](Dummy(), request))
339
340     def test_match_param_from_dict_fails(self):
835d48 341         _, predicates, _ = self._callFUT(match_param=('foo=bar','baz=bum'))
718a44 342         request = DummyRequest()
MM 343         request.matchdict = {'foo':'bar', 'baz':'foo'}
344         self.assertFalse(predicates[0](Dummy(), request))
5bf23f 345
49f082 346     def test_request_method_sequence(self):
CM 347         _, predicates, _ = self._callFUT(request_method=('GET', 'HEAD'))
348         request = DummyRequest()
349         request.method = 'HEAD'
350         self.assertTrue(predicates[0](Dummy(), request))
351         request.method = 'GET'
352         self.assertTrue(predicates[0](Dummy(), request))
353         request.method = 'POST'
354         self.assertFalse(predicates[0](Dummy(), request))
355
356     def test_request_method_ordering_hashes_same(self):
357         hash1, _, __= self._callFUT(request_method=('GET', 'HEAD'))
358         hash2, _, __= self._callFUT(request_method=('HEAD', 'GET'))
359         self.assertEqual(hash1, hash2)
360         hash1, _, __= self._callFUT(request_method=('GET',))
361         hash2, _, __= self._callFUT(request_method='GET')
362         self.assertEqual(hash1, hash2)
363
adf323 364     def test_unknown_predicate(self):
CM 365         from pyramid.exceptions import ConfigurationError
366         self.assertRaises(ConfigurationError, self._callFUT, unknown=1)
32333e 367
aafaf7 368     def test_predicate_close_matches(self):
FL 369         from pyramid.exceptions import ConfigurationError
370         with  self.assertRaises(ConfigurationError) as context:
371             self._callFUT(method='GET')
372         expected_msg = (
373             "Unknown predicate values: {'method': 'GET'} "
374             "(did you mean request_method)"
375         )
376         self.assertEqual(context.exception.args[0], expected_msg)
377
32333e 378     def test_notted(self):
CM 379         from pyramid.config import not_
380         from pyramid.testing import DummyRequest
381         request = DummyRequest()
382         _, predicates, _ = self._callFUT(
383             xhr='xhr',
384             request_method=not_('POST'),
385             header=not_('header'),
386             )
387         self.assertEqual(predicates[0].text(), 'xhr = True')
388         self.assertEqual(predicates[1].text(),
389                          "!request_method = POST")
390         self.assertEqual(predicates[2].text(), '!header header')
391         self.assertEqual(predicates[1](None, request), True)
392         self.assertEqual(predicates[2](None, request), True)
b098c2 393
32333e 394 class TestNotted(unittest.TestCase):
CM 395     def _makeOne(self, predicate):
396         from pyramid.config.util import Notted
397         return Notted(predicate)
ac0ece 398
32333e 399     def test_it_with_phash_val(self):
CM 400         pred = DummyPredicate('val')
401         inst = self._makeOne(pred)
402         self.assertEqual(inst.text(), '!val')
403         self.assertEqual(inst.phash(), '!val')
404         self.assertEqual(inst(None, None), False)
405
406     def test_it_without_phash_val(self):
407         pred = DummyPredicate('')
408         inst = self._makeOne(pred)
409         self.assertEqual(inst.text(), '')
410         self.assertEqual(inst.phash(), '')
411         self.assertEqual(inst(None, None), True)
b098c2 412
c7974f 413
MM 414 class TestDeprecatedPredicates(unittest.TestCase):
415     def test_it(self):
416         import warnings
417         with warnings.catch_warnings(record=True) as w:
418             warnings.filterwarnings('always')
419             from pyramid.config.predicates import XHRPredicate
420             self.assertEqual(len(w), 1)
421
32333e 422 class DummyPredicate(object):
CM 423     def __init__(self, result):
424         self.result = result
b098c2 425
32333e 426     def text(self):
CM 427         return self.result
428
429     phash = text
430
431     def __call__(self, context, request):
432         return True
b098c2 433
5bf23f 434 class DummyCustomPredicate(object):
CM 435     def __init__(self):
436         self.__text__ = 'custom predicate'
437
438     def classmethod_predicate(*args): pass
439     classmethod_predicate.__text__ = 'classmethod predicate'
440     classmethod_predicate = classmethod(classmethod_predicate)
441
442     @classmethod
443     def classmethod_predicate_no_text(*args): pass # pragma: no cover
444
718a44 445 class Dummy:
MM 446     pass
447
5bf23f 448 class DummyRequest:
CM 449     subpath = ()
450     matchdict = None
451     def __init__(self, environ=None):
452         if environ is None:
453             environ = {}
454         self.environ = environ
455         self.params = {}
456         self.cookies = {}
457
9c8ec5 458 class DummyConfigurator(object):
CM 459     def maybe_dotted(self, thing):
460         return thing
b098c2 461