1
0

chore: replace calls to asyncio.iscoroutinefunction

Replace calls to deprecated asyncio.iscoroutinefunction with calls to
inspect.iscoroutinefunction to prevent the following deprecation
warnings from showing up if running with Python 3.14:
```
/home/user/code/electrum-fork/electrum/util.py:1225: DeprecationWarning: 'asyncio.iscoroutinefunction' is deprecated and slated for removal in Python 3.16; use inspect.iscoroutinefunction() instead
  assert asyncio.iscoroutinefunction(func), 'func needs to be a coroutine'
/home/user/code/electrum-fork/electrum/util.py:507: DeprecationWarning: 'asyncio.iscoroutinefunction' is deprecated and slated for removal in Python 3.16; use inspect.iscoroutinefunction() instead
  if asyncio.iscoroutinefunction(func):
/home/user/code/electrum-fork/electrum/util.py:1246: DeprecationWarning: 'asyncio.iscoroutinefunction' is deprecated and slated for removal in Python 3.16; use inspect.iscoroutinefunction() instead
  assert asyncio.iscoroutinefunction(func), 'func needs to be a coroutine'
/home/user/code/electrum-fork/electrum/lnpeer.py:272: DeprecationWarning: 'asyncio.iscoroutinefunction' is deprecated and slated for removal in Python 3.16; use inspect.iscoroutinefunction() instead
  assert asyncio.iscoroutinefunction(func), 'func needs to be a coroutine'
/home/user/code/electrum-fork/electrum/util.py:1225: DeprecationWarning: 'asyncio.iscoroutinefunction' is deprecated and slated for removal in Python 3.16; use inspect.iscoroutinefunction() instead
  assert asyncio.iscoroutinefunction(func), 'func needs to be a coroutine'
/home/user/code/electrum-fork/electrum/util.py:507: DeprecationWarning: 'asyncio.iscoroutinefunction' is deprecated and slated for removal in Python 3.16; use inspect.iscoroutinefunction() instead
  if asyncio.iscoroutinefunction(func):
```
This commit is contained in:
f321x
2025-09-05 10:26:58 +02:00
parent 4a9b960ad8
commit e7bb75bc3e
4 changed files with 12 additions and 9 deletions

View File

@@ -2204,7 +2204,7 @@ def plugin_command(s, plugin_name):
name = plugin_name + '_' + func.__name__ name = plugin_name + '_' + func.__name__
if name in known_commands or hasattr(Commands, name): if name in known_commands or hasattr(Commands, name):
raise Exception(f"Command name {name} already exists. Plugin commands should not overwrite other commands.") raise Exception(f"Command name {name} already exists. Plugin commands should not overwrite other commands.")
assert asyncio.iscoroutinefunction(func), f"Plugin commands must be a coroutine: {name}" assert inspect.iscoroutinefunction(func), f"Plugin commands must be a coroutine: {name}"
@command(s) @command(s)
@wraps(func) @wraps(func)

View File

@@ -36,6 +36,7 @@ import queue
import asyncio import asyncio
from typing import Optional, TYPE_CHECKING, Sequence, Union, Dict, Mapping, Callable, List, Set from typing import Optional, TYPE_CHECKING, Sequence, Union, Dict, Mapping, Callable, List, Set
import concurrent.futures import concurrent.futures
import inspect
from PyQt6.QtGui import QPixmap, QKeySequence, QIcon, QCursor, QFont, QFontMetrics, QAction, QShortcut from PyQt6.QtGui import QPixmap, QKeySequence, QIcon, QCursor, QFont, QFontMetrics, QAction, QShortcut
from PyQt6.QtCore import Qt, QRect, QStringListModel, QSize, pyqtSignal, QTimer from PyQt6.QtCore import Qt, QRect, QStringListModel, QSize, pyqtSignal, QTimer
@@ -2734,7 +2735,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListener):
Registers a callback that will be called when the wallet is closed. If the callback Registers a callback that will be called when the wallet is closed. If the callback
returns a string it will be shown to the user as a warning to prevent them closing the wallet. returns a string it will be shown to the user as a warning to prevent them closing the wallet.
""" """
assert not asyncio.iscoroutinefunction(callback) assert not inspect.iscoroutinefunction(callback)
def warning_callback() -> Optional[str]: def warning_callback() -> Optional[str]:
try: try:
return callback() return callback()

View File

