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:
2026-07-31 16:03:17 -04:00
parent 649910e599
commit 08394f4868
48 changed files with 494 additions and 292 deletions

View File

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

View File

@@ -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``.

View File

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

View File

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

View File

@@ -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 = {}