Skip to main content

Self-registering nanobind helpers (import as pymergetic.easybind)

Project description

easybind

Simple self-registering helpers for distributed nanobind bindings.

Install

pip install pymergetic-easybind

Platforms: PyPI ships manylinux (glibc 2.28+) and Windows amd64 wheels for CPython 3.11–3.14. macOS is not built in CI yet. On unsupported platforms pip may fall back to the sdist and require a local C++ toolchain.

import pymergetic.easybind
from pymergetic.easybind import sample  # optional demo module

PyPI project: pymergetic-easybind (install name). Import: pymergetic.easybind.

Version: Set by Git tags at build time (v0.1.0, …) via setuptools-scm; see RELEASING.md. At runtime, pymergetic.easybind._version.__version__ is written when the wheel is built (or use importlib.metadata.version("pymergetic-easybind")).

Local dev / clangd

An editable install configures CMake under ./build/ and generates build/compile_commands.json, which clangd picks up via .clangd — same database as the Python build, no second configure step:

uv pip install -e .    # or: pip install -e .

If you need compile_commands.json without pip, run scripts/clangd-update.sh (plain cmake -S . -B build …).

Python layer

The Python package is implemented as native extensions. It exposes:

  • pymergetic.easybind (core helpers and macros)
  • pymergetic.easybind.module (module tree API)
  • pymergetic.easybind.sample (demo bindings)

Build-time SDK

Installed wheels ship CMake helpers under pymergetic/easybind/cmake/:

  • easybind_pip.cmakeeasybind_pip_setup() finds Python, nanobind (pip), libeasybind, and include roots for #include <pymergetic/easybind/...>, then pulls in easybind_dependencies.cmake. Helpers: easybind_pip_link_magic_enum(target), easybind_pip_set_rpath_next_to_easybind(target easybind_pkg_dir).
  • easybind_dependencies.cmake — pins nanobind, magic_enum, reflect-cpp (same tags as this repo). Use easybind_fetch_third_party_deps() to pull all three, or easybind_fetch_nanobind() / easybind_fetch_magic_enum() / easybind_fetch_reflect_cpp() when you only need a subset (e.g. pip already provides nanobind, so call only easybind_fetch_magic_enum()).

Typical consumer bootstrap:

find_package(Python REQUIRED COMPONENTS Interpreter Development.Module)
execute_process(COMMAND "${Python_EXECUTABLE}" -c
  "import pathlib, pymergetic.easybind; print(pathlib.Path(pymergetic.easybind.__file__).resolve().parent / 'cmake' / 'easybind_pip.cmake')"
  OUTPUT_VARIABLE _eb_pip OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY)
include("${_eb_pip}")
easybind_pip_setup()
easybind_fetch_magic_enum()   # if you include easybind headers that need magic_enum

When developing inside this repository, easybind_add_extension(...) is defined in the top-level CMakeLists.txt (not shipped in the wheel).

Devtools (release / pin bumps)

Implemented in pymergetic.common.devtools (pymergetic-common). Install via pymergetic-easybind (depends on common) or uv sync.

pymergetic-pin-pyproject --project-root packages/easybind --dry-run
pymergetic-release-tag --project-root packages/easybind --dry-run
pymergetic-wait-pypi --project-root packages/easybind

See pymergetic-common RELEASING.md and from pymergetic.common.devtools import ….

Core idea

  • Each namespace/module defines a ModuleNode and a bind callback.
  • The module entry point calls apply_init to run the callback and recurse.
  • Submodules are created on demand and registered in sys.modules.
  • Shared-object modules are marked so recursion stops at their boundary.
  • A minimal sample module lives at pymergetic.easybind.sample.

Developer note: layout rules

  • __init__.cpp marks the Python boundary (NB_MODULE) for a package/module.
  • node.cpp/.hpp is the pure C++ module-tree core.
  • ns_module.hpp defines the EASYBIND_NS_MODULE* macros.
  • Directory layout mirrors namespaces and Python modules.

