Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
6d216b7
Switch to scikit-build-core with cibuildwheel
ivh Dec 18, 2025
4952c3f
Fix cibuildwheel: remove retired macos-13, set gfortran env
ivh Dec 18, 2025
6bff2c9
Fix: include data files in wheel, set MACOSX_DEPLOYMENT_TARGET
ivh Dec 18, 2025
97db626
Consolidate workflows into python-app.yml
ivh Dec 18, 2025
e201984
Remove Linux aarch64 builds (QEMU too slow)
ivh Dec 18, 2025
dc2515d
Fix Windows gfortran, only run on tags or manual
ivh Dec 18, 2025
ecb58c4
Fix Windows gfortran with full paths
ivh Dec 18, 2025
8f861cf
Use Ninja generator for Windows CMake builds
ivh Dec 18, 2025
c696ba5
Fix Windows env var syntax for cibuildwheel
ivh Dec 18, 2025
93b21f7
Add MSYS2 to GitHub PATH for Windows builds
ivh Dec 19, 2025
d17a9b6
Add build path for delvewheel to find libsme.dll
ivh Dec 19, 2025
4a38315
Skip Windows wheel repair for now
ivh Dec 19, 2025
dff0e81
Custom Windows wheel repair script
ivh Dec 19, 2025
e498fd9
Use bash for Windows wheel repair
ivh Dec 19, 2025
475f17f
Release v0.5.0a1
ivh Dec 19, 2025
72068f1
uv lock & sync
ivh Jan 26, 2026
85f0111
Add CLAUDE.md, fix dev dependencies
ivh Jan 26, 2026
7b3082e
Fix Python 3.13 / numpy compatibility issues
ivh Jan 26, 2026
22fec9c
Update CLAUDE.md with smelib submodule info and dev setup
ivh Jan 26, 2026
564ac25
Auto-detect dev paths, remove need for symlinks
ivh Jan 26, 2026
073bbbb
Fix numpy/Python 3.13 compatibility issues
ivh Jan 26, 2026
03df7c3
update CLAUDE.md and submodule smelib
ivh Jan 26, 2026
77ebcfb
Exclude autotools artifacts from sdist
ivh Jan 26, 2026
dbb9930
Release v0.5.0a2
ivh Jan 26, 2026
55198db
Add GitHub release job, update README, use manylinux_2_28
ivh Jan 26, 2026
ae278a3
Release v0.5.0a3
ivh Jan 26, 2026
94e3308
Lazy load H-line interpolators, fix slow import
ivh Jan 27, 2026
315d586
Expand README installation section with fork/upstream distinction
ivh Jan 27, 2026
2bdced6
Fix deprecation warnings and minor issues
ivh Jan 27, 2026
8d14554
Update smelib submodule
ivh Jan 27, 2026
2e99d20
Release v0.5.0a4
ivh Jan 27, 2026
084e27d
Remove legacy build files and fix docs
ivh Jan 27, 2026
42f43d2
ignore untracked files from webgui branch
ivh Jan 27, 2026
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
200 changes: 92 additions & 108 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
@@ -1,127 +1,111 @@
# This workflow will install Python dependencies, run tests and lint with a single version of Python
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Python application

on:
push:
branches: [master]
pull_request:
branches: [master]
tags: ["v*"]
workflow_dispatch:

jobs:
build:
build_sdist:
name: Build source distribution
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Build sdist
run: pipx run build --sdist

