Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrate Python bindings to Nanobind. #92

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
Draft
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
7 changes: 3 additions & 4 deletions .github/workflows/all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ jobs:
pip install wheel
pip install -r dev-requirements.txt
- name: Build voyager locally
run: python setup.py develop
run: python -m pip install .
- name: Run tox tests
run: tox

Expand Down Expand Up @@ -209,7 +209,7 @@ jobs:
USE_ASAN: "1"
CC: clang
CXX: clang++
run: python setup.py develop
run: python -m pip install .
- name: Run tox tests with ASan loaded
# pytest can exit before all Python objects have been destroyed,
# so we tell ASan to ignore leaks.
Expand Down Expand Up @@ -333,9 +333,8 @@ jobs:
# on macOS and with Python 3.10: building NumPy from source fails without these options:
CIBW_ENVIRONMENT: NPY_BLAS_ORDER="" NPY_LAPACK_ORDER=""
CIBW_REPAIR_WHEEL_COMMAND_LINUX: pip install auditwheel-symbols && (auditwheel repair -w {dest_dir} {wheel} || auditwheel-symbols --manylinux 2010 {wheel})
# Use the minimum macOS deployment target that has C++17 support:
CIBW_TEST_SKIP: "*aarch64"
MACOSX_DEPLOYMENT_TARGET: "10.13"
MACOSX_DEPLOYMENT_TARGET: "10.14"
- uses: actions/upload-artifact@v3
with:
if-no-files-found: error
Expand Down
68 changes: 68 additions & 0 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
cmake_minimum_required(VERSION 3.15...3.27)
project(voyager LANGUAGES CXX)

# Warn if the user invokes CMake directly
if (NOT SKBUILD)
message(WARNING "\
This CMake file is meant to be executed using 'scikit-build-core'.
Running it directly will almost certainly not produce the desired
result. If you are a user trying to install this package, use the
command below, which will install all necessary build dependencies,
compile the package in an isolated environment, and then install it.
=====================================================================
$ pip install .
=====================================================================
If you are a software developer, and this is your own package, then
it is usually much more efficient to install the build dependencies
in your environment once and use the following command that avoids
a costly creation of a new virtual environment at every compilation:
=====================================================================
$ pip install nanobind scikit-build-core[pyproject]
$ pip install --no-build-isolation -ve .
=====================================================================
You may optionally add -Ceditable.rebuild=true to auto-rebuild when
the package is imported. Otherwise, you need to rerun the above
after editing C++ files.")
endif()

if (CMAKE_VERSION VERSION_LESS 3.18)
set(DEV_MODULE Development)
else()
set(DEV_MODULE Development.Module)
endif()

find_package(Python 3.10 COMPONENTS Interpreter ${DEV_MODULE})

# Import nanobind through CMake's find_package mechanism
find_package(nanobind CONFIG REQUIRED)


if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()

# Detect the installed nanobind package and import it into CMake
execute_process(
COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE nanobind_ROOT)
find_package(nanobind CONFIG REQUIRED)

# Check the USE_ASAN environment variable, and if set to 1, enable AddressSanitizer
if (DEFINED ENV{USE_ASAN} AND "$ENV{USE_ASAN}" STREQUAL "1")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
endif()

nanobind_add_module(
voyager_ext
# Target the stable ABI for Python 3.12+, which reduces
# the number of binary wheels that must be built. This
# does nothing on older Python versions
NB_STATIC STABLE_ABI LTO FREE_THREADED
# Sources:
src/bindings.cpp
)

# Install directive for scikit-build-core
install(TARGETS voyager_ext LIBRARY DESTINATION voyager)
2 changes: 0 additions & 2 deletions python/dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
-r test-requirements.txt
numpy
pybind11
pybind11-stubgen==0.16.2
ruff
psutil
mypy
Expand Down
54 changes: 48 additions & 6 deletions python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,51 @@
[build-system]
requires = [
"setuptools>=42",
"wheel",
"numpy>=1.10.0",
"pybind11>=2.0",
requires = ["scikit-build-core >=0.4.3", "nanobind >=1.3.2"]
build-backend = "scikit_build_core.build"

[project]
name = "voyager"
version = "2.0.10"
description = "Easy-to-use, fast, simple multi-platform approximate nearest-neighbor search library."
readme = "../README.md"
requires-python = ">=3.8"
authors = [
{ name = "Peter Sobot", email = "[email protected]" },
]
classifiers = [
"Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: Apache Software License",
"Operating System :: MacOS",
"Operating System :: Microsoft :: Windows",
"Operating System :: POSIX :: Linux",
"Programming Language :: C++",
"Programming Language :: Python",
"Topic :: Database :: Database Engines/Servers",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
# Optional: runtime dependency specification
# dependencies = [ "cryptography >=41.0" ]

[project.urls]
Homepage = "https://github.com/spotify/voyager"

[tool.scikit-build]
# Protect the configuration against future changes in scikit-build-core
minimum-version = "0.4"

# Setuptools-style build caching in a local directory
build-dir = "build/{wheel_tag}"

# Build stable ABI wheels for CPython 3.12+
wheel.py-api = "cp312"

[tool.ruff]
line-length = 120

build-backend = "setuptools.build_meta"
# Needed for full C++17 support on macOS
[tool.cibuildwheel.macos.environment]
MACOSX_DEPLOYMENT_TARGET = "10.14"
Empty file removed python/scripts/__init__.py
Empty file.
Loading
Loading