Merge branch 'pybind:master' into master

This commit is contained in:
Steve R. Sun 2024-10-13 09:59:27 +08:00 committed by GitHub
commit 76eb0c70c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 72 additions and 17 deletions

View File

@ -1564,15 +1564,24 @@ struct function_call {
handle init_self;
};
// See PR #5396 for the discussion that led to this
template <typename Base, typename Derived, typename = void>
struct is_same_or_base_of : std::is_same<Base, Derived> {};
// Only evaluate is_base_of if Derived is complete.
// is_base_of raises a compiler error if Derived is incomplete.
template <typename Base, typename Derived>
struct is_same_or_base_of<Base, Derived, decltype(void(sizeof(Derived)))>
: any_of<std::is_same<Base, Derived>, std::is_base_of<Base, Derived>> {};
/// Helper class which loads arguments for C++ functions called from Python
template <typename... Args>
class argument_loader {
using indices = make_index_sequence<sizeof...(Args)>;
template <typename Arg>
using argument_is_args = std::is_base_of<args, intrinsic_t<Arg>>;
using argument_is_args = is_same_or_base_of<args, intrinsic_t<Arg>>;
template <typename Arg>
using argument_is_kwargs = std::is_base_of<kwargs, intrinsic_t<Arg>>;
using argument_is_kwargs = is_same_or_base_of<kwargs, intrinsic_t<Arg>>;
// Get kwargs argument position, or -1 if not present:
static constexpr auto kwargs_pos = constexpr_last<argument_is_kwargs, Args...>();

View File

@ -164,14 +164,6 @@
# endif
#endif
#if !defined(PYBIND11_EXPORT_EXCEPTION)
# if defined(__apple_build_version__)
# define PYBIND11_EXPORT_EXCEPTION PYBIND11_EXPORT
# else
# define PYBIND11_EXPORT_EXCEPTION
# endif
#endif
// For CUDA, GCC7, GCC8:
// PYBIND11_NOINLINE_FORCED is incompatible with `-Wattributes -Werror`.
// When defining PYBIND11_NOINLINE_FORCED, it is best to also use `-Wno-attributes`.
@ -329,6 +321,17 @@ PYBIND11_WARNING_POP
# endif
#endif
// For libc++, the exceptions should be exported,
// otherwise, the exception translation would be incorrect.
// IMPORTANT: This code block must stay BELOW the #include <exception> above (see PR #5390).
#if !defined(PYBIND11_EXPORT_EXCEPTION)
# if defined(_LIBCPP_EXCEPTION)
# define PYBIND11_EXPORT_EXCEPTION PYBIND11_EXPORT
# else
# define PYBIND11_EXPORT_EXCEPTION
# endif
#endif
// Must be after including <version> or one of the other headers specified by the standard
#if defined(__cpp_lib_char8_t) && __cpp_lib_char8_t >= 201811L
# define PYBIND11_HAS_U8STRING

View File

@ -1470,11 +1470,17 @@ public:
PYBIND11_OBJECT_DEFAULT(iterator, object, PyIter_Check)
iterator &operator++() {
init();
advance();
return *this;
}
iterator operator++(int) {
// Note: We must call init() first so that rv.value is
// the same as this->value just before calling advance().
// Otherwise, dereferencing the returned iterator may call
// advance() again and return the 3rd item instead of the 1st.
init();
auto rv = *this;
advance();
return rv;
@ -1482,15 +1488,12 @@ public:
// NOLINTNEXTLINE(readability-const-return-type) // PR #3263
reference operator*() const {
if (m_ptr && !value.ptr()) {
auto &self = const_cast<iterator &>(*this);
self.advance();
}
init();
return value;
}
pointer operator->() const {
operator*();
init();
return &value;
}
@ -1513,6 +1516,13 @@ public:
friend bool operator!=(const iterator &a, const iterator &b) { return a->ptr() != b->ptr(); }
private:
void init() const {
if (m_ptr && !value.ptr()) {
auto &self = const_cast<iterator &>(*this);
self.advance();
}
}
void advance() {
value = reinterpret_steal<object>(PyIter_Next(m_ptr));
if (value.ptr() == nullptr && PyErr_Occurred()) {

View File

@ -52,8 +52,24 @@ void bind_empty0(py::module_ &m) {
}
} // namespace pr4220_tripped_over_this
namespace pr5396_forward_declared_class {
class ForwardClass;
class Args : public py::args {};
} // namespace pr5396_forward_declared_class
} // namespace test_class
static_assert(py::detail::is_same_or_base_of<py::args, py::args>::value, "");
static_assert(
py::detail::is_same_or_base_of<py::args,
test_class::pr5396_forward_declared_class::Args>::value,
"");
static_assert(!py::detail::is_same_or_base_of<
py::args,
test_class::pr5396_forward_declared_class::ForwardClass>::value,
"");
TEST_SUBMODULE(class_, m) {
m.def("obj_class_name", [](py::handle obj) { return py::detail::obj_class_name(obj.ptr()); });

View File

@ -76,7 +76,7 @@ def test_cross_module_exceptions(msg):
# TODO: FIXME
@pytest.mark.xfail(
"env.MACOS and (env.PYPY or pybind11_tests.compiler_info.startswith('Homebrew Clang')) or sys.platform.startswith('emscripten')",
"env.MACOS and env.PYPY",
raises=RuntimeError,
reason="See Issue #2847, PR #2999, PR #4324",
)

View File

@ -150,6 +150,18 @@ TEST_SUBMODULE(pytypes, m) {
m.def("get_iterator", [] { return py::iterator(); });
// test_iterable
m.def("get_iterable", [] { return py::iterable(); });
m.def("get_first_item_from_iterable", [](const py::iterable &iter) {
// This tests the postfix increment operator
py::iterator it = iter.begin();
py::iterator it2 = it++;
return *it2;
});
m.def("get_second_item_from_iterable", [](const py::iterable &iter) {
// This tests the prefix increment operator
py::iterator it = iter.begin();
++it;
return *it;
});
m.def("get_frozenset_from_iterable",
[](const py::iterable &iter) { return py::frozenset(iter); });
m.def("get_list_from_iterable", [](const py::iterable &iter) { return py::list(iter); });

View File

@ -52,6 +52,11 @@ def test_from_iterable(pytype, from_iter_func):
def test_iterable(doc):
assert doc(m.get_iterable) == "get_iterable() -> Iterable"
lins = [1, 2, 3]
i = m.get_first_item_from_iterable(lins)
assert i == 1
i = m.get_second_item_from_iterable(lins)
assert i == 2
def test_float(doc):