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
33 changes: 11 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,29 @@ jobs:
test:
defaults:
run:
shell: bash -el {0}
shell: bash
strategy:
matrix:
os: [ubuntu-latest]
python: ['3.11', '3.12', '3.13']
environment: [test-py311, test-py312, test-py313]
include:
- os: macos-latest
python: '3.11'
environment: test-py311
- os: windows-latest
python: '3.11'
environment: test-py311
fail-fast: false
runs-on: ${{ matrix.os }}
steps:
- name: Checkout Repo
uses: actions/checkout@v3
- uses: actions/setup-python@v5
uses: actions/checkout@v7
- uses: prefix-dev/setup-pixi@v0.10.0
with:
python-version: ${{ matrix.python }}
- name: Install Poetry
uses: snok/install-poetry@v1
- name: Configure Poetry
run: |
if [[ "${{ runner.os }}" == "Windows" ]]; then
poetry env use python
else
poetry env use python${{ matrix.python }}
fi
- name: Install package
run: |
poetry install --extras test
pixi-version: v0.72.2
environments: ${{ matrix.environment }}
- name: Run tests
run: |
poetry run pytest --junit-xml=test-${{ matrix.os }}-Python-${{ matrix.python }}.xml
- uses: codecov/codecov-action@v3
# junit and coverage reports go where pytest.ini says (junit/, coverage.xml)
run: pixi run -e ${{ matrix.environment }} test
- uses: codecov/codecov-action@v7

on:
# Trigger the workflow on push or pull request,
Expand Down
53 changes: 53 additions & 0 deletions .github/workflows/sysimage.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Sysimage

