Skip to content

Commit

Permalink
remove Application dependency from UrlDispatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
Nikolay Kim committed Dec 26, 2016
1 parent 70fad8e commit dc13304
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 30 deletions.
20 changes: 19 additions & 1 deletion aiohttp/web.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from .web_reqrep import * # noqa
from .web_server import Server
from .web_urldispatcher import * # noqa
from .web_urldispatcher import PrefixedSubAppResource, _wrap_add_subbapp
from .web_ws import * # noqa

__all__ = (web_reqrep.__all__ +
Expand All @@ -39,7 +40,7 @@ def __init__(self, *, logger=web_logger, loop=None,
router = web_urldispatcher.UrlDispatcher()
assert isinstance(router, AbstractRouter), router

router.post_init(self)
router.add_subapp = _wrap_add_subbapp(self)

if debug is ...:
debug = loop.get_debug()
Expand Down Expand Up @@ -125,6 +126,23 @@ def handler(app):
reg_handler('on_shutdown')
reg_handler('on_cleanup')

def add_subapp(self, prefix, subapp):
if self.frozen:
raise RuntimeError(
"Cannot add sub application to frozen application")
if subapp.frozen:
raise RuntimeError("Cannot add frozen application")
if prefix.endswith('/'):
prefix = prefix[:-1]
if prefix in ('', '/'):
raise ValueError("Prefix cannot be empty")

resource = PrefixedSubAppResource(prefix, subapp)
self.reg_resource(resource)
subapp._reg_subapp_signals(subapp)
subapp.freeze()
return resource

@property
def on_response_prepare(self):
return self._on_response_prepare
Expand Down
41 changes: 19 additions & 22 deletions aiohttp/web_urldispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -714,11 +714,6 @@ def __init__(self):
super().__init__()
self._resources = []
self._named_resources = {}
self._app = None

def post_init(self, app):
assert app is not None
self._app = app

@asyncio.coroutine
def resolve(self, request):
Expand Down Expand Up @@ -759,16 +754,13 @@ def routes(self):
def named_resources(self):
return MappingProxyType(self._named_resources)

def _reg_resource(self, resource):
def reg_resource(self, resource):
assert isinstance(resource, AbstractResource), \
'Instance of AbstractResource class is required, got {!r}'.format(
resource)
if self._app is None:
raise RuntimeError(".post_init() should be called before "
"first resource registering")
if self.frozen:
raise RuntimeError("Cannot register a resource into "
"frozen router.")
raise RuntimeError(
"Cannot register a resource into frozen router.")

name = resource.name

Expand All @@ -792,7 +784,7 @@ def add_resource(self, path, *, name=None):
raise ValueError("path should be started with / or be empty")
if not ('{' in path or '}' in path or self.ROUTE_RE.search(path)):
resource = PlainResource(quote(path, safe='/'), name=name)
self._reg_resource(resource)
self.reg_resource(resource)
return resource

pattern = ''
Expand Down Expand Up @@ -823,7 +815,7 @@ def add_resource(self, path, *, name=None):
raise ValueError(
"Bad pattern '{}': {}".format(pattern, exc)) from None
resource = DynamicResource(compiled, formatter, name=name)
self._reg_resource(resource)
self.reg_resource(resource)
return resource

def add_route(self, method, path, handler,
Expand Down Expand Up @@ -852,7 +844,7 @@ def add_static(self, prefix, path, *, name=None, expect_handler=None,
response_factory=response_factory,
show_index=show_index,
follow_symlinks=follow_symlinks)
self._reg_resource(resource)
self.reg_resource(resource)
return resource

def add_head(self, *args, **kwargs):
Expand Down Expand Up @@ -891,20 +883,25 @@ def add_delete(self, *args, **kwargs):
"""
return self.add_route(hdrs.METH_DELETE, *args, **kwargs)

def add_subapp(self, prefix, subapp):
def freeze(self):
super().freeze()
for resource in self._resources:
resource.freeze()


def _wrap_add_subbapp(app):

def add_subapp(prefix, subapp):
if subapp.frozen:
raise RuntimeError("Cannod add frozen application")
raise RuntimeError("Cannot add frozen application")
if prefix.endswith('/'):
prefix = prefix[:-1]
if prefix in ('', '/'):
raise ValueError("Prefix cannot be empty")
resource = PrefixedSubAppResource(prefix, subapp)
self._reg_resource(resource)
self._app._reg_subapp_signals(subapp)
app.router.reg_resource(resource)
app._reg_subapp_signals(subapp)
subapp.freeze()
return resource

def freeze(self):
super().freeze()
for resource in self._resources:
resource.freeze()
return add_subapp
8 changes: 1 addition & 7 deletions tests/test_urldispatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
from aiohttp.test_utils import make_mocked_request
from aiohttp.web import HTTPMethodNotAllowed, HTTPNotFound, Response
from aiohttp.web_urldispatcher import (AbstractResource, ResourceRoute,
SystemRoute, UrlDispatcher, View,
SystemRoute, View,
_defaultExpectHandler)


Expand Down Expand Up @@ -1011,9 +1011,3 @@ def test_convert_empty_path_to_slash_on_freezing(router):
assert resource.get_info() == {'path': ''}
router.freeze()
assert resource.get_info() == {'path': '/'}


def test_add_to_non_initialized_router():
router = UrlDispatcher()
with pytest.raises(RuntimeError):
router.add_get('/', make_handler())

0 comments on commit dc13304

Please sign in to comment.