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