diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index db65e57a..c77597d6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,9 +17,8 @@ jobs: python-version: "3.11" cache: pip - name: Install dependencies - run: python -m pip install .[test] - - name: Run lints - run: ./lint.sh + run: python -m pip install ".[test]" + - uses: j178/prek-action@1382ad72dea72f9d53832f2bcb65b3e87a947204 # v3.0.1 test: runs-on: ubuntu-latest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 00000000..3e08e1fa --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,18 @@ +repos: + - repo: https://github.com/astral-sh/ruff-pre-commit + rev: e05c5c0818279e5ac248ac9e954431ba58865e61 # frozen: v0.15.7 + hooks: + - id: ruff-check + args: [--exit-non-zero-on-fix] + - id: ruff-format + args: [--exit-non-zero-on-fix] + + - repo: local + hooks: + - id: pyright + name: pyright + entry: python -m pyright bench_runner + language: system + pass_filenames: false + types: [python] + stages: [pre-commit] diff --git a/DEVELOPER.md b/DEVELOPER.md index 2fbe45e2..42f5562f 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -2,6 +2,17 @@ This repository contains a number of GitHub Actions workflows to run benchmarks on a set of private, self-hosted, bare metal machines. +## Linting + +We recommend [prek](https://prek.j178.dev/) to run the hooks in +`.pre-commit-config.yaml`. From the repository root, with a virtual environment active: + +```sh +python -m pip install -e ".[test]" prek +prek install +prek run --all-files +``` + ## The workflows There is a single user-facing workflow, `benchmark.yml`, that [reuses](https://docs.github.com/en/actions/using-workflows/reusing-workflows) the other workflows, prefixed with `_`. diff --git a/bench_runner/config.py b/bench_runner/config.py index 7a8989bd..1e209ca3 100644 --- a/bench_runner/config.py +++ b/bench_runner/config.py @@ -82,7 +82,8 @@ def __post_init__(self): ) self.runners = { name: mrunners.Runner( - nickname=name, **runner # pyright: ignore[reportCallIssue] + nickname=name, + **runner, # pyright: ignore[reportCallIssue] ) for name, runner in self.runners.items() } diff --git a/bench_runner/plot.py b/bench_runner/plot.py index ef22d68d..8a4c6704 100644 --- a/bench_runner/plot.py +++ b/bench_runner/plot.py @@ -248,9 +248,9 @@ def __post_init__(self): def longitudinal_plot( results: Iterable[result.Result], output_filename: PathLike, - getter: Callable[ - [result.BenchmarkComparison], float | None - ] = lambda r: r.geometric_mean_float, + getter: Callable[[result.BenchmarkComparison], float | None] = lambda r: ( + r.geometric_mean_float + ), differences: tuple[str, str] = ("slower", "faster"), title="Performance improvement by configuration", ): @@ -442,9 +442,9 @@ def __post_init__(self): def flag_effect_plot( results: Iterable[result.Result], output_filename: PathLike, - getter: Callable[ - [result.BenchmarkComparison], float | None - ] = lambda r: r.geometric_mean_float, + getter: Callable[[result.BenchmarkComparison], float | None] = lambda r: ( + r.geometric_mean_float + ), differences: tuple[str, str] = ("slower", "faster"), title="Performance improvement by configuration", ): @@ -496,11 +496,10 @@ def get_comparison_value(ref, r, force_valid): ] = r for subplot, ax in zip(subplots, axs): - ax.set_title(f"Effect of {subplot.name}") version = tuple(int(x) for x in subplot.version.split(".")) assert len(version) == 2, ( - "Version config in {subplot.name}" " should only be major.minor" + "Version config in {subplot.name} should only be major.minor" ) for runner in cfg.runners.values(): diff --git a/bench_runner/result.py b/bench_runner/result.py index f561126a..b4b3439f 100644 --- a/bench_runner/result.py +++ b/bench_runner/result.py @@ -280,7 +280,7 @@ def _calculate_geometric_mean(self) -> str: elif gm > 1.0: return f"{gm:.03f}x faster" else: - return f"{1.0+(1.0-gm):.03f}x slower" + return f"{1.0 + (1.0 - gm):.03f}x slower" @property def geometric_mean(self) -> str: @@ -874,9 +874,7 @@ def track(it, *_args, **_kwargs): result, candidates, "base", - lambda ref: ( - ref.cpython_hash == result.cpython_hash and ref.flags == [] - ), + lambda ref: ref.cpython_hash == result.cpython_hash and ref.flags == [], ) diff --git a/bench_runner/scripts/compare.py b/bench_runner/scripts/compare.py index f5f490ad..d6bdcf33 100644 --- a/bench_runner/scripts/compare.py +++ b/bench_runner/scripts/compare.py @@ -61,7 +61,7 @@ def compare_pair( output_dir = Path(output_dir) rich.print( - f"Comparing {counter[0]+1: 2}/{counter[1]: 2}: {head_name} vs. {ref_name}" + f"Comparing {counter[0] + 1: 2}/{counter[1]: 2}: {head_name} vs. {ref_name}" ) counter[0] += 1 diff --git a/bench_runner/scripts/install.py b/bench_runner/scripts/install.py index 3e78e7f7..1a138fda 100644 --- a/bench_runner/scripts/install.py +++ b/bench_runner/scripts/install.py @@ -220,9 +220,9 @@ def generate_benchmark(dst: Any) -> Any: continue if "with" in job: for flag in flags.FLAGS: - job["with"][ - flag.gha_variable - ] = f"${{{{ inputs.{flag.gha_variable} }}}}" + job["with"][flag.gha_variable] = ( + f"${{{{ inputs.{flag.gha_variable} }}}}" + ) # Include all of the flags in the human-readable workflow "run name" dst["run-name"] += " " + " ".join( diff --git a/bench_runner/scripts/run_benchmarks.py b/bench_runner/scripts/run_benchmarks.py index b005c3b3..54d6f1dd 100644 --- a/bench_runner/scripts/run_benchmarks.py +++ b/bench_runner/scripts/run_benchmarks.py @@ -337,8 +337,8 @@ def run_summarize_stats( - benchmark: {benchmark} - fork: {fork} - ref: {ref} - - commit hash: {git.get_git_hash(Path('cpython'))[:7]} - - commit date: {git.get_git_commit_date(Path('cpython'))} + - commit hash: {git.get_git_hash(Path("cpython"))[:7]} + - commit date: {git.get_git_commit_date(Path("cpython"))} """ ) diff --git a/bench_runner/table.py b/bench_runner/table.py index cc04487f..abe0a89c 100644 --- a/bench_runner/table.py +++ b/bench_runner/table.py @@ -18,7 +18,7 @@ def output_table( """ def output_row(row): - fd.write(f'| {" | ".join(row)} |\n') + fd.write(f"| {' | '.join(row)} |\n") output_row(head) output_row(col.endswith(":") and "---:" or "---" for col in head) diff --git a/lint.sh b/lint.sh deleted file mode 100755 index 01d914fa..00000000 --- a/lint.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh -set -e -python -m black --check bench_runner tests -python -m flake8 bench_runner tests -python -m pyright bench_runner diff --git a/pyproject.toml b/pyproject.toml index ec632344..0ef47fb5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,13 +27,12 @@ dynamic = ["version"] [project.optional-dependencies] test = [ - "black==25.1.0", "filelock==3.29.0", - "flake8==7.3.0", "pyright==1.1.414", "pytest==8.4.1", "pytest-cov==6.2.1", "pytest-xdist==3.8.0", + "ruff==0.15.7", ] [tool.setuptools_scm] @@ -44,6 +43,15 @@ include-package-data = true [tool.setuptools.package-data] bench_runner = ["templates/*"] +[tool.ruff] +target-version = "py311" +line-length = 88 +fix = true + +[tool.ruff.lint] +extend-select = ["W605"] +extend-ignore = ["E203", "E402"] + [tool.pytest.ini_options] markers = [ "long_running: marks tests as long_running (deselect with '-m \"not running\"')", @@ -54,4 +62,4 @@ source = [ "bench_runner", "/tmp/pytest-of-*/pytest-*/*/repo/outer_venv/lib/python*/site-packages/bench_runner", "/tmp/pytest-of-*/pytest-*/*/repo/venv/lib/python*/site-packages/bench_runner", -] \ No newline at end of file +] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index b63059eb..00000000 --- a/setup.cfg +++ /dev/null @@ -1,3 +0,0 @@ -[flake8] -max-line-length = 88 -extend-ignore = E203, E402 \ No newline at end of file diff --git a/tests/test_generate_results.py b/tests/test_generate_results.py index 074796b8..b14fef85 100644 --- a/tests/test_generate_results.py +++ b/tests/test_generate_results.py @@ -76,9 +76,9 @@ def test_main(tmp_path, monkeypatch): ) with open(result_with_base) as fd: contents = json.load(fd) - contents["metadata"][ - "commit_merge_base" - ] = "9d38120e335357a3b294277fd5eff0a10e46e043" + contents["metadata"]["commit_merge_base"] = ( + "9d38120e335357a3b294277fd5eff0a10e46e043" + ) with open(result_with_base, "w") as fd: json.dump(contents, fd) # End hack diff --git a/tests/test_result.py b/tests/test_result.py index d878b79e..23938e39 100644 --- a/tests/test_result.py +++ b/tests/test_result.py @@ -57,9 +57,9 @@ def test_merge_base(tmp_path, monkeypatch): ) with open(result_with_base) as fd: contents = json.load(fd) - contents["metadata"][ - "commit_merge_base" - ] = "9d38120e335357a3b294277fd5eff0a10e46e043" + contents["metadata"]["commit_merge_base"] = ( + "9d38120e335357a3b294277fd5eff0a10e46e043" + ) with open(result_with_base, "w") as fd: json.dump(contents, fd) # End hack