Download backend/app/sandbox/python_runner.py from SevdanurGenc/LLM-Automated-Test-Generation-Agent: direct link, hf CLI and curl.
- Browser
- Download file 4.99 kB
-
https://huggingface.co/SevdanurGenc/LLM-Automated-Test-Generation-Agent/resolve/main/backend/app/sandbox/python_runner.py
- Command line
-
hf download hf://SevdanurGenc/LLM-Automated-Test-Generation-Agent/backend/app/sandbox/python_runner.py
-
curl -L -o python_runner.py https://huggingface.co/SevdanurGenc/LLM-Automated-Test-Generation-Agent/resolve/main/backend/app/sandbox/python_runner.py
4.99 kB
| """Python: pytest + pytest-cov (coverage.py).""" | |
| from __future__ import annotations | |
| import json | |
| import sys | |
| from pathlib import Path | |
| from typing import Optional | |
| from ..config import settings | |
| from ..models import RunResult, TestKind | |
| from .base import COMPILE_FAIL_RC, LanguageRunner, fill_counts, make_coverage, parse_junit_xml, truncate | |
| from .executor import ExecResult | |
| MODULE = "solution" | |
| class PythonRunner(LanguageRunner): | |
| language = "python" | |
| def image(self) -> str: | |
| return settings.docker_image_python | |
| def _py(self) -> str: | |
| return sys.executable if self.ex.mode == "local" else "python" | |
| def source_filename(self, code: str) -> str: | |
| return f"{MODULE}.py" | |
| def own_files(self) -> set[str]: | |
| return {"conftest.py", "pytest.ini", "setup.cfg", "tox.ini", "pyproject.toml"} | |
| def alias(self, source_name: str): | |
| stem = Path(source_name).stem | |
| # test_*.py / *_test.py adlı bir takma ad pytest tarafından test dosyası diye toplanırdı | |
| if not stem.isidentifier() or stem == MODULE or stem.startswith("test_") or stem.endswith("_test"): | |
| return None | |
| return f"{stem}.py", f"# {source_name} -> solution.py (çok dosyalı girdi)\nfrom {MODULE} import * # noqa\n" | |
| def test_filename(self, code: str, kind: TestKind) -> str: | |
| return "test_interface.py" if kind == "interface" else f"test_{MODULE}.py" | |
| def framework_hint(self, code: str, kind: TestKind) -> str: | |
| base = ( | |
| "Framework: pytest (Python 3.12). The code under test is saved as `solution.py` in the same " | |
| "directory as the test file. Import it with `from solution import ...` or `import solution`. " | |
| "Use plain `assert`, `with pytest.raises(SomeError):` in a dedicated test, and `pytest.approx` for floats. " | |
| "Prefer separate test functions over `pytest.mark.parametrize`; never use `isinstance(x, pytest.raises)`. " | |
| "Do not use network, sleep or external files. `unittest.mock` is available." | |
| ) | |
| if kind == "interface": | |
| base += ( | |
| " These are INTERFACE / CONTRACT tests: verify the public API surface (function and class " | |
| "signatures via `inspect`, return types, raised exception types, documented invariants) and " | |
| "how public units work together end-to-end. Do not test private helpers (names starting with `_`)." | |
| ) | |
| return base | |
| def write_files(self, wd: Path, code: str, test_code: str, kind: TestKind, html: Optional[str]) -> None: | |
| (wd / self.source_filename(code)).write_text(code, encoding="utf-8") | |
| (wd / self.test_filename(code, kind)).write_text(test_code, encoding="utf-8") | |
| (wd / "conftest.py").write_text("import sys, os\nsys.path.insert(0, os.path.dirname(__file__))\n") | |
| def command(self, wd: Path, code: str, test_code: str, kind: TestKind, with_coverage: bool) -> str: | |
| py = self._py() | |
| tf = self.test_filename(code, kind) | |
| cov = f"--cov={MODULE} --cov-report=json:.lta/cov.json --cov-report=" if with_coverage else "-p no:cov" | |
| return ( | |
| "mkdir -p .lta && " | |
| f"( {py} -m py_compile {MODULE}.py {tf} > .lta/compile.log 2>&1 || " | |
| f"{{ echo __LTA_COMPILE_FAILED__; cat .lta/compile.log; exit {COMPILE_FAIL_RC}; }} ) && " | |
| f"{py} -m pytest -q -p no:cacheprovider --tb=short --no-header -rN " | |
| f"--junitxml=.lta/junit.xml {cov} {tf}" | |
| ) | |
| def parse(self, wd: Path, res: ExecResult, code: str, kind: TestKind) -> RunResult: | |
| cases = parse_junit_xml([wd / ".lta" / "junit.xml"]) | |
| # Toplama (collection) hatası: test dosyası import edilemedi -> derleme hatası gibi ele al | |
| if not cases and res.returncode not in (0, 5): | |
| return RunResult(compiled=False, compile_output=truncate(res.combined), output=truncate(res.combined)) | |
| # Test dosyası import edilemediyse pytest bunu "collection failure" olarak raporlar | |
| coll = [c for c in cases if c.status == "error" and "collection failure" in c.message] | |
| if coll: | |
| msg = "\n".join(c.message for c in coll) | |
| return RunResult(compiled=False, compile_output=truncate(msg), output=truncate(res.combined)) | |
| # pytest junit isimleri: "test_solution::test_x" -> sadeleştir | |
| for c in cases: | |
| c.name = c.name.split("::")[-1] if "::" in c.name else c.name | |
| result = fill_counts(RunResult(cases=cases, output=truncate(res.combined))) | |
| cov_file = wd / ".lta" / "cov.json" | |
| if cov_file.exists(): | |
| data = json.loads(cov_file.read_text()) | |
| for fname, info in data.get("files", {}).items(): | |
| if Path(fname).name == f"{MODULE}.py": | |
| result.coverage = make_coverage(set(info.get("executed_lines", [])), | |
| set(info.get("missing_lines", []))) | |
| return result | |