Skip to content
Merged
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
2 changes: 1 addition & 1 deletion VERSION.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.20260226.0
0.20260302.0
2 changes: 1 addition & 1 deletion cmake/packages.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ function(retrieve_package PACKAGE_NAME PACKAGE_VERSION PACKAGE_REPOSITORY RELEAS
if("${PACKAGE_NAME}" STREQUAL "libCellML")
#---GRY--- USE THIS VERSION OF libCellML WHICH CORRESPONDS TO PR #1256 UNTIL IT GETS MERGED IN.

set(PACKAGE_URL "https://github.com/agarny/${PACKAGE_REPOSITORY}/releases/download/7cc5bea/${PACKAGE_FILE}")
set(PACKAGE_URL "https://github.com/agarny/${PACKAGE_REPOSITORY}/releases/download/387274c/${PACKAGE_FILE}")
endif()

set(ATTEMPT 1)
Expand Down
7 changes: 5 additions & 2 deletions extern/nanobind/cmake/nanobind-config.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -500,14 +500,16 @@ function(nanobind_sanitizer_preload_env env_var)
get_target_property(options ${tgt} ${prop})
if(options)
foreach(opt ${options})
if(opt MATCHES "-fsanitize=([^ ]+)")
if(opt MATCHES "-fsanitize=([^ >]+)")
list(APPEND san_flags "${CMAKE_MATCH_1}")
endif()
endforeach()
endif()
endforeach()
endforeach()

list(REMOVE_DUPLICATES san_flags)

# Parse sanitizer flags
foreach(flag ${san_flags})
string(REPLACE "\"" "" flag "${flag}")
Expand All @@ -517,6 +519,8 @@ function(nanobind_sanitizer_preload_env env_var)
list(APPEND detected_san "asan")
elseif(san MATCHES "^(thread|tsan)$")
list(APPEND detected_san "tsan")
elseif(san MATCHES "^(realtime)$")
list(APPEND detected_san "rtsan")
elseif(san MATCHES "^(undefined|ubsan)$")
list(APPEND detected_san "ubsan")
endif()
Expand All @@ -525,7 +529,6 @@ function(nanobind_sanitizer_preload_env env_var)
endforeach()

if (detected_san)
list(REMOVE_DUPLICATES detected_san)
set(libs "")

foreach(san ${detected_san})
Expand Down
13 changes: 11 additions & 2 deletions extern/nanobind/docs/api_core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1268,6 +1268,15 @@ Wrapper classes
// Now do something ...
});

.. cpp:class:: memoryview: public object

Wrapper class representing Python ``memoryview`` instances.

.. cpp:function:: memoryview(handle h)

Attempt to create a ``memoryview`` Python object from an object. Analogous
to the expression ``memoryview(h)`` in Python.

.. cpp:class:: ellipsis: public object

Wrapper class representing a Python ellipsis (``...``) object.
Expand Down Expand Up @@ -2641,8 +2650,8 @@ Class binding

Bind the enumeration of type `T` to the identifier `name` within the
scope `scope`. The variable length `extra` parameter can be used to pass
a docstring and other :ref:`enum binding annotations
<enum_binding_annotations>` (currently, only :cpp:class:`is_arithmetic` is supported).
a docstring and
:ref:`enum binding annotations <enum_binding_annotations>`.

.. cpp:function:: enum_ &value(const char * name, T value, const char * doc = nullptr)

Expand Down
4 changes: 2 additions & 2 deletions extern/nanobind/docs/bazel.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ in your MODULE.bazel file:
# Place this in your MODULE.bazel file.
# The major version of nanobind-bazel is equal to the version
# of the internally used nanobind.
# In this case, we are building bindings with nanobind v2.11.0.
bazel_dep(name = "nanobind_bazel", version = "2.11.0")
# In this case, we are building bindings with nanobind v2.12.0.
bazel_dep(name = "nanobind_bazel", version = "2.12.0")

To instead use a development version from GitHub, you can declare the
dependency as a ``git_override()`` in your MODULE.bazel:
Expand Down
33 changes: 31 additions & 2 deletions extern/nanobind/docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,35 @@ case, both modules must use the same nanobind ABI version, or they will be
isolated from each other. Releases that don't explicitly mention an ABI version
below inherit that of the preceding release.

