[Python-modules-commits] [python-aiohttp] 01/03: Import python-aiohttp_1.1.5.orig.tar.gz

Piotr Ożarowski piotr at moszumanska.debian.org
Fri Nov 18 19:01:17 UTC 2016


This is an automated email from the git hooks/post-receive script.

piotr pushed a commit to branch master
in repository python-aiohttp.

commit 98fe54bd7567469b73bb93caa7ea443afd70e309
Author: Piotr Ożarowski <piotr at debian.org>
Date:   Fri Nov 18 19:57:41 2016 +0100

    Import python-aiohttp_1.1.5.orig.tar.gz
---
 CHANGES.rst                                 | 20 +++++++
 CONTRIBUTORS.txt                            |  1 +
 PKG-INFO                                    | 22 +++++++-
 aiohttp.egg-info/PKG-INFO                   | 22 +++++++-
 aiohttp.egg-info/SOURCES.txt                |  1 +
 aiohttp/__init__.py                         |  2 +-
 aiohttp/client.py                           | 51 ++++--------------
 aiohttp/file_sender.py                      |  2 +-
 aiohttp/test_utils.py                       |  5 +-
 aiohttp/web.py                              |  1 +
 aiohttp/web_urldispatcher.py                | 52 +++++++++++-------
 docs/index.rst                              |  1 +
 docs/third_party.rst                        | 82 +++++++++++++++++++++++++++++
 docs/web.rst                                |  6 +--
 examples/background_tasks.py                |  1 +
 examples/client_auth.py                     |  1 +
 examples/client_json.py                     |  1 +
 examples/web_cookies.py                     |  1 +
 examples/web_srv.py                         |  1 +
 setup.cfg                                   |  2 +-
 tests/test_client_functional.py             | 18 +++++++
 tests/test_py35/test_cbv35.py               |  1 +
 tests/test_py35/test_client.py              |  1 +
 tests/test_py35/test_client_websocket_35.py |  1 +
 tests/test_py35/test_resp.py                |  1 +
 tests/test_py35/test_web_websocket_35.py    |  1 +
 tests/test_test_utils.py                    | 12 +++++
 tests/test_urldispatch.py                   | 36 ++++++++++---
 28 files changed, 269 insertions(+), 77 deletions(-)

diff --git a/CHANGES.rst b/CHANGES.rst
index 15c8fdd..5496dd0 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -1,6 +1,26 @@
 CHANGES
 =======
 
+1.1.5 (2016-11-16)
+------------------
+
+- Fix static file serving in fallback mode #1401
+
+1.1.4 (2016-11-14)
+------------------
+
+- Make `TestServer.make_url` compatible with `yarl.URL` #1389
+
+- Generate informative exception on redirects from server which
+  doesn't provide redirection headers #1396
+
+
+1.1.3 (2016-11-10)
+------------------
+
+- Support *root* resources for sub-applications #1379
+
+
 1.1.2 (2016-11-08)
 ------------------
 
diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt
index 4e92783..0a5a9a7 100644
--- a/CONTRIBUTORS.txt
+++ b/CONTRIBUTORS.txt
@@ -37,6 +37,7 @@ Chih-Yuan Chen
 Chris AtLee
 Chris Laws
 Chris Moore
+Christopher Schmitt
 Daniel García
 Daniel Nelson
 Danny Song
diff --git a/PKG-INFO b/PKG-INFO
index 7667c2e..589e88b 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: aiohttp
-Version: 1.1.2
+Version: 1.1.5
 Summary: http client/server for asyncio
 Home-page: https://github.com/KeepSafe/aiohttp/
 Author: Andrew Svetlov
@@ -161,6 +161,26 @@ Description: http client/server for asyncio
         CHANGES
         =======
         
+        1.1.5 (2016-11-16)
+        ------------------
+        
+        - Fix static file serving in fallback mode #1401
+        
+        1.1.4 (2016-11-14)
+        ------------------
+        
+        - Make `TestServer.make_url` compatible with `yarl.URL` #1389
+        
+        - Generate informative exception on redirects from server which
+          doesn't provide redirection headers #1396
+        
+        
+        1.1.3 (2016-11-10)
+        ------------------
+        
+        - Support *root* resources for sub-applications #1379
+        
+        
         1.1.2 (2016-11-08)
         ------------------
         
diff --git a/aiohttp.egg-info/PKG-INFO b/aiohttp.egg-info/PKG-INFO
index 7667c2e..589e88b 100644
--- a/aiohttp.egg-info/PKG-INFO
+++ b/aiohttp.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: aiohttp
-Version: 1.1.2
+Version: 1.1.5
 Summary: http client/server for asyncio
 Home-page: https://github.com/KeepSafe/aiohttp/
 Author: Andrew Svetlov
@@ -161,6 +161,26 @@ Description: http client/server for asyncio
         CHANGES
         =======
         
+        1.1.5 (2016-11-16)
+        ------------------
+        
+        - Fix static file serving in fallback mode #1401
+        
+        1.1.4 (2016-11-14)
+        ------------------
+        
+        - Make `TestServer.make_url` compatible with `yarl.URL` #1389
+        
+        - Generate informative exception on redirects from server which
+          doesn't provide redirection headers #1396
+        
+        
+        1.1.3 (2016-11-10)
+        ------------------
+        
+        - Support *root* resources for sub-applications #1379
+        
+        
         1.1.2 (2016-11-08)
         ------------------
         
diff --git a/aiohttp.egg-info/SOURCES.txt b/aiohttp.egg-info/SOURCES.txt
index 4d9931e..5ae2b03 100644
--- a/aiohttp.egg-info/SOURCES.txt
+++ b/aiohttp.egg-info/SOURCES.txt
@@ -65,6 +65,7 @@ docs/server.rst
 docs/spelling_wordlist.txt
 docs/streams.rst
 docs/testing.rst
+docs/third_party.rst
 docs/tutorial.rst
 docs/web.rst
 docs/web_reference.rst
diff --git a/aiohttp/__init__.py b/aiohttp/__init__.py
index 51d6f1b..057e9e8 100644
--- a/aiohttp/__init__.py
+++ b/aiohttp/__init__.py
@@ -1,4 +1,4 @@
-__version__ = '1.1.2'
+__version__ = '1.1.5'
 
 # Deprecated, keep it here for a while for backward compatibility.
 import multidict  # noqa
diff --git a/aiohttp/client.py b/aiohttp/client.py
index 900a96c..6c5d029 100644
--- a/aiohttp/client.py
+++ b/aiohttp/client.py
@@ -92,45 +92,9 @@ class ClientSession:
                 context['source_traceback'] = self._source_traceback
             self._loop.call_exception_handler(context)
 
-    def request(self, method, url, *,
-                params=None,
-                data=None,
-                headers=None,
-                skip_auto_headers=None,
-                auth=None,
-                allow_redirects=True,
-                max_redirects=10,
-                encoding='utf-8',
-                version=None,
-                compress=None,
-                chunked=None,
-                expect100=False,
-                read_until_eof=True,
-                proxy=None,
-                proxy_auth=None,
-                timeout=5*60):
+    def request(self, method, url, **kwargs):
         """Perform HTTP request."""
