From 804764839913b74f46f15170190ebacd0506dd0a Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Tue, 22 Sep 2015 21:20:11 +0300 Subject: [PATCH 1/2] Implement RoutesView --- aiohttp/web_urldispatcher.py | 20 ++++++++++++++++++++ tests/test_urldispatch.py | 21 +++++++++++++++++++++ 2 files changed, 41 insertions(+) diff --git a/aiohttp/web_urldispatcher.py b/aiohttp/web_urldispatcher.py index 62851b6edca..e8c316d214e 100644 --- a/aiohttp/web_urldispatcher.py +++ b/aiohttp/web_urldispatcher.py @@ -363,6 +363,23 @@ def __repr__(self): ', '.join(sorted(self._allowed_methods)))) +class RoutesView: + + __slots__ = '_urls' + + def __init__(self, urls): + self._urls = urls + + def __len__(self): + return len(self._urls) + + def __iter__(self): + yield from self._urls + + def __contains__(self, route): + return route in self._urls + + class UrlDispatcher(AbstractRouter, collections.abc.Mapping): DYN = re.compile(r'^\{(?P[a-zA-Z][_a-zA-Z0-9]*)\}$') @@ -417,6 +434,9 @@ def __contains__(self, name): def __getitem__(self, name): return self._routes[name] + def routes(self): + return RoutesView(self._urls) + def register_route(self, route): assert isinstance(route, Route), 'Instance of Route class is required.' diff --git a/tests/test_urldispatch.py b/tests/test_urldispatch.py index b845e7d73c8..e3fd882dbef 100644 --- a/tests/test_urldispatch.py +++ b/tests/test_urldispatch.py @@ -605,3 +605,24 @@ def test_static_handle_exception(self): self.assertIs(exc, fut.exception()) self.assertFalse(loop.add_writer.called) self.assertFalse(loop.remove_writer.called) + + def fill_routes(self): + route1 = self.router.add_route('GET', '/plain', self.make_handler()) + route2 = self.router.add_route('GET', '/variable/{name}', + self.make_handler()) + route3 = self.router.add_static('/static', + os.path.dirname(aiohttp.__file__)) + return route1, route2, route3 + + def test_routes_view_len(self): + self.fill_routes() + self.assertEqual(3, len(self.router.routes())) + + def test_routes_view_iter(self): + routes = self.fill_routes() + self.assertEqual(list(routes), list(self.router.routes())) + + def test_routes_view_contains(self): + routes = self.fill_routes() + for route in routes: + self.assertIn(route, self.router.routes()) From 26e8b1ed9f26ac730ec9e0caf56863991326c26b Mon Sep 17 00:00:00 2001 From: Andrew Svetlov Date: Tue, 22 Sep 2015 22:50:38 +0300 Subject: [PATCH 2/2] Add docs --- docs/web.rst | 19 +++++++++++++++++++ docs/web_reference.rst | 20 ++++++++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/docs/web.rst b/docs/web.rst index f0ab25b4ca9..cdeb7ee3da5 100644 --- a/docs/web.rst +++ b/docs/web.rst @@ -179,6 +179,25 @@ so application developer can use classes if he wants:: That means the handler for ``'/path'`` is applied for every HTTP method. +Route views +----------- + +.. versionadded:: 0.18 + +For look on *all* routes in the router you may use +:meth:`UrlDispatcher.routes` method. + +You can iterate over routes in the router table:: + + for route in app.router.routes(): + print(route) + +or get router table size:: + + len(app.router.routes()) + + + Custom conditions for routes lookup ----------------------------------- diff --git a/docs/web_reference.rst b/docs/web_reference.rst index f6fd288dfab..13eeebba6ce 100644 --- a/docs/web_reference.rst +++ b/docs/web_reference.rst @@ -1085,6 +1085,26 @@ Router is any object that implements :class:`AbstractRouter` interface. The method don't raise :exc:`HTTPNotFound` and :exc:`HTTPMethodNotAllowed` anymore. + .. method:: routes() + + The method returns a *view* for *all* registered routes. + + The view is an object that allows to: + + 1. Get size of the router table:: + + len(app.router.routes()) + + 2. Iterate over registered routes:: + + for route in app.router.routes(): + print(route) + + 3. Make a check if the route is registered in the router table:: + + route in app.router.routes() + + .. versionadded:: 0.18 .. _aiohttp-web-route: