Repository: aio-libs/aiohttp

Issue:
Relax attribute lookup in warning about old-styled middleware
For class-based middleware like
```
class Middleware:
    async def __call__(self, app, handler):
          ...
```
there is no `__name__` attr.
Moreover I could imaging other situations where `__name__` doesn't exists.
It breaks web server starting.

Let's change `middleware.__name__` to `repr(middleware)`.

Bugfix should be done in `2.3` branch.


Discussion:
do you want me to do this?
Could you do it asap? Otherwise I'll make a fix myself.
Because I'm blocked on switching to new aiohttp release.
Another finding: even if I decorated the method the check doesn't work:
```
class Middleware:
    @web.middleware
    async def __call__(self, app, handler):
          ...
```
`_prepare_middlewares()` should look on `__func__` in case of methoddescriptor.
Sounds like you know what it needs  to do and need the fix. Maybe best if you fix it.
Deal

Resolving patch:
diff --git a/aiohttp/web.py b/aiohttp/web.py
--- a/aiohttp/web.py
+++ b/aiohttp/web.py
@@ -288,12 +288,10 @@ def _make_request(self, message, payload, protocol, writer, task,
     def _prepare_middleware(self):
         for m in reversed(self._middlewares):
             if getattr(m, '__middleware_version__', None) == 1:
-                # first argument is request or r and this is
-                # new-style middleware
                 yield m, True
             else:
-                warnings.warn('old-style middleware "{}" deprecated, '
-                              'see #2252'.format(m.__name__),
+                warnings.warn('old-style middleware "{!r}" deprecated, '
+                              'see #2252'.format(m),
                               DeprecationWarning, stacklevel=2)
                 yield m, False
 


Test patch:
diff --git a/tests/test_web_middleware.py b/tests/test_web_middleware.py
--- a/tests/test_web_middleware.py
+++ b/tests/test_web_middleware.py
@@ -1,4 +1,5 @@
 import asyncio
+import re
 
 import pytest
 
@@ -235,7 +236,11 @@ def middleware(request):
 
     assert len(warning_checker) == 1
     msg = str(warning_checker.list[0].message)
-    assert 'old-style middleware "middleware_factory" deprecated' in msg
+    assert re.match('^old-style middleware '
+                    '"<function test_old_style_middleware.<locals>.'
+                    'middleware_factory at 0x[0-9a-fA-F]+>" '
+                    'deprecated, see #2252$',
+                    msg)
 
 
 @asyncio.coroutine
@@ -288,5 +293,106 @@ def m_new2(request, handler):
         assert 'OK[new style 2][old style 2][new style 1][old style 1]' == txt
 
     assert len(w) == 2
-    assert 'old-style middleware "m_old2" deprecated' in str(w.list[0].message)
-    assert 'old-style middleware "m_old1" deprecated' in str(w.list[1].message)
+    tmpl = ('^old-style middleware '
+            '"<function test_mixed_middleware.<locals>.'
+            '{} at 0x[0-9a-fA-F]+>" '
+            'deprecated, see #2252$')
+    p1 = tmpl.format('m_old1')
+    p2 = tmpl.format('m_old2')
+
+    assert re.match(p2, str(w.list[0].message))
+    assert re.match(p1, str(w.list[1].message))
+
+
+@asyncio.coroutine
+def test_old_style_middleware_class(loop, test_client):
+    @asyncio.coroutine
+    def handler(request):
+        return web.Response(body=b'OK')
+
+    class Middleware:
+        @asyncio.coroutine
+        def __call__(self, app, handler):
+            @asyncio.coroutine
+            def middleware(request):
+                resp = yield from handler(request)
+                assert 200 == resp.status
+                resp.set_status(201)
+                resp.text = resp.text + '[old style middleware]'
+                return resp
+            return middleware
+
+    with pytest.warns(DeprecationWarning) as warning_checker:
+        app = web.Application()
+        app.middlewares.append(Middleware())
+        app.router.add_route('GET', '/', handler)
+        client = yield from test_client(app)
+        resp = yield from client.get('/')
+        assert 201 == resp.status
+        txt = yield from resp.text()
+        assert 'OK[old style middleware]' == txt
+
+    assert len(warning_checker) == 1
+    msg = str(warning_checker.list[0].message)
+    assert re.match('^old-style middleware '
+                    '"<test_web_middleware.test_old_style_middleware_class.'
+                    '<locals>.Middleware object '
+                    'at 0x[0-9a-fA-F]+>" deprecated, see #2252$', msg)
+
+
+@asyncio.coroutine
+def test_new_style_middleware_class(loop, test_client):
+    @asyncio.coroutine
+    def handler(request):
+        return web.Response(body=b'OK')
+
+    @web.middleware
+    class Middleware:
+        @asyncio.coroutine
+        def __call__(self, request, handler):
+            resp = yield from handler(request)
+            assert 200 == resp.status
+            resp.set_status(201)
+            resp.text = resp.text + '[new style middleware]'
+            return resp
+
+    with pytest.warns(None) as warning_checker:
+        app = web.Application()
+        app.middlewares.append(Middleware())
+        app.router.add_route('GET', '/', handler)
+        client = yield from test_client(app)
+        resp = yield from client.get('/')
+        assert 201 == resp.status
+        txt = yield from resp.text()
+        assert 'OK[new style middleware]' == txt
+
+    assert len(warning_checker) == 0
+
+
+@asyncio.coroutine
+def test_new_style_middleware_method(loop, test_client):
+    @asyncio.coroutine
+    def handler(request):
+        return web.Response(body=b'OK')
+
+    class Middleware:
+        @web.middleware
+        @asyncio.coroutine
+        def call(self, request, handler):
+            resp = yield from handler(request)
+            assert 200 == resp.status
+            resp.set_status(201)
+            resp.text = resp.text + '[new style middleware]'
+            return resp
+
+    with pytest.warns(None) as warning_checker:
+        app = web.Application()
+        app.middlewares.append(Middleware().call)
+        app.router.add_route('GET', '/', handler)
+        client = yield from test_client(app)
+        resp = yield from client.get('/')
+        assert 201 == resp.status
+        txt = yield from resp.text()
+        assert 'OK[new style middleware]' == txt
+
+    assert len(warning_checker) == 0