NameError: trampoline name mangling breaks classes with leading underscore
Description
Classes with a leading underscore (e.g. _MyValidator) cause a NameError at import time because the generated trampoline name triggers Python's name mangling.
NameError: name '_CrossDomainValidator__CrossDomainValidator_validate_trampoline' is not defined
This prevents the entire test suite from running - not just the affected mutant.
Root Cause
trampoline_templates.py (L70) and file_mutation.py (L364) both build the prefix as:
prefix = f"_{class_name}_{method_name}"
When class_name = "_CrossDomainValidator", the resulting name starts with __, which Python mangles inside the class body. The module-level function keeps the original name, so the reference breaks.
Suggested Fix
Strip leading underscores from class_name in the prefix:
prefix = f"_{class_name.lstrip('_')}_{method_name}"
Caveat: if a module contains both class Foo and class _Foo with the same method name, this would produce identical prefixes. An alternative that avoids any collision risk:
prefix = f"_mutmut_{class_name}_{method_name}"
Real-World Case
I hit this in orchard-ml on the _CrossDomainValidator class in orchard/core/config/manifest.py. The lstrip fix resolves the issue - mutmut runs and all mutants are processed correctly.
Happy to open a PR with either approach.
NameError: trampoline name mangling breaks classes with leading underscore
Description
Classes with a leading underscore (e.g.
_MyValidator) cause aNameErrorat import time because the generated trampoline name triggers Python's name mangling.This prevents the entire test suite from running - not just the affected mutant.
Root Cause
trampoline_templates.py(L70) andfile_mutation.py(L364) both build the prefix as:When
class_name = "_CrossDomainValidator", the resulting name starts with__, which Python mangles inside the class body. The module-level function keeps the original name, so the reference breaks.Suggested Fix
Strip leading underscores from
class_namein the prefix:Caveat: if a module contains both
class Fooandclass _Foowith the same method name, this would produce identical prefixes. An alternative that avoids any collision risk:Real-World Case
I hit this in orchard-ml on the
_CrossDomainValidatorclass inorchard/core/config/manifest.py. Thelstripfix resolves the issue - mutmut runs and all mutants are processed correctly.Happy to open a PR with either approach.