diff --git a/python-autobahn.changes b/python-autobahn.changes index 9c75f00..1c3f41a 100644 --- a/python-autobahn.changes +++ b/python-autobahn.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Tue Jul 22 04:49:15 UTC 2025 - Steve Kowalik + +- Add patch use-plain-twisted.patch: + * Support pytest-asyncio 1.0 changes. + ------------------------------------------------------------------- Tue Dec 10 06:10:04 UTC 2024 - Steve Kowalik diff --git a/python-autobahn.spec b/python-autobahn.spec index 182e67c..dc059db 100644 --- a/python-autobahn.spec +++ b/python-autobahn.spec @@ -1,7 +1,7 @@ # # spec file for package python-autobahn # -# Copyright (c) 2024 SUSE LLC +# Copyright (c) 2025 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -33,6 +33,8 @@ Patch0: respect-cflags.patch Patch1: intrin-arch.patch # PATCH-FIX-UPSTREAM gh#crossbario/autobahn-python#1647 Patch2: support-new-pytest-asyncio.patch +# PATCH-FIX-UPSTREAM gh#crossbario/autobahn-python#1661 +Patch3: use-plain-twisted.patch BuildRequires: %{python_module PyNaCl >= 1.4.0} BuildRequires: %{python_module Twisted >= 24.3.0} BuildRequires: %{python_module argon2-cffi >= 20.1.0} diff --git a/use-plain-twisted.patch b/use-plain-twisted.patch new file mode 100644 index 0000000..a05b546 --- /dev/null +++ b/use-plain-twisted.patch @@ -0,0 +1,305 @@ +From e74b425e286aa72a59d36a7e6785731a8c023409 Mon Sep 17 00:00:00 2001 +From: meejah +Date: Sat, 7 Jun 2025 20:39:27 -0600 +Subject: [PATCH 1/2] Plain twisted utilities are sufficient + +--- + .../twisted/test/test_tx_websocket_agent.py | 5 ++-- + autobahn/twisted/testing/__init__.py | 29 ++----------------- + 2 files changed, 6 insertions(+), 28 deletions(-) + +diff --git a/autobahn/twisted/test/test_tx_websocket_agent.py b/autobahn/twisted/test/test_tx_websocket_agent.py +index c926cbefa..d65c3ca80 100644 +--- a/autobahn/twisted/test/test_tx_websocket_agent.py ++++ b/autobahn/twisted/test/test_tx_websocket_agent.py +@@ -1,12 +1,13 @@ + from twisted.trial import unittest + + try: +- from autobahn.twisted.testing import create_memory_agent, MemoryReactorClockResolver, create_pumper ++ from autobahn.twisted.testing import create_memory_agent, create_pumper + HAVE_TESTING = True + except ImportError: + HAVE_TESTING = False + + from twisted.internet.defer import inlineCallbacks ++from twisted.internet.testing import MemoryReactorClock + from autobahn.twisted.websocket import WebSocketServerProtocol + + +@@ -16,7 +17,7 @@ class TestAgent(unittest.TestCase): + + def setUp(self): + self.pumper = create_pumper() +- self.reactor = MemoryReactorClockResolver() ++ self.reactor = MemoryReactorClock() + return self.pumper.start() + + def tearDown(self): +diff --git a/autobahn/twisted/testing/__init__.py b/autobahn/twisted/testing/__init__.py +index 53d5f2d49..7926d79bb 100644 +--- a/autobahn/twisted/testing/__init__.py ++++ b/autobahn/twisted/testing/__init__.py +@@ -73,32 +73,9 @@ def resolveHostName(self, receiver, hostName, portNumber=0): + receiver.resolutionComplete() + + +-@implementer(IReactorPluggableNameResolver) +-class _TestNameResolver(object): +- """ +- A test version of IReactorPluggableNameResolver +- """ +- +- _resolver = None +- +- @property +- def nameResolver(self): +- if self._resolver is None: +- self._resolver = _StaticTestResolver() +- return self._resolver +- +- def installNameResolver(self, resolver): +- old = self._resolver +- self._resolver = resolver +- return old +- +- +-class MemoryReactorClockResolver(MemoryReactorClock, _TestNameResolver): +- """ +- Combine MemoryReactor, Clock and an IReactorPluggableNameResolver +- together. +- """ +- pass ++# in previous revisions, we exported MemoryReactorClockResolver so ++# this maintains compatibility with any downstream code ++MemoryReactorClockResolver = MemoryReactorClock + + + class _TwistedWebMemoryAgent(IWebSocketClientAgent): + +From 3067e1529d93855518c7a1c5bdc3b148e617d8cd Mon Sep 17 00:00:00 2001 +From: meejah +Date: Sat, 7 Jun 2025 21:49:31 -0600 +Subject: [PATCH 2/2] CI fixups + +--- + .github/workflows/main.yml | 15 +++++------ + autobahn/asyncio/test/test_aio_rawsocket.py | 18 ++++++------- + autobahn/asyncio/test/test_aio_websocket.py | 8 +++--- + autobahn/twisted/testing/__init__.py | 2 +- + autobahn/wamp/test/test_wamp_component_aio.py | 25 ++++++++++--------- + tox.ini | 4 +++ + 6 files changed, 39 insertions(+), 33 deletions(-) + +diff --git a/autobahn/asyncio/test/test_aio_rawsocket.py b/autobahn/asyncio/test/test_aio_rawsocket.py +index 726a62420..42c00c304 100644 +--- a/autobahn/asyncio/test/test_aio_rawsocket.py ++++ b/autobahn/asyncio/test/test_aio_rawsocket.py +@@ -11,7 +11,7 @@ + + + @pytest.mark.skipif(not os.environ.get('USE_ASYNCIO', False), reason='test runs on asyncio only') +-def test_sers(event_loop): ++def test_sers(): + serializers = get_serializers() + assert len(serializers) > 0 + m = serializers[0]().serialize(message.Abort('close')) +@@ -19,7 +19,7 @@ def test_sers(event_loop): + + + @pytest.mark.skipif(not os.environ.get('USE_ASYNCIO', False), reason='test runs on asyncio only') +-def test_prefix(event_loop): ++def test_prefix(): + p = PrefixProtocol() + transport = Mock() + receiver = Mock() +@@ -62,7 +62,7 @@ def test_prefix(event_loop): + + + @pytest.mark.skipif(not os.environ.get('USE_ASYNCIO', False), reason='test runs on asyncio only') +-def test_is_closed(event_loop): ++def test_is_closed(): + class CP(RawSocketClientProtocol): + @property + def serializer_id(self): +@@ -83,7 +83,7 @@ def serializer_id(self): + + + @pytest.mark.skipif(not os.environ.get('USE_ASYNCIO', False), reason='test runs on asyncio only') +-def test_raw_socket_server1(event_loop): ++def test_raw_socket_server1(): + + server = RawSocketServerProtocol() + ser = Mock(return_value=True) +@@ -108,7 +108,7 @@ def test_raw_socket_server1(event_loop): + + + @pytest.mark.skipif(not os.environ.get('USE_ASYNCIO', False), reason='test runs on asyncio only') +-def test_raw_socket_server_errors(event_loop): ++def test_raw_socket_server_errors(): + + server = RawSocketServerProtocol() + ser = Mock(return_value=True) +@@ -139,7 +139,7 @@ def test_raw_socket_server_errors(event_loop): + + + @pytest.mark.skipif(not os.environ.get('USE_ASYNCIO', False), reason='test runs on asyncio only') +-def test_raw_socket_client1(event_loop): ++def test_raw_socket_client1(): + class CP(RawSocketClientProtocol): + @property + def serializer_id(self): +@@ -162,7 +162,7 @@ def serializer_id(self): + + + @pytest.mark.skipif(not os.environ.get('USE_ASYNCIO', False), reason='test runs on asyncio only') +-def test_raw_socket_client_error(event_loop): ++def test_raw_socket_client_error(): + class CP(RawSocketClientProtocol): + @property + def serializer_id(self): +@@ -181,7 +181,7 @@ def serializer_id(self): + + + @pytest.mark.skipif(not os.environ.get('USE_ASYNCIO', False), reason='test runs on asyncio only') +-def test_wamp_server(event_loop): ++def test_wamp_server(): + transport = Mock(spec_set=('abort', 'close', 'write', 'get_extra_info')) + transport.write = Mock(side_effect=lambda m: messages.append(m)) + server = Mock(spec=['onOpen', 'onMessage']) +@@ -209,7 +209,7 @@ def fact_server(): + + + @pytest.mark.skipif(not os.environ.get('USE_ASYNCIO', False), reason='test runs on asyncio only') +-def test_wamp_client(event_loop): ++def test_wamp_client(): + transport = Mock(spec_set=('abort', 'close', 'write', 'get_extra_info')) + transport.write = Mock(side_effect=lambda m: messages.append(m)) + client = Mock(spec=['onOpen', 'onMessage']) +diff --git a/autobahn/asyncio/test/test_aio_websocket.py b/autobahn/asyncio/test/test_aio_websocket.py +index afcbfcf9e..0c2f1ee0a 100644 +--- a/autobahn/asyncio/test/test_aio_websocket.py ++++ b/autobahn/asyncio/test/test_aio_websocket.py +@@ -22,15 +22,15 @@ async def test_echo_async(): + + + @pytest.mark.skipif(not os.environ.get('USE_ASYNCIO', False), reason='test runs on asyncio only') +-def test_websocket_custom_loop(event_loop): +- factory = WebSocketServerFactory(loop=event_loop) ++def test_websocket_custom_loop(): ++ factory = WebSocketServerFactory(loop=asyncio.new_event_loop()) + server = factory() + transport = Mock() + server.connection_made(transport) + + + @pytest.mark.skipif(not os.environ.get('USE_ASYNCIO', False), reason='test runs on asyncio only') +-def test_async_on_connect_server(event_loop): ++def test_async_on_connect_server(): + + num = 42 + done = txaio.create_future() +@@ -64,7 +64,7 @@ async def on_connect(req): + ]) + server.processHandshake() + +- event_loop.run_until_complete(done) ++ asyncio.get_event_loop().run_until_complete(done) + + assert len(values) == 1 + assert values[0] == num * num +diff --git a/autobahn/twisted/testing/__init__.py b/autobahn/twisted/testing/__init__.py +index 7926d79bb..e014d3505 100644 +--- a/autobahn/twisted/testing/__init__.py ++++ b/autobahn/twisted/testing/__init__.py +@@ -37,7 +37,7 @@ + from twisted.internet.defer import Deferred + from twisted.internet.address import IPv4Address + from twisted.internet._resolver import HostResolution # "internal" class, but it's simple +-from twisted.internet.interfaces import ISSLTransport, IReactorPluggableNameResolver ++from twisted.internet.interfaces import ISSLTransport + try: + from twisted.internet.testing import MemoryReactorClock + except ImportError: +diff --git a/autobahn/wamp/test/test_wamp_component_aio.py b/autobahn/wamp/test/test_wamp_component_aio.py +index 2393fd7c6..971f8dddd 100644 +--- a/autobahn/wamp/test/test_wamp_component_aio.py ++++ b/autobahn/wamp/test/test_wamp_component_aio.py +@@ -29,14 +29,15 @@ + import unittest.mock as mock + import pytest + import txaio ++import asyncio + + if os.environ.get('USE_ASYNCIO', False): + from autobahn.asyncio.component import Component + + @pytest.mark.skipif(sys.version_info < (3, 5), reason="requires Python 3.5+") +- def test_asyncio_component(event_loop): ++ def test_asyncio_component(): + orig_loop = txaio.config.loop +- txaio.config.loop = event_loop ++ txaio.config.loop = asyncio.get_event_loop() + + comp = Component( + transports=[ +@@ -51,8 +52,8 @@ def test_asyncio_component(event_loop): + # if having trouble, try starting some logging (and use + # "py.test -s" to get real-time output) + # txaio.start_logging(level="debug") +- f = comp.start(loop=event_loop) +- txaio.config.loop = event_loop ++ f = comp.start(loop=asyncio.get_event_loop()) ++ txaio.config.loop = asyncio.get_event_loop() + finished = txaio.create_future() + + def fail(): +@@ -72,17 +73,17 @@ def done(f): + assert comp._done_f is None + f.add_done_callback(done) + +- event_loop.run_until_complete(finished) ++ asyncio.get_event_loop().run_until_complete(finished) + + @pytest.mark.skipif(sys.version_info < (3, 5), reason="requires Python 3.5+") +- def test_asyncio_component_404(event_loop): ++ def test_asyncio_component_404(): + """ + If something connects but then gets aborted, it should still try + to re-connect (in real cases this could be e.g. wrong path, + TLS failure, WebSocket handshake failure, etc) + """ + orig_loop = txaio.config.loop +- txaio.config.loop = event_loop ++ txaio.config.loop = asyncio.get_event_loop() + + class FakeTransport(object): + def close(self): +@@ -103,8 +104,8 @@ def create_connection(protocol_factory=None, server_hostname=None, host=None, po + else: + return txaio.create_future_error(RuntimeError("second connection fails completely")) + +- with mock.patch.object(event_loop, 'create_connection', create_connection): +- event_loop.create_connection = create_connection ++ with mock.patch.object(txaio.config.loop, 'create_connection', create_connection): ++ txaio.config.loop.create_connection = create_connection + + comp = Component( + transports=[ +@@ -119,8 +120,8 @@ def create_connection(protocol_factory=None, server_hostname=None, host=None, po + # if having trouble, try starting some logging (and use + # "py.test -s" to get real-time output) + # txaio.start_logging(level="debug") +- f = comp.start(loop=event_loop) +- txaio.config.loop = event_loop ++ f = comp.start(loop=asyncio.get_event_loop()) ++ txaio.config.loop = asyncio.get_event_loop() + + # now that we've started connecting, we *should* be able + # to connetion_lost our transport .. but we do a +@@ -151,4 +152,4 @@ def done(f): + txaio.config.loop = orig_loop + f.add_done_callback(done) + +- event_loop.run_until_complete(finished) ++ asyncio.get_event_loop().run_until_complete(finished)