Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d08e7a4
feat: add support for rsfitsio as backend
beckermr Jul 9, 2026
c410492
fix: wrong test code
beckermr Jul 9, 2026
0c4691c
test: adjust test exclusions more
beckermr Jul 9, 2026
bd5cea4
test: add CI for rsfitsio
beckermr Jul 9, 2026
a176900
fix: update tests
beckermr Jul 9, 2026
cf7fdc8
test: skip more tests
beckermr Jul 9, 2026
44975cc
fix: get linkages right
beckermr Jul 9, 2026
e3d2571
fix: has bzip2 support too
beckermr Jul 9, 2026
41eb68a
fix: skip bz2 test as it fails too
beckermr Jul 9, 2026
0c68c3d
Apply suggestion from @beckermr
beckermr Jul 9, 2026
200d0b9
test: add simple failing tests
beckermr Jul 10, 2026
c50f327
Merge branch 'master' into rsfitsio-build
beckermr Jul 11, 2026
10c0f6f
test: remove rsfitsio skips
beckermr Jul 11, 2026
5bad27d
fix: set dither seed for lossy compression
beckermr Jul 11, 2026
bfe6180
fix: convert to new backend functions
beckermr Jul 11, 2026
fe80eae
fix: more fixes in tests
beckermr Jul 11, 2026
3caac25
fix: wrong import
beckermr Jul 11, 2026
cf2958f
fix: more incorrect imports
beckermr Jul 11, 2026
01a7086
Apply suggestion from @beckermr
beckermr Jul 11, 2026
d8e70d1
fix: more test fixes
beckermr Jul 11, 2026
afe2357
fix: table test fixes
beckermr Jul 11, 2026
645d0f0
Merge branch 'rsfitsio-build' of https://github.com/esheldon/fitsio i…
beckermr Jul 11, 2026
bc87818
Merge branch 'master' into rsfitsio-build
beckermr Jul 14, 2026
67272bc
fix: use constants to help avoid bugs
beckermr Jul 14, 2026
87a68ef
Apply suggestion from @beckermr
beckermr Jul 14, 2026
f618831
fix: sharpen test for threading
beckermr Jul 14, 2026
27b1480
fix: exclude older pythons where GIL is not released
beckermr Jul 14, 2026
da07c59
test: adjust tolerance to be less strict
beckermr Jul 14, 2026
2b87171
test: clean up CI files some more
beckermr Jul 14, 2026
a07525d
test: make more robust by averaging three trials
beckermr Jul 14, 2026
4b409e1
fix: wrong print out
beckermr Jul 14, 2026
5d691d1
Merge branch 'master' into rsfitsio-build
beckermr Jul 16, 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
30 changes: 18 additions & 12 deletions .github/workflows/tests-external-cfitsio.yml
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ jobs:
cd ..
cd ..

- name: test non-bundled build
- name: build non-bundled fitsio
run: |
export CFLAGS="${CFLAGS} ${TEST_CFLAGS}"

Expand All @@ -149,19 +149,22 @@ jobs:
--config-settings="--global-option=--system-fitsio-includedir=$HOME/cfitsio-static-install/include" \
--config-settings="--global-option=--system-fitsio-libdir=$HOME/cfitsio-static-install/lib"

python -c "import fitsio; assert not fitsio.cfitsio_has_bzip2_support()"
- name: test non-bundled build
run: |
python -c "import fitsio; assert not fitsio.backend_has_bzip2_support()"
if [[ "${{ matrix.os }}" == "ubuntu-latest" ]]; then
python -c "import fitsio; assert not fitsio.cfitsio_has_curl_support()"
python -c "import fitsio; assert not fitsio.backend_has_curl_support()"
else
python -c "import fitsio; assert fitsio.cfitsio_has_curl_support()"
python -c "import fitsio; assert fitsio.backend_has_curl_support()"
fi
if [[ "${{ matrix.config.cf}}" != "" ]]; then
python -c "import fitsio; assert fitsio.cfitsio_is_reentrant()"
python -c "import fitsio; assert fitsio.backend_is_reentrant()"
else
python -c "import fitsio; assert not fitsio.cfitsio_is_reentrant()"
python -c "import fitsio; assert not fitsio.backend_is_reentrant()"
fi
python -c "import fitsio; assert fitsio.fitsio_backend() == 'cfitsio'"

pytest -vv --durations=20 ${PRP_FLAGS} fitsio
pytest --durations=20 ${PRP_FLAGS} fitsio

- name: install bzip2 on linux
if: matrix.os == 'ubuntu-latest'
Expand Down Expand Up @@ -201,7 +204,7 @@ jobs:
cd ..
cd ..

