Michael Merickel
2017-06-18 75c30dfe18b26ca04efae2acbe35052fa0d93ed6
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
BJR 394
28fc3d 395 class Test_takes_one_arg(unittest.TestCase):
CM 396     def _callFUT(self, view, attr=None, argname=None):
397         from pyramid.config.util import takes_one_arg
398         return takes_one_arg(view, attr=attr, argname=argname)
399
400     def test_requestonly_newstyle_class_no_init(self):
401         class foo(object):
402             """ """
403         self.assertFalse(self._callFUT(foo))
404
405     def test_requestonly_newstyle_class_init_toomanyargs(self):
406         class foo(object):
407             def __init__(self, context, request):
408                 """ """
409         self.assertFalse(self._callFUT(foo))
410
411     def test_requestonly_newstyle_class_init_onearg_named_request(self):
412         class foo(object):
413             def __init__(self, request):
414                 """ """
415         self.assertTrue(self._callFUT(foo))
416
417     def test_newstyle_class_init_onearg_named_somethingelse(self):
418         class foo(object):
419             def __init__(self, req):
420                 """ """
421         self.assertTrue(self._callFUT(foo))
422
423     def test_newstyle_class_init_defaultargs_firstname_not_request(self):
424         class foo(object):
425             def __init__(self, context, request=None):
426                 """ """
427         self.assertFalse(self._callFUT(foo))
428
429     def test_newstyle_class_init_defaultargs_firstname_request(self):
430         class foo(object):
431             def __init__(self, request, foo=1, bar=2):
432                 """ """
433         self.assertTrue(self._callFUT(foo, argname='request'))
434
435     def test_newstyle_class_init_firstname_request_with_secondname(self):
436         class foo(object):
437             def __init__(self, request, two):
438                 """ """
439         self.assertFalse(self._callFUT(foo))
440
441     def test_newstyle_class_init_noargs(self):
442         class foo(object):
443             def __init__():
444                 """ """
445         self.assertFalse(self._callFUT(foo))
446
447     def test_oldstyle_class_no_init(self):
448         class foo:
449             """ """
450         self.assertFalse(self._callFUT(foo))
451
452     def test_oldstyle_class_init_toomanyargs(self):
453         class foo:
454             def __init__(self, context, request):
455                 """ """
456         self.assertFalse(self._callFUT(foo))
457
458     def test_oldstyle_class_init_onearg_named_request(self):
459         class foo:
460             def __init__(self, request):
461                 """ """
462         self.assertTrue(self._callFUT(foo))
463
464     def test_oldstyle_class_init_onearg_named_somethingelse(self):
465         class foo:
466             def __init__(self, req):
467                 """ """
468         self.assertTrue(self._callFUT(foo))
469
470     def test_oldstyle_class_init_defaultargs_firstname_not_request(self):
471         class foo:
472             def __init__(self, context, request=None):
473                 """ """
474         self.assertFalse(self._callFUT(foo))
475
476     def test_oldstyle_class_init_defaultargs_firstname_request(self):
477         class foo:
478             def __init__(self, request, foo=1, bar=2):
479                 """ """
480         self.assertTrue(self._callFUT(foo, argname='request'), True)
481
482     def test_oldstyle_class_init_noargs(self):
483         class foo:
484             def __init__():
485                 """ """
486         self.assertFalse(self._callFUT(foo))
487
488     def test_function_toomanyargs(self):
489         def foo(context, request):
490             """ """
491         self.assertFalse(self._callFUT(foo))
492
493     def test_function_with_attr_false(self):
494         def bar(context, request):
495             """ """
496         def foo(context, request):
497             """ """
498         foo.bar = bar
499         self.assertFalse(self._callFUT(foo, 'bar'))
500
501     def test_function_with_attr_true(self):
502         def bar(context, request):
503             """ """
504         def foo(request):
505             """ """
506         foo.bar = bar
507         self.assertTrue(self._callFUT(foo, 'bar'))
508
509     def test_function_onearg_named_request(self):
510         def foo(request):
511             """ """
512         self.assertTrue(self._callFUT(foo))
513
514     def test_function_onearg_named_somethingelse(self):
515         def foo(req):
516             """ """
517         self.assertTrue(self._callFUT(foo))
518
519     def test_function_defaultargs_firstname_not_request(self):
520         def foo(context, request=None):
521             """ """
522         self.assertFalse(self._callFUT(foo))
523
524     def test_function_defaultargs_firstname_request(self):
525         def foo(request, foo=1, bar=2):
526             """ """
527         self.assertTrue(self._callFUT(foo, argname='request'))
528
529     def test_function_noargs(self):
530         def foo():
531             """ """
532         self.assertFalse(self._callFUT(foo))
533
534     def test_instance_toomanyargs(self):
535         class Foo:
536             def __call__(self, context, request):
537                 """ """
538         foo = Foo()
539         self.assertFalse(self._callFUT(foo))
540
541     def test_instance_defaultargs_onearg_named_request(self):
542         class Foo:
543             def __call__(self, request):
544                 """ """
545         foo = Foo()
546         self.assertTrue(self._callFUT(foo))
547
548     def test_instance_defaultargs_onearg_named_somethingelse(self):
549         class Foo:
550             def __call__(self, req):
551                 """ """
552         foo = Foo()
553         self.assertTrue(self._callFUT(foo))
554
555     def test_instance_defaultargs_firstname_not_request(self):
556         class Foo:
557             def __call__(self, context, request=None):
558                 """ """
559         foo = Foo()
560         self.assertFalse(self._callFUT(foo))
561
562     def test_instance_defaultargs_firstname_request(self):
563         class Foo:
564             def __call__(self, request, foo=1, bar=2):
565                 """ """
566         foo = Foo()
567         self.assertTrue(self._callFUT(foo, argname='request'), True)
568
569     def test_instance_nocall(self):
570         class Foo: pass
571         foo = Foo()
572         self.assertFalse(self._callFUT(foo))
b098c2 573
28fc3d 574     def test_method_onearg_named_request(self):
CM 575         class Foo:
576             def method(self, request):
577                 """ """
578         foo = Foo()
579         self.assertTrue(self._callFUT(foo.method))
580
d49949 581     def test_function_annotations(self):
IE 582         def foo(bar):
583             """ """
584         # avoid SyntaxErrors in python2, this if effectively nop
585         getattr(foo, '__annotations__', {}).update({'bar': 'baz'})
586         self.assertTrue(self._callFUT(foo))
0ccb82 587
32333e 588 class TestNotted(unittest.TestCase):
CM 589     def _makeOne(self, predicate):
590         from pyramid.config.util import Notted
591         return Notted(predicate)
ac0ece 592
32333e 593     def test_it_with_phash_val(self):
CM 594         pred = DummyPredicate('val')
595         inst = self._makeOne(pred)
596         self.assertEqual(inst.text(), '!val')
597         self.assertEqual(inst.phash(), '!val')
598         self.assertEqual(inst(None, None), False)
599
600     def test_it_without_phash_val(self):
601         pred = DummyPredicate('')
602         inst = self._makeOne(pred)
603         self.assertEqual(inst.text(), '')
604         self.assertEqual(inst.phash(), '')
605         self.assertEqual(inst(None, None), True)
b098c2 606
c7974f 607
MM 608 class TestDeprecatedPredicates(unittest.TestCase):
609     def test_it(self):
610         import warnings
611         with warnings.catch_warnings(record=True) as w:
612             warnings.filterwarnings('always')
613             from pyramid.config.predicates import XHRPredicate
614             self.assertEqual(len(w), 1)
615
32333e 616 class DummyPredicate(object):
CM 617     def __init__(self, result):
618         self.result = result
b098c2 619
32333e 620     def text(self):
CM 621         return self.result
622
623     phash = text
624
625     def __call__(self, context, request):
626         return True
b098c2 627
5bf23f 628 class DummyCustomPredicate(object):
CM 629     def __init__(self):
630         self.__text__ = 'custom predicate'
631
632     def classmethod_predicate(*args): pass
633     classmethod_predicate.__text__ = 'classmethod predicate'
634     classmethod_predicate = classmethod(classmethod_predicate)
635
636     @classmethod
637     def classmethod_predicate_no_text(*args): pass # pragma: no cover
638
718a44 639 class Dummy:
MM 640     pass
641
5bf23f 642 class DummyRequest:
CM 643     subpath = ()
644     matchdict = None
645     def __init__(self, environ=None):
646         if environ is None:
647             environ = {}
648         self.environ = environ
649         self.params = {}
650         self.cookies = {}
651
9c8ec5 652 class DummyConfigurator(object):
CM 653     def maybe_dotted(self, thing):
654         return thing
b098c2 655