Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

git merge smart_holder #30150

Merged
merged 10 commits into from
Aug 23, 2024
6 changes: 3 additions & 3 deletions docs/advanced/cast/stl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ the declaration

.. code-block:: cpp

PYBIND11_MAKE_OPAQUE(std::vector<int>);
PYBIND11_MAKE_OPAQUE(std::vector<int>)

before any binding code (e.g. invocations to ``class_::def()``, etc.). This
macro must be specified at the top level (and outside of any namespaces), since
Expand Down Expand Up @@ -207,8 +207,8 @@ The following example showcases usage of :file:`pybind11/stl_bind.h`:
// Don't forget this
#include <pybind11/stl_bind.h>

PYBIND11_MAKE_OPAQUE(std::vector<int>);
PYBIND11_MAKE_OPAQUE(std::map<std::string, double>);
PYBIND11_MAKE_OPAQUE(std::vector<int>)
PYBIND11_MAKE_OPAQUE(std::map<std::string, double>)

// ...

Expand Down
6 changes: 3 additions & 3 deletions docs/advanced/smart_ptrs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ top namespace level before any binding code:

.. code-block:: cpp

PYBIND11_DECLARE_HOLDER_TYPE(T, SmartPtr<T>);
PYBIND11_DECLARE_HOLDER_TYPE(T, SmartPtr<T>)

The first argument of :func:`PYBIND11_DECLARE_HOLDER_TYPE` should be a
placeholder name that is used as a template parameter of the second argument.
Expand All @@ -143,7 +143,7 @@ by default. Specify

.. code-block:: cpp

PYBIND11_DECLARE_HOLDER_TYPE(T, SmartPtr<T>, true);
PYBIND11_DECLARE_HOLDER_TYPE(T, SmartPtr<T>, true)

if ``SmartPtr<T>`` can always be initialized from a ``T*`` pointer without the
risk of inconsistencies (such as multiple independent ``SmartPtr`` instances
Expand All @@ -161,7 +161,7 @@ specialized:
.. code-block:: cpp

// Always needed for custom holder types
PYBIND11_DECLARE_HOLDER_TYPE(T, SmartPtr<T>);
PYBIND11_DECLARE_HOLDER_TYPE(T, SmartPtr<T>)

// Only needed if the type's `.get()` goes by another name
namespace PYBIND11_NAMESPACE { namespace detail {
Expand Down
7 changes: 7 additions & 0 deletions docs/basics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@ For brevity, all code examples assume that the following two lines are present:

namespace py = pybind11;

.. note::

``pybind11/pybind11.h`` includes ``Python.h``, as such it must be the first file
included in any source file or header for `the same reasons as Python.h`_.

.. _`the same reasons as Python.h`: https://docs.python.org/3/extending/extending.html#a-simple-example

Some features may require additional headers, but those will be specified as needed.

.. _simple_example:
Expand Down
17 changes: 17 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,23 @@ New Features:
* Support for CMake older than 3.15 removed. CMake 3.15-3.30 supported.
`#5304 <https://github.com/pybind/pybind11/pull/5304>`_

* The ``array_caster`` in pybind11/stl.h was enhanced to support value types that are not default-constructible.
`#5305 <https://github.com/pybind/pybind11/pull/5305>`_

Version 2.13.5 (August 22, 2024)
--------------------------------

Bug fixes:

* Fix includes when using Windows long paths (``\\?\`` prefix).
`#5321 <https://github.com/pybind/pybind11/pull/5321>`_

* Support ``-Wpedantic`` in C++20 mode.
`#5322 <https://github.com/pybind/pybind11/pull/5322>`_

* Fix and test ``<ranges>`` support for ``py::tuple`` and ``py::list``.
`#5314 <https://github.com/pybind/pybind11/pull/5314>`_

Version 2.13.4 (August 14, 2024)
--------------------------------

Expand Down
3 changes: 3 additions & 0 deletions include/pybind11/detail/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,8 @@ PYBIND11_WARNING_POP
}

\endrst */
PYBIND11_WARNING_PUSH
PYBIND11_WARNING_DISABLE_CLANG("-Wgnu-zero-variadic-macro-arguments")
#define PYBIND11_MODULE(name, variable, ...) \
static ::pybind11::module_::module_def PYBIND11_CONCAT(pybind11_module_def_, name) \
PYBIND11_MAYBE_UNUSED; \
Expand All @@ -499,6 +501,7 @@ PYBIND11_WARNING_POP
PYBIND11_CATCH_INIT_EXCEPTIONS \
} \
void PYBIND11_CONCAT(pybind11_init_, name)(::pybind11::module_ & (variable))
PYBIND11_WARNING_POP

PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)

Expand Down
2 changes: 2 additions & 0 deletions include/pybind11/pytypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -1267,6 +1267,7 @@ class sequence_fast_readonly {
using pointer = arrow_proxy<const handle>;

sequence_fast_readonly(handle obj, ssize_t n) : ptr(PySequence_Fast_ITEMS(obj.ptr()) + n) {}
sequence_fast_readonly() = default;

// NOLINTNEXTLINE(readability-const-return-type) // PR #3263
reference dereference() const { return *ptr; }
Expand All @@ -1289,6 +1290,7 @@ class sequence_slow_readwrite {
using pointer = arrow_proxy<const sequence_accessor>;

sequence_slow_readwrite(handle obj, ssize_t index) : obj(obj), index(index) {}
sequence_slow_readwrite() = default;

reference dereference() const { return {obj, static_cast<size_t>(index)}; }
void increment() { ++index; }
Expand Down
3 changes: 3 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,9 @@ function(pybind11_enable_warnings target_name)
-Wdeprecated
-Wundef
-Wnon-virtual-dtor)
if(DEFINED CMAKE_CXX_STANDARD AND NOT CMAKE_CXX_STANDARD VERSION_LESS 20)
target_compile_options(${target_name} PRIVATE -Wpedantic)
endif()
endif()

if(PYBIND11_WERROR)
Expand Down
16 changes: 8 additions & 8 deletions tests/local_bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,21 +56,21 @@ class LocalSimpleException : public std::exception {
std::string message = "";
};

PYBIND11_MAKE_OPAQUE(LocalVec);
PYBIND11_MAKE_OPAQUE(LocalVec2);
PYBIND11_MAKE_OPAQUE(LocalMap);
PYBIND11_MAKE_OPAQUE(NonLocalVec);
// PYBIND11_MAKE_OPAQUE(NonLocalVec2); // same type as LocalVec2
PYBIND11_MAKE_OPAQUE(NonLocalMap);
PYBIND11_MAKE_OPAQUE(NonLocalMap2);
PYBIND11_MAKE_OPAQUE(LocalVec)
PYBIND11_MAKE_OPAQUE(LocalVec2)
PYBIND11_MAKE_OPAQUE(LocalMap)
PYBIND11_MAKE_OPAQUE(NonLocalVec)
// PYBIND11_MAKE_OPAQUE(NonLocalVec2) // same type as LocalVec2
PYBIND11_MAKE_OPAQUE(NonLocalMap)
PYBIND11_MAKE_OPAQUE(NonLocalMap2)

// Simple bindings (used with the above):
template <typename T, int Adjust = 0, typename... Args>
py::class_<T> bind_local(Args &&...args) {
return py::class_<T>(std::forward<Args>(args)...).def(py::init<int>()).def("get", [](T &i) {
return i.i + Adjust;
});
};
}

