From 506185dca821c9cc1268c33b4cc867ae20f0fc4b Mon Sep 17 00:00:00 2001 From: Wenzel Jakob Date: Mon, 3 Jul 2023 22:49:33 +0200 Subject: [PATCH] improved constructors for ``nb::tuple`` and ``nb::list`` wrappers --- docs/api_core.rst | 18 ++++++++++++++++++ include/nanobind/nb_lib.h | 8 ++++++++ include/nanobind/nb_types.h | 7 ++++++- src/common.cpp | 16 ++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) diff --git a/docs/api_core.rst b/docs/api_core.rst index c909cd20..6fa9bfed 100644 --- a/docs/api_core.rst +++ b/docs/api_core.rst @@ -620,6 +620,15 @@ Wrapper classes Wrapper class representing Python ``tuple`` instances. + .. cpp:function:: tuple() + + Create an empty tuple + + .. cpp:function:: tuple(handle h) + + Attempt to convert a given Python object into a tuple. Analogous to the + expression ``tuple(h)`` in Python. + .. cpp:function:: size_t size() const Return the number of tuple elements. @@ -648,6 +657,15 @@ Wrapper classes Wrapper class representing Python ``list`` instances. + .. cpp:function:: list() + + Create an empty list + + .. cpp:function:: list(handle h) + + Attempt to convert a given Python object into a list. Analogous to the + expression ``list(h)`` in Python. + .. cpp:function:: size_t size() const Return the number of list elements. diff --git a/include/nanobind/nb_lib.h b/include/nanobind/nb_lib.h index e051059e..467bf06e 100644 --- a/include/nanobind/nb_lib.h +++ b/include/nanobind/nb_lib.h @@ -135,6 +135,14 @@ NB_CORE PyObject *float_from_obj(PyObject *o); // ======================================================================== +/// Convert a Python object into a Python list +NB_CORE PyObject *list_from_obj(PyObject *o); + +/// Convert a Python object into a Python tuple +NB_CORE PyObject *tuple_from_obj(PyObject *o); + +// ======================================================================== + /// Get an object attribute or raise an exception NB_CORE PyObject *getattr(PyObject *obj, const char *key); NB_CORE PyObject *getattr(PyObject *obj, PyObject *key); diff --git a/include/nanobind/nb_types.h b/include/nanobind/nb_types.h index 92f34cc1..82126994 100644 --- a/include/nanobind/nb_types.h +++ b/include/nanobind/nb_types.h @@ -415,7 +415,10 @@ class bytes : public object { }; class tuple : public object { - NB_OBJECT_DEFAULT(tuple, object, "tuple", PyTuple_Check) + NB_OBJECT(tuple, object, "tuple", PyTuple_Check) + tuple() : object(PyTuple_New(0), detail::steal_t()) { } + explicit tuple(handle h) + : object(detail::tuple_from_obj(h.ptr()), detail::steal_t{}) { } size_t size() const { return (size_t) NB_TUPLE_GET_SIZE(m_ptr); } template > = 1> detail::accessor operator[](T key) const; @@ -433,6 +436,8 @@ class type_object : public object { class list : public object { NB_OBJECT(list, object, "list", PyList_Check) list() : object(PyList_New(0), detail::steal_t()) { } + explicit list(handle h) + : object(detail::list_from_obj(h.ptr()), detail::steal_t{}) { } size_t size() const { return (size_t) NB_LIST_GET_SIZE(m_ptr); } template void append(T &&value); diff --git a/src/common.cpp b/src/common.cpp index 88e84f6d..b949ec26 100644 --- a/src/common.cpp +++ b/src/common.cpp @@ -552,6 +552,22 @@ PyObject *float_from_obj(PyObject *o) { // ======================================================================== +PyObject *tuple_from_obj(PyObject *o) { + PyObject *result = PySequence_Tuple(o); + if (!result) + raise_python_error(); + return result; +} + +PyObject *list_from_obj(PyObject *o) { + PyObject *result = PySequence_List(o); + if (!result) + raise_python_error(); + return result; +} + +// ======================================================================== + PyObject **seq_get(PyObject *seq, size_t *size_out, PyObject **temp_out) noexcept { PyObject *temp = nullptr; size_t size = 0;