Skip to content

Commit

Permalink
add cibuildwheel to spiceypy (#421)
Browse files Browse the repository at this point in the history
* added cibuildwheel to spiceypy github actions to build manylinux, macos, and windows wheels
* replacing old method for windows wheel builds, builds on each release but only attempts to push to pypi on tagged releases
* added pyproject.toml, need to deduplicate metadata from setup.py and maybe move to setup.cfg instead
  • Loading branch information
AndrewAnnex committed Sep 29, 2021
1 parent 945e307 commit 73bba45
Show file tree
Hide file tree
Showing 5 changed files with 162 additions and 64 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,4 @@ jobs:
- name: Upload 🆙 coverage 📈 report to codecov
run: |
codecov
97 changes: 44 additions & 53 deletions .github/workflows/publish-to-test-and-live-pypi.yml
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
name: Publish Python 🐍 distributions 📦 to PyPI and TestPyPI

on:
pull_request:
push:
branches: [ main ]
tags: [ 'v*' ]
release:
types: [ published ]

jobs:
build-n-publish-linux:
name: Build and publish SpiceyPy 🌶️ 🥧 Python 🐍 distributions 📦 to PyPI and TestPyPI
build_sdist:
name: Make SpiceyPy 🌶️ 🥧 Python 🐍 source distribution
runs-on: ubuntu-latest
steps:
- name: Checkout 🌶️ 🥧
Expand Down Expand Up @@ -38,77 +39,67 @@ jobs:
python setup.py sdist
- uses: actions/upload-artifact@v2
with:
name: spiceypy_linux_dist
path: dist/
- name: Publish distribution 📦 to Test PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.TEST_PYPI_PASSWORD }}
run: |
twine upload --non-interactive --skip-existing --repository testpypi dist/*
- name: Publish distribution 📦 to PyPI
if: startsWith(github.ref, 'refs/tags') && (github.event_name == 'push' || github.event_name == 'release')
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
run: |
twine upload --non-interactive --skip-existing dist/*
build-n-publish-windows:
name: Build and publish SpiceyPy 🌶️ 🥧 Python 🐍 distributions 📦 to PyPI and TestPyPI on Windows
path: dist/*.tar.gz
build_wheels:
env:
MACOSX_DEPLOYMENT_TARGET: "10.11"
strategy:
matrix:
include:
- python-version: 3.6
python-tag: "cp36"
- python-version: 3.7
python-tag: "cp37"
- python-version: 3.8
python-tag: "cp38"
- python-version: 3.9
python-tag: "cp39"
runs-on: windows-latest
os: [ ubuntu-latest, macos-latest, windows-latest ]
name: Build SpiceyPy 🌶️ 🥧 Python 🐍 wheels for ${{ matrix.os }}
runs-on: ${{ matrix.os }}
steps:
- name: Setup 🔬🍦🏗️
uses: ilammy/msvc-dev-cmd@v1.4.1
- name: Checkout 🌶️ 🥧
uses: actions/checkout@v2
- name: Set up Python 🐍 ${{ matrix.python-version }}
- name: Setup 🔬🍦🏗️
if: runner.os == 'Windows'
uses: ilammy/msvc-dev-cmd@v1.4.1
- name: Set up Python 🐍 3.9
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Display Python 🐍
python-version: 3.9
- name: Display Python 🐍 Version
run: python -c "import sys; print(sys.version)"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r ci-requirements.txt
- name: Install SpiceyPy 🌶️ 🥧
run: |
python setup.py install
- name: Test 🧪 with coverage 📈
run: |
coverage run --source spiceypy -m pytest --pyargs spiceypy
- name: Upload coverage report to codecov
run: |
codecov
- name: Build 🛠️ sdist source
run: |
python setup.py sdist
- name: Build 🛠️ bdist_wheel
python -m pip install -r ci-requirements.txt
python -m pip install cibuildwheel==2.1.2
- name: Build wheels for SpiceyPy 🌶️ 🥧
run: |
python setup.py bdist_wheel --plat-name="win-amd64" --python-tag=${{ matrix.python-tag }}
- uses: actions/upload-artifact@v2
python -m cibuildwheel --output-dir wheelhouse
- name: Upload wheels for SpiceyPy 🌶️ 🥧
uses: actions/upload-artifact@v2
with:
path: ./wheelhouse/*.whl
publish_to_pypi:
name: Publish SpiceyPy 🌶️ 🥧 Python 🐍 distributions 📦 to PyPI and TestPyPI
needs: [build_wheels, build_sdist]
runs-on: ubuntu-latest
if: startsWith(github.ref, 'refs/tags/v') && github.event_name == 'push'
steps:
- uses: actions/download-artifact@v2
with:
name: artifact
path: dist
- name: Set up Python 🐍 3.9
uses: actions/setup-python@v2
with:
name: spiceypy_windows_dist
path: dist/
python-version: 3.9
- name: Display Python 🐍
run: python -c "import sys; print(sys.version)"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install twine
- name: Publish distribution 📦 to Test PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.TEST_PYPI_PASSWORD }}
run: |
twine upload --non-interactive --skip-existing --repository testpypi dist/*
- name: Publish distribution 📦 to PyPI
if: startsWith(github.ref, 'refs/tags') && (github.event_name == 'push' || github.event_name == 'release')
if: startsWith(github.ref, 'refs/tags/v') && github.event_name == 'push'
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
Expand Down
53 changes: 53 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
[project]
name = "spiceypy"
version="4.0.2"
author="Andrew Annex"
author_email="ama6fy@virginia.edu"
description="A Python Wrapper for the NAIF CSPICE Toolkit"
license = "MIT"
homepage = "https://github.com/AndrewAnnex/SpiceyPy"
repository = "https://github.com/AndrewAnnex/SpiceyPy"
documentation = "https://spiceypy.readthedocs.io"
keywords=["spiceypy", "spice", "naif", "jpl", "space", "geometry", "ephemeris"]
readme = "README.rst"
classifiers=[
"Development Status :: 5 - Production/Stable",
"Natural Language :: English",
"Topic :: Scientific/Engineering",
"Topic :: Scientific/Engineering :: Astronomy",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Operating System :: MacOS :: MacOS X",
"Operating System :: POSIX :: Linux",
"Operating System :: POSIX :: BSD :: FreeBSD",
"Operating System :: Microsoft :: Windows",
]
requires-python = ">=3.6, <4"
dependencies = ["numpy>=1.17.0"]

[build-system]
requires = ["setuptools >= 42", "wheel"]
build-backend = "setuptools.build_meta"

[tool.cibuildwheel]
# Only build on CPython 3.9
build = "cp39-*"
# Skip 32-bit builds and pypy
skip = ["*-win32", "*-manylinux_i686", "pypy*"]
# other options
build-verbosity = 2
before-build = "python get_spice.py"
before-test = "pip install -r ci-requirements.txt"
test-command = [
"coverage run --source {package} -m pytest --pyargs {project}",
]

[tool.cibuildwheel.macos]
# to start just try to get amd64 working, later we can worry about arm
archs = ["x86_64"]

[tool.cibuildwheel.linux]
archs = ["x86_64"]
9 changes: 9 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@


[coverage:run]
relative_files = True

[coverage:paths]
source =
spiceypy/
work/SpiceyPy/SpiceyPy/
66 changes: 55 additions & 11 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,8 @@
from setuptools.command.build_py import build_py
from setuptools.dist import Distribution

from get_spice import InstallCSpice

DEV_CI_DEPENDENCIES = [
'numpy>=1.17.0;python_version>="3.5"',
'numpy>=1.17.0;python_version>="3.6"',
"pytest>=2.9.0",
"pandas>=0.24.0",
"coverage>=5.1.0",
Expand All @@ -42,12 +40,12 @@
]

TEST_DEPENDENCIES = [
'numpy>=1.17.0;python_version>="3.5"',
'numpy>=1.17.0;python_version>="3.6"',
"pytest>=2.9.0",
"pandas>=0.24.0",
]
DEPENDENCIES = [
'numpy>=1.17.0;python_version>="3.5"',
'numpy>=1.17.0;python_version>="3.6"',
]
REQUIRES = ["numpy"]

Expand All @@ -71,8 +69,14 @@ def finalize_options(self):
self.install_lib = self.install_platlib

def run(self):
InstallCSpice.get_cspice()
install.run(self)
try:
from get_spice import InstallCSpice

InstallCSpice.get_cspice()
except ModuleNotFoundError as mnfe:
pass
finally:
install.run(self)


class GetCSPICECommand(Command):
Expand All @@ -88,15 +92,26 @@ def finalize_options(self):
pass

def run(self):
InstallCSpice.get_cspice()
try:
from get_spice import InstallCSpice

InstallCSpice.get_cspice()
except ModuleNotFoundError as mnfe:
pass


class BuildPyCommand(build_py):
"""Custom build command to ensure cspice is built and packaged"""

def run(self):
InstallCSpice.get_cspice()
build_py.run(self)
try:
from get_spice import InstallCSpice

InstallCSpice.get_cspice()
except ModuleNotFoundError as mnfe:
pass
finally:
build_py.run(self)


cmdclass = {
Expand All @@ -105,6 +120,32 @@ def run(self):
"get_cspice": GetCSPICECommand,
}

# https://stackoverflow.com/questions/45150304/how-to-force-a-python-wheel-to-be-platform-specific-when-building-it
# http://lepture.com/en/2014/python-on-a-hard-wheel
try:
from wheel.bdist_wheel import bdist_wheel as _bdist_wheel

class generic_bdist_wheel(_bdist_wheel):
"""
override for bdist_wheel
"""

def finalize_options(self) -> None:
_bdist_wheel.finalize_options(self)
self.root_is_pure = False

def get_tag(self) -> (str, str, str):
python, abi, plat = _bdist_wheel.get_tag(self)
return "py3", "none", plat

# add our override to the cmdclass dict so we can inject this behavior
cmdclass["bdist_wheel"] = generic_bdist_wheel

except ImportError:
# we don't have wheel installed so there is nothing to change
pass


readme = open("README.rst", "r")
readmetext = readme.read()
readme.close()
Expand Down Expand Up @@ -139,7 +180,10 @@ def run(self):
include_package_data=True,
zip_safe=False,
distclass=SpiceyPyBinaryDistribution,
package_data={"spiceypy": ["utils/*.so", "utils/*.dll"]},
package_data={
"spiceypy": ["utils/*.so", "utils/*.dll"],
"": ["get_spice.py", "LICENSE"],
},
setup_requires=DEPENDENCIES,
install_requires=DEPENDENCIES,
requires=REQUIRES,
Expand Down

0 comments on commit 73bba45

Please sign in to comment.