Parsers

Multi-framework mutation report parsers and framework auto-detection.

Unified mutation testing parser interface.

This module provides a single entry point for parsing mutation testing output from multiple frameworks (Stryker, mutmut, etc.) with automatic framework detection.

Usage:

from curate_ipsum.parsers import parse_mutation_output

# Auto-detect framework result = parse_mutation_output(working_directory=”/path/to/project”)

# Explicit framework result = parse_mutation_output(

working_directory=”/path/to/project”, tool=”mutmut”

)

curate_ipsum.parsers.parse_mutation_output(working_directory, tool=None, report_path=None)[source]

Parse mutation testing output, auto-detecting framework if not specified.

This is the main entry point for all mutation testing parsers. It routes to the appropriate parser based on the tool parameter or auto-detection.

Parameters:
  • working_directory (str) – Project directory containing mutation output

  • tool (str | None) – Optional framework name (“stryker”, “mutmut”, etc.) If None, auto-detects based on available output files

  • report_path (str | None) – Optional path to report file or cache (interpretation depends on framework)

Returns:

Tuple of (total_mutants, killed, survived, no_coverage, score, by_file)

  • total_mutants: Total number of mutants processed

  • killed: Number of mutants killed by tests

  • survived: Number of mutants that survived

  • no_coverage: Number of mutants with no test coverage

  • score: Mutation score as killed/(killed+survived)

  • by_file: Per-file breakdown as FileMutationStats list

Raises:
Return type:

tuple[int, int, int, int, float, list[FileMutationStats]]

Examples

# Auto-detect framework >>> total, killed, survived, no_cov, score, by_file = parse_mutation_output(“./”)

# Explicit Stryker >>> parse_mutation_output(“./”, tool=”stryker”)

# Explicit mutmut with custom cache path >>> parse_mutation_output(“./”, tool=”mutmut”, report_path=”./.mutmut-cache”)

exception curate_ipsum.parsers.UnsupportedFrameworkError[source]

Bases: Exception

Raised when a mutation framework is not supported.

class curate_ipsum.parsers.MutationFramework(*values)[source]

Bases: StrEnum

Supported mutation testing frameworks.

STRYKER = 'stryker'
MUTMUT = 'mutmut'
COSMIC_RAY = 'cosmic-ray'
POODLE = 'poodle'
UNIVERSALMUTATOR = 'universalmutator'
MUTPY = 'mutpy'
UNKNOWN = 'unknown'
class curate_ipsum.parsers.FrameworkDetection(framework, confidence, evidence)[source]

Bases: object

Result of framework detection.

Parameters:
framework: MutationFramework
confidence: float
evidence: str
class curate_ipsum.parsers.ProjectLanguage(primary, secondary, confidence)[source]

Bases: object

Detected project language(s).

Parameters:
primary: str
secondary: list[str]
confidence: float
curate_ipsum.parsers.detect_language(working_directory)[source]

Detect primary language of a project.

Examines file extensions and configuration files to determine the project’s primary programming language.

Parameters:

working_directory (str) – Project directory to analyze

Returns:

ProjectLanguage with primary language and confidence

Return type:

ProjectLanguage

curate_ipsum.parsers.detect_available_frameworks(working_directory)[source]

Detect which mutation frameworks have been run or are configured.

Checks for: - Output files/directories from each framework - Configuration files - Cache files

Parameters:

working_directory (str) – Project directory to analyze

Returns:

List of detected frameworks with confidence scores

Return type:

list[FrameworkDetection]

curate_ipsum.parsers.recommend_framework(working_directory)[source]

Recommend the best mutation framework for a project.

Priority: 1. Already-run frameworks (have output/cache) 2. Configured frameworks 3. Language-based recommendation

Parameters:

working_directory (str) – Project directory

Returns:

Recommended framework with confidence and reasoning

Return type:

FrameworkDetection

curate_ipsum.parsers.parse_stryker_output(report_path, working_directory)[source]

Parse Stryker mutation testing output.

This is the main entry point for Stryker parsing.

Parameters:
  • report_path (str | None) – Optional explicit path to report

  • working_directory (str) – Project directory

Returns:

Tuple of (total_mutants, killed, survived, no_coverage, score, by_file)

Raises:
Return type:

