1"""test_utils""" 2import os, sys, time, unittest 3from nose.tools import eq_, assert_raises 4 5from routes.util import controller_scan, GenerationException 6from routes import * 7 8class TestUtils(unittest.TestCase): 9 def setUp(self): 10 m = Mapper(explicit=False) 11 m.minimization = True 12 m.connect('archive/:year/:month/:day', controller='blog', action='view', month=None, day=None, 13 requirements={'month':'\d{1,2}','day':'\d{1,2}'}) 14 m.connect('viewpost/:id', controller='post', action='view') 15 m.connect(':controller/:action/:id') 16 con = request_config() 17 con.mapper = m 18 con.host = 'www.test.com' 19 con.protocol = 'http' 20 if hasattr(con, 'environ'): 21 del con.environ 22 self.con = con 23 24 def test_url_for_with_nongen(self): 25 con = self.con 26 con.mapper_dict = {} 27 28 eq_('/blog', url_for('/blog')) 29 eq_('/blog?q=fred&q=here%20now', url_for('/blog', q=['fred', u'here now'])) 30 eq_('/blog#here', url_for('/blog', anchor='here')) 31 32 def test_url_for_with_nongen_no_encoding(self): 33 con = self.con 34 con.mapper_dict = {} 35 con.mapper.encoding = None 36 37 eq_('/blog', url_for('/blog')) 38 eq_('/blog#here', url_for('/blog', anchor='here')) 39 40 def test_url_for_with_unicode(self): 41 con = self.con 42 con.mapper_dict = {} 43 44 eq_('/blog', url_for(controller='blog')) 45 eq_('/blog/view/umulat', url_for(controller='blog', action='view', id=u'umulat')) 46 eq_('/blog/view/umulat?other=%CE%B1%CF%83%CE%B4%CE%B3', 47 url_for(controller='blog', action='view', id=u'umulat', other=u'\u03b1\u03c3\u03b4\u03b3')) 48 49 url = URLGenerator(con.mapper, {}) 50 for urlobj in [url_for, url]: 51 def raise_url(): 52 return urlobj(u'/some/st\xc3rng') 53 assert_raises(Exception, raise_url) 54 55 def test_url_for(self): 56 con = self.con 57 con.mapper_dict = {} 58 url = URLGenerator(con.mapper, {'HTTP_HOST':'www.test.com:80'}) 59 60 for urlobj in [url_for, url]: 61 eq_('/blog', urlobj(controller='blog')) 62 eq_('/content', urlobj()) 63 eq_('https://www.test.com/viewpost', urlobj(controller='post', action='view', protocol='https')) 64 eq_('http://www.test.org/content', urlobj(host='www.test.org')) 65 eq_('//www.test.com/viewpost', urlobj(controller='post', action='view', protocol='')) 66 eq_('//www.test.org/content', urlobj(host='www.test.org', protocol='')) 67 68 def test_url_raises(self): 69 con = self.con 70 con.mapper.explicit = True 71 con.mapper_dict = {} 72 url = URLGenerator(con.mapper, {}) 73 assert_raises(GenerationException, url_for, action='juice') 74 assert_raises(GenerationException, url, action='juice') 75 76 def test_url_for_with_defaults(self): 77 con = self.con 78 con.mapper_dict = {'controller':'blog','action':'view','id':4} 79 url = URLGenerator(con.mapper, {'wsgiorg.routing_args':((), con.mapper_dict)}) 80 81 eq_('/blog/view/4', url_for()) 82 eq_('/post/index/4', url_for(controller='post')) 83 eq_('/blog/view/2', url_for(id=2)) 84 eq_('/viewpost/4', url_for(controller='post', action='view', id=4)) 85 86 eq_('/blog/view/4', url.current()) 87 eq_('/post/index/4', url.current(controller='post')) 88 eq_('/blog/view/2', url.current(id=2)) 89 eq_('/viewpost/4', url.current(controller='post', action='view', id=4)) 90 91 con.mapper_dict = {'controller':'blog','action':'view','year':2004} 92 url = URLGenerator(con.mapper, {'wsgiorg.routing_args':((), con.mapper_dict)}) 93 94 eq_('/archive/2004/10', url_for(month=10)) 95 eq_('/archive/2004/9/2', url_for(month=9, day=2)) 96 eq_('/blog', url_for(controller='blog', year=None)) 97 98 eq_('/archive/2004/10', url.current(month=10)) 99 eq_('/archive/2004/9/2', url.current(month=9, day=2)) 100 eq_('/blog', url.current(controller='blog', year=None)) 101 102 def test_url_for_with_more_defaults(self): 103 con = self.con 104 con.mapper_dict = {'controller':'blog','action':'view','id':4} 105 url = URLGenerator(con.mapper, {'wsgiorg.routing_args':((), con.mapper_dict)}) 106 107 eq_('/blog/view/4', url_for()) 108 eq_('/post/index/4', url_for(controller='post')) 109 eq_('/blog/view/2', url_for(id=2)) 110 eq_('/viewpost/4', url_for(controller='post', action='view', id=4)) 111 112 eq_('/blog/view/4', url.current()) 113 eq_('/post/index/4', url.current(controller='post')) 114 eq_('/blog/view/2', url.current(id=2)) 115 eq_('/viewpost/4', url.current(controller='post', action='view', id=4)) 116 117 con.mapper_dict = {'controller':'blog','action':'view','year':2004} 118 url = URLGenerator(con.mapper, {'wsgiorg.routing_args':((), con.mapper_dict)}) 119 eq_('/archive/2004/10', url_for(month=10)) 120 eq_('/archive/2004/9/2', url_for(month=9, day=2)) 121 eq_('/blog', url_for(controller='blog', year=None)) 122 eq_('/archive/2004', url_for()) 123 124 eq_('/archive/2004/10', url.current(month=10)) 125 eq_('/archive/2004/9/2', url.current(month=9, day=2)) 126 eq_('/blog', url.current(controller='blog', year=None)) 127 eq_('/archive/2004', url.current()) 128 129 def test_url_for_with_defaults_and_qualified(self): 130 m = self.con.mapper 131 m.connect('home', '', controller='blog', action='splash') 132 m.connect('category_home', 'category/:section', controller='blog', action='view', section='home') 133 m.connect(':controller/:action/:id') 134 m.create_regs(['content','blog','admin/comments']) 135 self.con.environ = dict(SCRIPT_NAME='', HTTP_HOST='www.example.com', PATH_INFO='/blog/view/4') 136 self.con.environ.update({'wsgiorg.routing_args':((), self.con.mapper_dict)}) 137 url = URLGenerator(m, self.con.environ) 138 139 eq_('/blog/view/4', url_for()) 140 eq_('/post/index/4', url_for(controller='post')) 141 eq_('http://www.example.com/blog/view/4', url_for(qualified=True)) 142 eq_('/blog/view/2', url_for(id=2)) 143 eq_('/viewpost/4', url_for(controller='post', action='view', id=4)) 144 145 eq_('/blog/view/4', url.current()) 146 eq_('/post/index/4', url.current(controller='post')) 147 eq_('http://www.example.com/blog/view/4', url.current(qualified=True)) 148 eq_('/blog/view/2', url.current(id=2)) 149 eq_('/viewpost/4', url.current(controller='post', action='view', id=4)) 150 151 env = dict(SCRIPT_NAME='', SERVER_NAME='www.example.com', SERVER_PORT='8080', PATH_INFO='/blog/view/4') 152 env['wsgi.url_scheme'] = 'http' 153 self.con.environ = env 154 self.con.environ.update({'wsgiorg.routing_args':((), self.con.mapper_dict)}) 155 url = URLGenerator(m, self.con.environ) 156 157 eq_('/post/index/4', url_for(controller='post')) 158 eq_('http://www.example.com:8080/blog/view/4', url_for(qualified=True)) 159 160 eq_('/post/index/4', url.current(controller='post')) 161 eq_('http://www.example.com:8080/blog/view/4', url.current(qualified=True)) 162 163 def test_route_overflow(self): 164 m = self.con.mapper 165 m.create_regs(["x"*50000]) 166 m.connect('route-overflow', "x"*50000) 167 url = URLGenerator(m, {}) 168 eq_("/%s" % ("x"*50000), url('route-overflow')) 169 170 def test_with_route_names(self): 171 m = self.con.mapper 172 self.con.mapper_dict = {} 173 m.connect('home', '', controller='blog', action='splash') 174 m.connect('category_home', 'category/:section', controller='blog', action='view', section='home') 175 m.create_regs(['content','blog','admin/comments']) 176 url = URLGenerator(m, {}) 177 178 for urlobj in [url, url_for]: 179 eq_('/content/view', urlobj(controller='content', action='view')) 180 eq_('/content', urlobj(controller='content')) 181 eq_('/admin/comments', urlobj(controller='admin/comments')) 182 eq_('/category', urlobj('category_home')) 183 eq_('/category/food', urlobj('category_home', section='food')) 184 eq_('/', urlobj('home')) 185 186 def test_with_route_names_and_defaults(self): 187 m = self.con.mapper 188 self.con.mapper_dict = {} 189 m.connect('home', '', controller='blog', action='splash') 190 m.connect('category_home', 'category/:section', controller='blog', action='view', section='home') 191 m.connect('building', 'building/:campus/:building/alljacks', controller='building', action='showjacks') 192 m.create_regs(['content','blog','admin/comments','building']) 193 194 self.con.mapper_dict = dict(controller='building', action='showjacks', campus='wilma', building='port') 195 url = URLGenerator(m, {'wsgiorg.routing_args':((), self.con.mapper_dict)}) 196 197 eq_('/building/wilma/port/alljacks', url_for()) 198 eq_('/', url_for('home')) 199 eq_('/building/wilma/port/alljacks', url.current()) 200 eq_('/', url.current('home')) 201 202 def test_with_route_names_and_hardcode(self): 203 m = self.con.mapper 204 self.con.mapper_dict = {} 205 m.hardcode_names = False 206 207 m.connect('home', '', controller='blog', action='splash') 208 m.connect('category_home', 'category/:section', controller='blog', action='view', section='home') 209 m.connect('building', 'building/:campus/:building/alljacks', controller='building', action='showjacks') 210 m.connect('gallery_thumb', 'gallery/:(img_id)_thumbnail.jpg') 211 m.connect('gallery', 'gallery/:(img_id).jpg') 212 m.create_regs(['content','blog','admin/comments','building']) 213 214 self.con.mapper_dict = dict(controller='building', action='showjacks', campus='wilma', building='port') 215 url = URLGenerator(m, {'wsgiorg.routing_args':((), self.con.mapper_dict)}) 216 eq_('/building/wilma/port/alljacks', url_for()) 217 eq_('/', url_for('home')) 218 eq_('/gallery/home_thumbnail.jpg', url_for('gallery_thumb', img_id='home')) 219 eq_('/gallery/home_thumbnail.jpg', url_for('gallery', img_id='home')) 220 221 eq_('/building/wilma/port/alljacks', url.current()) 222 eq_('/', url.current('home')) 223 eq_('/gallery/home_thumbnail.jpg', url.current('gallery_thumb', img_id='home')) 224 eq_('/gallery/home_thumbnail.jpg', url.current('gallery', img_id='home')) 225 226 m.hardcode_names = True 227 eq_('/gallery/home_thumbnail.jpg', url_for('gallery_thumb', img_id='home')) 228 eq_('/gallery/home.jpg', url_for('gallery', img_id='home')) 229 230 eq_('/gallery/home_thumbnail.jpg', url.current('gallery_thumb', img_id='home')) 231 eq_('/gallery/home.jpg', url.current('gallery', img_id='home')) 232 m.hardcode_names = False 233 234 def test_redirect_to(self): 235 m = self.con.mapper 236 self.con.mapper_dict = {} 237 self.con.environ = dict(SCRIPT_NAME='', HTTP_HOST='www.example.com') 238 result = None 239 def printer(echo): 240 redirect_to.result = echo 241 self.con.redirect = printer 242 m.create_regs(['content','blog','admin/comments']) 243 244 redirect_to(controller='content', action='view') 245 eq_('/content/view', redirect_to.result) 246 redirect_to(controller='content', action='lookup', id=4) 247 eq_('/content/lookup/4', redirect_to.result) 248 redirect_to(controller='admin/comments',action='splash') 249 eq_('/admin/comments/splash', redirect_to.result) 250 redirect_to('http://www.example.com/') 251 eq_('http://www.example.com/', redirect_to.result) 252 redirect_to('/somewhere.html', var='keyword') 253 eq_('/somewhere.html?var=keyword', redirect_to.result) 254 255 def test_redirect_to_with_route_names(self): 256 m = self.con.mapper 257 self.con.mapper_dict = {} 258 result = None 259 def printer(echo): 260 redirect_to.result = echo 261 self.con.redirect = printer 262 m.connect('home', '', controller='blog', action='splash') 263 m.connect('category_home', 'category/:section', controller='blog', action='view', section='home') 264 m.create_regs(['content','blog','admin/comments']) 265 266 redirect_to(controller='content', action='view') 267 eq_('/content/view', redirect_to.result) 268 redirect_to(controller='content') 269 eq_('/content', redirect_to.result) 270 redirect_to(controller='admin/comments') 271 eq_('/admin/comments', redirect_to.result) 272 redirect_to('category_home') 273 eq_('/category', redirect_to.result) 274 redirect_to('category_home', section='food') 275 eq_('/category/food', redirect_to.result) 276 redirect_to('home') 277 eq_('/', redirect_to.result) 278 279 def test_static_route(self): 280 m = self.con.mapper 281 self.con.mapper_dict = {} 282 self.con.environ = dict(SCRIPT_NAME='', HTTP_HOST='example.com') 283 m.connect(':controller/:action/:id') 284 m.connect('home', 'http://www.groovie.org/', _static=True) 285 m.connect('space', '/nasa/images', _static=True) 286 m.create_regs(['content', 'blog']) 287 288 url = URLGenerator(m, {}) 289 for urlobj in [url_for, url]: 290 eq_('http://www.groovie.org/', urlobj('home')) 291 eq_('http://www.groovie.org/?s=stars', urlobj('home', s='stars')) 292 eq_('/content/view', urlobj(controller='content', action='view')) 293 eq_('/nasa/images?search=all', urlobj('space', search='all')) 294 295 def test_static_route_with_script(self): 296 m = self.con.mapper 297 self.con.mapper_dict = {} 298 self.con.environ = dict(SCRIPT_NAME='/webapp', HTTP_HOST='example.com') 299 m.connect(':controller/:action/:id') 300 m.connect('home', 'http://www.groovie.org/', _static=True) 301 m.connect('space', '/nasa/images', _static=True) 302 m.connect('login', '/login', action='nowhereville') 303 m.create_regs(['content', 'blog']) 304 305 self.con.environ.update({'wsgiorg.routing_args':((), {})}) 306 url = URLGenerator(m, self.con.environ) 307 for urlobj in [url_for, url]: 308 eq_('http://www.groovie.org/', urlobj('home')) 309 eq_('http://www.groovie.org/?s=stars', urlobj('home', s='stars')) 310 eq_('/webapp/content/view', urlobj(controller='content', action='view')) 311 eq_('/webapp/nasa/images?search=all', urlobj('space', search='all')) 312 eq_('http://example.com/webapp/nasa/images', urlobj('space', protocol='http')) 313 eq_('http://example.com/webapp/login', urlobj('login', qualified=True)) 314 315 def test_static_route_with_vars(self): 316 m = self.con.mapper 317 self.con.mapper_dict = {} 318 self.con.environ = dict(SCRIPT_NAME='/webapp', HTTP_HOST='example.com') 319 m.connect('home', 'http://{domain}.groovie.org/{location}', _static=True) 320 m.connect('space', '/nasa/{location}', _static=True) 321 m.create_regs(['home', 'space']) 322 323 self.con.environ.update({'wsgiorg.routing_args':((), {})}) 324 url = URLGenerator(m, self.con.environ) 325 for urlobj in [url_for, url]: 326 assert_raises(GenerationException, urlobj, 'home') 327 assert_raises(GenerationException, urlobj, 'home', domain='fred') 328 assert_raises(GenerationException, urlobj, 'home', location='index') 329 eq_('http://fred.groovie.org/index', urlobj('home', domain='fred', location='index')) 330 eq_('http://fred.groovie.org/index?search=all', urlobj('home', domain='fred', location='index', search='all')) 331 eq_('/webapp/nasa/images?search=all', urlobj('space', location='images', search='all')) 332 eq_('http://example.com/webapp/nasa/images', urlobj('space', location='images', protocol='http')) 333 334 def test_static_route_with_vars_and_defaults(self): 335 m = self.con.mapper 336 self.con.mapper_dict = {} 337 self.con.environ = dict(SCRIPT_NAME='/webapp', HTTP_HOST='example.com') 338 m.connect('home', 'http://{domain}.groovie.org/{location}', domain='routes', _static=True) 339 m.connect('space', '/nasa/{location}', location='images', _static=True) 340 m.create_regs(['home', 'space']) 341 342 self.con.environ.update({'wsgiorg.routing_args':((), {})}) 343 url = URLGenerator(m, self.con.environ) 344 345 assert_raises(GenerationException, url_for, 'home') 346 assert_raises(GenerationException, url_for, 'home', domain='fred') 347 eq_('http://routes.groovie.org/index', url_for('home', location='index')) 348 eq_('http://fred.groovie.org/index', url_for('home', domain='fred', location='index')) 349 eq_('http://routes.groovie.org/index?search=all', url_for('home', location='index', search='all')) 350 eq_('http://fred.groovie.org/index?search=all', url_for('home', domain='fred', location='index', search='all')) 351 eq_('/webapp/nasa/articles?search=all', url_for('space', location='articles', search='all')) 352 eq_('http://example.com/webapp/nasa/articles', url_for('space', location='articles', protocol='http')) 353 eq_('/webapp/nasa/images?search=all', url_for('space', search='all')) 354 eq_('http://example.com/webapp/nasa/images', url_for('space', protocol='http')) 355 356 assert_raises(GenerationException, url.current, 'home') 357 assert_raises(GenerationException, url.current, 'home', domain='fred') 358 eq_('http://routes.groovie.org/index', url.current('home', location='index')) 359 eq_('http://fred.groovie.org/index', url.current('home', domain='fred', location='index')) 360 eq_('http://routes.groovie.org/index?search=all', url.current('home', location='index', search='all')) 361 eq_('http://fred.groovie.org/index?search=all', url.current('home', domain='fred', location='index', search='all')) 362 eq_('/webapp/nasa/articles?search=all', url.current('space', location='articles', search='all')) 363 eq_('http://example.com/webapp/nasa/articles', url.current('space', location='articles', protocol='http')) 364 eq_('/webapp/nasa/images?search=all', url.current('space', search='all')) 365 eq_('http://example.com/webapp/nasa/images', url.current('space', protocol='http')) 366 367 368 def test_static_route_with_vars_and_requirements(self): 369 m = self.con.mapper 370 self.con.mapper_dict = {} 371 self.con.environ = dict(SCRIPT_NAME='/webapp', HTTP_HOST='example.com') 372 m.connect('home', 'http://{domain}.groovie.org/{location}', requirements=dict(domain='fred|bob'), _static=True) 373 m.connect('space', '/nasa/articles/{year}/{month}', requirements=dict(year=r'\d{2,4}', month=r'\d{1,2}'), _static=True) 374 m.create_regs(['home', 'space']) 375 376 377 self.con.environ.update({'wsgiorg.routing_args':((), {})}) 378 url = URLGenerator(m, self.con.environ) 379 380 assert_raises(GenerationException, url_for, 'home', domain='george', location='index') 381 assert_raises(GenerationException, url_for, 'space', year='asdf', month='1') 382 assert_raises(GenerationException, url_for, 'space', year='2004', month='a') 383 assert_raises(GenerationException, url_for, 'space', year='1', month='1') 384 assert_raises(GenerationException, url_for, 'space', year='20045', month='1') 385 assert_raises(GenerationException, url_for, 'space', year='2004', month='123') 386 eq_('http://fred.groovie.org/index', url_for('home', domain='fred', location='index')) 387 eq_('http://bob.groovie.org/index', url_for('home', domain='bob', location='index')) 388 eq_('http://fred.groovie.org/asdf', url_for('home', domain='fred', location='asdf')) 389 eq_('/webapp/nasa/articles/2004/6', url_for('space', year='2004', month='6')) 390 eq_('/webapp/nasa/articles/2004/12', url_for('space', year='2004', month='12')) 391 eq_('/webapp/nasa/articles/89/6', url_for('space', year='89', month='6')) 392 393 assert_raises(GenerationException, url.current, 'home', domain='george', location='index') 394 assert_raises(GenerationException, url.current, 'space', year='asdf', month='1') 395 assert_raises(GenerationException, url.current, 'space', year='2004', month='a') 396 assert_raises(GenerationException, url.current, 'space', year='1', month='1') 397 assert_raises(GenerationException, url.current, 'space', year='20045', month='1') 398 assert_raises(GenerationException, url.current, 'space', year='2004', month='123') 399 eq_('http://fred.groovie.org/index', url.current('home', domain='fred', location='index')) 400 eq_('http://bob.groovie.org/index', url.current('home', domain='bob', location='index')) 401 eq_('http://fred.groovie.org/asdf', url.current('home', domain='fred', location='asdf')) 402 eq_('/webapp/nasa/articles/2004/6', url.current('space', year='2004', month='6')) 403 eq_('/webapp/nasa/articles/2004/12', url.current('space', year='2004', month='12')) 404 eq_('/webapp/nasa/articles/89/6', url.current('space', year='89', month='6')) 405 406 def test_no_named_path(self): 407 m = self.con.mapper 408 self.con.mapper_dict = {} 409 self.con.environ = dict(SCRIPT_NAME='', HTTP_HOST='example.com') 410 m.connect(':controller/:action/:id') 411 m.connect('home', 'http://www.groovie.org/', _static=True) 412 m.connect('space', '/nasa/images', _static=True) 413 m.create_regs(['content', 'blog']) 414 415 url = URLGenerator(m, {}) 416 for urlobj in [url_for, url]: 417 eq_('http://www.google.com/search', urlobj('http://www.google.com/search')) 418 eq_('http://www.google.com/search?q=routes', urlobj('http://www.google.com/search', q='routes')) 419 eq_('/delicious.jpg', urlobj('/delicious.jpg')) 420 eq_('/delicious/search?v=routes', urlobj('/delicious/search', v='routes')) 421 422 def test_append_slash(self): 423 m = self.con.mapper 424 self.con.mapper_dict = {} 425 m.append_slash = True 426 self.con.environ = dict(SCRIPT_NAME='', HTTP_HOST='example.com') 427 m.connect(':controller/:action/:id') 428 m.connect('home', 'http://www.groovie.org/', _static=True) 429 m.connect('space', '/nasa/images', _static=True) 430 m.create_regs(['content', 'blog']) 431 432 url = URLGenerator(m, {}) 433 for urlobj in [url_for, url]: 434 eq_('http://www.google.com/search', urlobj('http://www.google.com/search')) 435 eq_('http://www.google.com/search?q=routes', urlobj('http://www.google.com/search', q='routes')) 436 eq_('/delicious.jpg', urlobj('/delicious.jpg')) 437 eq_('/delicious/search?v=routes', urlobj('/delicious/search', v='routes')) 438 eq_('/content/list/', urlobj(controller='/content', action='list')) 439 eq_('/content/list/?page=1', urlobj(controller='/content', action='list', page='1')) 440 441 def test_no_named_path_with_script(self): 442 m = self.con.mapper 443 self.con.mapper_dict = {} 444 self.con.environ = dict(SCRIPT_NAME='/webapp', HTTP_HOST='example.com') 445 m.connect(':controller/:action/:id') 446 m.connect('home', 'http://www.groovie.org/', _static=True) 447 m.connect('space', '/nasa/images', _static=True) 448 m.create_regs(['content', 'blog']) 449 450 url = URLGenerator(m, self.con.environ) 451 for urlobj in [url_for, url]: 452 eq_('http://www.google.com/search', urlobj('http://www.google.com/search')) 453 eq_('http://www.google.com/search?q=routes', urlobj('http://www.google.com/search', q='routes')) 454 eq_('/webapp/delicious.jpg', urlobj('/delicious.jpg')) 455 eq_('/webapp/delicious/search?v=routes', urlobj('/delicious/search', v='routes')) 456 457 def test_route_filter(self): 458 def article_filter(kargs): 459 article = kargs.pop('article', None) 460 if article is not None: 461 kargs.update( 462 dict(year=article.get('year', 2004), 463 month=article.get('month', 12), 464 day=article.get('day', 20), 465 slug=article.get('slug', 'default') 466 ) 467 ) 468 return kargs 469 470 self.con.mapper_dict = {} 471 self.con.environ = dict(SCRIPT_NAME='', HTTP_HOST='example.com') 472 473 m = Mapper(explicit=False) 474 m.minimization = True 475 m.connect(':controller/:(action)-:(id).html') 476 m.connect('archives', 'archives/:year/:month/:day/:slug', controller='archives', action='view', 477 _filter=article_filter) 478 m.create_regs(['content','archives','admin/comments']) 479 self.con.mapper = m 480 481 url = URLGenerator(m, self.con.environ) 482 for urlobj in [url_for, url]: 483 assert_raises(Exception, urlobj, controller='content', action='view') 484 assert_raises(Exception, urlobj, controller='content') 485 486 eq_('/content/view-3.html', urlobj(controller='content', action='view', id=3)) 487 eq_('/content/index-2.html', urlobj(controller='content', id=2)) 488 489 eq_('/archives/2005/10/5/happy', 490 urlobj('archives',year=2005, month=10, day=5, slug='happy')) 491 story = dict(year=2003, month=8, day=2, slug='woopee') 492 empty = {} 493 eq_({'controller':'archives','action':'view','year':'2005', 494 'month':'10','day':'5','slug':'happy'}, m.match('/archives/2005/10/5/happy')) 495 eq_('/archives/2003/8/2/woopee', urlobj('archives', article=story)) 496 eq_('/archives/2004/12/20/default', urlobj('archives', article=empty)) 497 498 def test_with_ssl_environ(self): 499 base_environ = dict(SCRIPT_NAME='', HTTPS='on', SERVER_PORT='443', PATH_INFO='/', 500 HTTP_HOST='example.com', SERVER_NAME='example.com') 501 self.con.mapper_dict = {} 502 self.con.environ = base_environ.copy() 503 504 m = Mapper(explicit=False) 505 m.minimization = True 506 m.connect(':controller/:action/:id') 507 m.create_regs(['content','archives','admin/comments']) 508 m.sub_domains = True 509 self.con.mapper = m 510 511 url = URLGenerator(m, self.con.environ) 512 for urlobj in [url_for, url]: 513 514 # HTTPS is on, but we're running on a different port internally 515 eq_(self.con.protocol, 'https') 516 eq_('/content/view', urlobj(controller='content', action='view')) 517 eq_('/content/index/2', urlobj(controller='content', id=2)) 518 eq_('https://nowhere.com/content', urlobj(host='nowhere.com', controller='content')) 519 520 # If HTTPS is on, but the port isn't 443, we'll need to include the port info 521 environ = base_environ.copy() 522 environ.update(dict(SERVER_PORT='8080')) 523 self.con.environ = environ 524 self.con.mapper_dict = {} 525 eq_('/content/index/2', urlobj(controller='content', id=2)) 526 eq_('https://nowhere.com/content', urlobj(host='nowhere.com', controller='content')) 527 eq_('https://nowhere.com:8080/content', urlobj(host='nowhere.com:8080', controller='content')) 528 eq_('http://nowhere.com/content', urlobj(host='nowhere.com', protocol='http', controller='content')) 529 eq_('http://home.com/content', urlobj(host='home.com', protocol='http', controller='content')) 530 531 532 def test_with_http_environ(self): 533 base_environ = dict(SCRIPT_NAME='', SERVER_PORT='1080', PATH_INFO='/', 534 HTTP_HOST='example.com', SERVER_NAME='example.com') 535 base_environ['wsgi.url_scheme'] = 'http' 536 self.con.environ = base_environ.copy() 537 self.con.mapper_dict = {} 538 539 m = Mapper(explicit=False) 540 m.minimization = True 541 m.connect(':controller/:action/:id') 542 m.create_regs(['content','archives','admin/comments']) 543 self.con.mapper = m 544 545 url = URLGenerator(m, self.con.environ) 546 for urlobj in [url_for, url]: 547 eq_(self.con.protocol, 'http') 548 eq_('/content/view', urlobj(controller='content', action='view')) 549 eq_('/content/index/2', urlobj(controller='content', id=2)) 550 eq_('https://example.com/content', urlobj(protocol='https', controller='content')) 551 552 553 def test_subdomains(self): 554 base_environ = dict(SCRIPT_NAME='', PATH_INFO='/', HTTP_HOST='example.com', SERVER_NAME='example.com') 555 self.con.mapper_dict = {} 556 self.con.environ = base_environ.copy() 557 558 m = Mapper(explicit=False) 559 m.minimization = True 560 m.sub_domains = True 561 m.connect(':controller/:action/:id') 562 m.create_regs(['content','archives','admin/comments']) 563 self.con.mapper = m 564 565 url = URLGenerator(m, self.con.environ) 566 for urlobj in [url_for, url]: 567 eq_('/content/view', urlobj(controller='content', action='view')) 568 eq_('/content/index/2', urlobj(controller='content', id=2)) 569 environ = base_environ.copy() 570 environ.update(dict(HTTP_HOST='sub.example.com')) 571 self.con.environ = environ 572 self.con.mapper_dict = {'sub_domain':'sub'} 573 eq_('/content/view/3', urlobj(controller='content', action='view', id=3)) 574 eq_('http://new.example.com/content', urlobj(controller='content', sub_domain='new')) 575 576 def test_subdomains_with_exceptions(self): 577 base_environ = dict(SCRIPT_NAME='', PATH_INFO='/', HTTP_HOST='example.com', SERVER_NAME='example.com') 578 self.con.mapper_dict = {} 579 self.con.environ = base_environ.copy() 580 581 m = Mapper(explicit=False) 582 m.minimization = True 583 m.sub_domains = True 584 m.sub_domains_ignore = ['www'] 585 m.connect(':controller/:action/:id') 586 m.create_regs(['content','archives','admin/comments']) 587 self.con.mapper = m 588 589 url = URLGenerator(m, self.con.environ) 590 eq_('/content/view', url_for(controller='content', action='view')) 591 eq_('/content/index/2', url_for(controller='content', id=2)) 592 eq_('/content/view', url(controller='content', action='view')) 593 eq_('/content/index/2', url(controller='content', id=2)) 594 595 environ = base_environ.copy() 596 environ.update(dict(HTTP_HOST='sub.example.com')) 597 self.con.environ = environ 598 self.con.mapper_dict = {'sub_domain':'sub'} 599 self.con.environ.update({'wsgiorg.routing_args':((), self.con.mapper_dict)}) 600 url = URLGenerator(m, self.con.environ) 601 602 eq_('/content/view/3', url_for(controller='content', action='view', id=3)) 603 eq_('http://new.example.com/content', url_for(controller='content', sub_domain='new')) 604 eq_('http://example.com/content', url_for(controller='content', sub_domain='www')) 605 eq_('/content/view/3', url(controller='content', action='view', id=3)) 606 eq_('http://new.example.com/content', url(controller='content', sub_domain='new')) 607 eq_('http://example.com/content', url(controller='content', sub_domain='www')) 608 609 self.con.mapper_dict = {'sub_domain':'www'} 610 self.con.environ.update({'wsgiorg.routing_args':((), self.con.mapper_dict)}) 611 url = URLGenerator(m, self.con.environ) 612 613 eq_('http://example.com/content/view/3', url_for(controller='content', action='view', id=3)) 614 eq_('http://new.example.com/content', url_for(controller='content', sub_domain='new')) 615 eq_('/content', url_for(controller='content', sub_domain='sub')) 616 617 # This requires the sub-domain, because we don't automatically go to the existing match dict 618 eq_('http://example.com/content/view/3', url(controller='content', action='view', id=3, sub_domain='www')) 619 eq_('http://new.example.com/content', url(controller='content', sub_domain='new')) 620 eq_('/content', url(controller='content', sub_domain='sub')) 621 622 def test_subdomains_with_named_routes(self): 623 base_environ = dict(SCRIPT_NAME='', PATH_INFO='/', HTTP_HOST='example.com', SERVER_NAME='example.com') 624 self.con.mapper_dict = {} 625 self.con.environ = base_environ.copy() 626 627 m = Mapper(explicit=False) 628 m.minimization = True 629 m.sub_domains = True 630 m.connect(':controller/:action/:id') 631 m.connect('category_home', 'category/:section', controller='blog', action='view', section='home') 632 m.connect('building', 'building/:campus/:building/alljacks', controller='building', action='showjacks') 633 m.create_regs(['content','blog','admin/comments','building']) 634 self.con.mapper = m 635 636 url = URLGenerator(m, self.con.environ) 637 for urlobj in [url_for, url]: 638 eq_('/content/view', urlobj(controller='content', action='view')) 639 eq_('/content/index/2', urlobj(controller='content', id=2)) 640 eq_('/category', urlobj('category_home')) 641 eq_('http://new.example.com/category', urlobj('category_home', sub_domain='new')) 642 643 environ = base_environ.copy() 644 environ.update(dict(HTTP_HOST='sub.example.com')) 645 self.con.environ = environ 646 self.con.mapper_dict = {'sub_domain':'sub'} 647 self.con.environ.update({'wsgiorg.routing_args':((), self.con.mapper_dict)}) 648 url = URLGenerator(m, self.con.environ) 649 650 eq_('/content/view/3', url_for(controller='content', action='view', id=3)) 651 eq_('http://joy.example.com/building/west/merlot/alljacks', 652 url_for('building', campus='west', building='merlot', sub_domain='joy')) 653 eq_('http://example.com/category/feeds', url_for('category_home', section='feeds', sub_domain=None)) 654 655 eq_('/content/view/3', url(controller='content', action='view', id=3)) 656 eq_('http://joy.example.com/building/west/merlot/alljacks', 657 url('building', campus='west', building='merlot', sub_domain='joy')) 658 eq_('http://example.com/category/feeds', url('category_home', section='feeds', sub_domain=None)) 659 660 661 def test_subdomains_with_ports(self): 662 base_environ = dict(SCRIPT_NAME='', PATH_INFO='/', HTTP_HOST='example.com:8000', SERVER_NAME='example.com') 663 self.con.mapper_dict = {} 664 self.con.environ = base_environ.copy() 665 666 m = Mapper(explicit=False) 667 m.minimization = True 668 m.sub_domains = True 669 m.connect(':controller/:action/:id') 670 m.connect('category_home', 'category/:section', controller='blog', action='view', section='home') 671 m.connect('building', 'building/:campus/:building/alljacks', controller='building', action='showjacks') 672 m.create_regs(['content','blog','admin/comments','building']) 673 self.con.mapper = m 674 675 url = URLGenerator(m, self.con.environ) 676 for urlobj in [url, url_for]: 677 self.con.environ['HTTP_HOST'] = 'example.com:8000' 678 eq_('/content/view', urlobj(controller='content', action='view')) 679 eq_('/category', urlobj('category_home')) 680 eq_('http://new.example.com:8000/category', urlobj('category_home', sub_domain='new')) 681 eq_('http://joy.example.com:8000/building/west/merlot/alljacks', 682 urlobj('building', campus='west', building='merlot', sub_domain='joy')) 683 684 self.con.environ['HTTP_HOST'] = 'example.com' 685 del self.con.environ['routes.cached_hostinfo'] 686 eq_('http://new.example.com/category', urlobj('category_home', sub_domain='new')) 687 688 def test_subdomains_with_default(self): 689 base_environ = dict(SCRIPT_NAME='', PATH_INFO='/', HTTP_HOST='example.com:8000', SERVER_NAME='example.com') 690 self.con.mapper_dict = {} 691 self.con.environ = base_environ.copy() 692 693 m = Mapper(explicit=False) 694 m.minimization = True 695 m.sub_domains = True 696 m.connect(':controller/:action/:id') 697 m.connect('category_home', 'category/:section', controller='blog', action='view', section='home', 698 sub_domain='cat', conditions=dict(sub_domain=['cat'])) 699 m.connect('building', 'building/:campus/:building/alljacks', controller='building', action='showjacks') 700 m.create_regs(['content','blog','admin/comments','building']) 701 self.con.mapper = m 702 703 urlobj = URLGenerator(m, self.con.environ) 704 self.con.environ['HTTP_HOST'] = 'example.com:8000' 705 eq_('/content/view', urlobj(controller='content', action='view')) 706 eq_('http://cat.example.com:8000/category', urlobj('category_home')) 707 708 self.con.environ['HTTP_HOST'] = 'example.com' 709 del self.con.environ['routes.cached_hostinfo'] 710 711 assert_raises(GenerationException, lambda: urlobj('category_home', sub_domain='new')) 712 713 714 def test_controller_scan(self): 715 here_dir = os.path.dirname(__file__) 716 controller_dir = os.path.join(os.path.dirname(here_dir), 717 os.path.join('test_files', 'controller_files')) 718 controllers = controller_scan(controller_dir) 719 eq_(len(controllers), 3) 720 eq_(controllers[0], 'admin/users') 721 eq_(controllers[1], 'content') 722 eq_(controllers[2], 'users') 723 724 def test_auto_controller_scan(self): 725 here_dir = os.path.dirname(__file__) 726 controller_dir = os.path.join(os.path.dirname(here_dir), 727 os.path.join('test_files', 'controller_files')) 728 m = Mapper(directory=controller_dir, explicit=False) 729 m.minimization = True 730 m.always_scan = True 731 m.connect(':controller/:action/:id') 732 733 eq_({'action':'index', 'controller':'content','id':None}, m.match('/content')) 734 eq_({'action':'index', 'controller':'users','id':None}, m.match('/users')) 735 eq_({'action':'index', 'controller':'admin/users','id':None}, m.match('/admin/users')) 736 737class TestUtilsWithExplicit(unittest.TestCase): 738 def setUp(self): 739 m = Mapper(explicit=True) 740 m.minimization = True 741 m.connect('archive/:year/:month/:day', controller='blog', action='view', month=None, day=None, 742 requirements={'month':'\d{1,2}','day':'\d{1,2}'}) 743 m.connect('viewpost/:id', controller='post', action='view', id=None) 744 m.connect(':controller/:action/:id') 745 con = request_config() 746 con.mapper = m 747 con.host = 'www.test.com' 748 con.protocol = 'http' 749 self.con = con 750 751 def test_url_for(self): 752 con = self.con 753 con.mapper_dict = {} 754 755 assert_raises(Exception, url_for, controller='blog') 756 assert_raises(Exception, url_for) 757 eq_('/blog/view/3', url_for(controller='blog', action='view', id=3)) 758 eq_('https://www.test.com/viewpost', url_for(controller='post', action='view', protocol='https')) 759 eq_('http://www.test.org/content/view/2', url_for(host='www.test.org', controller='content', action='view', id=2)) 760 761 def test_url_for_with_defaults(self): 762 con = self.con 763 con.mapper_dict = {'controller':'blog','action':'view','id':4} 764 765 assert_raises(Exception, url_for) 766 assert_raises(Exception, url_for, controller='post') 767 assert_raises(Exception, url_for, id=2) 768 eq_('/viewpost/4', url_for(controller='post', action='view', id=4)) 769 770 con.mapper_dict = {'controller':'blog','action':'view','year':2004} 771 assert_raises(Exception, url_for, month=10) 772 assert_raises(Exception, url_for, month=9, day=2) 773 assert_raises(Exception, url_for, controller='blog', year=None) 774 775 def test_url_for_with_more_defaults(self): 776 con = self.con 777 con.mapper_dict = {'controller':'blog','action':'view','id':4} 778 779 assert_raises(Exception, url_for) 780 assert_raises(Exception, url_for, controller='post') 781 assert_raises(Exception, url_for, id=2) 782 eq_('/viewpost/4', url_for(controller='post', action='view', id=4)) 783 784 con.mapper_dict = {'controller':'blog','action':'view','year':2004} 785 assert_raises(Exception, url_for, month=10) 786 assert_raises(Exception, url_for) 787 788 def test_url_for_with_defaults_and_qualified(self): 789 m = self.con.mapper 790 m.connect('home', '', controller='blog', action='splash') 791 m.connect('category_home', 'category/:section', controller='blog', action='view', section='home') 792 m.connect(':controller/:action/:id') 793 m.create_regs(['content','blog','admin/comments']) 794 env = dict(SCRIPT_NAME='', SERVER_NAME='www.example.com', SERVER_PORT='80', PATH_INFO='/blog/view/4') 795 env['wsgi.url_scheme'] = 'http' 796 797 self.con.environ = env 798 799 assert_raises(Exception, url_for) 800 assert_raises(Exception, url_for, controller='post') 801 assert_raises(Exception, url_for, id=2) 802 assert_raises(Exception, url_for, qualified=True, controller='blog', id=4) 803 eq_('http://www.example.com/blog/view/4', url_for(qualified=True, controller='blog', action='view', id=4)) 804 eq_('/viewpost/4', url_for(controller='post', action='view', id=4)) 805 806 env = dict(SCRIPT_NAME='', SERVER_NAME='www.example.com', SERVER_PORT='8080', PATH_INFO='/blog/view/4') 807 env['wsgi.url_scheme'] = 'http' 808 self.con.environ = env 809 assert_raises(Exception, url_for, controller='post') 810 eq_('http://www.example.com:8080/blog/view/4', url_for(qualified=True, controller='blog', action='view', id=4)) 811 812 813 def test_with_route_names(self): 814 m = self.con.mapper 815 m.minimization = True 816 self.con.mapper_dict = {} 817 m.connect('home', '', controller='blog', action='splash') 818 m.connect('category_home', 'category/:section', controller='blog', action='view', section='home') 819 m.create_regs(['content','blog','admin/comments']) 820 821 assert_raises(Exception, url_for, controller='content', action='view') 822 assert_raises(Exception, url_for, controller='content') 823 assert_raises(Exception, url_for, controller='admin/comments') 824 eq_('/category', url_for('category_home')) 825 eq_('/category/food', url_for('category_home', section='food')) 826 assert_raises(Exception, url_for, 'home', controller='content') 827 eq_('/', url_for('home')) 828 829 def test_with_route_names_and_nomin(self): 830 m = self.con.mapper 831 m.minimization = False 832 self.con.mapper_dict = {} 833 m.connect('home', '', controller='blog', action='splash') 834 m.connect('category_home', 'category/:section', controller='blog', action='view', section='home') 835 m.create_regs(['content','blog','admin/comments']) 836 837 assert_raises(Exception, url_for, controller='content', action='view') 838 assert_raises(Exception, url_for, controller='content') 839 assert_raises(Exception, url_for, controller='admin/comments') 840 eq_('/category/home', url_for('category_home')) 841 eq_('/category/food', url_for('category_home', section='food')) 842 assert_raises(Exception, url_for, 'home', controller='content') 843 eq_('/', url_for('home')) 844 845 def test_with_route_names_and_defaults(self): 846 m = self.con.mapper 847 self.con.mapper_dict = {} 848 m.connect('home', '', controller='blog', action='splash') 849 m.connect('category_home', 'category/:section', controller='blog', action='view', section='home') 850 m.connect('building', 'building/:campus/:building/alljacks', controller='building', action='showjacks') 851 m.create_regs(['content','blog','admin/comments','building']) 852 853 self.con.mapper_dict = dict(controller='building', action='showjacks', campus='wilma', building='port') 854 assert_raises(Exception, url_for) 855 eq_('/building/wilma/port/alljacks', url_for(controller='building', action='showjacks', campus='wilma', building='port')) 856 eq_('/', url_for('home')) 857 858 def test_with_resource_route_names(self): 859 m = Mapper() 860 self.con.mapper = m 861 self.con.mapper_dict = {} 862 m.resource('message', 'messages', member={'mark':'GET'}, collection={'rss':'GET'}) 863 m.create_regs(['messages']) 864 865 assert_raises(Exception, url_for, controller='content', action='view') 866 assert_raises(Exception, url_for, controller='content') 867 assert_raises(Exception, url_for, controller='admin/comments') 868 eq_('/messages', url_for('messages')) 869 eq_('/messages/rss', url_for('rss_messages')) 870 eq_('/messages/4', url_for('message', id=4)) 871 eq_('/messages/4/edit', url_for('edit_message', id=4)) 872 eq_('/messages/4/mark', url_for('mark_message', id=4)) 873 eq_('/messages/new', url_for('new_message')) 874 875 eq_('/messages.xml', url_for('formatted_messages', format='xml')) 876 eq_('/messages/rss.xml', url_for('formatted_rss_messages', format='xml')) 877 eq_('/messages/4.xml', url_for('formatted_message', id=4, format='xml')) 878 eq_('/messages/4/edit.xml', url_for('formatted_edit_message', id=4, format='xml')) 879 eq_('/messages/4/mark.xml', url_for('formatted_mark_message', id=4, format='xml')) 880 eq_('/messages/new.xml', url_for('formatted_new_message', format='xml')) 881 882 def test_with_resource_route_names_and_nomin(self): 883 m = Mapper() 884 self.con.mapper = m 885 self.con.mapper_dict = {} 886 m.minimization = False 887 m.resource('message', 'messages', member={'mark':'GET'}, collection={'rss':'GET'}) 888 m.create_regs(['messages']) 889 890 assert_raises(Exception, url_for, controller='content', action='view') 891 assert_raises(Exception, url_for, controller='content') 892 assert_raises(Exception, url_for, controller='admin/comments') 893 eq_('/messages', url_for('messages')) 894 eq_('/messages/rss', url_for('rss_messages')) 895 eq_('/messages/4', url_for('message', id=4)) 896 eq_('/messages/4/edit', url_for('edit_message', id=4)) 897 eq_('/messages/4/mark', url_for('mark_message', id=4)) 898 eq_('/messages/new', url_for('new_message')) 899 900 eq_('/messages.xml', url_for('formatted_messages', format='xml')) 901 eq_('/messages/rss.xml', url_for('formatted_rss_messages', format='xml')) 902 eq_('/messages/4.xml', url_for('formatted_message', id=4, format='xml')) 903 eq_('/messages/4/edit.xml', url_for('formatted_edit_message', id=4, format='xml')) 904 eq_('/messages/4/mark.xml', url_for('formatted_mark_message', id=4, format='xml')) 905 eq_('/messages/new.xml', url_for('formatted_new_message', format='xml')) 906 907 908if __name__ == '__main__': 909 unittest.main() 910else: 911 def bench_gen(withcache = False): 912 m = Mapper(explicit=False) 913 m.connect('', controller='articles', action='index') 914 m.connect('admin', controller='admin/general', action='index') 915 916 m.connect('admin/comments/article/:article_id/:action/:id', controller = 'admin/comments', action = None, id=None) 917 m.connect('admin/trackback/article/:article_id/:action/:id', controller='admin/trackback', action=None, id=None) 918 m.connect('admin/content/:action/:id', controller='admin/content') 919 920 m.connect('xml/:action/feed.xml', controller='xml') 921 m.connect('xml/articlerss/:id/feed.xml', controller='xml', action='articlerss') 922 m.connect('index.rdf', controller='xml', action='rss') 923 924 m.connect('articles', controller='articles', action='index') 925 m.connect('articles/page/:page', controller='articles', action='index', requirements = {'page':'\d+'}) 926 927 m.connect('articles/:year/:month/:day/page/:page', controller='articles', action='find_by_date', month = None, day = None, 928 requirements = {'year':'\d{4}', 'month':'\d{1,2}','day':'\d{1,2}'}) 929 m.connect('articles/category/:id', controller='articles', action='category') 930 m.connect('pages/*name', controller='articles', action='view_page') 931 con = Config() 932 con.mapper = m 933 con.host = 'www.test.com' 934 con.protocol = 'http' 935 con.mapper_dict = {'controller':'xml','action':'articlerss'} 936 937 if withcache: 938 m.urlcache = {} 939 m._create_gens() 940 n = 5000 941 start = time.time() 942 for x in range(1,n): 943 url_for(controller='/articles', action='index', page=4) 944 url_for(controller='admin/general', action='index') 945 url_for(controller='admin/comments', action='show', article_id=2) 946 947 url_for(controller='articles', action='find_by_date', year=2004, page=1) 948 url_for(controller='articles', action='category', id=4) 949 url_for(id=2) 950 end = time.time() 951 ts = time.time() 952 for x in range(1,n*6): 953 pass 954 en = time.time() 955 total = end-start-(en-ts) 956 per_url = total / (n*6) 957 print("Generation (%s URLs) RouteSet" % (n*6)) 958 print("%s ms/url" % (per_url*1000)) 959 print("%s urls/s\n" % (1.00/per_url)) 960