From 5289bd9ebe73ce74311a218d67057f805c4fa6f8 Mon Sep 17 00:00:00 2001 From: Ryan Crabbe Date: Sat, 9 May 2026 18:45:18 -0700 Subject: [PATCH] fix(mutation report): correctly parse function names with leading underscores mutmut's mutant-name prefix is x_ (single underscore), so a function named _foo produces mutants x__foo__mutmut_N. The previous regex \.x__(.+)__mutmut_ ate the function's leading underscore as part of the prefix. Changed to \.x_(.+)__mutmut_ so leading underscores are preserved in the captured function name; verified for normal, leading- underscore, and dunder-method names. --- scripts/mutation_report.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/mutation_report.py b/scripts/mutation_report.py index 99cba7fdec9..4d02a307cdc 100644 --- a/scripts/mutation_report.py +++ b/scripts/mutation_report.py @@ -55,8 +55,15 @@ def get_mutmut_show(mutant_name: str) -> str: def parse_mutant_name(name: str) -> tuple[str, str, str]: - """Parse `.x____mutmut_` -> (module, function, N).""" - m = re.match(r"^(.+)\.x__(.+)__mutmut_(\d+)$", name) + """Parse `.x___mutmut_` -> (module, function, N). + + mutmut prefixes mutated functions with `x_` (single underscore). For a + function named `foo`, mutants are `x_foo__mutmut_N`. For a function named + `_foo` (leading underscore), the mutant becomes `x__foo__mutmut_N` — so + the regex matches a single underscore after `x` and captures everything + (including any leading underscores) up to `__mutmut_`. + """ + m = re.match(r"^(.+)\.x_(.+)__mutmut_(\d+)$", name) if not m: return name, name, "?" return m.group(1), m.group(2), m.group(3)