tuple[int, int, int, int, float, list[FileMutationStats]]

curate_ipsum.parsers.parse_mutmut_output(working_directory, cache_path=None)[source]

Parse mutmut results from cache.

This is the main entry point for mutmut parsing, matching the signature of parse_stryker_output for unified interface compatibility.

Parameters:
  • working_directory (str) – Project directory

  • cache_path (str | None) – Optional explicit path to cache file

Returns:

Tuple of (total, killed, survived, no_coverage, score, by_file)

Raises:

FileNotFoundError – If cache not found

Return type:

tuple[int, int, int, int, float, list[FileMutationStats]]

curate_ipsum.parsers.parse_cosmic_ray_output(working_directory, report_path=None)[source]

Parse cosmic-ray mutation testing output.

Main entry point matching the unified parser interface (D-009).

Parameters:
  • working_directory (str) – Project directory

  • report_path (str | None) – Optional explicit path to session file or JSON dump

Returns:

Tuple of (total, killed, survived, no_coverage, score, by_file)

Raises:

FileNotFoundError – If session/report not found

Return type:

tuple[int, int, int, int, float, list[FileMutationStats]]

curate_ipsum.parsers.parse_poodle_output(working_directory, report_path=None)[source]

Parse poodle mutation testing output.

Main entry point matching the unified parser interface (D-009).

Parameters:
  • working_directory (str) – Project directory

  • report_path (str | None) – Optional explicit path to report file

Returns:

Tuple of (total, killed, survived, no_coverage, score, by_file)

Raises:
Return type:

tuple[int, int, int, int, float, list[FileMutationStats]]

curate_ipsum.parsers.parse_universalmutator_output(working_directory, report_path=None)[source]

Parse universalmutator results from killed.txt / not-killed.txt.

Main entry point matching the unified parser interface (D-009).

Parameters:
  • working_directory (str) – Project directory

  • report_path (str | None) – Optional explicit path to results directory

Returns:

Tuple of (total, killed, survived, no_coverage, score, by_file)

Raises:

FileNotFoundError – If result files not found

Return type:

tuple[int, int, int, int, float, list[FileMutationStats]]

Mutation framework and language detection.

Detects: - Project language (Python, JavaScript, etc.) - Available/configured mutation frameworks - Recommends the best framework for a project

class curate_ipsum.parsers.detection.MutationFramework(*values)[source]

Bases: StrEnum

Supported mutation testing frameworks.

STRYKER = 'stryker'
MUTMUT = 'mutmut'
COSMIC_RAY = 'cosmic-ray'
POODLE = 'poodle'
UNIVERSALMUTATOR = 'universalmutator'
MUTPY = 'mutpy'
UNKNOWN = 'unknown'
class curate_ipsum.parsers.detection.FrameworkDetection(framework, confidence, evidence)[source]

Bases: object

Result of framework detection.

Parameters:
framework: MutationFramework
confidence: float
evidence: str
class curate_ipsum.parsers.detection.ProjectLanguage(primary, secondary, confidence)[source]

Bases: object

Detected project language(s).

Parameters:
primary: str
secondary: list[str]
confidence: float
curate_ipsum.parsers.detection.detect_language(working_directory)[source]

Detect primary language of a project.

Examines file extensions and configuration files to determine the project’s primary programming language.

Parameters:

working_directory (str) – Project directory to analyze

Returns:

ProjectLanguage with primary language and confidence

Return type:

ProjectLanguage

curate_ipsum.parsers.detection.detect_available_frameworks(working_directory)[source]

Detect which mutation frameworks have been run or are configured.

Checks for: - Output files/directories from each framework - Configuration files - Cache files

Parameters:

working_directory (str) – Project directory to analyze

Returns:

List of detected frameworks with confidence scores

Return type:

list[FrameworkDetection]

curate_ipsum.parsers.detection.recommend_framework(working_directory)[source]

Recommend the best mutation framework for a project.

Priority: 1. Already-run frameworks (have output/cache) 2. Configured frameworks 3. Language-based recommendation

Parameters:

working_directory (str) – Project directory

Returns:

Recommended framework with confidence and reasoning

Return type:

FrameworkDetection

Stryker mutation testing report parser.

