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
70 changes: 45 additions & 25 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,47 +1,67 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python

# TODO:
# - cache this directory $HOME/.cache/pyensembl/
# - update coveralls
# - get a badge for tests passing
# - download binary dependencies from conda
name: Tests
on: [push, pull_request]
on:
push:
branches: [master]
pull_request:

jobs:
build:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"

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

- name: Lint with ruff
run: |
ruff check serializable tests

- name: Check formatting with ruff
run: |
ruff format --check serializable tests

test:
runs-on: ubuntu-latest
strategy:
fail-fast: true
matrix:
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.9", "3.10", "3.11", "3.12"]

steps:
- name: Checkout repository
uses: actions/checkout@v3
uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
cache: "pip"

- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install flake8 pytest pytest-cov coveralls pylint
pip install -r requirements.txt
pip install .
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Run default linting script
run: |
./lint.sh
pip install -e ".[dev]"

- name: Run unit tests
run: |
./test.sh
- name: Publish coverage to Coveralls
uses: coverallsapp/github-action@v2.2.3
pytest tests/ -v --cov=serializable --cov-report=xml

- name: Upload coverage to Coveralls
if: matrix.python-version == '3.11'
uses: coverallsapp/github-action@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
file: coverage.xml
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ celerybeat-schedule
.env

# virtualenv
.venv/
venv/
ENV/

Expand Down
97 changes: 97 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
## Repo Info

- **Package**: `serializable` — base class with serialization helpers for user-defined Python objects.
- **GitHub**: https://github.com/openvax/serializable
- **PyPI**: https://pypi.org/project/serializable/
- **Author**: Alex Rubinsteyn <alex.rubinsteyn@unc.edu>
- **Primary branch**: `master`

---

## Golden Rules

1. **Never commit to `master`.** Always `git checkout -b <feature-branch>` before editing. Land via PR.
2. **Every PR bumps the version.** Even doc-only PRs — at minimum a patch bump. Edit `serializable/version.py`.
3. **"Done" means merged AND deployed to PyPI** — never stop at merge. After a PR merges, run `./deploy.sh` from a clean `master`. Skipping deploy = task not done.
4. **File problems as issues, don't silently work around them.** If you hit a bug here or in a sibling openvax repo, open a GitHub issue on the correct repo and link it from the PR.
5. **After a PR ships, look for the next block of work.** Read open issues across relevant openvax repos, group by dependency + urgency. Prefer *foundational* changes that unblock multiple downstream improvements; otherwise chain the smallest independent improvements.

---

## Before Completing Any Task

Before considering any code change complete, you MUST:

1. **Run `./format.sh`** — Auto-format all code
2. **Run `./lint.sh`** — Verify linting passes (runs both `ruff check` and `ruff format --check`)
3. **Run `./test.sh`** — Verify all tests pass

Do not tell the user you are "done" or that changes are "complete" until all three of these pass.

## Scripts

- `./format.sh` — Formats code with ruff (run this first)
- `./lint.sh` — Checks linting and formatting (must pass). **Always use this for linting if it exists.**
- `./test.sh` — Runs pytest with coverage (must pass)
- `./deploy.sh` — Builds the distribution and uploads to PyPI via `twine` (gates on `lint.sh` and `test.sh`). **Always use this for deploying if it exists.**
- `./develop.sh` — Installs package in development mode into `.venv`

## Code Style

- Use ruff for formatting and linting
- Configuration is in `pyproject.toml` under `[tool.ruff]`
- Line length: 100 characters
- Target Python version: 3.9+

---

## Workflow Orchestration

### 1. Upfront Planning
- For ANY non-trivial task (3+ steps or architectural decisions): write a detailed spec before touching code
- If something goes sideways, STOP and re-plan immediately — don't keep pushing
- Use planning/verification steps, not just building
- Write detailed specs upfront to reduce ambiguity

### 2. Self-Improvement Loop
- After ANY correction from the user: update `tasks/lessons.md` with the pattern
- Write rules for yourself that prevent the same mistake
- Ruthlessly iterate on these lessons until mistake rate drops
- Review lessons at session start for relevant project

