lint: ruff cleanup pass across bal/ and tests/
- Sort imports and fix pyproject ruff config (per-file ignores for intentional Qt/core exceptions) - Mark Heirs.validate_* helpers as @staticmethod - Clean up dead code, rename shadowing vars, use raise ... from - Add AGENTS.md with env/lint/test/release guidance
This commit is contained in:
@@ -102,7 +102,7 @@ def validate_op_return_hex(data_hex: str) -> None:
|
||||
try:
|
||||
data = bytes.fromhex(data_hex)
|
||||
except ValueError:
|
||||
raise NotAnAddress(f"OP_RETURN data is not valid hex: {data_hex}")
|
||||
raise NotAnAddress(f"OP_RETURN data is not valid hex: {data_hex}") from None
|
||||
if len(data) > 80:
|
||||
raise NotAnAddress(
|
||||
f"OP_RETURN data too long ({len(data)} bytes, max 80)"
|
||||
@@ -205,7 +205,7 @@ def prepare_transactions(locktimes, available_utxos, fees, wallet):
|
||||
change = get_change_output(wallet, in_amount, out_amount, fee)
|
||||
if change:
|
||||
outputs.append(change)
|
||||
for i in range(0, 100):
|
||||
for _ in range(0, 100):
|
||||
random.shuffle(outputs)
|
||||
|
||||
#op_return_text = "Hello Bal!"
|
||||
@@ -281,7 +281,7 @@ def invalidate_inheritance_transactions(wallet):
|
||||
del dtxs[txid]
|
||||
|
||||
utxos = {}
|
||||
for txid, tx in dtxs.items():
|
||||
for _, tx in dtxs.items():
|
||||
get_utxos_from_inputs(tx.inputs(), tx, utxos)
|
||||
|
||||
utxos = sorted(utxos.items(), key=lambda item: len(item[1]))
|
||||
@@ -727,7 +727,7 @@ class Heirs(dict, Logger):
|
||||
)
|
||||
break
|
||||
except Exception:
|
||||
raise e
|
||||
raise
|
||||
total_fees = 0
|
||||
total_fees_real = 0
|
||||
total_in = 0
|
||||
@@ -853,6 +853,7 @@ class Heirs(dict, Logger):
|
||||
except AttributeError:
|
||||
return None
|
||||
|
||||
@staticmethod
|
||||
def validate_address(address):
|
||||
if is_op_return_address(address):
|
||||
data_hex = address[len(OP_RETURN_PREFIX):]
|
||||
@@ -862,24 +863,27 @@ class Heirs(dict, Logger):
|
||||
raise NotAnAddress(f"not an address,{address}")
|
||||
return address
|
||||
|
||||
@staticmethod
|
||||
def validate_amount(amount):
|
||||
try:
|
||||
famount = float(amount[:-1]) if Util.is_perc(amount) else float(amount)
|
||||
if famount <= 0.00000001:
|
||||
raise AmountNotValid(f"amount have to be positive {famount} < 0")
|
||||
except Exception as e:
|
||||
raise AmountNotValid(f"amount not properly formatted, {e}")
|
||||
raise AmountNotValid(f"amount not properly formatted, {e}") from e
|
||||
return amount
|
||||
|
||||
@staticmethod
|
||||
def validate_locktime(locktime, timestamp_to_check=False):
|
||||
try:
|
||||
if timestamp_to_check:
|
||||
if Util.parse_locktime_string(locktime, None) < timestamp_to_check:
|
||||
raise HeirExpiredException()
|
||||
except Exception as e:
|
||||
raise LocktimeNotValid(f"locktime string not properly formatted, {e}")
|
||||
raise LocktimeNotValid(f"locktime string not properly formatted, {e}") from e
|
||||
return locktime
|
||||
|
||||
@staticmethod
|
||||
def validate_heir(k, v, timestamp_to_check=False):
|
||||
address = Heirs.validate_address(v[HEIR_ADDRESS])
|
||||
if is_op_return_address(v[HEIR_ADDRESS]):
|
||||
@@ -889,6 +893,7 @@ class Heirs(dict, Logger):
|
||||
locktime = Heirs.validate_locktime(v[HEIR_LOCKTIME], timestamp_to_check)
|
||||
return (address, amount, locktime)
|
||||
|
||||
@staticmethod
|
||||
def _validate(data, timestamp_to_check=False):
|
||||
|
||||
for k, v in list(data.items()):
|
||||
|
||||
@@ -477,14 +477,14 @@ class BalTimestamp:
|
||||
We clamp out-of-range timestamps to INT32_MAX, mirroring Electrum's own
|
||||
``get_max_allowed_timestamp`` workaround (see Electrum issue #6170).
|
||||
"""
|
||||
INT32_MAX = 2 ** 31 - 1
|
||||
int32_max = 2 ** 31 - 1
|
||||
try:
|
||||
return datetime.fromtimestamp(ts)
|
||||
except (OSError, OverflowError, ValueError):
|
||||
try:
|
||||
return datetime.fromtimestamp(min(int(ts), INT32_MAX))
|
||||
return datetime.fromtimestamp(min(int(ts), int32_max))
|
||||
except (OSError, OverflowError, ValueError):
|
||||
return datetime.fromtimestamp(INT32_MAX)
|
||||
return datetime.fromtimestamp(int32_max)
|
||||
|
||||
def to_date(self, from_date=None, reverse=False):
|
||||
"""Resolve to a ``datetime``.
|
||||
|
||||
@@ -400,14 +400,14 @@ class Util:
|
||||
def get_lowest_valid_tx(available_utxos, will):
|
||||
"""Placeholder kept from the original code (sorts the will by locktime)."""
|
||||
will = sorted(will.items(), key=lambda x: x[1]["tx"].locktime)
|
||||
for txid, willitem in will.items():
|
||||
for _txid, _willitem in will.items():
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def get_locktimes(will):
|
||||
"""Return the distinct locktimes used by the transactions in ``will``."""
|
||||
locktimes = {}
|
||||
for txid, willitem in will.items():
|
||||
for _, willitem in will.items():
|
||||
locktimes[willitem["tx"].locktime] = True
|
||||
return locktimes.keys()
|
||||
|
||||
@@ -446,7 +446,7 @@ class Util:
|
||||
def get_will_spent_utxos(will):
|
||||
"""Collect every input spent by any transaction in ``will``."""
|
||||
utxos = []
|
||||
for txid, willitem in will.items():
|
||||
for _, willitem in will.items():
|
||||
utxos += willitem["tx"].inputs()
|
||||
|
||||
return utxos
|
||||
|
||||
@@ -43,9 +43,9 @@ from electrum.util import (
|
||||
bfh,
|
||||
)
|
||||
|
||||
from .heirs import WillExecutorFeeTooHighException
|
||||
from .util import Util
|
||||
from .willexecutors import Willexecutors
|
||||
from .heirs import WillExecutorFeeTooHighException
|
||||
|
||||
MIN_LOCKTIME = 1
|
||||
MIN_BLOCK = 1
|
||||
@@ -220,13 +220,8 @@ class Will:
|
||||
if ow.we["url"] == nw.we["url"]:
|
||||
if int(ow.we["base_fee"]) > int(nw.we["base_fee"]):
|
||||
return anticipate
|
||||
else:
|
||||
if int(ow.tx_fees) != int(nw.tx_fees):
|
||||
return anticipate
|
||||
else:
|
||||
ow.tx.locktime
|
||||
else:
|
||||
ow.tx.locktime
|
||||
elif int(ow.tx_fees) != int(nw.tx_fees):
|
||||
return anticipate
|
||||
else:
|
||||
if nw.we == ow.we:
|
||||
if not Util.cmp_heirs_by_values(ow.heirs, nw.heirs, [0, 3]):
|
||||
@@ -512,7 +507,7 @@ class Will:
|
||||
|
||||
@staticmethod
|
||||
def is_new(will):
|
||||
for wid, w in will.items():
|
||||
for _wid, w in will.items():
|
||||
if w.get_status("VALID") and not w.get_status("COMPLETE"):
|
||||
return True
|
||||
|
||||
@@ -784,7 +779,7 @@ class Will:
|
||||
timestamp_to_check: Reference UNIX timestamp (usually "now").
|
||||
"""
|
||||
_logger.info("check if some transaction is expired")
|
||||
for prevout_str, wid in all_inputs_min_locktime.items():
|
||||
for _inputs, wid in all_inputs_min_locktime.items():
|
||||
for w in wid:
|
||||
if w[1].get_status("VALID"):
|
||||
locktime = int(wid[0][1].tx.locktime)
|
||||
|
||||
@@ -389,7 +389,7 @@ class Willexecutors:
|
||||
except Exception as e:
|
||||
_logger.debug(f"error:{e}")
|
||||
if str(e) == "already present":
|
||||
raise Willexecutors.AlreadyPresentException()
|
||||
raise Willexecutors.AlreadyPresentException() from None
|
||||
out = False
|
||||
willexecutor["broadcast_status"] = _("Failed")
|
||||
|
||||
@@ -485,8 +485,7 @@ class Willexecutors:
|
||||
Returns:
|
||||
The same ``willexecutors`` mapping, updated in place.
|
||||
"""
|
||||
from concurrent.futures import ThreadPoolExecutor, wait
|
||||
from concurrent.futures import FIRST_COMPLETED
|
||||
from concurrent.futures import FIRST_COMPLETED, ThreadPoolExecutor, wait
|
||||
|
||||
items = list(willexecutors.items())
|
||||
if not items:
|
||||
@@ -566,8 +565,7 @@ class Willexecutors:
|
||||
Returns ``{url: (ok, exception_or_None)}`` for the servers that
|
||||
answered in time (timed-out servers are reported via ``on_timeout``).
|
||||
"""
|
||||
from concurrent.futures import ThreadPoolExecutor, wait
|
||||
from concurrent.futures import FIRST_COMPLETED
|
||||
from concurrent.futures import FIRST_COMPLETED, ThreadPoolExecutor, wait
|
||||
|
||||
targets = [(url, we) for url, we in willexecutors.items() if "txs" in we]
|
||||
results = {}
|
||||
@@ -684,8 +682,7 @@ class Willexecutors:
|
||||
Returns ``{wid: (result_or_None, exception_or_None)}`` for the servers
|
||||
that answered in time.
|
||||
"""
|
||||
from concurrent.futures import ThreadPoolExecutor, wait
|
||||
from concurrent.futures import FIRST_COMPLETED
|
||||
from concurrent.futures import FIRST_COMPLETED, ThreadPoolExecutor, wait
|
||||
|
||||
targets = [(wid, url) for wid, url in items if url]
|
||||
results = {}
|
||||
|
||||
@@ -9,11 +9,12 @@ to "check in" before the locktime expires. This module turns the event data
|
||||
into an RFC-5545 .ics file and opens it with the OS default application.
|
||||
"""
|
||||
|
||||
from .common import *
|
||||
from .common import _, _logger # underscore names are not re-exported by "import *"
|
||||
from PyQt6.QtGui import QAction
|
||||
from PyQt6.QtWidgets import QToolButton
|
||||
|
||||
from .common import *
|
||||
from .common import _, _logger # underscore names are not re-exported by "import *"
|
||||
|
||||
|
||||
class BalCalendarButton(QToolButton):
|
||||
"""A QToolButton with a dropdown menu for .ics calendar file actions.
|
||||
@@ -79,7 +80,8 @@ class BalCalendarButton(QToolButton):
|
||||
path = self._ensure_ics()
|
||||
if not path:
|
||||
return
|
||||
import shlex, subprocess
|
||||
import shlex
|
||||
import subprocess
|
||||
if self._bal_window.bal_plugin.is_basic_mode():
|
||||
app = self._bal_window.bal_plugin.CALENDAR_APP.default
|
||||
else:
|
||||
|
||||
@@ -27,65 +27,129 @@ from decimal import Decimal
|
||||
from functools import partial
|
||||
from typing import Any, Callable, Mapping, Optional, Union
|
||||
|
||||
from electrum.bitcoin import (NLOCKTIME_BLOCKHEIGHT_MAX, NLOCKTIME_MAX,
|
||||
NLOCKTIME_MIN)
|
||||
from electrum.bitcoin import NLOCKTIME_BLOCKHEIGHT_MAX, NLOCKTIME_MAX, NLOCKTIME_MIN
|
||||
from electrum.gui.qt.amountedit import BTCAmountEdit
|
||||
from electrum.gui.qt.main_window import ElectrumWindow, StatusBarButton
|
||||
from electrum.gui.qt.my_treeview import MyTreeView
|
||||
from electrum.gui.qt.password_dialog import PasswordDialog
|
||||
from electrum.gui.qt.transaction_dialog import TxDialog
|
||||
from electrum.gui.qt.util import (Buttons, CancelButton, ColorScheme,
|
||||
EnterButton, HelpButton, MessageBoxMixin,
|
||||
OkButton, TaskThread, WindowModalDialog,
|
||||
char_width_in_lineedit, getSaveFileName,
|
||||
import_meta_gui, read_QIcon_from_bytes,
|
||||
read_QPixmap_from_bytes, webopen)
|
||||
from electrum.gui.qt.util import (
|
||||
Buttons,
|
||||
CancelButton,
|
||||
ColorScheme,
|
||||
EnterButton,
|
||||
HelpButton,
|
||||
MessageBoxMixin,
|
||||
OkButton,
|
||||
TaskThread,
|
||||
WindowModalDialog,
|
||||
char_width_in_lineedit,
|
||||
getSaveFileName,
|
||||
import_meta_gui,
|
||||
read_QIcon_from_bytes,
|
||||
read_QPixmap_from_bytes,
|
||||
webopen,
|
||||
)
|
||||
from electrum.i18n import _
|
||||
from electrum.logging import get_logger
|
||||
from electrum.network import BestEffortRequestFailed, Network, TxBroadcastError
|
||||
from electrum.payment_identifier import PaymentIdentifier
|
||||
from electrum.plugin import hook
|
||||
from electrum.transaction import SerializationError, Transaction, tx_from_any
|
||||
from electrum.util import (DECIMAL_POINT, FileExportFailed, UserCancelled,
|
||||
decimal_point_to_base_unit_name, read_json_file,
|
||||
write_json_file)
|
||||
from PyQt6.QtCore import (QDateTime, QModelIndex, QPersistentModelIndex, QSize,
|
||||
Qt, QTimer, pyqtSignal)
|
||||
from PyQt6.QtGui import (QColor, QPainter, QPalette, QStandardItem,
|
||||
QStandardItemModel)
|
||||
from PyQt6.QtWidgets import (QAbstractItemView, QAbstractSpinBox, QCheckBox,
|
||||
QComboBox, QDateTimeEdit, QGridLayout, QHBoxLayout,
|
||||
QInputDialog, QLabel, QLineEdit, QTextEdit, QMenu,
|
||||
QMenuBar, QPushButton, QScrollArea, QSizePolicy,
|
||||
QSpinBox, QStackedWidget, QStyle, QStyleOptionFrame,
|
||||
QVBoxLayout, QWidget, QDialog)
|
||||
from electrum.util import (
|
||||
DECIMAL_POINT,
|
||||
FileExportFailed,
|
||||
UserCancelled,
|
||||
decimal_point_to_base_unit_name,
|
||||
read_json_file,
|
||||
write_json_file,
|
||||
)
|
||||
from PyQt6.QtCore import (
|
||||
QDateTime,
|
||||
QModelIndex,
|
||||
QPersistentModelIndex,
|
||||
QSize,
|
||||
Qt,
|
||||
QTimer,
|
||||
pyqtSignal,
|
||||
)
|
||||
from PyQt6.QtGui import QColor, QPainter, QPalette, QStandardItem, QStandardItemModel
|
||||
from PyQt6.QtWidgets import (
|
||||
QAbstractItemView,
|
||||
QAbstractSpinBox,
|
||||
QCheckBox,
|
||||
QComboBox,
|
||||
QDateTimeEdit,
|
||||
QDialog,
|
||||
QGridLayout,
|
||||
QHBoxLayout,
|
||||
QInputDialog,
|
||||
QLabel,
|
||||
QLineEdit,
|
||||
QMenu,
|
||||
QMenuBar,
|
||||
QPushButton,
|
||||
QScrollArea,
|
||||
QSizePolicy,
|
||||
QSpinBox,
|
||||
QStackedWidget,
|
||||
QStyle,
|
||||
QStyleOptionFrame,
|
||||
QTextEdit,
|
||||
QVBoxLayout,
|
||||
QWidget,
|
||||
)
|
||||
|
||||
from ...core.heirs import (
|
||||
HEIR_DUST_AMOUNT,
|
||||
HEIR_REAL_AMOUNT,
|
||||
OP_RETURN_PREFIX,
|
||||
HeirAmountIsDustException,
|
||||
Heirs,
|
||||
WillExecutorFeeTooHighException,
|
||||
get_op_return_hex,
|
||||
is_op_return_address,
|
||||
validate_op_return_hex,
|
||||
)
|
||||
|
||||
# --- Core (GUI-free) logic layer ---
|
||||
from ...core.plugin_base import BalPlugin, BalTimestamp
|
||||
from ...core.heirs import (HEIR_DUST_AMOUNT, HEIR_REAL_AMOUNT,
|
||||
HeirAmountIsDustException, Heirs,
|
||||
OP_RETURN_PREFIX, is_op_return_address,
|
||||
get_op_return_hex, validate_op_return_hex,
|
||||
WillExecutorFeeTooHighException)
|
||||
from ...core.util import Util
|
||||
from ...core.will import (AmountException, HeirChangeException,
|
||||
HeirNotFoundException, NoHeirsException,
|
||||
NotCompleteWillException, NoWillExecutorNotPresent,
|
||||
TxFeesChangedException, Will,
|
||||
WillexecutorChangeException, WillExecutorNotPresent,
|
||||
WillExpiredException, WillItem, WillPostponedException)
|
||||
from ...core.willexecutors import Willexecutors
|
||||
from ...core.willexecutors import is_onion_url, is_tor_active # noqa: F401
|
||||
from ...core.will import (
|
||||
AmountException,
|
||||
HeirChangeException,
|
||||
HeirNotFoundException,
|
||||
NoHeirsException,
|
||||
NotCompleteWillException,
|
||||
NoWillExecutorNotPresent,
|
||||
TxFeesChangedException,
|
||||
Will,
|
||||
WillexecutorChangeException,
|
||||
WillExecutorNotPresent,
|
||||
WillExpiredException,
|
||||
WillItem,
|
||||
WillPostponedException,
|
||||
)
|
||||
from ...core.willexecutors import ( # noqa: F401
|
||||
Willexecutors,
|
||||
is_onion_url,
|
||||
is_tor_active,
|
||||
)
|
||||
|
||||
# --- Presentation helpers ---
|
||||
from .theme import server_status_text, server_status_tooltip, status_color
|
||||
from .window_utils import (bring_to_front, show_modal, show_on_top,
|
||||
stop_thread, top_level_of)
|
||||
from .window_utils import (
|
||||
bring_to_front,
|
||||
show_modal,
|
||||
show_on_top,
|
||||
stop_thread,
|
||||
top_level_of,
|
||||
)
|
||||
|
||||
_logger = get_logger(__name__)
|
||||
|
||||
|
||||
class shown_cv:
|
||||
class shown_cv: # noqa: N801 (intentionally lowercase: mirrors Qt signal naming)
|
||||
_type = bool
|
||||
|
||||
def __init__(self, value):
|
||||
|
||||
@@ -17,13 +17,16 @@ the few list classes they reference are imported lazily inside the methods that
|
||||
use them (see ``lists`` imports below).
|
||||
"""
|
||||
|
||||
from .calendar import BalCalendar, BalCalendarButton
|
||||
from .common import *
|
||||
from .common import _, _logger # underscore names are not re-exported by "import *"
|
||||
from .widgets import (BalCheckBox, BalLineEdit, BalTextEdit, BalTxFeesWidget,
|
||||
LockTimeWidget, PercAmountEdit, ThresholdTimeWidget,
|
||||
WillSettingsWidget, WillWidget, basic_reminder_offsets,
|
||||
compute_reminder_offsets)
|
||||
from .calendar import BalCalendar, BalCalendarButton
|
||||
from .widgets import (
|
||||
WillSettingsWidget,
|
||||
WillWidget,
|
||||
basic_reminder_offsets,
|
||||
compute_reminder_offsets,
|
||||
)
|
||||
|
||||
# NOTE: list views (HeirListWidget, PreviewList, WillExecutorWidget) are
|
||||
# imported lazily where needed to avoid a dialogs<->lists import cycle.
|
||||
|
||||
@@ -31,9 +34,7 @@ from .calendar import BalCalendar, BalCalendarButton
|
||||
class BalDialog(QDialog,MessageBoxMixin):
|
||||
_stopping = False
|
||||
def __init__(self, parent, bal_plugin, title=None, icon="icons/bal16x16.png"):
|
||||
import signal
|
||||
from PyQt6.QtCore import QMetaObject, Qt
|
||||
from PyQt6.QtWidgets import QApplication
|
||||
def handler(signum, frame):
|
||||
QMetaObject.invokeMethod(self, "close", Qt.ConnectionType.QueuedConnection)
|
||||
|
||||
@@ -49,7 +50,7 @@ class BalDialog(QDialog,MessageBoxMixin):
|
||||
self.setWindowTitle(title)
|
||||
# WindowModalDialog.__init__(self,parent)
|
||||
self.setWindowIcon(read_QIcon_from_bytes(bal_plugin.read_file(icon)))
|
||||
|
||||
|
||||
def closeEvent(self, event):
|
||||
self._stopping = True
|
||||
# NOTE: we deliberately do NOT stop ``self.thread`` here.
|
||||
@@ -701,7 +702,7 @@ class BalBuildWillDialog(BalDialog):
|
||||
return None, Will.invalidate_will(
|
||||
self.bal_window.willitems, self.bal_window.wallet, fee_per_byte
|
||||
)
|
||||
except NoHeirsException as e:
|
||||
except NoHeirsException:
|
||||
_logger.debug("no heirs")
|
||||
self.msg_set_checking("No Heirs")
|
||||
except NotCompleteWillException as e:
|
||||
|
||||
@@ -14,12 +14,13 @@ construction) for all business actions, so the heavy logic stays in ``window``
|
||||
and ``dialogs``.
|
||||
"""
|
||||
|
||||
from PyQt6.QtWidgets import QLineEdit as _QLineEdit
|
||||
from PyQt6.QtWidgets import QMessageBox, QStyledItemDelegate
|
||||
|
||||
from .common import *
|
||||
from .common import _, _logger # underscore names are not re-exported by "import *"
|
||||
from .widgets import BalCheckBox, PercAmountEdit, WillSettingsWidget
|
||||
from PyQt6.QtWidgets import QMessageBox
|
||||
from PyQt6.QtWidgets import QStyledItemDelegate, QLineEdit as _QLineEdit
|
||||
from .dialogs import BalBuildWillDialog, BalDialog
|
||||
from .widgets import BalCheckBox, WillSettingsWidget
|
||||
|
||||
|
||||
class HeirListWidget(MyTreeView, MessageBoxMixin):
|
||||
@@ -194,7 +195,7 @@ class HeirListWidget(MyTreeView, MessageBoxMixin):
|
||||
set_current = QPersistentModelIndex(idx)
|
||||
try:
|
||||
self.will_settings_widget.on_locktime_change()
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
pass
|
||||
self.set_current_idx(set_current)
|
||||
# FIXME refresh loses sort order; so set "default" here:
|
||||
@@ -214,15 +215,15 @@ class HeirListWidget(MyTreeView, MessageBoxMixin):
|
||||
menu.addAction(_("Import"), self.bal_window.import_heirs)
|
||||
menu.addAction(_("Export"), lambda: self.bal_window.export_heirs())
|
||||
|
||||
newHeirButton = QPushButton(_("New Heir"))
|
||||
newHeirButton.clicked.connect(self.bal_window.new_heir_dialog)
|
||||
new_heir_button = QPushButton(_("New Heir"))
|
||||
new_heir_button.clicked.connect(self.bal_window.new_heir_dialog)
|
||||
|
||||
widget = QWidget(self)
|
||||
layout = QHBoxLayout(widget)
|
||||
self.will_settings_widget = WillSettingsWidget(self.bal_window, self)
|
||||
|
||||
layout.addWidget(self.will_settings_widget)
|
||||
layout.addWidget(newHeirButton)
|
||||
layout.addWidget(new_heir_button)
|
||||
|
||||
toolbar.insertWidget(2, widget)
|
||||
|
||||
@@ -281,7 +282,7 @@ class PreviewList(MyTreeView, MessageBoxMixin):
|
||||
self.setModel(QStandardItemModel(self))
|
||||
self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
|
||||
self.sortByColumn(self.Columns.NAME, Qt.SortOrder.AscendingOrder)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
self.setSortingEnabled(True)
|
||||
|
||||
@@ -15,14 +15,17 @@ and cached in ``self.bal_windows``.
|
||||
"""
|
||||
|
||||
from electrum.gui.qt.main_window import StatusBarButton
|
||||
from PyQt6.QtWidgets import QLayout
|
||||
|
||||
from .common import *
|
||||
from .common import _, _logger # underscore names are not re-exported by "import *"
|
||||
from .common import read_QIcon_from_bytes
|
||||
from .common import ( # underscore names are not re-exported by "import *"
|
||||
_,
|
||||
_logger,
|
||||
read_QIcon_from_bytes,
|
||||
)
|
||||
from .dialogs import BalDialog
|
||||
from .widgets import BalCheckBox, BalLineEdit, BalSpinBox, BalTextEdit
|
||||
from .window import BalWindow
|
||||
from .dialogs import BalDialog
|
||||
from PyQt6.QtWidgets import QLayout
|
||||
|
||||
|
||||
def _window_key(window):
|
||||
@@ -88,9 +91,11 @@ class Plugin(BalPlugin):
|
||||
except Exception:
|
||||
return []
|
||||
try:
|
||||
from electrum.gui.qt.plugins_dialog import PluginsDialog
|
||||
from electrum.gui.qt.plugins_dialog import (
|
||||
PluginsDialog as plugins_dialog, # noqa: N813
|
||||
)
|
||||
except Exception:
|
||||
PluginsDialog = None
|
||||
plugins_dialog = None
|
||||
app = QApplication.instance()
|
||||
if app is None:
|
||||
return []
|
||||
@@ -106,7 +111,7 @@ class Plugin(BalPlugin):
|
||||
for w in app.topLevelWidgets():
|
||||
try:
|
||||
is_match = False
|
||||
if PluginsDialog is not None and isinstance(w, PluginsDialog):
|
||||
if plugins_dialog is not None and isinstance(w, plugins_dialog):
|
||||
is_match = True
|
||||
elif type(w).__name__ == "PluginsDialog":
|
||||
is_match = True
|
||||
@@ -142,17 +147,17 @@ class Plugin(BalPlugin):
|
||||
each is guarded independently.
|
||||
"""
|
||||
try:
|
||||
from PyQt6.QtWidgets import QDialog
|
||||
from PyQt6.QtWidgets import QDialog as qdialog # noqa: N813
|
||||
except Exception:
|
||||
QDialog = None
|
||||
qdialog = None
|
||||
# 1) reject() / done(): the reliable way to end an exec() modal loop.
|
||||
if QDialog is not None and isinstance(d, QDialog):
|
||||
if qdialog is not None and isinstance(d, qdialog):
|
||||
try:
|
||||
d.reject()
|
||||
except Exception as e:
|
||||
_logger.debug("reject() failed: {}".format(e))
|
||||
try:
|
||||
d.done(QDialog.DialogCode.Rejected)
|
||||
d.done(qdialog.DialogCode.Rejected)
|
||||
except Exception as e:
|
||||
_logger.debug("done() failed: {}".format(e))
|
||||
# 2) close(): covers non-QDialog top-levels and is a harmless extra.
|
||||
@@ -172,9 +177,9 @@ class Plugin(BalPlugin):
|
||||
it and closes it themselves (it must not linger in the background).
|
||||
"""
|
||||
try:
|
||||
from PyQt6.QtCore import QTimer
|
||||
from PyQt6.QtCore import QTimer as qtimer # noqa: N813
|
||||
except Exception:
|
||||
QTimer = None
|
||||
qtimer = None
|
||||
# Schedule of retry delays (ms) measured from each call.
|
||||
retry_delays = [400, 800, 1500]
|
||||
dialogs = Plugin._find_plugins_manager_dialogs()
|
||||
@@ -190,8 +195,8 @@ class Plugin(BalPlugin):
|
||||
if not still_open:
|
||||
_logger.info("plugins dialog closed successfully")
|
||||
return
|
||||
if attempt < len(retry_delays) and QTimer is not None:
|
||||
QTimer.singleShot(
|
||||
if attempt < len(retry_delays) and qtimer is not None:
|
||||
qtimer.singleShot(
|
||||
retry_delays[attempt],
|
||||
lambda: Plugin._handle_plugins_manager_dialog(attempt + 1),
|
||||
)
|
||||
|
||||
@@ -18,9 +18,9 @@ Contents:
|
||||
* WillWidget - single will-tx box
|
||||
"""
|
||||
|
||||
from .calendar import BalCalendar, BalCalendarButton
|
||||
from .common import *
|
||||
from .common import _, _logger # underscore names are not re-exported by "import *"
|
||||
from .calendar import BalCalendar, BalCalendarButton
|
||||
|
||||
|
||||
def compute_reminder_offsets(days, count):
|
||||
@@ -690,7 +690,7 @@ class LockTimeDateEdit(QDateTimeEdit, _LockTimeEditor):
|
||||
return
|
||||
try:
|
||||
x = int(x)
|
||||
except Exception as e:
|
||||
except Exception:
|
||||
x = QDateTime.currentDateTime().timestamp()
|
||||
finally:
|
||||
# Use the overflow-safe converter: on Windows datetime.fromtimestamp
|
||||
@@ -1395,15 +1395,15 @@ class PercAmountEdit(BTCAmountEdit):
|
||||
if self.base_unit:
|
||||
panel = QStyleOptionFrame()
|
||||
self.initStyleOption(panel)
|
||||
textRect = self.style().subElementRect(
|
||||
text_rect = self.style().subElementRect(
|
||||
QStyle.SubElement.SE_LineEditContents, panel, self
|
||||
)
|
||||
textRect.adjust(2, 0, -10, 0)
|
||||
text_rect.adjust(2, 0, -10, 0)
|
||||
painter = QPainter(self)
|
||||
painter.setPen(ColorScheme.GRAY.as_color())
|
||||
if len(self.text()) == 0:
|
||||
painter.drawText(
|
||||
textRect,
|
||||
text_rect,
|
||||
int(Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignVCenter),
|
||||
self.base_unit() + " or perc value",
|
||||
)
|
||||
|
||||
@@ -18,11 +18,16 @@ import threading
|
||||
|
||||
from .common import *
|
||||
from .common import _, _logger # underscore names are not re-exported by "import *"
|
||||
from .widgets import LockTimeWidget, PercAmountEdit, WillSettingsWidget
|
||||
from .dialogs import (BalBlockingWaitingDialog, BalBuildWillDialog, BalDialog,
|
||||
BalWaitingDialog, BalWizardDialog, WillDetailDialog,
|
||||
WillExecutorDialog)
|
||||
from .lists import HeirListWidget, PreviewList, WillExecutorWidget
|
||||
from .dialogs import (
|
||||
BalBuildWillDialog,
|
||||
BalDialog,
|
||||
BalWaitingDialog,
|
||||
BalWizardDialog,
|
||||
WillDetailDialog,
|
||||
WillExecutorDialog,
|
||||
)
|
||||
from .lists import HeirListWidget, PreviewList
|
||||
from .widgets import LockTimeWidget, PercAmountEdit
|
||||
|
||||
|
||||
class BalWindow:
|
||||
|
||||
Reference in New Issue
Block a user