Skip to content

Commit fc10fe9

Browse files
authored
Migrate from flake8/black/isort to ruff (#625)
* Migrate to ruff formatting * Reformat using ruff
1 parent 55774f6 commit fc10fe9

24 files changed

Lines changed: 409 additions & 243 deletions

.pre-commit-config.yaml

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,21 @@
11
# See https://pre-commit.com for more information
22
# See https://pre-commit.com/hooks.html for more hooks
33
repos:
4-
- repo: https://github.com/PyCQA/isort
5-
rev: 8.0.1
6-
hooks:
7-
- id: isort
8-
- repo: https://github.com/psf/black
9-
rev: 26.3.1
10-
hooks:
11-
- id: black
12-
- repo: https://github.com/PyCQA/flake8
13-
rev: 7.3.0
14-
hooks:
15-
- id: flake8
164
- repo: https://github.com/pre-commit/pre-commit-hooks
175
rev: v6.0.0
186
hooks:
19-
- id: check-added-large-files
20-
args: ['--maxkb=1024']
217
- id: check-docstring-first
228
- id: check-merge-conflict
23-
- id: check-symlinks
24-
- id: check-yaml
259
- id: debug-statements
2610
- id: detect-private-key
27-
- id: end-of-file-fixer
28-
types: [python]
29-
- id: trailing-whitespace
11+
- id: requirements-txt-fixer
12+
- id: check-toml
13+
- id: check-yaml
14+
- id: check-added-large-files
15+
- repo: https://github.com/astral-sh/ruff-pre-commit
16+
rev: v0.15.8
17+
hooks:
18+
- id: ruff
19+
args:
20+
- --fix
21+
- id: ruff-format

pyproject.toml

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,14 @@ Homepage = "https://github.com/gnosis/safe-cli"
4848
[dependency-groups]
4949
dev = [
5050
"coverage",
51-
"flake8",
5251
"hatch",
5352
"ipdb",
5453
"ipython",
55-
"isort",
54+
"mypy",
5655
"pre-commit",
5756
"pytest",
5857
"pytest-sugar",
58+
"ruff",
5959
]
6060

6161
[tool.hatch.version]
@@ -103,22 +103,32 @@ exclude_lines = [
103103
"pass",
104104
]
105105

106-
[tool.isort]
107-
profile = "black"
108-
default_section = "THIRDPARTY"
109-
known_first_party = "safe_cli"
110-
known_safe_foundation = ["py_eth_sig_utils", "gnosis"]
111-
known_django = "django"
112-
sections = [
113-
"FUTURE",
114-
"STDLIB",
115-
"DJANGO",
116-
"THIRDPARTY",
117-
"SAFE_FOUNDATION",
118-
"FIRSTPARTY",
119-
"LOCALFOLDER",
106+
[tool.ruff]
107+
line-length = 88
108+
target-version = "py310"
109+
exclude = [
110+
".tox", ".git", "*/static/CACHE/*",
111+
"docs", "node_modules", ".venv"
120112
]
121113

114+
[tool.ruff.lint]
115+
extend-select = [
116+
"E", # pycodestyle errors
117+
"W", # pycodestyle warnings
118+
"F", # pyflakes
119+
"I", # isort
120+
"B", # flake8-bugbear
121+
"C4", # flake8-comprehensions
122+
"UP", # pyupgrade
123+
]
124+
ignore = ["E501", "B008"]
125+
126+
[tool.ruff.lint.isort]
127+
known-first-party = ["safe_cli"]
128+
known-third-party = ["py_eth_sig_utils", "safe", "fastapi", "pydantic"]
129+
combine-as-imports = true
130+
force-wrap-aliases = true
131+
122132
[tool.mypy]
123133
python_version = "3.13"
124134
check_untyped_defs = true

setup.cfg

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/safe_cli/argparse_validators.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,9 @@ def check_private_key(private_key: str) -> str:
4646
try:
4747
Account.from_key(private_key)
4848
except (ValueError, Error): # TODO Report `Error` exception as a bug of eth_account
49-
raise argparse.ArgumentTypeError(f"{private_key} is not a valid private key")
49+
raise argparse.ArgumentTypeError(
50+
f"{private_key} is not a valid private key"
51+
) from None
5052
return private_key
5153

5254

@@ -60,7 +62,9 @@ def check_hex_str(hex_str: str) -> HexBytes:
6062
try:
6163
return HexBytes(hex_str)
6264
except ValueError:
63-
raise argparse.ArgumentTypeError(f"{hex_str} is not a valid hexadecimal string")
65+
raise argparse.ArgumentTypeError(
66+
f"{hex_str} is not a valid hexadecimal string"
67+
) from None
6468

6569

6670
def check_keccak256_hash(hex_str: str) -> HexBytes:

src/safe_cli/main.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import os
44
import sys
55
from pathlib import Path
6-
from typing import Annotated, List
6+
from typing import Annotated
77

88
import typer
99
from art import text2art
@@ -32,7 +32,7 @@
3232
def _build_safe_operator_and_load_keys(
3333
safe_address: ChecksumAddress,
3434
node_url: str,
35-
private_keys: List[str],
35+
private_keys: list[str],
3636
interactive: bool,
3737
) -> SafeOperator:
3838
safe_operator = SafeOperator(safe_address, node_url, interactive=interactive)
@@ -98,7 +98,7 @@ def send_ether(
9898
int, typer.Argument(help="Amount of ether in wei to send.", show_default=False)
9999
],
100100
private_key: Annotated[
101-
List[str],
101+
list[str],
102102
typer.Option(
103103
help="List of private keys of signers.",
104104
rich_help_panel="Optional Arguments",
@@ -143,7 +143,7 @@ def send_erc20(
143143
),
144144
],
145145
private_key: Annotated[
146-
List[str],
146+
list[str],
147147
typer.Option(
148148
help="List of private keys of signers.",
149149
rich_help_panel="Optional Arguments",
@@ -185,7 +185,7 @@ def send_erc721(
185185
int, typer.Argument(help="Erc721 token id.", show_default=False)
186186
],
187187
private_key: Annotated[
188-
List[str],
188+
list[str],
189189
typer.Option(
190190
help="List of private keys of signers.",
191191
rich_help_panel="Optional Arguments",
@@ -225,7 +225,7 @@ def send_custom(
225225
),
226226
],
227227
private_key: Annotated[
228-
List[str],
228+
list[str],
229229
typer.Option(
230230
help="List of private keys of signers.",
231231
rich_help_panel="Optional Arguments",
@@ -276,7 +276,7 @@ def tx_builder(
276276
),
277277
],
278278
private_key: Annotated[
279-
List[str],
279+
list[str],
280280
typer.Option(
281281
help="List of private keys of signers.",
282282
rich_help_panel="Optional Arguments",
@@ -374,7 +374,7 @@ def default_attended_mode(
374374
safe_cli.loop()
375375

376376

377-
def _is_safe_cli_default_command(arguments: List[str]) -> bool:
377+
def _is_safe_cli_default_command(arguments: list[str]) -> bool:
378378
# safe-cli
379379
if len(arguments) == 1:
380380
return True

src/safe_cli/operators/hw_wallets/hw_wallet_manager.py

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from enum import Enum
2-
from functools import lru_cache
3-
from typing import Dict, List, Optional, Set, Tuple
2+
from functools import cache
43

54
from eth_typing import ChecksumAddress
65
from hexbytes import HexBytes
@@ -24,16 +23,16 @@ class HwWalletType(Enum):
2423
LEDGER = 1
2524

2625

27-
@lru_cache(maxsize=None)
26+
@cache
2827
def get_hw_wallet_manager():
2928
return HwWalletManager()
3029

3130

3231
class HwWalletManager:
3332
def __init__(self):
34-
self.wallets: Set[HwWallet] = set()
35-
self.supported_hw_wallet_types: Dict[str, HwWallet] = {}
36-
self.sender: Optional[HwWallet] = None
33+
self.wallets: set[HwWallet] = set()
34+
self.supported_hw_wallet_types: dict[str, HwWallet] = {}
35+
self.sender: HwWallet | None = None
3736
try:
3837
from .ledger_wallet import LedgerWallet
3938

@@ -51,16 +50,16 @@ def __init__(self):
5150
def is_supported_hw_wallet(self, hw_wallet_type: HwWalletType) -> bool:
5251
return hw_wallet_type in self.supported_hw_wallet_types
5352

54-
def get_hw_wallet(self, hw_wallet_type: HwWalletType) -> Optional[HwWallet]:
53+
def get_hw_wallet(self, hw_wallet_type: HwWalletType) -> HwWallet | None:
5554
if hw_wallet_type in self.supported_hw_wallet_types:
5655
return self.supported_hw_wallet_types[hw_wallet_type]
5756

5857
def get_accounts(
5958
self,
6059
hw_wallet_type: HwWalletType,
6160
template_derivation_path: str,
62-
number_accounts: Optional[int] = 5,
63-
) -> List[Tuple[ChecksumAddress, str]]:
61+
number_accounts: int | None = 5,
62+
) -> list[tuple[ChecksumAddress, str]]:
6463
"""
6564
6665
:param hw_wallet: Trezor or Ledger
@@ -101,7 +100,7 @@ def set_sender(self, hw_wallet_type: HwWalletType, derivation_path: str):
101100
hw_wallet = self.get_hw_wallet(hw_wallet_type)
102101
self.sender = hw_wallet(derivation_path)
103102

104-
def delete_accounts(self, addresses: List[ChecksumAddress]) -> Set:
103+
def delete_accounts(self, addresses: list[ChecksumAddress]) -> set:
105104
"""
106105
Remove ledger accounts from address
107106
@@ -119,8 +118,8 @@ def delete_accounts(self, addresses: List[ChecksumAddress]) -> Set:
119118
return accounts_to_remove
120119

121120
def sign_eip712(
122-
self, eip712_message: Dict, wallets: List[HwWallet]
123-
) -> List[SafeSignature]:
121+
self, eip712_message: dict, wallets: list[HwWallet]
122+
) -> list[SafeSignature]:
124123
"""
125124
Sign an EIP712 message
126125
@@ -130,7 +129,7 @@ def sign_eip712(
130129
"""
131130
_, domain_hash, message_hash = eip712_encode(eip712_message)
132131
eip712_message_hash = eip712_encode_hash(eip712_message)
133-
safe_signatures: List[SafeSignature] = []
132+
safe_signatures: list[SafeSignature] = []
134133
for wallet in wallets:
135134
print_formatted_text(
136135
HTML(
@@ -148,7 +147,7 @@ def sign_eip712(
148147

149148
return safe_signatures
150149

151-
def sign_safe_tx(self, safe_tx: SafeTx, wallets: List[HwWallet]) -> SafeTx:
150+
def sign_safe_tx(self, safe_tx: SafeTx, wallets: list[HwWallet]) -> SafeTx:
152151
"""
153152
Sign a safe transaction with the provided hardware wallets
154153
@@ -169,11 +168,11 @@ def sign_safe_tx(self, safe_tx: SafeTx, wallets: List[HwWallet]) -> SafeTx:
169168
def execute_safe_tx(
170169
self,
171170
safe_tx: SafeTx,
172-
tx_gas: Optional[int] = None,
173-
tx_gas_price: Optional[int] = None,
174-
tx_nonce: Optional[int] = None,
175-
eip1559_speed: Optional[TxSpeed] = None,
176-
) -> Tuple[HexBytes, TxParams]:
171+
tx_gas: int | None = None,
172+
tx_gas_price: int | None = None,
173+
tx_nonce: int | None = None,
174+
eip1559_speed: TxSpeed | None = None,
175+
) -> tuple[HexBytes, TxParams]:
177176
"""
178177
Send multisig tx to the Safe
179178
@@ -223,16 +222,16 @@ def execute_safe_tx(
223222
return safe_tx.tx_hash, safe_tx.tx
224223

225224
def sign_message(
226-
self, message: bytes, wallets: List[HwWallet]
227-
) -> List[SafeSignature]:
225+
self, message: bytes, wallets: list[HwWallet]
226+
) -> list[SafeSignature]:
228227
"""
229228
Sign a message for all the provided wallets
230229
231230
:param message:
232231
:param wallets:
233232
:return:
234233
"""
235-
signatures: List[SafeSignature] = []
234+
signatures: list[SafeSignature] = []
236235
for wallet in wallets:
237236
print_formatted_text(
238237
HTML(

src/safe_cli/operators/hw_wallets/ledger_exceptions.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,20 @@ def wrapper(*args, **kwargs):
1717
try:
1818
return function(*args, **kwargs)
1919
except LedgerNotFound as e:
20-
raise HardwareWalletException(e.message)
20+
raise HardwareWalletException(e.message) from e
2121
except LedgerLocked as e:
22-
raise HardwareWalletException(e.message)
22+
raise HardwareWalletException(e.message) from e
2323
except LedgerAppNotOpened as e:
24-
raise HardwareWalletException(e.message)
24+
raise HardwareWalletException(e.message) from e
2525
except LedgerCancel as e:
26-
raise HardwareWalletException(e.message)
26+
raise HardwareWalletException(e.message) from e
2727
except InvalidDerivationPath as e:
28-
raise HardwareWalletException(e.message)
28+
raise HardwareWalletException(e.message) from e
2929
except BaseException as e:
3030
if "Error while writing" in e.args:
31-
raise HardwareWalletException("Ledger error writing, restart safe-cli")
31+
raise HardwareWalletException(
32+
"Ledger error writing, restart safe-cli"
33+
) from e
3234
raise e
3335

3436
return wrapper

src/safe_cli/operators/hw_wallets/ledger_wallet.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from typing import Optional
2-
31
from eth_typing import ChecksumAddress
42
from hexbytes import HexBytes
53
from ledgerblue.Dongle import Dongle
@@ -16,7 +14,7 @@
1614
class LedgerWallet(HwWallet):
1715
@raise_ledger_exception_as_hw_wallet_exception
1816
def __init__(self, derivation_path: str):
19-
self.dongle: Optional[Dongle] = None
17+
self.dongle: Dongle | None = None
2018
self.connect()
2119
super().__init__(derivation_path)
2220

0 commit comments

Comments
 (0)