Michael Merickel
2011-08-21 7ecc829f5a78e2a04a64cc9a44d46a151b171554
commit | author | age
8392d7 1 import unittest
b60bdb 2 from pyramid import testing
8392d7 3
05c023 4 class TestRoute(unittest.TestCase):
CM 5     def _getTargetClass(self):
b60bdb 6         from pyramid.urldispatch import Route
05c023 7         return Route
CM 8
ae7d03 9     def _makeOne(self, *arg, **kw):
MM 10         return self._getTargetClass()(*arg, **kw)
05c023 11
74409d 12     def test_provides_IRoute(self):
b60bdb 13         from pyramid.interfaces import IRoute
74409d 14         from zope.interface.verify import verifyObject
CM 15         verifyObject(IRoute, self._makeOne('name', 'pattern'))
16
05c023 17     def test_ctor(self):
f646fe 18         import types
74409d 19         route = self._makeOne('name', ':path', 'factory')
CM 20         self.assertEqual(route.pattern, ':path')
6b9be1 21         self.assertEqual(route.path, ':path')
05c023 22         self.assertEqual(route.name, 'name')
CM 23         self.assertEqual(route.factory, 'factory')
a1d395 24         self.assertTrue(route.generate.__class__ is types.FunctionType)
CM 25         self.assertTrue(route.match.__class__ is types.FunctionType)
ae7d03 26         self.assertEqual(route.args, ['path'])
MM 27         self.assertEqual(route.pregenerator, None)
6b9be1 28
CM 29     def test_ctor_defaults(self):
f646fe 30         import types
74409d 31         route = self._makeOne('name', ':path')
CM 32         self.assertEqual(route.pattern, ':path')
6b9be1 33         self.assertEqual(route.path, ':path')
74409d 34         self.assertEqual(route.name, 'name')
6b9be1 35         self.assertEqual(route.factory, None)
a1d395 36         self.assertTrue(route.generate.__class__ is types.FunctionType)
CM 37         self.assertTrue(route.match.__class__ is types.FunctionType)
ae7d03 38         self.assertEqual(route.args, ['path'])
MM 39         self.assertEqual(route.pregenerator, None)
05c023 40
CM 41     def test_match(self):
74409d 42         route = self._makeOne('name', ':path')
f646fe 43         self.assertEqual(route.match('/whatever'), {'path':'whatever'})
d3c39d 44
05c023 45     def test_generate(self):
74409d 46         route = self._makeOne('name', ':path')
f646fe 47         self.assertEqual(route.generate({'path':'abc'}), '/abc')
05c023 48
ae7d03 49     def test_gen(self):
MM 50         request = DummyRequest({})
51         route = self._makeOne('name', ':path')
52         path, kw = route.gen(request, ('extra1', 'extra2'), {'path':1})
53         self.assertEqual(path, '/1/extra1/extra2')
54         self.assertEqual(kw, {'path':1})
55
56     def test_gen_no_elements(self):
57         request = DummyRequest({})
58         route = self._makeOne('name', ':path')
59         path, kw = route.gen(request, (), {'path':1})
60         self.assertEqual(path, '/1')
61         self.assertEqual(kw, {'path':1})
62
63     def test_gen_no_kwargs(self):
64         request = DummyRequest({})
65         route = self._makeOne('name', 'foo')
66         path, kw = route.gen(request, (), {})
67         self.assertEqual(path, '/foo')
68         self.assertEqual(kw, {})
69
70     def test_gen_with_pregenerator(self):
71         request = DummyRequest({})
72         def pregenerator(request, elements, kw):
73             return ('a',), {'path':2, '_app_url':'http://example.com:6543'}
74         route = self._makeOne('name', ':path', pregenerator=pregenerator)
75         path, kw = route.gen(request, ('extra1', 'extra2'), {'path':1})
76         self.assertEqual(path, '/2/a')
77         self.assertEqual(kw, {'path':2, '_app_url':'http://example.com:6543'})
78
50cedf 79 class TestRouteGroup(unittest.TestCase):
MM 80     def _getTargetClass(self):
81         from pyramid.urldispatch import RouteGroup
82         return RouteGroup
83
84     def _makeOne(self, *arg, **kw):
85         return self._getTargetClass()(*arg, **kw)
86
87     def _makeRoute(self, *arg, **kw):
88         from pyramid.urldispatch import Route
89         return Route(*arg, **kw)
90
91     def test_add(self):
92         group = self._makeOne('name')
93         route0 = self._makeRoute('name', ':path')
94         route1 = self._makeRoute('name', ':path/:foo')
95         route2 = self._makeRoute('name', ':path/:foo/:bar')
96         group.add(route0)
97         group.add(route1)
98         group.add(route2)
99
100         self.assertEqual(group.name, 'name')
101         self.assertEqual(len(group.routes), 3)
102         self.assertEqual(len(group.sorted_routes), 3)
103         self.assertEqual(group.routes[0], route0)
104         self.assertEqual(group.routes[1], route1)
105         self.assertEqual(group.routes[2], route2)
106
107         entry0 = group.sorted_routes[0]
108         entry1 = group.sorted_routes[1]
109         entry2 = group.sorted_routes[2]
110         self.assertEqual(entry0[3], route2)
111         self.assertEqual(entry1[3], route1)
112         self.assertEqual(entry2[3], route0)
113
114     def test_no_match(self):
115         request = DummyRequest({})
116         group = self._makeOne('name')
117         route0 = self._makeRoute('name', ':path')
118         route1 = self._makeRoute('name', ':path/:foo')
119         group.add(route0)
120         group.add(route1)
121
122         self.assertRaises(KeyError, group.gen, request, (), {})
123
124     def test_match(self):
125         request = DummyRequest({})
126         group = self._makeOne('name')
127         route0 = self._makeRoute('name', ':a/edit')
128         route1 = self._makeRoute('name', '/p/:a/:b/:c')
129         route2 = self._makeRoute('name', ':b/:c')
130         group.add(route0)
131         group.add(route1)
132         group.add(route2)
133
134         path, kw = group.gen(request, (), {'a':1})
135         self.assertEqual(path, '/1/edit')
136         self.assertEqual(kw, {'a':1})
137
138         path, kw = group.gen(request, (), {'a':1, 'b':2, 'c':3})
139         self.assertEqual(path, '/p/1/2/3')
140         self.assertEqual(kw, {'a':1, 'b':2, 'c':3})
141
142         path, kw = group.gen(request, (), {'b':2, 'c':3})
143         self.assertEqual(path, '/2/3')
144         self.assertEqual(kw, {'b':2, 'c':3})
145
146     def test_match_pregenerator(self):
147         request = DummyRequest({})
148         def pregenerator(request, elements, kwargs):
149             kwargs['a'] = 10
150             return elements, kwargs
151         group = self._makeOne('name')
152         route0 = self._makeRoute('name', ':a/edit')
153         route1 = self._makeRoute('name', '/p/:a/:b/:c',
154                                  pregenerator=pregenerator)
155         route2 = self._makeRoute('name', ':b/:c', pregenerator=pregenerator)
156         group.add(route0)
157         group.add(route1)
158         group.add(route2)
159
160         path, kw = group.gen(request, ('extra1', 'extra2'), {'a':1})
161         self.assertEqual(path, '/1/edit/extra1/extra2')
162         self.assertEqual(kw, {'a':1})
163
164         path, kw = group.gen(request, ('extra1',), {'a':1, 'b':2, 'c':3})
165         self.assertEqual(path, '/p/10/2/3/extra1')
166         self.assertEqual(kw, {'a':10, 'b':2, 'c':3})
167
168         path, kw = group.gen(request, (), {'b':2, 'c':3})
169         self.assertEqual(path, '/p/10/2/3')
170         self.assertEqual(kw, {'a':10, 'b':2, 'c':3})
171
172     def test_match_ordering(self):
173         request = DummyRequest({})
174         group = self._makeOne('name')
175         route0 = self._makeRoute('name', '/p/:a/:b/:c')
176         route1 = self._makeRoute('name', ':a/:b/:c')
177         group.add(route0)
178         group.add(route1)
179
180         path, kw = group.gen(request, (), {'a':1, 'b':2, 'c':3})
7ecc82 181         self.assertEqual(path, '/1/2/3')
50cedf 182         self.assertEqual(kw, {'a':1, 'b':2, 'c':3})
MM 183
cbfafb 184 class RoutesMapperTests(unittest.TestCase):
def444 185     def setUp(self):
11644e 186         testing.setUp()
def444 187
CM 188     def tearDown(self):
11644e 189         testing.tearDown()
def444 190         
11644e 191     def _getRequest(self, **kw):
b60bdb 192         from pyramid.threadlocal import get_current_registry
62267e 193         environ = {'SERVER_NAME':'localhost',
CM 194                    'wsgi.url_scheme':'http'}
195         environ.update(kw)
11644e 196         request = DummyRequest(environ)
e27974 197         reg = get_current_registry()
CM 198         request.registry = reg
11644e 199         return request
CM 200
8392d7 201     def _getTargetClass(self):
b60bdb 202         from pyramid.urldispatch import RoutesMapper
cbfafb 203         return RoutesMapper
8392d7 204
cbfafb 205     def _makeOne(self):
8392d7 206         klass = self._getTargetClass()
cbfafb 207         return klass()
8392d7 208
74409d 209     def test_provides_IRoutesMapper(self):
b60bdb 210         from pyramid.interfaces import IRoutesMapper
74409d 211         from zope.interface.verify import verifyObject
CM 212         verifyObject(IRoutesMapper, self._makeOne())
213
62267e 214     def test_no_route_matches(self):
cbfafb 215         mapper = self._makeOne()
11644e 216         request = self._getRequest(PATH_INFO='/')
CM 217         result = mapper(request)
cbfafb 218         self.assertEqual(result['match'], None)
CM 219         self.assertEqual(result['route'], None)
8392d7 220
534cb4 221     def test_connect_name_exists_removes_old(self):
MM 222         mapper = self._makeOne()
223         mapper.connect('foo', 'archives/:action/:article')
224         mapper.connect('foo', 'archives/:action/:article2')
225         self.assertEqual(len(mapper.routelist), 1)
226         self.assertEqual(len(mapper.routes), 1)
227         self.assertEqual(mapper.routes['foo'].pattern,
228                          'archives/:action/:article2')
229         self.assertEqual(mapper.routelist[0].pattern,
230                          'archives/:action/:article2')
0bf286 231
e725cf 232     def test_connect_static(self):
CM 233         mapper = self._makeOne()
234         mapper.connect('foo', 'archives/:action/:article', static=True)
235         self.assertEqual(len(mapper.routelist), 0)
236         self.assertEqual(len(mapper.routes), 1)
237         self.assertEqual(mapper.routes['foo'].pattern,
238                          'archives/:action/:article')
239
534cb4 240     def test_connect_static_overridden(self):
MM 241         mapper = self._makeOne()
242         mapper.connect('foo', 'archives/:action/:article', static=True)
243         self.assertEqual(len(mapper.routelist), 0)
244         self.assertEqual(len(mapper.routes), 1)
245         self.assertEqual(mapper.routes['foo'].pattern,
246                          'archives/:action/:article')
247         mapper.connect('foo', 'archives/:action/:article2')
248         self.assertEqual(len(mapper.routelist), 1)
249         self.assertEqual(len(mapper.routes), 1)
250         self.assertEqual(mapper.routes['foo'].pattern,
251                          'archives/:action/:article2')
252         self.assertEqual(mapper.routelist[0].pattern,
253                          'archives/:action/:article2')
e725cf 254
d3c39d 255     def test___call__route_matches(self):
cbfafb 256         mapper = self._makeOne()
74409d 257         mapper.connect('foo', 'archives/:action/:article')
11644e 258         request = self._getRequest(PATH_INFO='/archives/action1/article1')
CM 259         result = mapper(request)
cbfafb 260         self.assertEqual(result['route'], mapper.routes['foo'])
CM 261         self.assertEqual(result['match']['action'], 'action1')
262         self.assertEqual(result['match']['article'], 'article1')
8392d7 263
d3c39d 264     def test___call__route_matches_with_predicates(self):
cbfafb 265         mapper = self._makeOne()
74409d 266         mapper.connect('foo', 'archives/:action/:article',
65476e 267                        predicates=[lambda *arg: True])
CM 268         request = self._getRequest(PATH_INFO='/archives/action1/article1')
269         result = mapper(request)
cbfafb 270         self.assertEqual(result['route'], mapper.routes['foo'])
CM 271         self.assertEqual(result['match']['action'], 'action1')
272         self.assertEqual(result['match']['article'], 'article1')
65476e 273
d3c39d 274     def test___call__route_fails_to_match_with_predicates(self):
cbfafb 275         mapper = self._makeOne()
74409d 276         mapper.connect('foo', 'archives/:action/article1',
65476e 277                        predicates=[lambda *arg: True, lambda *arg: False])
74409d 278         mapper.connect('bar', 'archives/:action/:article')
65476e 279         request = self._getRequest(PATH_INFO='/archives/action1/article1')
CM 280         result = mapper(request)
cbfafb 281         self.assertEqual(result['route'], mapper.routes['bar'])
CM 282         self.assertEqual(result['match']['action'], 'action1')
283         self.assertEqual(result['match']['article'], 'article1')
65476e 284
d3c39d 285     def test___call__custom_predicate_gets_info(self):
44bc11 286         mapper = self._makeOne()
CM 287         def pred(info, request):
288             self.assertEqual(info['match'], {'action':u'action1'})
289             self.assertEqual(info['route'], mapper.routes['foo'])
290             return True
74409d 291         mapper.connect('foo', 'archives/:action/article1', predicates=[pred])
44bc11 292         request = self._getRequest(PATH_INFO='/archives/action1/article1')
CM 293         mapper(request)
294
74a8f6 295     def test_cc_bug(self):
CM 296         # "unordered" as reported in IRC by author of
297         # http://labs.creativecommons.org/2010/01/13/cc-engine-and-web-non-frameworks/
298         mapper = self._makeOne()
74409d 299         mapper.connect('rdf', 'licenses/:license_code/:license_version/rdf')
CM 300         mapper.connect('juri',
301                        'licenses/:license_code/:license_version/:jurisdiction')
74a8f6 302
CM 303         request = self._getRequest(PATH_INFO='/licenses/1/v2/rdf')
304         result = mapper(request)
305         self.assertEqual(result['route'], mapper.routes['rdf'])
306         self.assertEqual(result['match']['license_code'], '1')
307         self.assertEqual(result['match']['license_version'], 'v2')
308
309         request = self._getRequest(PATH_INFO='/licenses/1/v2/usa')
310         result = mapper(request)
311         self.assertEqual(result['route'], mapper.routes['juri'])
312         self.assertEqual(result['match']['license_code'], '1')
313         self.assertEqual(result['match']['license_version'], 'v2')
314         self.assertEqual(result['match']['jurisdiction'], 'usa')
315
d3c39d 316     def test___call__root_route_matches(self):
cbfafb 317         mapper = self._makeOne()
74409d 318         mapper.connect('root', '')
11644e 319         request = self._getRequest(PATH_INFO='/')
CM 320         result = mapper(request)
cbfafb 321         self.assertEqual(result['route'], mapper.routes['root'])
CM 322         self.assertEqual(result['match'], {})
9688ac 323
d3c39d 324     def test___call__root_route_matches2(self):
cbfafb 325         mapper = self._makeOne()
74409d 326         mapper.connect('root', '/')
11644e 327         request = self._getRequest(PATH_INFO='/')
CM 328         result = mapper(request)
cbfafb 329         self.assertEqual(result['route'], mapper.routes['root'])
CM 330         self.assertEqual(result['match'], {})
8392d7 331
d3c39d 332     def test___call__root_route_when_path_info_empty(self):
cbfafb 333         mapper = self._makeOne()
74409d 334         mapper.connect('root', '/')
22e72d 335         request = self._getRequest(PATH_INFO='')
CM 336         result = mapper(request)
cbfafb 337         self.assertEqual(result['route'], mapper.routes['root'])
CM 338         self.assertEqual(result['match'], {})
def444 339
c18e27 340     def test___call__root_route_when_path_info_notempty(self):
CM 341         mapper = self._makeOne()
342         mapper.connect('root', '/')
343         request = self._getRequest(PATH_INFO='/')
344         result = mapper(request)
345         self.assertEqual(result['route'], mapper.routes['root'])
346         self.assertEqual(result['match'], {})
347
d3c39d 348     def test___call__no_path_info(self):
cbfafb 349         mapper = self._makeOne()
74409d 350         mapper.connect('root', '/')
11644e 351         request = self._getRequest()
CM 352         result = mapper(request)
cbfafb 353         self.assertEqual(result['route'], mapper.routes['root'])
CM 354         self.assertEqual(result['match'], {})
dcb656 355
62267e 356     def test_has_routes(self):
cbfafb 357         mapper = self._makeOne()
62267e 358         self.assertEqual(mapper.has_routes(), False)
29e012 359         mapper.connect('whatever', 'archives/:action/:article')
62267e 360         self.assertEqual(mapper.has_routes(), True)
CM 361
750ce4 362     def test_get_routes(self):
b60bdb 363         from pyramid.urldispatch import Route
cbfafb 364         mapper = self._makeOne()
750ce4 365         self.assertEqual(mapper.get_routes(), [])
CM 366         mapper.connect('whatever', 'archives/:action/:article')
367         routes = mapper.get_routes()
368         self.assertEqual(len(routes), 1)
369         self.assertEqual(routes[0].__class__, Route)
370
74409d 371     def test_get_route_matches(self):
CM 372         mapper = self._makeOne()
373         mapper.connect('whatever', 'archives/:action/:article')
374         result = mapper.get_route('whatever')
375         self.assertEqual(result.pattern, 'archives/:action/:article')
376
377     def test_get_route_misses(self):
378         mapper = self._makeOne()
379         result = mapper.get_route('whatever')
380         self.assertEqual(result, None)
381
05c023 382     def test_generate(self):
cbfafb 383         mapper = self._makeOne()
05c023 384         def generator(kw):
CM 385             return 123
386         route = DummyRoute(generator)
387         mapper.routes['abc'] =  route
388         self.assertEqual(mapper.generate('abc', {}), 123)
62267e 389
534cb4 390     def test_add_group(self):
MM 391         mapper = self._makeOne()
392         group = mapper.add_group('foo')
393         groups = mapper.get_groups()
394         self.assertTrue('foo' in groups)
395         self.assertEqual(group.name, 'foo')
396
397     def test_connect_to_group(self):
398         mapper = self._makeOne()
399         group = mapper.add_group('foo')
400         mapper.connect('foo', '/bar')
401         mapper.connect('foo', '/baz')
402         self.assertEqual(len(mapper.routes), 1)
403         self.assertEqual(len(group.routes), 2)
404
405     def test_add_group_removes_old_group(self):
406         mapper = self._makeOne()
407         mapper.add_group('foo')
408         mapper.connect('foo', 'archives/:action')
409         mapper.add_group('foo')
410         mapper.connect('foo', 'archives/:action/:article2')
411         group = mapper.get_group('foo')
412         self.assertEqual(len(mapper.routelist), 1)
413         self.assertEqual(len(mapper.routes), 1)
414         self.assertEqual(len(mapper.groups), 1)
415         self.assertEqual(len(group.routes), 1)
416         self.assertEqual(group.routes[0].pattern,
417                          'archives/:action/:article2')
418         self.assertEqual(mapper.routelist[0].pattern,
419                          'archives/:action/:article2')
420
421     def test_add_group_removes_old_route(self):
422         mapper = self._makeOne()
423         mapper.connect('foo', 'archives/:action')
424         mapper.add_group('foo')
425         mapper.connect('foo', 'archives/:action/:article2')
426         group = mapper.get_group('foo')
427         self.assertEqual(len(mapper.routelist), 1)
428         self.assertEqual(len(mapper.routes), 1)
429         self.assertEqual(len(mapper.groups), 1)
430         self.assertEqual(len(group.routes), 1)
431         self.assertEqual(group.routes[0].pattern,
432                          'archives/:action/:article2')
433         self.assertEqual(mapper.routelist[0].pattern,
434                          'archives/:action/:article2')
435
05c023 436 class TestCompileRoute(unittest.TestCase):
4018ad 437     def _callFUT(self, pattern):
b60bdb 438         from pyramid.urldispatch import _compile_route
4018ad 439         return _compile_route(pattern)
05c023 440
CM 441     def test_no_star(self):
411d7f 442         matcher, generator, args = self._callFUT('/foo/:baz/biz/:buz/bar')
05c023 443         self.assertEqual(matcher('/foo/baz/biz/buz/bar'),
CM 444                          {'baz':'baz', 'buz':'buz'})
445         self.assertEqual(matcher('foo/baz/biz/buz/bar'), None)
446         self.assertEqual(generator({'baz':1, 'buz':2}), '/foo/1/biz/2/bar')
411d7f 447         self.assertEqual(args, ['baz', 'buz'])
05c023 448
CM 449     def test_with_star(self):
411d7f 450         matcher, generator, args = self._callFUT(
MM 451             '/foo/:baz/biz/:buz/bar*traverse')
05c023 452         self.assertEqual(matcher('/foo/baz/biz/buz/bar'),
25cbe1 453                          {'baz':'baz', 'buz':'buz', 'traverse':()})
05c023 454         self.assertEqual(matcher('/foo/baz/biz/buz/bar/everything/else/here'),
CM 455                          {'baz':'baz', 'buz':'buz',
25cbe1 456                           'traverse':('everything', 'else', 'here')})
05c023 457         self.assertEqual(matcher('foo/baz/biz/buz/bar'), None)
CM 458         self.assertEqual(generator(
459             {'baz':1, 'buz':2, 'traverse':u'/a/b'}), '/foo/1/biz/2/bar/a/b')
411d7f 460         self.assertEqual(args, ['baz', 'buz', 'traverse'])
49315b 461     
BB 462     def test_with_bracket_star(self):
411d7f 463         matcher, generator, args = self._callFUT(
3ce731 464             '/foo/{baz}/biz/{buz}/bar{remainder:.*}')
49315b 465         self.assertEqual(matcher('/foo/baz/biz/buz/bar'),
BB 466                          {'baz':'baz', 'buz':'buz', 'remainder':''})
467         self.assertEqual(matcher('/foo/baz/biz/buz/bar/everything/else/here'),
468                          {'baz':'baz', 'buz':'buz',
469                           'remainder':'/everything/else/here'})
470         self.assertEqual(matcher('foo/baz/biz/buz/bar'), None)
471         self.assertEqual(generator(
472             {'baz':1, 'buz':2, 'remainder':'/a/b'}), '/foo/1/biz/2/bar%2Fa%2Fb')
411d7f 473         self.assertEqual(args, ['baz', 'buz', 'remainder'])
05c023 474
CM 475     def test_no_beginning_slash(self):
411d7f 476         matcher, generator, args = self._callFUT('foo/:baz/biz/:buz/bar')
05c023 477         self.assertEqual(matcher('/foo/baz/biz/buz/bar'),
CM 478                          {'baz':'baz', 'buz':'buz'})
479         self.assertEqual(matcher('foo/baz/biz/buz/bar'), None)
480         self.assertEqual(generator({'baz':1, 'buz':2}), '/foo/1/biz/2/bar')
411d7f 481         self.assertEqual(args, ['baz', 'buz'])
05c023 482
0482bd 483     def test_url_decode_error(self):
b60bdb 484         from pyramid.exceptions import URLDecodeError
411d7f 485         matcher, generator, args = self._callFUT('/:foo')
0482bd 486         self.assertRaises(URLDecodeError, matcher, '/%FF%FE%8B%00')
e84116 487     
BB 488     def test_custom_regex(self):
411d7f 489         matcher, generator, args = self._callFUT(
MM 490             'foo/{baz}/biz/{buz:[^/\.]+}.{bar}')
e84116 491         self.assertEqual(matcher('/foo/baz/biz/buz.bar'),
BB 492                          {'baz':'baz', 'buz':'buz', 'bar':'bar'})
493         self.assertEqual(matcher('foo/baz/biz/buz/bar'), None)
959523 494         self.assertEqual(generator({'baz':1, 'buz':2, 'bar': 'html'}),
CM 495                          '/foo/1/biz/2.html')
411d7f 496         self.assertEqual(args, ['baz', 'buz', 'bar'])
959523 497
3ce731 498     def test_mixed_newstyle_oldstyle_pattern_defaults_to_newstyle(self):
CM 499         # pattern: '\\/foo\\/(?P<baz>abc)\\/biz\\/(?P<buz>[^/]+)\\/bar$'
500         # note presence of :abc in pattern (oldstyle match)
411d7f 501         matcher, generator, args = self._callFUT('foo/{baz:abc}/biz/{buz}/bar')
3ce731 502         self.assertEqual(matcher('/foo/abc/biz/buz/bar'),
CM 503                          {'baz':'abc', 'buz':'buz'})
504         self.assertEqual(generator({'baz':1, 'buz':2}), '/foo/1/biz/2/bar')
411d7f 505         self.assertEqual(args, ['baz', 'buz'])
3ce731 506
e39ddf 507     def test_custom_regex_with_embedded_squigglies(self):
411d7f 508         matcher, generator, args = self._callFUT('/{buz:\d{4}}')
e39ddf 509         self.assertEqual(matcher('/2001'), {'buz':'2001'})
JG 510         self.assertEqual(matcher('/200'), None)
511         self.assertEqual(generator({'buz':2001}), '/2001')
411d7f 512         self.assertEqual(args, ['buz'])
959523 513
e39ddf 514     def test_custom_regex_with_embedded_squigglies2(self):
411d7f 515         matcher, generator, args = self._callFUT('/{buz:\d{3,4}}')
e39ddf 516         self.assertEqual(matcher('/2001'), {'buz':'2001'})
JG 517         self.assertEqual(matcher('/200'), {'buz':'200'})
518         self.assertEqual(matcher('/20'), None)
519         self.assertEqual(generator({'buz':2001}), '/2001')
411d7f 520         self.assertEqual(args, ['buz'])
e39ddf 521
JG 522     def test_custom_regex_with_embedded_squigglies3(self):
411d7f 523         matcher, generator, args = self._callFUT(
MM 524             '/{buz:(\d{2}|\d{4})-[a-zA-Z]{3,4}-\d{2}}')
e39ddf 525         self.assertEqual(matcher('/2001-Nov-15'), {'buz':'2001-Nov-15'})
JG 526         self.assertEqual(matcher('/99-June-10'), {'buz':'99-June-10'})
527         self.assertEqual(matcher('/2-Nov-15'), None)
528         self.assertEqual(matcher('/200-Nov-15'), None)
529         self.assertEqual(matcher('/2001-No-15'), None)
530         self.assertEqual(generator({'buz':'2001-Nov-15'}), '/2001-Nov-15')
531         self.assertEqual(generator({'buz':'99-June-10'}), '/99-June-10')
411d7f 532         self.assertEqual(args, ['buz'])
0482bd 533
17358d 534 class TestCompileRouteMatchFunctional(unittest.TestCase):
523132 535     def matches(self, pattern, path, expected):
b60bdb 536         from pyramid.urldispatch import _compile_route
523132 537         matcher = _compile_route(pattern)[0]
CM 538         result = matcher(path)
539         self.assertEqual(result, expected)
17358d 540
CM 541     def generates(self, pattern, dict, result):
b60bdb 542         from pyramid.urldispatch import _compile_route
17358d 543         self.assertEqual(_compile_route(pattern)[1](dict), result)
CM 544
545     def test_matcher_functional(self):
546         self.matches('/', '', None)
547         self.matches('', '', None)
548         self.matches('/', '/foo', None)
549         self.matches('/foo/', '/foo', None)
550         self.matches('/:x', '', None)
523132 551         self.matches('/:x', '/', None)
CM 552         self.matches('/abc/:def', '/abc/', None)
17358d 553         self.matches('', '/', {})
CM 554         self.matches('/', '/', {})
555         self.matches('/:x', '/a', {'x':'a'})
556         self.matches('zzz/:x', '/zzz/abc', {'x':'abc'})
25cbe1 557         self.matches('zzz/:x*traverse', '/zzz/abc', {'x':'abc', 'traverse':()})
CM 558         self.matches('zzz/:x*traverse', '/zzz/abc/def/g',
559                      {'x':'abc', 'traverse':('def', 'g')})
560         self.matches('*traverse', '/zzz/abc', {'traverse':('zzz', 'abc')})
561         self.matches('*traverse', '/zzz/%20abc', {'traverse':('zzz', ' abc')})
562         self.matches(':x', '/La%20Pe%C3%B1a', {'x':u'La Pe\xf1a'})
563         self.matches('*traverse', '/La%20Pe%C3%B1a/x',
564                      {'traverse':(u'La Pe\xf1a', 'x')})
67273e 565         self.matches('/foo/:id.html', '/foo/bar.html', {'id':'bar'})
da171d 566         self.matches('/{num:[0-9]+}/*traverse', '/555/abc/def',
MM 567                      {'num':'555', 'traverse':('abc', 'def')})
568         self.matches('/{num:[0-9]*}/*traverse', '/555/abc/def',
569                      {'num':'555', 'traverse':('abc', 'def')})
17358d 570         
CM 571     def test_generator_functional(self):
572         self.generates('', {}, '/')
573         self.generates('/', {}, '/')
574         self.generates('/:x', {'x':''}, '/')
575         self.generates('/:x', {'x':'a'}, '/a')
576         self.generates('zzz/:x', {'x':'abc'}, '/zzz/abc')
577         self.generates('zzz/:x*traverse', {'x':'abc', 'traverse':''},
578                        '/zzz/abc')
579         self.generates('zzz/:x*traverse', {'x':'abc', 'traverse':'/def/g'},
580                        '/zzz/abc/def/g')
581         self.generates('/:x', {'x':unicode('/La Pe\xc3\xb1a', 'utf-8')},
582                        '/%2FLa%20Pe%C3%B1a')
583         self.generates('/:x*y', {'x':unicode('/La Pe\xc3\xb1a', 'utf-8'),
584                                  'y':'/rest/of/path'},
585                        '/%2FLa%20Pe%C3%B1a/rest/of/path')
25cbe1 586         self.generates('*traverse', {'traverse':('a', u'La Pe\xf1a')},
CM 587                        '/a/La%20Pe%C3%B1a')
fb70d9 588         self.generates('/foo/:id.html', {'id':'bar'}, '/foo/bar.html')
05c023 589
d93893 590 class TestDefaultsPregenerator(unittest.TestCase):
MM 591     def _callFUT(self, pregen, *elements, **kw):
592         request = DummyRequest({})
593         return pregen(request, elements, kw)
594
595     def _makeOne(self, defaults, wrapped=None):
596         from pyramid.urldispatch import DefaultsPregenerator
597         return DefaultsPregenerator(defaults, wrapped)
598
599     def test_defaults(self):
600         pregen = self._makeOne({'foo':'bar'})
601         elements, kw = self._callFUT(pregen, baz='buz')
602         self.assertEqual(elements, ())
603         self.assertEqual(kw, {'foo':'bar', 'baz':'buz'})
604
605     def test_override_default(self):
606         pregen = self._makeOne({'foo':'bar'})
607         elements, kw = self._callFUT(pregen, foo='dummy', baz='buz')
608         self.assertEqual(elements, ())
609         self.assertEqual(kw, {'foo':'dummy', 'baz':'buz'})
610
611     def test_wrapper_defaults(self):
612         inner_kw = {}
613         def wrapper(request, elements, kw):
614             inner_kw.update(kw)
615             return ('foo',), {'baz':'buz'}
616         pregen = self._makeOne({'foo':'bar'}, wrapper)
617         elements, kw = self._callFUT(pregen)
618         self.assertEqual(elements, ('foo',))
619         self.assertEqual(inner_kw, {'foo':'bar'})
620         self.assertEqual(kw, {'baz':'buz'})
621
622     def test_wrapper_override_defaults(self):
623         inner_kw = {}
624         def wrapper(request, elements, kw):
625             inner_kw.update(kw)
626             return ('foo',), {'baz':'buz'}
627         pregen = self._makeOne({'foo':'bar'}, wrapper)
628         elements, kw = self._callFUT(pregen, foo='dummy')
629         self.assertEqual(elements, ('foo',))
630         self.assertEqual(inner_kw, {'foo':'dummy'})
631         self.assertEqual(kw, {'baz':'buz'})
632
e62e47 633 class DummyContext(object):
CM 634     """ """
8392d7 635         
e62e47 636 class DummyRequest(object):
11644e 637     def __init__(self, environ):
CM 638         self.environ = environ
e62e47 639     
05c023 640 class DummyRoute(object):
CM 641     def __init__(self, generator):
642         self.generate = generator
643