-
-        return _RequestContextManager(
-            self._request(
-                method,
-                url,
-                params=params,
-                data=data,
-                headers=headers,
-                skip_auto_headers=skip_auto_headers,
-                auth=auth,
-                allow_redirects=allow_redirects,
-                max_redirects=max_redirects,
-                encoding=encoding,
-                version=version,
-                compress=compress,
-                chunked=chunked,
-                expect100=expect100,
-                read_until_eof=read_until_eof,
-                proxy=proxy,
-                proxy_auth=proxy_auth,
-                timeout=timeout))
+        return _RequestContextManager(self._request(method, url, **kwargs))
 
     @asyncio.coroutine
     def _request(self, method, url, *,
@@ -241,8 +205,14 @@ class ClientSession:
                     if headers.get(hdrs.CONTENT_LENGTH):
                         headers.pop(hdrs.CONTENT_LENGTH)
 
-                r_url = URL(resp.headers.get(hdrs.LOCATION) or
-                            resp.headers.get(hdrs.URI))
+                r_url = (resp.headers.get(hdrs.LOCATION) or
+                         resp.headers.get(hdrs.URI))
+                if r_url is None:
+                    raise RuntimeError("{0.method} {0.url_obj} returns "
+                                       "a redirect [{0.status}] status "
+                                       "but response lacks a Location "
+                                       "or URI HTTP header".format(resp))
+                r_url = URL(r_url)
 
                 scheme = r_url.scheme
                 if scheme not in ('http', 'https', ''):
@@ -510,6 +480,7 @@ class ClientSession:
         def __aexit__(self, exc_type, exc_val, exc_tb):
             yield from self.close()
 
+
 if PY_35:
     from collections.abc import Coroutine
     base = Coroutine
diff --git a/aiohttp/file_sender.py b/aiohttp/file_sender.py
index e32821b..0717e0e 100644
--- a/aiohttp/file_sender.py
+++ b/aiohttp/file_sender.py
@@ -129,7 +129,7 @@ class FileSender:
                 count = count - chunk_size
                 if count <= 0:
                     break
-                chunk = fobj.read(count)
+                chunk = fobj.read(min(chunk_size, count))
         finally:
             resp.set_tcp_nodelay(True)
 
diff --git a/aiohttp/test_utils.py b/aiohttp/test_utils.py
index 44618e6..e17ae5c 100644
--- a/aiohttp/test_utils.py
+++ b/aiohttp/test_utils.py
@@ -74,8 +74,9 @@ class TestServer:
                                                           ssl=self._ssl)
 
     def make_url(self, path):
-        assert path.startswith('/')
-        return URL(str(self._root) + path)
+        url = URL(path)
+        assert not url.is_absolute()
+        return self._root.join(url)
 
     @asyncio.coroutine
     def close(self):
diff --git a/aiohttp/web.py b/aiohttp/web.py
index f80ba0c..2e838ce 100644
--- a/aiohttp/web.py
+++ b/aiohttp/web.py
@@ -455,5 +455,6 @@ def main(argv):
     run_app(app, host=args.hostname, port=args.port)
     arg_parser.exit(message="Stopped\n")
 
+
 if __name__ == "__main__":  # pragma: no branch
     main(sys.argv[1:])  # pragma: no cover
diff --git a/aiohttp/web_urldispatcher.py b/aiohttp/web_urldispatcher.py
index aa644b9..4cf8853 100644
--- a/aiohttp/web_urldispatcher.py
+++ b/aiohttp/web_urldispatcher.py
@@ -76,6 +76,9 @@ class AbstractResource(Sized, Iterable):
     def get_info(self):
         """Return a dict with additional info useful for introspection"""
 
+    def freeze(self):
+        pass
+
 
 class AbstractRoute(abc.ABC):
 
@@ -286,14 +289,18 @@ class PlainResource(Resource):
 
     def __init__(self, path, *, name=None):
         super().__init__(name=name)
-        assert path.startswith('/')
+        assert not path or path.startswith('/')
         self._path = path
 
+    def freeze(self):
+        if not self._path:
+            self._path = '/'
+
     def add_prefix(self, prefix):
         assert prefix.startswith('/')
-        assert prefix.endswith('/')
+        assert not prefix.endswith('/')
         assert len(prefix) > 1
-        self._path = prefix + self._path[1:]
+        self._path = prefix + self._path
 
     def _match(self, path):
         # string comparison is about 10 times faster than regexp matching
@@ -329,10 +336,10 @@ class DynamicResource(Resource):
 
     def add_prefix(self, prefix):
         assert prefix.startswith('/')
-        assert prefix.endswith('/')
+        assert not prefix.endswith('/')
         assert len(prefix) > 1
-        self._pattern = re.compile(re.escape(prefix)+self._pattern.pattern[2:])
-        self._formatter = prefix + self._formatter[1:]
+        self._pattern = re.compile(re.escape(prefix)+self._pattern.pattern)
+        self._formatter = prefix + self._formatter
 
     def _match(self, path):
         match = self._pattern.fullmatch(path)
@@ -363,18 +370,16 @@ class DynamicResource(Resource):
 class PrefixResource(AbstractResource):
 
     def __init__(self, prefix, *, name=None):
-        assert prefix.startswith('/'), prefix
-        assert prefix.endswith('/'), prefix
+        assert not prefix or prefix.startswith('/'), prefix
+        assert prefix in ('', '/') or not prefix.endswith('/'), prefix
         super().__init__(name=name)
         self._prefix = quote(prefix, safe='/')
-        self._prefix_len = len(self._prefix)
 
     def add_prefix(self, prefix):
         assert prefix.startswith('/')
-        assert prefix.endswith('/')
+        assert not prefix.endswith('/')
         assert len(prefix) > 1
-        self._prefix = prefix + self._prefix[1:]
-        self._prefix_len = len(self._prefix)
+        self._prefix = prefix + self._prefix
 
 
 class StaticResource(PrefixResource):
@@ -415,6 +420,7 @@ class StaticResource(PrefixResource):
             filename = str(filename)
         while filename.startswith('/'):
             filename = filename[1:]
+        filename = '/' + filename
         url = self._prefix + quote(filename, safe='/')
         return URL(url)
 
@@ -440,7 +446,7 @@ class StaticResource(PrefixResource):
         if method not in allowed_methods:
             return None, allowed_methods
 
-        match_dict = {'filename': unquote(path[self._prefix_len:])}
+        match_dict = {'filename': unquote(path[len(self._prefix)+1:])}
         return (UrlMappingMatchInfo(match_dict, self._routes[method]),
                 allowed_methods)
         yield  # pragma: no cover
@@ -775,8 +781,8 @@ class UrlDispatcher(AbstractRouter, collections.abc.Mapping):
         self._resources.append(resource)
 
     def add_resource(self, path, *, name=None):
