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.20.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.20-cp314-cp314-win_amd64.whl (651.2 kB view details)

Uploaded CPython 3.14Windows x86-64

pymergetic_easybind-0.3.20-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.20-cp313-cp313-win_amd64.whl (638.5 kB view details)

Uploaded CPython 3.13Windows x86-64

pymergetic_easybind-0.3.20-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.20-cp312-cp312-win_amd64.whl (639.4 kB view details)

Uploaded CPython 3.12Windows x86-64

pymergetic_easybind-0.3.20-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.20-cp311-cp311-win_amd64.whl (640.6 kB view details)

Uploaded CPython 3.11Windows x86-64

pymergetic_easybind-0.3.20-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.20.tar.gz.

File metadata

  • Download URL: pymergetic_easybind-0.3.20.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.20.tar.gz
Algorithm Hash digest
SHA256 bcc139fba718355cc924e3969cf106eac3b3ed8565ae1aa9b4084269ab7eeb6b
MD5 034380ad61b5955a22f659bba1295323
BLAKE2b-256 355248ad855a751409a383c038c0636b5b94c4e25c289db17e0eabffd7551bf8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.20-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 5445077f51ec3e0a5c961092a0d2d47ff6e33a53568778f30662ce2a2c1540d6
MD5 3784be207adf30a075a05018f1baa7cd
BLAKE2b-256 45fc0b13944b17427f69ef1e6cbb2ec5b029119946e81dec3ab495ac0e66ba6f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.20-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 b9e2082938b3ac2d11bd4381dd5d797ff9afbc60a253d2975512c54ffcd51ffa
MD5 96ce118c47a9131a9953b581693813b7
BLAKE2b-256 c50683395bfcd1a738eba4bf4e1fc196b68146c52e11fe2698ef3c4889fe7bf2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.20-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 d5e740dc94cae89a3fe7ce75f090db5b7e401294b661a688793e52c383bf51f4
MD5 5fef1636553160a88177ff52e7077d73
BLAKE2b-256 1af20c422d6cf85cd98bb3edf511a8191c36df200682e6bb8cd12a6bdf613d32

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.20-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 116e3dd3b2c94dc178164fa9d28ed78bb12efbdc47f5791c5c29d8c466dedd1d
MD5 172ed81754cdb9646b208989fd3c5981
BLAKE2b-256 cd06523f56f41a9a56a58536f52b6da3c1d94cd98284df3eba43a9c5db241a4d

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.20-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 64df5ea0def61ab35abd8cc817b5426631c7e760d3cca099979aa0dd0f2ecefa
MD5 ee10edc965487de890beec517a040ef8
BLAKE2b-256 4c1ad21931c6d90897865f988906028d3d3317ffa4fc50bf168959f188bf25b4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.20-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 2ae5b54a78a132ca0c4e44cf42a1f0025b2293f847eb71b5e479ff3b0840e3ed
MD5 394e958364da38374cc14377b371a497
BLAKE2b-256 3b9a7c8d9c66810ef463e498cbb84d8fe06402390600f5fda9ae2f9471757c12

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.20-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 0745f814c9c5ec2b71831c85071c2aedb0ac4e2bf3f37f75bafd09992a775057
MD5 cf7dc1e4caf3812f0edabcb5aaeb5a2b
BLAKE2b-256 a2517df9073e0f3424ad2655971863bea06c64851937030d4cfa3de211347c39

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for pymergetic_easybind-0.3.20-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 e06d2cbf707295ab6b7989e4569c0c42c1977ef40c432f6d532ed3acfce01a3d
MD5 02184c710a8f6bbc27ed858a9daf5c54
BLAKE2b-256 188fadac27696d0af4d6e40ffaaf95b9b8c161e8fcea3f19ec681e87b8b0f767

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