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
9 changes: 6 additions & 3 deletions .github/workflows/build-windows-wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ jobs:
with:
python-version: ${{ matrix.python-version }}

- name: Install Poetry
run: pip install --upgrade poetry
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
python-version: ${{ matrix.python-version }}

- name: Build wheel
run: poetry build -f wheel
run: uv build --wheel

- name: Verify wheel contains binary
shell: pwsh
Expand Down
15 changes: 6 additions & 9 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,19 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Install poetry
run: pipx install poetry

- name: Set up Python
uses: actions/setup-python@v5
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
python-version: "3.10"
cache: "poetry"

- name: Install dependencies
run: poetry install --with docs
run: uv sync --locked --group docs

- name: Build docs
run: poetry run mkdocs build
run: uv run mkdocs build

- name: Deploy to gh-pages
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: poetry run mkdocs gh-deploy --force
run: uv run mkdocs gh-deploy --force
105 changes: 50 additions & 55 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,41 +25,36 @@ jobs:
steps:
- uses: actions/checkout@v4

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

- name: Install Eigen headers
run: sudo apt-get update && sudo apt-get install -y libeigen3-dev

# -- Poetry ------------------------------------------------------
- name: Install Poetry
run: pip install --upgrade poetry

- name: Cache Poetry env
uses: actions/cache@v4
# -- uv ----------------------------------------------------------
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
path: ~/.cache/pypoetry
key: ${{ runner.os }}-poetry-${{ hashFiles('pyproject.toml') }}-v2
enable-cache: true
python-version: ${{ matrix.python-version }}

- name: Install project (dev extras)
run: poetry install --with dev # Install core and development dependencies
- name: Check lockfile freshness
run: uv lock --check

- name: Install project (dev group)
run: uv sync --locked

# -- Lint / Format ----------------------------------------------
- name: flake8
run: poetry run flake8 src tests scripts
run: uv run flake8 src tests scripts

- name: black check
run: poetry run black --check src tests scripts
run: uv run black --check src tests scripts

# -- Tests ------------------------------------------------------
- name: pytest with coverage
run: poetry run pytest --cov=src/ellphi --cov-report=xml
run: uv run pytest --cov=src/ellphi --cov-report=xml

- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v4.0.1
uses: codecov/codecov-action@v5
continue-on-error: true
with:
token: ${{ secrets.CODECOV_TOKEN }}

Expand All @@ -72,32 +67,23 @@ jobs:
steps:
- uses: actions/checkout@v4

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

- name: Install Eigen headers
run: sudo apt-get update && sudo apt-get install -y libeigen3-dev

- name: Install Poetry
run: pip install --upgrade poetry

- name: Cache Poetry env
uses: actions/cache@v4
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
path: ~/.cache/pypoetry
key: ${{ runner.os }}-poetry-${{ hashFiles('pyproject.toml') }}-v2
enable-cache: true
python-version: "3.11"

- name: Install project (dev extras)
run: poetry install --with dev # Install core and development dependencies
- name: Install project (dev group)
run: uv sync --locked

- name: mypy
run: poetry run mypy src
run: uv run mypy src

- name: stubtest
run: MYPYPATH=src poetry run stubtest ellphi --allowlist stubtest-allowlist.txt
run: MYPYPATH=src uv run stubtest ellphi --allowlist stubtest-allowlist.txt

package-test:
runs-on: ubuntu-latest
Expand All @@ -111,16 +97,17 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"

- name: Install Eigen headers
run: sudo apt-get update && sudo apt-get install -y libeigen3-dev

- name: Install Poetry
run: pip install --upgrade poetry
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true

- name: Build package
run: poetry build
run: uv build

- name: Check sdist content
run: |
Expand All @@ -142,21 +129,24 @@ jobs:
# Create a fresh venv to test installation
python -m venv test-env
source test-env/bin/activate

