From 487678bce9244fc741f71b75a211b4c05c2c0328 Mon Sep 17 00:00:00 2001 From: The MMGen Project Date: Mon, 30 Dec 2024 16:58:14 +0300 Subject: [PATCH] Use Ruff static code analyzer for Github workflows --- .github/workflows/{pylint.yaml => ruff.yaml} | 23 +++------- mmgen/bip_hd/__init__.py | 1 - mmgen/cfgfile.py | 1 + mmgen/help/__init__.py | 2 +- mmgen/proto/btc/tx/new.py | 1 - mmgen/tx/__init__.py | 2 - mmgen/xmrwallet/ops/label.py | 2 +- mmgen/xmrwallet/rpc.py | 2 +- pyproject.toml | 45 ++++++++++++++++--- test/cmdtest_d/ct_automount.py | 2 - test/cmdtest_d/ct_base.py | 2 +- test/daemontest_d/ut_tx.py | 5 ++- test/include/coin_daemon_control.py | 2 +- test/misc/term.py | 2 +- test/modtest_d/ut_dep.py | 3 +- test/modtest_d/ut_testdep.py | 2 +- test/modtest_d/ut_tx.py | 4 +- .../fakemods/mmgen/proto/btc/tw/unspent.py | 1 - 18 files changed, 60 insertions(+), 42 deletions(-) rename .github/workflows/{pylint.yaml => ruff.yaml} (61%) diff --git a/.github/workflows/pylint.yaml b/.github/workflows/ruff.yaml similarity index 61% rename from .github/workflows/pylint.yaml rename to .github/workflows/ruff.yaml index 1c441e01..4b70d0f3 100644 --- a/.github/workflows/pylint.yaml +++ b/.github/workflows/ruff.yaml @@ -1,9 +1,9 @@ -name: pylint +name: ruff on: push: paths: - - '.github/workflows/pylint.yaml' + - '.github/workflows/ruff.yaml' - '.github/build-requirements.txt' - 'pyproject.toml' - 'setup.cfg' @@ -19,13 +19,6 @@ jobs: strategy: matrix: python-version: ["3.9", "3.11", "3.12"] - include: - - python-version: "3.9" - pylint_ver: "3.1.1" - - python-version: "3.11" - pylint_ver: "3.1.1" - - python-version: "3.12" - pylint_ver: "3.1.1" steps: - uses: actions/checkout@v4 @@ -47,15 +40,13 @@ jobs: run: | python3 -m pip install pip setuptools build wheel python3 -m pip install gmpy2 cryptography pynacl ecdsa aiohttp requests pexpect scrypt semantic-version - python3 -m pip install pycryptodomex pysocks pycoin ipaddress varint pylint==${{ matrix.pylint_ver }} - python3 -m pip install --no-deps py_ecc==1.6.0 mypy_extensions==0.4.1 monero + python3 -m pip install pycryptodomex pysocks pycoin ipaddress varint ruff + python3 -m pip install py_ecc mypy_extensions monero eth-keys python3 setup.py build_ext --inplace - - name: Check the code with Pylint static code analyzer + - name: Check the code with Ruff static code analyzer env: PYTHONPATH: . run: | - pylint --errors-only --jobs=0 mmgen - pylint --errors-only --jobs=0 test - pylint --errors-only --jobs=0 examples - pylint --errors-only --jobs=0 --disable=relative-beyond-top-level test/cmdtest_d + ruff check --output-format=github mmgen + ruff check --output-format=github test diff --git a/mmgen/bip_hd/__init__.py b/mmgen/bip_hd/__init__.py index 6e08f4fa..da587e64 100644 --- a/mmgen/bip_hd/__init__.py +++ b/mmgen/bip_hd/__init__.py @@ -16,7 +16,6 @@ bip_hd: BIP-44/49/84, SLIP-44 hierarchical-deterministic key derivation library # https://blog.unit410.com/bitcoin/bip32/bip39/kdf/2021/05/17/inconsistent-bip32-derivations.html import hmac -from collections import namedtuple from ..cfg import Config from ..util import is_int, fmt diff --git a/mmgen/cfgfile.py b/mmgen/cfgfile.py index f146bd55..37b95433 100755 --- a/mmgen/cfgfile.py +++ b/mmgen/cfgfile.py @@ -135,6 +135,7 @@ class cfg_file_sample(cfg_file): hdr = True chunk = [] in_chunk = False + last_nonblank = 0 for lineno, line in enumerate(lines, 1): diff --git a/mmgen/help/__init__.py b/mmgen/help/__init__.py index 09087dcc..c0614d80 100755 --- a/mmgen/help/__init__.py +++ b/mmgen/help/__init__.py @@ -20,7 +20,7 @@ help: help notes for MMGen suite commands """ -import sys, re +import sys from ..cfg import gc diff --git a/mmgen/proto/btc/tx/new.py b/mmgen/proto/btc/tx/new.py index bd967ba5..1a4641af 100755 --- a/mmgen/proto/btc/tx/new.py +++ b/mmgen/proto/btc/tx/new.py @@ -69,7 +69,6 @@ class New(Base, TxBase.New): # given network fee estimate in BTC/kB, return absolute fee using estimated tx size def fee_est2abs(self, fee_per_kb, fe_type=None): - from decimal import Decimal tx_size = self.estimate_size() ret = self.proto.coin_amt('1') * (fee_per_kb * self.cfg.fee_adjust * tx_size / 1024) if self.cfg.verbose: diff --git a/mmgen/tx/__init__.py b/mmgen/tx/__init__.py index 68f29780..4e6a8219 100755 --- a/mmgen/tx/__init__.py +++ b/mmgen/tx/__init__.py @@ -12,8 +12,6 @@ tx.__init__: transaction class initializer """ -from ..objmethods import MMGenObject - def _base_proto_subclass(clsname, modname, proto): if proto: clsname = ('Token' if proto.tokensym else '') + clsname diff --git a/mmgen/xmrwallet/ops/label.py b/mmgen/xmrwallet/ops/label.py index 82116f6d..bdd1a93b 100755 --- a/mmgen/xmrwallet/ops/label.py +++ b/mmgen/xmrwallet/ops/label.py @@ -12,7 +12,7 @@ xmrwallet.ops.label: Monero wallet ops for the MMGen Suite """ -from ...color import red, pink, cyan, gray +from ...color import pink, cyan, gray from ...util import msg, ymsg, gmsg, die, make_timestr from ...ui import keypress_confirm from ...addr import CoinAddr diff --git a/mmgen/xmrwallet/rpc.py b/mmgen/xmrwallet/rpc.py index 72aef8f4..f6d25d32 100755 --- a/mmgen/xmrwallet/rpc.py +++ b/mmgen/xmrwallet/rpc.py @@ -16,7 +16,7 @@ from collections import namedtuple from ..obj import CoinTxID from ..color import red, cyan, pink -from ..util import msg, msg_r, gmsg, gmsg_r, die, fmt +from ..util import msg, msg_r, gmsg, gmsg_r, die from ..addr import CoinAddr from .include import gen_acct_addr_info, XMRWalletAddrSpec diff --git a/pyproject.toml b/pyproject.toml index f0874546..81c06f68 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,11 +6,44 @@ requires = [ ] build-backend = "setuptools.build_meta" +[tool.ruff.lint] +ignore = [ + "E401", # multiple imports per line + "E701", # multiple statements per line + "E721", # use isinstance() + "E731", # lambda instead of def + "E402", # module import not top of file + "E722", # bare except + "E713", # membership 'not in' + "E741", # ambiguous variable name +] + +[tool.ruff.lint.per-file-ignores] +"mmgen/proto/eth/pyethereum/*" = [ "F401" ] # imported but unused +"mmgen/proto/eth/rlp/sedes/*" = [ "F401" ] # imported but unused +"mmgen/addrgen.py" = [ "F401" ] # imported but unused +"mmgen/tool/*" = [ + "F722", # Syntax error in forward annotation + "F821" # Undefined name `sstr` +] +"test/include/common.py" = [ "F821" ] # undefined name 'cfg' +"test/misc/input_func.py" = [ "F401" ] # imported but unused +"test/modtest_d/ut_cashaddr.py" = [ "F841" ] # assigned to but never used +"test/modtest_d/ut_dep.py" = [ "F401" ] # imported but unused +"test/modtest_d/ut_testdep.py" = [ "F401" ] # imported but unused +"test/modtest_d/ut_obj.py" = [ "F841" ] # assigned to but never used +"test/objtest_d/*" = [ "F401" ] # imported but unused +"test/objattrtest_d/*" = [ "F401" ] # imported but unused +"test/overlay/fakemods/*" = [ "F403", "F405" ] # `import *` used +"test/*.py" = [ "F401" ] # imported but unused +"test/colortest.py" = [ "F403", "F405" ] # `import *` used +"test/tooltest2.py" = [ "F403", "F405" ] # `import *` used + [tool.pylint.format] indent-string = "\t" indent-after-paren = 2 max-line-length = 116 - + [tool.pylint.main] recursive = true jobs = 0 @@ -28,7 +61,7 @@ ignored-modules = [ # ignored for no-member, otherwise checked "msvcrt", "gmpy2", ] - + [tool.pylint."messages control"] disable = [ "raw-checker-failed", @@ -50,7 +83,7 @@ disable = [ [tool.pylint.miscellaneous] notes = ["FIXME", "TODO", "DEBUG", "WIP"] - + [tool.pylint.typecheck] mixin-class-rgx = """.*[Mm]ixin|\ ^(Hilite|InitErrors|DummyWIF|\ @@ -59,9 +92,9 @@ mixin-class-rgx = """.*[Mm]ixin|\ CmdTestShared)$""" ignored-classes = [ # ignored for no-member, otherwise checked - "optparse.Values", - "thread._local", - "_thread._local", + "optparse.Values", + "thread._local", + "_thread._local", "argparse.Namespace", # mmgen: "baseconv", diff --git a/test/cmdtest_d/ct_automount.py b/test/cmdtest_d/ct_automount.py index c84bb91e..00313e53 100755 --- a/test/cmdtest_d/ct_automount.py +++ b/test/cmdtest_d/ct_automount.py @@ -12,11 +12,9 @@ test.cmdtest_d.ct_automount: autosigning with automount tests for the cmdtest.py test suite """ import time -from pathlib import Path from .ct_autosign import CmdTestAutosignThreaded from .ct_regtest import CmdTestRegtestBDBWallet, rt_pw -from .common import get_file_with_ext from ..include.common import cfg class CmdTestAutosignAutomount(CmdTestAutosignThreaded, CmdTestRegtestBDBWallet): diff --git a/test/cmdtest_d/ct_base.py b/test/cmdtest_d/ct_base.py index 046800c4..c8625cf2 100755 --- a/test/cmdtest_d/ct_base.py +++ b/test/cmdtest_d/ct_base.py @@ -55,7 +55,7 @@ class CmdTestBase: self.coin = self.proto.coin.lower() self.fork = 'btc' if self.coin == 'bch' and not cfg.cashaddr else self.coin self.altcoin_pfx = '' if self.fork == 'btc' else f'-{self.proto.coin}' - self.testnet_opt = [f'--testnet=1'] if cfg.testnet else [] + self.testnet_opt = ['--testnet=1'] if cfg.testnet else [] if len(self.tmpdir_nums) == 1: self.tmpdir_num = self.tmpdir_nums[0] if self.tr: diff --git a/test/daemontest_d/ut_tx.py b/test/daemontest_d/ut_tx.py index 4382b749..ef7353a8 100755 --- a/test/daemontest_d/ut_tx.py +++ b/test/daemontest_d/ut_tx.py @@ -4,10 +4,10 @@ test.daemontest_d.ut_tx: TX daemon tests for the MMGen suite """ -import os, json +import json from mmgen.color import purple, cyan -from mmgen.util import msg, Msg, Msg_r +from mmgen.util import Msg, Msg_r from mmgen.devtools import Pmsg from mmgen.protocol import init_proto from mmgen.tx import CompletedTX @@ -131,6 +131,7 @@ class unit_tests: print_info(name, 'Bitcoin Core test vectors') n = 1 + desc = '(no description)' for e in core_data: if isinstance(e[0], list): await test_tx( diff --git a/test/include/coin_daemon_control.py b/test/include/coin_daemon_control.py index 3d1a4368..56c96d5a 100755 --- a/test/include/coin_daemon_control.py +++ b/test/include/coin_daemon_control.py @@ -18,7 +18,7 @@ from pathlib import PurePath sys.path[0] = str(PurePath(*PurePath(__file__).parts[:-3])) from mmgen.cfg import Config, gc -from mmgen.util import msg, die, oneshot_warning, async_run +from mmgen.util import msg, die, oneshot_warning from mmgen.protocol import init_proto from mmgen.daemon import CoinDaemon diff --git a/test/misc/term.py b/test/misc/term.py index 6dca5025..5bd05a01 100755 --- a/test/misc/term.py +++ b/test/misc/term.py @@ -48,7 +48,7 @@ available commands for platform {sys.platform!r}: cfg = Config(opts_data=opts_data) -from mmgen.term import get_char, get_char_raw, get_terminal_size, get_term +from mmgen.term import get_char_raw, get_terminal_size, get_term from mmgen.ui import line_input, keypress_confirm, do_license_msg import mmgen.term as term_mod diff --git a/test/modtest_d/ut_dep.py b/test/modtest_d/ut_dep.py index 5af6a4ab..a9fe4e99 100755 --- a/test/modtest_d/ut_dep.py +++ b/test/modtest_d/ut_dep.py @@ -7,7 +7,7 @@ test.modtest_d.ut_dep: dependency unit tests for the MMGen suite No data verification is performed. """ -import sys, time +import sys from subprocess import run, PIPE @@ -57,6 +57,7 @@ class unit_tests: def py_ecc(self, name, ut): # ETH from py_ecc.secp256k1 import privtopub + privtopub(b'f' * 32) return True def pysocks(self, name, ut): diff --git a/test/modtest_d/ut_testdep.py b/test/modtest_d/ut_testdep.py index e0b6c4e2..cbd335d0 100755 --- a/test/modtest_d/ut_testdep.py +++ b/test/modtest_d/ut_testdep.py @@ -4,7 +4,7 @@ test.modtest_d.ut_testdep: test dependency unit tests for the MMGen suite """ -import sys, os +import os from subprocess import run, DEVNULL from mmgen.util import ymsg, bmsg diff --git a/test/modtest_d/ut_tx.py b/test/modtest_d/ut_tx.py index 67953cf8..20d38299 100755 --- a/test/modtest_d/ut_tx.py +++ b/test/modtest_d/ut_tx.py @@ -4,12 +4,10 @@ test.modtest_d.ut_tx: TX unit tests for the MMGen suite """ -import os, re +import os -from mmgen.devtools import get_diff, get_ndiff from mmgen.tx import CompletedTX, UnsignedTX from mmgen.tx.file import MMGenTxFile -from mmgen.protocol import init_proto from mmgen.cfg import Config from ..include.common import cfg, qmsg, vmsg diff --git a/test/overlay/fakemods/mmgen/proto/btc/tw/unspent.py b/test/overlay/fakemods/mmgen/proto/btc/tw/unspent.py index 2cd9e0a1..a8772ef0 100644 --- a/test/overlay/fakemods/mmgen/proto/btc/tw/unspent.py +++ b/test/overlay/fakemods/mmgen/proto/btc/tw/unspent.py @@ -6,7 +6,6 @@ if overlay_fake_os.getenv('MMGEN_BOGUS_UNSPENT_DATA'): class overlay_fake_BitcoinTwUnspentOutputs(BitcoinTwUnspentOutputs): async def get_rpc_data(self): - from decimal import Decimal import json from ....fileutil import get_data_from_file return json.loads(get_data_from_file(