- name: test non-bundled build w/ env vars w/ bzip2
- name: build non-bundled fitsio w/ env vars w/ bzip2
run: |
export CFLAGS="${CFLAGS} ${TEST_CFLAGS}"

Expand All @@ -213,11 +216,14 @@ jobs:
export FITSIO_SYSTEM_FITSIO_LIBDIR=$HOME/cfitsio-static-install/lib
pip install ${PIP_OPTIONS} -e .

python -c "import fitsio; assert fitsio.cfitsio_has_bzip2_support()"
- name: test non-bundled build w/ env vars w/ bzip2
run: |
python -c "import fitsio; assert fitsio.backend_has_bzip2_support()"
if [[ "${{ matrix.os }}" == "ubuntu-latest" ]]; then
python -c "import fitsio; assert not fitsio.cfitsio_has_curl_support()"
python -c "import fitsio; assert not fitsio.backend_has_curl_support()"
else
python -c "import fitsio; assert fitsio.cfitsio_has_curl_support()"
python -c "import fitsio; assert fitsio.backend_has_curl_support()"
fi
python -c "import fitsio; assert fitsio.fitsio_backend() == 'cfitsio'"

pytest -vv --durations=20 ${{ matrix.config.doslow }} ${PRP_FLAGS} fitsio
pytest --durations=20 ${{ matrix.config.doslow }} ${PRP_FLAGS} fitsio
9 changes: 5 additions & 4 deletions .github/workflows/tests-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ jobs:

- name: test fitsio
run: |
pytest -vv --durations=20 --slow fitsio
python -c "import fitsio; assert fitsio.cfitsio_has_bzip2_support()"
python -c "import fitsio; assert fitsio.cfitsio_has_curl_support()"
python -c "import fitsio; assert fitsio.cfitsio_is_reentrant()"
pytest --durations=20 --slow fitsio
python -c "import fitsio; assert fitsio.backend_has_bzip2_support()"
python -c "import fitsio; assert fitsio.backend_has_curl_support()"
python -c "import fitsio; assert fitsio.backend_is_reentrant()"
python -c "import fitsio; assert fitsio.fitsio_backend() == 'cfitsio'"
102 changes: 102 additions & 0 deletions .github/workflows/tests-rsfitsio.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
name: tests-rsfitsio

on:
push:
branches:
- master
pull_request: null

env:
PY_COLORS: "1"
# These compiler flags force the tests to fail if arrays are
# accessed at the C level from an unaligned location.
TEST_CFLAGS: "-fsanitize=alignment -fno-sanitize-recover=alignment"

defaults:
run:
shell: bash -leo pipefail {0}

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

jobs:
tests-rsfitsio:
name: tests-rsfitsio
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
config:
# - { pyver: "3.10", npver: "1", ft: ""}
# - { pyver: "3.11", npver: "1.26", ft: "python-gil"}
# - { pyver: "3.12", npver: "1.26", ft: "python-gil"}
# - { pyver: "3.11", npver: "2", ft: "python-gil"}
# - { pyver: "3.12", npver: "2", ft: "python-gil"}
# - { pyver: "3.13", npver: "2", ft: "python-gil"}
- { pyver: "3.14", npver: "2", ft: "python-gil"}
- { pyver: "3.14", npver: "2", ft: "python-freethreading"}

runs-on: ${{ matrix.os }}
env:
PIP_OPTIONS: "--no-cache-dir --no-deps --no-build-isolation -v"

steps:
- name: free disk space
if: matrix.os == 'ubuntu-latest'
uses: endersonmenezes/free-disk-space@v3
with:
remove_android: true
remove_dotnet: true
remove_haskell: true
rm_cmd: "rmz"

- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
fetch-depth: 0
fetch-tags: true

- uses: mamba-org/setup-micromamba@d7c9bd84e824b79d2af72a2d4196c7f4300d3476 #v3.0.0
with:
environment-name: fitsio-dev
environment-file: environment.yml
condarc: |
channels:
- conda-forge
show_channel_urls: true
channel_priority: strict
always_yes: true
create-args: >-
python=${{ matrix.config.pyver }}
numpy=${{ matrix.config.npver }}
${{ matrix.config.ft }}
rust

- name: set parallel testing flags
run: |
if [[ "${{ matrix.config.pyver }}" == "3.14" ]]; then
echo "PRP_FLAGS=--parallel-threads 4 --iterations 4" >> ${GITHUB_ENV}
fi

- name: build rsfitsio
run: |
git clone https://github.com/cruzzil/rsfitsio.git
pushd rsfitsio
RUSTFLAGS="--sysroot=${CONDA_PREFIX}" cargo build --release
popd