Version 2.12.0 (Feb 25, 2025)
-----------------------------

- Added :cpp:class:`nb::memoryview` that wraps the Python ``memoryview`` type.
(PR `#1291 <https://github.com/wjakob/nanobind/pull/1291>`__).

- Made stub generation compatible with the Realtime Sanitizer (RTSan)
from Clang 20.
(PR `#1285 <https://github.com/wjakob/nanobind/pull/1285>`__).

- Fixed a use-after-free when calling functions after their module has been
deleted. The internals state is now reference-counted with references held by
modules, functions, and types. This also fixes memory leaks reported in issue
`#957 <https://github.com/wjakob/nanobind/issues/957>`__.
(PR `#1287 <https://github.com/wjakob/nanobind/pull/1287>`__).

- Fixed two regressions from v2.11.0 related to the implicit ``std::optional``
:cpp:func:`.none() <arg::none>` annotation: an off-by-one error that applied
the annotation to the wrong argument for methods, and a missing ``convert``
flag that silently disabled implicit type conversions.
(issues `#1281 <https://github.com/wjakob/nanobind/issues/1281>`__,
`#1293 <https://github.com/wjakob/nanobind/issues/1293>`__,
commits `ed7ab31
<https://github.com/wjakob/nanobind/commit/ed7ab31f5ffe313b2ca945573e29112ea5e475b2>`__,
`1f96278
<https://github.com/wjakob/nanobind/commit/1f96278c09ec1f7110105f5e2e3dbd2f08dc66a4>`__).

- ABI version 19.

Version 2.11.0 (Jan 29, 2026)
-----------------------------

Expand Down Expand Up @@ -92,7 +121,7 @@ Version 2.11.0 (Jan 29, 2026)
(PR `#1255 <https://github.com/wjakob/nanobind/pull/1255>`__).

Version 2.10.2 (Dec 10, 2025)
----------------------------
-----------------------------

- Fixes a regression that broke compilation on 32-bit architectures.
(PR `#1239 <https://github.com/wjakob/nanobind/pull/1239>`__).
Expand Down Expand Up @@ -564,7 +593,7 @@ Version 2.3.0

There is no version 2.3.0 due to a deployment mishap.

- Added casters for `Eigen::Map<Eigen::SparseMatrix<...>` types from the `Eigen library
- Added casters for ``Eigen::Map<Eigen::SparseMatrix<...>>`` types from the `Eigen library
<https://eigen.tuxfamily.org/index.php?title=Main_Page>`__. (PR `#782
<https://github.com/wjakob/nanobind/pull/782>`_).

Expand Down
6 changes: 6 additions & 0 deletions extern/nanobind/docs/faq.rst
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,12 @@ build system compatible with another tool that is sufficiently
feature-complete, then please file an issue and I am happy to reference it in
the documentation.

Is there a way to pass ``JSON`` objects between Python and C++?
-------------------------------------------------
Yes, an unofficial, currently maintained, package supporting that can be found `here
<https://github.com/Griger5/nanobind_json>`_. It is based on a similar package for
``pybind11`` called ``pybind11_json``.

Are there tools to generate nanobind bindings automatically?
------------------------------------------------------------

Expand Down
2 changes: 1 addition & 1 deletion extern/nanobind/docs/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
furo
sphinx==6.1.3
sphinx-copybutton==0.5.1
sphinxcontrib-moderncmakedomain==3.25.0
sphinxcontrib-moderncmakedomain==3.29.0
sphinxcontrib-svg2pdfconverter==1.2.2
5 changes: 2 additions & 3 deletions extern/nanobind/docs/why.rst
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,6 @@ would require a substantial redesign and years of careful work by a team of C++
metaprogramming experts. At the same time, changing anything in pybind11 is
extremely hard because of the large number of downstream users and their
requirements on API/ABI stability. I personally don't have the time and energy
to fix pybind11 and have moved my focus to this project. The `testimonials
section
<https://github.com/wjakob/nanobind/blob/master/README.md#testimonials>` lists
to fix pybind11 and have moved my focus to this project. The `testimonials section
<https://github.com/wjakob/nanobind/blob/master/README.md#testimonials>`__ lists
the experience of a number of large projects that made the switch.
8 changes: 6 additions & 2 deletions extern/nanobind/include/nanobind/nanobind.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@
#endif

