diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a0511af..4e714bb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -20,7 +20,7 @@ jobs: strategy: matrix: os: [Ubuntu, Windows, MacOS] - python-version: ["3.8", "3.9", "3.10"] + python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14-dev"] qt-version: ["pyside2", "pyside6", "pyqt5", "pyqt6"] include: - os: Ubuntu @@ -29,6 +29,9 @@ jobs: image: windows-2022 - os: MacOS image: macos-14 + - os: MacOS + qt-version: pyside2 + image: macos-13 fail-fast: false defaults: run: diff --git a/qasync/__init__.py b/qasync/__init__.py index ef9264b..4e5bbea 100644 --- a/qasync/__init__.py +++ b/qasync/__init__.py @@ -817,29 +817,30 @@ def wrapper(*args, **kwargs): return outer_decorator - -class QEventLoopPolicyMixin: - def new_event_loop(self): - return QEventLoop(QApplication.instance() or QApplication(sys.argv)) - - -class DefaultQEventLoopPolicy( - QEventLoopPolicyMixin, - asyncio.DefaultEventLoopPolicy, -): - pass - - @contextlib.contextmanager -def _set_event_loop_policy(policy): - old_policy = asyncio.get_event_loop_policy() - asyncio.set_event_loop_policy(policy) +def _use_qeventloop(loop_factory): + app = QApplication.instance() or QApplication([sys.argv]) + if loop_factory is None: + loop = QEventLoop(app) + else: + loop = loop_factory(app) + try: + old_loop = asyncio.get_event_loop() + except RuntimeError: # No current event loop + old_loop = None + asyncio.set_event_loop(loop) try: - yield + yield loop finally: - asyncio.set_event_loop_policy(old_policy) - + loop.close() + asyncio.set_event_loop(old_loop) -def run(*args, **kwargs): - with _set_event_loop_policy(DefaultQEventLoopPolicy()): - return asyncio.run(*args, **kwargs) +# A run function matching the signature of asyncio.run +def run(main_coro, *, debug=None, loop_factory=None): + """ + Run the given coroutine using a QEventLoop. + """ + with _use_qeventloop(loop_factory) as loop: + if debug is not None: + loop.set_debug(debug) + return loop.run_until_complete(main_coro) diff --git a/tests/test_run.py b/tests/test_run.py new file mode 100644 index 0000000..b7ed047 --- /dev/null +++ b/tests/test_run.py @@ -0,0 +1,18 @@ +import qasync +import asyncio +import os +from qasync import QApplication + +def test_run_with_contextmanager(application): + async def coro(): + event_loop = asyncio.get_event_loop() + assert type(event_loop).__name__ == "QIOCPEventLoop" if os.name == 'nt' else "QSelectorEventLoop" + await asyncio.sleep(0) + + qasync.run(coro()) + + try: + event_loop = asyncio.get_event_loop() + except: + event_loop = None + assert type(event_loop).__name__ != "QIOCPEventLoop" if os.name == 'nt' else "QSelectorEventLoop"