-
Notifications
You must be signed in to change notification settings - Fork 1
Comparing changes
Open a pull request
base repository: ArtVsMark/Stepik-Python-Grader
base: v1.4.0
head repository: ArtVsMark/Stepik-Python-Grader
compare: v1.5.0
- 6 commits
- 20 files changed
- 2 contributors
Commits on Jul 5, 2026
-
refactor(memory): prlimit after spawn + remove unwired timeout helper (…
…#67, #69) * fix(core): apply memory cap via resource.prlimit after spawn, not preexec_fn (#67) preexec_fn форкает в многопоточном родителе (грейдер держит psutil-поток мониторинга памяти) — документированно небезопасно. Ставим RLIMIT_AS через resource.prlimit на pid дочернего процесса ПОСЛЕ spawn, без fork в родителе. - _make_memory_limiter() (preexec_fn-фабрика) → _apply_memory_limit(pid, mb) в core/grader_core.py и core/microbench_runner.py (дубль, тот же DAG-довод). - run_single_test: prlimit(proc.pid) после Popen (preexec_fn убран). - run_microbench: subprocess.run → Popen + communicate(timeout=60), чтобы получить pid для prlimit; таймаут/OSError-ветки сохранены. - Linux-only: prlimit отсутствует на macOS (AttributeError → no-op), нет resource на Windows — cap всё равно best-effort (#43 S-01), thread-safety важнее. Окно «ребёнок без лимита» ~мс до exec пользовательского кода. Тесты: _make_memory_limiter-тесты (×4 в двух файлах) переписаны под _apply_memory_limit (prlimit-моки, AttributeError-ветка macOS); mock subprocess.run → Popen в timeout/OSError тестах microbench. 624 зелёных, ruff/mypy чисто, E2E режимы 3/4 работают. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VcThPLNgaqaBbEDouT5THj * chore(core): remove unwired run_microbench_with_timeout() (#69) Вердикт по «музейному экспонату»: Remove. Функция жила два релизных цикла без единого production-вызова; её собственный докстринг признавал, что защиты она не даёт (ThreadPoolExecutor-обёртка поверх уже subprocess.run(timeout=60)-защищённого вызова), а при реальном таймауте оставляет orphan-поток. Мёртвый код, вводящий в заблуждение — история в git. Убраны заодно: import concurrent.futures и Callable (больше нигде не нужны в microbench_runner.py), два теста в test_microbench_runner_module.py и import time (использовался только ими). Заметки в CLAUDE.md/CHANGELOG. 622 теста зелёные, ruff/mypy чисто. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VcThPLNgaqaBbEDouT5THj --------- Co-authored-by: Claude <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for 50baaa6 - Browse repository at this point
Copy the full SHA 50baaa6View commit details -
feat(cache): opt-in result caching to skip unchanged solutions (#56)
Add a new leaf module core/cache.py (stdlib hashlib + core/storage.py JSON I/O only) that caches --mode 1/2 correctness verdicts keyed by sha256(solution content) + sha256(all test-dir files). A solution is skipped and its previous verdict reused until either hash changes. - --cache / --no-cache (argparse.BooleanOptionalAction, default from GraderConfig.use_cache / [tool.stepik-grader] use_cache) - --clear-cache deletes .grader_cache/ and reports removed entry count - cache stored in .grader_cache/results.json (CWD), added to .gitignore - corrupt/version-mismatched cache file degrades to empty, never crashes - mode 1 prints a cache-hit note; mode 2 prints an N-of-M summary - 15 tests (hashing stability/sensitivity, roundtrip, invalidation, corrupt-file handling, CLI integration) Docs: README --cache section, CHANGELOG, CLAUDE.md (structure/DAG/backlog). Claude-Session: https://claude.ai/code/session_01VcThPLNgaqaBbEDouT5THj Co-authored-by: Claude <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for 04140e8 - Browse repository at this point
Copy the full SHA 04140e8View commit details
Commits on Jul 6, 2026
-
feat(pytest): run grader as a pytest plugin via --grader-mode (#57)
Add pytest_plugin.py registered as a pytest11 entry point. With `pytest --grader-mode StepikTasks/`, pytest collects each solution file (task*.py) as a pytest.File and yields one pytest.Item per test case from its tests/ directory, running through the same run_single_test engine as CLI mode 1. A wrong answer is a normal FAILED with an "expected/actual" diff; a runtime error surfaces the exception text. - off by default (no-op unless --grader-mode or `grader_mode = true` ini), so it never interferes with a project's own test suite - core imports are lazy (inside hooks): pytest11 plugins load before coverage.py starts, so a module-level core import would mark the whole package's def-lines uncovered - pytest_plugin.py itself is omitted from coverage (its def/class headers execute at plugin-load before coverage; bodies are covered behaviorally) - 16 tests via the pytester fixture (enabled in conftest.py) Docs: README pytest-plugin section, CHANGELOG, CLAUDE.md (structure/DAG/backlog). Claude-Session: https://claude.ai/code/session_01VcThPLNgaqaBbEDouT5THj Co-authored-by: Claude <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for cdae390 - Browse repository at this point
Copy the full SHA cdae390View commit details -
feat(watch): incremental --mode 2 re-run via the #56 cache (#71)
Under --watch, --mode 2 now auto-enables the result cache (issue #56), so a file-change event only re-runs the changed solution — the other rows are served from cache instead of re-running the whole folder. On a folder with a dozen tasks the feedback loop no longer degrades. Reuses #56's disk cache (the existing load-on-create + save-at-end plumbing persists state across watch iterations) rather than a separate in-memory solution, as the issue proposed. - --cache default changed from CONFIG.use_cache to None so an explicit --cache/--no-cache is distinguishable from "unset" and always wins - new _resolve_use_cache helper: explicit flag → watch-incremental default → [tool.stepik-grader] use_cache - --mode 1 (single file) does NOT auto-enable cache under --watch - --no-cache opts out (restores the old full-folder rerun) - 7 tests (resolution matrix + main() wiring for mode 1/2 watch) Docs: README --watch section, CHANGELOG, CLAUDE.md backlog #71. Claude-Session: https://claude.ai/code/session_01VcThPLNgaqaBbEDouT5THj Co-authored-by: Claude <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for a4f6358 - Browse repository at this point
Copy the full SHA a4f6358View commit details -
fix(ide): launch tasks via the editor interpreter + version consisten…
…cy audit The generated VS Code tasks and the README PyCharm recipe invoked the bare `stepik-grader` console script, which is only on PATH when the venv is activated — the most likely reason the beginner IDE integration "wouldn't launch". Both now run through the interpreter selected in the IDE, so no manual venv activation is needed. - VS Code (--init-vscode): command → ${command:python.interpreterPath}, type → process (robust to interpreter paths with spaces), args prefixed with -m stepik_grader.grader - README PyCharm External Tool: Program → $PyInterpreterDirectory$/python, Arguments → -m stepik_grader.grader ... - test_ide.py updated for the new command/args/type Docs: also audited version consistency across README/CLAUDE.md (fixed a stale `# 1.2.0` --version example → 1.4.0; refreshed the metrics table test count 622 → 660) and added a pre-merge rule to CLAUDE.md's checklist: always verify the version is consistent across the whole project before merging. Claude-Session: https://claude.ai/code/session_01VcThPLNgaqaBbEDouT5THj Co-authored-by: Claude <noreply@anthropic.com>Configuration menu - View commit details
-
Copy full SHA for d504b61 - Browse repository at this point
Copy the full SHA d504b61View commit details -
chore(release): prepare v1.5.0
- pyproject version 1.4.0 → 1.5.0 - CHANGELOG: consolidate [Unreleased] into [1.5.0] (2026-07-06) with a concise summary + collapsible full details; batch = #56 cache, #57 pytest plugin, #71 incremental watch, IDE launch fix, and post-v1.4.0 cleanup (#67/#69) - README: version badge, Status, --version example → 1.5.0; new v1.5.0 column in the release-comparison table (660 / 95%) - CLAUDE.md: metrics table → v1.5.0 (stable), 660 tests - version consistent across pyproject/README/CLAUDE.md (pre-merge rule) Claude-Session: https://claude.ai/code/session_01VcThPLNgaqaBbEDouT5THj Co-authored-by: Claude <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for 5941b5f - Browse repository at this point
Copy the full SHA 5941b5fView commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff v1.4.0...v1.5.0