Skip to content

Fix "pragma: no mutate" on match/case headers being silently ignored - #554

Open
mathieu-lacage wants to merge 1 commit into
boxed:mainfrom
mathieu-lacage:main
Open

Fix "pragma: no mutate" on match/case headers being silently ignored#554
mathieu-lacage wants to merge 1 commit into
boxed:mainfrom
mathieu-lacage:main

Conversation

@mathieu-lacage

Copy link
Copy Markdown

visit_Match incorrectly assumed that Match has the same structure as an if/elif/else statement and the code was missing a visit_MatchCase to handle individual case statements:

  • fix visit_Match, add visit_MatchCase
  • add corresponding parser unit tests
  • add corresponding e2e mutation tests

Disclaimer: I generated this fix and the corresponding unit tests with claude Sonnet. I reviewed extensively both the patch and the tests.

visit_Match incorrectly assumed that Match has the same structure as an
if/elif/else statement and the code was missing a visit_MatchCase to
handle individual case statements:

- fix visit_Match, add visit_MatchCase
- add corresponding parser unit tests
- add corresponding e2e mutation tests
@mathieu-lacage

Copy link
Copy Markdown
Author

mathieu@Host-001:~/code-oss/mutmut$ uv run pytest
==================================================================================================================== test session starts =====================================================================================================================
platform linux -- Python 3.10.20, pytest-9.0.3, pluggy-1.6.0
rootdir: /home/mathieu/code-oss/mutmut
configfile: pyproject.toml
testpaths: tests
plugins: asyncio-1.3.0, inline-snapshot-0.32.0
asyncio: mode=strict, debug=False, asyncio_default_fixture_loop_scope=function, asyncio_default_test_loop_scope=function
collected 393 items

tests/e2e/test_cli_version.py .... [ 1%]
tests/e2e/test_e2e_config.py . [ 1%]
tests/e2e/test_e2e_coverage.py . [ 1%]
tests/e2e/test_e2e_my_lib.py . [ 1%]
tests/e2e/test_e2e_py3_14.py s [ 2%]
tests/e2e/test_e2e_type_checking.py .. [ 2%]
tests/mutation/test_line_spans.py .............. [ 6%]
tests/mutation/test_mutation.py ..........................................................................................................................................................................................................s........... [ 60%]
....................... [ 66%]
tests/mutation/test_mutation_runtime.py ..... [ 67%]
tests/mutation/test_pragma_handling.py .......................................... [ 78%]
tests/mutation/test_trampoline.py ............................. [ 85%]
tests/test_check_associations.py ..... [ 87%]
tests/test_code_coverage.py ..... [ 88%]
tests/test_configuration.py .............................. [ 95%]
tests/test_generation_error_handling.py . [ 96%]
tests/test_mutation regression.py . [ 96%]
tests/test_type_checking.py .... [ 97%]
tests/threading/test_timeout.py ........ [ 99%]
tests/utils/test_safe_setproctitle.py ss [100%]

============================================================================================================== 389 passed, 4 skipped in 14.11s ===============================================================================================================
mathieu@Host-001:~/code-oss/mutmut$

@mathieu-lacage mathieu-lacage changed the title Fix pragma: no mutate on match/case headers being silently ignored Fix "pragma: no mutate" on match/case headers being silently ignored Aug 19, 2026

@nicklafleur nicklafleur left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice catch

nicklafleur pushed a commit that referenced this pull request Sep 5, 2026
* Honour 'pragma: no mutate block' on else/except/finally arms

_visit_compound_header is only reachable from visit_If/For/While/With/
Try/FunctionDef/ClassDef/Match. In libcst, else, except, except* and
finally are separate nodes owning their own suite, so a pragma on their
header line reached no visitor and was silently dropped -- while elif,
which parses as a nested If, worked. try/except* parses as TryStar, so
the pragma on its try line was dropped too.

README documents the block pragma as working on 'any compound statement
-- functions, classes, if/elif/else, loops, context managers, etc.'

Match/MatchCase is left alone; #554 is fixing that.

* tests: triple-quote the compound-arm pragma sources

The parametrized cases were escaped one-line strings while every other
test in the file writes its source as a triple-quoted block with real
newlines and indentation. Match the surrounding style so the pragma
placement is readable at a glance. No behaviour change.

---------

Co-authored-by: Dylan Pulver <dylanpulver@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants