Releases: ArtVsMark/Stepik-Python-Grader
Release list
v1.9.0
What's Changed
- chore(release): prepare v1.8.0 (#358) by @ArtVsMark in #361
- docs(plan): план оптимизации — глоссарий (832 драфта) + web-UX по пунктам а–к (эпики #362/#363) by @ArtVsMark in #372
- docs(changelog): ротация старых версий в архив + политика краткости (#373) by @ArtVsMark in #374
- feat(history): core/history.py — opt-in SQLite-история прогонов (#344) by @ArtVsMark in #375
- feat(rules,lint): пакет rules/ + core/lint.py — правила PEP 8 и ruff-проверка (#345, #346) by @ArtVsMark in #376
- feat(insights): core/insights.py — таксономия падений + затухание карточек «Подучить» (#347) by @ArtVsMark in #377
- feat(cli): stepik-grader --insights + флаг --lint — карточки «Подучить» и стиль в терминале (#349) by @ArtVsMark in #378
- feat(web): API разделов «Правила»/«Подучить» — /api/rules, /api/insights (часть #348) by @ArtVsMark in #379
- feat(web): UI разделов «Правила»/«Подучить» + единый hash-роутер by @ArtVsMark in #380
- feat(web): UX-оптимизация раздела «Проверка решений» (эпик #362, пункты а–к) by @ArtVsMark in #387
- docs: аудит Markdown-документации после v1.8.0 — устранение дрейфа (эпик #381) by @ArtVsMark in #389
- feat(glossary): двуязычные карточки — i18n {ru,en} поверх ?lang= (#363) by @ArtVsMark in #388
- feat(glossary): волна В1 «Строки (str)» — гранулярный двуязычный глоссарий (#371) by @ArtVsMark in #390
- docs(audit): полный аудит 253 issue (2026-07-15) + эпик #413 для хвостов by @ArtVsMark in #414
- docs(audit): глубокий аудит v1.8.0 — 8 ролей, эпик + 18 issue by @ArtVsMark in #391
- docs(audit): мультиролевой аудит 2026-07-15 — факт-чекинг v1.8.0 + backlog из 7 эпиков by @ArtVsMark in #415
- docs(roles): встроить шаблон 13 ролей без раздувания CLAUDE.md by @ArtVsMark in #446
- docs(handoff): план работ по открытым issue в claude-handoff.md by @ArtVsMark in #447
- fix: Волна 1 — стоп-краш/хэнг (runner, history, web, cli, downloader) by @ArtVsMark in #448
- docs(handoff): отметить Волну 1 плана выполненной by @ArtVsMark in #449
- fix(web): Волна 2 (1/2) — независимые security-дыры (CSRF, oauth 0600, confine root) by @ArtVsMark in #450
- feat(web): Волна 2 (2/2) — sandbox во всех путях исполнения web + usrmerge-фикс backend by @ArtVsMark in #451
- test(sandbox): полная Linux-песочница в CI через privileged-контейнер + фикс биндинга /usr (#420) by @ArtVsMark in #452
- docs: синхронизировать контракт с кодом — sandbox в web (#396) и Волна 2 by @ArtVsMark in #453
- ci: покрыть Windows + Python 3.14 в матрице (#454) by @ArtVsMark in #456
- refactor(core): Волна 3 (1/3) — ранжирование в core + единый вердикт + stdin в кейсах (#397) by @ArtVsMark in #455
- feat(web): Волна 3 (2/3) — наполнить «Подучить» (web→история #395 + lint→история #403) by @ArtVsMark in #457
- feat(insights): Волна 3 (3/3) — TTFG + экспорт прогресса + подсветка правил (#431, #432, #403) by @ArtVsMark in #458
- ci: покрыть macOS + Python 3.14 в матрице (#456) by @ArtVsMark in #459
- feat(cli): цикл меню, пункт «Веб-интерфейс» и тумблер истории (#445, #430) by @ArtVsMark in #460
- feat(oauth): guided secrets wizard (#433) + браузерный OAuth в --serve (#402) by @ArtVsMark in #461
- feat(glossary): ready-only по умолчанию (#436) + docs: English quick-start (#437) by @ArtVsMark in #462
- fix(web): контраст тёмной темы до WCAG AA (#424) + .hint/a11y/reporter (#409) by @ArtVsMark in #463
- feat(stepik): импорт закреплённого решения Stepik как reference (#55, PR1 core+CLI) by @ArtVsMark in #464
- feat(web): тёмная подсветка синтаксиса CodeMirror на дизайн-токенах (#425) by @ArtVsMark in #465
- feat(web): импорт reference Stepik по кнопке в разделе проверки (#55, PR2) by @ArtVsMark in #466
- fix(pre-commit): поднять ruff v0.11.13 → v0.15.21 и убрать --unsafe-fixes by @ArtVsMark in #467
- docs(adr): ADR-0003 — стратегия AI-интеграции BYOK OpenAI-compatible (#434) by @ArtVsMark in #468
- feat(web): back-pressure для POST /api/v1/runs — лимит активных job + 429 (#429) by @ArtVsMark in #469
- feat(ai): --ai-hints — opt-in AI-объяснение WA/RE через OpenAI-compatible endpoint (#435) by @ArtVsMark in #470
- refactor(core): retire executor.py duplicate + decompose run_single_test (#406) by @ArtVsMark in #471
- feat(web): задачные названия режимов + единый реестр разделов (#428) by @ArtVsMark in #472
- refactor(web): разбить app.js на ES-модули + static-allowlist сканом (#426) by @ArtVsMark in #473
- refactor(web): таблица маршрутов в server.py вместо do_GET/do_POST if/elif (#427) by @ArtVsMark in #474
- refactor(typing): mypy strictness, CaseResult TypedDict, Path signatures (#441, #442, #407) by @ArtVsMark in #475
- fix(web): TTL job'ов от завершения + атомарная запись JSON (#408) by @ArtVsMark in #476
- chore(lint): расширить ruff-select (PTH/SIM105/SIM115/RUF022/RUF100/D1) и устранить нарушения (#443) by @ArtVsMark in #477
- perf(glossary): кеш производных индексов/терминов + единый retry; property-тесты (#404, #405) by @ArtVsMark in #478
- fix: хвосты аудита 2026-07-15 — прогрев микробенча (#412) + докфиксы ADR/trace-format (#411) by @ArtVsMark in #479
- docs: устранить дрейф метрик и числа карточек глоссария (#398) by @ArtVsMark in #480
- test(web): контрактный тест «docs/api.md ↔ маршруты server.py» (#439) by @ArtVsMark in #481
- fix(core): dotted-float/testblock parsing + traceback redaction (#410) by @ArtVsMark in #482
- docs(adr): record setuptools-scm, src-layout, Runner, sandbox decisions (#410) by @ArtVsMark in #483
- docs(server): дизайн-подготовка server mode — sandbox backend + data model (#153, #154, #155) by @ArtVsMark in #484
- feat(scripts): полуавтоматический B1-конвейер черновиков глоссария (#438) by @ArtVsMark in #485
- feat(glossary): волна В1 «Числа» — 13 методов int/float/complex до ready (#363) by @ArtVsMark in #486
- feat(glossary): волна В1 «Списки» — 11 методов list до ready (#363) by @ArtVsMark in #487
- feat(glossary): волна В1 «Словари» — 10 методов dict до ready (#363) by @ArtVsMark in #488
- feat(glossary): волна В1 «Множества» — 25 методов set/frozenset до ready (#363) by @ArtVsMark in #489
- feat(glossary): волна В1 «Кортежи» — 2 метода tuple до ready (#363) by @ArtVsMark in #490
- feat(glossary): завершить В1 builtins + начать В2 «Исключения» (#363) by @ArtVsMark in #492
- feat(glossary): В2 модульные исключения — 35 stdlib-исключений до ready (#363) by @ArtVsMark in #493
- feat(glossary): В3 «Учебные модули» батч 1 — json/functools/itertools (#363) by @ArtVsMark in #494
- feat(glossary): В3 «Учебные модули» батч 2 — datetime/statistics (#363) by @ArtVsMark in #509
- docs: устранить вводящие в заблуждение...
v1.8.0
What's Changed
- chore(release): prepare v1.7.0 by @ArtVsMark in #292
- fix(core/web): статус "NO TESTS" вместо FAIL 0/0 для пустой tests/ by @ArtVsMark in #305
- docs: changelog-archive.md в индекс docs/ + guardrail полноты индекса by @ArtVsMark in #306
- docs(sandbox): привести докстринг core/sandbox/init.py в соответствие с реализацией (nsjail) by @ArtVsMark in #307
- ci: укрепить запас покрытия — платформо-специфичные sandbox-бэкенды vs fail_under=85 by @ArtVsMark in #308
- docs(installation): троублшутинг для ModuleNotFoundError из-за протухшего global editable-install by @ArtVsMark in #309
- fix(core): убрать pid из текста warning'а о ненадёжном замере памяти — схлопнуть шум by @ArtVsMark in #310
- refactor(frontend): собрать vendored CodeMirror в единый бандл без unenv node-шимов by @ArtVsMark in #311
- feat(web): отдельный статус "cancelled" в /api/v1/runs — решить до заморозки контракта by @ArtVsMark in #312
- feat(web): режим 1 через POST /api/v1/runs с кодом в теле — закрыть гонку save→grade by @ArtVsMark in #313
- fix(a11y): aria-live для вердиктов, доступность прогресс-бара и результатов by @ArtVsMark in #332
- feat(web): подсказка при не-UTF-8 байтах в выводе решения by @ArtVsMark in #333
- refactor: SRP-разбиение downloader.py (32 КБ) by @ArtVsMark in #335
- feat(glossary): контент-эпик #316 — карточки, база 581+832, фильтры/deep-link, методы+coverage 100% by @ArtVsMark in #334
- feat(web): эпик #314 «Песочница» — MVP + трассировщик + плеер + диаграмма + глоссарий (#317–#321) by @ArtVsMark in #336
- feat(web): эпик #315 «Функции в коде» — панель в режимах 1/2 + /api/code-terms (#322/#323/#324) by @ArtVsMark in #337
- fix(web): аудит-мелочи — дрейф документации (#330) + бейджи/aria (#331) by @ArtVsMark in #338
- perf(web): кешировать распарсенный глоссарий по mtime (#339) by @ArtVsMark in #340
- feat(logging): эпик #146 — opt-in диагностическое логирование сети/OAuth с редакцией секретов by @ArtVsMark in #341
- docs(audit): глубокий мультиролевой аудит 2026-07 + дизайн разделов «Правила/PEP» и «Подучить» by @ArtVsMark in #359
- chore(hygiene): audit 2026-07 cleanup — #350–#357 (epic #343) by @ArtVsMark in #360
Full Changelog: v1.7.0...v1.8.0
v1.7.0
What's Changed
- docs: formalize architecture contracts and server-mode direction by @ArtVsMark in #216
- ci(docs): add README and Markdown guardrails by @ArtVsMark in #217
- docs: clarify sandbox limits and sync v1.6 docs by @ArtVsMark in #218
- fix(web): harden client-side escaping for href/action-card attributes by @ArtVsMark in #219
- fix(glossary): reduce false positives in exception-name detector by @ArtVsMark in #220
- feat(core): TestResult dataclass + Verdict Literal (epic #112) by @ArtVsMark in #221
- feat(client): Retry/HTTPAdapter reliability for Stepik API (epic #108) by @ArtVsMark in #222
- feat(config): lazy CONFIG + dataclasses.fields + i18n locale foundation (epic #141) by @ArtVsMark in #223
- feat(runner): Runner Protocol + LocalRunner (epic #136) by @ArtVsMark in #224
- test(cli): characterization tests for entrypoint flags + facade contract by @ArtVsMark in #225
- refactor(cli): extract parsing/options helpers into cli/options.py by @ArtVsMark in #226
- refactor(cli): extract mode handlers into cli/commands.py with CliContext by @ArtVsMark in #227
- refactor(cli): extract table rendering into cli/rendering.py by @ArtVsMark in #228
- refactor(cli): extract interactive menu into cli/interactive.py with CliContext by @ArtVsMark in #229
- test(cli): add subprocess-level regression tests for entrypoints by @ArtVsMark in #230
- fix(version): exclude badge-bot commits from PATCH counter; require CHANGELOG entry per PR by @ArtVsMark in #232
- feat(web): реализовать рабочую область проверки решения (#125) by @ArtVsMark in #233
- feat(web): редизайн UI под маску эпика #123 + режим «Сравнение» by @ArtVsMark in #234
- fix(web): исправить режимы 1/2 по фидбеку в #125 by @ArtVsMark in #235
- feat(web): Downloader workflow — раздел «Загрузчик задач» (#186) by @ArtVsMark in #236
- feat(web): Microbench (режим 4) в веб-интерфейсе (issue #187) by @ArtVsMark in #237
- test(web): cross-adapter user-journey tests, closes epic #123 (issue #129) by @ArtVsMark in #238
- feat(web): editable code window for mode 1 (issue #125) by @ArtVsMark in #239
- fix(docs): sync architecture.md DAG with web/ package structure (issue #247) by @ArtVsMark in #249
- fix(docs): update CLAUDE.md metrics and stale issue references (issue #248) by @ArtVsMark in #250
- fix(downloader): stop leaking Stepik OAuth token to third-party hosts by @ArtVsMark in #251
- fix(oauth): add state to OAuth callback flow to prevent Login-CSRF by @ArtVsMark in #252
- fix(web): validate Host/Origin for localhost API to block CSRF/DNS-rebinding by @ArtVsMark in #253
- fix(storage): restrict secrets.json permissions to owner-only on POSIX by @ArtVsMark in #254
- fix(wrapper): import stdlib before sys.path.insert in function wrapper by @ArtVsMark in #255
- fix(executor): safely parse EXECUTOR_TIMEOUT from env by @ArtVsMark in #256
- fix(test-loader): warn on input/output block count mismatch by @ArtVsMark in #257
- fix(config): resolve pyproject.toml from cwd instead of package file (#258) by @ArtVsMark in #269
- fix(web): API input limits + vendor fonts locally (#259, #260) by @ArtVsMark in #271
- feat(web): workspace root confinement for --serve (#261) by @ArtVsMark in #272
- test(web): Playwright e2e smoke tests + XSS regression (issue #263) by @ArtVsMark in #273
- refactor(i18n): message_id catalog for web API responses (issue #264) by @ArtVsMark in #274
- chore(ci): retry badge-update push on concurrent-merge race by @ArtVsMark in #275
- docs(versions): add web UI + IDE integration rows to fork-vs-original table by @ArtVsMark in #276
- feat(web): async job model for bench/microbench (issue #262) by @ArtVsMark in #277
- feat(web): CodeMirror 6 editor for mode 1 (issue #265) by @ArtVsMark in #278
- docs(installation): troubleshooting note for pytest env issues (issue #270) by @ArtVsMark in #279
- feat(cli): opt-in local run statistics (issue #268) by @ArtVsMark in #280
- feat(sandbox): cross-platform SandboxRunner MVP (--sandbox, issue #266) by @ArtVsMark in #281
- refactor(api): use Path instead of str in public contracts by @ArtVsMark in #282
- chore(ci): combine coverage across OS matrix, add second badge by @ArtVsMark in #284
- docs: add HTTP API reference, split web-mvp.md, archive old changelog by @ArtVsMark in #285
- fix(ci): commit new badge files by staging before the diff check by @ArtVsMark in #287
- docs: pre-release accuracy audit ahead of v1.7.0 by @ArtVsMark in #288
- fix(ci): give the two coverage badges distinct labels by @ArtVsMark in #290
- chore(readme): cache-bust badge endpoints with cacheSeconds=300 by @ArtVsMark in #291
Full Changelog: v1.6.0...v1.7.0
v1.6.0
What's Changed
- feat(glossary): link RE verdicts to Glossary-Python (#72, epic #96) by @ArtVsMark in #158
- chore(packaging): MIT LICENSE + py.typed (PR-1, #98/#100/#101) by @ArtVsMark in #159
- docs: split README into docs/ knowledge base (PR-2, #102) by @ArtVsMark in #160
- docs: split README into focused documentation by @ArtVsMark in #179
- docs: add configuration reference by @ArtVsMark in #180
- docs: specify web MVP UX and local UI architecture by @ArtVsMark in #181
- docs: remove stale release plan and trim contributing guide by @ArtVsMark in #182
- chore: derive package version from git tags by @ArtVsMark in #183
- docs: clarify versioning policy and prepare Claude handoff by @ArtVsMark in #184
- docs: clarify web MVP downloader, microbench, and glossary scope by @ArtVsMark in #185
- docs: fix microbench entrypoint references by @ArtVsMark in #188
- feat: add JSON glossary provider foundation by @ArtVsMark in #189
- docs: clean up markdown drift after glossary foundation by @ArtVsMark in #192
- docs: add glossary source-of-truth and security policy by @ArtVsMark in #203
- docs: sync changelog and Claude handoff before glossary work by @ArtVsMark in #205
- refactor(glossary): add origin/module/qualname to GlossaryMissingEntry by @ArtVsMark in #206
- feat(glossary): stdlib inventory scanner for official Python coverage by @ArtVsMark in #207
- feat(glossary): coverage report and missing JSON generator by @ArtVsMark in #208
- feat(glossary): CLI entrypoint for coverage scan by @ArtVsMark in #209
- feat(version): distinguish dev vs release in --version by @ArtVsMark in #210
- feat(ci): auto-update README coverage badge by @ArtVsMark in #211
- feat(ci): live current-version badge alongside Release by @ArtVsMark in #212
Full Changelog: v1.5.0...v1.6.0
v1.5.0
What's Changed
- Audit backlog cleanup: prlimit memory cap (#67) + remove unwired code (#69) by @ArtVsMark in #90
- feat(cache): opt-in result caching to skip unchanged solutions (#56) by @ArtVsMark in #91
- feat(pytest): run grader as a pytest plugin via --grader-mode (#57) by @ArtVsMark in #92
- feat(watch): incremental --mode 2 re-run via the #56 cache (#71) by @ArtVsMark in #93
- fix(ide): launch tasks via the editor interpreter + version consistency audit by @ArtVsMark in #94
- chore(release): prepare v1.5.0 by @ArtVsMark in #95
Full Changelog: v1.4.0...v1.5.0
v1.4.0
What's Changed
- docs(readme): PyPI install is live — pipx install stepik-python-grader (#70) by @ArtVsMark in #85
- feat(web): local web UI — stepik-grader --serve (epic #80 Tier 1, #58) by @ArtVsMark in #86
- feat(web): polish Web UI — benchmark mode, default path, localStorage, summary by @ArtVsMark in #87
- feat(ide): IDE integration — stepik-grader --init-vscode + PyCharm docs (Tier 2, #58) by @ArtVsMark in #88
- chore(release): prepare v1.4.0 — version bump + docs sync by @ArtVsMark in #89
Full Changelog: v1.3.0...v1.4.0
What's Changed
- docs(readme): PyPI install is live — pipx install stepik-python-grader (#70) by @ArtVsMark in #85
- feat(web): local web UI — stepik-grader --serve (epic #80 Tier 1, #58) by @ArtVsMark in #86
- feat(web): polish Web UI — benchmark mode, default path, localStorage, summary by @ArtVsMark in #87
- feat(ide): IDE integration — stepik-grader --init-vscode + PyCharm docs (Tier 2, #58) by @ArtVsMark in #88
- chore(release): prepare v1.4.0 — version bump + docs sync by @ArtVsMark in #89
Full Changelog: v1.3.0...v1.4.0
v1.3.0
What's Changed
- Onboarding UX: beginner-proof README + native file-dialog fallback (#79) by @ArtVsMark in #77
- docs/housekeeping: version-evolution comparison + fix stale root_dir in config example by @ArtVsMark in #81
- ci(release): PyPI trusted-publishing job (#70) — pivot from standalone .exe (#78) by @ArtVsMark in #82
- chore(release): prepare v1.3.0 — version bump + docs sync by @ArtVsMark in #84
Full Changelog: v1.2.0...v1.3.0
v1.2.0
What's Changed
- Audit v1.1.0 epic: Sprints A-E, #45 A-01, roadmap #53/#54/#58 by @ArtVsMark in #63
- Release v1.2.0 — UTF-8 stdio, python -m entry point, mode-4 Py-heap column, versioning docs by @ArtVsMark in #76
Full Changelog: v1.1.0...v1.2.0
Stepik Python Grader v1.1.0 — Sprint 6–8
What's Changed
- refactor: core/ restructuring, dedup, grader.py split, Sprints 6–8.1 by @ArtVsMark in #22
- Add claude GitHub actions 1783010684945 by @ArtVsMark in #40
- release: v1.1.0 — Sprint 6–8 backlog, src-layout, docs sync by @ArtVsMark in #41
- docs(claude): update Glossary-Python status (closes #38) by @ArtVsMark in #42
Full Changelog: v1.0.0...v1.1.0
Stepik Python Grader v1.0.0 — Stable Release
🚀 Stepik Python Grader v1.0.0 — Stable Release
Первый стабильный релиз. Полный рефакторинг с нуля: переименование модулей, OAuth-фасад, rich-вывод, 260 тестов, CI на Python 3.11–3.14.
Локальный грейдер для курсов «Поколение Python» на Stepik: скачивает данные задачи с сайта и позволяет не только проверить решение локально, но и сравнить несколько решений более честно — сначала по корректности, затем по benchmark-метрикам.
✨ Ключевые возможности
- 4 режима работы: одиночный тест / все тесты в папке / subprocess-бенчмарк / timeit-микробенчмарк
- Вердикты AC / WA / TLE / RE с подсветкой через
rich - OAuth 2.0 авторизация для скачивания тестов со Stepik (browser-flow + refresh-токены)
- Автоизвлечение тест-кейсов из HTML-таблицы и ZIP-архивов в тексте задачи
- Поддержка 3 репозиториев с тестами
python-generation: Professional, OOP, Samurai - Прогресс-бары и цветные таблицы результатов, diff при WA
- Профили нагрузки (low / medium / high / custom) и оценка по median, а не по одиночному замеру
🏗️ Архитектура
Слоистая структура, граф зависимостей — DAG без циклов:
- Domain / Application —
downloader.py,grader.py,diagnostik_stepik.py - Infrastructure —
stepik_client.py(OAuth2 + HTTP),executor.py(compile + exec с таймаутом),microbench_runner.py(timeit через subprocess),oauth_flow.py(OAuth-фасад) - Infrastructure / Utilities (leaf, без project-зависимостей) —
storage.py(JSON I/O),normalizers.py(нормализация вывода)
oauth_flow.py — единая точка входа для авторизации, устраняет дублирование load_secrets между downloader.py и diagnostik_stepik.py. Ребро downloader.py → grader.py сделано локальным импортом внутри функции, чтобы не нарушать слоистость и избежать циклов.
🔧 Что изменилось (основные изменения)
Рефакторинг
- Переименование модулей:
at_first.py → downloader.py,test.py → grader.py(полная замена, 16 файлов) - Создан
oauth_flow.py— unified OAuth facade, устранено дублированиеload_secrets grader.pyимпортируетrun_microbenchизmicrobench_runner.pyи_normalize_output_lineизnormalizers.py- Удалены мёртвые функции, убран
chardet,StepikTasks/добавлен в.gitignore
Тесты
- 260 тестов (pytest, 0 failures)
- OAuth safety net:
load_secrets,token_is_valid,wait_for_auth_code,OAuthHandler - Покрытие
oauth_flow.pyдоведено до 100% - 45+ тестов для
run_microbench,normalizers,_is_python_code_block,load_test_cases
CI/CD
- GitHub Actions workflow:
pytest+ruffна Python 3.11 / 3.12 / 3.13 / 3.14 (3.14 — experimental) - Консолидация workflow'ов: удалены дублирующие
lint.ymlиtest.yml, остался единыйci.yml - Bump
ruffдо 0.15.19
Документация
- Полный README: дерево файлов, DAG зависимостей, таблица модулей, режимы работы, конфигурация
- CHANGELOG, бейджи (CI, version, coverage, Python)
- Строгий README review — 11 исправлений; Issue #1 closed
Исправления
grader.py: fallback-стабы дляConsole/Table/Text, инициализацияmem_thread, удаление неиспользуемых переменных- Режимы меню 2/3/4: per-solution
test_dir,run_benchmark, function-mode для микробенчмарка - Audit fixes для rich-вывода и вердиктов
📊 Статистика
- Тестов: 260 (pytest, 0 failures)
- Python: 3.11 | 3.12 | 3.13 | 3.14
- Линтер: ruff (профиль E, F, W, I, UP, B, S102) — clean
- Coverage: 59%
🚀 Быстрый старт
git clone https://github.com/ArtVsMark/Stepik-Python-Grader.git
cd Stepik-Python-Grader
# Виртуальное окружение
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# Зависимости
pip install -r requirements.txt # для разработки: pip install -e ".[dev]"
# Запуск грейдера
python grader.pyПри запуске появится меню с выбором режима [0–4]. Для скачивания данных задачи со Stepik настройте OAuth-приложение и secrets.json, затем запустите python downloader.py (подробности — в README).