-        if not path.startswith('/'):
-            raise ValueError("path should be started with /")
+        if path and not path.startswith('/'):
+            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)
@@ -830,8 +836,8 @@ class UrlDispatcher(AbstractRouter, collections.abc.Mapping):
         """
         # TODO: implement via PrefixedResource, not ResourceAdapter
         assert prefix.startswith('/')
-        if not prefix.endswith('/'):
-            prefix += '/'
+        if prefix.endswith('/'):
+            prefix = prefix[:-1]
         resource = StaticResource(prefix, path,
                                   name=name,
                                   expect_handler=expect_handler,
@@ -879,13 +885,19 @@ class UrlDispatcher(AbstractRouter, collections.abc.Mapping):
         return self.add_route(hdrs.METH_DELETE, *args, **kwargs)
 
     def add_subapp(self, prefix, subapp):
-        assert prefix.startswith('/')
-        if not prefix.endswith('/'):
-            prefix += '/'
         if subapp.frozen:
             raise RuntimeError("Cannod 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)
         subapp.freeze()
         return resource
+
+    def freeze(self):
+        super().freeze()
+        for resource in self._resources:
+            resource.freeze()
diff --git a/docs/index.rst b/docs/index.rst
index e531137..786bf82 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -207,6 +207,7 @@ Contents
    testing
    deployment
    faq
+   third_party
    essays
    contributing
    changes
diff --git a/docs/third_party.rst b/docs/third_party.rst
new file mode 100644
index 0000000..fadf6f2
--- /dev/null
+++ b/docs/third_party.rst
@@ -0,0 +1,82 @@
+Third-Party libraries
+=====================
+
+
+aiohttp is not the library for making HTTP requests and creating WEB
+server only.
+
+It is the grand basement for libraries built *on top* of aiohttp.
+
+This page is a list of these tools.
+
+Please feel free to add your open sourced library if it's not enlisted
+yet by making Pull Request to https://github.com/KeepSafe/aiohttp/
+
+- Q. Why do you might want to include your awesome library into the list?
+
+- A. Just because the list increases your library visibility. People
+  will have an easy way to find it.
+
+
+Officially supported
+--------------------
+
+This list contains libraries which are supported by *aio-libs* team
+and located on https://github.com/aio-libs
+
+
+aiohttp extensions
+^^^^^^^^^^^^^^^^^^
+
+- `aiohttp-session <https://github.com/aio-libs/aiohttp-session>`_
+   provides sessions for :mod:`aiohttp.web`.
+
+- `aiohttp-debugtoolbar <https://github.com/aio-libs/aiohttp-debugtoolbar>`_
+   is a library for *debug toolbar* support for :mod:`aiohttp.web`.
+
+- `aiohttp-security <https://github.com/aio-libs/aiohttp-security>`_
+   auth and permissions for :mod:`aiohttp.web`.
+
+
+Database drivers
+^^^^^^^^^^^^^^^^
+
+- `aiopg <https://github.com/aio-libs/aiopg>`_ PostgreSQL async driver.
+
+- `aiomysql <https://github.com/aio-libs/aiomysql>`_ MySql async driver.
+
+- `aioredis <https://github.com/aio-libs/aioredis>`_ Redis async driver.
+
+
+Approved third-party libraries
+------------------------------
+
+The libraries are not part of ``aio-libs`` but they are proven to be very
+well written and highly recommended for usage.
+
+- `uvloop <https://github.com/MagicStack/uvloop>`_ Ultra fast
+  implementation of asyncio event loop on top of ``libuv``.
+
+  We are highly recommending to use it instead of standard ``asyncio``.
+
+Database drivers
+^^^^^^^^^^^^^^^^
+
+- `asyncpg <https://github.com/MagicStack/asyncpg>`_ Another
+  PostgreSQL async driver. It's much faster than ``aiopg`` but it is
+  not drop-in replacement -- the API is different. Anyway please take
+  a look on it -- the driver is really incredible fast.
+
+
+Others
+------
+
+The list of libs which are exists but not enlisted in former categories.
+
+They are may be perfect or not -- we don't know.
+
+Please add your library reference here first and after some time
+period ask to raise he status.
+
+- `aiohttp-cache <https://github.com/cr0hn/aiohttp-cache>`_ A cache
+  system for aiohttp server.
diff --git a/docs/web.rst b/docs/web.rst
index 20d91d8..6f2cdb2 100644
--- a/docs/web.rst
+++ b/docs/web.rst
@@ -955,7 +955,7 @@ connect it to main app with prefix by
    admin = web.Application()
    # setup admin routes, signals and middlewares
 
-   app.add_subapp('/admin/', admin)
+   app.router.add_subapp('/admin/', admin)
 
 Middlewares and signals from ``app`` and ``admin`` are chained.
 
@@ -983,9 +983,9 @@ Url reversing for sub-applications should generate urls with proper prefix.
 But for getting URL sub-application's router should be used::
 
    admin = web.Application()
-   admin.add_get('/resource', handler, name='name')
+   admin.router.add_get('/resource', handler, name='name')
 
-   app.add_subapp('/admin/', admin)
+   app.router.add_subapp('/admin/', admin)
 
    url = admin.router['name'].url_for()
 
diff --git a/examples/background_tasks.py b/examples/background_tasks.py
index 00d54b1..b7dbcf8 100755
--- a/examples/background_tasks.py
+++ b/examples/background_tasks.py
@@ -5,6 +5,7 @@ import asyncio
 import aioredis
 from aiohttp.web import Application, WebSocketResponse, run_app
 
+
 async def websocket_handler(request):
     ws = WebSocketResponse()
     await ws.prepare(request)
diff --git a/examples/client_auth.py b/examples/client_auth.py
index c6e80e8..4e0b734 100755
--- a/examples/client_auth.py
+++ b/examples/client_auth.py
@@ -2,6 +2,7 @@ import asyncio
 
 import aiohttp
 
+
 async def fetch(session):
     print('Query http://httpbin.org/basic-auth/andrew/password')
     async with session.get(
diff --git a/examples/client_json.py b/examples/client_json.py
index 79df6f5..db6d998 100755
--- a/examples/client_json.py
+++ b/examples/client_json.py
@@ -2,6 +2,7 @@ import asyncio
 
 import aiohttp
 
+
 async def fetch(session):
     print('Query http://httpbin.org/get')
     async with session.get(
diff --git a/examples/web_cookies.py b/examples/web_cookies.py
index d4a7c66..adb1fb9 100755
--- a/examples/web_cookies.py
+++ b/examples/web_cookies.py
@@ -47,6 +47,7 @@ def init(loop):
     app.router.add_get('/logout', logout)
     return app
 
+
 loop = asyncio.get_event_loop()
 app = loop.run_until_complete(init(loop))
 web.run_app(app)
diff --git a/examples/web_srv.py b/examples/web_srv.py
index 56e2f1f..fe9faf0 100755
--- a/examples/web_srv.py
+++ b/examples/web_srv.py
@@ -7,6 +7,7 @@ import textwrap
 
 from aiohttp.web import Application, Response, StreamResponse, run_app
 
+
 async def intro(request):
     txt = textwrap.dedent("""\
         Type {url}/hello/John  {url}/simple or {url}/change_body
