Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-nanobind for openSUSE:Factory
checked in at 2026-04-02 17:41:16
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-nanobind (Old)
and /work/SRC/openSUSE:Factory/.python-nanobind.new.21863 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-nanobind"
Thu Apr 2 17:41:16 2026 rev:9 rq:1344227 version:2.12.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-nanobind/python-nanobind.changes
2026-02-06 19:17:25.053966522 +0100
+++
/work/SRC/openSUSE:Factory/.python-nanobind.new.21863/python-nanobind.changes
2026-04-02 17:42:24.802447180 +0200
@@ -1,0 +2,8 @@
+Sat Mar 7 12:00:49 UTC 2026 - Friedrich Haubensak <[email protected]>
+
+- update to release 2.12.0
+ * for details about changes see
+ github.com/wjakob/nanobind/blob/master/docs/changelog.rst
+- adapt nanobind-installationpath.patch to fit 2.12.0
+
+-------------------------------------------------------------------
Old:
----
nanobind-2.11.0.tar.gz
New:
----
nanobind-2.12.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-nanobind.spec ++++++
--- /var/tmp/diff_new_pack.kZ3hPu/_old 2026-04-02 17:42:26.982537219 +0200
+++ /var/tmp/diff_new_pack.kZ3hPu/_new 2026-04-02 17:42:26.994537715 +0200
@@ -18,7 +18,7 @@
%{?sle15_python_module_pythons}
Name: python-nanobind
-Version: 2.11.0
+Version: 2.12.0
Release: 0
Summary: Tiny And Efficient C++/Python Bindings
License: BSD-3-Clause
++++++ nanobind-2.11.0.tar.gz -> nanobind-2.12.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/cmake/nanobind-config.cmake
new/nanobind-2.12.0/cmake/nanobind-config.cmake
--- old/nanobind-2.11.0/cmake/nanobind-config.cmake 2026-01-29
12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/cmake/nanobind-config.cmake 2026-02-25
10:40:59.000000000 +0100
@@ -500,7 +500,7 @@
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()
@@ -508,6 +508,8 @@
endforeach()
endforeach()
+ list(REMOVE_DUPLICATES san_flags)
+
# Parse sanitizer flags
foreach(flag ${san_flags})
string(REPLACE "\"" "" flag "${flag}")
@@ -517,6 +519,8 @@
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()
@@ -525,7 +529,6 @@
endforeach()
if (detected_san)
- list(REMOVE_DUPLICATES detected_san)
set(libs "")
foreach(san ${detected_san})
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/docs/api_core.rst
new/nanobind-2.12.0/docs/api_core.rst
--- old/nanobind-2.11.0/docs/api_core.rst 2026-01-29 12:23:42.000000000
+0100
+++ new/nanobind-2.12.0/docs/api_core.rst 2026-02-25 10:40:59.000000000
+0100
@@ -1268,6 +1268,15 @@
// 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.
@@ -2641,8 +2650,8 @@
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)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/docs/bazel.rst
new/nanobind-2.12.0/docs/bazel.rst
--- old/nanobind-2.11.0/docs/bazel.rst 2026-01-29 12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/docs/bazel.rst 2026-02-25 10:40:59.000000000 +0100
@@ -27,8 +27,8 @@
# 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:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/docs/changelog.rst
new/nanobind-2.12.0/docs/changelog.rst
--- old/nanobind-2.11.0/docs/changelog.rst 2026-01-29 12:23:42.000000000
+0100
+++ new/nanobind-2.12.0/docs/changelog.rst 2026-02-25 10:40:59.000000000
+0100
@@ -15,6 +15,35 @@
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)
-----------------------------
@@ -92,7 +121,7 @@
(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>`__).
@@ -564,7 +593,7 @@
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>`_).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/docs/faq.rst
new/nanobind-2.12.0/docs/faq.rst
--- old/nanobind-2.11.0/docs/faq.rst 2026-01-29 12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/docs/faq.rst 2026-02-25 10:40:59.000000000 +0100
@@ -369,6 +369,12 @@
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?
------------------------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/docs/requirements.txt
new/nanobind-2.12.0/docs/requirements.txt
--- old/nanobind-2.11.0/docs/requirements.txt 2026-01-29 12:23:42.000000000
+0100
+++ new/nanobind-2.12.0/docs/requirements.txt 2026-02-25 10:40:59.000000000
+0100
@@ -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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/docs/why.rst
new/nanobind-2.12.0/docs/why.rst
--- old/nanobind-2.11.0/docs/why.rst 2026-01-29 12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/docs/why.rst 2026-02-25 10:40:59.000000000 +0100
@@ -247,7 +247,6 @@
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.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/include/nanobind/nanobind.h
new/nanobind-2.12.0/include/nanobind/nanobind.h
--- old/nanobind-2.11.0/include/nanobind/nanobind.h 2026-01-29
12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/include/nanobind/nanobind.h 2026-02-25
10:40:59.000000000 +0100
@@ -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>
@@ -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"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/include/nanobind/nb_attr.h
new/nanobind-2.12.0/include/nanobind/nb_attr.h
--- old/nanobind-2.11.0/include/nanobind/nb_attr.h 2026-01-29
12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/include/nanobind/nb_attr.h 2026-02-25
10:40:59.000000000 +0100
@@ -328,7 +328,7 @@
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;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/include/nanobind/nb_defs.h
new/nanobind-2.12.0/include/nanobind/nb_defs.h
--- old/nanobind-2.11.0/include/nanobind/nb_defs.h 2026-01-29
12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/include/nanobind/nb_defs.h 2026-02-25
10:40:59.000000000 +0100
@@ -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)
\
@@ -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) {
\
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/include/nanobind/nb_func.h
new/nanobind-2.12.0/include/nanobind/nb_func.h
--- old/nanobind-2.11.0/include/nanobind/nb_func.h 2026-01-29
12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/include/nanobind/nb_func.h 2026-02-25
10:40:59.000000000 +0100
@@ -190,15 +190,14 @@
};
// 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;
@@ -326,6 +325,14 @@
(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);
}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/include/nanobind/nb_lib.h
new/nanobind-2.12.0/include/nanobind/nb_lib.h
--- old/nanobind-2.11.0/include/nanobind/nb_lib.h 2026-01-29
12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/include/nanobind/nb_lib.h 2026-02-25
10:40:59.000000000 +0100
@@ -117,8 +117,6 @@
// ========================================================================
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);
// ========================================================================
@@ -176,6 +174,9 @@
/// 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
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/include/nanobind/nb_types.h
new/nanobind-2.12.0/include/nanobind/nb_types.h
--- old/nanobind-2.11.0/include/nanobind/nb_types.h 2026-01-29
12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/include/nanobind/nb_types.h 2026-02-25
10:40:59.000000000 +0100
@@ -753,6 +753,12 @@
}
};
+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; }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/pyproject.toml
new/nanobind-2.12.0/pyproject.toml
--- old/nanobind-2.11.0/pyproject.toml 2026-01-29 12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/pyproject.toml 2026-02-25 10:40:59.000000000 +0100
@@ -4,7 +4,7 @@
[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 = """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/src/__init__.py
new/nanobind-2.12.0/src/__init__.py
--- old/nanobind-2.11.0/src/__init__.py 2026-01-29 12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/src/__init__.py 2026-02-25 10:40:59.000000000 +0100
@@ -16,7 +16,7 @@
"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__",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/src/common.cpp
new/nanobind-2.12.0/src/common.cpp
--- old/nanobind-2.11.0/src/common.cpp 2026-01-29 12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/src/common.cpp 2026-02-25 10:40:59.000000000 +0100
@@ -673,6 +673,13 @@
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 {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/src/nb_abi.h
new/nanobind-2.12.0/src/nb_abi.h
--- old/nanobind-2.11.0/src/nb_abi.h 2026-01-29 12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/src/nb_abi.h 2026-02-25 10:40:59.000000000 +0100
@@ -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__)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/src/nb_func.cpp
new/nanobind-2.12.0/src/nb_func.cpp
--- old/nanobind-2.11.0/src/nb_func.cpp 2026-01-29 12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/src/nb_func.cpp 2026-02-25 10:40:59.000000000 +0100
@@ -121,6 +121,8 @@
}
PyObject_GC_Del(self);
+
+ internals_dec_ref();
}
int nb_bound_method_traverse(PyObject *self, visitproc visit, void *arg) {
@@ -296,6 +298,7 @@
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 ||
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/src/nb_internals.cpp
new/nanobind-2.12.0/src/nb_internals.cpp
--- old/nanobind-2.11.0/src/nb_internals.cpp 2026-01-29 12:23:42.000000000
+0100
+++ new/nanobind-2.12.0/src/nb_internals.cpp 2026-02-25 10:40:59.000000000
+0100
@@ -176,58 +176,128 @@
"dl_device",
};
-PyObject **static_pyobjects = nullptr;
+PyObject *static_pyobjects[pyobj_name::total_count] = {};
-static bool init_pyobjects(PyObject* m) {
- PyObject** pyobjects = (PyObject**) PyModule_GetState(m);
- if (!pyobjects)
- return false;
+static void new_constant(nb_internals *p, int index, PyObject *o) {
+ static_pyobjects[index] = o;
+ new_object(p, o);
+}
+
+/// Populate this library's static_pyobjects[]
+static void init_pyobjects(nb_internals *p) {
+ if (static_pyobjects[0])
+ return;
NB_NOUNROLL
for (int i = 0; i < pyobj_name::string_count; ++i)
- pyobjects[i] = PyUnicode_InternFromString(interned_c_strs[i]);
+ new_constant(p, i, PyUnicode_InternFromString(interned_c_strs[i]));
+
+ new_constant(p, pyobj_name::copy_tpl,
+ PyTuple_Pack(1, static_pyobjects[pyobj_name::copy_str]));
+ new_constant(p, pyobj_name::max_version_tpl,
+ PyTuple_Pack(1,
static_pyobjects[pyobj_name::max_version_str]));
- pyobjects[pyobj_name::copy_tpl] =
- PyTuple_Pack(1, pyobjects[pyobj_name::copy_str]);
- pyobjects[pyobj_name::max_version_tpl] =
- PyTuple_Pack(1, pyobjects[pyobj_name::max_version_str]);
-
- PyObject* one = PyLong_FromLong(1);
- PyObject* zero = PyLong_FromLong(0);
- pyobjects[pyobj_name::dl_cpu_tpl] = PyTuple_Pack(2, one, zero);
+ PyObject *one = PyLong_FromLong(1), *zero = PyLong_FromLong(0);
+ new_constant(p, pyobj_name::dl_cpu_tpl, PyTuple_Pack(2, one, zero));
Py_DECREF(zero);
Py_DECREF(one);
- PyObject* major = PyLong_FromLong(dlpack::major_version);
- PyObject* minor = PyLong_FromLong(dlpack::minor_version);
- pyobjects[pyobj_name::dl_version_tpl] = PyTuple_Pack(2, major, minor);
+ PyObject *major = PyLong_FromLong(dlpack::major_version),
+ *minor = PyLong_FromLong(dlpack::minor_version);
+ new_constant(p, pyobj_name::dl_version_tpl, PyTuple_Pack(2, major, minor));
Py_DECREF(minor);
Py_DECREF(major);
+}
+
+/// Create lifeline + internal types if needed
+static void init_internals(nb_internals *p) {
+ if (p->lifeline)
+ return;
+
+ p->lifeline = PyList_New(0);
+ check(p->lifeline, "nanobind::detail::nb_module_exec(): "
+ "could not create lifeline list!");
+
+ str nb_name("nanobind");
+ p->nb_module = PyModule_NewObject(nb_name.ptr());
+ new_object(p, p->nb_module);
+
+ nb_meta_slots[0].pfunc = (PyObject *) &PyType_Type;
+ p->nb_meta = new_type(p, &nb_meta_spec);
+
+ p->nb_type_dict = PyDict_New();
+ new_object(p, p->nb_type_dict);
- static_pyobjects = pyobjects;
+ p->nb_func = new_type(p, &nb_func_spec);
+ p->nb_method = new_type(p, &nb_method_spec);
+ p->nb_bound_method = new_type(p, &nb_bound_method_spec);
- return true;
+ check(p->nb_module && p->nb_meta && p->nb_type_dict && p->nb_func &&
+ p->nb_method && p->nb_bound_method,
+ "nanobind::detail::nb_module_exec(): initialization failed!");
+
+#if defined(Py_LIMITED_API)
+ p->PyType_Type_tp_free = (freefunc) PyType_GetSlot(&PyType_Type,
Py_tp_free);
+ p->PyType_Type_tp_init = (initproc) PyType_GetSlot(&PyType_Type,
Py_tp_init);
+ p->PyType_Type_tp_dealloc =
+ (destructor) PyType_GetSlot(&PyType_Type, Py_tp_dealloc);
+ p->PyType_Type_tp_setattro =
+ (setattrofunc) PyType_GetSlot(&PyType_Type, Py_tp_setattro);
+ p->PyProperty_Type_tp_descr_get =
+ (descrgetfunc) PyType_GetSlot(&PyProperty_Type, Py_tp_descr_get);
+ p->PyProperty_Type_tp_descr_set =
+ (descrsetfunc) PyType_GetSlot(&PyProperty_Type, Py_tp_descr_set);
+
+ PyType_Slot dummy_slots[] = {
+ { Py_tp_base, &PyType_Type },
+ { 0, nullptr }
+ };
+
+ PyType_Spec dummy_spec = {
+ /* .name = */ "nanobind.dummy",
+ /* .basicsize = */ - (int) sizeof(void*),
+ /* .itemsize = */ 0,
+ /* .flags = */ Py_TPFLAGS_DEFAULT,
+ /* .slots = */ dummy_slots
+ };
+
+ PyObject *dummy = PyType_FromMetaclass(
+ p->nb_meta, p->nb_module, &dummy_spec, nullptr);
+ p->type_data_offset =
+ (uint8_t *) PyObject_GetTypeData(dummy, p->nb_meta) - (uint8_t *)
dummy;
+ Py_DECREF(dummy);
+#endif
}
-NB_NOINLINE int nb_module_traverse(PyObject *m, visitproc visit, void *arg) {
- PyObject** pyobjects = (PyObject**) PyModule_GetState(m);
- NB_NOUNROLL
- for (int i = 0; i < pyobj_name::total_count; ++i)
- Py_VISIT(pyobjects[i]);
- return 0;
+void internals_inc_ref() {
+ internals->shared_ref_count.value++;
}
-NB_NOINLINE int nb_module_clear(PyObject *m) {
- PyObject** pyobjects = (PyObject**) PyModule_GetState(m);
- NB_NOUNROLL
+void internals_dec_ref() {
+ nb_internals *p = internals;
+ auto value = --p->shared_ref_count.value;
+ if (value != 0)
+ return;
+
+ Py_CLEAR(p->lifeline);
+
+ p->nb_module = nullptr;
+ p->nb_meta = nullptr;
+ p->nb_type_dict = nullptr;
+ p->nb_func = nullptr;
+ p->nb_method = nullptr;
+ p->nb_bound_method = nullptr;
+ p->nb_static_property.store_release(nullptr);
+ p->nb_ndarray.store_release(nullptr);
+
+ nb_meta_cache = nullptr;
+
for (int i = 0; i < pyobj_name::total_count; ++i)
- Py_CLEAR(pyobjects[i]);
- return 0;
+ static_pyobjects[i] = nullptr;
}
-void nb_module_free(void *m) {
- // Allow nanobind_##name##_exec to omit calling nb_module_clear on error.
- (void) nb_module_clear((PyObject *) m);
+void nb_module_free(void *) {
+ internals_dec_ref();
}
@@ -384,12 +454,14 @@
#endif
}
-NB_NOINLINE void nb_module_exec(const char *name, PyObject *m) {
- if (internals)
+NB_NOINLINE void nb_module_exec(const char *name, PyObject *) {
+ if (internals) {
+ init_internals(internals);
+ init_pyobjects(internals);
+ nb_meta_cache = internals->nb_meta;
+ internals_inc_ref();
return;
-
- check(init_pyobjects(m), "nanobind::detail::nb_module_exec(): "
- "could not initialize module state!");
+ }
#if defined(PYPY_VERSION)
PyObject *dict = PyEval_GetBuiltins();
@@ -410,8 +482,13 @@
internals = (nb_internals *) PyCapsule_GetPointer(capsule,
"nb_internals");
check(internals, "nanobind::detail::nb_module_exec(): "
"capsule pointer is NULL!");
- nb_meta_cache = internals->nb_meta;
is_alive_ptr = internals->is_alive_ptr;
+
+ init_internals(internals);
+ init_pyobjects(internals);
+ nb_meta_cache = internals->nb_meta;
+ internals_inc_ref();
+
Py_DECREF(capsule);
return;
}
@@ -429,65 +506,25 @@
#endif
p->shard_count = shard_count;
- str nb_name("nanobind");
- p->nb_module = PyModule_NewObject(nb_name.ptr());
+ internals = p;
- nb_meta_slots[0].pfunc = (PyObject *) &PyType_Type;
- nb_meta_cache = p->nb_meta = (PyTypeObject *)
PyType_FromSpec(&nb_meta_spec);
- p->nb_type_dict = PyDict_New();
- p->nb_func = (PyTypeObject *) PyType_FromSpec(&nb_func_spec);
- p->nb_method = (PyTypeObject *) PyType_FromSpec(&nb_method_spec);
- p->nb_bound_method = (PyTypeObject *)
PyType_FromSpec(&nb_bound_method_spec);
+ init_internals(p);
+ init_pyobjects(p);
+ nb_meta_cache = p->nb_meta;
#if defined(NB_FREE_THREADED)
p->nb_static_property_disabled = PyThread_tss_alloc();
PyThread_tss_create(p->nb_static_property_disabled);
#endif
- check(p->nb_module && p->nb_meta && p->nb_type_dict && p->nb_func &&
- p->nb_method && p->nb_bound_method,
- "nanobind::detail::nb_module_exec(): initialization failed!");
-
-#if defined(Py_LIMITED_API)
- // Cache important functions from PyType_Type and PyProperty_Type
- p->PyType_Type_tp_free = (freefunc) PyType_GetSlot(&PyType_Type,
Py_tp_free);
- p->PyType_Type_tp_init = (initproc) PyType_GetSlot(&PyType_Type,
Py_tp_init);
- p->PyType_Type_tp_dealloc =
- (destructor) PyType_GetSlot(&PyType_Type, Py_tp_dealloc);
- p->PyType_Type_tp_setattro =
- (setattrofunc) PyType_GetSlot(&PyType_Type, Py_tp_setattro);
- p->PyProperty_Type_tp_descr_get =
- (descrgetfunc) PyType_GetSlot(&PyProperty_Type, Py_tp_descr_get);
- p->PyProperty_Type_tp_descr_set =
- (descrsetfunc) PyType_GetSlot(&PyProperty_Type, Py_tp_descr_set);
-
- PyType_Slot dummy_slots[] = {
- { Py_tp_base, &PyType_Type },
- { 0, nullptr }
- };
-
- PyType_Spec dummy_spec = {
- /* .name = */ "nanobind.dummy",
- /* .basicsize = */ - (int) sizeof(void*),
- /* .itemsize = */ 0,
- /* .flags = */ Py_TPFLAGS_DEFAULT,
- /* .slots = */ dummy_slots
- };
-
- // Determine the offset, at which types defined by nanobind begin
- PyObject *dummy = PyType_FromMetaclass(
- p->nb_meta, p->nb_module, &dummy_spec, nullptr);
- p->type_data_offset =
- (uint8_t *) PyObject_GetTypeData(dummy, p->nb_meta) - (uint8_t *)
dummy;
- Py_DECREF(dummy);
-#endif
-
p->translators = { default_exception_translator, nullptr, nullptr };
is_alive_value = true;
is_alive_ptr = &is_alive_value;
p->is_alive_ptr = is_alive_ptr;
+ internals_inc_ref();
+
#if PY_VERSION_HEX < 0x030C0000 && !defined(PYPY_VERSION)
/* The implementation of typing.py on CPython <3.12 tends to introduce
spurious reference leaks that upset nanobind's leak checker. The
@@ -536,7 +573,6 @@
"nanobind::detail::nb_module_exec(): capsule creation failed!");
Py_DECREF(capsule);
Py_DECREF(key);
- internals = p;
}
#if defined(NB_COMPACT_ASSERTIONS)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/src/nb_internals.h
new/nanobind-2.12.0/src/nb_internals.h
--- old/nanobind-2.11.0/src/nb_internals.h 2026-01-29 12:23:42.000000000
+0100
+++ new/nanobind-2.12.0/src/nb_internals.h 2026-02-25 10:40:59.000000000
+0100
@@ -426,6 +426,13 @@
// Size of the 'shards' data structure. Only rarely accessed, hence at the
end
size_t shard_count = 1;
+
+ /// Reference count tracking modules + types + functions using shared state
+ nb_maybe_atomic<uint32_t> shared_ref_count = 0;
+
+ /// PyList keeping managed PyObjects alive. Cleared when shared_ref_count
+ /// reaches 0.
+ PyObject *lifeline = nullptr;
};
// Names for the PyObject* entries in the per-module state array.
@@ -450,9 +457,24 @@
};
};
-static_assert(pyobj_name::total_count * sizeof(PyObject*) ==
NB_MOD_STATE_SIZE);
+extern PyObject *static_pyobjects[];
+
+extern void internals_inc_ref();
+extern void internals_dec_ref();
-extern PyObject **static_pyobjects;
+/// Append 'o' to the lifeline and transfer ownership to it
+inline void new_object(nb_internals *p, PyObject *o) {
+ PyList_Append(p->lifeline, o);
+ Py_DECREF(o);
+}
+
+/// Create a type via PyType_FromSpec and transfer ownership to the lifeline
+inline PyTypeObject *new_type(nb_internals *p, PyType_Spec *spec) {
+ PyTypeObject *tp = (PyTypeObject *) PyType_FromSpec(spec);
+ if (tp)
+ new_object(p, (PyObject *) tp);
+ return tp;
+}
/// Convenience macro to potentially access cached functions
#if defined(Py_LIMITED_API)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/src/nb_ndarray.cpp
new/nanobind-2.12.0/src/nb_ndarray.cpp
--- old/nanobind-2.11.0/src/nb_ndarray.cpp 2026-01-29 12:23:42.000000000
+0100
+++ new/nanobind-2.12.0/src/nb_ndarray.cpp 2026-02-25 10:40:59.000000000
+0100
@@ -271,7 +271,7 @@
ndarray_handle *th = ((nb_ndarray *) self)->th;
PyObject *capsule;
- if (max_major_version >= dlpack::major_version)
+ if (max_major_version >= (long)dlpack::major_version)
capsule = th->make_capsule_versioned();
else
capsule = th->make_capsule_unversioned();
@@ -338,7 +338,7 @@
/* .slots = */ slots
};
- tp = (PyTypeObject *) PyType_FromSpec(&spec);
+ tp = new_type(internals_, &spec);
check(tp, "nb_ndarray type creation failed!");
internals_->nb_ndarray.store_release(tp);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/src/nb_static_property.cpp
new/nanobind-2.12.0/src/nb_static_property.cpp
--- old/nanobind-2.11.0/src/nb_static_property.cpp 2026-01-29
12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/src/nb_static_property.cpp 2026-02-25
10:40:59.000000000 +0100
@@ -62,7 +62,7 @@
/* .slots = */ slots
};
- tp = (PyTypeObject *) PyType_FromSpec(&spec);
+ tp = new_type(internals_, &spec);
check(tp, "nb_static_property type creation failed!");
internals_->nb_static_property_descr_set =
nb_static_property_descr_set;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/src/nb_type.cpp
new/nanobind-2.12.0/src/nb_type.cpp
--- old/nanobind-2.11.0/src/nb_type.cpp 2026-01-29 12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/src/nb_type.cpp 2026-02-25 10:40:59.000000000 +0100
@@ -437,8 +437,12 @@
PyMem_Free(t->implicit.py);
}
+ bool initialized = t->name != nullptr;
free((char *) t->name);
NB_SLOT(PyType_Type, tp_dealloc)(o);
+
+ if (initialized)
+ internals_dec_ref();
}
/// Called when a C++ type is extended from within Python
@@ -493,6 +497,8 @@
((PyTypeObject *) self)->tp_vectorcall = nullptr;
#endif
+ internals_inc_ref();
+
return 0;
}
@@ -1319,6 +1325,7 @@
Py_DECREF(metaclass);
make_immortal(result);
+ internals_inc_ref();
type_data *to = nb_type_data((PyTypeObject *) result);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/tests/test_callbacks.cpp
new/nanobind-2.12.0/tests/test_callbacks.cpp
--- old/nanobind-2.11.0/tests/test_callbacks.cpp 2026-01-29
12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/tests/test_callbacks.cpp 2026-02-25
10:40:59.000000000 +0100
@@ -3,11 +3,12 @@
// directly keep a Python object alive (they're trivially copyable), we
// maintain a sideband structure to manage the lifetimes.
+#include <nanobind/nanobind.h>
+
#include <algorithm>
#include <unordered_set>
#include <vector>
-#include <nanobind/nanobind.h>
#include <nanobind/stl/unordered_set.h>
namespace nb = nanobind;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/tests/test_classes.cpp
new/nanobind-2.12.0/tests/test_classes.cpp
--- old/nanobind-2.11.0/tests/test_classes.cpp 2026-01-29 12:23:42.000000000
+0100
+++ new/nanobind-2.12.0/tests/test_classes.cpp 2026-02-25 10:40:59.000000000
+0100
@@ -60,6 +60,13 @@
Struct s2;
};
+// Test case for issue #1280
+struct OptionalNoneTest {
+ int compute(int i, std::optional<int> j, int k) const {
+ return i + j.value_or(0) + k;
+ }
+};
+
struct Big {
char data[1024];
Big() { memset(data, 0xff, 1024); }
@@ -187,6 +194,12 @@
.def_rw("s1", &PairStruct::s1, "A documented property")
.def_rw("s2", &PairStruct::s2);
+ // Test case for issue #1280
+ nb::class_<OptionalNoneTest>(m, "OptionalNoneTest")
+ .def(nb::init<>())
+ .def("compute", &OptionalNoneTest::compute,
+ "i"_a, "j"_a = nb::none(), "k"_a = 0);
+
m.def("stats", []{
nb::dict d;
d["default_constructed"] = default_constructed;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/tests/test_classes_ext.pyi.ref
new/nanobind-2.12.0/tests/test_classes_ext.pyi.ref
--- old/nanobind-2.11.0/tests/test_classes_ext.pyi.ref 2026-01-29
12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/tests/test_classes_ext.pyi.ref 2026-02-25
10:40:59.000000000 +0100
@@ -60,6 +60,11 @@
@s2.setter
def s2(self, arg: Struct, /) -> None: ...
+class OptionalNoneTest:
+ def __init__(self) -> None: ...
+
+ def compute(self, i: int, j: int | None = None, k: int = 0) -> int: ...
+
def stats() -> dict: ...
def reset() -> None: ...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/tests/test_functions.cpp
new/nanobind-2.12.0/tests/test_functions.cpp
--- old/nanobind-2.11.0/tests/test_functions.cpp 2026-01-29
12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/tests/test_functions.cpp 2026-02-25
10:40:59.000000000 +0100
@@ -1,6 +1,7 @@
+#include <nanobind/nanobind.h>
+
#include <string.h>
-#include <nanobind/nanobind.h>
#include <nanobind/stl/function.h>
#include <nanobind/stl/pair.h>
#include <nanobind/stl/string.h>
@@ -367,6 +368,8 @@
return s.contains(h);
});
+ m.def("test_memoryview", []() { return
nb::memoryview(nb::bytes("123456")); });
+ m.def("test_bad_memview", []() { return nb::memoryview(nb::int_(0)); });
m.def("test_del_list", [](nb::list l) { nb::del(l[2]); });
m.def("test_del_dict", [](nb::dict l) { nb::del(l["a"]); });
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/tests/test_functions.py
new/nanobind-2.12.0/tests/test_functions.py
--- old/nanobind-2.11.0/tests/test_functions.py 2026-01-29 12:23:42.000000000
+0100
+++ new/nanobind-2.12.0/tests/test_functions.py 2026-02-25 10:40:59.000000000
+0100
@@ -783,3 +783,10 @@
def test54_dict_default():
assert t.test_get_dict_default({'key': 100}) == 100
assert t.test_get_dict_default({'key2': 100}) == 123
+
+def test_55_memoryview():
+ memview = t.test_memoryview()
+ assert isinstance(memview, memoryview)
+ assert bytes(memview[0:3]) == b'123'
+ with pytest.raises(TypeError):
+ t.test_bad_memview()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/tests/test_functions_ext.pyi.ref
new/nanobind-2.12.0/tests/test_functions_ext.pyi.ref
--- old/nanobind-2.11.0/tests/test_functions_ext.pyi.ref 2026-01-29
12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/tests/test_functions_ext.pyi.ref 2026-02-25
10:40:59.000000000 +0100
@@ -187,6 +187,10 @@
def test_frozenset_contains(arg0: frozenset, arg1: object, /) -> bool: ...
+def test_memoryview() -> memoryview: ...
+
+def test_bad_memview() -> memoryview: ...
+
def test_del_list(arg: list, /) -> None: ...
def test_del_dict(arg: dict, /) -> None: ...
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/tests/test_stl.cpp
new/nanobind-2.12.0/tests/test_stl.cpp
--- old/nanobind-2.11.0/tests/test_stl.cpp 2026-01-29 12:23:42.000000000
+0100
+++ new/nanobind-2.12.0/tests/test_stl.cpp 2026-02-25 10:40:59.000000000
+0100
@@ -284,6 +284,12 @@
m.def("optional_unbound_type_with_nullopt_as_default",
[](std::optional<int> &x) { return x; }, nb::arg("x") = std::nullopt);
m.def("optional_non_assignable", [](std::optional<NonAssignable> &x) {
return x; });
+ // Regression test: std::optional<> with lossy implicit conversion on a
+ // sibling argument and no explicit nb::arg annotations (issue #1293)
+ m.def("optional_implicit_convert", [](float f, std::optional<int> o) {
+ return (double) f + o.value_or(0);
+ });
+
// ----- test43-test50 ------
m.def("variant_copyable", [](std::variant<Copyable, int> &) {});
m.def("variant_copyable_none", [](std::variant<std::monostate, int,
Copyable> &) {}, nb::arg("x").none());
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/tests/test_stl.py
new/nanobind-2.12.0/tests/test_stl.py
--- old/nanobind-2.11.0/tests/test_stl.py 2026-01-29 12:23:42.000000000
+0100
+++ new/nanobind-2.12.0/tests/test_stl.py 2026-02-25 10:40:59.000000000
+0100
@@ -388,6 +388,13 @@
assert t.optional_non_assignable(None) == None
+def test38b_std_optional_implicit_convert():
+ # Regression test: std::optional<> with lossy implicit conversion on a
+ # sibling argument and no explicit nb::arg annotations (issue #1293)
+ assert t.optional_implicit_convert(16777217, 10) == 16777216.0 + 10
+ assert t.optional_implicit_convert(16777217, None) == 16777216.0
+
+
def test39_std_optional_ret_opt_movable(clean):
assert t.optional_ret_opt_movable().value == 5
opt_movable = optional("test_stl_ext.Movable")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/tests/test_stl_bind_map.cpp
new/nanobind-2.12.0/tests/test_stl_bind_map.cpp
--- old/nanobind-2.11.0/tests/test_stl_bind_map.cpp 2026-01-29
12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/tests/test_stl_bind_map.cpp 2026-02-25
10:40:59.000000000 +0100
@@ -1,9 +1,10 @@
+#include <nanobind/stl/bind_map.h>
+
#include <map>
#include <string>
#include <unordered_map>
#include <vector>
-#include <nanobind/stl/bind_map.h>
#include <nanobind/stl/string.h>
#include <nanobind/stl/vector.h>
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/nanobind-2.11.0/tests/test_stl_ext.pyi.ref
new/nanobind-2.12.0/tests/test_stl_ext.pyi.ref
--- old/nanobind-2.11.0/tests/test_stl_ext.pyi.ref 2026-01-29
12:23:42.000000000 +0100
+++ new/nanobind-2.12.0/tests/test_stl_ext.pyi.ref 2026-02-25
10:40:59.000000000 +0100
@@ -169,6 +169,8 @@
def optional_non_assignable(arg: NonAssignable | None) -> NonAssignable |
None: ...
+def optional_implicit_convert(arg0: float, arg1: int | None) -> float: ...
+
def variant_copyable(arg: Copyable | int, /) -> None: ...
def variant_copyable_none(x: int | Copyable | None) -> None: ...
++++++ nanobind-installationpath.patch ++++++
--- /var/tmp/diff_new_pack.kZ3hPu/_old 2026-04-02 17:42:28.154585626 +0200
+++ /var/tmp/diff_new_pack.kZ3hPu/_new 2026-04-02 17:42:28.194587277 +0200
@@ -31,6 +31,6 @@
- return os.path.join(os.path.abspath(os.path.dirname(__file__)), "cmake")
+ return "/usr/share/nanobind/cmake"
- __version__ = "2.11.0"
+ __version__ = "2.12.0"