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:
@@ -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