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
7 changes: 7 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Machine-generated / capture-synced paths: GitHub shows "Generated" in PRs
# (diff collapsed by default, expandable; omitted from language stats).
# _generated_*.py → make generate-settings
# contracts.toml → notebook/contract capture + make sync-settings (bundled copy)
sdks/python/src/learning_commons_evaluators/settings/_generated_*.py linguist-generated=true
sdks/python/src/learning_commons_evaluators/settings/**/contracts.toml linguist-generated=true
sdks/settings/**/contracts.toml linguist-generated=true
49 changes: 49 additions & 0 deletions .github/workflows/test-sdk-python.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: 🐍 Test Python SDK

on:
push:
branches:
- main
paths:
- "sdks/python/**"
- "sdks/settings/**"
- ".github/workflows/test-sdk-python.yml"
pull_request:
paths:
- "sdks/python/**"
- "sdks/settings/**"
- ".github/workflows/test-sdk-python.yml"

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
verify:
name: Verify (Python ${{ matrix.python-version }})
runs-on: ubuntu-latest
defaults:
run:
working-directory: sdks/python
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- name: Checkout
uses: actions/checkout@v6

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v6
with:
python-version: ${{ matrix.python-version }}

- name: Install package and dev tools
run: |
python -m pip install --upgrade pip
pip install -e ".[dev]"

- name: make verify
run: make verify
28 changes: 28 additions & 0 deletions sdks/python/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Virtual environments
.venv/
venv/
env/

# Build / install
build/
dist/
*.egg-info/
*.egg

# Testing
.pytest_cache/
.coverage
htmlcov/

# Environment
.env
.env.local

# IDE
.idea/
.vscode/
*.swp
*~

# OS
.DS_Store
108 changes: 108 additions & 0 deletions sdks/python/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
PYTHON ?= python3
PYTEST := $(PYTHON) -m pytest
RUFF := $(PYTHON) -m ruff
MYPY := $(PYTHON) -m mypy

# Bundled settings directory inside the package. Two things are maintained here:
# _generated_*_settings.py — generated from settings.toml by `make generate-settings`
# contracts.toml — copied from sdks/settings/ by `make sync-settings`
#
# Tests always read contracts.toml from the bundled copy (via importlib.resources
# fallback in shared_settings_root()). EVALUATORS_SETTINGS_DIR is intentionally NOT
# exported here so that dev and installed-package runs behave identically.
SETTINGS_DST := src/learning_commons_evaluators/settings

.PHONY: help build check-build test unit-test contract-test \
generate-settings check-generated sync-settings check-sync \
lint format format-check typecheck pip-check verify coverage

help:
@echo "Usage: make <target>"
@echo ""
@echo " build Prepare the package: generate settings + sync contracts TOML"
@echo " check-build Verify build artifacts are up to date (use in CI)"
@echo ""
@echo " lint Ruff linter (src/, tests/, scripts/)"
@echo " format Apply Ruff formatter"
@echo " format-check Fail if Ruff would reformat any file"
@echo " typecheck Mypy on src package + tests"
@echo " pip-check pip dependency consistency check"
@echo " verify check-build + lint + format-check + typecheck + pip-check + test (unit + contract)"
@echo " coverage Unit tests with coverage report (requires dev install)"
@echo ""
@echo " test Run the full test suite (unit + contract)"
@echo " unit-test Run unit tests only (skip contract tests)"
@echo " contract-test Run contract tests only"
@echo ""
@echo " generate-settings Re-generate _generated_*_settings.py from sdks/settings/"
@echo " check-generated Verify generated .py files match sdks/settings/ (exits 1 if stale)"
@echo " sync-settings Copy contracts.toml from sdks/settings/ into the package"
@echo " check-sync Verify bundled contracts.toml matches sdks/settings/"
@echo ""
@echo "Typical workflows:"
@echo " After editing evaluator settings TOML: make generate-settings && make test"
@echo " After editing contracts TOML: make sync-settings && make contract-test"
@echo " Fresh checkout / before release: make build && make verify"
@echo " CI: make verify"

# ── Build ─────────────────────────────────────────────────────────────────────
# Prepares all package build artifacts in one step. Run after editing any
# file under sdks/settings/, or on a fresh checkout before running tests.

build: generate-settings sync-settings

check-build: check-generated check-sync

# ── Static checks (Ruff + Mypy) ───────────────────────────────────────────────

lint:
$(RUFF) check src tests scripts

format:
$(RUFF) format src tests scripts

format-check:
$(RUFF) format --check src tests scripts

typecheck:
$(MYPY) src/learning_commons_evaluators tests

pip-check:
$(PYTHON) -m pip check

verify: check-build lint format-check typecheck pip-check test

coverage:
$(PYTEST) tests/ -q --ignore=tests/contract_tests --cov=learning_commons_evaluators --cov-report=term-missing

# ── Testing ───────────────────────────────────────────────────────────────────

test:
$(PYTEST) tests/ -v

unit-test:
$(PYTEST) tests/ -v --ignore=tests/contract_tests

contract-test:
$(PYTEST) tests/contract_tests/ -v

# ── Code generation ───────────────────────────────────────────────────────────
# Re-run when an evaluator settings TOML under sdks/settings/ changes.
# The generator sets EVALUATORS_SETTINGS_DIR itself to point at sdks/settings/.

generate-settings:
$(PYTHON) scripts/generate_settings.py

check-generated:
$(PYTHON) scripts/generate_settings.py --check

# ── Contract test bundling ────────────────────────────────────────────────────
# contracts.toml is bundled so contract tests run consistently whether using
# a development checkout or a pip-installed package. The sync command is
# handled by the Python generator script.

sync-settings:
$(PYTHON) scripts/generate_settings.py --sync

check-sync:
$(PYTHON) scripts/generate_settings.py --check-sync
Loading