Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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]'
Expand Down
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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, 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.
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -95,7 +95,7 @@ flowchart LR
B["Browser<br/>localhost:4173"] --> A
subgraph Docker["Docker Compose"]
A["app<br/>FastAPI + React UI"]
R["runner<br/>Python 3.12 · JDK 21 · Clang 19 · Kotlin 2.0<br/>no network"]
R["runner<br/>Python 3.14 · JDK 25 · Clang 19 · Kotlin 2.4<br/>no network"]
D[("localcode-data volume<br/>content.db · user.db")]
A -- "code + test inputs<br/>(Unix socket)" --> R
R -- "raw outputs" --> A
Expand Down
2 changes: 1 addition & 1 deletion backend/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down
4 changes: 2 additions & 2 deletions backend/localcode/importer/dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -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", []):
Expand Down Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion backend/localcode/judging/runner_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 1 addition & 1 deletion backend/pyproject.toml
Original file line number Diff line number Diff line change
@@ -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]
Expand Down
2 changes: 1 addition & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`:
Expand Down
2 changes: 1 addition & 1 deletion ruff.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
line-length = 120
target-version = "py312"
target-version = "py314"
extend-exclude = ["web", "**/.venv"]

[lint]
Expand Down
10 changes: 5 additions & 5 deletions runner/Dockerfile
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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/"]
2 changes: 1 addition & 1 deletion runner/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down