diff --git a/bench_runner/config.py b/bench_runner/config.py index 7d0419e8..1ebd6b2d 100644 --- a/bench_runner/config.py +++ b/bench_runner/config.py @@ -13,7 +13,7 @@ @functools.cache def get_bench_runner_config( - filepath: Path = Path("bench_runner.toml"), + filepath: Path | str = Path("bench_runner.toml"), ): - with open(filepath, "rb") as fd: + with Path(filepath).open("rb") as fd: return tomllib.load(fd) diff --git a/bench_runner/git.py b/bench_runner/git.py index 45a01a91..e94c6c5f 100644 --- a/bench_runner/git.py +++ b/bench_runner/git.py @@ -10,9 +10,12 @@ import rich +from .util import PathLike + + def get_log( format: str, - dirname: Path, + dirname: PathLike, ref: str | None = None, n: int = 1, extra: list[str] | None = None, @@ -42,22 +45,22 @@ def get_log( ).strip() -def get_git_hash(dirname: Path) -> str: +def get_git_hash(dirname: PathLike) -> str: return get_log("%h", dirname) -def get_git_commit_date(dirname: Path) -> str: +def get_git_commit_date(dirname: PathLike) -> str: return get_log("%cI", dirname) -def remove(repodir: Path, path: Path) -> None: +def remove(repodir: Path, path: PathLike) -> None: subprocess.check_output( ["git", "rm", str(path)], cwd=repodir, ) -def get_git_merge_base(dirname: Path) -> str | None: +def get_git_merge_base(dirname: PathLike) -> str | None: # We need to make sure we have commits from main that are old enough to be # the base of this branch, but not so old that we waste a ton of bandwidth commit_date = datetime.datetime.fromisoformat(get_git_commit_date(dirname)) @@ -109,14 +112,14 @@ def get_git_merge_base(dirname: Path) -> str | None: return merge_base -def get_tags(dirname: Path) -> list[str]: +def get_tags(dirname: PathLike) -> list[str]: subprocess.check_call(["git", "fetch", "--tags"], cwd=dirname) return subprocess.check_output( ["git", "tag"], cwd=dirname, encoding="utf-8" ).splitlines() -def get_commits_between(dirname: Path, ref1: str, ref2: str) -> list[str]: +def get_commits_between(dirname: PathLike, ref1: str, ref2: str) -> list[str]: return list( subprocess.check_output( ["git", "rev-list", "--ancestry-path", f"{ref1}..{ref2}"], @@ -126,6 +129,6 @@ def get_commits_between(dirname: Path, ref1: str, ref2: str) -> list[str]: ) -def bisect_commits(dirname: Path, ref1: str, ref2: str) -> str: +def bisect_commits(dirname: PathLike, ref1: str, ref2: str) -> str: commits = get_commits_between(dirname, ref1, ref2) return commits[len(commits) // 2] diff --git a/bench_runner/hpt.py b/bench_runner/hpt.py index dc848b6b..d42c01f7 100644 --- a/bench_runner/hpt.py +++ b/bench_runner/hpt.py @@ -35,16 +35,16 @@ from numpy.typing import NDArray -from bench_runner import util - +from . import util +from .util import PathLike ACC_MAXSU = 2 def load_from_json( - json_path: Path, + json_path: PathLike, ) -> dict[str, NDArray[np.float64]]: - with json_path.open() as fd: + with Path(json_path).open() as fd: content = json.load(fd) return load_data(content) @@ -311,7 +311,7 @@ def maxspeedup( return base_su -def make_report(ref: Path, head: Path, alpha=0.1): +def make_report(ref: PathLike, head: PathLike, alpha=0.1): # The original code inverted the inputs from the standard in bench_runner, # and it's easier to just flip them here. a, b = head, ref diff --git a/bench_runner/plot.py b/bench_runner/plot.py index 71b39dea..eaa12a5c 100644 --- a/bench_runner/plot.py +++ b/bench_runner/plot.py @@ -24,6 +24,7 @@ from . import config as mconfig from . import flags as mflags from . import result +from .util import PathLike INTERPRETER_HEAVY = { @@ -48,7 +49,7 @@ } -def savefig(output_filename: Path, **kwargs): +def savefig(output_filename: PathLike, **kwargs): class Options: quiet = True remove_descriptive_elements = True @@ -58,6 +59,8 @@ class Options: shorten_ids = True digits = 3 + output_filename = Path(output_filename) + plt.savefig(output_filename, **kwargs) plt.close("all") @@ -139,7 +142,7 @@ def formatter(val, pos): def plot_diff( combined_data: result.CombinedData, - output_filename: Path, + output_filename: PathLike, title: str, differences: tuple[str, str], ) -> None: @@ -227,7 +230,7 @@ def add_axvline(ax, dt: datetime.datetime, name: str): def longitudinal_plot( results: Iterable[result.Result], - output_filename: Path, + output_filename: PathLike, getter: Callable[ [result.BenchmarkComparison], float | None ] = lambda r: r.hpt_percentile_float(99), @@ -243,6 +246,7 @@ def get_comparison_value(ref, r, base): data[key] = value return value + output_filename = Path(output_filename) cfg = get_plot_config() data_cache = output_filename.with_suffix(".json") @@ -252,7 +256,7 @@ def get_comparison_value(ref, r, base): else: data = {} - axs: Sequence[matplotlib.Axes] + axs: Sequence[matplotlib.Axes] # pyright: ignore fig, axs = plt.subplots( len(cfg["versions"]), @@ -350,7 +354,7 @@ def get_comparison_value(ref, r, base): json.dump(data, fd, indent=2) -def _standardize_xlims(axs: Sequence[matplotlib.Axes]) -> None: +def _standardize_xlims(axs: Sequence[matplotlib.Axes]) -> None: # pyright: ignore if not len(axs): return @@ -369,13 +373,15 @@ def _standardize_xlims(axs: Sequence[matplotlib.Axes]) -> None: def flag_effect_plot( results: Iterable[result.Result], - output_filename: Path, + output_filename: PathLike, getter: Callable[ [result.BenchmarkComparison], float | None ] = lambda r: r.hpt_percentile_float(99), differences: tuple[str, str] = ("slower", "faster"), title="Performance improvement by configuration", ): + output_filename = Path(output_filename) + # We don't need to track the performance of the Tier 2 configuration all_flags = [flag for flag in mflags.FLAGS if flag.name != "PYTHON_UOPS"] flags = [flag.name for flag in reversed(all_flags)] @@ -399,7 +405,7 @@ def get_comparison_value(ref, r): else: data = {} - axs: Sequence[matplotlib.Axes] + axs: Sequence[matplotlib.Axes] # pyright: ignore fig, axs = plt.subplots( len(flags), 1, figsize=(10, 5 * len(flags)), layout="constrained" diff --git a/bench_runner/result.py b/bench_runner/result.py index 0f037f89..357eaed1 100644 --- a/bench_runner/result.py +++ b/bench_runner/result.py @@ -30,6 +30,7 @@ from . import plot from . import runners from . import util +from .util import PathLike CombinedData = list[tuple[str, np.ndarray | None, float]] @@ -54,7 +55,7 @@ def _clean_for_url(string: str) -> str: return string.replace("-", "%2d") -def _get_platform_value(python: Path, item: str) -> str: +def _get_platform_value(python: PathLike, item: str) -> str: """ Get a value from the platform module of the given Python interpreter. """ @@ -64,7 +65,7 @@ def _get_platform_value(python: Path, item: str) -> str: return output.strip().lower() -def _get_architecture(python: Path) -> str: +def _get_architecture(python: PathLike) -> str: machine = _get_platform_value(python, "machine") bits = eval(_get_platform_value(python, "architecture"))[0] if bits == "32bit": @@ -152,7 +153,9 @@ def _generate_contents(self) -> str: fd.write(f"- memory change: {self._calculate_memory_change()}") return fd.getvalue() - def write_table(self, filename: Path) -> str | None: + def write_table(self, filename: PathLike) -> str | None: + filename = Path(filename) + entries = [ ("fork", unquote(self.head.fork)), ("ref", self.head.ref), @@ -212,7 +215,7 @@ def get_timing_diff(self) -> CombinedData: head_data = self.head.get_timing_data() return self._get_combined_data(ref_data, head_data) - def write_timing_plot(self, filename: Path) -> None: + def write_timing_plot(self, filename: PathLike) -> None: plot.plot_diff( self.get_timing_diff(), filename, @@ -231,7 +234,7 @@ def get_memory_diff(self) -> CombinedData: # Explicitly reversed so higher is bigger return self._get_combined_data(head_data, ref_data) - def write_memory_plot(self, filename: Path) -> None: + def write_memory_plot(self, filename: PathLike) -> None: plot.plot_diff( self.get_memory_diff(), filename, @@ -376,7 +379,9 @@ def get_files(self) -> Iterable[tuple[Callable, str, str]]: return yield (self.write_pystats_diff, ".md", "pystats diff") - def write_pystats_diff(self, filename: Path) -> None: + def write_pystats_diff(self, filename: PathLike) -> None: + filename = Path(filename) + try: contents = subprocess.check_output( [ @@ -434,7 +439,8 @@ def __init__( self.bases = {} @classmethod - def from_filename(cls, filename: Path) -> "Result": + def from_filename(cls, filename: PathLike) -> "Result": + filename = Path(filename) ( name, _, @@ -469,7 +475,7 @@ def from_filename(cls, filename: Path) -> "Result": @classmethod def from_scratch( cls, - python: Path, + python: PathLike, fork: str, ref: str, extra: Iterable[str] | None = None, @@ -687,7 +693,7 @@ def memory_value(metadata): def has_result( - results_dir: Path, + results_dir: PathLike, commit_hash: str, machine: str, pystats: bool, @@ -822,14 +828,14 @@ def track(it, *_args, **_kwargs): def load_all_results( bases: Sequence[str] | None, - results_dir: Path, + results_dir: PathLike, sorted: bool = True, match: bool = True, progress: bool = True, ) -> list[Result]: results = [] - for entry in results_dir.glob("**/*.json"): + for entry in Path(results_dir).glob("**/*.json"): result = Result.from_filename(entry) if result.result_info[0] not in ["raw results", "pystats raw"]: continue diff --git a/bench_runner/scripts/backfill.py b/bench_runner/scripts/backfill.py index b38f2e2e..fdd362d6 100644 --- a/bench_runner/scripts/backfill.py +++ b/bench_runner/scripts/backfill.py @@ -22,13 +22,14 @@ from bench_runner import git from bench_runner import result as mod_result from bench_runner import runners +from bench_runner.util import PathLike RunnerType: TypeAlias = runners.Runner @functools.cache -def _get_hash_and_date(cpython: Path, ref: str) -> tuple[str, datetime.datetime]: +def _get_hash_and_date(cpython: PathLike, ref: str) -> tuple[str, datetime.datetime]: hash, date = git.get_log("%H %cI", cpython, ref).split() return hash, datetime.datetime.fromisoformat(date) @@ -38,7 +39,7 @@ class Commit: Represents a single commit to possibly benchmark. """ - def __init__(self, cpython: Path, ref: str, source: str): + def __init__(self, cpython: PathLike, ref: str, source: str): self.cpython = cpython self.ref = ref self.source = source @@ -61,7 +62,7 @@ def date(self) -> datetime.datetime: def get_all_with_prefix( - cpython: Path, tags: Iterable[str], prefix: str + cpython: PathLike, tags: Iterable[str], prefix: str ) -> Iterable[Commit]: """ Get all tags with the given prefix. @@ -72,7 +73,7 @@ def get_all_with_prefix( def get_latest_with_prefix( - cpython: Path, tags: Iterable[str], prefix: str + cpython: PathLike, tags: Iterable[str], prefix: str ) -> Iterable[Commit]: """ Get the most recent (by commit date) tag with the given prefix. @@ -97,7 +98,7 @@ def next_weekday(d: datetime.datetime, weekday: int) -> datetime.datetime: return d + datetime.timedelta(days_ahead) -def get_weekly_since(cpython: Path, start_date: str) -> Iterable[Commit]: +def get_weekly_since(cpython: PathLike, start_date: str) -> Iterable[Commit]: """ Get weekly commits on Sundays since the given start date. """ @@ -123,7 +124,7 @@ def get_weekly_since(cpython: Path, start_date: str) -> Iterable[Commit]: break -def get_bisect(cpython: Path, refs: Sequence[str]) -> Iterable[Commit]: +def get_bisect(cpython: PathLike, refs: Sequence[str]) -> Iterable[Commit]: if len(refs) != 2: raise ValueError(f"Each --bisect entry must contain 2 refs, got {len(refs)}") @@ -177,7 +178,7 @@ def remove_existing( def get_commits( - cpython: Path, + cpython: PathLike, tags: Iterable[str], all_with_prefix: Iterable[str], latest_with_prefix: Iterable[str], @@ -197,7 +198,9 @@ def get_commits( yield from get_bisect(cpython, entry) -def deduplicate_commits(cpython: Path, commits: Iterable[Commit]) -> Iterable[Commit]: +def deduplicate_commits( + cpython: PathLike, commits: Iterable[Commit] +) -> Iterable[Commit]: commits_by_hash = defaultdict(list) for commit in commits: @@ -226,7 +229,7 @@ def format_runners( def _main( - cpython: Path, + cpython: PathLike, all_with_prefix: Sequence[str] | None, latest_with_prefix: Sequence[str] | None, weekly_since: Sequence[str] | None, diff --git a/bench_runner/scripts/compare.py b/bench_runner/scripts/compare.py index 59dbd614..04f672a7 100644 --- a/bench_runner/scripts/compare.py +++ b/bench_runner/scripts/compare.py @@ -20,6 +20,7 @@ from bench_runner import result as mod_result from bench_runner import runners as mod_runners from bench_runner import util +from bench_runner.util import PathLike ParsedCommits: TypeAlias = Sequence[ @@ -49,7 +50,7 @@ def get_machines(results: Iterable[mod_result.Result]) -> set[str]: def compare_pair( - output_dir: Path, + output_dir: PathLike, machine: str, ref_name: str, ref: mod_result.Result, @@ -57,6 +58,8 @@ def compare_pair( head: mod_result.Result, counter: list[int], ) -> str: + output_dir = Path(output_dir) + rich.print(f"Comparing {counter[0]+1}/{counter[1]}", end="\r") counter[0] += 1 @@ -79,7 +82,7 @@ def do_one_to_many( fd: TextIO, parsed_commits: ParsedCommits, machine: str, - output_dir: Path, + output_dir: PathLike, counter: list[int], ) -> None: _, _, first_name, first_results = parsed_commits[0] @@ -100,7 +103,7 @@ def do_many_to_many( fd, parsed_commits: ParsedCommits, machine: str, - output_dir: Path, + output_dir: PathLike, counter: list[int], ) -> None: write_row(fd, ["", *[f"{x[2]} ({x[0]})" for x in parsed_commits]]) @@ -124,7 +127,7 @@ def do_many_to_many( fd.write("\n\nRows are 'bases', columns are 'heads'\n") -def _main(commits: Sequence[str], output_dir: Path, comparison_type: str): +def _main(commits: Sequence[str], output_dir: PathLike, comparison_type: str): results = mod_result.load_all_results( None, Path("results"), sorted=False, match=False ) diff --git a/bench_runner/scripts/generate_results.py b/bench_runner/scripts/generate_results.py index 6b389b36..76931263 100644 --- a/bench_runner/scripts/generate_results.py +++ b/bench_runner/scripts/generate_results.py @@ -25,6 +25,7 @@ ) from bench_runner import table from bench_runner import util +from bench_runner.util import PathLike def _tuple_to_nested_dicts(entries: Iterable[tuple], d: dict | None = None) -> dict: @@ -82,7 +83,7 @@ def save_generated_results(results: Iterable[Result], force: bool = False) -> No def output_results_index( - fd: TextIO, bases: Iterable[str], results: Iterable[Result], filename: Path + fd: TextIO, bases: Iterable[str], results: Iterable[Result], filename: PathLike ): """ Outputs a results index table. @@ -186,7 +187,7 @@ def get_most_recent_pystats(results: Iterable[Result]) -> Result | None: def generate_index( - filename: Path, + filename: PathLike, bases: Iterable[str], all_results: Iterable[Result], benchmarking_results: Iterable[Result], @@ -218,7 +219,7 @@ def generate_indices( bases: Iterable[str], all_results: Iterable[Result], benchmarking_results: Iterable[Result], - repo_dir: Path, + repo_dir: PathLike, ) -> None: """ Generate both indices: @@ -228,6 +229,7 @@ def generate_indices( (For the ideas repo, the second file is at `results/README.md`). """ + repo_dir = Path(repo_dir) generate_index( repo_dir / "README.md", bases, all_results, benchmarking_results, True ) @@ -365,7 +367,8 @@ def filter_broken_memory_results(results): return [r for r in results if r.nickname != "darwin"] -def _main(repo_dir: Path, force: bool = False, bases: Sequence[str] | None = None): +def _main(repo_dir: PathLike, force: bool = False, bases: Sequence[str] | None = None): + repo_dir = Path(repo_dir) results_dir = repo_dir / "results" if bases is None: bases = get_bases() diff --git a/bench_runner/scripts/get_merge_base.py b/bench_runner/scripts/get_merge_base.py index 7eec3d6e..8fbebb35 100644 --- a/bench_runner/scripts/get_merge_base.py +++ b/bench_runner/scripts/get_merge_base.py @@ -10,10 +10,11 @@ from bench_runner import git from bench_runner.result import has_result from bench_runner import util +from bench_runner.util import PathLike -def get_python_version(cpython: Path): - with (cpython / "Include" / "patchlevel.h").open() as fd: +def get_python_version(cpython: PathLike): + with (Path(cpython) / "Include" / "patchlevel.h").open() as fd: for line in fd.readlines(): if m := re.match(r'#define\s+PY_VERSION\s+"(.+)"', line.strip()): return m.groups()[0] @@ -25,7 +26,7 @@ def _main( machine: str, pystats: bool, flags: list[str], - cpython: Path = Path("cpython"), + cpython: PathLike = Path("cpython"), ) -> None: commit_hash = git.get_git_hash(cpython) print(f"head={commit_hash}") diff --git a/bench_runner/scripts/install.py b/bench_runner/scripts/install.py index c405a0ec..b0418ca6 100644 --- a/bench_runner/scripts/install.py +++ b/bench_runner/scripts/install.py @@ -21,6 +21,7 @@ from bench_runner import config from bench_runner import flags from bench_runner import runners +from bench_runner.util import PathLike ROOT_PATH = Path() @@ -28,9 +29,9 @@ WORKFLOW_PATH = Path() / ".github" / "workflows" -def fail_check(dst: Path): +def fail_check(dst: PathLike): rich.print( - f"[red]{dst.relative_to(ROOT_PATH)} needs to be regenerated.[/red]", + f"[red]{Path(dst).relative_to(ROOT_PATH)} needs to be regenerated.[/red]", file=sys.stderr, ) rich.print( @@ -40,7 +41,7 @@ def fail_check(dst: Path): sys.exit(1) -def write_yaml(dst: Path, contents: Any, check: bool): +def write_yaml(dst: PathLike, contents: Any, check: bool): """ Write `contents` to `dst` as YAML. @@ -48,6 +49,7 @@ def write_yaml(dst: Path, contents: Any, check: bool): in CI to confirm that the file was regenerated after changes to the source file. """ + dst = Path(dst) def do_write(contents, fd): fd.write("# Generated file: !!! DO NOT EDIT !!!\n") @@ -70,11 +72,11 @@ def do_write(contents, fd): do_write(contents, fd) -def load_yaml(src: Path) -> Any: +def load_yaml(src: PathLike) -> Any: """ Load YAML from `src`. """ - with src.open() as fd: + with Path(src).open() as fd: yaml = YAML() return yaml.load(fd) diff --git a/bench_runner/scripts/profiling_plot.py b/bench_runner/scripts/profiling_plot.py index b2144c7f..bcf0c973 100644 --- a/bench_runner/scripts/profiling_plot.py +++ b/bench_runner/scripts/profiling_plot.py @@ -20,6 +20,9 @@ import rich_argparse +from bench_runner.util import PathLike + + SANITY_CHECK = True @@ -253,11 +256,13 @@ def category_for_obj_sym(obj: str, sym: str) -> str: def handle_benchmark( - csv_path: Path, + csv_path: PathLike, md: IO[str], results: defaultdict[str, defaultdict[str, float]], categories: defaultdict[str, defaultdict[tuple[str, str], float]], ): + csv_path = Path(csv_path) + stem = csv_path.stem.split(".", 1)[0] md.write(f"\n## {stem}\n\n") @@ -322,7 +327,7 @@ def handle_benchmark( def plot_bargraph( results: defaultdict[str, defaultdict[str, float]], categories: list[tuple[float, str]], - output_filename: Path, + output_filename: PathLike, ): fig, ax = plt.subplots(figsize=(8, len(results) * 0.3), layout="constrained") @@ -357,7 +362,7 @@ def plot_bargraph( fig.savefig(output_filename) -def plot_pie(categories: list[tuple[float, str]], output_filename: Path): +def plot_pie(categories: list[tuple[float, str]], output_filename: PathLike): fig, ax = plt.subplots(figsize=(5, 3), layout="constrained") values = [x[0] for x in categories] labels = [i < 10 and f"{x[1]} {x[0]:.2%}" or "" for i, x in enumerate(categories)] @@ -380,7 +385,10 @@ def plot_pie(categories: list[tuple[float, str]], output_filename: Path): fig.savefig(output_filename, dpi=200) -def _main(input_dir: Path, output_prefix: Path): +def _main(input_dir: PathLike, output_prefix: PathLike): + input_dir = Path(input_dir) + output_prefix = Path(output_prefix) + results = defaultdict(lambda: defaultdict(float)) categories = defaultdict(lambda: defaultdict(float)) diff --git a/bench_runner/scripts/purge.py b/bench_runner/scripts/purge.py index d1a5dfe9..d623b30a 100644 --- a/bench_runner/scripts/purge.py +++ b/bench_runner/scripts/purge.py @@ -19,9 +19,10 @@ from bench_runner.bases import get_bases, get_minimum_version_for_all_comparisons from bench_runner.result import load_all_results from bench_runner.scripts.generate_results import _main as generate_results +from bench_runner.util import PathLike -def dir_size(path: Path) -> int: +def dir_size(path: PathLike) -> int: total = 0 for root, _, files in os.walk(path): root = Path(root) @@ -30,8 +31,10 @@ def dir_size(path: Path) -> int: return total -def _main(repo_dir: Path, days: int, dry_run: bool, bases: Sequence[str] | None = None): - results_dir = repo_dir / "results" +def _main( + repo_dir: PathLike, days: int, dry_run: bool, bases: Sequence[str] | None = None +): + results_dir = Path(repo_dir) / "results" if bases is None: bases = get_bases() if len(bases) == 0: diff --git a/bench_runner/scripts/remove_benchmark.py b/bench_runner/scripts/remove_benchmark.py index e78d8879..ffbf07dc 100644 --- a/bench_runner/scripts/remove_benchmark.py +++ b/bench_runner/scripts/remove_benchmark.py @@ -14,12 +14,13 @@ from bench_runner import result from bench_runner.scripts import generate_results +from bench_runner.util import PathLike def remove_benchmark( - filename: Path, remove: set[str], keep_hash: set[str], dry_run: bool + filename: PathLike, remove: set[str], keep_hash: set[str], dry_run: bool ): - with filename.open() as fd: + with Path(filename).open() as fd: data = json.load(fd) if data["metadata"]["benchmark_hash"] in keep_hash: @@ -37,7 +38,7 @@ def remove_benchmark( data["benchmarks"] = benchmarks if not dry_run: - with filename.open("w") as fd: + with Path(filename).open("w") as fd: json.dump(data, fd, indent=2) diff --git a/bench_runner/scripts/run_benchmarks.py b/bench_runner/scripts/run_benchmarks.py index a1e7fbaa..96b67110 100644 --- a/bench_runner/scripts/run_benchmarks.py +++ b/bench_runner/scripts/run_benchmarks.py @@ -12,7 +12,7 @@ import sys import tempfile import textwrap -from typing import Iterable, Union +from typing import Iterable import rich_argparse @@ -23,6 +23,7 @@ from bench_runner.result import Result from bench_runner.table import md_link from bench_runner import util +from bench_runner.util import PathLike REPO_ROOT = Path() @@ -61,7 +62,7 @@ def get_benchmark_names(benchmarks: str) -> list[str]: def run_benchmarks( - python: Union[Path, str], + python: PathLike, benchmarks: str, command_prefix: Iterable[str] | None = None, test_mode: bool = False, @@ -122,7 +123,7 @@ def run_benchmarks( def collect_pystats( - python: Path, + python: PathLike, benchmarks: str, fork: str, ref: str, @@ -172,7 +173,7 @@ def collect_pystats( run_summarize_stats(python, fork, ref, "all", benchmark_links, flags=flags) -def perf_to_csv(lines: Iterable[str], output: Path): +def perf_to_csv(lines: Iterable[str], output: PathLike): event_count_prefix = "# Event count (approx.): " total = None @@ -194,14 +195,14 @@ def perf_to_csv(lines: Iterable[str], output: Path): rows.sort(key=itemgetter(0), reverse=True) - with output.open("w") as fd: + with Path(output).open("w") as fd: csvwriter = csv.writer(fd) csvwriter.writerow(["self", "pid", "command", "shared_obj", "symbol"]) for row in rows: csvwriter.writerow(row) -def collect_perf(python: Path, benchmarks: str): +def collect_perf(python: PathLike, benchmarks: str): all_benchmarks = get_benchmark_names(benchmarks) if PROFILING_RESULTS.is_dir(): @@ -250,13 +251,13 @@ def collect_perf(python: Path, benchmarks: str): def update_metadata( - filename: Path, + filename: PathLike, fork: str, ref: str, - cpython: Path = Path("cpython"), + cpython: PathLike = Path("cpython"), run_id: str | None = None, ) -> None: - with filename.open() as fd: + with Path(filename).open() as fd: content = json.load(fd) metadata = content.setdefault("metadata", {}) @@ -275,12 +276,12 @@ def update_metadata( if actor is not None: metadata["github_actor"] = actor - with filename.open("w") as fd: + with Path(filename).open("w") as fd: json.dump(content, fd, indent=2) def copy_to_directory( - filename: Path, python: Path, fork: str, ref: str, flags: Iterable[str] + filename: PathLike, python: PathLike, fork: str, ref: str, flags: Iterable[str] ) -> None: result = Result.from_scratch(python, fork, ref, flags=flags) result.filename.parent.mkdir(parents=True, exist_ok=True) @@ -288,7 +289,7 @@ def copy_to_directory( def run_summarize_stats( - python: Path, + python: PathLike, fork: str, ref: str, benchmark: str, @@ -364,7 +365,7 @@ def select_benchmarks(benchmarks: str): def _main( mode: str, - python: Path, + python: PathLike, fork: str, ref: str, benchmarks: str, diff --git a/bench_runner/table.py b/bench_runner/table.py index b297bdd2..cc04487f 100644 --- a/bench_runner/table.py +++ b/bench_runner/table.py @@ -7,6 +7,9 @@ from urllib.parse import quote +from .util import PathLike + + def output_table( fd: TextIO, head: Sequence[str], rows: Sequence[Sequence[str]] ) -> None: @@ -23,7 +26,7 @@ def output_row(row): output_row(row) -def replace_section(filename: Path, name: str, content: str) -> None: +def replace_section(filename: PathLike, name: str, content: str) -> None: """ Replace a table in a markdown file with the new content. @@ -35,6 +38,7 @@ def replace_section(filename: Path, name: str, content: str) -> None: ``` """ + filename = Path(filename) lines = iter(filename.read_text().splitlines()) with filename.open("w") as fd: @@ -52,12 +56,12 @@ def replace_section(filename: Path, name: str, content: str) -> None: fd.write(line + "\n") -def md_link(text: str, link: str, root: Path | None = None) -> str: +def md_link(text: str, link: str, root: PathLike | None = None) -> str: """ Formats a Markdown link. The link is resolved relative to the given root. """ if root is not None: - link = str(Path(link).resolve().relative_to(root.parent.resolve())) + link = str(Path(link).resolve().relative_to(Path(root).parent.resolve())) if not str(link).startswith("http"): link = "/".join(quote(x) for x in Path(link).parts) return f"[{text}]({link})" diff --git a/bench_runner/util.py b/bench_runner/util.py index 271384e8..7581e27a 100644 --- a/bench_runner/util.py +++ b/bench_runner/util.py @@ -2,11 +2,15 @@ import hashlib import os from pathlib import Path +from typing import TypeAlias, Union from . import config +PathLike: TypeAlias = Union[str, os.PathLike] + + def get_benchmark_hash() -> str: hash = hashlib.sha256() hash.update(os.environ["PYPERFORMANCE_HASH"].encode("ascii")[:7]) @@ -21,11 +25,12 @@ def get_benchmark_hash() -> str: } -def apply_suffix(path: Path, suffix: str) -> Path: +def apply_suffix(path: PathLike, suffix: str) -> Path: """ Like Path.with_suffix but allows adding things like "-mem.svg". """ - return path.parent / (path.stem + suffix) + path_ = Path(path) + return path_.parent / (path_.stem + suffix) @functools.cache diff --git a/pyrightconfig.json b/pyrightconfig.json index 73cea0ba..bc10f640 100644 --- a/pyrightconfig.json +++ b/pyrightconfig.json @@ -1,4 +1,3 @@ { - "useLibraryCodeForTypes": false, - "reportAttributeAccessIssue": false + "useLibraryCodeForTypes": false }