Skip to content
Open
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
124 changes: 100 additions & 24 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
@@ -1,35 +1,111 @@
name: Upload to PyPI
name: Build and publish to PyPI

on:
release:
types: [published]
workflow_dispatch:

jobs:
Upload:
build_wheels:
name: Build wheels on ${{ matrix.os }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
cibw_archs: x86_64
- os: macos-latest
cibw_archs: arm64

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Build wheels
uses: pypa/cibuildwheel@v3.3.1
env:
CIBW_ARCHS: ${{ matrix.cibw_archs }}

- name: Upload wheels
uses: actions/upload-artifact@v4
with:
name: cibw-wheels-${{ matrix.os }}-${{ matrix.cibw_archs }}
path: ./wheelhouse/*.whl

build_sdist:
name: Build source distribution
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.10"

- name: Install build dependencies
run: python -m pip install --upgrade pip build

- name: Build sdist
run: python -m build --sdist

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

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a block for test.pypi? Just to make sure the release doesn't break the official packages.

This was suggested by copilot.

  publish-testpypi:
    name: Publish to TestPyPI
    needs: [build_wheels, build_sdist]
    runs-on: ubuntu-latest
    if: github.event_name == 'workflow_dispatch'   # manual trigger only
    environment:
      name: testpypi
      url: https://test.pypi.org/p/pyccl
    permissions:
      contents: read
      id-token: write

    steps:
      - name: Download all artifacts
        uses: actions/download-artifact@v4
        with:
          pattern: cibw-*
          path: dist
          merge-multiple: true

      - name: Publish to TestPyPI
        uses: pypa/gh-action-pypi-publish@release/v1
        with:
          repository-url: https://test.pypi.org/legacy/

@damonge, @c-d-leonard I think we need your intervention to set up the identity provider in test-pypi https://test.pypi.org/project/pyccl/. Also, it might be good if you add desc-ccl as maintainer (which I believe is what we use to publish to pypi?).

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added, as you say, also in the next comments, I am assuming that trusted publishing is set up. So maybe some work is required by maintainers to fix that, if that is not true.

publish_testpypi:
name: Publish to TestPyPI
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
if: github.event_name == 'workflow_dispatch'
environment:
name: testpypi
url: https://test.pypi.org/p/pyccl
permissions:
contents: read
id-token: write

steps:
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
pattern: cibw-*
path: dist
merge-multiple: true

- name: Publish to TestPyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
repository-url: https://test.pypi.org/legacy/

publish:
name: Publish to PyPI
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
if: github.event_name == 'release'
environment:
name: pypi
url: https://pypi.org/p/pyccl
permissions:
contents: read
id-token: write # Required for trusted publishing
id-token: write

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, copilot suggested to add an environment section. I am not familiar enough with pypi publishing to know if we should pay attention to it or not.

  environment:
    name: pypi
    url: https://pypi.org/p/pyccl

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that is required by trusted publishing, I've added that.

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

- name: Setup python
uses: actions/setup-python@v5
with:
python-version: '3.10'

- name: Install build dependencies
run: |
python -m pip install --upgrade pip
python -m pip install build

- name: Build source tarball only
run: |
python -m build --sdist

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
with:
password: ${{ secrets.PYPI_PYCCL_UPLOAD }}
- name: Download all artifacts
uses: actions/download-artifact@v4
with:
pattern: cibw-*
path: dist
merge-multiple: true

- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
2 changes: 1 addition & 1 deletion cmake/Modules/BuildFFTW.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ if(NOT FFTW_FOUND )
ExternalProject_Add(FFTW
PREFIX FFTW
URL http://www.fftw.org/fftw-${FFTWVersion}.tar.gz
URL_MD5 ${GSLMD5}
URL_MD5 ${FFTWMD5}
DOWNLOAD_NO_PROGRESS 1
CONFIGURE_COMMAND ./configure --prefix=${CMAKE_BINARY_DIR}/extern --enable-shared=no --with-pic=yes
BUILD_COMMAND make -j8
Expand Down
8 changes: 4 additions & 4 deletions cmake/Modules/FindPythonLibsNew.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,12 @@ endif()
# The library suffix is from the config var LDVERSION sometimes, otherwise
# VERSION. VERSION will typically be like "2.7" on unix, and "27" on windows.
execute_process(COMMAND "${PYTHON_EXECUTABLE}" "-c"
"from distutils import sysconfig as s;import sys;import struct;
"import sysconfig as s;import sys;import struct;
print('.'.join(str(v) for v in sys.version_info));
print(sys.prefix);
print(s.get_python_inc(plat_specific=True));
print(s.get_python_lib(plat_specific=True));
print(s.get_config_var('SO'));
print(s.get_path('platinclude'));
print(s.get_path('platlib'));
print(s.get_config_var('EXT_SUFFIX') or s.get_config_var('SO') or '');
print(hasattr(sys, 'gettotalrefcount')+0);
print(struct.calcsize('@P'));
print(s.get_config_var('LDVERSION') or s.get_config_var('VERSION'));
Expand Down
12 changes: 5 additions & 7 deletions pyccl/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,12 @@ else()
endif()
swig_link_libraries(ccllib ccl_static)

# SWIG>=4.4 triggers int-conversion warning/error while calling numpy's import_array()
# GCC 14+ and Clang both treat this as an error.
target_compile_options(${SWIG_MODULE_ccllib_REAL_NAME} PRIVATE "-Wno-error=int-conversion")

if(APPLE)
# SWIG>=4.4 triggers int-conversion warning/error while calling numpy's import_array()
# GCC seems to be raising warnings but clang raises an error, instead.
# We make clang to treat them as warnings with next line.
target_compile_options(${SWIG_MODULE_ccllib_REAL_NAME} PRIVATE "-Wno-error=int-conversion")
# Unpleasant subtelty for linking on osx
# On macOS, allow undefined symbols to be resolved at runtime by the Python interpreter.
set_target_properties(${SWIG_MODULE_ccllib_REAL_NAME} PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
else(APPLE)
swig_link_libraries(ccllib ${PYTHON_LIBRARIES})
endif()
set_target_properties(${SWIG_MODULE_ccllib_REAL_NAME} PROPERTIES SUFFIX .so)
18 changes: 14 additions & 4 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,7 @@ documentation = "https://ccl.readthedocs.io/en/latest/"
repository = "https://github.com/LSSTDESC/CCL"

[project.optional-dependencies]
dev = [
"pytest",
"pytest-cov",
]
dev = ["pytest", "pytest-cov"]

[tool.setuptools.packages.find]
include = ["pyccl*"]
Expand All @@ -49,3 +46,16 @@ include = ["pyccl*"]
pyccl = ["_ccllib.so", "emulators/data/*.npz"]

[tool.setuptools_scm]

[tool.cibuildwheel]
build = "cp310-* cp311-* cp312-* cp313-* cp314-*"
skip = "pp* *-musllinux_* *-win* *-manylinux_i686 *-manylinux_s390x *-manylinux_ppc64le"
test-command = "python -c \"import pyccl; print(pyccl.__version__)\""

[tool.cibuildwheel.linux]
manylinux-x86_64-image = "manylinux_2_28"
manylinux-aarch64-image = "manylinux_2_28"
before-all = "dnf install -y pcre-devel automake autoconf libtool bison"

[tool.cibuildwheel.macos]
environment = { MACOSX_DEPLOYMENT_TARGET = "11.0" }
13 changes: 11 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import shutil
import sys
from subprocess import call

Expand All @@ -9,10 +10,15 @@


def _compile_ccl(debug=False):
call(["mkdir", "-p", "build"])
# Clean stale CMake cache to avoid cross-version contamination
# (e.g. when cibuildwheel builds multiple Python versions sequentially).
if os.path.exists("build/CMakeCache.txt"):
shutil.rmtree("build")
os.makedirs("build", exist_ok=True)
v = sys.version_info
cmd = ["cmake", "-H.", "-Bbuild",
"-DPYTHON_VERSION=%d.%d.%d" % (v.major, v.minor, v.micro)]
"-DPYTHON_VERSION=%d.%d.%d" % (v.major, v.minor, v.micro),
"-DPYTHON_EXECUTABLE=%s" % sys.executable]
if debug:
cmd += ["-DCMAKE_BUILD_TYPE=Debug"]
if call(cmd) != 0:
Expand Down Expand Up @@ -45,6 +51,9 @@ def __init__(self, attr=None):
self.debug = False
super().__init__(attr)

def has_ext_modules(self):
return True


class Build(_build):
"""Specialized Python source builder."""
Expand Down