Closed 15r10nk closed 2 weeks ago
failed to collect stats
Hmm. I guess mutmut should error out there already. Without that step working, running the tests clean is kinda useless.
These changes will be applied, because you used --inline-snapshot=update
Are you running tests that themselves modify tests in-place on disk?
No, I'm not changing any test files in the tests/
folder on disk.
I create tests for pytest in temporary folders and use pytest to run these tests. The update you see in the log is from one of these pytest runs (rootdir is a temporary dir).
My assumption is that my tests fail for some reason when you try to collect your stats. But I have currently no idea why.
I added a requirements.txt to my branch and tested it in a normal venv.
I got the same problem with mutmut run
, but I was able to execute python -m pytest tests --import-mode=append -x -q
inside the mutants directory successfully.
My best guess at the moment is that your stats collector plugin causes some problems in combination with my tests. I will later take a look at it again.
Getting closer... I discovered that when I go into mutants
and execute pytest it still imports from the original src
dir, and not from the mutants
dir.
Yea.. as I write that I get why. I don't use a src
dir for my projects, so after mutation generation I would get mutants/iommi
for example, while you get mutants/src/inline_snapshot
, but mutants
is added to the python path, while you need mutants/src
to be added!
src_path = (Path('mutants') / 'src')
source_path = (Path('mutants') / 'source')
if src_path.exists():
sys.path.insert(0, str(src_path.absolute()))
elif source_path.exists():
sys.path.insert(0, str(source_path.absolute))
else:
sys.path.insert(0, os.path.abspath('mutants'))
instead of just inserting mutants
works. Now it crashes with SyntaxError: from __future__ imports must occur at the beginning of the file
. Huge progress!
Now I discovered that my trampolines don't preserve generator semantics. So that's where I'm at right now.
I released 3.1.0 with fixes for from __future__
, stat hard exit, and generator handling. Still no luck in running your project though, but I'm getting a lot further.
my generators return also values.
I think you should change your trampoline code to something like this:
if not mutant_under_test.startswith(prefix):
result=yield from orig(*args, **kwargs)
return result # for the yield case
mutant_name = mutant_under_test.rpartition('.')[-1]
result = yield from mutants[mutant_name](*args, **kwargs)
return result
Ah. Good point. I pushed a fix for that. Even with that fix I crash here:
File "/Users/boxed/Projects/inline-snapshot/mutants/src/inline_snapshot/_inline_snapshot.py", line 2297, in _get_changes
yield from _mutmut_yield_from_trampoline(object.__getattribute__(self, "xǁUndecidedValueǁ_get_changes__mutmut_orig"), object.__getattribute__(self, "xǁUndecidedValueǁ_get_changes__mutmut_mutants"), *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/boxed/Projects/inline-snapshot/mutants/src/inline_snapshot/_inline_snapshot.py", line 35, in _mutmut_yield_from_trampoline
result = yield from orig(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/boxed/Projects/inline-snapshot/mutants/src/inline_snapshot/_inline_snapshot.py", line 1541, in xǁUndecidedValueǁ_get_changes__mutmut_orig
yield from handle(self._ast_node, self._old_value)
File "/Users/boxed/Projects/inline-snapshot/mutants/src/inline_snapshot/_inline_snapshot.py", line 1522, in handle
for item in adapter.items(obj, node):
^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/boxed/Projects/inline-snapshot/mutants/src/inline_snapshot/_adapter/dict_adapter.py", line 294, in items
return _mutmut_trampoline(object.__getattribute__(self, "xǁDictAdapterǁitems__mutmut_orig"), object.__getattribute__(self, "xǁDictAdapterǁitems__mutmut_mutants"), *args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/boxed/Projects/inline-snapshot/mutants/src/inline_snapshot/_adapter/dict_adapter.py", line 14, in _mutmut_trampoline
result = orig(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/Users/boxed/Projects/inline-snapshot/mutants/src/inline_snapshot/_adapter/dict_adapter.py", line 60, in xǁDictAdapterǁitems__mutmut_orig
assert isinstance(node, ast.Dict), f'{type(node)}, {ast.unparse(node.parent.parent)}'
^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: <class 'ast.Starred'>, result = orig(*args, **kwargs)
I don't really understand how this happens.
I asked me while reading your trampoline code if it could be possible to remove the trampoline indirection and replace it with if-else constructs in the functions, like:
def add(a,b):
if __mutmut_use_orig(...):
return a+b
elif __mutmut_use_mutant(1,...):
return a-b
elif __mutmut_use_mutant(2,...):
return ... # some other mutant
This would allow it to use inspect.currentframe()
like I do in snapshot().
The global and class namespaces would also stay clean, which can be important for code that uses globals()
or cls.__dict__
Hm. Yea I guess that could work too. The function bodies would be rather huge which can have other problems I guess. It would also make it more annoying to implement the code to get the diff for a mutant.
I tried adding
while 'mutmut' not in frame.f_code.co_name:
frame = frame.f_back
into snapshot()
, which maybe improves things as far as mutmut is concerned, but still it fails on that AST traversal thing.
are you not mutating snapshot()
because it uses inspect.currentframe
or because it has a decorator?
I didn't realize until you said so right now that snapshot()
isn't mutated! I don't know why. It should be!
I removed the decorator and got mutated.
I think the problem is that snapshot() has problems finding the correct frame. I will look at it later again. Maybe this helps you.
Yea ok, so decorators stop mutation! I wrote a small test for that and yea. That should just result in fewer mutants though, not a fail like the traceback above I think.
I think the problem is that snapshot() has problems finding the correct frame. I will look at it later again. Maybe this helps you. Yea, the added while loop I wrote about above will work around that issue.
== 60 failed, 321 passed, 28 skipped, 874 subtests passed in 76.08s (0:01:16) ==
made some progress. skipping the mutmut frames was a good idea, but I had to use:
while "mutmut" in frame.f_code.co_name:
frame = frame.f_back
in
vs not in
is important.
Doh! haha, yea my bad. Coding at night when you are sleep deprived because you're sick doesn't give you the best code :P
That is maybe an other issue but I found it could be caused by the failing mutmut run
.
I tried to apply an mutation.
❯ mutmut show src.inline_snapshot._adapter.value_adapter.xǁValueAdapterǁassign__mutmut_29
# src.inline_snapshot._adapter.value_adapter.xǁValueAdapterǁassign__mutmut_29: not checked
--- src/inline_snapshot/_adapter/value_adapter.py
+++ src/inline_snapshot/_adapter/value_adapter.py
@@ -31,7 +31,6 @@
new_code=new_code,
flag=flag,
old_value=old_value,
- new_value=new_value,
)
return new_value
inline-snapshot on mutmut3 [?] is 📦 v0.13.3 via 🐍 v3.10.14 (venv_mutmut)
❯ mutmut apply src.inline_snapshot._adapter.value_adapter.xǁValueAdapterǁassign__mutmut_29
Traceback (most recent call last):
File "/home/frank/projects/inline-snapshot/venv_mutmut/bin/mutmut", line 8, in <module>
sys.exit(cli())
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/click/core.py", li
ne 1157, in __call__
return self.main(*args, **kwargs)
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/click/core.py", li
ne 1078, in main
rv = self.invoke(ctx)
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/click/core.py", li
ne 1688, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/click/core.py", li
ne 1434, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/click/core.py", li
ne 783, in invoke
return __callback(*args, **kwargs)
File "/home/frank/projects/mutmut/mutmut/__main__.py", line 1393, in apply
apply_mutant(mutant_name)
File "/home/frank/projects/mutmut/mutmut/__main__.py", line 1416, in apply_mutant
raise FileNotFoundError(f'Could not apply mutant {mutant_name}')
FileNotFoundError: Could not apply mutant src.inline_snapshot._adapter.value_adapter.xǁValueAdapterǁassi
gn__mutmut_29
I found the problem:
def assign(self, *args, **kwargs):
yield from _mutmut_yield_from_trampoline(object.__getattribute__(self, "xǁValueAdapterǁassign__mutmut_orig"), object.__getattribute__(self, "xǁValueAdapterǁassign__mutmut_mutants"), *args, **kwargs)
This example is from my ValueAdapter
. The problem is that this generated function does not return the value from the generator
The code should look like this:
def assign(self, *args, **kwargs):
result=yield from _mutmut_yield_from_trampoline(object.__getattribute__(self, "xǁValueAdapterǁassign__mutmut_orig"), object.__getattribute__(self, "xǁValueAdapterǁassign__mutmut_mutants"), *args, **kwargs)
return result
Ah. Fixed on main now.
Now I can get mutmut to collect stats on your project, but running the clean tests fail on test_persist
.
yes, I know. I will look into it.
This is what I get when I run the following command in mutants/
.
❯ MUTANT_UNDER_TEST="." python -m pytest --import-mode=append -k test_outsource
========================================= test session starts ==========================================
platform linux -- Python 3.10.14, pytest-8.3.3, pluggy-1.5.0
rootdir: /home/frank/projects/inline-snapshot/mutants
configfile: pyproject.toml
plugins: xdist-3.6.1, time-machine-2.16.0, hypothesis-6.115.3, subtests-0.13.1, inline-snapshot-0.13.3
collected 381 items / 380 deselected / 1 selected
tests/test_external.py E [100%]
================================================ ERRORS ================================================
___________________________________ ERROR at setup of test_outsource ___________________________________
file /home/frank/projects/inline-snapshot/tests/test_external.py, line 32
def test_outsource(storage):
E fixture 'storage' not found
> available fixtures: LineMatcher, _config_for_test, _pytest, _sys_snapshot, cache, capfd, capfdbi
nary, caplog, capsys, capsysbinary, check_update, doctest_namespace, executing_used, linecomp, monkeypat
ch, project, pytestconfig, pytester, record_property, record_testsuite_property, record_xml_attribute, r
ecwarn, snapshot_check, source, subtests, testdir, testrun_uid, time_machine, tmp_path, tmp_path_factory
, tmpdir, tmpdir_factory, worker_id
> use 'pytest --fixtures [testpath]' for help on them.
/home/frank/projects/inline-snapshot/tests/test_external.py:32
=========================================== inline snapshot ============================================
=========================== short test summary info ============================
ERROR tests/test_external.py::test_outsource
======================= 380 deselected, 1 error in 0.20s =======================
rootdir is mutants/
(which is correct) but the test is from the project root.
It should be from /home/frank/projects/inline-snapshot/mutants/tests/test_external.py:32
I have the same problem when I run it with mutmut run
(the might look different because I changed some mutmut code.)
❯ mutmut run
generating mutants
done in 1982ms
⠏ running stats> pytest -x -q --import-mode=append {'plugins': [<mutmut.__main__.PytestRunner.run_stats.
<locals>.StatsCollector object at 0x7fdd331bf010>]}
...........F
=============================================== FAILURES ===============================================
___________________________________ test_snapshot_generates_hasrepr ____________________________________
def test_snapshot_generates_hasrepr():
> Example(
"""\
from inline_snapshot import snapshot
class Thing:
def __repr__(self):
return "<something>"
def __eq__(self,other):
if not isinstance(other,Thing):
return NotImplemented
return True
def test_thing():
assert Thing() == snapshot()
"""
).run_pytest(
["--inline-snapshot=create"],
returncode=snapshot(0),
changed_files=snapshot(
{
"test_something.py": """\
from inline_snapshot import snapshot
from inline_snapshot import HasRepr
class Thing:
def __repr__(self):
return "<something>"
def __eq__(self,other):
if not isinstance(other,Thing):
return NotImplemented
return True
def test_thing():
assert Thing() == snapshot(HasRepr(Thing, "<something>"))
\
"""
}
),
).run_pytest(
["--inline-snapshot=disable"], returncode=0
).run_pytest(
returncode=0
)
../tests/test_code_repr.py:46:
the test should be from tests/test_code_repr.py:46:
and not from ../tests/test_code_repr.py:46:
I made some progress by setting the --rootdir
M mutmut/__main__.py
@@ -683,7 +683,7 @@ class ListAllTestsResult:
class PytestRunner(TestRunner):
def execute_pytest(self, params, **kwargs):
import pytest
- exit_code = int(pytest.main(params, **kwargs))
+ exit_code = int(pytest.main(["--rootdir=.",*params], **kwargs))
if exit_code == 4:
raise BadTestExecutionCommandsException(params)
return exit_code
I use now the correct inline-snapshot version in every case for all of my tests. I get now a different error:
❯ mutmut run
generating mutants
done in 1971ms
⠧ running stats...........F
=============================================== FAILURES ===============================================
___________________________________ test_snapshot_generates_hasrepr ____________________________________
def test_snapshot_generates_hasrepr():
> Example(
"""\
from inline_snapshot import snapshot
class Thing:
def __repr__(self):
return "<something>"
def __eq__(self,other):
if not isinstance(other,Thing):
return NotImplemented
return True
def test_thing():
assert Thing() == snapshot()
"""
).run_pytest(
["--inline-snapshot=create"],
returncode=snapshot(0),
changed_files=snapshot(
{
"test_something.py": """\
from inline_snapshot import snapshot
from inline_snapshot import HasRepr
class Thing:
def __repr__(self):
return "<something>"
def __eq__(self,other):
if not isinstance(other,Thing):
return NotImplemented
return True
def test_thing():
assert Thing() == snapshot(HasRepr(Thing, "<something>"))
\
"""
}
),
).run_pytest(
["--inline-snapshot=disable"], returncode=0
).run_pytest(
returncode=0
)
../tests/test_code_repr.py:46:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
src/inline_snapshot/testing/_example.py:14784: in run_pytest
result = _mutmut_trampoline(object.__getattribute__(self, "xǁExampleǁrun_pytest__mutmut_orig"), obj
ect.__getattribute__(self, "xǁExampleǁrun_pytest__mutmut_mutants"), *args, **kwargs)
src/inline_snapshot/testing/_example.py:14: in _mutmut_trampoline
result = orig(*args, **kwargs)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <inline_snapshot.testing._example.Example object at 0x7f261b99dc90>
args = ['--inline-snapshot=create']
def xǁExampleǁrun_pytest__mutmut_orig(
self,
args: list[str] = [],
*,
env: dict[str, str] = {},
changed_files: Snapshot[dict[str, str]] | None = None,
report: Snapshot[str] | None = None,
returncode: Snapshot[int] | None = None,
) -> Example:
"""Run pytest with the given args and env variables in an seperate
process.
It can be used to test the interaction between your code and pytest, but it is a bit slower than
`run_inline`
Parameters:
args: pytest arguments like "--inline-snapshot=fix"
env: dict of environment variables
changed_files: snapshot of files which are changed by this run.
report: snapshot of the report at the end of the pytest run.
returncode: snapshot of the pytest returncode.
Returns:
A new Example instance which contains the changed files.
"""
with TemporaryDirectory() as dir:
tmp_path = Path(dir)
self._write_files(tmp_path)
cmd = ["pytest", *args]
term_columns = 80
command_env = dict(os.environ)
command_env["TERM"] = "unknown"
command_env["COLUMNS"] = str(
term_columns + 1 if platform.system() == "Windows" else term_columns
)
command_env.pop("CI", None)
command_env.update(env)
result = sp.run(cmd, cwd=tmp_path, capture_output=True, env=command_env)
print("run>", *cmd)
print("stdout:")
print(result.stdout.decode())
print("stderr:")
print(result.stderr.decode())
if returncode is not None:
> assert result.returncode == returncode
E AssertionError
src/inline_snapshot/testing/_example.py:7544: AssertionError
----------------------------------------- Captured stdout call -----------------------------------------
file: test_something.py
from inline_snapshot import snapshot
class Thing:
def __repr__(self):
return "<something>"
def __eq__(self,other):
if not isinstance(other,Thing):
return NotImplemented
return True
def test_thing():
assert Thing() == snapshot()
run> pytest --inline-snapshot=create
stdout:
stderr:
Traceback (most recent call last):
File "/home/frank/projects/inline-snapshot/venv_mutmut/bin/pytest", line 8, in <module>
sys.exit(console_main())
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/_pytest/config/__i
nit__.py", line 201, in console_main
code = main()
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/_pytest/config/__i
nit__.py", line 156, in main
config = _prepareconfig(args, plugins)
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/_pytest/config/__i
nit__.py", line 341, in _prepareconfig
config = pluginmanager.hook.pytest_cmdline_parse(
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/pluggy/_hooks.py",
line 513, in __call__
return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/pluggy/_manager.py
", line 120, in _hookexec
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/pluggy/_callers.py
", line 139, in _multicall
raise exception.with_traceback(exception.__traceback__)
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/pluggy/_callers.py
", line 122, in _multicall
teardown.throw(exception) # type: ignore[union-attr]
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/_pytest/helpconfig
.py", line 105, in pytest_cmdline_parse
config = yield
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/pluggy/_callers.py
", line 103, in _multicall
res = hook_impl.function(*args)
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/_pytest/config/__i
nit__.py", line 1140, in pytest_cmdline_parse
self.parse(args)
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/_pytest/config/__i
nit__.py", line 1494, in parse
self._preparse(args, addopts=addopts)
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/_pytest/config/__i
nit__.py", line 1381, in _preparse
self.pluginmanager.load_setuptools_entrypoints("pytest11")
File "/home/frank/projects/inline-snapshot/venv_mutmut/lib/python3.10/site-packages/pluggy/_manager.py
", line 421, in load_setuptools_entrypoints
plugin = ep.load()
File "/home/frank/.local/share/hatch/pythons/3.10/python/lib/python3.10/importlib/metadata/__init__.py
", line 171, in load
module = import_module(match.group('module'))
File "/home/frank/.local/share/hatch/pythons/3.10/python/lib/python3.10/importlib/__init__.py", line 1
26, in import_module
return _bootstrap._gcd_import(name[level:], package, level)
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 992, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 883, in exec_module
File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
File "/home/frank/projects/inline-snapshot/mutants/src/inline_snapshot/__init__.py", line 46, in <modu
le>
from ._code_repr import customize_repr
File "/home/frank/projects/inline-snapshot/mutants/src/inline_snapshot/_code_repr.py", line 562, in <m
odule>
def _(value: Enum):
File "/home/frank/projects/inline-snapshot/mutants/src/inline_snapshot/_code_repr.py", line 410, in cu
stomize_repr
result = _mutmut_trampoline(x_customize_repr__mutmut_orig, x_customize_repr__mutmut_mutants, *args,
**kwargs)
File "/home/frank/projects/inline-snapshot/mutants/src/inline_snapshot/_code_repr.py", line 12, in _mu
tmut_trampoline
record_trampoline_hit(orig.__module__ + '.' + orig.__name__)
File "/home/frank/projects/mutmut/mutmut/__main__.py", line 135, in record_trampoline_hit
if mutmut.config.max_stack_depth != -1:
AttributeError: module 'mutmut' has no attribute 'config'
=========================================== inline snapshot ============================================
Error: one snapshot has incorrect values (--inline-snapshot=fix)
You can also use --inline-snapshot=review to approve the changes interactively
=========================== short test summary info ============================
FAILED tests/test_code_repr.py::test_snapshot_generates_hasrepr - AssertionError
!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!
1 failed, 11 passed in 1.16s
failed to collect stats. runner returned 1
The reason is that I write source files in temporary folders and execute them with pytest in a subprocess. But mutmut is not initialized in this case. Is it possible that mutmut3 can work in subprocesses?
The reason is that I write source files in temporary folders and execute them with pytest in a subprocess.
And you want those subprocesses to have mutants turned on?
But mutmut is not initialized in this case. Is it possible that mutmut3 can work in subprocesses?
Not in this case I think. Even if it survives the conf (by say loading it), the registration of the trampoline hit is communicated in-process. I guess that could be changed to be a network call or a local pipe or something...
With this conf in setup.cfg i get a bit further
[mutmut]
also_copy=
conftest.py
pyproject.toml
do_not_mutate=
src/inline_snapshot/pytest_plugin.py
And you want those subprocesses to have mutants turned on?
I would be nice if it is possible, but it is not a must have. I fixed the subprocess problem for now:
def record_trampoline_hit(name):
if not hasattr(mutmut,"config"):
return
This causes no crash and I hope it is ok for mutmut.
I think the only open problem is that mutmut does not copy my py.typed
file from src/inline-snapshot
You can add it to the also_copy
config.
This issue turned into a pile of issues, many (all?) of which are solved, so I'm closing this. If there are problems still, it's better to create new issues for that.
I tried to test inline-snapshot with mutmut but got the following error:
I don't know if this problem is only caused by mutmut, because inline-snapshot does also some special things with pytest/assert-rewriting and some ast analysis which can have problems when the source code is modified before it is compiled.
I hope you can reproduce the problem in this branch with.