tgalal / yowsup

The WhatsApp lib
GNU General Public License v3.0
7.06k stars 2.23k forks source link

Replace asyncore with asyncio for better support #3264

Open SimchaSucot opened 4 months ago

SimchaSucot commented 4 months ago

Pull Request Description

Title: Migration from asyncore to asyncio for Compatibility with Python 3.12 and Above

Description:

This pull request migrates the AsyncoreConnectionDispatcher class from using the deprecated asyncore module to the modern asyncio module. The asyncore module has been removed in Python 3.12, necessitating this update to ensure compatibility with current and future versions of Python.

Changes Made:

  1. Module Replacement:

    • Replaced all instances of asyncore with asyncio.
    • Updated import statements accordingly.
  2. Class Definition:

    • Removed inheritance from asyncore.dispatcher_with_send.
    • Updated the class to inherit only from YowConnectionDispatcher.
  3. Initialization:

    • Used super().__init__() for proper initialization in Python 3.
    • Added initialization of the asyncio event loop with self.loop = asyncio.get_event_loop().
    • Introduced self.sock = None to maintain a reference to the socket.
  4. sendData Method:

    • Replaced the synchronous send logic with an asynchronous coroutine _send_data.
    • Used self.sock.sendall(data) to send data over the socket.
    • Wrapped the coroutine call with asyncio.run(self._send_data(data)) in sendData.
  5. connect Method:

    • Moved connection logic to an asynchronous coroutine _connect.
    • Created a non-blocking socket and used await self.loop.sock_connect(self.sock, host) for the connection.
    • Added error handling to log connection failures.
    • Used self.loop.run_until_complete(self._connect(host)) to run the coroutine in connect.
  6. handle_connect Method:

    • Retained the same logic to update connection status and invoke the callback.
  7. handle_close Method:

    • Updated to check if the socket is initialized before attempting to close it.
    • Ensured the socket is properly closed and the connection status is updated.
  8. handle_error Method:

    • Retained the same logic to log errors and close the connection.
  9. handle_read Method:

    • Moved reading logic to an asynchronous coroutine _handle_read.
    • Used await self.loop.sock_recv(self.sock, 1024) for non-blocking read.
    • Added error handling for read failures.
    • Wrapped the coroutine call with asyncio.run(self._handle_read()) in handle_read.
  10. disconnect Method:

    • Retained the same logic to close the connection.

Why These Changes Are Required:

Testing and Verification:

Conclusion:

This pull request updates the AsyncoreConnectionDispatcher class to use asyncio, ensuring compatibility with Python 3.12 and above while maintaining existing functionalities and structure. This migration is essential for the long-term maintenance and support of the codebase, aligning it with modern Python standards for asynchronous programming.

BonifacioCalindoro commented 3 months ago

Very good PR