Smallest possible example

1) Define a C++ type (normal code)

#pragma once

#include <string>

struct PeerInfo {
    std::string peer_id;
    int transport = 0;
};

2) Bind it in a separate file (module node)

#include <pymergetic/easybind/bind.hpp>

struct PeerInfo;  // forward declare or include the header

EASYBIND_NS_MODULE(my_pkg, m, false, {
    nanobind::class_<PeerInfo>(m, "PeerInfo")
        .def(nanobind::init<>())
        .def_rw("peer_id", &PeerInfo::peer_id)
        .def_rw("transport", &PeerInfo::transport);
});

3) Module entry point (shared-object boundary)

Use this only for the package that has its own .so and NB_MODULE entry point. Do not pair it with EASYBIND_NS_MODULE for the same my_pkg name. If you need to add bindings from another file, use EASYBIND_NS_MODULE_EXTEND to extend the same module node instead.

#include <pymergetic/easybind/bind.hpp>

EASYBIND_NS_MODULE_SHARED_OBJECT(my_pkg, my_pkg, m, true, {
    m.doc() = "my_pkg module";
});

4) Extend from another file

#include <pymergetic/easybind/bind.hpp>

EASYBIND_NS_MODULE_EXTEND(my_pkg, m, {
    m.def("ping", [] { return "pong"; });
});

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

pymergetic_easybind-0.3.10.tar.gz (54.1 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

pymergetic_easybind-0.3.10-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (296.1 kB view details)

Uploaded CPython 3.14manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pymergetic_easybind-0.3.10-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (296.1 kB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pymergetic_easybind-0.3.10-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (296.1 kB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

pymergetic_easybind-0.3.10-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (296.5 kB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

File details

Details for the file pymergetic_easybind-0.3.10.tar.gz.

File metadata

  • Download URL: pymergetic_easybind-0.3.10.tar.gz
  • Upload date:
  • Size: 54.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for pymergetic_easybind-0.3.10.tar.gz
Algorithm Hash digest
SHA256 95f0ec17c0f83654cd2b432020cf63fa9c4d5748c83e53ff12d1beea5b97cb18
MD5 cd0a3e6307600bf185cc7d21a4ba3a1e
BLAKE2b-256 83c1cb4140fbf41e4cc6b6e8dc6de131f497d9edfcaaccffc78fea0597859c75

See more details on using hashes here.

File details

Details for the file pymergetic_easybind-0.3.10-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.10-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 73ccae5200b00b69375cf97a8e17e051a42a41ed6c1a6439381038d35b6014e7
MD5 cd9e174f60074bdc007639e1d69a4d27
BLAKE2b-256 33a66a9f5c50d3f162eaf3e21d33bbaf19917422a04a7ca55706feb46074c9e3

See more details on using hashes here.

File details

Details for the file pymergetic_easybind-0.3.10-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.10-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e963444a69e5c8a5b7bd4d8b5517c84c269e849c572391cae626163d2267984a
MD5 18ecf8336c0b4d7e3edc90c71d18de08
BLAKE2b-256 6c9dbefb34b0de4ee5146cc933d6314fbef550c14cf26606fbb403ce9aeb82f3

See more details on using hashes here.

File details

Details for the file pymergetic_easybind-0.3.10-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.10-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 74590fe08befba33dc08a67eb11598536d943b0764df5adab53e793442c6331f
MD5 e55493b65efebecb31726a48925d1d64
BLAKE2b-256 a8173f81fed9672e792f14b90bef6ebac350dcd0efa7cebf5c46010b2944ee13

See more details on using hashes here.

File details

Details for the file pymergetic_easybind-0.3.10-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.10-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 a443ac26fca04878be3cce7ddb8791c5cfe7e537beb5f9986e8d1ec724a13bc5
MD5 feded63ab8b5fdf2bdba8a3d7473a3a4
BLAKE2b-256 24639b396165c3bb541e2fab7e8d795f3941725a06fcb51595d2d29bbd5d7375

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page