Skip to content

Commit 33e1820

Browse files
authored
Replace black/pylint/isort with ruff (#4350)
1 parent 1c39288 commit 33e1820

88 files changed

Lines changed: 655 additions & 584 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Makefile

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,8 @@ MARKDOWN_FILES = $(CURDIR)/README.md \
187187
lint: pyspec
188188
@$(MDFORMAT_VENV) --number --wrap=80 $(MARKDOWN_FILES)
189189
@$(CODESPELL_VENV) . --skip "./.git,$(VENV),$(PYSPEC_DIR)/.mypy_cache" -I .codespell-whitelist
190-
@$(PYTHON_VENV) -m isort --quiet $(CURDIR)/tests $(CURDIR)/pysetup $(CURDIR)/setup.py
191-
@$(PYTHON_VENV) -m black --quiet $(CURDIR)/tests $(CURDIR)/pysetup $(CURDIR)/setup.py
192-
@$(PYTHON_VENV) -m pylint --rcfile $(PYLINT_CONFIG) $(PYLINT_SCOPE)
190+
@$(PYTHON_VENV) -m ruff check --fix --quiet $(CURDIR)/tests $(CURDIR)/pysetup $(CURDIR)/setup.py
191+
@$(PYTHON_VENV) -m ruff format --quiet $(CURDIR)/tests $(CURDIR)/pysetup $(CURDIR)/setup.py
193192
@$(PYTHON_VENV) -m mypy --config-file $(MYPY_CONFIG) $(MYPY_SCOPE)
194193

195194
###############################################################################

pyproject.toml

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,13 @@ test = [
3737
"pytest==8.4.0",
3838
]
3939
lint = [
40-
"black==25.1.0",
4140
"codespell==2.4.1",
42-
"isort==6.0.1",
4341
"mdformat-gfm-alerts==1.0.2",
4442
"mdformat-gfm==0.4.1",
4543
"mdformat-toc==0.3.0",
4644
"mdformat==0.7.22",
4745
"mypy==1.16.0",
48-
"pylint==3.3.7",
46+
"ruff==0.11.12",
4947
]
5048
generator = [
5149
"filelock==3.18.0",
@@ -61,16 +59,29 @@ docs = [
6159
"mkdocs==1.6.1",
6260
]
6361

64-
[tool.black]
62+
[tool.ruff]
6563
line-length = 100
6664

67-
[tool.isort]
68-
profile = "black"
69-
line_length = 100
70-
combine_as_imports = true
71-
known_first_party = ["eth2spec"]
72-
order_by_type = false
73-
skip_glob = [
74-
"tests/core/pyspec/eth2spec/*/mainnet.py",
75-
"tests/core/pyspec/eth2spec/*/minimal.py",
65+
[tool.ruff.lint]
66+
select = [
67+
"F", # https://docs.astral.sh/ruff/rules/#pyflakes-f
68+
"I", # https://docs.astral.sh/ruff/rules/#isort-i
69+
"PL", # https://docs.astral.sh/ruff/rules/#pylint-pl
70+
"UP", # https://docs.astral.sh/ruff/rules/#pyupgrade-up
7671
]
72+
ignore = [
73+
"PLR0911", # https://docs.astral.sh/ruff/rules/too-many-return-statements/
74+
"PLR0912", # https://docs.astral.sh/ruff/rules/too-many-branches/
75+
"PLR0913", # https://docs.astral.sh/ruff/rules/too-many-arguments/
76+
"PLR0915", # https://docs.astral.sh/ruff/rules/too-many-statements/
77+
"PLR1714", # https://docs.astral.sh/ruff/rules/repeated-equality-comparison/
78+
"PLR2004", # https://docs.astral.sh/ruff/rules/magic-value-comparison/
79+
"PLW0128", # https://docs.astral.sh/ruff/rules/redeclared-assigned-name/
80+
"PLW0603", # https://docs.astral.sh/ruff/rules/global-statement/
81+
"PLW2901", # https://docs.astral.sh/ruff/rules/redefined-loop-name/
82+
]
83+
84+
[tool.ruff.lint.isort]
85+
combine-as-imports = true
86+
known-first-party = ["eth2spec"]
87+
order-by-type = false

pysetup/helpers.py

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import re
22
import textwrap
33
from functools import reduce
4-
from typing import Dict, List, TypeVar, Union
4+
from typing import TypeVar
55

66
from .constants import CONSTANT_DEP_SUNDRY_CONSTANTS_FUNCTIONS
77
from .md_doc_paths import PREVIOUS_FORK_OF
@@ -23,8 +23,8 @@ def collect_prev_forks(fork: str) -> list[str]:
2323

2424

2525
def requires_mypy_type_ignore(value: str) -> bool:
26-
return value.startswith(("ByteVector")) or (
27-
value.startswith(("Vector")) and any(k in value for k in ["ceillog2", "floorlog2"])
26+
return value.startswith("ByteVector") or (
27+
value.startswith("Vector") and any(k in value for k in ["ceillog2", "floorlog2"])
2828
)
2929

3030

@@ -34,13 +34,13 @@ def make_function_abstract(protocol_def: ProtocolDefinition, key: str):
3434

3535

3636
def objects_to_spec(
37-
preset_name: str, spec_object: SpecObject, fork: str, ordered_class_objects: Dict[str, str]
37+
preset_name: str, spec_object: SpecObject, fork: str, ordered_class_objects: dict[str, str]
3838
) -> str:
3939
"""
4040
Given all the objects that constitute a spec, combine them into a single pyfile.
4141
"""
4242

43-
def gen_new_type_definitions(custom_types: Dict[str, str]) -> str:
43+
def gen_new_type_definitions(custom_types: dict[str, str]) -> str:
4444
return "\n\n".join(
4545
[
4646
(
@@ -89,11 +89,9 @@ def format_protocol(protocol_name: str, protocol_def: ProtocolDefinition) -> str
8989
# Access global dict of config vars for runtime configurables
9090
# Ignore variable between quotes and doubles quotes
9191
for name in spec_object.config_vars.keys():
92-
functions_spec = re.sub(
93-
r"(?<!['\"])\b%s\b(?!['\"])" % name, "config." + name, functions_spec
94-
)
92+
functions_spec = re.sub(rf"(?<!['\"])\b{name}\b(?!['\"])", "config." + name, functions_spec)
9593
ordered_class_objects_spec = re.sub(
96-
r"(?<!['\"])\b%s\b(?!['\"])" % name, "config." + name, ordered_class_objects_spec
94+
rf"(?<!['\"])\b{name}\b(?!['\"])", "config." + name, ordered_class_objects_spec
9795
)
9896

9997
def format_config_var(name: str, vardef) -> str:
@@ -202,17 +200,17 @@ def format_constant(name: str, vardef: VariableDefinition) -> str:
202200
format_constant(k, v) for k, v in spec_object.preset_vars.items()
203201
)
204202
ssz_dep_constants = "\n".join(
205-
map(lambda x: "%s = %s" % (x, hardcoded_ssz_dep_constants[x]), hardcoded_ssz_dep_constants)
203+
map(lambda x: f"{x} = {hardcoded_ssz_dep_constants[x]}", hardcoded_ssz_dep_constants)
206204
)
207205
ssz_dep_constants_verification = "\n".join(
208206
map(
209-
lambda x: "assert %s == %s" % (x, spec_object.ssz_dep_constants[x]),
207+
lambda x: f"assert {x} == {spec_object.ssz_dep_constants[x]}",
210208
filtered_ssz_dep_constants,
211209
)
212210
)
213211
func_dep_presets_verification = "\n".join(
214212
map(
215-
lambda x: "assert %s == %s # noqa: E501" % (x, spec_object.func_dep_presets[x]),
213+
lambda x: f"assert {x} == {spec_object.func_dep_presets[x]} # noqa: E501",
216214
filtered_hardcoded_func_dep_presets,
217215
)
218216
)
@@ -247,8 +245,8 @@ def format_constant(name: str, vardef: VariableDefinition) -> str:
247245

248246

249247
def combine_protocols(
250-
old_protocols: Dict[str, ProtocolDefinition], new_protocols: Dict[str, ProtocolDefinition]
251-
) -> Dict[str, ProtocolDefinition]:
248+
old_protocols: dict[str, ProtocolDefinition], new_protocols: dict[str, ProtocolDefinition]
249+
) -> dict[str, ProtocolDefinition]:
252250
for key, value in new_protocols.items():
253251
if key not in old_protocols:
254252
old_protocols[key] = value
@@ -261,7 +259,7 @@ def combine_protocols(
261259
T = TypeVar("T")
262260

263261

264-
def combine_dicts(old_dict: Dict[str, T], new_dict: Dict[str, T]) -> Dict[str, T]:
262+
def combine_dicts(old_dict: dict[str, T], new_dict: dict[str, T]) -> dict[str, T]:
265263
return {**old_dict, **new_dict}
266264

267265

@@ -305,7 +303,7 @@ def combine_dicts(old_dict: Dict[str, T], new_dict: Dict[str, T]) -> Dict[str, T
305303
]
306304

307305

308-
def dependency_order_class_objects(objects: Dict[str, str], custom_types: Dict[str, str]) -> None:
306+
def dependency_order_class_objects(objects: dict[str, str], custom_types: dict[str, str]) -> None:
309307
"""
310308
Determines which SSZ Object is dependent on which other and orders them appropriately
311309
"""
@@ -332,7 +330,7 @@ def dependency_order_class_objects(objects: Dict[str, str], custom_types: Dict[s
332330
objects[item] = objects.pop(item)
333331

334332

335-
def combine_ssz_objects(old_objects: Dict[str, str], new_objects: Dict[str, str]) -> Dict[str, str]:
333+
def combine_ssz_objects(old_objects: dict[str, str], new_objects: dict[str, str]) -> dict[str, str]:
336334
"""
337335
Takes in old spec and new spec ssz objects, combines them,
338336
and returns the newer versions of the objects in dependency order.
@@ -378,11 +376,11 @@ def combine_spec_objects(spec0: SpecObject, spec1: SpecObject) -> SpecObject:
378376
)
379377

380378

381-
def parse_config_vars(conf: Dict[str, str]) -> Dict[str, Union[str, List[Dict[str, str]]]]:
379+
def parse_config_vars(conf: dict[str, str]) -> dict[str, str | list[dict[str, str]]]:
382380
"""
383381
Parses a dict of basic str/int/list types into a dict for insertion into the spec code.
384382
"""
385-
out: Dict[str, Union[str, List[Dict[str, str]]]] = dict()
383+
out: dict[str, str | list[dict[str, str]]] = dict()
386384
for k, v in conf.items():
387385
if isinstance(v, list):
388386
# A special case for list of records

pysetup/md_doc_paths.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ def is_post_fork(a, b) -> bool:
5050
prev_fork = PREVIOUS_FORK_OF[a]
5151
if prev_fork == b:
5252
return True
53-
elif prev_fork == None:
53+
elif prev_fork is None:
5454
return False
5555
else:
5656
return is_post_fork(prev_fork, b)

pysetup/md_to_spec.py

Lines changed: 29 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
import json
33
import re
44
import string
5-
from functools import lru_cache
5+
from collections.abc import Iterator, Mapping
6+
from functools import cache
67
from pathlib import Path
7-
from typing import cast, Dict, Iterator, Mapping, Optional, Tuple
8+
from typing import cast
89

910
from marko.block import BlankLine, Document, FencedCode, Heading, HTMLBlock
1011
from marko.element import Element
@@ -31,7 +32,7 @@ def __init__(
3132
self.preset_name = preset_name
3233

3334
self.document_iterator: Iterator[Element] = self._parse_document(file_name)
34-
self.all_custom_types: Dict[str, str] = {}
35+
self.all_custom_types: dict[str, str] = {}
3536
self.current_heading_name: str | None = None
3637

3738
# Use a single dict to hold all SpecObject fields
@@ -59,7 +60,7 @@ def run(self) -> SpecObject:
5960
self._finalize_types()
6061
return self._build_spec_object()
6162

62-
def _get_next_element(self) -> Optional[Element]:
63+
def _get_next_element(self) -> Element | None:
6364
"""
6465
Returns the next non-blank element in the document.
6566
"""
@@ -240,7 +241,7 @@ def _process_table(self, table: Table) -> None:
240241
self.spec["constant_vars"][name] = value_def
241242

242243
@staticmethod
243-
def _get_table_row_fields(row: TableRow) -> tuple[str, str, Optional[str]]:
244+
def _get_table_row_fields(row: TableRow) -> tuple[str, str, str | None]:
244245
"""
245246
Extracts the name, value, and description fields from a table row element.
246247
"""
@@ -294,9 +295,9 @@ def _process_list_of_records_table(self, table: Table, list_of_records_name: str
294295
# For mainnet, check that the spec config & file config are the same
295296
# For minimal, we expect this to be different; just use the file config
296297
if self.preset_name == "mainnet":
297-
assert (
298-
list_of_records_spec == list_of_records_config_file
299-
), f"list of records mismatch: {list_of_records_spec} vs {list_of_records_config_file}"
298+
assert list_of_records_spec == list_of_records_config_file, (
299+
f"list of records mismatch: {list_of_records_spec} vs {list_of_records_config_file}"
300+
)
300301

301302
# Set the config variable
302303
self.spec["config_vars"][list_of_records_name] = list_of_records_config_file
@@ -435,21 +436,21 @@ def _build_spec_object(self) -> SpecObject:
435436
)
436437

437438

438-
@lru_cache(maxsize=None)
439-
def _get_name_from_heading(heading: Heading) -> Optional[str]:
439+
@cache
440+
def _get_name_from_heading(heading: Heading) -> str | None:
440441
last_child = heading.children[-1]
441442
if isinstance(last_child, CodeSpan):
442443
return last_child.children
443444
return None
444445

445446

446-
@lru_cache(maxsize=None)
447+
@cache
447448
def _get_source_from_code_block(block: FencedCode) -> str:
448449
return block.children[0].children.strip()
449450

450451

451-
@lru_cache(maxsize=None)
452-
def _get_self_type_from_source(fn: ast.FunctionDef) -> Optional[str]:
452+
@cache
453+
def _get_self_type_from_source(fn: ast.FunctionDef) -> str | None:
453454
args = fn.args.args
454455
if len(args) == 0:
455456
return None
@@ -460,8 +461,8 @@ def _get_self_type_from_source(fn: ast.FunctionDef) -> Optional[str]:
460461
return args[0].annotation.id
461462

462463

463-
@lru_cache(maxsize=None)
464-
def _get_class_info_from_ast(cls: ast.ClassDef) -> Tuple[str, Optional[str]]:
464+
@cache
465+
def _get_class_info_from_ast(cls: ast.ClassDef) -> tuple[str, str | None]:
465466
base = cls.bases[0]
466467
if isinstance(base, ast.Name):
467468
parent_class = base.id
@@ -475,7 +476,7 @@ def _get_class_info_from_ast(cls: ast.ClassDef) -> Tuple[str, Optional[str]]:
475476
return cls.name, parent_class
476477

477478

478-
@lru_cache(maxsize=None)
479+
@cache
479480
def _is_constant_id(name: str) -> bool:
480481
"""
481482
Checks if the given name follows the convention for constant identifiers.
@@ -485,16 +486,16 @@ def _is_constant_id(name: str) -> bool:
485486
return all(map(lambda c: c in string.ascii_uppercase + "_" + string.digits, name[1:]))
486487

487488

488-
@lru_cache(maxsize=None)
489-
def _load_kzg_trusted_setups(preset_name: str) -> Tuple[list[str], list[str], list[str]]:
489+
@cache
490+
def _load_kzg_trusted_setups(preset_name: str) -> tuple[list[str], list[str], list[str]]:
490491
trusted_setups_file_path = (
491492
str(Path(__file__).parent.parent)
492493
+ "/presets/"
493494
+ preset_name
494495
+ "/trusted_setups/trusted_setup_4096.json"
495496
)
496497

497-
with open(trusted_setups_file_path, "r") as f:
498+
with open(trusted_setups_file_path) as f:
498499
json_data = json.load(f)
499500
trusted_setup_G1_monomial = json_data["g1_monomial"]
500501
trusted_setup_G1_lagrange = json_data["g1_lagrange"]
@@ -503,8 +504,8 @@ def _load_kzg_trusted_setups(preset_name: str) -> Tuple[list[str], list[str], li
503504
return trusted_setup_G1_monomial, trusted_setup_G1_lagrange, trusted_setup_G2_monomial
504505

505506

506-
@lru_cache(maxsize=None)
507-
def _load_curdleproofs_crs(preset_name: str) -> Dict[str, list[str]]:
507+
@cache
508+
def _load_curdleproofs_crs(preset_name: str) -> dict[str, list[str]]:
508509
"""
509510
NOTE: File generated from https://github.com/asn-d6/curdleproofs/blob/8e8bf6d4191fb6a844002f75666fb7009716319b/tests/crs.rs#L53-L67
510511
"""
@@ -515,7 +516,7 @@ def _load_curdleproofs_crs(preset_name: str) -> Dict[str, list[str]]:
515516
+ "/trusted_setups/curdleproofs_crs.json"
516517
)
517518

518-
with open(file_path, "r") as f:
519+
with open(file_path) as f:
519520
json_data = json.load(f)
520521

521522
return json_data
@@ -532,10 +533,8 @@ def _load_curdleproofs_crs(preset_name: str) -> Dict[str, list[str]]:
532533
}
533534

534535

535-
@lru_cache(maxsize=None)
536-
def _parse_value(
537-
name: str, typed_value: str, type_hint: Optional[str] = None
538-
) -> VariableDefinition:
536+
@cache
537+
def _parse_value(name: str, typed_value: str, type_hint: str | None = None) -> VariableDefinition:
539538
comment = None
540539
if name in ("ROOT_OF_UNITY_EXTENDED", "ROOTS_OF_UNITY_EXTENDED", "ROOTS_OF_UNITY_REDUCED"):
541540
comment = "noqa: E501"
@@ -585,7 +584,7 @@ def _update_constant_vars_with_curdleproofs_crs(
585584
)
586585

587586

588-
@lru_cache(maxsize=None)
587+
@cache
589588
def parse_markdown(content: str) -> Document:
590589
return gfm.parse(content)
591590

@@ -613,9 +612,9 @@ def check_yaml_matches_spec(
613612
else:
614613
raise ValueError(f"Variable {var} should be a string in the yaml file.")
615614
try:
616-
assert yaml[var_name] == repr(
617-
eval(updated_value)
618-
), f"mismatch for {var_name}: {yaml[var_name]} vs {eval(updated_value)}"
615+
assert yaml[var_name] == repr(eval(updated_value)), (
616+
f"mismatch for {var_name}: {yaml[var_name]} vs {eval(updated_value)}"
617+
)
619618
except NameError:
620619
# Okay it's probably something more serious, let's ignore
621620
pass

pysetup/spec_builders/altair.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
from typing import Dict
2-
31
from ..constants import ALTAIR, OPTIMIZED_BLS_AGGREGATE_PUBKEYS
42
from .base import BaseSpecBuilder
53

@@ -39,15 +37,15 @@ def compute_merkle_proof(object: SSZObject,
3937
return build_proof(object.get_backing(), index)"""
4038

4139
@classmethod
42-
def hardcoded_ssz_dep_constants(cls) -> Dict[str, str]:
40+
def hardcoded_ssz_dep_constants(cls) -> dict[str, str]:
4341
return {
4442
"FINALIZED_ROOT_GINDEX": "GeneralizedIndex(105)",
4543
"CURRENT_SYNC_COMMITTEE_GINDEX": "GeneralizedIndex(54)",
4644
"NEXT_SYNC_COMMITTEE_GINDEX": "GeneralizedIndex(55)",
4745
}
4846

4947
@classmethod
50-
def implement_optimizations(cls, functions: Dict[str, str]) -> Dict[str, str]:
48+
def implement_optimizations(cls, functions: dict[str, str]) -> dict[str, str]:
5149
if "eth_aggregate_pubkeys" in functions:
5250
functions["eth_aggregate_pubkeys"] = OPTIMIZED_BLS_AGGREGATE_PUBKEYS.strip()
5351
return functions

0 commit comments

Comments
 (0)