annoy icon indicating copy to clipboard operation
annoy copied to clipboard

Add Python 3.13 support and deploy a compiled wheel to PyPI

Open benglewis opened this issue 7 months ago • 8 comments

Add support for Python 3.13 and configure deployment to PyPI.

  • CI Configuration: Update .github/workflows/ci.yml to include Python version 3.13 in the python-version matrix.
  • Setup.py: Update setup.py to list supported Python versions up to 3.13 in the classifiers list.
  • Tox Configuration: Update tox.ini to include Python 3.13 in the envlist.
  • Publish Workflow: Add a new GitHub Actions workflow in .github/workflows/publish.yml for publishing the package to PyPI.

For more details, open the Copilot Workspace session.

benglewis avatar May 04 '25 15:05 benglewis

Side note: I would be happy to implement Trusted Publishing for publishing to PyPI instead if you prefer

benglewis avatar May 04 '25 15:05 benglewis

Nice! But I don't think the publish step will work unless you have proper credentials set up?

erikbern avatar May 04 '25 18:05 erikbern

@erikbern Correct. It either needs the secret to be configured in GitHub Actions or I can change the code to use the Trusted Publishing option if you configure that on the PyPI side (which is what I recommend and we use since it is more secure - it restricts only GitHub Actions from the GitHub repository to publish to PyPI via OIDC). Which would you prefer? 🙏

benglewis avatar May 05 '25 09:05 benglewis

This workflow would make sense for a pure Python project, but not for a compiled one: I don’t think we should go for a single wheel built for x86_64 linux glibc if we can have all the platforms for no cost.

State-of-the-art for compiled wheels published from GitHub is cibuildwheel’s GitHub action, which is very easy to set up!

Please update the workflow for that one, it’ll make the package much more useful!

flying-sheep avatar May 17 '25 11:05 flying-sheep

@flying-sheep That makes sense. I'll try to remember to update the next time that I am in front of computer

benglewis avatar May 17 '25 11:05 benglewis

As per @flying-sheep 's suggestion, I have switched the workflow to use cibuildwheel

benglewis avatar May 25 '25 11:05 benglewis

Wonderful!

@erikbern could we get a release with this soon? @benglewis did you test this? For my Rust-backed Python packages I usually have to disable 1–3 more exotic platforms, because they don’t build. But maybe that’s not the case for pure C++ code like here.

flying-sheep avatar May 26 '25 08:05 flying-sheep

@flying-sheep I did a quick test now in a GitHub Codespace and found a little bug that with the help of ChatGPT I was able to resolve. It looks like builds for all platforms works now.

@erikbern How can I help you get this merged?

benglewis avatar May 28 '25 12:05 benglewis

@benglewis I wanted to give this a proper test with (trusted) publishing, and noticed that while everything built for macos and windows, the final step of "publish package" fails because its only meant to run on linux.

Run >&2 echo This action is only able to run under GNU/Linux environments
  >&2 echo This action is only able to run under GNU/Linux environments
  exit 1
  shell: C:\Program Files\Git\bin\bash.EXE -eEuo pipefail {0}
  env:
    pythonLocation: C:\hostedtoolcache\windows\Python\3.13.3\x64
    PKG_CONFIG_PATH: C:\hostedtoolcache\windows\Python\3.13.3\x64/lib/pkgconfig
    Python_ROOT_DIR: C:\hostedtoolcache\windows\Python\3.13.3\x64
    Python2_ROOT_DIR: C:\hostedtoolcache\windows\Python\3.13.3\x64
    Python3_ROOT_DIR: C:\hostedtoolcache\windows\Python\3.13.3\x64

a fix: move publishing out to a separate step

  publish:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Download all artifacts
        uses: actions/download-artifact@v4
        with:
          pattern: cibw-wheels-*
          path: dist
          merge-multiple: true

      - name: Publish package
        uses: pypa/gh-action-pypi-publish@release/v1
        if: startsWith(github.ref, 'refs/tags/v') && github.event_name == 'push'
        # with:
        #   password: ${{ secrets.PYPI_API_TOKEN }}

though now there's an error due to markup. oh the things testing reveals... image

PR with fixes: https://github.com/benglewis/annoy/pull/1 (including ensuring sdist is uploaded) workflow file with end-to-end success (uploads all artifacts to pypi: https://github.com/mathematicalmichael/annoy/actions/runs/15769257949/workflow)

mathematicalmichael avatar Jun 19 '25 20:06 mathematicalmichael

quick update:

  • ~~windows build issues handled by removing an image that's currently not working the README.rst anyway~~
  • ~~windows build issues handled by a bit of regex cleanup of README.rst in setup.py~~
  • windows build issues handled by switching from codecs to open which handles file encoding better
  • tested linux-aarch64 / arm64 wheels (as well as amd64), added them to linux build options in https://github.com/benglewis/annoy/pull/1

demonstration of publishing to pypi under my own namespace as a test: https://pypi.org/project/annoy-mm/1.17.4rc2/#files the github action that published it: https://github.com/mathematicalmichael/annoy/actions/runs/15985163036

  • 12 for windows (x86)
  • 12 for macOS (arm)
  • 48 manylinux (24 x86, 24 arm)
  • 24 musllinux (12 x86, 12 arm)

ive checked that I can pip install annoy-mm on python debian and alpine base images on both arm64 and amd64. literally the only thing I can think of missing is Windows on ARM which... I mean... can we leave that for later?

mathematicalmichael avatar Jun 30 '25 23:06 mathematicalmichael

Python 3.14 came out this month. Maybe it makes sense to update this to build wheels that are compatible with Python 3.14 as well?

ngoldbaum avatar Oct 22 '25 19:10 ngoldbaum

@ngoldbaum Once I merge @mathematicalmichael 's changes, then I can update this PR with Python 3.14 and hopefully @erikbern can then merge this :)

benglewis avatar Oct 23 '25 06:10 benglewis

Merging this with https://github.com/benglewis/annoy/pull/1 (and added 3.14 support) would be awesome, but I think ideally every binary package should instead build ABI3 / stable ABI wheels. Stable ABI wheels can be installed with any Python version ≥ the ABI version you targeted (e.g. <name>-<version>-cp311-abi3-<platform>.whl can be used by any Python version ≥3.11), which has several advantages:

  1. it’s future-compatible (no more updating your package on PyPI just to have wheels for the newest Python version)
  2. you only need to adjust CI when you need some new Python ABI feature, never to include new Python version
  3. you need fewer build jobs / need to build fewer wheels (only one per platform instead of one per platform per python version)

flying-sheep avatar Oct 23 '25 06:10 flying-sheep

I agree abi3 wheels are nice, but one note is that the free-threaded build does not (yet) support the stable ABI. So cp314-cp314t wheels are still needed. IMO supporting the free-threaded build shouldn't be blocked on setting up abi3 wheels, which free-threading suppory can't benefit from.

ngoldbaum avatar Oct 23 '25 15:10 ngoldbaum

@erikbern Please take a look at this again 🙏 It would be great to put this in

benglewis avatar Oct 29 '25 11:10 benglewis

Thanks!

erikbern avatar Oct 29 '25 14:10 erikbern

I'll poke at opening a followup for 3.14 and 3.14t support.

ngoldbaum avatar Oct 29 '25 14:10 ngoldbaum