diff --git a/.github/workflows/cibuildwheel.yml b/.github/workflows/cibuildwheel.yml new file mode 100644 index 00000000..c0646bba --- /dev/null +++ b/.github/workflows/cibuildwheel.yml @@ -0,0 +1,66 @@ +name: Build + +on: + release: + types: + - published + +jobs: + build_wheels: + name: Build wheels on ${{ matrix.os }} + runs-on: ${{ matrix.os }} + strategy: + matrix: + # macos-13 is an intel runner, macos-14 is apple silicon + os: [ubuntu-latest, windows-latest, macos-13] + + steps: + - uses: actions/checkout@v4 + + - name: Build wheels + uses: pypa/cibuildwheel@v2.19.1 + env: + CIBW_SOME_OPTION: value + with: + package-dir: . + output-dir: wheelhouse + config-file: "{package}/pyproject.toml" + + - uses: actions/upload-artifact@v4 + with: + name: cibw-wheels-${{ matrix.os }}-${{ strategy.job-index }} + path: ./wheelhouse/*.whl + + build_sdist: + name: Build source distribution + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Build sdist + run: pipx run build --sdist + + - uses: actions/upload-artifact@v4 + with: + name: cibw-sdist + path: dist/*.tar.gz + upload_pypi: + needs: [build_wheels, build_sdist] + runs-on: ubuntu-latest + environment: pypi + permissions: + id-token: write + if: github.event_name == 'release' && github.event.action == 'published' + # or, alternatively, upload to PyPI on every tag starting with 'v' (remove on: release above to use this) + # if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v') + steps: + - uses: actions/download-artifact@v4 + with: + # unpacks all CIBW artifacts into dist/ + pattern: cibw-* + path: dist + merge-multiple: true + + - uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ diff --git a/pyproject.toml b/pyproject.toml index be643e65..43bffe92 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,10 +6,54 @@ requires = [ ] build-backend = "setuptools.build_meta" -# NOTE: overrides here are only used if CIBW_ENVIRONMENT is not set [tool.cibuildwheel] -environment = { PIP_CONSTRAINT="build-constraints.txt" } +build = "*" +skip = "pp* cp36* cp37* cp38*" +test-skip = "" +free-threaded-support = false -[[tool.cibuildwheel.overrides]] -select = "*-macosx_arm64" -environment = { PIP_CONSTRAINT="build-constraints.txt", BLIS_COMPILER="clang -arch arm64" } +archs = ["native"] + +build-frontend = "default" +config-settings = {} +dependency-versions = "pinned" +environment = {} +environment-pass = [] +build-verbosity = 0 + +before-all = "" +before-build = "" +repair-wheel-command = "" + +test-command = "" +before-test = "" +test-requires = [] +test-extras = [] + +container-engine = "docker" + +manylinux-x86_64-image = "manylinux2014" +manylinux-i686-image = "manylinux2014" +manylinux-aarch64-image = "manylinux2014" +manylinux-ppc64le-image = "manylinux2014" +manylinux-s390x-image = "manylinux2014" +manylinux-pypy_x86_64-image = "manylinux2014" +manylinux-pypy_i686-image = "manylinux2014" +manylinux-pypy_aarch64-image = "manylinux2014" + +musllinux-x86_64-image = "musllinux_1_2" +musllinux-i686-image = "musllinux_1_2" +musllinux-aarch64-image = "musllinux_1_2" +musllinux-ppc64le-image = "musllinux_1_2" +musllinux-s390x-image = "musllinux_1_2" + + +[tool.cibuildwheel.linux] +repair-wheel-command = "auditwheel repair -w {dest_dir} {wheel}" + +[tool.cibuildwheel.macos] +repair-wheel-command = "delocate-wheel --require-archs {delocate_archs} -w {dest_dir} -v {wheel}" + +[tool.cibuildwheel.windows] + +[tool.cibuildwheel.pyodide] diff --git a/tests/test_dotv.py b/tests/test_dotv.py index 018bc97e..b0b87feb 100644 --- a/tests/test_dotv.py +++ b/tests/test_dotv.py @@ -1,23 +1,20 @@ from __future__ import division from hypothesis import given, assume -from math import sqrt, floor +import numpy from blis_tests_common import * from blis.py import dotv -from blis.cy import NO_CONJUGATE, CONJUGATE @given( - ndarrays(min_len=10, max_len=100, - min_val=-100.0, max_val=100.0, dtype='float64'), - ndarrays(min_len=10, max_len=100, - min_val=-100.0, max_val=100.0, dtype='float64'), + ndarrays(min_len=10, max_len=100, min_val=-100.0, max_val=100.0, dtype="float64"), + ndarrays(min_len=10, max_len=100, min_val=-100.0, max_val=100.0, dtype="float64"), ) def test_memoryview_double_noconj(A, B): if len(A) < len(B): - B = B[:len(A)] + B = B[: len(A)] else: - A = A[:len(B)] + A = A[: len(B)] assume(A is not None) assume(B is not None) numpy_result = A.dot(B) @@ -26,18 +23,32 @@ def test_memoryview_double_noconj(A, B): @given( - ndarrays(min_len=10, max_len=100, - min_val=-100.0, max_val=100.0, dtype='float32'), - ndarrays(min_len=10, max_len=100, - min_val=-100.0, max_val=100.0, dtype='float32'), + ndarrays(min_len=10, max_len=100, min_val=-100.0, max_val=100.0, dtype="float32"), + ndarrays(min_len=10, max_len=100, min_val=-100.0, max_val=100.0, dtype="float32"), ) def test_memoryview_float_noconj(A, B): if len(A) < len(B): - B = B[:len(A)] + B = B[: len(A)] else: - A = A[:len(B)] + A = A[: len(B)] assume(A is not None) assume(B is not None) numpy_result = A.dot(B) result = dotv(A, B) - assert_allclose([numpy_result], result, atol=1e-3, rtol=1e-3) + # We want to also know the true(r) answer, if one of them is off. + A_float64 = A.astype(numpy.float64) + B_float64 = B.astype(numpy.float64) + numpy_result64 = A_float64.dot(B_float64) + blis_result64 = dotv(A_float64, B_float64) + try: + assert_allclose( + [numpy_result], + result, + atol=1e-3, + rtol=1e-3, + ) + except AssertionError as e: + # Probably better to make a combined message, but eh + print(f"Numpy 64bit result: {numpy_result64}") + print(f"blis 64bit result: {blis_result64}") + raise e