- uses: actions/upload-artifact@v4
with:
name: sdist
path: dist/*.tar.gz

build_wheels:
name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-15, macos-13] # macos-15/14=arm64,macos-13=x86_64
py: ['3.9','3.10','3.11','3.12','3.13']
name: py${{ matrix.py }} on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
# strategy:
# fail-fast: false
# matrix:
# include:
# - name: ubuntu
# runs_on: ubuntu-latest
# - name: macos-intel
# runs_on: macos-13
# - name: macos-apple-silicon
# runs_on: macos-15
# runs-on: ${{ matrix.runs_on }}
environment: release
permissions:
contents: write
id-token: write # IMPORTANT: mandatory for trusted publishing
os: [ubuntu-22.04, macos-14, windows-2022]

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
# - name: Install autoconf and gfortran (libgfortran) on macOS (GCC route)
# if: ${{ matrix.name == 'macos-intel' || matrix.name == 'macos-apple-silicon' }}
# run: |
# brew update
# # brew install autoconf automake libtool gcc
# # brew link --force gcc
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.py }}
# run: |
# python -V
# python -c "import sys, sysconfig; print(sys.executable); print(sysconfig.get_platform())"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
# pip install flake8 pytest
python -m pip install .[dev]
# python setup.py version
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: Test with pytest
run: pytest

- name: GitHub Tag
if: github.event_name != 'pull_request' && matrix.os == 'ubuntu-latest' && matrix.py == '3.12'
id: tag_release
uses: mathieudutour/github-tag-action@v6.2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
submodules: recursive

- uses: actions/checkout@v4
if: github.event_name != 'pull_request' && matrix.os == 'ubuntu-latest' && matrix.py == '3.12'
- name: Install MSYS2 (Windows)
if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2
with:
ref: ${{ steps.tag_release.outputs.new_tag }}
clean: false

- name: Build Wheel
if: matrix.os == 'ubuntu-latest' && matrix.py == '3.12'
# run: pip install wheel && python setup.py sdist bdist_wheel
run: |
python -m pip install -U pip
python -m pip install -U wheel build
python -m build

- name: Zip data
if: matrix.os == 'ubuntu-latest' && matrix.py == '3.12'
id: zip_data
run: zip -r dist dist && echo "::set-output name=filename::dist.zip"

- name: Create Release
if: github.event_name != 'pull_request' && matrix.os == 'ubuntu-latest' && matrix.py == '3.12'
id: create_release
uses: actions/create-release@v1
msystem: MINGW64
update: false
install: mingw-w64-x86_64-gcc-fortran mingw-w64-x86_64-ninja

- name: Add MSYS2 to PATH (Windows)
if: runner.os == 'Windows'
shell: pwsh
run: echo "C:\msys64\mingw64\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append

- name: Build wheels
uses: pypa/cibuildwheel@v2.22
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
CIBW_BUILD_VERBOSITY: 1
CIBW_ENVIRONMENT_WINDOWS: 'FC=gfortran CC=gcc CXX=g++ CMAKE_GENERATOR=Ninja'

- uses: actions/upload-artifact@v4
with:
tag_name: ${{ steps.tag_release.outputs.new_tag }}
release_name: Release ${{ steps.tag_release.outputs.new_tag }}
draft: false
prerelease: false

- name: Upload Release Asset
if: github.event_name != 'pull_request' && matrix.os == 'ubuntu-latest' && matrix.py == '3.12'
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
name: wheels-${{ matrix.os }}
path: ./wheelhouse/*.whl

publish:
name: Publish to PyPI
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
environment:
name: pypi
url: https://pypi.org/p/pysme-astro
permissions:
id-token: write

steps:
- uses: actions/download-artifact@v4
with:
pattern: wheels-*
path: dist
merge-multiple: true

- uses: actions/download-artifact@v4
with:
upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: ./dist.zip
asset_name: dist.zip
asset_content_type: application/zip
name: sdist
path: dist

- name: Publish a Python distribution to PyPI
if: github.event_name != 'pull_request' && matrix.os == 'ubuntu-latest' && matrix.py == '3.12'
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
# with:
# user: __token__
# password: ${{ secrets.pypi_password }}

release:
name: Create GitHub Release
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
permissions:
contents: write

steps:
- uses: actions/download-artifact@v4
with:
pattern: wheels-*
path: dist
merge-multiple: true

- uses: actions/download-artifact@v4
with:
name: sdist
path: dist

- name: Create GitHub Release
run: gh release create ${{ github.ref_name }} dist/* --repo ${{ github.repository }} --title "${{ github.ref_name }}" --prerelease
env:
GH_TOKEN: ${{ github.token }}
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -164,4 +164,7 @@ paper/*.html
local/
atmo_ml/

src/pysme/lib
# Frontend build artifacts (webgui branch)
src/pysme/gui/frontend/node_modules/
src/pysme/gui/frontend/dist/
docs/websme-reference/
3 changes: 1 addition & 2 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
[submodule "smelib"]
path = smelib
url = https://github.com/AWehrhahn/SMElib
update = checkout
url = https://github.com/MingjieJian/SMElib.git
4 changes: 0 additions & 4 deletions .isort.cfg

This file was deleted.

130 changes: 130 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# PySME Development Guide

## Quick Start

```bash
uv sync # Install in dev mode (compiles native code)
uv run pytest # Run tests
```

## Project Overview

PySME (Spectroscopy Made Easy) is a Python package for stellar spectroscopy analysis. It includes a native library (`libsme`) written in Fortran/C++ that handles the computationally intensive spectral synthesis.

## Build System

Uses **scikit-build-core** with CMake to compile the native extension:
- `smelib/` - Git submodule containing Fortran/C++ source (from MingjieJian/SMElib)
- `CMakeLists.txt` - Builds `libsme` shared library and `_smelib` Python extension
- `pyproject.toml` - Build configuration and cibuildwheel settings

The native code is compiled at build time (not runtime), producing platform-specific wheels.

### smelib Submodule

The `smelib/` directory is a git submodule pointing to `ivh/SMElib` (forked from `MingjieJian/SMElib`, which is the active upstream). The original repo `AWehrhahn/SMElib` is abandoned.

PySME's CMakeLists.txt compiles these smelib sources:
- `smelib/src/sme/sme_synth_faster.cpp` - main C++ synthesis code
- `smelib/src/sme/*.f`, `smelib/src/eos/*.f` - Fortran routines
- `smelib/pymodule/_smelib.cpp` - Python extension wrapper
- `smelib/src/data/` - runtime data files

Into:
- `libsme.so/.dylib/.dll` - shared library with Fortran routines
- `_smelib` - Python extension module

#### smelib cleanup

The fork has been cleaned of files not needed by PySME:
- Removed: CI configs (`.github/`, `.travis.yml`, `travis/`), test suite, debug scripts, backup files
- Kept: autotools build system (`bootstrap`, `configure.ac`, `Makefile.am`, etc.) and `pymodule/smelib.py` for standalone/IDL use

#### Build system history

**Old approach** (before current build system):
1. `pip install pysme-astro` installed pure Python
2. At runtime, PySME detected platform and downloaded pre-built `libsme` binaries from SMElib GitHub releases
3. Those releases were built by SMElib's own CI workflows (now removed from our fork)

**Current approach**:
1. `pip install pysme-astro` installs a wheel with compiled `libsme` included
2. Compilation happens at wheel build time via PySME's CI (CMake/scikit-build-core)
3. No runtime downloads needed

The standalone SMElib releases (from MingjieJian/SMElib) are still produced for IDL users who use SME without Python.

## CI/CD

GitHub Actions workflow (`.github/workflows/python-app.yml`):
- Triggers on version tags (`v*`) or manual dispatch
- Builds wheels for:
- Linux x86_64 (manylinux)
- macOS arm64
- Windows AMD64
- Publishes to PyPI via trusted publishing (OIDC)

### Platform-specific notes

- **macOS**: Uses Homebrew gcc/gfortran-14, MACOSX_DEPLOYMENT_TARGET=14.0
- **Windows**: Uses MSYS2 MinGW gfortran, Ninja generator, custom wheel repair script
- **Linux**: Uses manylinux container with gfortran

## Release Process

1. Update version in `pyproject.toml`:
```
version = "X.Y.Z" # stable release
version = "X.Y.ZaN" # alpha (not installed by default)
version = "X.Y.ZbN" # beta
version = "X.Y.ZrcN" # release candidate
```

2. Sync lockfile and commit:
```bash
uv sync
git add pyproject.toml uv.lock
git commit -m "Release vX.Y.Z"
git tag vX.Y.Z
git push && git push origin vX.Y.Z
```

3. GitHub Actions builds wheels and publishes to PyPI automatically.

4. If PyPI publish fails (permissions), create GitHub release manually:
```bash
gh run download <run-id> --dir release-artifacts
gh release create vX.Y.Z --prerelease --title "vX.Y.Z" \
release-artifacts/sdist/* release-artifacts/wheels-*/*
```

## Key Files

- `src/pysme/` - Main Python package
- `src/pysme/smelib/` - Native library interface
- `smelib/` - Fortran/C++ source (submodule)
- `CMakeLists.txt` - Native build configuration
- `pyproject.toml` - Package metadata, build config, cibuildwheel config

## Dependencies

Runtime: numpy, scipy, pandas, astropy, tqdm, emcee, plotly, matplotlib, etc.
Build: scikit-build-core, numpy, CMake, Fortran compiler (gfortran)

## Testing

```bash
uv run pytest # Run all tests
uv run python -c "from pysme.sme import SME_Structure" # Quick import test
```

## Local Development Setup

After cloning, initialize submodules and install:

```bash
git submodule update --init --recursive
uv sync
```

This compiles the native code and installs in editable mode. After editing C/Fortran code in `smelib/`, re-run `uv sync` to rebuild.
Loading