From be2cd02e54f96aec127e5f101e7b54063fbac6ec Mon Sep 17 00:00:00 2001 From: SomberNight Date: Fri, 10 Jan 2025 13:26:39 +0000 Subject: [PATCH] some clean-ups now that we require python 3.10 --- electrum/daemon.py | 4 ++-- electrum/network.py | 3 ++- electrum/plugin.py | 13 +++---------- electrum/util.py | 30 +----------------------------- tests/qt_util.py | 4 +--- 5 files changed, 9 insertions(+), 45 deletions(-) diff --git a/electrum/daemon.py b/electrum/daemon.py index 825f2b058..f399d01fe 100644 --- a/electrum/daemon.py +++ b/electrum/daemon.py @@ -46,7 +46,7 @@ from .network import Network from .util import (json_decode, to_bytes, to_string, profiler, standardize_path, constant_time_compare, InvalidPassword) from .invoices import PR_PAID, PR_EXPIRED from .util import log_exceptions, ignore_exceptions, randrange, OldTaskGroup, UserFacingException, JsonRPCError -from .util import EventListener, event_listener, traceback_format_exception +from .util import EventListener, event_listener from .wallet import Wallet, Abstract_Wallet from .storage import WalletStorage from .wallet_db import WalletDB, WalletRequiresSplit, WalletRequiresUpgrade, WalletUnfinished @@ -264,7 +264,7 @@ class AuthenticatedServer(Logger): 'message': "internal error while executing RPC", 'data': { "exception": repr(e), - "traceback": "".join(traceback_format_exception(e)), + "traceback": "".join(traceback.format_exception(e)), }, } return web.json_response(response) diff --git a/electrum/network.py b/electrum/network.py index 2b10b6ad3..48b824e82 100644 --- a/electrum/network.py +++ b/electrum/network.py @@ -38,6 +38,7 @@ from concurrent import futures import copy import functools from enum import IntEnum +from contextlib import nullcontext import aiorpcx from aiorpcx import ignore_after, NetAddress @@ -47,7 +48,7 @@ from . import util from .util import (log_exceptions, ignore_exceptions, OldTaskGroup, bfh, make_aiohttp_session, send_exception_to_crash_reporter, is_hash256_str, is_non_negative_integer, MyEncoder, NetworkRetryManager, - nullcontext, error_text_str_to_safe_str) + error_text_str_to_safe_str) from .bitcoin import COIN, DummyAddress, DummyAddressUsedInTxException from . import constants from . import blockchain diff --git a/electrum/plugin.py b/electrum/plugin.py index 67eb45867..f9eca84b8 100644 --- a/electrum/plugin.py +++ b/electrum/plugin.py @@ -127,10 +127,7 @@ class Plugins(DaemonThread): # sys.modules needs to be modified for relative imports to work # see https://stackoverflow.com/a/50395128 sys.modules[path] = module - if sys.version_info >= (3, 10): - spec.loader.exec_module(module) - else: - module = spec.loader.load_module(path) + spec.loader.exec_module(module) except Exception as e: raise Exception(f"Error pre-loading {path}: {repr(e)}") from e return module @@ -209,12 +206,8 @@ class Plugins(DaemonThread): if name in self.external_plugin_metadata: raise Exception(f"duplicate plugins for name={name}") module_path = f'electrum_external_plugins.{name}' - if sys.version_info >= (3, 10): - spec = zipfile.find_spec(name) - module = self.exec_module_from_spec(spec, module_path) - else: - module = zipfile.load_module(name) - sys.modules[module_path] = module + spec = zipfile.find_spec(name) + module = self.exec_module_from_spec(spec, module_path) d = module.__dict__ gui_good = self.gui_name in d.get('available_for', []) if not gui_good: diff --git a/electrum/util.py b/electrum/util.py index 4571a6e0e..cbaefd8d6 100644 --- a/electrum/util.py +++ b/electrum/util.py @@ -52,6 +52,7 @@ from functools import partial from abc import abstractmethod, ABC import socket import enum +from contextlib import nullcontext import attr import aiohttp @@ -2067,35 +2068,6 @@ def test_read_write_permissions(path) -> None: raise IOError('echo sanity-check failed') -class nullcontext: - """Context manager that does no additional processing. - This is a ~backport of contextlib.nullcontext from Python 3.10 - """ - - def __init__(self, enter_result=None): - self.enter_result = enter_result - - def __enter__(self): - return self.enter_result - - def __exit__(self, *excinfo): - pass - - async def __aenter__(self): - return self.enter_result - - async def __aexit__(self, *excinfo): - pass - - -def traceback_format_exception(exc: BaseException) -> Sequence[str]: - """Compatibility wrapper for stdlib traceback.format_exception using python 3.10+ API.""" - if sys.version_info[:3] >= (3, 10): - return traceback.format_exception(exc) - else: - return traceback.format_exception(type(exc), value=exc, tb=exc.__traceback__) - - class classproperty(property): """~read-only class-level @property from https://stackoverflow.com/a/13624858 by denis-ryzhkov diff --git a/tests/qt_util.py b/tests/qt_util.py index 2863425ce..cad939ed6 100644 --- a/tests/qt_util.py +++ b/tests/qt_util.py @@ -6,8 +6,6 @@ from unittest import SkipTest from PyQt6.QtCore import QCoreApplication, QMetaObject, Qt, pyqtSlot, QObject -from electrum.util import traceback_format_exception - class TestQCoreApplication(QCoreApplication): @pyqtSlot() @@ -78,7 +76,7 @@ def qt_test(func): if not res: self._e = Exception('testcase timed out') if self._e: - print("".join(traceback_format_exception(self._e))) + print("".join(traceback.format_exception(self._e))) # deallocate stored exception from qt thread otherwise we SEGV garbage collector # instead, re-create using the exception message, special casing AssertionError and SkipTest e = None