Skip to content

Commit

Permalink
Migrate to Nanobind.
Browse files Browse the repository at this point in the history
  • Loading branch information
psobot committed Oct 8, 2024
1 parent ca1b9e9 commit 95736ce
Show file tree
Hide file tree
Showing 10 changed files with 362 additions and 1,351 deletions.
62 changes: 62 additions & 0 deletions python/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
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)

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)
47 changes: 41 additions & 6 deletions python/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,9 +1,44 @@
[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-backend = "setuptools.build_meta"
# Build stable ABI wheels for CPython 3.12+
wheel.py-api = "cp312"
180 changes: 0 additions & 180 deletions python/setup.py

This file was deleted.

38 changes: 19 additions & 19 deletions python/src/PythonFileLike.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@
#include <optional>
#include <string>

namespace py = pybind11;
namespace nb = nanobind;

namespace PythonException {
// Check if there's a Python exception pending in the interpreter.
inline bool isPending() {
py::gil_scoped_acquire acquire;
nb::gil_scoped_acquire acquire;
return PyErr_Occurred() != nullptr;
}

// If an exception is pending, raise it as a C++ exception to break the current
// control flow and result in an error being thrown in Python later.
inline void raise() {
py::gil_scoped_acquire acquire;
nb::gil_scoped_acquire acquire;

if (PyErr_Occurred()) {
py::error_already_set existingError;
nb::python_error existingError;
throw existingError;
}
}
Expand All @@ -44,47 +44,47 @@ inline void raise() {
*/
class PythonFileLike {
public:
PythonFileLike(py::object fileLike) : fileLike(fileLike) {}
PythonFileLike(nb::object fileLike) : fileLike(fileLike) {}

std::string getRepresentation() {
py::gil_scoped_acquire acquire;
return py::repr(fileLike).cast<std::string>();
nb::gil_scoped_acquire acquire;
return nb::cast<std::string>(nb::repr(fileLike));
}

std::optional<std::string> getFilename() {
// Some Python file-like objects expose a ".name" property.
// If this object has that property, return its value;
// otherwise return an empty optional.
py::gil_scoped_acquire acquire;
nb::gil_scoped_acquire acquire;

if (py::hasattr(fileLike, "name")) {
return py::str(fileLike.attr("name")).cast<std::string>();
if (nb::hasattr(fileLike, "name")) {
return nb::cast<std::string>(nb::str(fileLike.attr("name")));
} else {
return {};
}
}

bool isSeekable() {
py::gil_scoped_acquire acquire;
return fileLike.attr("seekable")().cast<bool>();
nb::gil_scoped_acquire acquire;
return nb::cast<bool>(fileLike.attr("seekable")());
}

long long getPosition() {
py::gil_scoped_acquire acquire;
return fileLike.attr("tell")().cast<long long>();
nb::gil_scoped_acquire acquire;
return nb::cast<long long>(fileLike.attr("tell")());
}

bool setPosition(long long pos) {
py::gil_scoped_acquire acquire;
if (fileLike.attr("seekable")().cast<bool>()) {
nb::gil_scoped_acquire acquire;
if (nb::cast<bool>(fileLike.attr("seekable")())) {
fileLike.attr("seek")(pos);
}

return fileLike.attr("tell")().cast<long long>() == pos;
return nb::cast<long long>(fileLike.attr("tell")()) == pos;
}

py::object getFileLikeObject() { return fileLike; }
nb::object getFileLikeObject() { return fileLike; }

protected:
py::object fileLike;
nb::object fileLike;
};
Loading

0 comments on commit 95736ce

Please sign in to comment.