#define NB_VERSION_MAJOR 2
#define NB_VERSION_MINOR 11
#define NB_VERSION_MINOR 12
#define NB_VERSION_PATCH 0
#define NB_VERSION_DEV 0 // A value > 0 indicates a development release

// nb_python.h includes Python.h, which according to
// https://docs.python.org/3/c-api/intro.html#include-files, must be included
// before standard headers because it overrides feature test macros
#include "nb_python.h"

// Core C++ headers that nanobind depends on
#include <cstddef>
#include <cstdint>
Expand All @@ -39,7 +44,6 @@

// Implementation. The nb_*.h files should only be included through nanobind.h
// IWYU pragma: begin_exports
#include "nb_python.h"
#include "nb_defs.h"
#include "nb_enums.h"
#include "nb_traits.h"
Expand Down
2 changes: 1 addition & 1 deletion extern/nanobind/include/nanobind/nb_attr.h
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ NB_INLINE void func_extra_apply(F &f, const arg &a, size_t &index) {
flag |= (uint8_t) cast_flags::convert;

arg_data &arg = f.args[index];
arg.flag |= flag;
arg.flag = flag;
arg.name = a.name_;
arg.signature = a.signature_;
arg.value = nullptr;
Expand Down
8 changes: 3 additions & 5 deletions extern/nanobind/include/nanobind/nb_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,8 +169,6 @@
X(const X &) = delete; \
X &operator=(const X &) = delete;

#define NB_MOD_STATE_SIZE (12 * sizeof(PyObject*))

// Helper macros to ensure macro arguments are expanded before token pasting/stringification
#define NB_MODULE_IMPL(name, variable) NB_MODULE_IMPL2(name, variable)
#define NB_MODULE_IMPL2(name, variable) \
Expand All @@ -196,9 +194,9 @@
NB_MODULE_SLOTS_2 \
}; \
static struct PyModuleDef nanobind_##name##_module = { \
PyModuleDef_HEAD_INIT, #name, nullptr, NB_MOD_STATE_SIZE, nullptr, \
nanobind_##name##_slots, nanobind::detail::nb_module_traverse, \
nanobind::detail::nb_module_clear, nanobind::detail::nb_module_free \
PyModuleDef_HEAD_INIT, #name, nullptr, 0, nullptr, \
nanobind_##name##_slots, nullptr, nullptr, \
nanobind::detail::nb_module_free \
}; \
extern "C" [[maybe_unused]] NB_EXPORT PyObject *PyInit_##name(void); \
extern "C" PyObject *PyInit_##name(void) { \
Expand Down
21 changes: 14 additions & 7 deletions extern/nanobind/include/nanobind/nb_func.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,14 @@ NB_INLINE PyObject *func_create(Func &&func, Return (*)(Args...),
};

// The following temporary record will describe the function in detail
func_data_prelim<has_arg_defaults ? nargs : nargs_provided> f;
func_data_prelim<has_arg_defaults ? (nargs - is_method_det) : nargs_provided> f;