# Builds the Julia sysimage for each platform and publishes it to the GitHub
# release tagged `sysimage-<key>`, where <key> identifies the exact Julia
# environment. Users download it with `pixi run fetch-sysimage`.
on:
workflow_dispatch:
push:
branches:
- main
paths:
- src/galley_jl_python/juliapkg.json
- scripts/sysimage/**
- pyproject.toml
- pixi.lock
- .github/workflows/sysimage.yml

permissions:
contents: write

jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, ubuntu-24.04-arm, macos-latest, windows-latest]
fail-fast: false
runs-on: ${{ matrix.os }}
# GitHub-hosted maximum; the generic multi-CPU build is slow
timeout-minutes: 360
defaults:
run:
shell: bash
steps:
- name: Checkout Repo
uses: actions/checkout@v7
- uses: prefix-dev/setup-pixi@v0.10.0
with:
pixi-version: v0.72.2
- name: Build sysimage
id: build
run: pixi run build-sysimage
- name: Publish to release
env:
GH_TOKEN: ${{ github.token }}
TAG: ${{ steps.build.outputs.tag }}
IMAGE: ${{ steps.build.outputs.path }}
run: |
# the matrix jobs race to create the release; losing the race is fine
gh release view "$TAG" > /dev/null 2>&1 \
|| gh release create "$TAG" --prerelease --title "$TAG" \
--notes "Prebuilt Julia sysimages. Fetch with \`pixi run fetch-sysimage\`." \
|| gh release view "$TAG" > /dev/null
gh release upload "$TAG" "$IMAGE" --clobber
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,6 @@ cython_debug/
.pixi/
*.egg-info
pixi.lock

# PackageCompiler environment used by scripts/sysimage/build_sysimage.jl
scripts/sysimage/.build-env/
92 changes: 81 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,35 @@ pip install galley-jl-python

## Contributing

### Packaging
### Development environment

Galley uses [poetry](https://python-poetry.org/) for packaging.
Galley uses [pixi](https://pixi.sh) for development. All configuration lives in
`pyproject.toml`: the package metadata and dependencies are under `[project]`,
and pixi's settings are under `[tool.pixi]`.

To install for development, clone the repository and run:
To set up, clone the repository and run:
```bash
poetry install --with test
pixi install # the default environment
pixi install -e test # adds the test dependencies (the `test` extra)
```
to install the current project and dev dependencies.

pixi installs the package in editable mode. Julia is not a pixi dependency:
[juliapkg](https://github.com/JuliaPy/pyjuliapkg) installs the pinned Julia
version and packages the first time `galley_jl_python` is imported. To trigger
that, and to fetch the sysimage (see below), run:
```bash
pixi run compile
```

Run any other command inside an environment with `pixi run`, for example
`pixi run -e test python`.

The package is still built and published with Poetry (see
[Publishing](#publishing)).

### Working with a local copy of Finch.jl
The `develop.py ` script can be used to set up a local copy of Finch.jl for development.
The `develop.py` script can be used to set up a local copy of Finch.jl for
development. Run it with `pixi run python develop.py`.

```
Usage:
Expand All @@ -38,6 +55,36 @@ Options:
--path Path to the local copy of Finch.jl [default: ../Finch.jl].
```

### Julia sysimage

Most of Galley's startup time is Julia compiling Finch itself. A prebuilt Julia
sysimage removes it: the first operations of a session drop from minutes to a
few seconds.

- `pixi run fetch-sysimage` downloads the image for your platform into
`~/.cache/galley-jl-python/` (`GALLEY_JL_PYTHON_CACHE` overrides this).
`pixi run compile` and `pixi run test` run this step first.
- `pixi run build-sysimage` builds the image locally instead. This takes hours.
- `import galley_jl_python` loads a cached image automatically when it matches
the current Julia environment. Otherwise Julia starts without it. Set
`GALLEY_JL_PYTHON_SYSIMAGE=0` to turn this off.

An image works only with the exact Julia and package versions it was built
from. For this reason `src/galley_jl_python/juliapkg.json` pins Julia and every
Julia package. Each image's name includes a hash of that environment. A local
Finch.jl from `develop.py` therefore runs without the image.

To update the Julia dependencies:

1. Loosen the pins you want to change.
2. Resolve with `pixi run compile`.
3. Re-pin with `python scripts/sysimage/pin_julia_deps.py`.

Pushing the new pins to `main` runs the "Sysimage" GitHub Action. It builds
images for Linux, macOS and Windows and publishes them to a `sysimage-<hash>`
GitHub release, where `fetch-sysimage` finds them. The action can also be run
manually from the Actions tab.

### Publishing

The "Publish" GitHub Action is a manual workflow for publishing Python packages to PyPI using Poetry. It handles the version management based on the `pyproject.toml` file and automates tagging and creating GitHub releases.
Expand All @@ -61,18 +108,41 @@ On successful execution, the action publishes the package to PyPI and tags the r

### Pre-commit hooks

To add pre-commit hooks, run:
The hooks run in their own `pre-commit` environment, which doesn't install
galley's dependencies or Julia.

```bash
poetry run pre-commit install
pixi run pre-commit-install # run the hooks on every `git commit`
pixi run pre-commit # run every hook on every file now
pixi run pre-commit ruff # the same, skipping the listed hook ids
```

To run a single hook, use `pixi shell -e pre-commit` and then
`pre-commit run <hook-id> -a`.

### Testing

Finch uses [pytest](https://docs.pytest.org/en/latest/) for testing. To run the
Galley uses [pytest](https://docs.pytest.org/en/latest/) for testing. To run the
tests:

```bash
poetry run pytest
pixi run test # one pytest-xdist worker per CPU
pixi run test 4 # or a fixed number of workers
```

This runs `compile` first, then two suites one after the other, each spread
over the workers:

- `pixi run test-unit` runs the unit tests.
- `pixi run test-array-api` runs the Array API tests described below.

Each worker is a separate Julia process that uses 1–2 GB of memory, so lower
the worker count on machines with little memory.

To run a subset, call pytest in the test environment directly:

```bash
pixi run -e test pytest tests/test_fused.py
```

Array API tests are included in `tests/test_array_api.py`. These tests invoke
Expand All @@ -82,7 +152,7 @@ To forward `pytest` options to the nested
`--array-api-pytest-args`):

```bash
poetry run pytest tests/test_array_api.py \
pixi run -e test pytest tests/test_array_api.py \
--array-api="-k creation_functions" \
--array-api="-x"
```
Expand Down
7 changes: 7 additions & 0 deletions array-api-skips.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ array_api_tests/test_special_cases.py::test_unary[sign((x_i is -0 or x_i == +0))
array_api_tests/test_searching_functions.py::test_where
# `test_solve` is not defined in Finch, hangs as xfail
array_api_tests/test_linalg.py::test_solve
# Galley drops the array's shape for `x & False`, `x * 0` and other annihilating
# constants (https://github.com/finch-tensor/Finch.jl/issues/820), and binary
# functions don't accept a scalar as the first argument. Remove these once both
# are fixed.
array_api_tests/test_operators_and_elementwise_functions.py::test_binary_with_scalars_bool[logical_and]
array_api_tests/test_operators_and_elementwise_functions.py::test_binary_with_scalars_bitwise[bitwise_and]

# test_signatures

Expand Down Expand Up @@ -249,6 +255,7 @@ array_api_tests/test_indexing_functions.py::test_take
# test_linalg

# not implemented
array_api_tests/test_linalg.py::test_cross
array_api_tests/test_linalg.py::test_matrix_transpose
array_api_tests/test_linalg.py::test_vecdot
array_api_tests/test_linalg.py::test_eigh
Expand Down
35 changes: 0 additions & 35 deletions pixi.toml

This file was deleted.

Loading
Loading