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.18.tar.gz (53.5 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.18-cp314-cp314-win_amd64.whl (651.2 kB view details)

Uploaded CPython 3.14Windows x86-64

pymergetic_easybind-0.3.18-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (295.9 kB view details)

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

pymergetic_easybind-0.3.18-cp313-cp313-win_amd64.whl (638.5 kB view details)

Uploaded CPython 3.13Windows x86-64

pymergetic_easybind-0.3.18-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (295.9 kB view details)

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

pymergetic_easybind-0.3.18-cp312-cp312-win_amd64.whl (639.4 kB view details)

Uploaded CPython 3.12Windows x86-64

pymergetic_easybind-0.3.18-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (295.8 kB view details)

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

pymergetic_easybind-0.3.18-cp311-cp311-win_amd64.whl (640.6 kB view details)

Uploaded CPython 3.11Windows x86-64

pymergetic_easybind-0.3.18-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (296.3 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.18.tar.gz.

File metadata

  • Download URL: pymergetic_easybind-0.3.18.tar.gz
  • Upload date:
  • Size: 53.5 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.18.tar.gz
Algorithm Hash digest
SHA256 2dcf8790cf90a882a159492a6ab29bec27e6750bf01ebef0770ded602f05e1c4
MD5 e871d7ffa5ecf81daaf5364d8ee2033e
BLAKE2b-256 c5878dc9309757e90aa8544beac59a9bcb9a169f1f303c0c4cff92244f5efd72

See more details on using hashes here.

File details

Details for the file pymergetic_easybind-0.3.18-cp314-cp314-win_amd64.whl.

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.18-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 6f6f05af8f9530405b576fbd3f64f5a7c3a545259e1c6fb0e2b6076cf8978d5d
MD5 639d317f6e54580f1ba8be68344d1072
BLAKE2b-256 77973aee1344964cbd0206423ad727831abf2174ca007026e4d460dd78be62f5

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.18-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 556da85a669a4d52d7ee92d49297b4dc5f9cb441a4b8691f52decda536843651
MD5 fbf24c9ab15271028921309869ca162e
BLAKE2b-256 f9ca6e2b019dd3e25202f92fcf4bf549c4b53a274f59babbfd48706419edb9f1

See more details on using hashes here.

File details

Details for the file pymergetic_easybind-0.3.18-cp313-cp313-win_amd64.whl.

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.18-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 e5a89c367094f21a3492ef5b76fa27451d85841d40e68ed14d0da9a912126aea
MD5 b66bcebc7b838fc27040b23469bdecb8
BLAKE2b-256 0c54f91fd5646126b1befcc0a9fe5d0c9ef30502ed130c441d187c12dd8aa0b1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.18-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 d1f804ca886b480bb8dad5814564dffd9970f4e05bdfe172b14d261493891992
MD5 da3d58d9a1e68ec4d947b52ef9e23588
BLAKE2b-256 9666aa650b7c615aeaf762dd67a2f91928e6ea8f4c7e7857b24321bd861f0232

See more details on using hashes here.

File details

Details for the file pymergetic_easybind-0.3.18-cp312-cp312-win_amd64.whl.

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.18-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 c7162032a5433d0b105938b37a9dbc391391f7376ed62238d6ea63566db61bf4
MD5 903707177aee56627abd934308f755a8
BLAKE2b-256 6060f52469167f21c34b2c19b16006af74fd8b457fa504f20b5886da9c038d6d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.18-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ed3230cd33c406ba58f5570013262a08b7de235a3e329676943f8a05131416a0
MD5 e49e89ab4c0650bebfc71dcbad0690b5
BLAKE2b-256 0f39212a91eba20132ff5cf2f597adcbf4e49def09b9182092d9d9864f21e90b

See more details on using hashes here.

File details

Details for the file pymergetic_easybind-0.3.18-cp311-cp311-win_amd64.whl.

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.18-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 576758574c18a6941dad9003b6318cd5cb3cb05f0b4188035c41f7d69ef0dacb
MD5 8035609161eec0087c7849531f955c10
BLAKE2b-256 cb5fe8889c1b399b49467176279a8399af2195519dbc3ce8b4b964f691b79ca3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.18-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 15c8775b5979b651d573bdebfc51b6e9a229a87e4943c6ea02ad92cd636975dc
MD5 74858d5c2507abc8745d4ba092c5e876
BLAKE2b-256 8ccaf6adaa1a5eed6a3546a25867b1f2d3b56e2117324aa01a213a55a66d6e29

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