Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

mutmut breaks on tests with fixture directories with broken symlinks

Aperta
#582 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
3/5
Tempo stimato
1-2 giorni
Idoneità per principianti
75/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python
Ambito
testing

Direzione di ricerca

Inizia con il progetto minimo fornito ed esegui uv run mutmut run per riprodurre il fallimento in mutmut/utils/file_utils.py, nello specifico in copy_also_copy_files(). Verifica come la chiamata a shutil.copytree gestisce il collegamento non valido in tests/fixtures. Il lavoro è completato quando la generazione delle mutazioni termina preservando il collegamento simbolico non valido nel progetto copiato.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

So let's say you have this project (that's a minified version of course)

% tre
.
├── Makefile
├── README.md
├── pyproject.toml
├── src
│   └── example
│       ├── __init__.py
│       └── core.py
├── tests
│   ├── fixtures
│   │   └── broken-link
│   └── test_core.py
└── uv.lock

Directories: 4, Files: 7, Symbolic Links: 1, Lines: 0

And broken-link is, well, a broken link, since my project works with files, links specifically, and I need to ensure that it works on broken links.

% file tests/fixtures/broken-link
tests/fixtures/broken-link: broken symbolic link to missing-target
[project]
name = "mutmut-broken-symlink-mre"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = []

[dependency-groups]
dev = [
    "mutmut==3.8.0",
    "pytest>=8.0",
]

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["src/example"]

[tool.mutmut]
source_paths = ["src"]
only_mutate = ["src/example/core.py"]
pytest_add_cli_args_test_selection = ["tests/test_core.py"]

Tests and implementation themselves don't really matter, but since mutmut copies the whole thing, it follows symlinks and then seem to fall apart.

uv run mutmut run

⠋ Generating mutants
⠙ Generating mutants
⠹ Generating mutants
⠸ Generating mutants
⠼ Generating mutants
Traceback (most recent call last):
  File "/private/tmp/mutmut-broken-symlink-mre/.venv/bin/mutmut", line 10, in <module>
    sys.exit(cli())
             ~~~^^
  File "/private/tmp/mutmut-broken-symlink-mre/.venv/lib/python3.14/site-packages/click/core.py", line 1631, in __call__
    return self.main(*args, **kwargs)
           ~~~~~~~~~^^^^^^^^^^^^^^^^^
  File "/private/tmp/mutmut-broken-symlink-mre/.venv/lib/python3.14/site-packages/click/core.py", line 1552, in main
    rv = self.invoke(ctx)
  File "/private/tmp/mutmut-broken-symlink-mre/.venv/lib/python3.14/site-packages/click/core.py", line 2032, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
                           ~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^
  File "/private/tmp/mutmut-broken-symlink-mre/.venv/lib/python3.14/site-packages/click/core.py", line 1415, in invoke
    return ctx.invoke(self.callback, **ctx.params)
           ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/tmp/mutmut-broken-symlink-mre/.venv/lib/python3.14/site-packages/click/core.py", line 910, in invoke
    return callback(*args, **kwargs)
  File "/private/tmp/mutmut-broken-symlink-mre/.venv/lib/python3.14/site-packages/mutmut/__main__.py", line 941, in run
    _run(mutant_names, max_children)
    ~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/private/tmp/mutmut-broken-symlink-mre/.venv/lib/python3.14/site-packages/mutmut/__main__.py", line 957, in _run
    copy_also_copy_files()
    ~~~~~~~~~~~~~~~~~~~~^^
  File "/private/tmp/mutmut-broken-symlink-mre/.venv/lib/python3.14/site-packages/mutmut/utils/file_utils.py", line 77, in copy_also_copy_files
    shutil.copytree(path, destination, dirs_exist_ok=True)
    ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/<redacted>/.local/share/uv/python/cpython-3.14.4-macos-aarch64-none/lib/python3.14/shutil.py", line 654, in copytree
    return _copytree(entries=entries, src=src, dst=dst, symlinks=symlinks,
                     ignore=ignore, copy_function=copy_function,
                     ignore_dangling_symlinks=ignore_dangling_symlinks,
                     dirs_exist_ok=dirs_exist_ok)
  File "/<redacted>/.local/share/uv/python/cpython-3.14.4-macos-aarch64-none/lib/python3.14/shutil.py", line 608, in _copytree
    raise Error(errors)
shutil.Error: [('tests/fixtures/broken-link', 'mutants/tests/fixtures/broken-link', "[Errno 2] No such file or directory: 'tests/fixtures/broken-link'")]
make: *** [mutant] Error 1

Expected behaviour

I'd expect it to just leave my links the way they are, as my tests need them.
I know for some uses it might be fine to filter out, but it wouldn't work that well in my case.

Context

Potentially related to https://github.com/boxed/mutmut/issues/486, but with how special symlinks are, I decided they deserve their own issue

Lingua principale
Python
Stelle
1.5k
Fork
179
Merge medio
1g 18h
PR unite (30g)
6

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di boxed/mutmut

Tutte le issue di boxed/mutmut

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.