Comments (13)
aiohttp.web_exceptions.NotAppKeyWarning: It is recommended to use web.AppKey instances for keys. https://docs.aiohttp.org/en/stable/web_advanced.html#application-s-config
Trivially fixable if you'd like to make a contribution. Though I'd also like to know why this isn't reproducing in our CI. The test appears to be passing: https://github.com/aio-libs/aiohttp/actions/runs/8210202661/job/22457206363#step:11:1653
from aiohttp.
Trivially fixable if you'd like to make a contribution.
I actually tried. Spent half an hour on it or so, without great success. It was somewhat complicated due to it is a nested test, a pytest that tests another pytest.
Its not that I don't want to contribute, but I figured someone who are more familiar with the code would do it in significantly less time than me.
Though I'd also like to know why this isn't reproducing in our CI. The test appears to be passing: https://github.com/aio-libs/aiohttp/actions/runs/8210202661/job/22457206363#step:11:1653
Exactly! I noticed that too and found it weird. What version of pytest are you using? I have bumped in several cases where pytest-8 breaks things.
(I am in the process of updating python to 3.12 for Alpine Linux. 1375 python packages left to build. Today I was able to rebuild ~58. I calculated that it will take me 24 days with current speed if I am able to spend 100% of my time on this.)
from aiohttp.
What version of pytest are you using?
The linked CI log says it's 8.0.2:
https://github.com/aio-libs/aiohttp/actions/runs/8210202661/job/22457206363#step:11:19.
We don't touch that code often so it's unlike it'll be faster for us to fix.
Anyway, are you able to provide a minimum reproducer with an Alpine container or something like that? It may have clues to what's different. Like maybe you have a Pure-python build w/o C-extensions or something..
from aiohttp.
FWIW it's probably the filterwarnings setting or equivalent that is turning warnings to errors. Not sure why, though.
Also, don't we have 3.9.4 already?
from aiohttp.
I actually tried. Spent half an hour on it or so, without great success. It was somewhat complicated due to it is a nested test, a pytest that tests another pytest.
Huh, it should just be replacing the strings as per the documentation linked in the warning.
At a glance, it's just 'value'
used in 2 places, which would need to be replaced with an AppKey:
value_key = web.AppKey("value_key", str)
So, just define that as a global and replace 'value'
with value_key
:
aiohttp/tests/test_pytest_plugin.py
Lines 70 to 73 in 0588e34
Only problem with me making the change is that I can't see the error in the first place to confirm it's fixed.
Also, don't we have 3.9.4 already?
Uh, no, I was partly waiting on another fix to merge and partly got caught up with other things. Will make the release next week.
from aiohttp.
I think problem is related pytest 8, which changes how warnings are handled.
As I read the test, it is checking that warnings are raised?
aiohttp/tests/test_pytest_plugin.py
Line 107 in 77f5633
from aiohttp.
diff --git a/tests/test_pytest_plugin.py b/tests/test_pytest_plugin.py
index b25a553..5faa254 100644
--- a/tests/test_pytest_plugin.py
+++ b/tests/test_pytest_plugin.py
@@ -73,9 +73,10 @@ async def test_noop() -> None:
async def previous(request):
+ value_key = web.AppKey("value", str)
if request.method == 'POST':
with pytest.deprecated_call(): # FIXME: this isn't actually called
- request.app['value'] = (await request.post())['value']
+ request.app[value_key] = (await request.post())[value_key]
return web.Response(body=b'thanks for the data')
else:
v = request.app.get('value', 'unknown')
The result is:
$ PYTHONPATH="$(echo
build/lib.*)" pytest --no-cov --ignore tests/autobahn/test_autobahn.py --ignore tests/test_proxy_fun
ctional.py -k "test_aiohttp_plugin" -vvv
======================================= test session starts ========================================
platform linux -- Python 3.11.8, pytest-8.0.2, pluggy-1.4.0 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/ncopa/aports/community/py3-aiohttp/src/aiohttp-3.9.3
configfile: setup.cfg
testpaths: tests/
plugins: cov-4.1.0, xdist-3.5.0, mock-3.10.0, requests-mock-1.11.0
collected 3079 items / 3076 deselected / 3 selected
tests/test_pytest_plugin.py::test_aiohttp_plugin FAILED [ 33%]
tests/test_pytest_plugin.py::test_aiohttp_plugin_async_fixture PASSED [ 66%]
tests/test_pytest_plugin.py::test_aiohttp_plugin_async_gen_fixture PASSED [100%]
============================================= FAILURES =============================================
_______________________________________ test_aiohttp_plugin ________________________________________
testdir = <Testdir local('/tmp/pytest-of-ncopa/pytest-43/test_aiohttp_plugin0')>
def test_aiohttp_plugin(testdir) -> None:
testdir.makepyfile(
"""\
import pytest
from unittest import mock
from aiohttp import web
async def hello(request):
return web.Response(body=b'Hello, world')
def create_app(loop=None):
app = web.Application()
app.router.add_route('GET', '/', hello)
return app
async def test_hello(aiohttp_client) -> None:
client = await aiohttp_client(create_app)
resp = await client.get('/')
assert resp.status == 200
text = await resp.text()
assert 'Hello, world' in text
async def test_hello_from_app(aiohttp_client, loop) -> None:
app = web.Application()
app.router.add_get('/', hello)
client = await aiohttp_client(app)
resp = await client.get('/')
assert resp.status == 200
text = await resp.text()
assert 'Hello, world' in text
async def test_hello_with_loop(aiohttp_client, loop) -> None:
client = await aiohttp_client(create_app)
resp = await client.get('/')
assert resp.status == 200
text = await resp.text()
assert 'Hello, world' in text
async def test_set_args(aiohttp_client, loop) -> None:
with pytest.raises(AssertionError):
app = web.Application()
await aiohttp_client(app, 1, 2, 3)
async def test_set_keyword_args(aiohttp_client, loop) -> None:
app = web.Application()
with pytest.raises(TypeError):
await aiohttp_client(app, param=1)
async def test_noop() -> None:
pass
async def previous(request):
value_key = web.AppKey("value", str)
if request.method == 'POST':
with pytest.deprecated_call(): # FIXME: this isn't actually called
request.app[value_key] = (await request.post())[value_key]
return web.Response(body=b'thanks for the data')
else:
v = request.app.get('value', 'unknown')
return web.Response(body='value: {}'.format(v).encode())
def create_stateful_app(loop):
app = web.Application()
app.router.add_route('*', '/', previous)
return app
@pytest.fixture
def cli(loop, aiohttp_client):
return loop.run_until_complete(aiohttp_client(create_stateful_app))
async def test_set_value(cli) -> None:
resp = await cli.post('/', data={'value': 'foo'})
assert resp.status == 200
text = await resp.text()
assert text == 'thanks for the data'
assert cli.server.app['value'] == 'foo'
async def test_get_value(cli) -> None:
resp = await cli.get('/')
assert resp.status == 200
text = await resp.text()
assert text == 'value: unknown'
with pytest.warns(DeprecationWarning):
cli.server.app['value'] = 'bar'
resp = await cli.get('/')
assert resp.status == 200
text = await resp.text()
assert text == 'value: bar'
def test_noncoro() -> None:
assert True
async def test_failed_to_create_client(aiohttp_client) -> None:
def make_app(loop):
raise RuntimeError()
with pytest.raises(RuntimeError):
await aiohttp_client(make_app)
async def test_custom_port_aiohttp_client(aiohttp_client, aiohttp_unused_port):
port = aiohttp_unused_port()
client = await aiohttp_client(create_app, server_kwargs={'port': port})
assert client.port == port
resp = await client.get('/')
assert resp.status == 200
text = await resp.text()
assert 'Hello, world' in text
async def test_custom_port_test_server(aiohttp_server, aiohttp_unused_port):
app = create_app()
port = aiohttp_unused_port()
server = await aiohttp_server(app, port=port)
assert server.port == port
"""
)
testdir.makeconftest(CONFTEST)
result = testdir.runpytest("-p", "no:sugar", "--aiohttp-loop=pyloop")
> result.assert_outcomes(passed=12)
E AssertionError: assert {'passed': 10, 'skipped': 0, 'failed': 2, 'errors': 0, 'xpassed': 0, 'xfailed': 0} == {'passed': 12, 'skipped': 0, 'failed': 0, 'errors': 0, 'xpassed': 0, 'xfailed': 0}
E
E Common items:
E {'errors': 0, 'skipped': 0, 'xfailed': 0, 'xpassed': 0}
E Differing items:
E {'failed': 2} != {'failed': 0}
E {'passed': 10} != {'passed': 12}
E
E Full diff:
E {
E 'errors': 0,
E - 'failed': 0,
E ? ^
E + 'failed': 2,
E ? ^
E - 'passed': 12,
E ? ^
E + 'passed': 10,
E ? ^
E 'skipped': 0,
E 'xfailed': 0,
E 'xpassed': 0,
E }
result = <RunResult ret=1 len(stdout.lines)=55 len(stderr.lines)=0 duration=0.17s>
testdir = <Testdir local('/tmp/pytest-of-ncopa/pytest-43/test_aiohttp_plugin0')>
/home/ncopa/aports/community/py3-aiohttp/src/aiohttp-3.9.3/tests/test_pytest_plugin.py:151: AssertionError
--------------------------------------- Captured stdout call ---------------------------------------
============================= test session starts ==============================
platform linux -- Python 3.11.8, pytest-8.0.2, pluggy-1.4.0
rootdir: /tmp/pytest-of-ncopa/pytest-43/test_aiohttp_plugin0
plugins: cov-4.1.0, xdist-3.5.0, mock-3.10.0, requests-mock-1.11.0
collected 12 items
test_aiohttp_plugin.py ......FF.... [100%]
=================================== FAILURES ===================================
____________________________ test_set_value[pyloop] ____________________________
cli = <aiohttp.test_utils.TestClient object at 0x7f86b1afc3d0>
async def test_set_value(cli) -> None:
> resp = await cli.post('/', data={'value': 'foo'})
test_aiohttp_plugin.py:82:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/home/ncopa/aports/community/py3-aiohttp/src/aiohttp-3.9.3/build/lib.linux-x86_64-cpython-311/aiohttp/test_utils.py:322: in _request
resp = await self._session.request(method, self.make_url(path), **kwargs)
/home/ncopa/aports/community/py3-aiohttp/src/aiohttp-3.9.3/build/lib.linux-x86_64-cpython-311/aiohttp/client.py:605: in _request
await resp.start(conn)
/home/ncopa/aports/community/py3-aiohttp/src/aiohttp-3.9.3/build/lib.linux-x86_64-cpython-311/aiohttp/client_reqrep.py:966: in start
message, payload = await protocol.read() # type: ignore[union-attr]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <aiohttp.client_proto.ResponseHandler object at 0x7f86b1a55080>
async def read(self) -> _T:
if not self._buffer and not self._eof:
assert not self._waiter
self._waiter = self._loop.create_future()
try:
> await self._waiter
E aiohttp.client_exceptions.ServerDisconnectedError: Server disconnected
/home/ncopa/aports/community/py3-aiohttp/src/aiohttp-3.9.3/build/lib.linux-x86_64-cpython-311/aiohttp/streams.py:622: ServerDisconnectedError
____________________________ test_get_value[pyloop] ____________________________
cli = <aiohttp.test_utils.TestClient object at 0x7f86b16fc7d0>
async def test_get_value(cli) -> None:
resp = await cli.get('/')
assert resp.status == 200
text = await resp.text()
assert text == 'value: unknown'
> with pytest.warns(DeprecationWarning):
E aiohttp.web_exceptions.NotAppKeyWarning: It is recommended to use web.AppKey instances for keys.
E https://docs.aiohttp.org/en/stable/web_advanced.html#application-s-config
test_aiohttp_plugin.py:94: NotAppKeyWarning
=========================== short test summary info ============================
FAILED test_aiohttp_plugin.py::test_set_value[pyloop] - aiohttp.client_except...
FAILED test_aiohttp_plugin.py::test_get_value[pyloop] - aiohttp.web_exception...
========================= 2 failed, 10 passed in 0.16s =========================
======================================= slowest 10 durations =======================================
0.17s call tests/test_pytest_plugin.py::test_aiohttp_plugin
0.06s call tests/test_pytest_plugin.py::test_aiohttp_plugin_async_fixture
0.03s call tests/test_pytest_plugin.py::test_aiohttp_plugin_async_gen_fixture
0.00s setup tests/test_pytest_plugin.py::test_aiohttp_plugin
0.00s setup tests/test_pytest_plugin.py::test_aiohttp_plugin_async_fixture
0.00s setup tests/test_pytest_plugin.py::test_aiohttp_plugin_async_gen_fixture
0.00s teardown tests/test_pytest_plugin.py::test_aiohttp_plugin
0.00s teardown tests/test_pytest_plugin.py::test_aiohttp_plugin_async_gen_fixture
0.00s teardown tests/test_pytest_plugin.py::test_aiohttp_plugin_async_fixture
===================================== short test summary info ======================================
FAILED tests/test_pytest_plugin.py::test_aiohttp_plugin - AssertionError: assert {'passed': 10, 'skipped': 0, 'failed': 2, 'errors': 0, 'xpassed': 0, 'xf...
=========================== 1 failed, 2 passed, 3076 deselected in 0.56s ===========================
from aiohttp.
I think problem is related pytest 8, which changes how warnings are handled.
Right, not clear what's changed, but this is reproducing in the Dependabot PR: #8223
So, that gives us somewhere to reproduce.
As I read the test, it is checking that warnings are raised?
No, that line long predates AppKey: https://github.com/aio-libs/aiohttp/blame/77f5633ce02da71c6879d3b25b5fbe8b240647c6/tests/test_pytest_plugin.py#L107
The AppKey warning is also not a DeprecationWarning, so it should never have caught it before.
I suspect the runpytest() thing that these tests are using never errored on warnings with previous versions of pytest.
from aiohttp.
Oh, also, the tests are passing in current pytest on master. So, there must be some difference with 3.x.
from aiohttp.
I don't see any test_get_value
or test_set_value
in master branch.
from aiohttp.
OK, will take a look next week, I'm away for the next few days.
from aiohttp.
Thank you! Enjoy!
from aiohttp.
It was fixed in #8223.
from aiohttp.
Related Issues (20)
- TypeError: _patch_task.<locals>.task_new_init() got an unexpected keyword argument 'eager_start' HOT 5
- Sending default 'Server' header when failing on wrong HTTP method HOT 6
- Websocket ping test has transient failures on loaded systems HOT 1
- Send 100-continue only when handler reads body
- typing error with `timeout` argument of `aiohttp.ClientSession` requests methods HOT 1
- Rename compress parameter HOT 6
- on_request_headers_sent params type was never imported into the top-level file. HOT 2
- AsyncResolver not passing on loop too aiodns.DNSResolver HOT 4
- test_web_sendfile_functional isn't testing sendfile
- Incorrect re-use future in _make_or_get_ssl_context HOT 10
- ClientSession.get() doesn't support hostname.
- MIsing header file HOT 1
- Replace blockdiag HOT 1
- 3.9.2 server keep-alive timeout can cause disconnect of active connections and hence client server disconnect errors HOT 18
- Disable retry in tests
- add `Sequence[str | int]` typing in `_RequestOptions.params` HOT 2
- Middleware fix up is unexpectedly expensive HOT 2
- Regression in aiohttp 3.10.3 when running multiple loops in multiple threads HOT 2
- Remove make_mocked_coro()
- Replace aioredis in example HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from aiohttp.