Merge branch 'master' into sh_merge_master

This commit is contained in:
Ralf W. Grosse-Kunstleve 2024-10-11 20:40:52 -07:00
commit d8b1541168
No known key found for this signature in database
5 changed files with 44 additions and 14 deletions

View File

@ -164,14 +164,6 @@
# endif # endif
#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: // For CUDA, GCC7, GCC8:
// PYBIND11_NOINLINE_FORCED is incompatible with `-Wattributes -Werror`. // PYBIND11_NOINLINE_FORCED is incompatible with `-Wattributes -Werror`.
// When defining PYBIND11_NOINLINE_FORCED, it is best to also use `-Wno-attributes`. // When defining PYBIND11_NOINLINE_FORCED, it is best to also use `-Wno-attributes`.
@ -329,6 +321,17 @@ PYBIND11_WARNING_POP
# endif # endif
#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 // 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 #if defined(__cpp_lib_char8_t) && __cpp_lib_char8_t >= 201811L
# define PYBIND11_HAS_U8STRING # define PYBIND11_HAS_U8STRING

View File

@ -1470,11 +1470,17 @@ public:
PYBIND11_OBJECT_DEFAULT(iterator, object, PyIter_Check) PYBIND11_OBJECT_DEFAULT(iterator, object, PyIter_Check)
iterator &operator++() { iterator &operator++() {
init();
advance(); advance();
return *this; return *this;
} }
iterator operator++(int) { 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; auto rv = *this;
advance(); advance();
return rv; return rv;
@ -1482,15 +1488,12 @@ public:
// NOLINTNEXTLINE(readability-const-return-type) // PR #3263 // NOLINTNEXTLINE(readability-const-return-type) // PR #3263
reference operator*() const { reference operator*() const {
if (m_ptr && !value.ptr()) { init();
auto &self = const_cast<iterator &>(*this);
self.advance();
}
return value; return value;
} }
pointer operator->() const { pointer operator->() const {
operator*(); init();
return &value; return &value;
} }
@ -1513,6 +1516,13 @@ public:
friend bool operator!=(const iterator &a, const iterator &b) { return a->ptr() != b->ptr(); } friend bool operator!=(const iterator &a, const iterator &b) { return a->ptr() != b->ptr(); }
private: private:
void init() const {
if (m_ptr && !value.ptr()) {
auto &self = const_cast<iterator &>(*this);
self.advance();
}
}
void advance() { void advance() {
value = reinterpret_steal<object>(PyIter_Next(m_ptr)); value = reinterpret_steal<object>(PyIter_Next(m_ptr));
if (value.ptr() == nullptr && PyErr_Occurred()) { if (value.ptr() == nullptr && PyErr_Occurred()) {

View File

@ -76,7 +76,7 @@ def test_cross_module_exceptions(msg):
# TODO: FIXME # TODO: FIXME
@pytest.mark.xfail( @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, raises=RuntimeError,
reason="See Issue #2847, PR #2999, PR #4324", 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(); }); m.def("get_iterator", [] { return py::iterator(); });
// test_iterable // test_iterable
m.def("get_iterable", [] { return py::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", m.def("get_frozenset_from_iterable",
[](const py::iterable &iter) { return py::frozenset(iter); }); [](const py::iterable &iter) { return py::frozenset(iter); });
m.def("get_list_from_iterable", [](const py::iterable &iter) { return py::list(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): def test_iterable(doc):
assert doc(m.get_iterable) == "get_iterable() -> Iterable" 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): def test_float(doc):