# Install the built wheel
pip install dist/*.whl

# Install test dependencies (pytest)
# Note: runtime dependencies (numpy, etc.) are installed by pip automatically from the wheel metadata
pip install pytest

# Run tests against the installed package
# We assume tests are in 'tests/' and we want to avoid importing from local 'src/'
# So we move to a different directory or explicitely tell pytest where to look
# So we move to a different directory or explicitly tell pytest where to look
mkdir -p test_run
cd test_run
pytest ../tests

# Demo dependencies now live in the separate ellphi-demo repository.
# This job (name kept for branch protection) now verifies that a plain
# `pip install` from the sdist compiles the C++ backend from source.
demo-install:
runs-on: ubuntu-latest
steps:
Expand All @@ -166,16 +156,21 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: "3.11"
cache: "pip"

- name: Install Poetry
run: pip install --upgrade poetry

- name: Cache Poetry env
uses: actions/cache@v4
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
path: ~/.cache/pypoetry
key: ${{ runner.os }}-poetry-${{ hashFiles('pyproject.toml') }}-v2
enable-cache: true

- name: Install project (demo extras)
run: poetry install --with demo # Ensure the demo dependency set resolves
- name: Build sdist
run: uv build --sdist

- name: Install from sdist and smoke test
run: |
python -m venv test-env
source test-env/bin/activate
pip install dist/*.tar.gz
mkdir -p test_run
cd test_run
python -m ellphi --build-info
python -c "from ellphi.solver import has_cpp_backend; assert has_cpp_backend(), 'C++ backend not available'"
34 changes: 14 additions & 20 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,14 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
python-version: "3.12"

- name: Install Poetry
run: pip install --upgrade poetry

- name: Build sdist
run: poetry build -f sdist
run: uv build --sdist

- name: Upload sdist
uses: actions/upload-artifact@v4
Expand All @@ -71,19 +69,17 @@ jobs:
steps:
- uses: actions/checkout@v4

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

- name: Install Eigen headers
run: sudo apt-get update && sudo apt-get install -y libeigen3-dev

- name: Install Poetry
run: pip install --upgrade poetry
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
python-version: ${{ matrix.python-version }}

- name: Build wheel
run: poetry build -f wheel
run: uv build --wheel

- name: Upload wheel
uses: actions/upload-artifact@v4
Expand All @@ -100,16 +96,14 @@ jobs:
steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
- name: Install uv
uses: astral-sh/setup-uv@v6
with:
enable-cache: true
python-version: ${{ matrix.python-version }}

- name: Install Poetry
run: pip install --upgrade poetry

- name: Build wheel
run: poetry build -f wheel
run: uv build --wheel

- name: Upload wheel
uses: actions/upload-artifact@v4
Expand Down
39 changes: 21 additions & 18 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,49 +10,52 @@ This file provides instructions for AI agents working on this repository. Read i

### 1. One-Time Setup

Before you start working, set up your environment by running the following command.
Before you start working, set up your environment by running the following command. Dependencies are managed with [uv](https://docs.astral.sh/uv/).

```bash
poetry install
uv sync
```

This command installs all Python dependencies and also compiles the C++ backend for the tangency solver. If the C++ code (`src/ellphi/_tangency_cpp_impl.cpp`) is modified, the backend will be automatically rebuilt the next time you run `poetry install`.
This command installs all Python dependencies (including the `dev` dependency group) and also compiles the C++ backend for the tangency solver. If the C++ code (`src/ellphi/_tangency_cpp_impl.cpp`) is modified, the backend will be automatically rebuilt the next time you run `uv sync`.

Optional Eigen build (C++ linear algebra):
- Install Eigen headers (Ubuntu: `apt-get install libeigen3-dev`, macOS: `brew install eigen`).
- Rebuild with `ELLPHI_USE_EIGEN=1` and `ELLPHI_EIGEN_INCLUDE` set to the Eigen include path.
- Rebuild with `ELLPHI_USE_EIGEN=1` and `ELLPHI_EIGEN_INCLUDE` set to the Eigen include path, forcing a reinstall of the project: `ELLPHI_USE_EIGEN=1 ELLPHI_EIGEN_INCLUDE=/usr/include/eigen3 uv sync --reinstall-package ellphi`
- Linux default: `/usr/include/eigen3`
- macOS default: `/opt/homebrew/include/eigen3` (Apple Silicon) or `/usr/local/include/eigen3` (Intel)
- Verify with `python -m ellphi --build-info` and check `cpp_linalg_kind`.
- Verify with `uv run python -m ellphi --build-info` and check `cpp_linalg_kind`.

### A Note on Managing Dependencies

If you need to add, remove, or update dependencies in `pyproject.toml`, you must also update the `poetry.lock` file to reflect these changes. After modifying `pyproject.toml`, run the following command:
If you need to add, remove, or update dependencies in `pyproject.toml`, you must also update the `uv.lock` file to reflect these changes. After modifying `pyproject.toml`, run the following command:

```bash
poetry lock
uv lock
```

This ensures that the project's dependencies remain consistent and reproducible. After running the command, remember to commit both the `pyproject.toml` and `poetry.lock` files.
This ensures that the project's dependencies remain consistent and reproducible. After running the command, remember to commit both the `pyproject.toml` and `uv.lock` files. CI verifies lockfile freshness with `uv lock --check`, so a stale `uv.lock` will fail the build.

### 2. Run Test and Lint

In this repository, all CI tests must pass before PRs are merged. Therefore, before pushing you must have run all relevant tests. Use the following checklist and do not skip any step:

```bash
# Format and verify formatting
poetry run black src tests scripts
poetry run black --check src tests scripts
uv run black src tests scripts
uv run black --check src tests scripts

# Lint and static analysis
poetry run flake8 src tests scripts
poetry run mypy src tests
uv run flake8 src tests scripts
uv run mypy src tests

# Type Stub Validation
MYPYPATH=src poetry run stubtest ellphi --allowlist stubtest-allowlist.txt
MYPYPATH=src uv run stubtest ellphi --allowlist stubtest-allowlist.txt

# Tests
poetry run pytest
uv run pytest

# Lockfile freshness (if pyproject.toml changed)
uv lock --check
```

If CI introduces new tools, immediately add them to this checklist.
Expand All @@ -64,7 +67,7 @@ If CI introduces new tools, immediately add them to this checklist.
**Command:**

```bash
MYPYPATH=src poetry run stubtest ellphi --allowlist stubtest-allowlist.txt
MYPYPATH=src uv run stubtest ellphi --allowlist stubtest-allowlist.txt
```

**Purpose:**
Expand All @@ -84,9 +87,8 @@ When `stubtest` reports a failure, it means there is a mismatch between the impl
This section documents the reasons for each entry in the `stubtest-allowlist.txt` file.

* `ellphi._solver_python.MethodName`
* `ellphi.solver.MethodName`

**Reason:** These entries are necessary because the `MethodName` type alias is defined as a `typing.Literal` in the implementation, but it is simplified to `str` in the corresponding stub files (`.pyi`). This simplification is intentional to avoid duplicating the literal values in the stub, which would make it harder to maintain.
**Reason:** This entry is necessary because the `MethodName` type alias is defined as a `typing.Literal` in the implementation, but it is simplified to `str` in the corresponding stub file (`.pyi`). This simplification is intentional to avoid duplicating the literal values in the stub, which would make it harder to maintain. (An equivalent entry for the `ellphi.solver` re-export was needed with older mypy versions but is reported as unused since mypy 1.20.)

#### Managing the Allowlist

Expand All @@ -113,7 +115,8 @@ do **not** require the full Python CI checklist (black/flake8/mypy/pytest).
Instead, run:

```bash
poetry run mkdocs build
uv sync --group docs
uv run mkdocs build
```

and confirm it exits without errors before committing.
Loading
Loading