- name: build fitsio
run: |
export CFLAGS="${CFLAGS} ${TEST_CFLAGS}"
export FITSIO_USE_RSFITSIO=`pwd`/rsfitsio/target/release

pip install ${PIP_OPTIONS} -e .

- name: test fitsio
run: |
pytest --durations=20 ${PRP_FLAGS} fitsio
python -c "import fitsio; assert fitsio.backend_has_bzip2_support()"
python -c "import fitsio; assert fitsio.backend_has_curl_support()"
python -c "import fitsio; assert not fitsio.backend_is_bundled()"
python -c "import fitsio; assert fitsio.backend_is_reentrant()"
python -c "import fitsio; assert fitsio.fitsio_backend() == 'rsfitsio'"
9 changes: 5 additions & 4 deletions .github/workflows/tests-windows.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,14 @@ jobs:
- name: make nmake available
uses: ilammy/msvc-dev-cmd@v1

- name: install code
- name: build fitsio
run: |
python -m pip install --upgrade pip
pip install -v -e .[dev]
python -c "import fitsio"

- name: test
- name: test fitsio
run: |
python -c "import fitsio; assert not fitsio.cfitsio_is_reentrant()"
pytest -vv --durations=20 --parallel-threads 4 --iterations 4 --ignore-gil-enabled fitsio
python -c "import fitsio; assert not fitsio.backend_is_reentrant()"
python -c "import fitsio; assert fitsio.fitsio_backend() == 'cfitsio'"
pytest --durations=20 --parallel-threads 4 --iterations 4 --ignore-gil-enabled fitsio
34 changes: 21 additions & 13 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ jobs:
echo "PRP_FLAGS=--parallel-threads 4 --iterations 4" >> ${GITHUB_ENV}
fi

- name: test bundled build
- name: build bundled fitsio
run: |
export CFLAGS="${CFLAGS} ${TEST_CFLAGS}"

Expand All @@ -86,16 +86,20 @@ jobs:
rm -rf $HOME/cfitsio-static-install
find . -name "*.so" -type f -delete
pip install ${PIP_OPTIONS} -e .

- name: test bundled build
run: |
if [[ "${{ matrix.os }}" == "ubuntu-latest" ]]; then
pytest -vv --durations=20 ${PRP_FLAGS} fitsio
python -c "import fitsio; assert not fitsio.cfitsio_has_bzip2_support()"
python -c "import fitsio; assert not fitsio.cfitsio_has_curl_support()"
pytest --durations=20 ${PRP_FLAGS} fitsio
python -c "import fitsio; assert not fitsio.backend_has_bzip2_support()"
python -c "import fitsio; assert not fitsio.backend_has_curl_support()"
else
pytest -vv --durations=20 ${PRP_FLAGS} fitsio
python -c "import fitsio; assert fitsio.cfitsio_has_bzip2_support()"
python -c "import fitsio; assert fitsio.cfitsio_has_curl_support()"
pytest --durations=20 ${PRP_FLAGS} fitsio
python -c "import fitsio; assert fitsio.backend_has_bzip2_support()"
python -c "import fitsio; assert fitsio.backend_has_curl_support()"
fi
python -c "import fitsio; assert fitsio.cfitsio_is_reentrant()"
python -c "import fitsio; assert fitsio.backend_is_reentrant()"
python -c "import fitsio; assert fitsio.fitsio_backend() == 'cfitsio'"

- name: install bzip2 and curl on linux
if: matrix.os == 'ubuntu-latest'
Expand All @@ -121,7 +125,7 @@ jobs:
cd -
pip uninstall fitsio --yes

- name: test sdist
- name: build fitsio from sdist
run: |
export CFLAGS="${CFLAGS} ${TEST_CFLAGS}"

Expand All @@ -132,6 +136,9 @@ jobs:
rm -rf dist

python setup.py sdist

- name: test fitsio from sdist
run: |
pushd dist/

fname=$(ls fitsio*.gz)
Expand All @@ -140,10 +147,11 @@ jobs:
pushd $dname

pip install ${PIP_OPTIONS} -e .
pytest -vv --durations=20 ${PRP_FLAGS} fitsio
python -c "import fitsio; assert fitsio.cfitsio_has_bzip2_support()"
python -c "import fitsio; assert fitsio.cfitsio_has_curl_support()"
python -c "import fitsio; assert fitsio.cfitsio_is_reentrant()"
pytest --durations=20 ${PRP_FLAGS} fitsio
python -c "import fitsio; assert fitsio.backend_has_bzip2_support()"
python -c "import fitsio; assert fitsio.backend_has_curl_support()"
python -c "import fitsio; assert fitsio.backend_is_reentrant()"
python -c "import fitsio; assert fitsio.fitsio_backend() == 'cfitsio'"

