python-engineio fails to build with Python 3.11.0b3. =================================== FAILURES =================================== ____________________ TestAsyncServer.test_connect_bad_poll _____________________ self = <tests.asyncio.test_asyncio_server.TestAsyncServer testMethod=test_connect_bad_poll> import_module = <MagicMock name='import_module' id='140656792811152'> AsyncSocket = <MagicMock name='AsyncSocket' id='140656792810384'> @mock.patch('engineio.asyncio_socket.AsyncSocket') @mock.patch('importlib.import_module') def test_connect_bad_poll(self, import_module, AsyncSocket): a = self.get_async_mock() import_module.side_effect = [a] AsyncSocket.return_value = self._get_mock_socket() AsyncSocket.return_value.poll.side_effect = [exceptions.QueueEmpty] s = asyncio_server.AsyncServer() _run(s.handle_request('request')) assert a._async['make_response'].call_count == 1 > assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' E AssertionError: assert '200 OK' == '400 BAD REQUEST' E - 400 BAD REQUEST E + 200 OK tests/asyncio/test_asyncio_server.py:291: AssertionError _______________ TestAsyncServer.test_connect_transport_websocket _______________ self = <tests.asyncio.test_asyncio_server.TestAsyncServer testMethod=test_connect_transport_websocket> import_module = <MagicMock name='import_module' id='140656788334672'> AsyncSocket = <MagicMock name='AsyncSocket' id='140656788328912'> @mock.patch('engineio.asyncio_socket.AsyncSocket') @mock.patch('importlib.import_module') def test_connect_transport_websocket(self, import_module, AsyncSocket): a = self.get_async_mock( { 'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'transport=websocket', 'HTTP_UPGRADE': 'websocket', } ) import_module.side_effect = [a] AsyncSocket.return_value = self._get_mock_socket() s = asyncio_server.AsyncServer() s.generate_id = mock.MagicMock(return_value='123') # force socket to stay open, so that we can check it later AsyncSocket().closed = False _run(s.handle_request('request')) assert ( s.sockets['123'].send.mock.call_args[0][0].packet_type == packet.OPEN > ) E AttributeError: 'function' object has no attribute 'mock' tests/asyncio/test_asyncio_server.py:313: AttributeError ___________ TestAsyncServer.test_connect_transport_websocket_closed ____________ self = <tests.asyncio.test_asyncio_server.TestAsyncServer testMethod=test_connect_transport_websocket_closed> import_module = <MagicMock name='import_module' id='140656791298256'> AsyncSocket = <MagicMock name='AsyncSocket' id='140656791305040'> @mock.patch('engineio.asyncio_socket.AsyncSocket') @mock.patch('importlib.import_module') def test_connect_transport_websocket_closed( self, import_module, AsyncSocket ): a = self.get_async_mock( { 'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'transport=websocket', 'HTTP_UPGRADE': 'websocket' } ) import_module.side_effect = [a] AsyncSocket.return_value = self._get_mock_socket() s = asyncio_server.AsyncServer() s.generate_id = mock.MagicMock(return_value='123') # this mock handler just closes the socket, as it would happen on a # real websocket exchange async def mock_handle(environ): s.sockets['123'].closed = True AsyncSocket().handle_get_request = mock_handle _run(s.handle_request('request')) > assert '123' not in s.sockets # socket should close on its own E AssertionError: assert '123' not in {'123': <engineio.asyncio_socket.AsyncSocket object at 0x7fed364c6810>} E + where {'123': <engineio.asyncio_socket.AsyncSocket object at 0x7fed364c6810>} = <engineio.asyncio_server.AsyncServer object at 0x7fed35ff0c90>.sockets tests/asyncio/test_asyncio_server.py:361: AssertionError _____________________ TestAsyncServer.test_disconnect_all ______________________ self = <tests.asyncio.test_asyncio_server.TestAsyncServer testMethod=test_disconnect_all> def test_disconnect_all(self): s = asyncio_server.AsyncServer() s.sockets['foo'] = mock_foo = self._get_mock_socket() s.sockets['bar'] = mock_bar = self._get_mock_socket() > _run(s.disconnect()) tests/asyncio/test_asyncio_server.py:157: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ tests/asyncio/test_asyncio_server.py:33: in _run return asyncio.get_event_loop().run_until_complete(coro) /usr/lib64/python3.11/asyncio/base_events.py:650: in run_until_complete return future.result() ../../BUILDROOT/python-engineio-4.3.2-1.fc37.x86_64/usr/lib/python3.11/site-packages/engineio/asyncio_server.py:178: in disconnect await asyncio.wait([client.close() _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ fs = {<coroutine object AsyncMock.<locals>.mock_coro at 0x7fed361f0e50>, <coroutine object AsyncMock.<locals>.mock_coro at 0x7fed361f05e0>} async def wait(fs, *, timeout=None, return_when=ALL_COMPLETED): """Wait for the Futures or Tasks given by fs to complete. The fs iterable must not be empty. Coroutines will be wrapped in Tasks. Returns two sets of Future: (done, pending). Usage: done, pending = await asyncio.wait(fs) Note: This does not raise TimeoutError! Futures that aren't done when the timeout occurs are returned in the second set. """ if futures.isfuture(fs) or coroutines.iscoroutine(fs): raise TypeError(f"expect a list of futures, not {type(fs).__name__}") if not fs: raise ValueError('Set of Tasks/Futures is empty.') if return_when not in (FIRST_COMPLETED, FIRST_EXCEPTION, ALL_COMPLETED): raise ValueError(f'Invalid return_when value: {return_when}') fs = set(fs) if any(coroutines.iscoroutine(f) for f in fs): > raise TypeError("Passing coroutines is forbidden, use tasks explicitly.") E TypeError: Passing coroutines is forbidden, use tasks explicitly. /usr/lib64/python3.11/asyncio/tasks.py:424: TypeError ______________ TestAsyncServer.test_http_upgrade_case_insensitive ______________ self = <tests.asyncio.test_asyncio_server.TestAsyncServer testMethod=test_http_upgrade_case_insensitive> import_module = <MagicMock name='import_module' id='140656789877840'> AsyncSocket = <MagicMock name='AsyncSocket' id='140656789870800'> @mock.patch('engineio.asyncio_socket.AsyncSocket') @mock.patch('importlib.import_module') def test_http_upgrade_case_insensitive(self, import_module, AsyncSocket): a = self.get_async_mock( { 'REQUEST_METHOD': 'GET', 'QUERY_STRING': 'transport=websocket', 'HTTP_UPGRADE': 'WebSocket', } ) import_module.side_effect = [a] AsyncSocket.return_value = self._get_mock_socket() s = asyncio_server.AsyncServer() s.generate_id = mock.MagicMock(return_value='123') # force socket to stay open, so that we can check it later AsyncSocket().closed = False _run(s.handle_request('request')) assert ( s.sockets['123'].send.mock.call_args[0][0].packet_type == packet.OPEN > ) E AttributeError: 'function' object has no attribute 'mock' tests/asyncio/test_asyncio_server.py:335: AttributeError =============================== warnings summary =============================== ../../../../usr/lib/python3.11/site-packages/eventlet/support/greenlets.py:6 /usr/lib/python3.11/site-packages/eventlet/support/greenlets.py:6: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead. preserves_excinfo = (distutils.version.LooseVersion(greenlet.__version__) ../../../../usr/lib/python3.11/site-packages/eventlet/support/greenlets.py:7 /usr/lib/python3.11/site-packages/eventlet/support/greenlets.py:7: DeprecationWarning: distutils Version classes are deprecated. Use packaging.version instead. >= distutils.version.LooseVersion('0.3.2')) tests/asyncio/test_async_asgi.py: 46 warnings /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_async_asgi.py:23: DeprecationWarning: There is no current event loop return asyncio.get_event_loop().run_until_complete(coro) tests/asyncio/test_async_tornado.py::TornadoTests::test_translate_request tests/asyncio/test_async_tornado.py::TornadoTests::test_translate_request /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_async_tornado.py:16: DeprecationWarning: There is no current event loop return asyncio.get_event_loop().run_until_complete(coro) tests/asyncio/test_asyncio_client.py: 83 warnings /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_client.py:33: DeprecationWarning: There is no current event loop return asyncio.get_event_loop().run_until_complete(coro) tests/asyncio/test_asyncio_client.py::TestAsyncClient::test_background_tasks /builddir/build/BUILDROOT/python-engineio-4.3.2-1.fc37.x86_64/usr/lib/python3.11/site-packages/engineio/asyncio_client.py:177: DeprecationWarning: There is no current event loop return asyncio.ensure_future(target(*args, **kwargs)) tests/asyncio/test_asyncio_client.py::TestAsyncClient::test_background_tasks /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_client.py:238: DeprecationWarning: There is no current event loop pending = asyncio.all_tasks(loop=asyncio.get_event_loop()) \ tests/asyncio/test_asyncio_client.py::TestAsyncClient::test_background_tasks /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_client.py:240: DeprecationWarning: There is no current event loop asyncio.get_event_loop().run_until_complete(asyncio.wait(pending)) tests/asyncio/test_asyncio_client.py::TestAsyncClient::test_disconnect_polling_abort /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_client.py:212: RuntimeWarning: coroutine 'AsyncMock.<locals>.mock_coro' was never awaited assert c not in client.connected_clients Enable tracemalloc to get traceback where the object was allocated. See https://docs.pytest.org/en/stable/how-to/capture-warnings.html#resource-warnings for more info. tests/asyncio/test_asyncio_client.py::TestAsyncClient::test_disconnect_websocket_abort /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_client.py:228: RuntimeWarning: coroutine 'AsyncMock.<locals>.mock_coro' was never awaited assert c not in client.connected_clients Enable tracemalloc to get traceback where the object was allocated. See https://docs.pytest.org/en/stable/how-to/capture-warnings.html#resource-warnings for more info. tests/asyncio/test_asyncio_client.py::TestAsyncClient::test_signal_handler /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_client.py:1456: DeprecationWarning: There is no current event loop asyncio.get_event_loop().run_until_complete(test()) tests/asyncio/test_asyncio_client.py::TestAsyncClient::test_trigger_event_coroutine_async /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_client.py:943: DeprecationWarning: There is no current event loop asyncio.get_event_loop().run_until_complete(fut) tests/asyncio/test_asyncio_client.py::TestAsyncClient::test_trigger_event_coroutine_async_error /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_client.py:971: DeprecationWarning: There is no current event loop asyncio.get_event_loop().run_until_complete(fut) tests/asyncio/test_asyncio_client.py::TestAsyncClient::test_trigger_event_function_async /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_client.py:930: DeprecationWarning: There is no current event loop asyncio.get_event_loop().run_until_complete(fut) tests/asyncio/test_asyncio_client.py::TestAsyncClient::test_trigger_event_function_async_error /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_client.py:957: DeprecationWarning: There is no current event loop asyncio.get_event_loop().run_until_complete(fut) tests/asyncio/test_asyncio_client.py::TestAsyncClient::test_websocket_connection_no_open_packet tests/asyncio/test_asyncio_client.py::TestAsyncClient::test_websocket_connection_with_cookies tests/asyncio/test_asyncio_client.py::TestAsyncClient::test_websocket_upgrade_no_pong tests/common/test_client.py::TestClient::test_signal_handler tests/common/test_client.py::TestClient::test_signal_handler tests/common/test_client.py::TestClient::test_signal_handler /builddir/build/BUILDROOT/python-engineio-4.3.2-1.fc37.x86_64/usr/lib/python3.11/site-packages/engineio/asyncio_client.py:200: DeprecationWarning: There is no current event loop loop = asyncio.get_event_loop() tests/asyncio/test_asyncio_server.py::TestAsyncServer::test_background_tasks /builddir/build/BUILDROOT/python-engineio-4.3.2-1.fc37.x86_64/usr/lib/python3.11/site-packages/engineio/asyncio_server.py:332: DeprecationWarning: There is no current event loop return asyncio.ensure_future(target(*args, **kwargs)) tests/asyncio/test_asyncio_server.py::TestAsyncServer::test_background_tasks /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_server.py:1012: DeprecationWarning: There is no current event loop pending = asyncio.all_tasks(loop=asyncio.get_event_loop()) \ tests/asyncio/test_asyncio_server.py::TestAsyncServer::test_background_tasks /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_server.py:1014: DeprecationWarning: There is no current event loop asyncio.get_event_loop().run_until_complete(asyncio.wait(pending)) tests/asyncio/test_asyncio_server.py: 68 warnings /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_server.py:33: DeprecationWarning: There is no current event loop return asyncio.get_event_loop().run_until_complete(coro) tests/asyncio/test_asyncio_server.py::TestAsyncServer::test_trigger_event_coroutine_async /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_server.py:1094: DeprecationWarning: There is no current event loop asyncio.get_event_loop().run_until_complete(fut) tests/asyncio/test_asyncio_server.py::TestAsyncServer::test_trigger_event_coroutine_async_error /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_server.py:1122: DeprecationWarning: There is no current event loop asyncio.get_event_loop().run_until_complete(fut) tests/asyncio/test_asyncio_server.py::TestAsyncServer::test_trigger_event_function_async /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_server.py:1081: DeprecationWarning: There is no current event loop asyncio.get_event_loop().run_until_complete(fut) tests/asyncio/test_asyncio_server.py::TestAsyncServer::test_trigger_event_function_async_error /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_server.py:1108: DeprecationWarning: There is no current event loop asyncio.get_event_loop().run_until_complete(fut) tests/asyncio/test_asyncio_socket.py: 50 warnings /builddir/build/BUILD/python-engineio-4.3.2/tests/asyncio/test_asyncio_socket.py:28: DeprecationWarning: There is no current event loop return asyncio.get_event_loop().run_until_complete(coro) tests/common/test_client.py::TestClient::test_read_loop_websocket_disconnected /usr/lib64/python3.11/inspect.py:3081: RuntimeWarning: coroutine 'AsyncMock.<locals>.mock_coro' was never awaited arg_val = next(arg_vals) Enable tracemalloc to get traceback where the object was allocated. See https://docs.pytest.org/en/stable/how-to/capture-warnings.html#resource-warnings for more info. -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html =========================== short test summary info ============================ FAILED tests/asyncio/test_asyncio_server.py::TestAsyncServer::test_connect_bad_poll FAILED tests/asyncio/test_asyncio_server.py::TestAsyncServer::test_connect_transport_websocket FAILED tests/asyncio/test_asyncio_server.py::TestAsyncServer::test_connect_transport_websocket_closed FAILED tests/asyncio/test_asyncio_server.py::TestAsyncServer::test_disconnect_all FAILED tests/asyncio/test_asyncio_server.py::TestAsyncServer::test_http_upgrade_case_insensitive ================= 5 failed, 475 passed, 275 warnings in 5.66s ================== https://docs.python.org/3.11/whatsnew/3.11.html For the build logs, see: https://copr-be.cloud.fedoraproject.org/results/@python/python3.11/fedora-rawhide-x86_64/04500557-python-engineio/ For all our attempts to build python-engineio with Python 3.11, see: https://copr.fedorainfracloud.org/coprs/g/python/python3.11/package/python-engineio/ Testing and mass rebuild of packages is happening in copr. You can follow these instructions to test locally in mock if your package builds with Python 3.11: https://copr.fedorainfracloud.org/coprs/g/python/python3.11/ Let us know here if you have any questions. Python 3.11 is planned to be included in Fedora 37. To make that update smoother, we're building Fedora packages with all pre-releases of Python 3.11. A build failure prevents us from testing all dependent packages (transitive [Build]Requires), so if this package is required a lot, it's important for us to get it fixed soon. We'd appreciate help from the people who know this package best, but if you don't want to work on this now, let us know so we can try to work around it on our side.
I am not sure that it will be trivial for me to fix these myself, although I haven’t taken the time to make a serious effort. However, I have reported the failures upstream: https://github.com/miguelgrinberg/python-engineio/issues/279
Upstream doesn’t plan to look at this until Python 3.11 final is released. I will try to have a look before then, but debugging the intersection of Python testing/mocking magic and async code is no picnic. Suggestions welcome.
Suggestion: Very politely and very carefully convince upstream that dealing with 3.11 after it's released is not soon enough :) If that doesn't work, we can probably fix this later, the dep tree is not *that* big: $ repoquery --repo=rawhide{,-source} --whatrequires python3-engineio --recursive pgadmin4-0:6.9-2.fc37.src pgadmin4-0:6.9-2.fc37.x86_64 pgadmin4-langpack-cs-0:6.9-2.fc37.noarch pgadmin4-langpack-de-0:6.9-2.fc37.noarch pgadmin4-langpack-es-0:6.9-2.fc37.noarch pgadmin4-langpack-fr-0:6.9-2.fc37.noarch pgadmin4-langpack-it-0:6.9-2.fc37.noarch pgadmin4-langpack-ja-0:6.9-2.fc37.noarch pgadmin4-langpack-ko-0:6.9-2.fc37.noarch pgadmin4-langpack-pl-0:6.9-2.fc37.noarch pgadmin4-langpack-ru-0:6.9-2.fc37.noarch pgadmin4-langpack-zh-0:6.9-2.fc37.noarch pgadmin4-qt-0:6.9-2.fc37.x86_64 python-flask-socketio-0:5.2.0-2.fc37.src python-socketio-0:5.6.0-1.fc37.src python3-aioambient-0:1.3.0-2.fc36.noarch python3-engineio+asyncio_client-0:4.3.2-1.fc37.noarch python3-engineio+client-0:4.3.2-1.fc37.noarch python3-flask-socketio-0:5.2.0-2.fc37.noarch python3-socketio+asyncio_client-0:5.6.0-1.fc37.noarch python3-socketio+client-0:5.6.0-1.fc37.noarch python3-socketio-0:5.6.0-1.fc37.noarch
*** Bug 2098900 has been marked as a duplicate of this bug. ***
Looking a bit at the failing tests, I think it is only the actual test code resp. something related to unittest.mock which is broken. Could we therefore just submit a build with ignored test failures to unbreak the dependency chain?
(In reply to Sandro Mani from comment #5) > Looking a bit at the failing tests, I think it is only the actual test code > resp. something related to unittest.mock which is broken. Could we therefore > just submit a build with ignored test failures to unbreak the dependency > chain? From errors like > assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' E AssertionError: assert '200 OK' == '400 BAD REQUEST' E - 400 BAD REQUEST E + 200 OK it’s hard for me to tell if that is true or not. However, it’s unlikely that upstream is going to work on it soon, and unlikely that I will be able to be able to make further progress on understanding the four remaining errors ( (I did fix “tests/asyncio/test_asyncio_server.py::TestAsyncServer::test_disconnect_all” in [1]), so maybe ignoring the problem is the way to go for now. I’m going to set up a COPR and see what happens with the dependent packages if I skip these four tests and build python3-engineio. [1] https://src.fedoraproject.org/rpms/python-engineio/c/ced66f73bb96639586c18387a7087c889e84d439?branch=rawhide
FWIW, I've already set up a COPR repo with the dependency chain up to pgadmin [1]. Regarding the test failures: i.e. > AttributeError: 'function' object has no attribute 'mock' seems to indicate that mocking of engineio.asyncio_socket.AsyncSocket did not happen for some reason. One possibility could be that for a similar reason > AsyncSocket.return_value.poll.side_effect = [exceptions.QueueEmpty] has no effect, which would lead to > assert a._async['make_response'].call_args[0][0] == '400 BAD REQUEST' failing since the side_effect was not set. Clearly all pure assumptions, I've spent some time hunting around trying to debug this, but unfortunately I've not really used mock before, so not terribly efficient debugging. [1] https://copr.fedorainfracloud.org/coprs/smani/py311/
Okay, your COPR looks reasonable, and so does my testing, so I’ll proceed with skipping the four failing tests.
FEDORA-2022-147280e5e4 has been submitted as an update to Fedora 37. https://bodhi.fedoraproject.org/updates/FEDORA-2022-147280e5e4
FEDORA-2022-147280e5e4 has been pushed to the Fedora 37 stable repository. If problem still persists, please make note of it in this bug report.
(In reply to Sandro Mani from comment #7) > FWIW, I've already set up a COPR repo with the dependency chain up to > pgadmin [1]. Since the primary user of the python-engineio/python-socketio/python-flask-socketio stack is pgadmin4, would you like to co-maintain those three packages?
Thanks! - yes feel free to add me to those packages.