Stryker is a mutation testing framework primarily for JavaScript/TypeScript. This parser handles Stryker’s JSON report format.

Report locations searched (in order): 1. Explicit reportPath argument 2. reports/mutation/mutation.json 3. reports/stryker-report.json

curate_ipsum.parsers.stryker_parser.find_stryker_report(working_directory, report_path=None)[source]

Locate the Stryker report file.

Parameters:
  • working_directory (str) – Project directory

  • report_path (str | None) – Optional explicit path to report

Returns:

Path to report file, or None if not found

Return type:

Path | None

curate_ipsum.parsers.stryker_parser.parse_stryker_report(report_path)[source]

Parse a Stryker JSON report file.

Parameters:

report_path (Path) – Path to the report file

Returns:

Parsed JSON data

Raises:
Return type:

dict

curate_ipsum.parsers.stryker_parser.parse_stryker_output(report_path, working_directory)[source]

Parse Stryker mutation testing output.

This is the main entry point for Stryker parsing.

Parameters:
  • report_path (str | None) – Optional explicit path to report

  • working_directory (str) – Project directory

Returns:

Tuple of (total_mutants, killed, survived, no_coverage, score, by_file)

Raises:
Return type:

tuple[int, int, int, int, float, list[FileMutationStats]]

Mutmut mutation testing cache parser.

Mutmut is a popular Python mutation testing tool. It stores results in a SQLite database (.mutmut-cache) rather than JSON reports.

Cache schema (mutmut 2.x):

SourceFile: filename, hash Line: sourcefile_id, line, line_number Mutant: line_id, index, tested_against_hash, status

Status values:
  • ok_killed: Mutant was killed by tests

  • bad_survived: Mutant survived (not detected)

  • bad_timeout: Test execution timed out

  • ok_suspicious: Suspicious result

  • untested: Not yet tested

  • skipped: Skipped (pragma or config)

class curate_ipsum.parsers.mutmut_parser.MutmutStatus[source]

Bases: object

Mutmut status values (lowercase for comparison).

OK_KILLED = 'ok_killed'
BAD_SURVIVED = 'bad_survived'
BAD_TIMEOUT = 'bad_timeout'
OK_SUSPICIOUS = 'ok_suspicious'
UNTESTED = 'untested'
SKIPPED = 'skipped'
class curate_ipsum.parsers.mutmut_parser.MutmutMutant(id, file_path, line_number, status, index)[source]

Bases: object

A single mutant from mutmut cache.

Parameters:
id: int
file_path: str
line_number: int
status: str
index: int
curate_ipsum.parsers.mutmut_parser.find_mutmut_cache(working_directory)[source]

Locate the mutmut cache file.

Searches in order: 1. .mutmut-cache in working directory 2. .mutmut-cache in parent directories (up to 3 levels)

Parameters:

working_directory (str) – Starting directory to search

Returns:

Path to cache file, or None if not found

Return type:

Path | None

curate_ipsum.parsers.mutmut_parser.parse_mutmut_cache(cache_path)[source]

Parse mutmut SQLite cache and extract all mutants.

Handles multiple schema versions by trying v2 first, then v1.

Parameters:

cache_path (Path) – Path to .mutmut-cache file

Returns:

List of all mutants in the cache

Raises:
Return type:

list[MutmutMutant]

curate_ipsum.parsers.mutmut_parser.aggregate_mutmut_stats(mutants)[source]

Aggregate mutant list into summary statistics.

Groups mutants by file and computes per-file and overall statistics.

Parameters:

mutants (list[MutmutMutant]) – List of mutants to aggregate

Returns:

Tuple of (total, killed, survived, no_coverage, score, by_file)

Return type:

tuple[int, int, int, int, float, list[FileMutationStats]]

curate_ipsum.parsers.mutmut_parser.parse_mutmut_output(working_directory, cache_path=None)[source]

Parse mutmut results from cache.

This is the main entry point for mutmut parsing, matching the signature of parse_stryker_output for unified interface compatibility.

Parameters:
  • working_directory (str) – Project directory

  • cache_path (str | None) – Optional explicit path to cache file

Returns:

Tuple of (total, killed, survived, no_coverage, score, by_file)

Raises:

FileNotFoundError – If cache not found

Return type:

tuple[int, int, int, int, float, list[FileMutationStats]]