popd
popd
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,3 +130,5 @@ prof/
.DS_Store
cfitsio-*/
zlib/

rsfitsio/
10 changes: 10 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changes

## 1.5.0 (unreleased)

Changes

- Added support for `rsfitsio` as a backend in addition to `cfitsio`.
- Added function `fitsio_backend` to return the current backend.
- Renamed `cfitsio_*` functions to `backend_*` functions for clarity.
- Added constant `CFITSIO_BACKEND` and `RSFITSIO_BACKEND` which are
the return values of `fitsio_backend`.

## 1.4.2

Changes
Expand Down
13 changes: 13 additions & 0 deletions fitsio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,23 @@
FITSRuntimeWarning,
cfitsio_is_bundled,
)

backend_version = cfitsio_version
backend_is_bundled = cfitsio_is_bundled
from ._fitsio_wrap import (
cfitsio_has_bzip2_support,
cfitsio_has_curl_support,
cfitsio_is_reentrant,
fitsio_backend,
)

backend_has_bzip2_support = cfitsio_has_bzip2_support
backend_has_curl_support = cfitsio_has_curl_support
backend_is_reentrant = cfitsio_is_reentrant

# return values of fitsio_backend, here to help make code
# clearer and avoid mispelling errors in testing strings
CFITSIO_BACKEND = "cfitsio"
RSFITSIO_BACKEND = "rsfitsio"

from .fits_exceptions import FITSFormatError
38 changes: 35 additions & 3 deletions fitsio/fitsio_pywrap.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,27 @@
*/

#include "fitsio.h"
#include "fitsio2.h"
#include <Python.h>
#include <string.h>
// #include "fitsio_pywrap_lists.h"
#include <numpy/arrayobject.h>

#ifdef FITSIO_BACKEND_RSFITSIO
/* random extras needed by fitsio */
int CFITS_API fits_unset_compression_request(fitsfile *fptr, int *status);
int ffgbytoff(fitsfile *fptr, long gsize, long ngroups, long offset,
void *buffer, int *status);
int ffseek(FITSfile *fptr, LONGLONG position);
int ffread(FITSfile *fptr, long nbytes, void *buffer, int *status);
#define REPORT_EOF 0
#define FSTRCMP(a, b) \
((a)[0]<(b)[0] ? -1 : (a)[0]>(b)[0] ? 1 : strcmp((a), (b)))
#endif

#ifdef FITSIO_BACKEND_CFITSIO
#include "fitsio2.h"
#endif

// this is not defined anywhere in cfitsio except in
// the fits file structure
#define CFITSIO_MAX_ARRAY_DIMS 99
Expand Down Expand Up @@ -6347,9 +6362,11 @@ static PyObject *PyFITS_cfitsio_version(void) {
static PyObject *PyFITS_cfitsio_is_bundled(void) {
#ifdef FITSIO_USING_SYSTEM_FITSIO
Py_RETURN_FALSE;
#else
Py_RETURN_TRUE;
#endif
#ifdef FITSIO_BACKEND_RSFITSIO
Py_RETURN_FALSE;
#endif
Py_RETURN_TRUE;
}

static PyObject *PyFITS_cfitsio_has_bzip2_support(void) {
Expand Down Expand Up @@ -6380,6 +6397,18 @@ static PyObject *PyFITS_cfitsio_is_reentrant(void) {
}
}

static PyObject *PyFITS_fitsio_backend(void) {
#ifdef FITSIO_BACKEND_CFITSIO
return PyUnicode_FromString("cfitsio");
#endif
#ifdef FITSIO_BACKEND_RSFITSIO
return PyUnicode_FromString("rsfitsio");
#endif
PyErr_SetString(PyExc_ValueError,
"No valid fitsio backend specified in C layer!");
return NULL;
}

/*

'C', 'L', 'I', 'F' 'X'
Expand Down Expand Up @@ -6685,6 +6714,9 @@ static PyMethodDef fitstype_methods[] = {
METH_NOARGS,
"cfitsio_is_reentrant\n\nReturn True if cfitsio was compiled with "
"reentrant support."},
{"fitsio_backend", (PyCFunction)PyFITS_fitsio_backend, METH_NOARGS,
"fitsio_backend\n\nReturn the backend FITS library (e.g., 'cfitsio', "
"'rsfitsio')."},
{"parse_card", (PyCFunction)PyFITS_parse_card, METH_VARARGS,
"parse_card\n\nparse the card to get the key name, value (as a string), "
"data type and comment."},
Expand Down
Loading
Loading