### 3. Verification Before Done
- Never mark a task complete without proving it works
- Diff behavior between the latest code and your changes when relevant
- Ask yourself: "Would a staff engineer approve this?"
- Run tests, check logs, demonstrate correctness

### 4. Demand Elegance (Balanced)
- For non-trivial changes: pause and ask "is there a more elegant way?"
- If a fix feels hacky: "Knowing everything I know now, implement the elegant solution"
- Skip this for simple, obvious fixes — don't over-engineer
- Challenge your own work before presenting it

### 5. Autonomous Bug Fixing
- When given a bug report: just fix it. Don't ask for hand-holding
- Point at logs, errors, failing tests — then resolve them
- Zero context switching required from the user
- Fix failing unit tests without being told how

---

## Task Management

1. **Plan First**: Write plan to `tasks/todo.md` with checkable items
2. **Verify Plan**: Check in before starting implementation
3. **Track Progress**: Mark items complete as you go
4. **Explain Changes**: High-level summary at each step
5. **Document Results**: Add review section to `tasks/todo.md`
6. **Capture Lessons**: Update `tasks/lessons.md` after corrections

---

## Core Principles

- **Simplicity First**: Make every change as simple as possible. Impact minimal code.
- **No Laziness**: Find root causes. No temporary fixes. Senior developer standards.
- **Minimal Impact**: Changes should only touch what's necessary. Avoid introducing bugs.
17 changes: 17 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Project Instructions

See @AGENTS.md for verification steps, workflow principles, and repo info.

---

## Claude Code-Specific

### Plan Mode
- Enter plan mode for ANY non-trivial task (3+ steps or architectural decisions)
- Use plan mode for verification steps, not just building

### Subagent Strategy
- Use subagents liberally to keep main context window clean
- Offload research, exploration, and parallel analysis to subagents
- For complex problems, throw more compute at it via subagents
- One task per subagent for focused execution
22 changes: 15 additions & 7 deletions deploy.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
./lint.sh && \
./test.sh && \
python3 -m pip install --upgrade build && \
python3 -m pip install --upgrade twine && \
rm -rf dist && \
python3 -m build && \
python3 -m twine upload dist/*
#!/usr/bin/env bash
set -euo pipefail

ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$ROOT"

./lint.sh
./test.sh

PYTHON_BIN="${DEPLOY_PYTHON:-python3}"
"$PYTHON_BIN" -m pip install --upgrade build twine
rm -rf dist build ./*.egg-info
"$PYTHON_BIN" -m build
"$PYTHON_BIN" -m twine check dist/*
"$PYTHON_BIN" -m twine upload dist/*
22 changes: 22 additions & 0 deletions develop.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash

set -e

VENV_DIR=".venv"

if [ ! -d "$VENV_DIR" ]; then
echo "Creating virtual environment at $VENV_DIR..."
python -m venv "$VENV_DIR"
fi

# shellcheck disable=SC1091
source "$VENV_DIR/bin/activate"

# Check if UV is installed and available in the PATH
if command -v uv &> /dev/null; then
echo "Using uv to install package with development dependencies..."
uv pip install -e ".[dev]"
else
echo "uv not found, falling back to regular pip..."
pip install -e ".[dev]"
fi
10 changes: 10 additions & 0 deletions format.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash

set -e

SOURCES="serializable tests"

echo "Running ruff format..."
ruff format $SOURCES

echo "Formatting complete!"
1 change: 0 additions & 1 deletion lint-and-test.sh

This file was deleted.

19 changes: 10 additions & 9 deletions lint.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#!/bin/bash
set -o errexit
#!/usr/bin/env bash

# getting false positives due to this issue with pylint:
# https://bitbucket.org/logilab/pylint/issues/701/false-positives-with-not-an-iterable-and
set -e

find serializable -name '*.py' \
| xargs pylint \
--errors-only \
--disable=unsubscriptable-object,not-an-iterable
SOURCES="serializable tests"

echo 'Passes pylint check'
echo "Running ruff check..."
ruff check $SOURCES

echo "Running ruff format check..."
ruff format --check $SOURCES

echo "All checks passed!"
5 changes: 0 additions & 5 deletions pylintrc

This file was deleted.

Loading
Loading