// Simulate a foreign library base class (to match the example in the docs):
namespace pets {
Expand Down
2 changes: 1 addition & 1 deletion tests/test_callbacks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ TEST_SUBMODULE(callbacks, m) {
m.def("dummy_function2", [](int i, int j) { return i + j; });
m.def(
"roundtrip",
[](std::function<int(int)> f, bool expect_none = false) {
[](std::function<int(int)> f, bool expect_none) {
if (expect_none && f) {
throw std::runtime_error("Expected None to be converted to empty std::function");
}
Expand Down
4 changes: 2 additions & 2 deletions tests/test_eigen_matrix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ void reset_refs() {
}

// Returns element 2,1 from a matrix (used to test copy/nocopy)
double get_elem(const Eigen::Ref<const Eigen::MatrixXd> &m) { return m(2, 1); };
double get_elem(const Eigen::Ref<const Eigen::MatrixXd> &m) { return m(2, 1); }

// Returns a matrix with 10*r + 100*c added to each matrix element (to help test that the matrix
// reference is referencing rows/columns correctly).
Expand All @@ -76,7 +76,7 @@ struct CustomOperatorNew {
Eigen::Matrix4d a = Eigen::Matrix4d::Zero();
Eigen::Matrix4d b = Eigen::Matrix4d::Identity();

EIGEN_MAKE_ALIGNED_OPERATOR_NEW;
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};

TEST_SUBMODULE(eigen_matrix, m) {
Expand Down
2 changes: 1 addition & 1 deletion tests/test_opaque_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
// This also deliberately doesn't use the below StringList type alias to test
// that MAKE_OPAQUE can handle a type containing a `,`. (The `std::allocator`
// bit is just the default `std::vector` allocator).
PYBIND11_MAKE_OPAQUE(std::vector<std::string, std::allocator<std::string>>);
PYBIND11_MAKE_OPAQUE(std::vector<std::string, std::allocator<std::string>>)

using StringList = std::vector<std::string, std::allocator<std::string>>;

Expand Down
63 changes: 63 additions & 0 deletions tests/test_pytypes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@

#include <utility>

//__has_include has been part of C++17, no need to check it
#if defined(PYBIND11_CPP20) && __has_include(<ranges>)
# if !defined(PYBIND11_COMPILER_CLANG) || __clang_major__ >= 16 // llvm/llvm-project#52696
# define PYBIND11_TEST_PYTYPES_HAS_RANGES
# include <ranges>
# endif
#endif

namespace external {
namespace detail {
bool check(PyObject *o) { return PyFloat_Check(o) != 0; }
Expand Down Expand Up @@ -923,4 +931,59 @@ TEST_SUBMODULE(pytypes, m) {
#else
m.attr("defined_PYBIND11_TYPING_H_HAS_STRING_LITERAL") = false;
#endif

#if defined(PYBIND11_TEST_PYTYPES_HAS_RANGES)

// test_tuple_ranges
m.def("tuple_iterator_default_initialization", []() {
using TupleIterator = decltype(std::declval<py::tuple>().begin());
static_assert(std::random_access_iterator<TupleIterator>);
return TupleIterator{} == TupleIterator{};
});

m.def("transform_tuple_plus_one", [](py::tuple &tpl) {
py::list ret{};
for (auto it : tpl | std::views::transform([](auto &o) { return py::cast<int>(o) + 1; })) {
ret.append(py::int_(it));
}
return ret;
});

// test_list_ranges
m.def("list_iterator_default_initialization", []() {
using ListIterator = decltype(std::declval<py::list>().begin());
static_assert(std::random_access_iterator<ListIterator>);
return ListIterator{} == ListIterator{};
});

m.def("transform_list_plus_one", [](py::list &lst) {
py::list ret{};
for (auto it : lst | std::views::transform([](auto &o) { return py::cast<int>(o) + 1; })) {
ret.append(py::int_(it));
}
return ret;
});

// test_dict_ranges
m.def("dict_iterator_default_initialization", []() {
using DictIterator = decltype(std::declval<py::dict>().begin());
static_assert(std::forward_iterator<DictIterator>);
return DictIterator{} == DictIterator{};
});

m.def("transform_dict_plus_one", [](py::dict &dct) {
py::list ret{};
for (auto it : dct | std::views::transform([](auto &o) {
return std::pair{py::cast<int>(o.first) + 1,
py::cast<int>(o.second) + 1};
})) {
ret.append(py::make_tuple(py::int_(it.first), py::int_(it.second)));
}
return ret;
});

m.attr("defined_PYBIND11_TEST_PYTYPES_HAS_RANGES") = true;
#else
m.attr("defined_PYBIND11_TEST_PYTYPES_HAS_RANGES") = false;
#endif
}
42 changes: 42 additions & 0 deletions tests/test_pytypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1048,3 +1048,45 @@ def test_typevar(doc):
assert doc(m.annotate_listT_to_T) == "annotate_listT_to_T(arg0: list[T]) -> T"

assert doc(m.annotate_object_to_T) == "annotate_object_to_T(arg0: object) -> T"


@pytest.mark.skipif(
not m.defined_PYBIND11_TEST_PYTYPES_HAS_RANGES,
reason="<ranges> not available.",
)
@pytest.mark.parametrize(
("tested_tuple", "expected"),
[((1,), [2]), ((3, 4), [4, 5]), ((7, 8, 9), [8, 9, 10])],
)
def test_tuple_ranges(tested_tuple, expected):
assert m.tuple_iterator_default_initialization()
assert m.transform_tuple_plus_one(tested_tuple) == expected


@pytest.mark.skipif(
not m.defined_PYBIND11_TEST_PYTYPES_HAS_RANGES,
reason="<ranges> not available.",
)
@pytest.mark.parametrize(
("tested_list", "expected"), [([1], [2]), ([3, 4], [4, 5]), ([7, 8, 9], [8, 9, 10])]
)
def test_list_ranges(tested_list, expected):
assert m.list_iterator_default_initialization()
assert m.transform_list_plus_one(tested_list) == expected


@pytest.mark.skipif(
not m.defined_PYBIND11_TEST_PYTYPES_HAS_RANGES,
reason="<ranges> not available.",
)
@pytest.mark.parametrize(
("tested_dict", "expected"),
[
({1: 2}, [(2, 3)]),
({3: 4, 5: 6}, [(4, 5), (6, 7)]),
({7: 8, 9: 10, 11: 12}, [(8, 9), (10, 11), (12, 13)]),
],
)
def test_dict_ranges(tested_dict, expected):
assert m.dict_iterator_default_initialization()
assert m.transform_dict_plus_one(tested_dict) == expected
2 changes: 1 addition & 1 deletion tests/test_return_value_policy_override.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ const char *return_value_policy_name(return_value_policy policy) {
default:
return "Expected to be unreachable.";
}
};
}

template <>
struct type_caster<some_type> : type_caster_base<some_type> {
Expand Down
4 changes: 2 additions & 2 deletions tests/test_sequences_and_iterators.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ class NonCopyableInt {
};
using NonCopyableIntPair = std::pair<NonCopyableInt, NonCopyableInt>;

PYBIND11_MAKE_OPAQUE(std::vector<NonCopyableInt>);
PYBIND11_MAKE_OPAQUE(std::vector<NonCopyableIntPair>);
PYBIND11_MAKE_OPAQUE(std::vector<NonCopyableInt>)
PYBIND11_MAKE_OPAQUE(std::vector<NonCopyableIntPair>)

template <typename PythonType>
py::list test_random_access_iterator(PythonType x) {
Expand Down
15 changes: 9 additions & 6 deletions tests/test_smart_ptr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
#include "object.h"
#include "pybind11_tests.h"

// This breaks on PYBIND11_DECLARE_HOLDER_TYPE
PYBIND11_WARNING_DISABLE_GCC("-Wpedantic")

namespace {

// This is just a wrapper around unique_ptr, but with extra fields to deliberately bloat up the
Expand Down Expand Up @@ -279,13 +282,13 @@ struct holder_helper<ref<T>> {
} // namespace PYBIND11_NAMESPACE

// Make pybind aware of the ref-counted wrapper type (s):
PYBIND11_DECLARE_HOLDER_TYPE(T, ref<T>, true);
PYBIND11_DECLARE_HOLDER_TYPE(T, ref<T>, true)
// The following is not required anymore for std::shared_ptr, but it should compile without error:
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>);
PYBIND11_DECLARE_HOLDER_TYPE(T, huge_unique_ptr<T>);
PYBIND11_DECLARE_HOLDER_TYPE(T, custom_unique_ptr<T>);
PYBIND11_DECLARE_HOLDER_TYPE(T, shared_ptr_with_addressof_operator<T>);
PYBIND11_DECLARE_HOLDER_TYPE(T, unique_ptr_with_addressof_operator<T>);
PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>)
PYBIND11_DECLARE_HOLDER_TYPE(T, huge_unique_ptr<T>)
PYBIND11_DECLARE_HOLDER_TYPE(T, custom_unique_ptr<T>)
PYBIND11_DECLARE_HOLDER_TYPE(T, shared_ptr_with_addressof_operator<T>)
PYBIND11_DECLARE_HOLDER_TYPE(T, unique_ptr_with_addressof_operator<T>)

TEST_SUBMODULE(smart_ptr, m) {
// Please do not interleave `struct` and `class` definitions with bindings code,
Expand Down
2 changes: 1 addition & 1 deletion tests/test_stl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ struct visit_helper<boost::variant> {
} // namespace PYBIND11_NAMESPACE
#endif

PYBIND11_MAKE_OPAQUE(std::vector<std::string, std::allocator<std::string>>);
PYBIND11_MAKE_OPAQUE(std::vector<std::string, std::allocator<std::string>>)

/// Issue #528: templated constructor
struct TplCtorClass {
Expand Down
2 changes: 1 addition & 1 deletion tests/test_tagbased_polymorphic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,4 +145,4 @@ TEST_SUBMODULE(tagbased_polymorphic, m) {
.def(py::init<std::string>())
.def("purr", &Panther::purr);
m.def("create_zoo", &create_zoo);
};
}
2 changes: 1 addition & 1 deletion tests/test_type_caster_odr_guard_2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ inline void pass_vector_type_mrc(const std::vector<type_mrc> &) {}

} // namespace mrc_ns

PYBIND11_MAKE_OPAQUE(std::vector<mrc_ns::type_mrc>);
PYBIND11_MAKE_OPAQUE(std::vector<mrc_ns::type_mrc>)

namespace pybind11 {
namespace detail {
Expand Down
2 changes: 1 addition & 1 deletion tests/test_virtual_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -589,4 +589,4 @@ void initialize_inherited_virtuals(py::module_ &m) {
// Fix issue #1454 (crash when acquiring/releasing GIL on another thread in Python 2.7)
m.def("test_gil", &test_gil);
m.def("test_gil_from_thread", &test_gil_from_thread);
};
}