Skip to content

Commit

Permalink
Avoid to create unnecessary resources (aio-libs#2586)
Browse files Browse the repository at this point in the history
Do not create a new resource when adding a route with the same
name and path of an existing resource
  • Loading branch information
sheb committed Dec 13, 2017
1 parent bb9fc9d commit 001cc78
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGES/2586.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Avoid to create a new resource when adding a route with the same
name and path of the last added resource
15 changes: 15 additions & 0 deletions aiohttp/web_urldispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,10 @@ async def resolve(self, request):
else:
return None, allowed_methods

@abc.abstractmethod
def raw_match(self, path):
"""Perform a raw match against path"""

def __len__(self):
return len(self._routes)

Expand Down Expand Up @@ -332,6 +336,9 @@ def _match(self, path):
else:
return None

def raw_match(self, path):
return self._path == path

def get_info(self):
return {'path': self._path}

Expand Down Expand Up @@ -400,6 +407,9 @@ def _match(self, path):
return {key: unquote(value, unsafe='+') for key, value in
match.groupdict().items()}

def raw_match(self, path):
return self._formatter == path

def get_info(self):
return {'formatter': self._formatter,
'pattern': self._pattern}
Expand Down Expand Up @@ -830,6 +840,11 @@ def register_resource(self, resource):
def add_resource(self, path, *, name=None):
if path and not path.startswith('/'):
raise ValueError("path should be started with / or be empty")
# Reuse last added resource if path and name are the same
if self._resources:
resource = self._resources[-1]
if resource.name == name and resource.raw_match(path):
return resource
if not ('{' in path or '}' in path or ROUTE_RE.search(path)):
url = URL(path)
resource = PlainResource(url.raw_path, name=name)
Expand Down
20 changes: 20 additions & 0 deletions tests/test_web_urldispatcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,3 +342,23 @@ async def handler(_):
r = await client.head('/b')
assert r.status == 405
await r.release()


@pytest.mark.parametrize("path", [
'/a',
'/{a}',
])
def test_reuse_last_added_resource(path):
"""
Test that adding a route with the same name and path of the last added
resource doesn't create a new resource.
"""
app = web.Application()

async def handler(request):
return web.Response()

app.router.add_get(path, handler, name="a")
app.router.add_post(path, handler, name="a")

assert len(app.router.resources()) == 1

0 comments on commit 001cc78

Please sign in to comment.