From c475cb5146ea41f332693e99c720729457e3444d Mon Sep 17 00:00:00 2001 From: Ryan Pope Date: Sat, 31 Oct 2026 01:35:55 -0500 Subject: [PATCH 1/2] build: judge with LeetCode's versions: Python 3.14 and Java 25 Runner: Python 3.14.10, Temurin JDK 25.0.5, Kotlin 2.4.21 (checksum matches JetBrains' published .sha256). The app, CI and local tooling move to Python 3.14 too, so there is one Python line; ruff now targets py314. --- .github/workflows/ci.yml | 2 +- CHANGELOG.md | 2 +- CONTRIBUTING.md | 2 +- Makefile | 2 +- README.md | 4 ++-- backend/Dockerfile | 2 +- backend/localcode/importer/dataset.py | 4 ++-- backend/localcode/judging/runner_client.py | 2 +- backend/pyproject.toml | 2 +- docs/architecture.md | 2 +- ruff.toml | 2 +- runner/Dockerfile | 10 +++++----- runner/server.py | 2 +- 13 files changed, 19 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 397dba2..e276205 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0 with: - python-version: "3.12" + python-version: "3.14" cache: pip cache-dependency-path: backend/pyproject.toml - run: pip install -e 'backend[dev]' diff --git a/CHANGELOG.md b/CHANGELOG.md index 230f6b7..f8f6936 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ All notable changes are documented here. The format follows [Keep a Changelog](h ### Added - First public version: about 4,100 problems (2,830 runnable against 274k hidden tests), company frequency lists for 423 companies, reference solutions with explanations. -- Judging in Python 3.12, Java 21, C++23 (Clang 19, as LeetCode uses) and Kotlin 2.0 in a sandboxed runner with no network access. +- Judging in Python 3.14 and Java 25 (the versions LeetCode judges with), C++23 with Clang 19 and Kotlin 2.4, in a sandboxed runner with no network access. - Problem list, company pages, workspace with Run/Submit and custom cases, submission history, progress dashboard and export. - One-command setup with Docker Compose; content imported from open datasets at first run, with mirror fallbacks. - Repo-kept content in `content/`: new problems and extra solutions, tests or corrections for existing ones, checked in CI by `make validate-content` and marked "local" in the app. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f71a85b..ad59702 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -10,7 +10,7 @@ Everyone taking part is expected to follow the [Code of Conduct](CODE_OF_CONDUCT ## Getting set up -You need Docker (with Compose v2), Python 3.12, Node 22 and `make`. +You need Docker (with Compose v2), Python 3.14, Node 22 and `make`. ```bash git clone https://github.com/RyPope/localcode.git && cd localcode diff --git a/Makefile b/Makefile index de835bb..0bbd250 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ logs: ## Follow app and runner logs docker compose logs -f setup: ## Install local dev dependencies (Python venv + web node_modules) - python3.12 -m venv backend/.venv + python3.14 -m venv backend/.venv $(PY)/pip install -e 'backend[dev]' npm --prefix web ci diff --git a/README.md b/README.md index f1bea81..b5ba4d7 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ About 4,100 problems · 2,830 judged against 274k hidden tests · company frequency lists for 423 companies · Python, Java, C++ and Kotlin [![License: MIT](https://img.shields.io/badge/license-MIT-86A3FF.svg)](LICENSE) -![Python 3.12](https://img.shields.io/badge/python-3.12-3776AB.svg) +![Python 3.14](https://img.shields.io/badge/python-3.14-3776AB.svg) ![React 18](https://img.shields.io/badge/react-18-61DAFB.svg) ![Docker Compose](https://img.shields.io/badge/docker-compose-2496ED.svg) [![PRs welcome](https://img.shields.io/badge/PRs-welcome-4FC48C.svg)](CONTRIBUTING.md) @@ -95,7 +95,7 @@ flowchart LR B["Browser
localhost:4173"] --> A subgraph Docker["Docker Compose"] A["app
FastAPI + React UI"] - R["runner
Python 3.12 · JDK 21 · Clang 19 · Kotlin 2.0
no network"] + R["runner
Python 3.14 · JDK 25 · Clang 19 · Kotlin 2.4
no network"] D[("localcode-data volume
content.db · user.db")] A -- "code + test inputs
(Unix socket)" --> R R -- "raw outputs" --> A diff --git a/backend/Dockerfile b/backend/Dockerfile index b670e70..c1d68e0 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -6,7 +6,7 @@ RUN npm ci --no-audit --no-fund COPY web/ ./ RUN npm run build -FROM python:3.12.15-slim-trixie +FROM python:3.14.10-slim-trixie RUN apt-get update && apt-get install -y --no-install-recommends git ca-certificates \ && rm -rf /var/lib/apt/lists/* \ && groupadd --gid 1000 localcode \ diff --git a/backend/localcode/importer/dataset.py b/backend/localcode/importer/dataset.py index cdccf2c..6932283 100644 --- a/backend/localcode/importer/dataset.py +++ b/backend/localcode/importer/dataset.py @@ -100,7 +100,7 @@ def parse_cases(test_src: str, params: list[dict], ret: str = "") -> list[dict]: names = [p["name"] for p in params] try: fn = ast.parse(test_src).body[0] - except (SyntaxError, IndexError): + except SyntaxError, IndexError: return [] cases = [] for st in getattr(fn, "body", []): @@ -131,7 +131,7 @@ def parse_cases(test_src: str, params: list[dict], ret: str = "") -> list[dict]: expected = [] json.dumps(expected) # must be JSON-representable cases.append({"args": args, "expected": expected}) - except (ValueError, TypeError, SyntaxError): + except ValueError, TypeError, SyntaxError: continue return cases diff --git a/backend/localcode/judging/runner_client.py b/backend/localcode/judging/runner_client.py index d648444..ab64d76 100644 --- a/backend/localcode/judging/runner_client.py +++ b/backend/localcode/judging/runner_client.py @@ -73,6 +73,6 @@ def versions() -> dict[str, str] | None: with _client(endpoint, 60) as client: _versions = client.get("/health").json()["versions"] break - except (httpx.HTTPError, KeyError, ValueError): + except httpx.HTTPError, KeyError, ValueError: continue return _versions diff --git a/backend/pyproject.toml b/backend/pyproject.toml index e169ca5..dab12e9 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "localcode" version = "0.1.0" -requires-python = ">=3.12" +requires-python = ">=3.14" dependencies = ["fastapi==0.162.0", "uvicorn==0.54.0", "httpx==0.28.1", "PyYAML==6.0.3", "markdown-it-py==4.2.0"] [project.optional-dependencies] diff --git a/docs/architecture.md b/docs/architecture.md index 01f8993..043f7ac 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -4,7 +4,7 @@ | Service | Image | Network | Responsibility | |---|---|---|---| -| `app` | `backend/Dockerfile` (Python 3.12 + built web UI) | default (for downloads); reaches the runner via `/run/localcode/runner-*.sock` | HTTP API, static UI, content import, judging, user data | +| `app` | `backend/Dockerfile` (Python 3.14 + built web UI) | default (for downloads); reaches the runner via `/run/localcode/runner-*.sock` | HTTP API, static UI, content import, judging, user data | | `runner` | `runner/Dockerfile` (pinned toolchains) | none (`network_mode: none`); serves on a Unix socket in the `runner-socket` volume | Compile and execute submissions; return raw per-case results | Data lives in the `localcode-data` volume mounted at `/data`: diff --git a/ruff.toml b/ruff.toml index 533f05a..a008eb8 100644 --- a/ruff.toml +++ b/ruff.toml @@ -1,5 +1,5 @@ line-length = 120 -target-version = "py312" +target-version = "py314" extend-exclude = ["web", "**/.venv"] [lint] diff --git a/runner/Dockerfile b/runner/Dockerfile index 5a33d6c..14bd41e 100644 --- a/runner/Dockerfile +++ b/runner/Dockerfile @@ -1,16 +1,16 @@ # Pinned toolchains: every localcode user judges against exactly these versions. -FROM python:3.12.15-slim-trixie AS runtime +FROM python:3.14.10-slim-trixie AS runtime RUN apt-get update \ && apt-get install -y --no-install-recommends clang g++ nlohmann-json3-dev curl unzip ca-certificates \ && rm -rf /var/lib/apt/lists/* -COPY --from=eclipse-temurin:21.0.5_11-jdk /opt/java/openjdk /opt/java +COPY --from=eclipse-temurin:25.0.5_8-jdk /opt/java/openjdk /opt/java # Downloads are verified against pinned SHA-256 checksums (Kotlin's matches JetBrains' published # .sha256; Gson's was computed from the jar matching Maven Central's published SHA-1). -ARG KOTLIN_VERSION=2.0.21 -ARG KOTLIN_SHA256=0352c0a45bd22f80f6b26e485cd04da8047baa5de54865281fb9f89a4a7bcf2a +ARG KOTLIN_VERSION=2.4.21 +ARG KOTLIN_SHA256=7cc140e76daf416a0424a5557f99afd7ca89ebd463ea1101261e3e01c33e75cd RUN curl -fsSL -o /tmp/k.zip https://github.com/JetBrains/kotlin/releases/download/v${KOTLIN_VERSION}/kotlin-compiler-${KOTLIN_VERSION}.zip \ && echo "${KOTLIN_SHA256} /tmp/k.zip" | sha256sum -c - \ && unzip -q /tmp/k.zip -d /opt && rm /tmp/k.zip @@ -44,7 +44,7 @@ CMD ["python", "-u", "server.py"] # Test image: the runtime plus pytest and the test suite (never shipped). FROM runtime AS test -RUN pip install --no-cache-dir pytest==8.3.4 +RUN pip install --no-cache-dir pytest==9.2.0 COPY pytest.ini ./ COPY tests/ tests/ CMD ["pytest", "-q", "tests/"] diff --git a/runner/server.py b/runner/server.py index 7d3577f..40104c1 100644 --- a/runner/server.py +++ b/runner/server.py @@ -29,7 +29,7 @@ def first(cmd): try: p = subprocess.run(cmd, capture_output=True, text=True, timeout=30) return (p.stdout or p.stderr).strip().splitlines()[0] - except (OSError, subprocess.TimeoutExpired, IndexError): + except OSError, subprocess.TimeoutExpired, IndexError: return "unavailable" _versions = { From 6753de7565a63ccc300593c6d14567d956c82944 Mon Sep 17 00:00:00 2001 From: Ryan Pope Date: Sat, 31 Oct 2026 01:52:47 -0500 Subject: [PATCH 2/2] docs: describe the judge toolchains without naming other platforms --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8f6936..f44ee9f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ All notable changes are documented here. The format follows [Keep a Changelog](h ### Added - First public version: about 4,100 problems (2,830 runnable against 274k hidden tests), company frequency lists for 423 companies, reference solutions with explanations. -- Judging in Python 3.14 and Java 25 (the versions LeetCode judges with), C++23 with Clang 19 and Kotlin 2.4, in a sandboxed runner with no network access. +- Judging in Python 3.14, Java 25, C++23 (Clang 19) and Kotlin 2.4 in a sandboxed runner with no network access. - Problem list, company pages, workspace with Run/Submit and custom cases, submission history, progress dashboard and export. - One-command setup with Docker Compose; content imported from open datasets at first run, with mirror fallbacks. - Repo-kept content in `content/`: new problems and extra solutions, tests or corrections for existing ones, checked in CI by `make validate-content` and marked "local" in the app.