__init__.py 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. # Copyright (C) 2023 The Qt Company Ltd.
  2. # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
  3. from __future__ import annotations
  4. from .events import (
  5. QAsyncioEventLoopPolicy, QAsyncioEventLoop, QAsyncioHandle, QAsyncioTimerHandle
  6. )
  7. from .futures import QAsyncioFuture
  8. from .tasks import QAsyncioTask
  9. from typing import Coroutine, Any
  10. import asyncio
  11. __all__ = [
  12. "QAsyncioEventLoopPolicy", "QAsyncioEventLoop",
  13. "QAsyncioHandle", "QAsyncioTimerHandle",
  14. "QAsyncioFuture", "QAsyncioTask"
  15. ]
  16. def run(coro: Coroutine | None = None,
  17. keep_running: bool = True, quit_qapp: bool = True, *, handle_sigint: bool = False,
  18. debug: bool | None = None) -> Any:
  19. """
  20. Run the QtAsyncio event loop.
  21. If there is no instance of a QCoreApplication, QGuiApplication or
  22. QApplication yet, a new instance of QCoreApplication is created.
  23. :param coro: The coroutine to run. Optional if keep_running is
  24. True.
  25. :param keep_running: If True, QtAsyncio (the asyncio event loop) will
  26. continue running after the coroutine finished, or
  27. run "forever" if no coroutine was provided.
  28. If False, QtAsyncio will stop after the
  29. coroutine finished. A coroutine must be provided if
  30. this argument is set to False.
  31. :param quit_qapp: If True, the QCoreApplication will quit when
  32. QtAsyncio (the asyncio event loop) stops.
  33. If False, the QCoreApplication will remain active
  34. after QtAsyncio stops, and can continue to be used.
  35. :param handle_sigint: If True, the SIGINT signal will be handled by the
  36. event loop, causing it to stop.
  37. :param debug: If True, the event loop will run in debug mode.
  38. If False, the event loop will run in normal mode.
  39. If None, the default behavior is used.
  40. """
  41. # Event loop policies are expected to be deprecated with Python 3.13, with
  42. # subsequent removal in Python 3.15. At that point, part of the current
  43. # logic of the QAsyncioEventLoopPolicy constructor will have to be moved
  44. # here and/or to a loop factory class (to be provided as an argument to
  45. # asyncio.run()). In particular, this concerns the logic of setting up the
  46. # QCoreApplication and the SIGINT handler.
  47. #
  48. # More details:
  49. # https://discuss.python.org/t/removing-the-asyncio-policy-system-asyncio-set-event-loop-policy-in-python-3-15/37553 # noqa: E501
  50. default_policy = asyncio.get_event_loop_policy()
  51. asyncio.set_event_loop_policy(
  52. QAsyncioEventLoopPolicy(quit_qapp=quit_qapp, handle_sigint=handle_sigint))
  53. ret = None
  54. exc = None
  55. if keep_running:
  56. if coro:
  57. asyncio.ensure_future(coro)
  58. asyncio.get_event_loop().run_forever()
  59. else:
  60. if coro:
  61. ret = asyncio.run(coro, debug=debug)
  62. else:
  63. exc = RuntimeError(
  64. "QtAsyncio was set not to keep running after the coroutine "
  65. "finished, but no coroutine was provided.")
  66. asyncio.set_event_loop_policy(default_policy)
  67. if ret:
  68. return ret
  69. if exc:
  70. raise exc