diff --git a/setup.cfg b/setup.cfg
index 17b944d..c1c1081 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -5,7 +5,7 @@ zip_ok = false
 ignore = N801,N802,N803,E226
 
 [tool:pytest]
-timeout = 5
+timeout = 10
 
 [isort]
 known_third_party = jinja2
diff --git a/tests/test_client_functional.py b/tests/test_client_functional.py
index ca3ba68..a515b43 100644
--- a/tests/test_client_functional.py
+++ b/tests/test_client_functional.py
@@ -1696,3 +1696,21 @@ def test_redirect_to_absolute_url(loop, test_client):
     resp = yield from client.get('/redirect')
     assert 200 == resp.status
     resp.close()
+
+
+ at asyncio.coroutine
+def test_redirect_without_location_header(loop, test_client):
+    @asyncio.coroutine
+    def handler_redirect(request):
+        return web.Response(status=301)
+
+    app = web.Application(loop=loop)
+    app.router.add_route('GET', '/redirect', handler_redirect)
+    client = yield from test_client(app)
+
+    with pytest.raises(RuntimeError) as ctx:
+        yield from client.get('/redirect')
+    assert str(ctx.value) == ('GET http://127.0.0.1:{}/redirect returns '
+                              'a redirect [301] status but response lacks '
+                              'a Location or URI HTTP header'
+                              .format(client.port))
diff --git a/tests/test_py35/test_cbv35.py b/tests/test_py35/test_cbv35.py
index f056a22..ec506be 100644
--- a/tests/test_py35/test_cbv35.py
+++ b/tests/test_py35/test_cbv35.py
@@ -3,6 +3,7 @@ from unittest import mock
 from aiohttp import web
 from aiohttp.web_urldispatcher import View
 
+
 async def test_render_ok():
     resp = web.Response(text='OK')
 
diff --git a/tests/test_py35/test_client.py b/tests/test_py35/test_client.py
index 84a1f8e..6173e93 100644
--- a/tests/test_py35/test_client.py
+++ b/tests/test_py35/test_client.py
@@ -3,6 +3,7 @@ import pytest
 import aiohttp
 from aiohttp import web
 
+
 async def test_async_with_session(loop):
     async with aiohttp.ClientSession(loop=loop) as session:
         pass
diff --git a/tests/test_py35/test_client_websocket_35.py b/tests/test_py35/test_client_websocket_35.py
index 55e9f60..80e597a 100644
--- a/tests/test_py35/test_client_websocket_35.py
+++ b/tests/test_py35/test_client_websocket_35.py
@@ -3,6 +3,7 @@ import pytest
 import aiohttp
 from aiohttp import helpers, web
 
+
 async def test_client_ws_async_for(loop, test_client):
     items = ['q1', 'q2', 'q3']
 
diff --git a/tests/test_py35/test_resp.py b/tests/test_py35/test_resp.py
index fb3b575..7daac91 100644
--- a/tests/test_py35/test_resp.py
+++ b/tests/test_py35/test_resp.py
@@ -7,6 +7,7 @@ import aiohttp
 from aiohttp import web
 from aiohttp.client import _RequestContextManager
 
+
 async def test_await(test_server, loop):
 
     async def handler(request):
diff --git a/tests/test_py35/test_web_websocket_35.py b/tests/test_py35/test_web_websocket_35.py
index db34e31..9152b65 100644
--- a/tests/test_py35/test_web_websocket_35.py
+++ b/tests/test_py35/test_web_websocket_35.py
@@ -2,6 +2,7 @@ import aiohttp
 from aiohttp import helpers, web
 from aiohttp._ws_impl import WSMsgType
 
+
 async def test_server_ws_async_for(loop, test_server):
     closed = helpers.create_future(loop)
 
diff --git a/tests/test_test_utils.py b/tests/test_test_utils.py
index 668a3d7..d4327aa 100644
--- a/tests/test_test_utils.py
+++ b/tests/test_test_utils.py
@@ -3,6 +3,7 @@ from unittest import mock
 
 import pytest
 from multidict import CIMultiDict, CIMultiDictProxy
