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"
  
 

Reply via email to