From acc788c37485c7c7a7fa8ce860e3c50f9866c692 Mon Sep 17 00:00:00 2001 From: Eleftherios Zisis Date: Thu, 3 Feb 2022 17:14:37 +0100 Subject: [PATCH] Add configuration for building wheels --- .github/workflows/build-wheels.yml | 69 +++++++++++++++++++++++++++++ .github/workflows/run-tests.yml | 24 ++++++++++ .gitignore | 2 + MANIFEST.in | 2 +- setup.py | 54 +++++++--------------- tess/tests.py => tests/test_tess.py | 35 ++++++++++++++- tox.ini | 23 ++++++++++ 7 files changed, 170 insertions(+), 39 deletions(-) create mode 100644 .github/workflows/build-wheels.yml create mode 100644 .github/workflows/run-tests.yml rename tess/tests.py => tests/test_tess.py (89%) create mode 100644 tox.ini diff --git a/.github/workflows/build-wheels.yml b/.github/workflows/build-wheels.yml new file mode 100644 index 0000000..cd5a530 --- /dev/null +++ b/.github/workflows/build-wheels.yml @@ -0,0 +1,69 @@ +name: Build for macos, manylinux and windows. Publish to pypi if a release. +on: [pull_request, push] + +env: + + CIBW_BUILD_VERBOSITY: 3 + CIBW_BUILD: 'cp37-* cp38-* cp39-* cp310-*' + CIBW_SKIP: '*-manylinux_i686 *-musllinux_* *-win32' + CIBW_BEFORE_BUILD: pip install cython + CIBW_TEST_REQUIRES: pytest numpy scipy + CIBW_TEST_COMMAND: pytest -s -v {project}/tests + +jobs: + build_wheels: + name: Build wheels on ${{ matrix.os }} + + if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-20.04, macos-latest, windows-latest] + + steps: + + - uses: actions/checkout@v2 + + - name: Build wheels + uses: pypa/cibuildwheel@v2.3.1 + + - uses: actions/upload-artifact@v2 + with: + path: ./wheelhouse/*.whl + + build_sdist: + name: Build source distribution + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + + - name: Build sdist + run: | + pip install cython + python setup.py sdist + + - uses: actions/upload-artifact@v2 + with: + path: dist/*.tar.gz + + upload_pypi: + needs: [build_wheels, build_sdist] + runs-on: ubuntu-latest + # upload to PyPI on every tag starting with 'v' + if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + + steps: + - uses: actions/download-artifact@v2 + with: + name: artifact + path: dist + + - name: Display structure of downloaded files + run: ls -R + working-directory: dist + + - uses: pypa/gh-action-pypi-publish@v1.4.2 + with: + user: __token__ + password: ${{ secrets.pypi_password }} diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml new file mode 100644 index 0000000..216bf95 --- /dev/null +++ b/.github/workflows/run-tests.yml @@ -0,0 +1,24 @@ +name: Run tests +on: [pull_request, push] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ['3.7', '3.8', '3.9', '3.10'] + + steps: + - uses: actions/checkout@v1 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install tox tox-gh-actions cython + + - name: Test with tox + run: tox diff --git a/.gitignore b/.gitignore index 928b6d6..006ee97 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ src/libvoro++.a *.o *.so *.pyc +.eggs tess/_voro.cpp examples/walls/torus examples/walls/tetrahedron @@ -37,3 +38,4 @@ __pycache__ /docs/.build /docs/.templates /docs/.static +.tox/ diff --git a/MANIFEST.in b/MANIFEST.in index 6c5742b..f371d87 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,4 +1,4 @@ include README.rst include LICENSE recursive-include src *.cc *.hh -include tess/_voro.pyx +include tess/_voro.pyx tess/_voro.cpp diff --git a/setup.py b/setup.py index 6b3b5f9..553050d 100644 --- a/setup.py +++ b/setup.py @@ -22,43 +22,22 @@ made with packings of spherical particles in mind, possibly with variable sizes. """ +import importlib +from setuptools import setup, Extension +from setuptools.command.sdist import sdist -from setuptools import setup -from distutils.extension import Extension -from distutils.command.sdist import sdist as _sdist -try: - from Cython.Build import cythonize -except ImportError: - cythonize = None - -extension_version = "0.3.1" - -if cythonize is not None: - print("Building with Cython.") - ext = cythonize( - [ - Extension( - "tess._voro", - sources=["tess/_voro.pyx", "src/voro++.cc"], - include_dirs=["src"], - language="c++", - ) - ] - ) -else: - print("Cython not found, using prebuilt file.") - ext = [ - Extension( +# setuptools transparently fallback to using the cpp file if cython is not available. See: +# https://setuptools.pypa.io/en/latest/userguide/distribution.html#distributing-extensions-compiled-with-cython +extension = Extension( "tess._voro", - sources=["tess/_voro.cpp", "src/voro++.cc"], + sources=["tess/_voro.pyx", "src/voro++.cc"], include_dirs=["src"], language="c++", - ) - ] +) -class sdist(_sdist): +class cython_sdist(sdist): # Set sdist to make the .cpp file # from http://stackoverflow.com/a/18418524/4190270 @@ -66,18 +45,14 @@ def run(self): # this is already imported, but the import might have failed. # If so, raise an ImportError now. from Cython.Build import cythonize - # Make sure the compiled Cython files in the distribution are up-to-date cythonize(["tess/_voro.pyx"]) - _sdist.run(self) - + sdist.run(self) -cmdclass = dict(sdist=sdist) # create the extension and add it to the python distribution setup( name="tess", - version=extension_version, author="Wendell Smith", author_email="wackywendell@gmail.com", description=("A module for calculating and analyzing Voronoi tessellations"), @@ -96,6 +71,11 @@ def run(self): ], packages=["tess"], package_dir={"tess": "tess"}, - ext_modules=ext, - cmdclass=cmdclass, + cmdclass={'sdist': cython_sdist}, + ext_modules=[extension], + use_scm_version=True, + setup_requires=["setuptools>=40.9.0", "wheel", "setuptools_scm"], + extras_require={ + 'tests': ["numpy", "scipy", "sphinx", "sphinx_rtd_theme"], + }, ) diff --git a/tess/tests.py b/tests/test_tess.py similarity index 89% rename from tess/tests.py rename to tests/test_tess.py index e182834..96a49fd 100644 --- a/tess/tests.py +++ b/tests/test_tess.py @@ -1,4 +1,4 @@ -from . import Container +from tess import Container from unittest import TestCase from math import sqrt @@ -10,6 +10,39 @@ scipy = None +def test_cell_methods(): + """Simple checks for the Cell method bindings + """ + cell_positions = [[1., 1., 1.], [2., 2., 2.]] + cell_radii = [0.2, 0.1] + + cells = Container( + cell_positions, radii=cell_radii, limits=(3,3,3), periodic=False + ) + + for i, cell in enumerate(cells): + + assert cell.id == i + assert np.allclose(cell.pos, cell_positions[i]) + assert np.isclose(cell.radius, cell_radii[i]) + assert cell.volume() > 0.0 + assert cell.max_radius_squared() > 0.0 + assert cell.total_edge_distance() > 0.0 + assert cell.surface_area() > 0.0 + assert cell.number_of_faces() > 0 + assert cell.number_of_edges() > 0 + assert len(cell.centroid()) == 3 + assert len(cell.vertex_orders()) > 0 + assert len(cell.vertices()) > 0 + assert len(cell.face_areas()) > 0 + assert len(cell.face_freq_table()) > 0 + assert len(cell.face_vertices()) > 0 + assert len(cell.face_perimeters()) > 0 + assert len(cell.normals()) > 0 + assert len(cell.neighbors()) > 0 + assert str(cell) == repr(cell) == f"" + + class LatticeTest: """A basic test for testing a lattice. The basic constants below need to be overwritten, as well as the setUp() function.""" diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..bdfa59b --- /dev/null +++ b/tox.ini @@ -0,0 +1,23 @@ +[tox] +envlist = + py{37,38,39,310} + +[gh-actions] +python = + 3.7: py37 + 3.8: py38 + 3.9: py39 + 3.10: py310 + +[testenv] +deps = + pytest +extras = tests +changedir = docs +commands = + pytest --doctest-modules {envsitepackagesdir}/tess + pytest {toxinidir}/tests/ {posargs} + make doctest +whitelist_externals = + cd + make