deployproof 0.2.0__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {deployproof-0.2.0/src/deployproof.egg-info → deployproof-0.2.2}/PKG-INFO +6 -5
- {deployproof-0.2.0 → deployproof-0.2.2}/README.md +5 -4
- {deployproof-0.2.0 → deployproof-0.2.2}/pyproject.toml +1 -1
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof/__init__.py +1 -1
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof/cli.py +1 -1
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof/dependencies.py +1 -1
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof/mutator.py +13 -1
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof/reporter.py +1 -1
- {deployproof-0.2.0 → deployproof-0.2.2/src/deployproof.egg-info}/PKG-INFO +6 -5
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_cli.py +3 -3
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_mutator.py +39 -1
- {deployproof-0.2.0 → deployproof-0.2.2}/LICENSE +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/setup.cfg +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof/control_flow.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof/diff.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof/mocks.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof/secrets.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof/symlinks.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof/wsl.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof.egg-info/SOURCES.txt +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof.egg-info/dependency_links.txt +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof.egg-info/entry_points.txt +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof.egg-info/requires.txt +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/src/deployproof.egg-info/top_level.txt +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_baseline_collection_error.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_cli_dependency_scan.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_control_flow.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_dependencies_extractor.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_dependencies_pypi.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_diff.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_edge_cases_validation.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_mocks.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_mutation_suites.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_secrets.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_stress_regressions.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_symlinks.py +0 -0
- {deployproof-0.2.0 → deployproof-0.2.2}/tests/test_wsl.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deployproof
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A deterministic AI-code deployability checker that catches what coverage misses.
|
|
5
5
|
Author-email: SVS Praveen <svspraveens@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -32,10 +32,10 @@ Dynamic: license-file
|
|
|
32
32
|
|
|
33
33
|
> Deterministic pre-push verification for AI-assisted codebases: AST mutation testing, credential scanning, sandbox-escape detection, mock-usage alerts, swallowed-exception checks, and dependency hallucination defense.
|
|
34
34
|
|
|
35
|
-
[](https://pypi.org/project/deployproof/)
|
|
36
36
|
[](https://pypi.org/project/deployproof/)
|
|
37
37
|
[](https://github.com/SVSPraveen/DeployProof/actions/workflows/ci.yml)
|
|
38
|
-
[](https://github.com/SVSPraveen/DeployProof)
|
|
39
39
|
[](stress_fixtures/)
|
|
40
40
|
[](LICENSE)
|
|
41
41
|
|
|
@@ -189,7 +189,7 @@ deployproof check --json
|
|
|
189
189
|
|
|
190
190
|
```json
|
|
191
191
|
{
|
|
192
|
-
"version": "0.2.
|
|
192
|
+
"version": "0.2.2",
|
|
193
193
|
"status": "passed",
|
|
194
194
|
"summary": {
|
|
195
195
|
"target_files_count": 1,
|
|
@@ -271,6 +271,7 @@ deployproof check --json
|
|
|
271
271
|
|
|
272
272
|
## What This Doesn't Do
|
|
273
273
|
|
|
274
|
+
- **Test-only diffs are not yet caught.** If a diff modifies or weakens assertions in a test file without changing the corresponding source file, DeployProof currently sees zero modified source lines and passes with 0 mutants evaluated. This is a known gap — see [INVESTIGATION_blastradius.md](INVESTIGATION_blastradius.md) for the reverse-mapping approach being evaluated to close it. Until this lands, DeployProof does not protect against test suites being weakened directly.
|
|
274
275
|
- **Not a full-repo audit.** Checks are scoped to files changed in the current session (git diff). Files you haven't touched are not re-evaluated.
|
|
275
276
|
- **Python only.** Mutation testing and import extraction currently support Python files only. Other languages are not scanned.
|
|
276
277
|
- **No auto-fix.** DeployProof reports findings; it does not modify your code, rewrite imports, or suggest patches.
|
|
@@ -288,7 +289,7 @@ Fixtures cover weak test suites, zero-test orphan modules, planted OpenAI/AWS cr
|
|
|
288
289
|
|
|
289
290
|
## Status & Roadmap
|
|
290
291
|
|
|
291
|
-
- **Current (v0.2.
|
|
292
|
+
- **Current (v0.2.2):** Diff-scoped AST mutation testing (with recursive `test/`/`tests/` discovery, AST column-offset snippet reconstruction, and `SIGINT`/`SIGTERM`/`SIGBREAK` signal-safe disk restoration), baseline test-collection failure isolation with distinct exit code `2`, entropy-driven value-based secrets scanner (including unquoted .env values and prefix validation), GhostApproval symlink sandbox-escape detector, PyPI dependency hallucination / slopsquatting scanner (with import-to-distribution translation, recursive `-r` requirements scanning, and dynamic import detection via `importlib` / `__import__`), mock-introduction detector (`--strict-mocks`), control-flow / swallowed-exception scanner (`--strict-error-handling`), 11/11 launch-day stress test suite, 94 unit tests, machine-readable `--json` output, and Tier 2 CI verification via GitHub Actions (mutmut).
|
|
292
293
|
- **Next:** Multi-language mutation support and expanded ecosystem rule packs.
|
|
293
294
|
|
|
294
295
|
## Contributing
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
> Deterministic pre-push verification for AI-assisted codebases: AST mutation testing, credential scanning, sandbox-escape detection, mock-usage alerts, swallowed-exception checks, and dependency hallucination defense.
|
|
4
4
|
|
|
5
|
-
[](https://pypi.org/project/deployproof/)
|
|
6
6
|
[](https://pypi.org/project/deployproof/)
|
|
7
7
|
[](https://github.com/SVSPraveen/DeployProof/actions/workflows/ci.yml)
|
|
8
|
-
[](https://github.com/SVSPraveen/DeployProof)
|
|
9
9
|
[](stress_fixtures/)
|
|
10
10
|
[](LICENSE)
|
|
11
11
|
|
|
@@ -159,7 +159,7 @@ deployproof check --json
|
|
|
159
159
|
|
|
160
160
|
```json
|
|
161
161
|
{
|
|
162
|
-
"version": "0.2.
|
|
162
|
+
"version": "0.2.2",
|
|
163
163
|
"status": "passed",
|
|
164
164
|
"summary": {
|
|
165
165
|
"target_files_count": 1,
|
|
@@ -241,6 +241,7 @@ deployproof check --json
|
|
|
241
241
|
|
|
242
242
|
## What This Doesn't Do
|
|
243
243
|
|
|
244
|
+
- **Test-only diffs are not yet caught.** If a diff modifies or weakens assertions in a test file without changing the corresponding source file, DeployProof currently sees zero modified source lines and passes with 0 mutants evaluated. This is a known gap — see [INVESTIGATION_blastradius.md](INVESTIGATION_blastradius.md) for the reverse-mapping approach being evaluated to close it. Until this lands, DeployProof does not protect against test suites being weakened directly.
|
|
244
245
|
- **Not a full-repo audit.** Checks are scoped to files changed in the current session (git diff). Files you haven't touched are not re-evaluated.
|
|
245
246
|
- **Python only.** Mutation testing and import extraction currently support Python files only. Other languages are not scanned.
|
|
246
247
|
- **No auto-fix.** DeployProof reports findings; it does not modify your code, rewrite imports, or suggest patches.
|
|
@@ -258,7 +259,7 @@ Fixtures cover weak test suites, zero-test orphan modules, planted OpenAI/AWS cr
|
|
|
258
259
|
|
|
259
260
|
## Status & Roadmap
|
|
260
261
|
|
|
261
|
-
- **Current (v0.2.
|
|
262
|
+
- **Current (v0.2.2):** Diff-scoped AST mutation testing (with recursive `test/`/`tests/` discovery, AST column-offset snippet reconstruction, and `SIGINT`/`SIGTERM`/`SIGBREAK` signal-safe disk restoration), baseline test-collection failure isolation with distinct exit code `2`, entropy-driven value-based secrets scanner (including unquoted .env values and prefix validation), GhostApproval symlink sandbox-escape detector, PyPI dependency hallucination / slopsquatting scanner (with import-to-distribution translation, recursive `-r` requirements scanning, and dynamic import detection via `importlib` / `__import__`), mock-introduction detector (`--strict-mocks`), control-flow / swallowed-exception scanner (`--strict-error-handling`), 11/11 launch-day stress test suite, 94 unit tests, machine-readable `--json` output, and Tier 2 CI verification via GitHub Actions (mutmut).
|
|
262
263
|
- **Next:** Multi-language mutation support and expanded ecosystem rule packs.
|
|
263
264
|
|
|
264
265
|
## Contributing
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "deployproof"
|
|
7
|
-
version = "0.2.
|
|
7
|
+
version = "0.2.2"
|
|
8
8
|
description = "A deterministic AI-code deployability checker that catches what coverage misses."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"""DeployProof - Deterministic AI-Code Deployability Checker."""
|
|
2
|
-
__version__ = "0.2.
|
|
2
|
+
__version__ = "0.2.2"
|
|
@@ -82,7 +82,7 @@ def handle_check(args: argparse.Namespace) -> int:
|
|
|
82
82
|
for f in target_files:
|
|
83
83
|
try:
|
|
84
84
|
loc = len(f.read_text(encoding='utf-8', errors='replace').splitlines())
|
|
85
|
-
if loc
|
|
85
|
+
if loc >= LARGE_FILE_LOC_THRESHOLD:
|
|
86
86
|
try:
|
|
87
87
|
rel = f.relative_to(repo_root or cwd)
|
|
88
88
|
except ValueError:
|
|
@@ -983,7 +983,7 @@ def query_pypi_registry(
|
|
|
983
983
|
url = f"https://pypi.org/pypi/{canonical_pkg}/json"
|
|
984
984
|
req = urllib.request.Request(
|
|
985
985
|
url,
|
|
986
|
-
headers={"User-Agent": "DeployProof/0.2.
|
|
986
|
+
headers={"User-Agent": "DeployProof/0.2.2 (https://github.com/SVSPraveen/DeployProof)"},
|
|
987
987
|
)
|
|
988
988
|
|
|
989
989
|
try:
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import ast
|
|
3
3
|
import atexit
|
|
4
4
|
import copy
|
|
5
|
+
import importlib.util
|
|
5
6
|
import os
|
|
6
7
|
import re
|
|
7
8
|
import shutil
|
|
@@ -57,7 +58,7 @@ _PREV_SIGTERM: Any = None
|
|
|
57
58
|
_PREV_SIGBREAK: Any = None
|
|
58
59
|
|
|
59
60
|
def _restore_current_mutant_file() -> None:
|
|
60
|
-
"""Immediately restore the currently mutated file on disk if one is active."""
|
|
61
|
+
"""Immediately restore the currently mutated file on disk if one is active and clear its specific bytecode cache."""
|
|
61
62
|
global _CURRENT_MUTATED_FILE, _CURRENT_ORIGINAL_CONTENT
|
|
62
63
|
if _CURRENT_MUTATED_FILE is not None and _CURRENT_ORIGINAL_CONTENT is not None:
|
|
63
64
|
target_path = _CURRENT_MUTATED_FILE
|
|
@@ -70,6 +71,17 @@ def _restore_current_mutant_file() -> None:
|
|
|
70
71
|
f"Please verify this file's contents before committing or running tests.\n"
|
|
71
72
|
)
|
|
72
73
|
sys.stderr.flush()
|
|
74
|
+
|
|
75
|
+
# Remove specific __pycache__ .pyc entry for target_path if it exists
|
|
76
|
+
try:
|
|
77
|
+
pyc_path_str = importlib.util.cache_from_source(str(target_path))
|
|
78
|
+
if pyc_path_str:
|
|
79
|
+
pyc_file = Path(pyc_path_str)
|
|
80
|
+
if pyc_file.is_file():
|
|
81
|
+
pyc_file.unlink(missing_ok=True)
|
|
82
|
+
except (OSError, ValueError):
|
|
83
|
+
pass
|
|
84
|
+
|
|
73
85
|
_CURRENT_MUTATED_FILE = None
|
|
74
86
|
_CURRENT_ORIGINAL_CONTENT = None
|
|
75
87
|
atexit.register(_restore_current_mutant_file)
|
|
@@ -10,7 +10,7 @@ from deployproof.secrets import SecretsScanResult
|
|
|
10
10
|
from deployproof.symlinks import SymlinkScanResult
|
|
11
11
|
LARGE_FILE_LOC_THRESHOLD = 300
|
|
12
12
|
|
|
13
|
-
def format_json_report(result: MutationResult, target_files: List[Path], secrets_result: Optional[SecretsScanResult]=None, symlink_result: Optional[SymlinkScanResult]=None, dependency_result: Optional[DependencyScanSummary]=None, mock_result: Optional[MockScanSummary]=None, control_flow_result: Optional[ControlFlowScanSummary]=None, strict_mocks: bool=False, strict_error_handling: bool=False, repo_root: Optional[Path]=None, threshold: float=80.0, version: str='0.2.
|
|
13
|
+
def format_json_report(result: MutationResult, target_files: List[Path], secrets_result: Optional[SecretsScanResult]=None, symlink_result: Optional[SymlinkScanResult]=None, dependency_result: Optional[DependencyScanSummary]=None, mock_result: Optional[MockScanSummary]=None, control_flow_result: Optional[ControlFlowScanSummary]=None, strict_mocks: bool=False, strict_error_handling: bool=False, repo_root: Optional[Path]=None, threshold: float=80.0, version: str='0.2.2') -> str:
|
|
14
14
|
"""Format all scan findings and mutation results as a structured JSON string."""
|
|
15
15
|
root = (repo_root or Path.cwd()).resolve()
|
|
16
16
|
strict_mocks_triggered = bool(strict_mocks and mock_result and (mock_result.total_findings > 0))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: deployproof
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A deterministic AI-code deployability checker that catches what coverage misses.
|
|
5
5
|
Author-email: SVS Praveen <svspraveens@gmail.com>
|
|
6
6
|
License-Expression: MIT
|
|
@@ -32,10 +32,10 @@ Dynamic: license-file
|
|
|
32
32
|
|
|
33
33
|
> Deterministic pre-push verification for AI-assisted codebases: AST mutation testing, credential scanning, sandbox-escape detection, mock-usage alerts, swallowed-exception checks, and dependency hallucination defense.
|
|
34
34
|
|
|
35
|
-
[](https://pypi.org/project/deployproof/)
|
|
36
36
|
[](https://pypi.org/project/deployproof/)
|
|
37
37
|
[](https://github.com/SVSPraveen/DeployProof/actions/workflows/ci.yml)
|
|
38
|
-
[](https://github.com/SVSPraveen/DeployProof)
|
|
39
39
|
[](stress_fixtures/)
|
|
40
40
|
[](LICENSE)
|
|
41
41
|
|
|
@@ -189,7 +189,7 @@ deployproof check --json
|
|
|
189
189
|
|
|
190
190
|
```json
|
|
191
191
|
{
|
|
192
|
-
"version": "0.2.
|
|
192
|
+
"version": "0.2.2",
|
|
193
193
|
"status": "passed",
|
|
194
194
|
"summary": {
|
|
195
195
|
"target_files_count": 1,
|
|
@@ -271,6 +271,7 @@ deployproof check --json
|
|
|
271
271
|
|
|
272
272
|
## What This Doesn't Do
|
|
273
273
|
|
|
274
|
+
- **Test-only diffs are not yet caught.** If a diff modifies or weakens assertions in a test file without changing the corresponding source file, DeployProof currently sees zero modified source lines and passes with 0 mutants evaluated. This is a known gap — see [INVESTIGATION_blastradius.md](INVESTIGATION_blastradius.md) for the reverse-mapping approach being evaluated to close it. Until this lands, DeployProof does not protect against test suites being weakened directly.
|
|
274
275
|
- **Not a full-repo audit.** Checks are scoped to files changed in the current session (git diff). Files you haven't touched are not re-evaluated.
|
|
275
276
|
- **Python only.** Mutation testing and import extraction currently support Python files only. Other languages are not scanned.
|
|
276
277
|
- **No auto-fix.** DeployProof reports findings; it does not modify your code, rewrite imports, or suggest patches.
|
|
@@ -288,7 +289,7 @@ Fixtures cover weak test suites, zero-test orphan modules, planted OpenAI/AWS cr
|
|
|
288
289
|
|
|
289
290
|
## Status & Roadmap
|
|
290
291
|
|
|
291
|
-
- **Current (v0.2.
|
|
292
|
+
- **Current (v0.2.2):** Diff-scoped AST mutation testing (with recursive `test/`/`tests/` discovery, AST column-offset snippet reconstruction, and `SIGINT`/`SIGTERM`/`SIGBREAK` signal-safe disk restoration), baseline test-collection failure isolation with distinct exit code `2`, entropy-driven value-based secrets scanner (including unquoted .env values and prefix validation), GhostApproval symlink sandbox-escape detector, PyPI dependency hallucination / slopsquatting scanner (with import-to-distribution translation, recursive `-r` requirements scanning, and dynamic import detection via `importlib` / `__import__`), mock-introduction detector (`--strict-mocks`), control-flow / swallowed-exception scanner (`--strict-error-handling`), 11/11 launch-day stress test suite, 94 unit tests, machine-readable `--json` output, and Tier 2 CI verification via GitHub Actions (mutmut).
|
|
292
293
|
- **Next:** Multi-language mutation support and expanded ecosystem rule packs.
|
|
293
294
|
|
|
294
295
|
## Contributing
|
|
@@ -9,7 +9,7 @@ from deployproof.cli import create_parser, main
|
|
|
9
9
|
|
|
10
10
|
def test_version():
|
|
11
11
|
"""Verify version string is accessible."""
|
|
12
|
-
assert __version__ == "0.2.
|
|
12
|
+
assert __version__ == "0.2.2"
|
|
13
13
|
|
|
14
14
|
|
|
15
15
|
def test_parser_version(capsys):
|
|
@@ -19,7 +19,7 @@ def test_parser_version(capsys):
|
|
|
19
19
|
parser.parse_args(["--version"])
|
|
20
20
|
assert exc_info.value.code == 0
|
|
21
21
|
captured = capsys.readouterr()
|
|
22
|
-
assert "deployproof 0.2.
|
|
22
|
+
assert "deployproof 0.2.2" in captured.out or "deployproof 0.2.2" in captured.err
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def test_parser_help(capsys):
|
|
@@ -105,7 +105,7 @@ def test_main_check_json_output_passing(capsys):
|
|
|
105
105
|
|
|
106
106
|
data = json.loads(captured.out)
|
|
107
107
|
assert data["status"] == "passed"
|
|
108
|
-
assert data["version"] == "0.2.
|
|
108
|
+
assert data["version"] == "0.2.2"
|
|
109
109
|
assert data["summary"]["mutation_score"] == 100.0
|
|
110
110
|
assert data["summary"]["secrets_found"] == 0
|
|
111
111
|
assert data["summary"]["symlink_escapes_found"] == 0
|
|
@@ -287,7 +287,7 @@ def test_real_subprocess_os_signal_interrupt_restoration():
|
|
|
287
287
|
import sys
|
|
288
288
|
import time
|
|
289
289
|
|
|
290
|
-
with tempfile.TemporaryDirectory() as tmpdir:
|
|
290
|
+
with tempfile.TemporaryDirectory(ignore_cleanup_errors=True) as tmpdir:
|
|
291
291
|
tmp_path = Path(tmpdir).resolve()
|
|
292
292
|
src_file = tmp_path / "calc.py"
|
|
293
293
|
orig_code = (
|
|
@@ -368,6 +368,44 @@ def test_real_subprocess_os_signal_interrupt_restoration():
|
|
|
368
368
|
|
|
369
369
|
# Target source file MUST be restored to original content immediately
|
|
370
370
|
assert src_file.read_text(encoding="utf-8") == mod_code
|
|
371
|
+
time.sleep(0.2)
|
|
372
|
+
|
|
373
|
+
|
|
374
|
+
def test_restore_removes_pyc_cache_file():
|
|
375
|
+
"""Verify that _restore_current_mutant_file unlinks the exact .pyc cache file without removing other cache files."""
|
|
376
|
+
import importlib.util
|
|
377
|
+
import py_compile
|
|
378
|
+
from deployproof import mutator
|
|
379
|
+
|
|
380
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
381
|
+
tmp_path = Path(tmpdir).resolve()
|
|
382
|
+
src1 = tmp_path / "module1.py"
|
|
383
|
+
src1.write_text("def func1(): return 1\n", encoding="utf-8")
|
|
384
|
+
src2 = tmp_path / "module2.py"
|
|
385
|
+
src2.write_text("def func2(): return 2\n", encoding="utf-8")
|
|
386
|
+
|
|
387
|
+
# Compile both to generate .pyc files in __pycache__
|
|
388
|
+
py_compile.compile(str(src1), doraise=True)
|
|
389
|
+
py_compile.compile(str(src2), doraise=True)
|
|
390
|
+
|
|
391
|
+
pyc1_path = Path(importlib.util.cache_from_source(str(src1)))
|
|
392
|
+
pyc2_path = Path(importlib.util.cache_from_source(str(src2)))
|
|
393
|
+
|
|
394
|
+
assert pyc1_path.is_file(), "pyc1 should exist before restoration"
|
|
395
|
+
assert pyc2_path.is_file(), "pyc2 should exist before restoration"
|
|
396
|
+
|
|
397
|
+
# Simulate active mutant tracking on src1
|
|
398
|
+
mutator._CURRENT_MUTATED_FILE = src1
|
|
399
|
+
mutator._CURRENT_ORIGINAL_CONTENT = "def func1(): return 100\n"
|
|
400
|
+
|
|
401
|
+
# Trigger restoration (as happens on interrupt / atexit)
|
|
402
|
+
mutator._restore_current_mutant_file()
|
|
403
|
+
|
|
404
|
+
# src1 should be restored and its specific .pyc removed
|
|
405
|
+
assert src1.read_text(encoding="utf-8") == "def func1(): return 100\n"
|
|
406
|
+
assert not pyc1_path.exists(), "src1's specific .pyc must be deleted"
|
|
407
|
+
assert pyc2_path.is_file(), "unrelated src2's .pyc must remain intact"
|
|
408
|
+
|
|
371
409
|
|
|
372
410
|
|
|
373
411
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|