From 9758f6e8f455886f2b189269a84d586f38935b4d Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Sat, 28 May 2022 12:56:51 -0700 Subject: [PATCH] Fold in PR #3970 with `#ifdef`s --- include/pybind11/pytypes.h | 58 ++++++++++++++++++++++++++++++++++++-- tests/test_pytypes.cpp | 5 ++++ tests/test_pytypes.py | 5 +++- 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index 796ff906fa5..501e87e494e 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -85,7 +85,13 @@ class object_api : public pyobject_tag { or `object` subclass causes a call to ``__setitem__``. \endrst */ item_accessor operator[](handle key) const; - /// See above (the only difference is that they key is provided as a string literal) +#define PYBIND11_PR3970 +#ifdef PYBIND11_PR3970 +# define PYBIND11_PR3970_ITEM_ACCESSOR + /// See above (the only difference is that the key's reference is stolen) + item_accessor operator[](object &&key) const; +#endif + /// See above (the only difference is that the key is provided as a string literal) item_accessor operator[](const char *key) const; /** \rst @@ -95,7 +101,12 @@ class object_api : public pyobject_tag { or `object` subclass causes a call to ``setattr``. \endrst */ obj_attr_accessor attr(handle key) const; - /// See above (the only difference is that they key is provided as a string literal) + /// See above (the only difference is that the key's reference is stolen) +#ifdef PYBIND11_PR3970 +# define PYBIND11_PR3970_ATTR_ACCESSOR + obj_attr_accessor attr(object &&key) const; + /// See above (the only difference is that the key is provided as a string literal) +#endif str_attr_accessor attr(const char *key) const; /** \rst @@ -676,7 +687,12 @@ class accessor : public object_api> { } template void operator=(T &&value) & { +#ifdef PYBIND11_PR3970 +# define PYBIND11_PR3970_ENSURE_OBJECT + get_cache() = ensure_object(object_or_cast(std::forward(value))); +#else get_cache() = reinterpret_borrow(object_or_cast(std::forward(value))); +#endif } template @@ -704,6 +720,11 @@ class accessor : public object_api> { } private: +#ifdef PYBIND11_PR3970_ENSURE_OBJECT + static object ensure_object(object &&o) { return std::move(o); } + static object ensure_object(handle h) { return reinterpret_borrow(h); } +#endif + object &get_cache() const { if (!cache) { cache = Policy::get(obj, key); @@ -1703,7 +1724,14 @@ class tuple : public object { size_t size() const { return (size_t) PyTuple_Size(m_ptr); } bool empty() const { return size() == 0; } detail::tuple_accessor operator[](size_t index) const { return {*this, index}; } +#ifdef PYBIND11_PR3970 + template ::value, int> = 0> + detail::item_accessor operator[](T o) const { + return object::operator[](std::forward(o)); + } +#else detail::item_accessor operator[](handle h) const { return object::operator[](h); } +#endif detail::tuple_iterator begin() const { return {*this, 0}; } detail::tuple_iterator end() const { return {*this, PyTuple_GET_SIZE(m_ptr)}; } }; @@ -1763,7 +1791,14 @@ class sequence : public object { } bool empty() const { return size() == 0; } detail::sequence_accessor operator[](size_t index) const { return {*this, index}; } +#ifdef PYBIND11_PR3970 + template ::value, int> = 0> + detail::item_accessor operator[](T o) const { + return object::operator[](std::forward(o)); + } +#else detail::item_accessor operator[](handle h) const { return object::operator[](h); } +#endif detail::sequence_iterator begin() const { return {*this, 0}; } detail::sequence_iterator end() const { return {*this, PySequence_Size(m_ptr)}; } }; @@ -1782,7 +1817,14 @@ class list : public object { size_t size() const { return (size_t) PyList_Size(m_ptr); } bool empty() const { return size() == 0; } detail::list_accessor operator[](size_t index) const { return {*this, index}; } +#ifdef PYBIND11_PR3970 + template ::value, int> = 0> + detail::item_accessor operator[](T o) const { + return object::operator[](std::forward(o)); + } +#else detail::item_accessor operator[](handle h) const { return object::operator[](h); } +#endif detail::list_iterator begin() const { return {*this, 0}; } detail::list_iterator end() const { return {*this, PyList_GET_SIZE(m_ptr)}; } template @@ -2077,6 +2119,12 @@ template iterator object_api::end() const { return iterator::sentinel(); } +#ifdef PYBIND11_PR3970_ITEM_ACCESSOR +template +item_accessor object_api::operator[](object &&key) const { + return {derived(), std::move(key)}; +} +#endif template item_accessor object_api::operator[](handle key) const { return {derived(), reinterpret_borrow(key)}; @@ -2085,6 +2133,12 @@ template item_accessor object_api::operator[](const char *key) const { return {derived(), pybind11::str(key)}; } +#ifdef PYBIND11_PR3970_ATTR_ACCESSOR +template +obj_attr_accessor object_api::attr(object &&key) const { + return {derived(), std::move(key)}; +} +#endif template obj_attr_accessor object_api::attr(handle key) const { return {derived(), reinterpret_borrow(key)}; diff --git a/tests/test_pytypes.cpp b/tests/test_pytypes.cpp index 71db12cfb93..e7c01cf0565 100644 --- a/tests/test_pytypes.cpp +++ b/tests/test_pytypes.cpp @@ -300,6 +300,11 @@ TEST_SUBMODULE(pytypes, m) { m.def("accessor_moves", []() { py::list return_list; #ifdef PYBIND11_HANDLE_REF_DEBUG +# ifdef PYBIND11_PR3970 + return_list.append("move"); +# else + return_list.append("copy"); +# endif py::list lst; lst.append(0); auto list_accessor = lst[0]; diff --git a/tests/test_pytypes.py b/tests/test_pytypes.py index 44b36329162..8a39e9c0be8 100644 --- a/tests/test_pytypes.py +++ b/tests/test_pytypes.py @@ -320,7 +320,10 @@ def func(self, x, *args): def test_accessor_moves(): inc_refs = m.accessor_moves() if inc_refs: - assert inc_refs == [1, 1, 1, 1] + if inc_refs[0] == "copy": + assert inc_refs == ["copy", 1, 1, 1, 1] + else: + assert inc_refs == ["move", 1, 0, 1, 0] else: pytest.skip("Not defined: PYBIND11_HANDLE_REF_DEBUG")