def test_match_entire_path(uri_template, path): router = DefaultRouter() router.add_route(uri_template, {}, ResourceWithId(1)) route = router.find(path) assert route is None
def test_capture_path_complex(template): router = DefaultRouter() with pytest.raises( ValueError, match='Cannot use converter "path" of variable "bar" in a template ' ): router.add_route(template, ResourceWithId(1))
def test_match_entire_path(uri_template, path): router = DefaultRouter() router.add_route(uri_template, ResourceWithId(1)) route = router.find(path) assert route is None
def test_user_regression_special_chars(uri_template, path, expected_params): router = DefaultRouter() router.add_route(uri_template, ResourceWithId(1)) route = router.find(path) assert route is not None resource, __, params, __ = route assert resource.resource_id == 1 assert params == expected_params
def test_user_regression_special_chars(uri_template, path, expected_params): router = DefaultRouter() router.add_route(uri_template, {}, ResourceWithId(1)) route = router.find(path) assert route is not None resource, __, params, __ = route assert resource.resource_id == 1 assert params == expected_params
def test_user_regression_recipes(): router = DefaultRouter() router.add_route('/recipes/{activity}/{type_id}', ResourceWithId(1)) router.add_route('/recipes/baking', ResourceWithId(2)) resource, __, __, __ = router.find('/recipes/baking/4242') assert resource.resource_id == 1 resource, __, __, __ = router.find('/recipes/baking') assert resource.resource_id == 2 route = router.find('/recipes/grilling') assert route is None
def test_user_regression_recipes(): router = DefaultRouter() router.add_route( '/recipes/{activity}/{type_id}', ResourceWithId(1) ) router.add_route( '/recipes/baking', ResourceWithId(2) ) resource, __, __, __ = router.find('/recipes/baking/4242') assert resource.resource_id == 1 resource, __, __, __ = router.find('/recipes/baking') assert resource.resource_id == 2 route = router.find('/recipes/grilling') assert route is None
def test_root_path(): router = DefaultRouter() router.add_route('/', {}, ResourceWithId(42)) resource, __, __, __ = router.find('/') assert resource.resource_id == 42 expected_src = textwrap.dedent(""" def find(path, return_values, patterns, converters, params): path_len = len(path) if path_len > 0: if path[0] == '': if path_len == 1: return return_values[0] return None return None return None """).strip() assert router.finder_src == expected_src
def test_user_regression_versioned_url(): router = DefaultRouter() router.add_route('/{version}/messages', {}, ResourceWithId(2)) resource, __, __, __ = router.find('/v2/messages') assert resource.resource_id == 2 router.add_route('/v2', {}, ResourceWithId(1)) resource, __, __, __ = router.find('/v2') assert resource.resource_id == 1 resource, __, __, __ = router.find('/v2/messages') assert resource.resource_id == 2 resource, __, __, __ = router.find('/v1/messages') assert resource.resource_id == 2 route = router.find('/v1') assert route is None
def test_user_regression_versioned_url(): router = DefaultRouter() router.add_route('/{version}/messages', ResourceWithId(2)) resource, __, __, __ = router.find('/v2/messages') assert resource.resource_id == 2 router.add_route('/v2', ResourceWithId(1)) resource, __, __, __ = router.find('/v2') assert resource.resource_id == 1 resource, __, __, __ = router.find('/v2/messages') assert resource.resource_id == 2 resource, __, __, __ = router.find('/v1/messages') assert resource.resource_id == 2 route = router.find('/v1') assert route is None
def test_root_path(): router = DefaultRouter() router.add_route('/', ResourceWithId(42)) resource, __, __, __ = router.find('/') assert resource.resource_id == 42 expected_src = textwrap.dedent(""" def find(path, return_values, patterns, converters, params): path_len = len(path) if path_len > 0: if path[0] == '': if path_len == 1: return return_values[0] return None return None return None """).strip() assert router.finder_src == expected_src
def test_capture_path_no_match(): router = DefaultRouter() router.add_route('/foo/bar/baz', ResourceWithId(1)) router.add_route('/foo/{bar:path}', ResourceWithId(2)) router.add_route('/foo/bar/{foo:path}', ResourceWithId(3)) assert router.find('/foo') is None
class TestRegressionCases(testing.TestBase): """Test specific repros reported by users of the framework.""" def before(self): self.router = DefaultRouter() def test_versioned_url(self): self.router.add_route('/{version}/messages', {}, ResourceWithId(2)) resource, __, __, __ = self.router.find('/v2/messages') self.assertEqual(resource.resource_id, 2) self.router.add_route('/v2', {}, ResourceWithId(1)) resource, __, __, __ = self.router.find('/v2') self.assertEqual(resource.resource_id, 1) resource, __, __, __ = self.router.find('/v2/messages') self.assertEqual(resource.resource_id, 2) resource, __, __, __ = self.router.find('/v1/messages') self.assertEqual(resource.resource_id, 2) route = self.router.find('/v1') self.assertIs(route, None) def test_recipes(self): self.router.add_route( '/recipes/{activity}/{type_id}', {}, ResourceWithId(1)) self.router.add_route( '/recipes/baking', {}, ResourceWithId(2)) resource, __, __, __ = self.router.find('/recipes/baking/4242') self.assertEqual(resource.resource_id, 1) resource, __, __, __ = self.router.find('/recipes/baking') self.assertEqual(resource.resource_id, 2) route = self.router.find('/recipes/grilling') self.assertIs(route, None)
class TestRegressionCases(testing.TestBase): """Test specific repros reported by users of the framework.""" def before(self): self.router = DefaultRouter() def test_versioned_url(self): self.router.add_route('/{version}/messages', {}, ResourceWithId(2)) resource, method_map, params = self.router.find('/v2/messages') self.assertEqual(resource.resource_id, 2) self.router.add_route('/v2', {}, ResourceWithId(1)) resource, method_map, params = self.router.find('/v2') self.assertEqual(resource.resource_id, 1) resource, method_map, params = self.router.find('/v2/messages') self.assertEqual(resource.resource_id, 2) resource, method_map, params = self.router.find('/v1/messages') self.assertEqual(resource.resource_id, 2) route = self.router.find('/v1') self.assertIs(route, None) def test_recipes(self): self.router.add_route( '/recipes/{activity}/{type_id}', {}, ResourceWithId(1)) self.router.add_route( '/recipes/baking', {}, ResourceWithId(2)) resource, method_map, params = self.router.find('/recipes/baking/4242') self.assertEqual(resource.resource_id, 1) resource, method_map, params = self.router.find('/recipes/baking') self.assertEqual(resource.resource_id, 2) route = self.router.find('/recipes/grilling') self.assertIs(route, None)
def test_capture_path_no_children(): router = DefaultRouter() router.add_route('/foo/{bar:path}', ResourceWithId(1)) res = router.finder_src with pytest.raises( ValueError, match='Cannot add route with template "/foo/{bar:path}/child". ' 'Field name "bar" uses the converter "path"', ): router.add_route('/foo/{bar:path}/child', ResourceWithId(1)) with pytest.raises( ValueError, match='Cannot add route with template "/{bar:path}/child". ' 'Field name "bar" uses the converter "path"', ): router.add_route('/{bar:path}/child', ResourceWithId(1)) assert res == router.finder_src
class TestStandaloneRouter(testing.TestBase): def before(self): from falcon.routing import DefaultRouter self.router = DefaultRouter() setup_routes(self.router) @ddt.data( '/teams/{collision}', # simple vs simple '/emojis/signs/{id_too}', # another simple vs simple '/repos/{org}/{repo}/compare/{complex}:{vs}...{complex2}:{collision}', ) def test_collision(self, template): self.assertRaises( ValueError, self.router.add_route, template, {}, ResourceWithId(-1) ) @ddt.data( '/repos/{org}/{repo}/compare/{simple-vs-complex}', '/repos/{complex}.{vs}.{simple}', '/repos/{org}/{repo}/compare/{complex}:{vs}...{complex2}/full', ) def test_non_collision(self, template): self.router.add_route(template, {}, ResourceWithId(-1)) def test_dump(self): print(self.router._src) def test_override(self): self.router.add_route('/emojis/signs/0', {}, ResourceWithId(-1)) resource, method_map, params = self.router.find('/emojis/signs/0') self.assertEqual(resource.resource_id, -1) def test_missing(self): resource, method_map, params = self.router.find('/this/does/not/exist') self.assertIs(resource, None) resource, method_map, params = self.router.find('/user/bogus') self.assertIs(resource, None) resource, method_map, params = self.router.find('/teams/1234/bogus') self.assertIs(resource, None) resource, method_map, params = self.router.find( '/repos/racker/falcon/compare/johndoe:master...janedoe:dev/bogus') self.assertIs(resource, None) def test_literal_segment(self): resource, method_map, params = self.router.find('/emojis/signs/0') self.assertEqual(resource.resource_id, 12) resource, method_map, params = self.router.find('/emojis/signs/1') self.assertEqual(resource.resource_id, 13) resource, method_map, params = self.router.find('/emojis/signs/42') self.assertEqual(resource.resource_id, 14) resource, method_map, params = self.router.find('/emojis/signs/42/small') self.assertEqual(resource.resource_id, 14.1) resource, method_map, params = self.router.find('/emojis/signs/1/small') self.assertEqual(resource, None) @ddt.data( '/teams', '/emojis/signs', '/gists', '/gists/42', ) def test_dead_segment(self, template): resource, method_map, params = self.router.find(template) self.assertIs(resource, None) def test_malformed_pattern(self): resource, method_map, params = self.router.find( '/repos/racker/falcon/compare/foo') self.assertIs(resource, None) resource, method_map, params = self.router.find( '/repos/racker/falcon/compare/foo/full') self.assertIs(resource, None) def test_literal(self): resource, method_map, params = self.router.find('/user/memberships') self.assertEqual(resource.resource_id, 8) def test_variable(self): resource, method_map, params = self.router.find('/teams/42') self.assertEqual(resource.resource_id, 6) self.assertEqual(params, {'id': '42'}) resource, method_map, params = self.router.find('/emojis/signs/stop') self.assertEqual(params, {'id': 'stop'}) resource, method_map, params = self.router.find('/gists/42/raw') self.assertEqual(params, {'id': '42'}) def test_subsegment_not_found(self): resource, method_map, params = self.router.find('/emojis/signs/0/x') self.assertIs(resource, None) def test_multivar(self): resource, method_map, params = self.router.find( '/repos/racker/falcon/commits') self.assertEqual(resource.resource_id, 4) self.assertEqual(params, {'org': 'racker', 'repo': 'falcon'}) resource, method_map, params = self.router.find( '/repos/racker/falcon/compare/all') self.assertEqual(resource.resource_id, 11) self.assertEqual(params, {'org': 'racker', 'repo': 'falcon'}) @ddt.data(('', 5), ('/full', 10), ('/part', 15)) @ddt.unpack def test_complex(self, url_postfix, resource_id): uri = '/repos/racker/falcon/compare/johndoe:master...janedoe:dev' resource, method_map, params = self.router.find(uri + url_postfix) self.assertEqual(resource.resource_id, resource_id) self.assertEqual(params, { 'org': 'racker', 'repo': 'falcon', 'usr0': 'johndoe', 'branch0': 'master', 'usr1': 'janedoe', 'branch1': 'dev' }) @ddt.data(('', 16), ('/full', 17)) @ddt.unpack def test_complex_alt(self, url_postfix, resource_id): uri = '/repos/falconry/falcon/compare/johndoe:master' resource, method_map, params = self.router.find(uri + url_postfix) self.assertEqual(resource.resource_id, resource_id) self.assertEqual(params, { 'org': 'falconry', 'repo': 'falcon', 'usr0': 'johndoe', 'branch0': 'master', })
def add_route(self, uri_template, method_map, resource, name=None): if name: self.url_map[name] = uri_template DefaultRouter.add_route(self, uri_template, method_map, resource)
def router(): router = DefaultRouter() router.add_route('/repos', ResourceWithId(1)) router.add_route('/repos/{org}', ResourceWithId(2)) router.add_route('/repos/{org}/{repo}', ResourceWithId(3)) router.add_route('/repos/{org}/{repo}/commits', ResourceWithId(4)) router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}', ResourceWithId(5)) router.add_route('/teams/{id}', ResourceWithId(6)) router.add_route('/teams/{id}/members', ResourceWithId(7)) router.add_route('/teams/default', ResourceWithId(19)) router.add_route('/teams/default/members/thing', ResourceWithId(19)) router.add_route('/user/memberships', ResourceWithId(8)) router.add_route('/emojis', ResourceWithId(9)) router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}/full', ResourceWithId(10)) router.add_route('/repos/{org}/{repo}/compare/all', ResourceWithId(11)) # NOTE(kgriffs): The ordering of these calls is significant; we # need to test that the {id} field does not match the other routes, # regardless of the order they are added. router.add_route('/emojis/signs/0', ResourceWithId(12)) router.add_route('/emojis/signs/{id}', ResourceWithId(13)) router.add_route('/emojis/signs/42', ResourceWithId(14)) router.add_route('/emojis/signs/42/small.jpg', ResourceWithId(23)) router.add_route('/emojis/signs/78/small.png', ResourceWithId(24)) # Test some more special chars router.add_route('/emojis/signs/78/small(png)', ResourceWithId(25)) router.add_route('/emojis/signs/78/small_png', ResourceWithId(26)) router.add_route('/images/{id}.gif', ResourceWithId(27)) router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}/part', ResourceWithId(15)) router.add_route('/repos/{org}/{repo}/compare/{usr0}:{branch0}', ResourceWithId(16)) router.add_route('/repos/{org}/{repo}/compare/{usr0}:{branch0}/full', ResourceWithId(17)) router.add_route('/gists/{id}/{representation}', ResourceWithId(21)) router.add_route('/gists/{id}/raw', ResourceWithId(18)) router.add_route('/gists/first', ResourceWithId(20)) router.add_route('/item/{q}', ResourceWithId(28)) # ---------------------------------------------------------------- # Routes with field converters # ---------------------------------------------------------------- router.add_route('/cvt/teams/{id:int(min=7)}', ResourceWithId(29)) router.add_route('/cvt/teams/{id:int(min=7)}/members', ResourceWithId(30)) router.add_route('/cvt/teams/default', ResourceWithId(31)) router.add_route('/cvt/teams/default/members/{id:int}-{tenure:int}', ResourceWithId(32)) router.add_route( '/cvt/repos/{org}/{repo}/compare/{usr0}:{branch0:int}...{usr1}:{branch1:int}/part', ResourceWithId(33)) router.add_route('/cvt/repos/{org}/{repo}/compare/{usr0}:{branch0:int}', ResourceWithId(34)) router.add_route( '/cvt/repos/{org}/{repo}/compare/{usr0}:{branch0:int}/full', ResourceWithId(35)) return router
class TestComplexRouting(testing.TestBase): def before(self): self.router = DefaultRouter() self.router.add_route( '/repos', {}, ResourceWithId(1)) self.router.add_route( '/repos/{org}', {}, ResourceWithId(2)) self.router.add_route( '/repos/{org}/{repo}', {}, ResourceWithId(3)) self.router.add_route( '/repos/{org}/{repo}/commits', {}, ResourceWithId(4)) self.router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}', {}, ResourceWithId(5)) self.router.add_route( '/teams/{id}', {}, ResourceWithId(6)) self.router.add_route( '/teams/{id}/members', {}, ResourceWithId(7)) self.router.add_route( '/teams/default', {}, ResourceWithId(19)) self.router.add_route( '/teams/default/members/thing', {}, ResourceWithId(19)) self.router.add_route( '/user/memberships', {}, ResourceWithId(8)) self.router.add_route( '/emojis', {}, ResourceWithId(9)) self.router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}/full', {}, ResourceWithId(10)) self.router.add_route( '/repos/{org}/{repo}/compare/all', {}, ResourceWithId(11)) # NOTE(kgriffs): The ordering of these calls is significant; we # need to test that the {id} field does not match the other routes, # regardless of the order they are added. self.router.add_route( '/emojis/signs/0', {}, ResourceWithId(12)) self.router.add_route( '/emojis/signs/{id}', {}, ResourceWithId(13)) self.router.add_route( '/emojis/signs/42', {}, ResourceWithId(14)) self.router.add_route( '/emojis/signs/42/small', {}, ResourceWithId(14.1)) self.router.add_route( '/emojis/signs/78/small', {}, ResourceWithId(22)) self.router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}/part', {}, ResourceWithId(15)) self.router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}', {}, ResourceWithId(16)) self.router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}/full', {}, ResourceWithId(17)) self.router.add_route( '/gists/{id}/{representation}', {}, ResourceWithId(21)) self.router.add_route( '/gists/{id}/raw', {}, ResourceWithId(18)) self.router.add_route( '/gists/first', {}, ResourceWithId(20)) @ddt.data( '/teams/{collision}', # simple vs simple '/emojis/signs/{id_too}', # another simple vs simple '/repos/{org}/{repo}/compare/{complex}:{vs}...{complex2}:{collision}', ) def test_collision(self, template): self.assertRaises( ValueError, self.router.add_route, template, {}, ResourceWithId(-1) ) @ddt.data( '/repos/{complex}.{vs}.{simple}', '/repos/{org}/{repo}/compare/{complex}:{vs}...{complex2}/full', ) def test_non_collision(self, template): self.router.add_route(template, {}, ResourceWithId(-1)) def test_dump(self): print(self.router._src) def test_override(self): self.router.add_route('/emojis/signs/0', {}, ResourceWithId(-1)) resource, method_map, params = self.router.find('/emojis/signs/0') self.assertEqual(resource.resource_id, -1) def test_literal_segment(self): resource, method_map, params = self.router.find('/emojis/signs/0') self.assertEqual(resource.resource_id, 12) resource, method_map, params = self.router.find('/emojis/signs/1') self.assertEqual(resource.resource_id, 13) resource, method_map, params = self.router.find('/emojis/signs/42') self.assertEqual(resource.resource_id, 14) resource, method_map, params = self.router.find('/emojis/signs/42/small') self.assertEqual(resource.resource_id, 14.1) route = self.router.find('/emojis/signs/1/small') self.assertEqual(route, None) @ddt.data( '/teams', '/emojis/signs', '/gists', '/gists/42', ) def test_dead_segment(self, template): route = self.router.find(template) self.assertIs(route, None) def test_malformed_pattern(self): route = self.router.find( '/repos/racker/falcon/compare/foo') self.assertIs(route, None) route = self.router.find( '/repos/racker/falcon/compare/foo/full') self.assertIs(route, None) def test_literal(self): resource, method_map, params = self.router.find('/user/memberships') self.assertEqual(resource.resource_id, 8) def test_variable(self): resource, method_map, params = self.router.find('/teams/42') self.assertEqual(resource.resource_id, 6) self.assertEqual(params, {'id': '42'}) resource, method_map, params = self.router.find('/emojis/signs/stop') self.assertEqual(params, {'id': 'stop'}) resource, method_map, params = self.router.find('/gists/42/raw') self.assertEqual(params, {'id': '42'}) @ddt.data( ('/teams/default', 19), ('/teams/default/members', 7), ('/teams/foo', 6), ('/teams/foo/members', 7), ('/gists/first', 20), ('/gists/first/raw', 18), ('/gists/first/pdf', 21), ('/gists/1776/pdf', 21), ('/emojis/signs/78', 13), ('/emojis/signs/78/small', 22), ) @ddt.unpack def test_literal_vs_variable(self, path, expected_id): resource, method_map, params = self.router.find(path) self.assertEqual(resource.resource_id, expected_id) @ddt.data( # Misc. '/this/does/not/exist', '/user/bogus', '/repos/racker/falcon/compare/johndoe:master...janedoe:dev/bogus', # Literal vs variable (teams) '/teams', '/teams/42/members/undefined', '/teams/42/undefined', '/teams/42/undefined/segments', '/teams/default/members/undefined', '/teams/default/members/thing/undefined', '/teams/default/members/thing/undefined/segments', '/teams/default/undefined', '/teams/default/undefined/segments', # Literal vs variable (emojis) '/emojis/signs', '/emojis/signs/0/small', '/emojis/signs/0/undefined', '/emojis/signs/0/undefined/segments', '/emojis/signs/20/small', '/emojis/signs/20/undefined', '/emojis/signs/42/undefined', '/emojis/signs/78/undefined', ) def test_not_found(self, path): route = self.router.find(path) self.assertIs(route, None) def test_subsegment_not_found(self): route = self.router.find('/emojis/signs/0/x') self.assertIs(route, None) def test_multivar(self): resource, method_map, params = self.router.find( '/repos/racker/falcon/commits') self.assertEqual(resource.resource_id, 4) self.assertEqual(params, {'org': 'racker', 'repo': 'falcon'}) resource, method_map, params = self.router.find( '/repos/racker/falcon/compare/all') self.assertEqual(resource.resource_id, 11) self.assertEqual(params, {'org': 'racker', 'repo': 'falcon'}) @ddt.data(('', 5), ('/full', 10), ('/part', 15)) @ddt.unpack def test_complex(self, url_postfix, resource_id): uri = '/repos/racker/falcon/compare/johndoe:master...janedoe:dev' resource, method_map, params = self.router.find(uri + url_postfix) self.assertEqual(resource.resource_id, resource_id) self.assertEqual(params, { 'org': 'racker', 'repo': 'falcon', 'usr0': 'johndoe', 'branch0': 'master', 'usr1': 'janedoe', 'branch1': 'dev', }) @ddt.data(('', 16), ('/full', 17)) @ddt.unpack def test_complex_alt(self, url_postfix, resource_id): uri = '/repos/falconry/falcon/compare/johndoe:master' resource, method_map, params = self.router.find(uri + url_postfix) self.assertEqual(resource.resource_id, resource_id) self.assertEqual(params, { 'org': 'falconry', 'repo': 'falcon', 'usr0': 'johndoe', 'branch0': 'master', })
def router(): router = DefaultRouter() router.add_route("/browse/{id:int}/", lambda x: x) return router
def router(): router = DefaultRouter() router.add_route( '/repos', {}, ResourceWithId(1)) router.add_route( '/repos/{org}', {}, ResourceWithId(2)) router.add_route( '/repos/{org}/{repo}', {}, ResourceWithId(3)) router.add_route( '/repos/{org}/{repo}/commits', {}, ResourceWithId(4)) router.add_route( u'/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}', {}, ResourceWithId(5)) router.add_route( '/teams/{id}', {}, ResourceWithId(6)) router.add_route( '/teams/{id}/members', {}, ResourceWithId(7)) router.add_route( '/teams/default', {}, ResourceWithId(19)) router.add_route( '/teams/default/members/thing', {}, ResourceWithId(19)) router.add_route( '/user/memberships', {}, ResourceWithId(8)) router.add_route( '/emojis', {}, ResourceWithId(9)) router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}/full', {}, ResourceWithId(10)) router.add_route( '/repos/{org}/{repo}/compare/all', {}, ResourceWithId(11)) # NOTE(kgriffs): The ordering of these calls is significant; we # need to test that the {id} field does not match the other routes, # regardless of the order they are added. router.add_route( '/emojis/signs/0', {}, ResourceWithId(12)) router.add_route( '/emojis/signs/{id}', {}, ResourceWithId(13)) router.add_route( '/emojis/signs/42', {}, ResourceWithId(14)) router.add_route( '/emojis/signs/42/small.jpg', {}, ResourceWithId(23)) router.add_route( '/emojis/signs/78/small.png', {}, ResourceWithId(24)) # Test some more special chars router.add_route( '/emojis/signs/78/small(png)', {}, ResourceWithId(25)) router.add_route( '/emojis/signs/78/small_png', {}, ResourceWithId(26)) router.add_route('/images/{id}.gif', {}, ResourceWithId(27)) router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}/part', {}, ResourceWithId(15)) router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}', {}, ResourceWithId(16)) router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}/full', {}, ResourceWithId(17)) router.add_route( '/gists/{id}/{representation}', {}, ResourceWithId(21)) router.add_route( '/gists/{id}/raw', {}, ResourceWithId(18)) router.add_route( '/gists/first', {}, ResourceWithId(20)) router.add_route('/item/{q}', {}, ResourceWithId(28)) # ---------------------------------------------------------------- # Routes with field converters # ---------------------------------------------------------------- router.add_route( '/cvt/teams/{id:int(min=7)}', {}, ResourceWithId(29)) router.add_route( '/cvt/teams/{id:int(min=7)}/members', {}, ResourceWithId(30)) router.add_route( '/cvt/teams/default', {}, ResourceWithId(31)) router.add_route( '/cvt/teams/default/members/{id:int}-{tenure:int}', {}, ResourceWithId(32)) router.add_route( '/cvt/repos/{org}/{repo}/compare/{usr0}:{branch0:int}...{usr1}:{branch1:int}/part', {}, ResourceWithId(33)) router.add_route( '/cvt/repos/{org}/{repo}/compare/{usr0}:{branch0:int}', {}, ResourceWithId(34)) router.add_route( '/cvt/repos/{org}/{repo}/compare/{usr0}:{branch0:int}/full', {}, ResourceWithId(35)) return router
class TestComplexRouting(testing.TestBase): def before(self): self.router = DefaultRouter() self.router.add_route('/repos', {}, ResourceWithId(1)) self.router.add_route('/repos/{org}', {}, ResourceWithId(2)) self.router.add_route('/repos/{org}/{repo}', {}, ResourceWithId(3)) self.router.add_route('/repos/{org}/{repo}/commits', {}, ResourceWithId(4)) self.router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}', {}, ResourceWithId(5)) self.router.add_route('/teams/{id}', {}, ResourceWithId(6)) self.router.add_route('/teams/{id}/members', {}, ResourceWithId(7)) self.router.add_route('/teams/default', {}, ResourceWithId(19)) self.router.add_route('/teams/default/members/thing', {}, ResourceWithId(19)) self.router.add_route('/user/memberships', {}, ResourceWithId(8)) self.router.add_route('/emojis', {}, ResourceWithId(9)) self.router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}/full', {}, ResourceWithId(10)) self.router.add_route('/repos/{org}/{repo}/compare/all', {}, ResourceWithId(11)) # NOTE(kgriffs): The ordering of these calls is significant; we # need to test that the {id} field does not match the other routes, # regardless of the order they are added. self.router.add_route('/emojis/signs/0', {}, ResourceWithId(12)) self.router.add_route('/emojis/signs/{id}', {}, ResourceWithId(13)) self.router.add_route('/emojis/signs/42', {}, ResourceWithId(14)) self.router.add_route('/emojis/signs/42/small', {}, ResourceWithId(14.1)) self.router.add_route('/emojis/signs/78/small', {}, ResourceWithId(22)) self.router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}/part', {}, ResourceWithId(15)) self.router.add_route('/repos/{org}/{repo}/compare/{usr0}:{branch0}', {}, ResourceWithId(16)) self.router.add_route( '/repos/{org}/{repo}/compare/{usr0}:{branch0}/full', {}, ResourceWithId(17)) self.router.add_route('/gists/{id}/{representation}', {}, ResourceWithId(21)) self.router.add_route('/gists/{id}/raw', {}, ResourceWithId(18)) self.router.add_route('/gists/first', {}, ResourceWithId(20)) @ddt.data( '/teams/{collision}', # simple vs simple '/emojis/signs/{id_too}', # another simple vs simple '/repos/{org}/{repo}/compare/{complex}:{vs}...{complex2}:{collision}', ) def test_collision(self, template): self.assertRaises(ValueError, self.router.add_route, template, {}, ResourceWithId(-1)) @ddt.data( '/repos/{org}/{repo}/compare/{simple_vs_complex}', '/repos/{complex}.{vs}.{simple}', '/repos/{org}/{repo}/compare/{complex}:{vs}...{complex2}/full', ) def test_non_collision(self, template): self.router.add_route(template, {}, ResourceWithId(-1)) @ddt.data( '/{}', '/{9v}', '/{@kgriffs}', '/repos/{simple-thing}/etc', '/repos/{or g}/{repo}/compare/{thing}', '/repos/{org}/{repo}/compare/{}', '/repos/{complex}.{}.{thing}', '/repos/{complex}.{9v}.{thing}/etc', ) def test_invalid_field_name(self, template): self.assertRaises(ValueError, self.router.add_route, template, {}, ResourceWithId(-1)) def test_dump(self): print(self.router._src) def test_override(self): self.router.add_route('/emojis/signs/0', {}, ResourceWithId(-1)) resource, method_map, params = self.router.find('/emojis/signs/0') self.assertEqual(resource.resource_id, -1) def test_literal_segment(self): resource, method_map, params = self.router.find('/emojis/signs/0') self.assertEqual(resource.resource_id, 12) resource, method_map, params = self.router.find('/emojis/signs/1') self.assertEqual(resource.resource_id, 13) resource, method_map, params = self.router.find('/emojis/signs/42') self.assertEqual(resource.resource_id, 14) resource, method_map, params = self.router.find( '/emojis/signs/42/small') self.assertEqual(resource.resource_id, 14.1) route = self.router.find('/emojis/signs/1/small') self.assertEqual(route, None) @ddt.data( '/teams', '/emojis/signs', '/gists', '/gists/42', ) def test_dead_segment(self, template): route = self.router.find(template) self.assertIs(route, None) def test_malformed_pattern(self): route = self.router.find('/repos/racker/falcon/compare/foo') self.assertIs(route, None) route = self.router.find('/repos/racker/falcon/compare/foo/full') self.assertIs(route, None) def test_literal(self): resource, method_map, params = self.router.find('/user/memberships') self.assertEqual(resource.resource_id, 8) def test_variable(self): resource, method_map, params = self.router.find('/teams/42') self.assertEqual(resource.resource_id, 6) self.assertEqual(params, {'id': '42'}) resource, method_map, params = self.router.find('/emojis/signs/stop') self.assertEqual(params, {'id': 'stop'}) resource, method_map, params = self.router.find('/gists/42/raw') self.assertEqual(params, {'id': '42'}) @ddt.data( ('/teams/default', 19), ('/teams/default/members', 7), ('/teams/foo', 6), ('/teams/foo/members', 7), ('/gists/first', 20), ('/gists/first/raw', 18), ('/gists/first/pdf', 21), ('/gists/1776/pdf', 21), ('/emojis/signs/78', 13), ('/emojis/signs/78/small', 22), ) @ddt.unpack def test_literal_vs_variable(self, path, expected_id): resource, method_map, params = self.router.find(path) self.assertEqual(resource.resource_id, expected_id) @ddt.data( # Misc. '/this/does/not/exist', '/user/bogus', '/repos/racker/falcon/compare/johndoe:master...janedoe:dev/bogus', # Literal vs variable (teams) '/teams', '/teams/42/members/undefined', '/teams/42/undefined', '/teams/42/undefined/segments', '/teams/default/members/undefined', '/teams/default/members/thing/undefined', '/teams/default/members/thing/undefined/segments', '/teams/default/undefined', '/teams/default/undefined/segments', # Literal vs variable (emojis) '/emojis/signs', '/emojis/signs/0/small', '/emojis/signs/0/undefined', '/emojis/signs/0/undefined/segments', '/emojis/signs/20/small', '/emojis/signs/20/undefined', '/emojis/signs/42/undefined', '/emojis/signs/78/undefined', ) def test_not_found(self, path): route = self.router.find(path) self.assertIs(route, None) def test_subsegment_not_found(self): route = self.router.find('/emojis/signs/0/x') self.assertIs(route, None) def test_multivar(self): resource, method_map, params = self.router.find( '/repos/racker/falcon/commits') self.assertEqual(resource.resource_id, 4) self.assertEqual(params, {'org': 'racker', 'repo': 'falcon'}) resource, method_map, params = self.router.find( '/repos/racker/falcon/compare/all') self.assertEqual(resource.resource_id, 11) self.assertEqual(params, {'org': 'racker', 'repo': 'falcon'}) @ddt.data(('', 5), ('/full', 10), ('/part', 15)) @ddt.unpack def test_complex(self, url_postfix, resource_id): uri = '/repos/racker/falcon/compare/johndoe:master...janedoe:dev' resource, method_map, params = self.router.find(uri + url_postfix) self.assertEqual(resource.resource_id, resource_id) self.assertEqual( params, { 'org': 'racker', 'repo': 'falcon', 'usr0': 'johndoe', 'branch0': 'master', 'usr1': 'janedoe', 'branch1': 'dev', }) @ddt.data(('', 16), ('/full', 17)) @ddt.unpack def test_complex_alt(self, url_postfix, resource_id): uri = '/repos/falconry/falcon/compare/johndoe:master' resource, method_map, params = self.router.find(uri + url_postfix) self.assertEqual(resource.resource_id, resource_id) self.assertEqual( params, { 'org': 'falconry', 'repo': 'falcon', 'usr0': 'johndoe', 'branch0': 'master', })
def capture_path_router(): router = DefaultRouter() router.add_route('/foo/bar/baz', ResourceWithId(1)) router.add_route('/foo/{bar:path}', ResourceWithId(2)) router.add_route('/foo/bar/{foo:path}', ResourceWithId(3)) router.add_route('/{baz:path}', ResourceWithId(4)) router.add_route('/x/{v1:int}/{v2}/{other:path}', ResourceWithId(5)) router.add_route('/y/{v1:int}/{v2:int}/{other:path}', ResourceWithId(6)) return router
def test_root_path(): router = DefaultRouter() router.add_route('/', {}, ResourceWithId(42)) resource, __, __, __ = router.find('/') assert resource.resource_id == 42
def test_duplicate_field_names(uri_template): router = DefaultRouter() with pytest.raises(ValueError): router.add_route(uri_template, {}, ResourceWithId(1))
def test_duplicate_field_names(uri_template): router = DefaultRouter() with pytest.raises(ValueError): router.add_route(uri_template, ResourceWithId(1))
class TestStandaloneRouter(testing.TestBase): def before(self): from falcon.routing import DefaultRouter self.router = DefaultRouter() setup_routes(self.router) @ddt.data( '/teams/{collision}', '/repos/{org}/{repo}/compare/{simple-collision}', '/emojis/signs/{id_too}', ) def test_collision(self, template): self.assertRaises( ValueError, self.router.add_route, template, {}, ResourceWithId(-1) ) def test_dump(self): print(self.router._src) def test_override(self): self.router.add_route('/emojis/signs/0', {}, ResourceWithId(-1)) resource, method_map, params = self.router.find('/emojis/signs/0') self.assertEqual(resource.resource_id, -1) def test_missing(self): resource, method_map, params = self.router.find('/this/does/not/exist') self.assertIs(resource, None) resource, method_map, params = self.router.find('/user/bogus') self.assertIs(resource, None) resource, method_map, params = self.router.find('/teams/1234/bogus') self.assertIs(resource, None) resource, method_map, params = self.router.find( '/repos/racker/falcon/compare/johndoe:master...janedoe:dev/bogus') self.assertIs(resource, None) def test_literal_segment(self): resource, method_map, params = self.router.find('/emojis/signs/0') self.assertEqual(resource.resource_id, 12) resource, method_map, params = self.router.find('/emojis/signs/1') self.assertEqual(resource.resource_id, 13) resource, method_map, params = self.router.find('/emojis/signs/42') self.assertEqual(resource.resource_id, 14) resource, method_map, params = self.router.find('/emojis/signs/42/small') self.assertEqual(resource.resource_id, 14.1) resource, method_map, params = self.router.find('/emojis/signs/1/small') self.assertEqual(resource, None) @ddt.data( '/teams', '/emojis/signs', '/gists', '/gists/42', ) def test_dead_segment(self, template): resource, method_map, params = self.router.find(template) self.assertIs(resource, None) def test_malformed_pattern(self): resource, method_map, params = self.router.find( '/repos/racker/falcon/compare/foo') self.assertIs(resource, None) resource, method_map, params = self.router.find( '/repos/racker/falcon/compare/foo/full') self.assertIs(resource, None) def test_literal(self): resource, method_map, params = self.router.find('/user/memberships') self.assertEqual(resource.resource_id, 8) def test_variable(self): resource, method_map, params = self.router.find('/teams/42') self.assertEqual(resource.resource_id, 6) self.assertEqual(params, {'id': '42'}) resource, method_map, params = self.router.find('/emojis/signs/stop') self.assertEqual(params, {'id': 'stop'}) resource, method_map, params = self.router.find('/gists/42/raw') self.assertEqual(params, {'id': '42'}) def test_subsegment_not_found(self): resource, method_map, params = self.router.find('/emojis/signs/0/x') self.assertIs(resource, None) def test_multivar(self): resource, method_map, params = self.router.find( '/repos/racker/falcon/commits') self.assertEqual(resource.resource_id, 4) self.assertEqual(params, {'org': 'racker', 'repo': 'falcon'}) resource, method_map, params = self.router.find( '/repos/racker/falcon/compare/all') self.assertEqual(resource.resource_id, 11) self.assertEqual(params, {'org': 'racker', 'repo': 'falcon'}) @ddt.data(('', 5), ('/full', 10), ('/part', 15)) @ddt.unpack def test_complex(self, url_postfix, resource_id): uri = '/repos/racker/falcon/compare/johndoe:master...janedoe:dev' resource, method_map, params = self.router.find(uri + url_postfix) self.assertEqual(resource.resource_id, resource_id) self.assertEqual(params, { 'org': 'racker', 'repo': 'falcon', 'usr0': 'johndoe', 'branch0': 'master', 'usr1': 'janedoe', 'branch1': 'dev' }) @ddt.data(('', 16), ('/full', 17)) @ddt.unpack def test_complex_alt(self, url_postfix, resource_id): uri = '/repos/falconry/falcon/compare/johndoe:master' resource, method_map, params = self.router.find(uri + url_postfix) self.assertEqual(resource.resource_id, resource_id) self.assertEqual(params, { 'org': 'falconry', 'repo': 'falcon', 'usr0': 'johndoe', 'branch0': 'master', })
def param_router(): r = DefaultRouter() r.add_route('/c/foo/{bar}/baz', ResourceWithId(1)) r.add_route('/c/{foo}/bar/other', ResourceWithId(2)) r.add_route('/c/foo/{a:int}-{b}/a', ResourceWithId(3)) r.add_route('/upload/{service}/auth/token', ResourceWithId(4)) r.add_route('/upload/youtube/{project_id}/share', ResourceWithId(5)) r.add_route('/x/y/{a}.{b}/z', ResourceWithId(6)) r.add_route('/x/{y}/o.o/w', ResourceWithId(7)) return r
class TestComplexRouting(testing.TestBase): def before(self): self.router = DefaultRouter() self.router.add_route("/repos", {}, ResourceWithId(1)) self.router.add_route("/repos/{org}", {}, ResourceWithId(2)) self.router.add_route("/repos/{org}/{repo}", {}, ResourceWithId(3)) self.router.add_route("/repos/{org}/{repo}/commits", {}, ResourceWithId(4)) self.router.add_route("/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}", {}, ResourceWithId(5)) self.router.add_route("/teams/{id}", {}, ResourceWithId(6)) self.router.add_route("/teams/{id}/members", {}, ResourceWithId(7)) self.router.add_route("/teams/default", {}, ResourceWithId(19)) self.router.add_route("/teams/default/members/thing", {}, ResourceWithId(19)) self.router.add_route("/user/memberships", {}, ResourceWithId(8)) self.router.add_route("/emojis", {}, ResourceWithId(9)) self.router.add_route( "/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}/full", {}, ResourceWithId(10) ) self.router.add_route("/repos/{org}/{repo}/compare/all", {}, ResourceWithId(11)) # NOTE(kgriffs): The ordering of these calls is significant; we # need to test that the {id} field does not match the other routes, # regardless of the order they are added. self.router.add_route("/emojis/signs/0", {}, ResourceWithId(12)) self.router.add_route("/emojis/signs/{id}", {}, ResourceWithId(13)) self.router.add_route("/emojis/signs/42", {}, ResourceWithId(14)) self.router.add_route("/emojis/signs/42/small", {}, ResourceWithId(14.1)) self.router.add_route("/emojis/signs/78/small", {}, ResourceWithId(22)) self.router.add_route( "/repos/{org}/{repo}/compare/{usr0}:{branch0}...{usr1}:{branch1}/part", {}, ResourceWithId(15) ) self.router.add_route("/repos/{org}/{repo}/compare/{usr0}:{branch0}", {}, ResourceWithId(16)) self.router.add_route("/repos/{org}/{repo}/compare/{usr0}:{branch0}/full", {}, ResourceWithId(17)) self.router.add_route("/gists/{id}/{representation}", {}, ResourceWithId(21)) self.router.add_route("/gists/{id}/raw", {}, ResourceWithId(18)) self.router.add_route("/gists/first", {}, ResourceWithId(20)) @ddt.data( "/teams/{collision}", # simple vs simple "/emojis/signs/{id_too}", # another simple vs simple "/repos/{org}/{repo}/compare/{complex}:{vs}...{complex2}:{collision}", ) def test_collision(self, template): self.assertRaises(ValueError, self.router.add_route, template, {}, ResourceWithId(-1)) @ddt.data( "/repos/{org}/{repo}/compare/{simple-vs-complex}", "/repos/{complex}.{vs}.{simple}", "/repos/{org}/{repo}/compare/{complex}:{vs}...{complex2}/full", ) def test_non_collision(self, template): self.router.add_route(template, {}, ResourceWithId(-1)) def test_dump(self): print(self.router._src) def test_override(self): self.router.add_route("/emojis/signs/0", {}, ResourceWithId(-1)) resource, method_map, params = self.router.find("/emojis/signs/0") self.assertEqual(resource.resource_id, -1) def test_literal_segment(self): resource, method_map, params = self.router.find("/emojis/signs/0") self.assertEqual(resource.resource_id, 12) resource, method_map, params = self.router.find("/emojis/signs/1") self.assertEqual(resource.resource_id, 13) resource, method_map, params = self.router.find("/emojis/signs/42") self.assertEqual(resource.resource_id, 14) resource, method_map, params = self.router.find("/emojis/signs/42/small") self.assertEqual(resource.resource_id, 14.1) route = self.router.find("/emojis/signs/1/small") self.assertEqual(route, None) @ddt.data("/teams", "/emojis/signs", "/gists", "/gists/42") def test_dead_segment(self, template): route = self.router.find(template) self.assertIs(route, None) def test_malformed_pattern(self): route = self.router.find("/repos/racker/falcon/compare/foo") self.assertIs(route, None) route = self.router.find("/repos/racker/falcon/compare/foo/full") self.assertIs(route, None) def test_literal(self): resource, method_map, params = self.router.find("/user/memberships") self.assertEqual(resource.resource_id, 8) def test_variable(self): resource, method_map, params = self.router.find("/teams/42") self.assertEqual(resource.resource_id, 6) self.assertEqual(params, {"id": "42"}) resource, method_map, params = self.router.find("/emojis/signs/stop") self.assertEqual(params, {"id": "stop"}) resource, method_map, params = self.router.find("/gists/42/raw") self.assertEqual(params, {"id": "42"}) @ddt.data( ("/teams/default", 19), ("/teams/default/members", 7), ("/teams/foo", 6), ("/teams/foo/members", 7), ("/gists/first", 20), ("/gists/first/raw", 18), ("/gists/first/pdf", 21), ("/gists/1776/pdf", 21), ("/emojis/signs/78", 13), ("/emojis/signs/78/small", 22), ) @ddt.unpack def test_literal_vs_variable(self, path, expected_id): resource, method_map, params = self.router.find(path) self.assertEqual(resource.resource_id, expected_id) @ddt.data( # Misc. "/this/does/not/exist", "/user/bogus", "/repos/racker/falcon/compare/johndoe:master...janedoe:dev/bogus", # Literal vs variable (teams) "/teams", "/teams/42/members/undefined", "/teams/42/undefined", "/teams/42/undefined/segments", "/teams/default/members/undefined", "/teams/default/members/thing/undefined", "/teams/default/members/thing/undefined/segments", "/teams/default/undefined", "/teams/default/undefined/segments", # Literal vs variable (emojis) "/emojis/signs", "/emojis/signs/0/small", "/emojis/signs/0/undefined", "/emojis/signs/0/undefined/segments", "/emojis/signs/20/small", "/emojis/signs/20/undefined", "/emojis/signs/42/undefined", "/emojis/signs/78/undefined", ) def test_not_found(self, path): route = self.router.find(path) self.assertIs(route, None) def test_subsegment_not_found(self): route = self.router.find("/emojis/signs/0/x") self.assertIs(route, None) def test_multivar(self): resource, method_map, params = self.router.find("/repos/racker/falcon/commits") self.assertEqual(resource.resource_id, 4) self.assertEqual(params, {"org": "racker", "repo": "falcon"}) resource, method_map, params = self.router.find("/repos/racker/falcon/compare/all") self.assertEqual(resource.resource_id, 11) self.assertEqual(params, {"org": "racker", "repo": "falcon"}) @ddt.data(("", 5), ("/full", 10), ("/part", 15)) @ddt.unpack def test_complex(self, url_postfix, resource_id): uri = "/repos/racker/falcon/compare/johndoe:master...janedoe:dev" resource, method_map, params = self.router.find(uri + url_postfix) self.assertEqual(resource.resource_id, resource_id) self.assertEqual( params, { "org": "racker", "repo": "falcon", "usr0": "johndoe", "branch0": "master", "usr1": "janedoe", "branch1": "dev", }, ) @ddt.data(("", 16), ("/full", 17)) @ddt.unpack def test_complex_alt(self, url_postfix, resource_id): uri = "/repos/falconry/falcon/compare/johndoe:master" resource, method_map, params = self.router.find(uri + url_postfix) self.assertEqual(resource.resource_id, resource_id) self.assertEqual(params, {"org": "falconry", "repo": "falcon", "usr0": "johndoe", "branch0": "master"})