curate_ipsum.parsers.mutmut_parser.get_mutmut_region_mutants(working_directory, region, cache_path=None)[source]

Get mutants within a specific region.

Useful for region-level mutation score calculation.

Parameters:
  • working_directory (str) – Project directory

  • region (Region) – Region to filter to

  • cache_path (str | None) – Optional explicit path to cache

Returns:

List of mutants within the region

Return type:

list[MutmutMutant]

curate_ipsum.parsers.mutmut_parser.get_region_mutation_stats(working_directory, region, cache_path=None)[source]

Get mutation statistics for a specific region.

Parameters:
  • working_directory (str) – Project directory

  • region (Region) – Region to get stats for

  • cache_path (str | None) – Optional explicit path to cache

Returns:

FileMutationStats for the region, or None if no mutants found

Return type:

FileMutationStats | None

Cosmic-ray mutation testing parser.

Cosmic-ray is a Python mutation testing tool that stores results in a SQLite session database. Results can also be exported via cosmic-ray dump <session> to JSON.

Session DB schema:
WorkItem: job_id, module, operator_name, occurrence, start_pos, end_pos,

worker_outcome (int), test_outcome (int), diff

JSON dump format (from cosmic-ray dump):
[
{

“module”: “mypackage.mymodule”, “operator”: “core/NumberReplacer”, “occurrence”: 0, “line_number”: 42, “job_id”: “abc123”, “test_outcome”: “TestOutcome.KILLED”, “worker_outcome”: “WorkerOutcome.NORMAL”, “diff”: “— a/mymodule.py

+++ …”

]

Worker outcomes:

NORMAL = 0 # Worker completed normally TIMEOUT = 1 # Worker timed out EXCEPTION = 2 # Worker raised an exception

Test outcomes:

SURVIVED = 0 # Mutant survived (tests passed) KILLED = 1 # Mutant killed (tests failed) INCOMPETENT = 2 # Mutant was incompetent (couldn’t apply)

class curate_ipsum.parsers.cosmic_ray_parser.CosmicRayMutant(job_id, module, operator, occurrence, line_number, worker_outcome, test_outcome)[source]

Bases: object

A single mutant from cosmic-ray results.

Parameters:
  • job_id (str)

  • module (str)

  • operator (str)

  • occurrence (int)

  • line_number (int | None)

  • worker_outcome (str)

  • test_outcome (str)

job_id: str
module: str
operator: str
occurrence: int
line_number: int | None
worker_outcome: str
test_outcome: str
curate_ipsum.parsers.cosmic_ray_parser.find_cosmic_ray_session(working_directory)[source]

Locate the cosmic-ray session database or JSON dump.

Searches for: 1. *.sqlite session databases 2. cosmic-ray.json dump files 3. .cosmic-ray.toml config (to find session path)

Parameters:

working_directory (str) – Starting directory to search

Returns:

Path to session/report file, or None if not found

Return type:

Path | None

curate_ipsum.parsers.cosmic_ray_parser.parse_cosmic_ray_session(session_path)[source]

Parse cosmic-ray results from session file (SQLite or JSON).

Auto-detects format based on file content.

Parameters:

session_path (Path) – Path to session DB or JSON dump

Returns:

List of all mutants

Raises:

FileNotFoundError – If session file doesn’t exist

Return type:

list[CosmicRayMutant]

curate_ipsum.parsers.cosmic_ray_parser.aggregate_cosmic_ray_stats(mutants)[source]

Aggregate cosmic-ray mutants into summary statistics.

Groups mutants by module (converted to file path) and computes per-file and overall statistics.

Classification: - killed: test_outcome == “killed” AND worker_outcome == “normal” - survived: test_outcome == “survived” AND worker_outcome == “normal” - no_coverage: worker_outcome in (“timeout”, “exception”)

OR test_outcome == “incompetent”

Parameters:

mutants (list[CosmicRayMutant]) – List of mutants to aggregate

Returns:

Tuple of (total, killed, survived, no_coverage, score, by_file)

Return type:

tuple[int, int, int, int, float, list[FileMutationStats]]

curate_ipsum.parsers.cosmic_ray_parser.parse_cosmic_ray_output(working_directory, report_path=None)[source]

Parse cosmic-ray mutation testing output.

Main entry point matching the unified parser interface (D-009).

Parameters:
  • working_directory (str) – Project directory

  • report_path (str | None) – Optional explicit path to session file or JSON dump

Returns:

Tuple of (total, killed, survived, no_coverage, score, by_file)

Raises:

FileNotFoundError – If session/report not found

Return type:

tuple[int, int, int, int, float, list[FileMutationStats]]

Poodle (poodle-test) mutation testing parser.

Poodle is a Python mutation testing tool that outputs JSON reports following the mutation-testing-report-schema (same schema used by Stryker).

Report format:
{

“schemaVersion”: “1”, “thresholds”: {“high”: 80, “low”: 60}, “files”: {

“src/module.py”: {

“language”: “python”, “source”: “…”, “mutants”: [

{

“id”: “1”, “mutatorName”: “ConditionalsBoundary”, “replacement”: “>=”, “location”: {

“start”: {“line”: 10, “column”: 5}, “end”: {“line”: 10, “column”: 6}

}, “status”: “Killed”, “description”: “…”

]

}

}

Status values (mutation-testing-report-schema):
  • Killed: Mutant was detected by tests

  • Survived: Mutant was not detected

  • NoCoverage: No tests cover this mutant

  • CompileError: Mutant caused a compilation error

  • RuntimeError: Mutant caused a runtime error

  • Timeout: Test execution timed out

  • Ignored: Mutant was ignored (pragma, config)

  • Pending: Mutant has not been tested yet

curate_ipsum.parsers.poodle_parser.find_poodle_report(working_directory)[source]

Locate the poodle mutation testing report.

Searches for common poodle report locations: 1. mutation-report.json (poodle default) 2. poodle-report.json 3. reports/mutation/mutation.json 4. .poodle-report.json

Parameters:

working_directory (str) – Starting directory to search

Returns:

Path to report file, or None if not found

Return type:

Path | None

curate_ipsum.parsers.poodle_parser.parse_poodle_report(report_path)[source]

Parse a poodle JSON report file.

The report follows the mutation-testing-report-schema, which is the same schema used by Stryker. This parser handles poodle-specific nuances (Python file paths, poodle status values).

Parameters:

report_path (Path) – Path to the report file

Returns:

Parsed JSON data

Raises:
Return type:

dict

curate_ipsum.parsers.poodle_parser.parse_poodle_output(working_directory, report_path=None)[source]

Parse poodle mutation testing output.

Main entry point matching the unified parser interface (D-009).

Parameters:
  • working_directory (str) – Project directory

  • report_path (str | None) – Optional explicit path to report file

Returns:

Tuple of (total, killed, survived, no_coverage, score, by_file)

Raises:
Return type:

tuple[int, int, int, int, float, list[FileMutationStats]]

universalmutator mutation testing parser.

universalmutator is a language-agnostic mutation tool that works by applying regex-based mutations to source files. It outputs results as plain text files.

Output files:

killed.txt - One mutant filename per line (mutants detected by tests) not-killed.txt - One mutant filename per line (mutants NOT detected) notkilled.txt - Alternative name for not-killed.txt

Mutant filenames typically follow the pattern:

<original_file>.mutant.<number>.<mutation_type> or <original_file>_mutant_<number>

Examples

src/main.py.mutant.1.AOR src/utils.py.mutant.2.ROR src/main.py.mutant.3.CRP

curate_ipsum.parsers.universalmutator_parser.find_universalmutator_results(working_directory)[source]

Locate universalmutator result files.

Searches for killed.txt / not-killed.txt in common locations.

Parameters:

working_directory (str) – Starting directory to search

Returns:

Path to the directory containing result files, or None

Return type:

Path | None

curate_ipsum.parsers.universalmutator_parser.parse_universalmutator_output(working_directory, report_path=None)[source]

Parse universalmutator results from killed.txt / not-killed.txt.

Main entry point matching the unified parser interface (D-009).

Parameters:
  • working_directory (str) – Project directory

  • report_path (str | None) – Optional explicit path to results directory

Returns:

Tuple of (total, killed, survived, no_coverage, score, by_file)

Raises:

FileNotFoundError – If result files not found

Return type:

tuple[int, int, int, int, float, list[FileMutationStats]]