@@ -13,6 +13,7 @@ from typing import Tuple, Dict, TYPE_CHECKING, Optional, Union, Set, Callable, A
from datetime import datetime from datetime import datetime
import functools import functools
from functools import partial from functools import partial
import inspect
import electrum_ecc as ecc import electrum_ecc as ecc
from electrum_ecc import ecdsa_sig64_from_r_and_s, ecdsa_der_sig_from_ecdsa_sig64, ECPubkey from electrum_ecc import ecdsa_sig64_from_r_and_s, ecdsa_der_sig_from_ecdsa_sig64, ECPubkey
@@ -256,7 +257,7 @@ class Peer(Logger, EventListener):
payload['sender_node_id'] = self.pubkey payload['sender_node_id'] = self.pubkey
# note: the message handler might be async or non-async. In either case, by default, # note: the message handler might be async or non-async. In either case, by default,
# we wait for it to complete before we return, i.e. before the next message is processed. # we wait for it to complete before we return, i.e. before the next message is processed.
if asyncio.iscoroutinefunction(f): if inspect.iscoroutinefunction(f):
async with AsyncHangDetector( async with AsyncHangDetector(
message=f"message handler still running for {message_type.upper()}", message=f"message handler still running for {message_type.upper()}",
logger=self.logger, logger=self.logger,
@@ -269,7 +270,7 @@ class Peer(Logger, EventListener):
"""Makes a message handler non-blocking: while processing the message, """Makes a message handler non-blocking: while processing the message,
the message_loop keeps processing subsequent incoming messages asynchronously. the message_loop keeps processing subsequent incoming messages asynchronously.
""" """
assert asyncio.iscoroutinefunction(func), 'func needs to be a coroutine' assert inspect.iscoroutinefunction(func), 'func needs to be a coroutine'
@functools.wraps(func) @functools.wraps(func)
async def wrapper(self: 'Peer', *args, **kwargs): async def wrapper(self: 'Peer', *args, **kwargs):
return await self.taskgroup.spawn(func(self, *args, **kwargs)) return await self.taskgroup.spawn(func(self, *args, **kwargs))

View File

@@ -54,6 +54,7 @@ from abc import abstractmethod, ABC
import enum import enum
from contextlib import nullcontext from contextlib import nullcontext
import traceback import traceback
import inspect
import aiohttp import aiohttp
from aiohttp_socks import ProxyConnector, ProxyType from aiohttp_socks import ProxyConnector, ProxyType
@@ -504,7 +505,7 @@ def profiler(func=None, *, min_threshold: Union[int, float, None] = None):
if min_threshold is None or t > min_threshold: if min_threshold is None or t > min_threshold:
_profiler_logger.debug(f"{func.__qualname__} {t:,.4f} sec") _profiler_logger.debug(f"{func.__qualname__} {t:,.4f} sec")
if asyncio.iscoroutinefunction(func): if inspect.iscoroutinefunction(func):
async def do_profile(*args, **kw_args): async def do_profile(*args, **kw_args):
timer_start() timer_start()
o = await func(*args, **kw_args) o = await func(*args, **kw_args)
@@ -1222,7 +1223,7 @@ def is_subpath(long_path: str, short_path: str) -> bool:
def log_exceptions(func): def log_exceptions(func):
"""Decorator to log AND re-raise exceptions.""" """Decorator to log AND re-raise exceptions."""
assert asyncio.iscoroutinefunction(func), 'func needs to be a coroutine' assert inspect.iscoroutinefunction(func), 'func needs to be a coroutine'
@functools.wraps(func) @functools.wraps(func)
async def wrapper(*args, **kwargs): async def wrapper(*args, **kwargs):
@@ -1243,7 +1244,7 @@ def log_exceptions(func):
def ignore_exceptions(func): def ignore_exceptions(func):
"""Decorator to silently swallow all exceptions.""" """Decorator to silently swallow all exceptions."""
assert asyncio.iscoroutinefunction(func), 'func needs to be a coroutine' assert inspect.iscoroutinefunction(func), 'func needs to be a coroutine'
@functools.wraps(func) @functools.wraps(func)
async def wrapper(*args, **kwargs): async def wrapper(*args, **kwargs):
@@ -1761,7 +1762,7 @@ def run_sync_function_on_asyncio_thread(func: Callable[[], Any], *, block: bool)
For any other thread, we only wait for completion if `block` is True. For any other thread, we only wait for completion if `block` is True.
""" """
assert not asyncio.iscoroutinefunction(func), "func must be a non-async function" assert not inspect.iscoroutinefunction(func), "func must be a non-async function"
asyncio_loop = get_asyncio_loop() asyncio_loop = get_asyncio_loop()
if get_running_loop() == asyncio_loop: # we are running on the asyncio thread if get_running_loop() == asyncio_loop: # we are running on the asyncio thread
func() func()
@@ -1964,7 +1965,7 @@ class CallbackManager(Logger):
with self.callback_lock: with self.callback_lock:
callbacks = self.callbacks[event][:] callbacks = self.callbacks[event][:]
for callback in callbacks: for callback in callbacks:
if asyncio.iscoroutinefunction(callback): # async cb if inspect.iscoroutinefunction(callback): # async cb
fut = asyncio.run_coroutine_threadsafe(callback(*args), loop) fut = asyncio.run_coroutine_threadsafe(callback(*args), loop)
def on_done(fut_: concurrent.futures.Future): def on_done(fut_: concurrent.futures.Future):