+from yarl import URL
 
 import aiohttp
 from aiohttp import web, web_reqrep
@@ -266,3 +267,14 @@ def test_client_host_mutually_exclusive_with_server(loop):
 def test_client_unsupported_arg():
     with pytest.raises(TypeError):
         _TestClient('string')
+
+
+def test_server_make_url_yarl_compatibility(loop):
+    app = _create_example_app(loop)
+    with _TestServer(app) as server:
+        make_url = server.make_url
+        assert make_url(URL('/foo')) == make_url('/foo')
+        with pytest.raises(AssertionError):
+            make_url('http://foo.com')
+        with pytest.raises(AssertionError):
+            make_url(URL('http://foo.com'))
diff --git a/tests/test_urldispatch.py b/tests/test_urldispatch.py
index 825c3be..a3819d0 100644
--- a/tests/test_urldispatch.py
+++ b/tests/test_urldispatch.py
@@ -418,19 +418,19 @@ def test_contains(router):
 def test_static_repr(router):
     router.add_static('/get', os.path.dirname(aiohttp.__file__),
                       name='name')
-    assert re.match(r"<StaticResource 'name' /get/", repr(router['name']))
+    assert re.match(r"<StaticResource 'name' /get", repr(router['name']))
 
 
 def test_static_adds_slash(router):
     route = router.add_static('/prefix',
                               os.path.dirname(aiohttp.__file__))
-    assert '/prefix/' == route._prefix
+    assert '/prefix' == route._prefix
 
 
-def test_static_dont_add_trailing_slash(router):
+def test_static_remove_trailing_slash(router):
     route = router.add_static('/prefix/',
                               os.path.dirname(aiohttp.__file__))
-    assert '/prefix/' == route._prefix
+    assert '/prefix' == route._prefix
 
 
 @asyncio.coroutine
@@ -805,7 +805,7 @@ def test_static_resource_get_info(router):
     directory = pathlib.Path(aiohttp.__file__).parent
     resource = router.add_static('/st', directory)
     assert resource.get_info() == {'directory': directory,
-                                   'prefix': '/st/'}
+                                   'prefix': '/st'}
 
 
 @asyncio.coroutine
@@ -910,7 +910,7 @@ def test_url_for_in_resource_route(router):
 def test_subapp_get_info(router, loop):
     subapp = web.Application(loop=loop)
     resource = router.add_subapp('/pre', subapp)
-    assert resource.get_info() == {'prefix': '/pre/', 'app': subapp}
+    assert resource.get_info() == {'prefix': '/pre', 'app': subapp}
 
 
 def test_subapp_url(router, loop):
@@ -931,7 +931,7 @@ def test_subapp_repr(router, loop):
     subapp = web.Application(loop=loop)
     resource = router.add_subapp('/pre', subapp)
     assert repr(resource).startswith(
-        '<PrefixedSubAppResource /pre/ -> <Application')
+        '<PrefixedSubAppResource /pre -> <Application')
 
 
 def test_subapp_len(router, loop):
@@ -989,3 +989,25 @@ def test_set_options_route(router):
 def test_dynamic_url_with_name_started_from_undescore(router):
     route = router.add_route('GET', '/get/{_name}', make_handler())
     assert URL('/get/John') == route.url_for(_name='John')
+
+
+def test_cannot_add_subapp_with_empty_prefix(router, loop):
+    subapp = web.Application(loop=loop)
+    with pytest.raises(ValueError):
+        router.add_subapp('', subapp)
+
+
+def test_cannot_add_subapp_with_slash_prefix(router, loop):
+    subapp = web.Application(loop=loop)
+    with pytest.raises(ValueError):
+        router.add_subapp('/', subapp)
+
+
+ at asyncio.coroutine
+def test_convert_empty_path_to_slash_on_freezing(router):
+    handler = make_handler()
+    route = router.add_get('', handler)
+    resource = route.resource
+    assert resource.get_info() == {'path': ''}
+    router.freeze()
+    assert resource.get_info() == {'path': '/'}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-aiohttp.git



More information about the Python-modules-commits mailing list