What changed, and why it matters
This commit only turns on a Python style lint rule (E713) that prefers 'not in' over 'not ... in'. It updates test scripts and helper tools to match the style, with no changes to the Bitcoin Core software that users run. There is no security issue here.
No action needed; this is a code-quality/style change only.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch enables the ruff E713 lint rule and mechanically rewrites membership tests from ‘not x in y’ to ‘x not in y’. These are logically equivalent in Python. The changes are confined to test/functional, contrib/guix, contrib/linearize, and test/lint/test_runner. No consensus, networking, wallet, or node runtime code is affected.
Changed components
test/functional/mempool_persist.pytest/functional/p2p_v2_transport.pytest/functional/rpc_psbt.pytest/functional/rpc_setban.pytest/functional/test_framework/descriptors.pytest/functional/wallet_abandonconflict.pytest/functional/wallet_send.pycontrib/guix/symbol-check.pycontrib/linearize/linearize-data.pytest/lint/test_runner/src/main.rsInspect captured patch +18 / −17
diff --git a/contrib/guix/symbol-check.py b/contrib/guix/symbol-check.py
index c32c1b5b..93002ddc 100755
--- a/contrib/guix/symbol-check.py
+++ b/contrib/guix/symbol-check.py
@@ -172,7 +172,7 @@ PE_ALLOWED_LIBRARIES = {
def check_version(max_versions, version, arch) -> bool:
(lib, _, ver) = version.rpartition('_')
ver = tuple([int(x) for x in ver.split('.')])
- if not lib in max_versions:
+ if lib not in max_versions:
return False
if isinstance(max_versions[lib], tuple):
return ver <= max_versions[lib]
diff --git a/contrib/linearize/linearize-data.py b/contrib/linearize/linearize-data.py
index 9b29fe71..afaaca18 100755
--- a/contrib/linearize/linearize-data.py
+++ b/contrib/linearize/linearize-data.py
@@ -229,7 +229,7 @@ class BlockDataCopier:
inExtent = BlockExtent(self.inFn, self.inF.tell(), inhdr, blk_hdr, inLen)
self.hash_str = calc_hash_str(blk_hdr)
- if not self.hash_str in blkmap:
+ if self.hash_str not in blkmap:
# Because blocks can be written to files out-of-order as of 0.10, the script
# may encounter blocks it doesn't know about. Treat as debug output.
if settings['debug_output'] == 'true':
@@ -320,7 +320,7 @@ if __name__ == '__main__':
blkmap = mkblockmap(blkindex)
# Block hash map won't be byte-reversed. Neither should the genesis hash.
- if not settings['genesis'] in blkmap:
+ if settings['genesis'] not in blkmap:
print("Genesis block not found in hashlist")
else:
BlockDataCopier(settings, blkindex, blkmap).run()
diff --git a/test/functional/mempool_persist.py b/test/functional/mempool_persist.py
index ce3981a3..23b6b192 100755
--- a/test/functional/mempool_persist.py
+++ b/test/functional/mempool_persist.py
@@ -233,13 +233,13 @@ class MempoolPersistTest(BitcoinTestFramework):
self.nodes[0].sendrawtransaction(tx_node01["hex"])
self.nodes[1].sendrawtransaction(tx_node01["hex"])
assert tx_node0["txid"] in self.nodes[0].getrawmempool()
- assert not tx_node0["txid"] in self.nodes[1].getrawmempool()
- assert not tx_node1["txid"] in self.nodes[0].getrawmempool()
+ assert tx_node0["txid"] not in self.nodes[1].getrawmempool()
+ assert tx_node1["txid"] not in self.nodes[0].getrawmempool()
assert tx_node1["txid"] in self.nodes[1].getrawmempool()
assert tx_node01["txid"] in self.nodes[0].getrawmempool()
assert tx_node01["txid"] in self.nodes[1].getrawmempool()
- assert not tx_node01_secret["txid"] in self.nodes[0].getrawmempool()
- assert not tx_node01_secret["txid"] in self.nodes[1].getrawmempool()
+ assert tx_node01_secret["txid"] not in self.nodes[0].getrawmempool()
+ assert tx_node01_secret["txid"] not in self.nodes[1].getrawmempool()
self.log.debug("Check that importmempool can add txns without replacing the entire mempool")
mempooldat0 = str(self.nodes[0].chain_path / "mempool.dat")
@@ -249,7 +249,7 @@ class MempoolPersistTest(BitcoinTestFramework):
# All transactions should be in node1's mempool now.
assert tx_node0["txid"] in self.nodes[1].getrawmempool()
assert tx_node1["txid"] in self.nodes[1].getrawmempool()
- assert not tx_node1["txid"] in self.nodes[0].getrawmempool()
+ assert tx_node1["txid"] not in self.nodes[0].getrawmempool()
# For transactions that already existed, priority should be changed
entry_node01 = self.nodes[1].getmempoolentry(tx_node01["txid"])
assert_equal(entry_node01["fees"]["base"] + 1, entry_node01["fees"]["modified"])
diff --git a/test/functional/p2p_v2_transport.py b/test/functional/p2p_v2_transport.py
index b09fe1a6..731df998 100755
--- a/test/functional/p2p_v2_transport.py
+++ b/test/functional/p2p_v2_transport.py
@@ -165,7 +165,7 @@ class V2TransportTest(BitcoinTestFramework):
peer_id = self.nodes[0].getpeerinfo()[-1]["id"]
s.sendall(b'\x00') # send out last byte
# should disconnect immediately
- self.wait_until(lambda: not peer_id in [p["id"] for p in self.nodes[0].getpeerinfo()])
+ self.wait_until(lambda: peer_id not in [p["id"] for p in self.nodes[0].getpeerinfo()])
if __name__ == '__main__':
diff --git a/test/functional/rpc_psbt.py b/test/functional/rpc_psbt.py
index 9d6049f8..cc443f6a 100755
--- a/test/functional/rpc_psbt.py
+++ b/test/functional/rpc_psbt.py
@@ -126,7 +126,7 @@ class PSBTTest(BitcoinTestFramework):
utxos = wonline.listunspent(addresses=[offline_addr])
raw = wonline.createrawtransaction([{"txid":utxos[0]["txid"], "vout":utxos[0]["vout"]}],[{online_addr:0.9999}])
psbt = wonline.walletprocesspsbt(online_node.converttopsbt(raw))["psbt"]
- assert not "not_witness_utxo" in mining_node.decodepsbt(psbt)["inputs"][0]
+ assert "not_witness_utxo" not in mining_node.decodepsbt(psbt)["inputs"][0]
# add non-witness UTXO manually
psbt_new = PSBT.from_base64(psbt)
@@ -136,7 +136,7 @@ class PSBTTest(BitcoinTestFramework):
# Have the offline node sign the PSBT (which will remove the non-witness UTXO)
signed_psbt = offline_node.walletprocesspsbt(psbt_new.to_base64())
- assert not "non_witness_utxo" in mining_node.decodepsbt(signed_psbt["psbt"])["inputs"][0]
+ assert "non_witness_utxo" not in mining_node.decodepsbt(signed_psbt["psbt"])["inputs"][0]
# Make sure we can mine the resulting transaction
txid = mining_node.sendrawtransaction(signed_psbt["hex"])
diff --git a/test/functional/rpc_setban.py b/test/functional/rpc_setban.py
index 4a0a3787..9b684ae4 100755
--- a/test/functional/rpc_setban.py
+++ b/test/functional/rpc_setban.py
@@ -24,7 +24,7 @@ class SetBanTests(BitcoinTestFramework):
# Node 0 connects to Node 1, check that the noban permission is not granted
self.connect_nodes(0, 1)
peerinfo = self.nodes[1].getpeerinfo()[0]
- assert not "noban" in peerinfo["permissions"]
+ assert "noban" not in peerinfo["permissions"]
# Node 0 get banned by Node 1
self.nodes[1].setban("127.0.0.1", "add")
@@ -51,7 +51,7 @@ class SetBanTests(BitcoinTestFramework):
self.restart_node(1, [])
self.connect_nodes(0, 1)
peerinfo = self.nodes[1].getpeerinfo()[0]
- assert not "noban" in peerinfo["permissions"]
+ assert "noban" not in peerinfo["permissions"]
self.log.info("Test that a non-IP address can be banned/unbanned")
node = self.nodes[1]
diff --git a/test/functional/test_framework/descriptors.py b/test/functional/test_framework/descriptors.py
index 46b40574..0f65f63d 100644
--- a/test/functional/test_framework/descriptors.py
+++ b/test/functional/test_framework/descriptors.py
@@ -25,7 +25,7 @@ def descsum_expand(s):
groups = []
symbols = []
for c in s:
- if not c in INPUT_CHARSET:
+ if c not in INPUT_CHARSET:
return None
v = INPUT_CHARSET.find(c)
symbols.append(v & 31)
@@ -47,7 +47,7 @@ def descsum_create(s):
def descsum_check(s, require=True):
"""Verify that the checksum is correct in a descriptor"""
- if not '#' in s:
+ if '#' not in s:
return not require
if s[-9] != '#':
return False
diff --git a/test/functional/wallet_abandonconflict.py b/test/functional/wallet_abandonconflict.py
index f4d289e4..afd0f504 100755
--- a/test/functional/wallet_abandonconflict.py
+++ b/test/functional/wallet_abandonconflict.py
@@ -120,7 +120,7 @@ class AbandonConflictTest(BitcoinTestFramework):
balances = alice.getbalances()['mine']
assert_equal(balances['untrusted_pending'] + balances['trusted'], newbalance)
# Also shouldn't show up in listunspent
- assert not txABC2 in [utxo["txid"] for utxo in alice.listunspent(0)]
+ assert txABC2 not in [utxo["txid"] for utxo in alice.listunspent(0)]
balance = newbalance
# Abandon original transaction and verify inputs are available again
diff --git a/test/functional/wallet_send.py b/test/functional/wallet_send.py
index bbc2b990..ab8f74f2 100755
--- a/test/functional/wallet_send.py
+++ b/test/functional/wallet_send.py
@@ -159,7 +159,7 @@ class WalletSendTest(BitcoinTestFramework):
assert "txid" in res
else:
assert_equal(res["complete"], False)
- assert not "txid" in res
+ assert "txid" not in res
assert "psbt" in res
from_balance = from_wallet.getbalances()["mine"]["trusted"]
diff --git a/test/lint/test_runner/src/main.rs b/test/lint/test_runner/src/main.rs
index 5c65fcad..171c9807 100644
--- a/test/lint/test_runner/src/main.rs
+++ b/test/lint/test_runner/src/main.rs
@@ -307,6 +307,7 @@ fn lint_py_lint() -> LintResult {
"E702", // multiple statements on one line (semicolon)
"E703", // statement ends with a semicolon
"E711", // comparison to None should be 'if cond is None:'
+ "E713", // test for membership should be "not in"
"E714", // test for object identity should be "is not"
"E721", // do not compare types, use "isinstance()"
"E722", // do not use bare 'except'
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.