// Initialize argument flags. The first branch turns std::optional<> types
// into implicit nb::none() anotations.
// Pre-initialize argument flags with 'convert'. The 'accepts_none' flag
// for std::optional<> args is applied after func_extra_apply (see below).
if constexpr (has_arg_defaults) {
size_t i = 0;
((f.args[i++] = { nullptr, nullptr, nullptr, nullptr,
has_arg_defaults_v<Args> ? (uint8_t) cast_flags::accepts_none
: (uint8_t) 0 }), ...);
((void)(Is < (size_t)is_method_det ||
(f.args[Is - is_method_det] = { nullptr, nullptr, nullptr, nullptr,
(uint8_t) cast_flags::convert }, true)), ...);
} else if constexpr (nargs_provided > 0) {
for (size_t i = 0; i < nargs_provided; ++i)
f.args[i].flag = 0;
Expand Down Expand Up @@ -326,6 +325,14 @@ NB_INLINE PyObject *func_create(Func &&func, Return (*)(Args...),

(void) arg_index;

// Apply implicit accepts_none for std::optional<> typed arguments
// after func_extra_apply, so that explicit nb::arg().noconvert() works.
if constexpr (has_arg_defaults) {
((void)(Is >= (size_t)is_method_det && has_arg_defaults_v<Args> &&
(f.args[Is - is_method_det].flag |=
(uint8_t) cast_flags::accepts_none, true)), ...);
}

return nb_func_new(&f);
}

Expand Down
5 changes: 3 additions & 2 deletions extern/nanobind/include/nanobind/nb_lib.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,6 @@ NB_CORE void raise_next_overload_if_null(void *p);
// ========================================================================

NB_CORE void nb_module_exec(const char *domain, PyObject *m);
NB_CORE int nb_module_traverse(PyObject *m, visitproc visit, void *arg);
NB_CORE int nb_module_clear(PyObject *m);
NB_CORE void nb_module_free(void *m);

// ========================================================================
Expand Down Expand Up @@ -176,6 +174,9 @@ NB_CORE PyObject *set_from_obj(PyObject *o);
/// Convert a Python object into a Python frozenset
NB_CORE PyObject *frozenset_from_obj(PyObject *o);

/// Convert a Python object into a Python memoryview
NB_CORE PyObject *memoryview_from_obj(PyObject *o);

// ========================================================================

/// Get an object attribute or raise an exception
Expand Down
6 changes: 6 additions & 0 deletions extern/nanobind/include/nanobind/nb_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,12 @@ class slice : public object {
}
};

class memoryview : public object {
NB_OBJECT(memoryview, object, "memoryview", PyMemoryView_Check)
explicit memoryview(handle h)
: object(detail::memoryview_from_obj(h.ptr()), detail::steal_t{}) { }
};

class ellipsis : public object {
static bool is_ellipsis(PyObject *obj) { return obj == Py_Ellipsis; }

Expand Down
2 changes: 1 addition & 1 deletion extern/nanobind/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "scikit_build_core.build"

[project]
name = "nanobind"
version = "2.11.0"
version = "2.12.0"
description = "nanobind: tiny and efficient C++/Python bindings"
readme.content-type = "text/markdown"
readme.text = """
Expand Down
2 changes: 1 addition & 1 deletion extern/nanobind/src/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def cmake_dir() -> str:
"Return the path to the nanobind CMake module directory."
return os.path.join(os.path.abspath(os.path.dirname(__file__)), "cmake")

__version__ = "2.11.0"
__version__ = "2.12.0"

__all__ = (
"__version__",
Expand Down
7 changes: 7 additions & 0 deletions extern/nanobind/src/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,6 +673,13 @@ PyObject *frozenset_from_obj(PyObject *o) {
return result;
}

PyObject *memoryview_from_obj(PyObject *o) {
PyObject *result = PyMemoryView_FromObject(o);
if (!result)
raise_python_error();
return result;
}

// ========================================================================

PyObject **seq_get(PyObject *seq, size_t *size_out, PyObject **temp_out) noexcept {
Expand Down
2 changes: 1 addition & 1 deletion extern/nanobind/src/nb_abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

/// Tracks the version of nanobind's internal data structures
#ifndef NB_INTERNALS_VERSION
# define NB_INTERNALS_VERSION 18
# define NB_INTERNALS_VERSION 19
#endif

#if defined(__MINGW32__)
Expand Down
3 changes: 3 additions & 0 deletions extern/nanobind/src/nb_func.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ void nb_func_dealloc(PyObject *self) {
}

PyObject_GC_Del(self);

internals_dec_ref();
}

int nb_bound_method_traverse(PyObject *self, visitproc visit, void *arg) {
Expand Down Expand Up @@ -296,6 +298,7 @@ PyObject *nb_func_new(const func_data_prelim_base *f) noexcept {
name_cstr);

make_immortal((PyObject *) func);
internals_inc_ref();

// Check if the complex dispatch loop is needed
bool complex_call = can_mutate_args || has_var_kwargs || has_var_args ||
Expand Down
Loading
Loading