class RouterTest(TestCase): def setUp(self): self.router = Router() def test_match_static_routes(self): def target_func(): pass self.router.add('^/tests/$', 'GET', target_func) test_env = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/tests/'} actual_target, actual_args = self.router.match(test_env) self.assertEqual(actual_target, target_func) self.assertEqual(actual_args, ()) def test_match_dynamic_routes_with_numbers(self): def target_func(): pass self.router.add('^/tests/(?P<year>\d{4})/$', 'GET', target_func) test_env = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/tests/2015/'} actual_target, actual_args = self.router.match(test_env) self.assertEqual(actual_target, target_func) self.assertEqual(actual_args, ('2015', )) def test_match_dynamic_routes_with_string(self): def target_func(): pass self.router.add('^/tests/(?P<name>\w+)/$', 'GET', target_func) test_env = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/tests/kobin/'} actual_target, actual_args = self.router.match(test_env) self.assertEqual(actual_target, target_func) self.assertEqual(actual_args, ('kobin', ))
def setUp(self): self.router = Router() def index() -> Response: return Response('hello world') def user_detail(user_id: int) -> Response: return Response(f'hello user{user_id}') self.router.add('/', 'GET', 'top', index) self.router.add('/users/{user_id}', 'GET', 'user-detail', user_detail)
class RouterTests(TestCase): def setUp(self): self.router = Router() def test_match_dynamic_routes_with_casted_number(self): def dummy_func(year: int) -> int: return year self.router.add('GET', '/tests/{year}', 'hoge', dummy_func) test_env = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/tests/2015/'} actual_target, actual_args = self.router.match(test_env) self.assertEqual(actual_args, {'year': 2015}) def test_match_dynamic_routes_with_string(self): def dummy_func(name): return name self.router.add('GET', '/tests/{name}', 'hoge', dummy_func) test_env = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/tests/kobin/'} actual_target, actual_args = self.router.match(test_env) self.assertEqual(actual_args, {'name': 'kobin'}) def test_404_not_found(self): def dummy_func(name): return name self.router.add('GET', '/tests/{name}', 'hoge', dummy_func) test_env = {'REQUEST_METHOD': 'GET', 'PATH_INFO': '/this_is_not_found'} self.assertRaises(HTTPError, self.router.match, test_env)
class ReverseRoutingTests(TestCase): def setUp(self): self.router = Router() def index() -> Response: return Response('hello world') def user_detail(user_id: int) -> Response: return Response(f'hello user{user_id}') self.router.add('/', 'GET', 'top', index) self.router.add('/users/{user_id}', 'GET', 'user-detail', user_detail) def test_reverse_route_without_url_vars(self): actual = self.router.reverse('top') expected = '/' self.assertEqual(actual, expected) def test_reverse_route_with_url_vars(self): actual = self.router.reverse('user-detail', user_id=1) expected = '/users/1' self.assertEqual(actual, expected) def test_reverse_not_match(self): actual = self.router.reverse('foobar', foo=1) expected = None self.assertEqual(actual, expected)
class RouterTest(TestCase): def setUp(self): self.router = Router() def test_split_routes(self): input_route = '/user/mypage' expected_route = ['user', 'mypage'] actual_route = self.router._split_routes(input_route) self.assertListEqual(actual_route, expected_route) def test_add_func_when_input_static(self): def target_func(): pass self.router.add('/user/', 'GET', target_func) actual = self.router.static self.assertIn('GET', actual) self.assertIn('/user/', actual['GET']) expected_tuple = (target_func, None) self.assertTupleEqual(actual['GET']['/user/'], expected_tuple)
class Kobin(object): def __init__(self): self.router = Router() def run(self, host: str='', port: int=8000): try: from wsgiref.simple_server import make_server httpd = make_server(host, port, self) print('Serving on port %d...' % port) httpd.serve_forever() except KeyboardInterrupt: print('Goodbye.') def add_route(self, route: Route): self.router.add(route.rule, route.method, route) def route(self, path: str=None, method: str='GET', callback: Callable[..., str]=None) -> Callable[..., str]: def decorator(callback_func): route = Route(path, method, callback_func) self.add_route(route) return callback_func return decorator(callback) if callback else decorator def _handle(self, environ: Dict): route, args = self.router.match(environ) return route.call(*args) def wsgi(self, environ: Dict, start_response) -> List[str]: out = self._handle(environ) if isinstance(out, str): out = out.encode('utf-8') start_response('200 OK', [('Content-Type', 'text/html')]) return [out] def __call__(self, environ: Dict, start_response) -> List[str]: """It is called when receive http request.""" return self.wsgi(environ, start_response)
def setUp(self): self.router = Router()
def test_405_method_not_allowed(self): r = Router() r.add('/tests/{name}', 'GET', 'hoge', view_str) with self.assertRaises(HTTPError) as cm: r.match('/tests/kobin', 'POST') self.assertEqual('405 Method Not Allowed', cm.exception.status)
def test_404_not_found(self): r = Router() r.add('/tests/{name}', 'GET', 'hoge', view_str) with self.assertRaises(HTTPError) as cm: r.match('/this_is_not_found', 'GET') self.assertEqual('404 Not Found', cm.exception.status)
def test_match_dynamic_routes_with_string(self): r = Router() r.add('/tests/{name}', 'GET', 'hoge', view_str) actual_target, actual_args = r.match('/tests/kobin/', 'GET') self.assertEqual(actual_args, {'name': 'kobin'})
def test_match_dynamic_routes_with_casted_number(self): r = Router() r.add('/tests/{year}', 'GET', 'hoge', view_int) actual_target, actual_args = r.match('/tests/2015/', 'GET') self.assertEqual(actual_args, {'year': 2015})
def __init__(self): self.router = Router()