Fix ambiguous str(handle) constructor for object-derived types (#5949)

* Fix ambiguous `str(handle)` constructor for object-derived types

Templatize `str(handle h)` with SFINAE to exclude types derived from
`object`, resolving ambiguity with `str(const object&)` when calling
`py::str()` on types like `kwargs`, `dict`, etc.

The template now only accepts `handle` or `PyObject*`, while all
`object`-derived types use the `str(const object&)` overload.

* fix(tests): CIBW test fixes from b-pass→vectorcall branch

- Install multiple-interpreter test modules into wheel (CMakeLists.txt)
  The mod_per_interpreter_gil, mod_shared_interpreter_gil, and
  mod_per_interpreter_gil_with_singleton modules were being built
  but not installed into the wheel when using scikit-build-core.

- Pin numpy 2.4.0 for Python 3.14 CI tests (requirements.txt)
  NumPy 2.4.0 is the first version with official Python 3.14 wheels.

- Add IOS platform constant to tests/env.py

- Skip subinterpreter tests on iOS (test_multiple_interpreters.py)
  Subinterpreters are not supported in the iOS simulator environment.

- Enable pytest timeout of 120s for CIBW tests (pyproject.toml)
  Provides a safety net to catch hanging tests before CI job timeout.

- Disable pytest-timeout for Pyodide (no signal.setitimer)
  Pyodide runs in WebAssembly without POSIX signals.

- Add -v flag for verbose pytest output in CIBW tests
This commit is contained in:
Ralf W. Grosse-Kunstleve
2025-12-30 19:54:44 +07:00
committed by GitHub
parent fee2527dfa
commit b93c0f7ed8
8 changed files with 29 additions and 2 deletions

View File

@@ -1690,7 +1690,13 @@ public:
Return a string representation of the object. This is analogous to
the ``str()`` function in Python.
\endrst */
explicit str(handle h) : object(raw_str(h.ptr()), stolen_t{}) {
// Templatized to avoid ambiguity with str(const object&) for object-derived types.
template <typename T,
detail::enable_if_t<!std::is_base_of<object, detail::remove_cvref_t<T>>::value
&& std::is_constructible<handle, T>::value,
int>
= 0>
explicit str(T &&h) : object(raw_str(handle(std::forward<T>(h)).ptr()), stolen_t{}) {
if (!m_ptr) {
throw error_already_set();
}