| /* |
| pybind11/pytypes.h: Convenience wrapper classes for basic Python types |
| |
| Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch> |
| |
| All rights reserved. Use of this source code is governed by a |
| BSD-style license that can be found in the LICENSE file. |
| */ |
| |
| #pragma once |
| |
| #include "detail/common.h" |
| #include "buffer_info.h" |
| #include <utility> |
| #include <type_traits> |
| |
| #if defined(PYBIND11_HAS_OPTIONAL) |
| # include <optional> |
| #endif |
| |
| PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) |
| |
| /* A few forward declarations */ |
| class handle; class object; |
| class str; class iterator; |
| class type; |
| struct arg; struct arg_v; |
| |
| PYBIND11_NAMESPACE_BEGIN(detail) |
| class args_proxy; |
| bool isinstance_generic(handle obj, const std::type_info &tp); |
| |
| // Accessor forward declarations |
| template <typename Policy> class accessor; |
| namespace accessor_policies { |
| struct obj_attr; |
| struct str_attr; |
| struct generic_item; |
| struct sequence_item; |
| struct list_item; |
| struct tuple_item; |
| } // namespace accessor_policies |
| using obj_attr_accessor = accessor<accessor_policies::obj_attr>; |
| using str_attr_accessor = accessor<accessor_policies::str_attr>; |
| using item_accessor = accessor<accessor_policies::generic_item>; |
| using sequence_accessor = accessor<accessor_policies::sequence_item>; |
| using list_accessor = accessor<accessor_policies::list_item>; |
| using tuple_accessor = accessor<accessor_policies::tuple_item>; |
| |
| /// Tag and check to identify a class which implements the Python object API |
| class pyobject_tag { }; |
| template <typename T> using is_pyobject = std::is_base_of<pyobject_tag, remove_reference_t<T>>; |
| |
| /** \rst |
| A mixin class which adds common functions to `handle`, `object` and various accessors. |
| The only requirement for `Derived` is to implement ``PyObject *Derived::ptr() const``. |
| \endrst */ |
| template <typename Derived> |
| class object_api : public pyobject_tag { |
| const Derived &derived() const { return static_cast<const Derived &>(*this); } |
| |
| public: |
| /** \rst |
| Return an iterator equivalent to calling ``iter()`` in Python. The object |
| must be a collection which supports the iteration protocol. |
| \endrst */ |
| iterator begin() const; |
| /// Return a sentinel which ends iteration. |
| iterator end() const; |
| |
| /** \rst |
| Return an internal functor to invoke the object's sequence protocol. Casting |
| the returned ``detail::item_accessor`` instance to a `handle` or `object` |
| subclass causes a corresponding call to ``__getitem__``. Assigning a `handle` |
| 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) |
| item_accessor operator[](const char *key) const; |
| |
| /** \rst |
| Return an internal functor to access the object's attributes. Casting the |
| returned ``detail::obj_attr_accessor`` instance to a `handle` or `object` |
| subclass causes a corresponding call to ``getattr``. Assigning a `handle` |
| 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) |
| str_attr_accessor attr(const char *key) const; |
| |
| /** \rst |
| Matches * unpacking in Python, e.g. to unpack arguments out of a ``tuple`` |
| or ``list`` for a function call. Applying another * to the result yields |
| ** unpacking, e.g. to unpack a dict as function keyword arguments. |
| See :ref:`calling_python_functions`. |
| \endrst */ |
| args_proxy operator*() const; |
| |
| /// Check if the given item is contained within this object, i.e. ``item in obj``. |
| template <typename T> bool contains(T &&item) const; |
| |
| /** \rst |
| Assuming the Python object is a function or implements the ``__call__`` |
| protocol, ``operator()`` invokes the underlying function, passing an |
| arbitrary set of parameters. The result is returned as a `object` and |
| may need to be converted back into a Python object using `handle::cast()`. |
| |
| When some of the arguments cannot be converted to Python objects, the |
| function will throw a `cast_error` exception. When the Python function |
| call fails, a `error_already_set` exception is thrown. |
| \endrst */ |
| template <return_value_policy policy = return_value_policy::automatic_reference, typename... Args> |
| object operator()(Args &&...args) const; |
| template <return_value_policy policy = return_value_policy::automatic_reference, typename... Args> |
| PYBIND11_DEPRECATED("call(...) was deprecated in favor of operator()(...)") |
| object call(Args&&... args) const; |
| |
| /// Equivalent to ``obj is other`` in Python. |
| bool is(object_api const& other) const { return derived().ptr() == other.derived().ptr(); } |
| /// Equivalent to ``obj is None`` in Python. |
| bool is_none() const { return derived().ptr() == Py_None; } |
| /// Equivalent to obj == other in Python |
| bool equal(object_api const &other) const { return rich_compare(other, Py_EQ); } |
| bool not_equal(object_api const &other) const { return rich_compare(other, Py_NE); } |
| bool operator<(object_api const &other) const { return rich_compare(other, Py_LT); } |
| bool operator<=(object_api const &other) const { return rich_compare(other, Py_LE); } |
| bool operator>(object_api const &other) const { return rich_compare(other, Py_GT); } |
| bool operator>=(object_api const &other) const { return rich_compare(other, Py_GE); } |
| |
| object operator-() const; |
| object operator~() const; |
| object operator+(object_api const &other) const; |
| object operator+=(object_api const &other) const; |
| object operator-(object_api const &other) const; |
| object operator-=(object_api const &other) const; |
| object operator*(object_api const &other) const; |
| object operator*=(object_api const &other) const; |
| object operator/(object_api const &other) const; |
| object operator/=(object_api const &other) const; |
| object operator|(object_api const &other) const; |
| object operator|=(object_api const &other) const; |
| object operator&(object_api const &other) const; |
| object operator&=(object_api const &other) const; |
| object operator^(object_api const &other) const; |
| object operator^=(object_api const &other) const; |
| object operator<<(object_api const &other) const; |
| object operator<<=(object_api const &other) const; |
| object operator>>(object_api const &other) const; |
| object operator>>=(object_api const &other) const; |
| |
| PYBIND11_DEPRECATED("Use py::str(obj) instead") |
| pybind11::str str() const; |
| |
| /// Get or set the object's docstring, i.e. ``obj.__doc__``. |
| str_attr_accessor doc() const; |
| |
| /// Return the object's current reference count |
| int ref_count() const { return static_cast<int>(Py_REFCNT(derived().ptr())); } |
| |
| // TODO PYBIND11_DEPRECATED("Call py::type::handle_of(h) or py::type::of(h) instead of h.get_type()") |
| handle get_type() const; |
| |
| private: |
| bool rich_compare(object_api const &other, int value) const; |
| }; |
| |
| PYBIND11_NAMESPACE_END(detail) |
| |
| /** \rst |
| Holds a reference to a Python object (no reference counting) |
| |
| The `handle` class is a thin wrapper around an arbitrary Python object (i.e. a |
| ``PyObject *`` in Python's C API). It does not perform any automatic reference |
| counting and merely provides a basic C++ interface to various Python API functions. |
| |
| .. seealso:: |
| The `object` class inherits from `handle` and adds automatic reference |
| counting features. |
| \endrst */ |
| class handle : public detail::object_api<handle> { |
| public: |
| /// The default constructor creates a handle with a ``nullptr``-valued pointer |
| handle() = default; |
| /// Creates a ``handle`` from the given raw Python object pointer |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| handle(PyObject *ptr) : m_ptr(ptr) { } // Allow implicit conversion from PyObject* |
| |
| /// Return the underlying ``PyObject *`` pointer |
| PyObject *ptr() const { return m_ptr; } |
| PyObject *&ptr() { return m_ptr; } |
| |
| /** \rst |
| Manually increase the reference count of the Python object. Usually, it is |
| preferable to use the `object` class which derives from `handle` and calls |
| this function automatically. Returns a reference to itself. |
| \endrst */ |
| const handle& inc_ref() const & { Py_XINCREF(m_ptr); return *this; } |
| |
| /** \rst |
| Manually decrease the reference count of the Python object. Usually, it is |
| preferable to use the `object` class which derives from `handle` and calls |
| this function automatically. Returns a reference to itself. |
| \endrst */ |
| const handle& dec_ref() const & { Py_XDECREF(m_ptr); return *this; } |
| |
| /** \rst |
| Attempt to cast the Python object into the given C++ type. A `cast_error` |
| will be throw upon failure. |
| \endrst */ |
| template <typename T> T cast() const; |
| /// Return ``true`` when the `handle` wraps a valid Python object |
| explicit operator bool() const { return m_ptr != nullptr; } |
| /** \rst |
| Deprecated: Check that the underlying pointers are the same. |
| Equivalent to ``obj1 is obj2`` in Python. |
| \endrst */ |
| PYBIND11_DEPRECATED("Use obj1.is(obj2) instead") |
| bool operator==(const handle &h) const { return m_ptr == h.m_ptr; } |
| PYBIND11_DEPRECATED("Use !obj1.is(obj2) instead") |
| bool operator!=(const handle &h) const { return m_ptr != h.m_ptr; } |
| PYBIND11_DEPRECATED("Use handle::operator bool() instead") |
| bool check() const { return m_ptr != nullptr; } |
| protected: |
| PyObject *m_ptr = nullptr; |
| }; |
| |
| /** \rst |
| Holds a reference to a Python object (with reference counting) |
| |
| Like `handle`, the `object` class is a thin wrapper around an arbitrary Python |
| object (i.e. a ``PyObject *`` in Python's C API). In contrast to `handle`, it |
| optionally increases the object's reference count upon construction, and it |
| *always* decreases the reference count when the `object` instance goes out of |
| scope and is destructed. When using `object` instances consistently, it is much |
| easier to get reference counting right at the first attempt. |
| \endrst */ |
| class object : public handle { |
| public: |
| object() = default; |
| PYBIND11_DEPRECATED("Use reinterpret_borrow<object>() or reinterpret_steal<object>()") |
| object(handle h, bool is_borrowed) : handle(h) { if (is_borrowed) inc_ref(); } |
| /// Copy constructor; always increases the reference count |
| object(const object &o) : handle(o) { inc_ref(); } |
| /// Move constructor; steals the object from ``other`` and preserves its reference count |
| object(object &&other) noexcept { m_ptr = other.m_ptr; other.m_ptr = nullptr; } |
| /// Destructor; automatically calls `handle::dec_ref()` |
| ~object() { dec_ref(); } |
| |
| /** \rst |
| Resets the internal pointer to ``nullptr`` without decreasing the |
| object's reference count. The function returns a raw handle to the original |
| Python object. |
| \endrst */ |
| handle release() { |
| PyObject *tmp = m_ptr; |
| m_ptr = nullptr; |
| return handle(tmp); |
| } |
| |
| object& operator=(const object &other) { |
| other.inc_ref(); |
| // Use temporary variable to ensure `*this` remains valid while |
| // `Py_XDECREF` executes, in case `*this` is accessible from Python. |
| handle temp(m_ptr); |
| m_ptr = other.m_ptr; |
| temp.dec_ref(); |
| return *this; |
| } |
| |
| object& operator=(object &&other) noexcept { |
| if (this != &other) { |
| handle temp(m_ptr); |
| m_ptr = other.m_ptr; |
| other.m_ptr = nullptr; |
| temp.dec_ref(); |
| } |
| return *this; |
| } |
| |
| // Calling cast() on an object lvalue just copies (via handle::cast) |
| template <typename T> T cast() const &; |
| // Calling on an object rvalue does a move, if needed and/or possible |
| template <typename T> T cast() &&; |
| |
| protected: |
| // Tags for choosing constructors from raw PyObject * |
| struct borrowed_t { }; |
| struct stolen_t { }; |
| |
| #ifndef DOXYGEN_SHOULD_SKIP_THIS // Issue in breathe 4.26.1 |
| template <typename T> friend T reinterpret_borrow(handle); |
| template <typename T> friend T reinterpret_steal(handle); |
| #endif |
| |
| public: |
| // Only accessible from derived classes and the reinterpret_* functions |
| object(handle h, borrowed_t) : handle(h) { inc_ref(); } |
| object(handle h, stolen_t) : handle(h) { } |
| }; |
| |
| /** \rst |
| Declare that a `handle` or ``PyObject *`` is a certain type and borrow the reference. |
| The target type ``T`` must be `object` or one of its derived classes. The function |
| doesn't do any conversions or checks. It's up to the user to make sure that the |
| target type is correct. |
| |
| .. code-block:: cpp |
| |
| PyObject *p = PyList_GetItem(obj, index); |
| py::object o = reinterpret_borrow<py::object>(p); |
| // or |
| py::tuple t = reinterpret_borrow<py::tuple>(p); // <-- `p` must be already be a `tuple` |
| \endrst */ |
| template <typename T> T reinterpret_borrow(handle h) { return {h, object::borrowed_t{}}; } |
| |
| /** \rst |
| Like `reinterpret_borrow`, but steals the reference. |
| |
| .. code-block:: cpp |
| |
| PyObject *p = PyObject_Str(obj); |
| py::str s = reinterpret_steal<py::str>(p); // <-- `p` must be already be a `str` |
| \endrst */ |
| template <typename T> T reinterpret_steal(handle h) { return {h, object::stolen_t{}}; } |
| |
| PYBIND11_NAMESPACE_BEGIN(detail) |
| std::string error_string(); |
| PYBIND11_NAMESPACE_END(detail) |
| |
| #if defined(_MSC_VER) |
| # pragma warning(push) |
| # pragma warning(disable: 4275 4251) // warning C4275: An exported class was derived from a class that wasn't exported. Can be ignored when derived from a STL class. |
| #endif |
| /// Fetch and hold an error which was already set in Python. An instance of this is typically |
| /// thrown to propagate python-side errors back through C++ which can either be caught manually or |
| /// else falls back to the function dispatcher (which then raises the captured error back to |
| /// python). |
| class PYBIND11_EXPORT_EXCEPTION error_already_set : public std::runtime_error { |
| public: |
| /// Constructs a new exception from the current Python error indicator, if any. The current |
| /// Python error indicator will be cleared. |
| error_already_set() : std::runtime_error(detail::error_string()) { |
| PyErr_Fetch(&m_type.ptr(), &m_value.ptr(), &m_trace.ptr()); |
| } |
| |
| error_already_set(const error_already_set &) = default; |
| error_already_set(error_already_set &&) = default; |
| |
| inline ~error_already_set() override; |
| |
| /// Give the currently-held error back to Python, if any. If there is currently a Python error |
| /// already set it is cleared first. After this call, the current object no longer stores the |
| /// error variables (but the `.what()` string is still available). |
| void restore() { PyErr_Restore(m_type.release().ptr(), m_value.release().ptr(), m_trace.release().ptr()); } |
| |
| /// If it is impossible to raise the currently-held error, such as in a destructor, we can write |
| /// it out using Python's unraisable hook (`sys.unraisablehook`). The error context should be |
| /// some object whose `repr()` helps identify the location of the error. Python already knows the |
| /// type and value of the error, so there is no need to repeat that. After this call, the current |
| /// object no longer stores the error variables, and neither does Python. |
| void discard_as_unraisable(object err_context) { |
| restore(); |
| PyErr_WriteUnraisable(err_context.ptr()); |
| } |
| /// An alternate version of `discard_as_unraisable()`, where a string provides information on the |
| /// location of the error. For example, `__func__` could be helpful. |
| void discard_as_unraisable(const char *err_context) { |
| discard_as_unraisable(reinterpret_steal<object>(PYBIND11_FROM_STRING(err_context))); |
| } |
| |
| // Does nothing; provided for backwards compatibility. |
| PYBIND11_DEPRECATED("Use of error_already_set.clear() is deprecated") |
| void clear() {} |
| |
| /// Check if the currently trapped error type matches the given Python exception class (or a |
| /// subclass thereof). May also be passed a tuple to search for any exception class matches in |
| /// the given tuple. |
| bool matches(handle exc) const { |
| return (PyErr_GivenExceptionMatches(m_type.ptr(), exc.ptr()) != 0); |
| } |
| |
| const object& type() const { return m_type; } |
| const object& value() const { return m_value; } |
| const object& trace() const { return m_trace; } |
| |
| private: |
| object m_type, m_value, m_trace; |
| }; |
| #if defined(_MSC_VER) |
| # pragma warning(pop) |
| #endif |
| |
| #if PY_VERSION_HEX >= 0x03030000 |
| |
| /// Replaces the current Python error indicator with the chosen error, performing a |
| /// 'raise from' to indicate that the chosen error was caused by the original error. |
| inline void raise_from(PyObject *type, const char *message) { |
| // Based on _PyErr_FormatVFromCause: |
| // https://github.com/python/cpython/blob/467ab194fc6189d9f7310c89937c51abeac56839/Python/errors.c#L405 |
| // See https://github.com/pybind/pybind11/pull/2112 for details. |
| PyObject *exc = nullptr, *val = nullptr, *val2 = nullptr, *tb = nullptr; |
| |
| assert(PyErr_Occurred()); |
| PyErr_Fetch(&exc, &val, &tb); |
| PyErr_NormalizeException(&exc, &val, &tb); |
| if (tb != nullptr) { |
| PyException_SetTraceback(val, tb); |
| Py_DECREF(tb); |
| } |
| Py_DECREF(exc); |
| assert(!PyErr_Occurred()); |
| |
| PyErr_SetString(type, message); |
| |
| PyErr_Fetch(&exc, &val2, &tb); |
| PyErr_NormalizeException(&exc, &val2, &tb); |
| Py_INCREF(val); |
| PyException_SetCause(val2, val); |
| PyException_SetContext(val2, val); |
| PyErr_Restore(exc, val2, tb); |
| } |
| |
| /// Sets the current Python error indicator with the chosen error, performing a 'raise from' |
| /// from the error contained in error_already_set to indicate that the chosen error was |
| /// caused by the original error. After this function is called error_already_set will |
| /// no longer contain an error. |
| inline void raise_from(error_already_set& err, PyObject *type, const char *message) { |
| err.restore(); |
| raise_from(type, message); |
| } |
| |
| #endif |
| |
| /** \defgroup python_builtins _ |
| Unless stated otherwise, the following C++ functions behave the same |
| as their Python counterparts. |
| */ |
| |
| /** \ingroup python_builtins |
| \rst |
| Return true if ``obj`` is an instance of ``T``. Type ``T`` must be a subclass of |
| `object` or a class which was exposed to Python as ``py::class_<T>``. |
| \endrst */ |
| template <typename T, detail::enable_if_t<std::is_base_of<object, T>::value, int> = 0> |
| bool isinstance(handle obj) { return T::check_(obj); } |
| |
| template <typename T, detail::enable_if_t<!std::is_base_of<object, T>::value, int> = 0> |
| bool isinstance(handle obj) { return detail::isinstance_generic(obj, typeid(T)); } |
| |
| template <> inline bool isinstance<handle>(handle) = delete; |
| template <> inline bool isinstance<object>(handle obj) { return obj.ptr() != nullptr; } |
| |
| /// \ingroup python_builtins |
| /// Return true if ``obj`` is an instance of the ``type``. |
| inline bool isinstance(handle obj, handle type) { |
| const auto result = PyObject_IsInstance(obj.ptr(), type.ptr()); |
| if (result == -1) |
| throw error_already_set(); |
| return result != 0; |
| } |
| |
| /// \addtogroup python_builtins |
| /// @{ |
| inline bool hasattr(handle obj, handle name) { |
| return PyObject_HasAttr(obj.ptr(), name.ptr()) == 1; |
| } |
| |
| inline bool hasattr(handle obj, const char *name) { |
| return PyObject_HasAttrString(obj.ptr(), name) == 1; |
| } |
| |
| inline void delattr(handle obj, handle name) { |
| if (PyObject_DelAttr(obj.ptr(), name.ptr()) != 0) { throw error_already_set(); } |
| } |
| |
| inline void delattr(handle obj, const char *name) { |
| if (PyObject_DelAttrString(obj.ptr(), name) != 0) { throw error_already_set(); } |
| } |
| |
| inline object getattr(handle obj, handle name) { |
| PyObject *result = PyObject_GetAttr(obj.ptr(), name.ptr()); |
| if (!result) { throw error_already_set(); } |
| return reinterpret_steal<object>(result); |
| } |
| |
| inline object getattr(handle obj, const char *name) { |
| PyObject *result = PyObject_GetAttrString(obj.ptr(), name); |
| if (!result) { throw error_already_set(); } |
| return reinterpret_steal<object>(result); |
| } |
| |
| inline object getattr(handle obj, handle name, handle default_) { |
| if (PyObject *result = PyObject_GetAttr(obj.ptr(), name.ptr())) { |
| return reinterpret_steal<object>(result); |
| } |
| PyErr_Clear(); |
| return reinterpret_borrow<object>(default_); |
| } |
| |
| inline object getattr(handle obj, const char *name, handle default_) { |
| if (PyObject *result = PyObject_GetAttrString(obj.ptr(), name)) { |
| return reinterpret_steal<object>(result); |
| } |
| PyErr_Clear(); |
| return reinterpret_borrow<object>(default_); |
| } |
| |
| inline void setattr(handle obj, handle name, handle value) { |
| if (PyObject_SetAttr(obj.ptr(), name.ptr(), value.ptr()) != 0) { throw error_already_set(); } |
| } |
| |
| inline void setattr(handle obj, const char *name, handle value) { |
| if (PyObject_SetAttrString(obj.ptr(), name, value.ptr()) != 0) { throw error_already_set(); } |
| } |
| |
| inline ssize_t hash(handle obj) { |
| auto h = PyObject_Hash(obj.ptr()); |
| if (h == -1) { throw error_already_set(); } |
| return h; |
| } |
| |
| /// @} python_builtins |
| |
| PYBIND11_NAMESPACE_BEGIN(detail) |
| inline handle get_function(handle value) { |
| if (value) { |
| #if PY_MAJOR_VERSION >= 3 |
| if (PyInstanceMethod_Check(value.ptr())) |
| value = PyInstanceMethod_GET_FUNCTION(value.ptr()); |
| else |
| #endif |
| if (PyMethod_Check(value.ptr())) |
| value = PyMethod_GET_FUNCTION(value.ptr()); |
| } |
| return value; |
| } |
| |
| // Reimplementation of python's dict helper functions to ensure that exceptions |
| // aren't swallowed (see #2862) |
| |
| // copied from cpython _PyDict_GetItemStringWithError |
| inline PyObject * dict_getitemstring(PyObject *v, const char *key) |
| { |
| #if PY_MAJOR_VERSION >= 3 |
| PyObject *kv = nullptr, *rv = nullptr; |
| kv = PyUnicode_FromString(key); |
| if (kv == NULL) { |
| throw error_already_set(); |
| } |
| |
| rv = PyDict_GetItemWithError(v, kv); |
| Py_DECREF(kv); |
| if (rv == NULL && PyErr_Occurred()) { |
| throw error_already_set(); |
| } |
| return rv; |
| #else |
| return PyDict_GetItemString(v, key); |
| #endif |
| } |
| |
| inline PyObject * dict_getitem(PyObject *v, PyObject *key) |
| { |
| #if PY_MAJOR_VERSION >= 3 |
| PyObject *rv = PyDict_GetItemWithError(v, key); |
| if (rv == NULL && PyErr_Occurred()) { |
| throw error_already_set(); |
| } |
| return rv; |
| #else |
| return PyDict_GetItem(v, key); |
| #endif |
| } |
| |
| // Helper aliases/functions to support implicit casting of values given to python accessors/methods. |
| // When given a pyobject, this simply returns the pyobject as-is; for other C++ type, the value goes |
| // through pybind11::cast(obj) to convert it to an `object`. |
| template <typename T, enable_if_t<is_pyobject<T>::value, int> = 0> |
| auto object_or_cast(T &&o) -> decltype(std::forward<T>(o)) { return std::forward<T>(o); } |
| // The following casting version is implemented in cast.h: |
| template <typename T, enable_if_t<!is_pyobject<T>::value, int> = 0> |
| object object_or_cast(T &&o); |
| // Match a PyObject*, which we want to convert directly to handle via its converting constructor |
| inline handle object_or_cast(PyObject *ptr) { return ptr; } |
| |
| #if defined(_MSC_VER) && _MSC_VER < 1920 |
| # pragma warning(push) |
| # pragma warning(disable: 4522) // warning C4522: multiple assignment operators specified |
| #endif |
| template <typename Policy> |
| class accessor : public object_api<accessor<Policy>> { |
| using key_type = typename Policy::key_type; |
| |
| public: |
| accessor(handle obj, key_type key) : obj(obj), key(std::move(key)) { } |
| accessor(const accessor &) = default; |
| accessor(accessor &&) noexcept = default; |
| |
| // accessor overload required to override default assignment operator (templates are not allowed |
| // to replace default compiler-generated assignments). |
| void operator=(const accessor &a) && { std::move(*this).operator=(handle(a)); } |
| void operator=(const accessor &a) & { operator=(handle(a)); } |
| |
| template <typename T> void operator=(T &&value) && { |
| Policy::set(obj, key, object_or_cast(std::forward<T>(value))); |
| } |
| template <typename T> void operator=(T &&value) & { |
| get_cache() = reinterpret_borrow<object>(object_or_cast(std::forward<T>(value))); |
| } |
| |
| template <typename T = Policy> |
| PYBIND11_DEPRECATED("Use of obj.attr(...) as bool is deprecated in favor of pybind11::hasattr(obj, ...)") |
| explicit operator enable_if_t<std::is_same<T, accessor_policies::str_attr>::value || |
| std::is_same<T, accessor_policies::obj_attr>::value, bool>() const { |
| return hasattr(obj, key); |
| } |
| template <typename T = Policy> |
| PYBIND11_DEPRECATED("Use of obj[key] as bool is deprecated in favor of obj.contains(key)") |
| explicit operator enable_if_t<std::is_same<T, accessor_policies::generic_item>::value, bool>() const { |
| return obj.contains(key); |
| } |
| |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| operator object() const { return get_cache(); } |
| PyObject *ptr() const { return get_cache().ptr(); } |
| template <typename T> T cast() const { return get_cache().template cast<T>(); } |
| |
| private: |
| object &get_cache() const { |
| if (!cache) { cache = Policy::get(obj, key); } |
| return cache; |
| } |
| |
| private: |
| handle obj; |
| key_type key; |
| mutable object cache; |
| }; |
| #if defined(_MSC_VER) && _MSC_VER < 1920 |
| # pragma warning(pop) |
| #endif |
| |
| PYBIND11_NAMESPACE_BEGIN(accessor_policies) |
| struct obj_attr { |
| using key_type = object; |
| static object get(handle obj, handle key) { return getattr(obj, key); } |
| static void set(handle obj, handle key, handle val) { setattr(obj, key, val); } |
| }; |
| |
| struct str_attr { |
| using key_type = const char *; |
| static object get(handle obj, const char *key) { return getattr(obj, key); } |
| static void set(handle obj, const char *key, handle val) { setattr(obj, key, val); } |
| }; |
| |
| struct generic_item { |
| using key_type = object; |
| |
| static object get(handle obj, handle key) { |
| PyObject *result = PyObject_GetItem(obj.ptr(), key.ptr()); |
| if (!result) { throw error_already_set(); } |
| return reinterpret_steal<object>(result); |
| } |
| |
| static void set(handle obj, handle key, handle val) { |
| if (PyObject_SetItem(obj.ptr(), key.ptr(), val.ptr()) != 0) { throw error_already_set(); } |
| } |
| }; |
| |
| struct sequence_item { |
| using key_type = size_t; |
| |
| template <typename IdxType, detail::enable_if_t<std::is_integral<IdxType>::value, int> = 0> |
| static object get(handle obj, const IdxType &index) { |
| PyObject *result = PySequence_GetItem(obj.ptr(), ssize_t_cast(index)); |
| if (!result) { throw error_already_set(); } |
| return reinterpret_steal<object>(result); |
| } |
| |
| template <typename IdxType, detail::enable_if_t<std::is_integral<IdxType>::value, int> = 0> |
| static void set(handle obj, const IdxType &index, handle val) { |
| // PySequence_SetItem does not steal a reference to 'val' |
| if (PySequence_SetItem(obj.ptr(), ssize_t_cast(index), val.ptr()) != 0) { |
| throw error_already_set(); |
| } |
| } |
| }; |
| |
| struct list_item { |
| using key_type = size_t; |
| |
| template <typename IdxType, detail::enable_if_t<std::is_integral<IdxType>::value, int> = 0> |
| static object get(handle obj, const IdxType &index) { |
| PyObject *result = PyList_GetItem(obj.ptr(), ssize_t_cast(index)); |
| if (!result) { throw error_already_set(); } |
| return reinterpret_borrow<object>(result); |
| } |
| |
| template <typename IdxType, detail::enable_if_t<std::is_integral<IdxType>::value, int> = 0> |
| static void set(handle obj, const IdxType &index, handle val) { |
| // PyList_SetItem steals a reference to 'val' |
| if (PyList_SetItem(obj.ptr(), ssize_t_cast(index), val.inc_ref().ptr()) != 0) { |
| throw error_already_set(); |
| } |
| } |
| }; |
| |
| struct tuple_item { |
| using key_type = size_t; |
| |
| template <typename IdxType, detail::enable_if_t<std::is_integral<IdxType>::value, int> = 0> |
| static object get(handle obj, const IdxType &index) { |
| PyObject *result = PyTuple_GetItem(obj.ptr(), ssize_t_cast(index)); |
| if (!result) { throw error_already_set(); } |
| return reinterpret_borrow<object>(result); |
| } |
| |
| template <typename IdxType, detail::enable_if_t<std::is_integral<IdxType>::value, int> = 0> |
| static void set(handle obj, const IdxType &index, handle val) { |
| // PyTuple_SetItem steals a reference to 'val' |
| if (PyTuple_SetItem(obj.ptr(), ssize_t_cast(index), val.inc_ref().ptr()) != 0) { |
| throw error_already_set(); |
| } |
| } |
| }; |
| PYBIND11_NAMESPACE_END(accessor_policies) |
| |
| /// STL iterator template used for tuple, list, sequence and dict |
| template <typename Policy> |
| class generic_iterator : public Policy { |
| using It = generic_iterator; |
| |
| public: |
| using difference_type = ssize_t; |
| using iterator_category = typename Policy::iterator_category; |
| using value_type = typename Policy::value_type; |
| using reference = typename Policy::reference; |
| using pointer = typename Policy::pointer; |
| |
| generic_iterator() = default; |
| generic_iterator(handle seq, ssize_t index) : Policy(seq, index) { } |
| |
| // NOLINTNEXTLINE(readability-const-return-type) // PR #3263 |
| reference operator*() const { return Policy::dereference(); } |
| // NOLINTNEXTLINE(readability-const-return-type) // PR #3263 |
| reference operator[](difference_type n) const { return *(*this + n); } |
| pointer operator->() const { return **this; } |
| |
| It &operator++() { Policy::increment(); return *this; } |
| It operator++(int) { auto copy = *this; Policy::increment(); return copy; } |
| It &operator--() { Policy::decrement(); return *this; } |
| It operator--(int) { auto copy = *this; Policy::decrement(); return copy; } |
| It &operator+=(difference_type n) { Policy::advance(n); return *this; } |
| It &operator-=(difference_type n) { Policy::advance(-n); return *this; } |
| |
| friend It operator+(const It &a, difference_type n) { auto copy = a; return copy += n; } |
| friend It operator+(difference_type n, const It &b) { return b + n; } |
| friend It operator-(const It &a, difference_type n) { auto copy = a; return copy -= n; } |
| friend difference_type operator-(const It &a, const It &b) { return a.distance_to(b); } |
| |
| friend bool operator==(const It &a, const It &b) { return a.equal(b); } |
| friend bool operator!=(const It &a, const It &b) { return !(a == b); } |
| friend bool operator< (const It &a, const It &b) { return b - a > 0; } |
| friend bool operator> (const It &a, const It &b) { return b < a; } |
| friend bool operator>=(const It &a, const It &b) { return !(a < b); } |
| friend bool operator<=(const It &a, const It &b) { return !(a > b); } |
| }; |
| |
| PYBIND11_NAMESPACE_BEGIN(iterator_policies) |
| /// Quick proxy class needed to implement ``operator->`` for iterators which can't return pointers |
| template <typename T> |
| struct arrow_proxy { |
| T value; |
| |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| arrow_proxy(T &&value) noexcept : value(std::move(value)) { } |
| T *operator->() const { return &value; } |
| }; |
| |
| /// Lightweight iterator policy using just a simple pointer: see ``PySequence_Fast_ITEMS`` |
| class sequence_fast_readonly { |
| protected: |
| using iterator_category = std::random_access_iterator_tag; |
| using value_type = handle; |
| using reference = const handle; // PR #3263 |
| using pointer = arrow_proxy<const handle>; |
| |
| sequence_fast_readonly(handle obj, ssize_t n) : ptr(PySequence_Fast_ITEMS(obj.ptr()) + n) { } |
| |
| // NOLINTNEXTLINE(readability-const-return-type) // PR #3263 |
| reference dereference() const { return *ptr; } |
| void increment() { ++ptr; } |
| void decrement() { --ptr; } |
| void advance(ssize_t n) { ptr += n; } |
| bool equal(const sequence_fast_readonly &b) const { return ptr == b.ptr; } |
| ssize_t distance_to(const sequence_fast_readonly &b) const { return ptr - b.ptr; } |
| |
| private: |
| PyObject **ptr; |
| }; |
| |
| /// Full read and write access using the sequence protocol: see ``detail::sequence_accessor`` |
| class sequence_slow_readwrite { |
| protected: |
| using iterator_category = std::random_access_iterator_tag; |
| using value_type = object; |
| using reference = sequence_accessor; |
| using pointer = arrow_proxy<const sequence_accessor>; |
| |
| sequence_slow_readwrite(handle obj, ssize_t index) : obj(obj), index(index) { } |
| |
| reference dereference() const { return {obj, static_cast<size_t>(index)}; } |
| void increment() { ++index; } |
| void decrement() { --index; } |
| void advance(ssize_t n) { index += n; } |
| bool equal(const sequence_slow_readwrite &b) const { return index == b.index; } |
| ssize_t distance_to(const sequence_slow_readwrite &b) const { return index - b.index; } |
| |
| private: |
| handle obj; |
| ssize_t index; |
| }; |
| |
| /// Python's dictionary protocol permits this to be a forward iterator |
| class dict_readonly { |
| protected: |
| using iterator_category = std::forward_iterator_tag; |
| using value_type = std::pair<handle, handle>; |
| using reference = const value_type; // PR #3263 |
| using pointer = arrow_proxy<const value_type>; |
| |
| dict_readonly() = default; |
| dict_readonly(handle obj, ssize_t pos) : obj(obj), pos(pos) { increment(); } |
| |
| // NOLINTNEXTLINE(readability-const-return-type) // PR #3263 |
| reference dereference() const { return {key, value}; } |
| void increment() { |
| if (PyDict_Next(obj.ptr(), &pos, &key, &value) == 0) { |
| pos = -1; |
| } |
| } |
| bool equal(const dict_readonly &b) const { return pos == b.pos; } |
| |
| private: |
| handle obj; |
| PyObject *key = nullptr, *value = nullptr; |
| ssize_t pos = -1; |
| }; |
| PYBIND11_NAMESPACE_END(iterator_policies) |
| |
| #if !defined(PYPY_VERSION) |
| using tuple_iterator = generic_iterator<iterator_policies::sequence_fast_readonly>; |
| using list_iterator = generic_iterator<iterator_policies::sequence_fast_readonly>; |
| #else |
| using tuple_iterator = generic_iterator<iterator_policies::sequence_slow_readwrite>; |
| using list_iterator = generic_iterator<iterator_policies::sequence_slow_readwrite>; |
| #endif |
| |
| using sequence_iterator = generic_iterator<iterator_policies::sequence_slow_readwrite>; |
| using dict_iterator = generic_iterator<iterator_policies::dict_readonly>; |
| |
| inline bool PyIterable_Check(PyObject *obj) { |
| PyObject *iter = PyObject_GetIter(obj); |
| if (iter) { |
| Py_DECREF(iter); |
| return true; |
| } |
| PyErr_Clear(); |
| return false; |
| } |
| |
| inline bool PyNone_Check(PyObject *o) { return o == Py_None; } |
| inline bool PyEllipsis_Check(PyObject *o) { return o == Py_Ellipsis; } |
| |
| #ifdef PYBIND11_STR_LEGACY_PERMISSIVE |
| inline bool PyUnicode_Check_Permissive(PyObject *o) { return PyUnicode_Check(o) || PYBIND11_BYTES_CHECK(o); } |
| #define PYBIND11_STR_CHECK_FUN detail::PyUnicode_Check_Permissive |
| #else |
| #define PYBIND11_STR_CHECK_FUN PyUnicode_Check |
| #endif |
| |
| inline bool PyStaticMethod_Check(PyObject *o) { return o->ob_type == &PyStaticMethod_Type; } |
| |
| class kwargs_proxy : public handle { |
| public: |
| explicit kwargs_proxy(handle h) : handle(h) { } |
| }; |
| |
| class args_proxy : public handle { |
| public: |
| explicit args_proxy(handle h) : handle(h) { } |
| kwargs_proxy operator*() const { return kwargs_proxy(*this); } |
| }; |
| |
| /// Python argument categories (using PEP 448 terms) |
| template <typename T> using is_keyword = std::is_base_of<arg, T>; |
| template <typename T> using is_s_unpacking = std::is_same<args_proxy, T>; // * unpacking |
| template <typename T> using is_ds_unpacking = std::is_same<kwargs_proxy, T>; // ** unpacking |
| template <typename T> using is_positional = satisfies_none_of<T, |
| is_keyword, is_s_unpacking, is_ds_unpacking |
| >; |
| template <typename T> using is_keyword_or_ds = satisfies_any_of<T, is_keyword, is_ds_unpacking>; |
| |
| // Call argument collector forward declarations |
| template <return_value_policy policy = return_value_policy::automatic_reference> |
| class simple_collector; |
| template <return_value_policy policy = return_value_policy::automatic_reference> |
| class unpacking_collector; |
| |
| PYBIND11_NAMESPACE_END(detail) |
| |
| // TODO: After the deprecated constructors are removed, this macro can be simplified by |
| // inheriting ctors: `using Parent::Parent`. It's not an option right now because |
| // the `using` statement triggers the parent deprecation warning even if the ctor |
| // isn't even used. |
| #define PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \ |
| public: \ |
| PYBIND11_DEPRECATED("Use reinterpret_borrow<"#Name">() or reinterpret_steal<"#Name">()") \ |
| Name(handle h, bool is_borrowed) : Parent(is_borrowed ? Parent(h, borrowed_t{}) : Parent(h, stolen_t{})) { } \ |
| Name(handle h, borrowed_t) : Parent(h, borrowed_t{}) { } \ |
| Name(handle h, stolen_t) : Parent(h, stolen_t{}) { } \ |
| PYBIND11_DEPRECATED("Use py::isinstance<py::python_type>(obj) instead") \ |
| bool check() const { return m_ptr != nullptr && (CheckFun(m_ptr) != 0); } \ |
| static bool check_(handle h) { return h.ptr() != nullptr && CheckFun(h.ptr()); } \ |
| template <typename Policy_> \ |
| /* NOLINTNEXTLINE(google-explicit-constructor) */ \ |
| Name(const ::pybind11::detail::accessor<Policy_> &a) : Name(object(a)) { } |
| |
| #define PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun) \ |
| PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \ |
| /* This is deliberately not 'explicit' to allow implicit conversion from object: */ \ |
| /* NOLINTNEXTLINE(google-explicit-constructor) */ \ |
| Name(const object &o) \ |
| : Parent(check_(o) ? o.inc_ref().ptr() : ConvertFun(o.ptr()), stolen_t{}) \ |
| { if (!m_ptr) throw error_already_set(); } \ |
| /* NOLINTNEXTLINE(google-explicit-constructor) */ \ |
| Name(object &&o) \ |
| : Parent(check_(o) ? o.release().ptr() : ConvertFun(o.ptr()), stolen_t{}) \ |
| { if (!m_ptr) throw error_already_set(); } |
| |
| #define PYBIND11_OBJECT_CVT_DEFAULT(Name, Parent, CheckFun, ConvertFun) \ |
| PYBIND11_OBJECT_CVT(Name, Parent, CheckFun, ConvertFun) \ |
| Name() : Parent() { } |
| |
| #define PYBIND11_OBJECT_CHECK_FAILED(Name, o_ptr) \ |
| ::pybind11::type_error("Object of type '" + \ |
| ::pybind11::detail::get_fully_qualified_tp_name(Py_TYPE(o_ptr)) + \ |
| "' is not an instance of '" #Name "'") |
| |
| #define PYBIND11_OBJECT(Name, Parent, CheckFun) \ |
| PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \ |
| /* This is deliberately not 'explicit' to allow implicit conversion from object: */ \ |
| /* NOLINTNEXTLINE(google-explicit-constructor) */ \ |
| Name(const object &o) : Parent(o) \ |
| { if (m_ptr && !check_(m_ptr)) throw PYBIND11_OBJECT_CHECK_FAILED(Name, m_ptr); } \ |
| /* NOLINTNEXTLINE(google-explicit-constructor) */ \ |
| Name(object &&o) : Parent(std::move(o)) \ |
| { if (m_ptr && !check_(m_ptr)) throw PYBIND11_OBJECT_CHECK_FAILED(Name, m_ptr); } |
| |
| #define PYBIND11_OBJECT_DEFAULT(Name, Parent, CheckFun) \ |
| PYBIND11_OBJECT(Name, Parent, CheckFun) \ |
| Name() : Parent() { } |
| |
| /// \addtogroup pytypes |
| /// @{ |
| |
| /** \rst |
| Wraps a Python iterator so that it can also be used as a C++ input iterator |
| |
| Caveat: copying an iterator does not (and cannot) clone the internal |
| state of the Python iterable. This also applies to the post-increment |
| operator. This iterator should only be used to retrieve the current |
| value using ``operator*()``. |
| \endrst */ |
| class iterator : public object { |
| public: |
| using iterator_category = std::input_iterator_tag; |
| using difference_type = ssize_t; |
| using value_type = handle; |
| using reference = const handle; // PR #3263 |
| using pointer = const handle *; |
| |
| PYBIND11_OBJECT_DEFAULT(iterator, object, PyIter_Check) |
| |
| iterator& operator++() { |
| advance(); |
| return *this; |
| } |
| |
| iterator operator++(int) { |
| auto rv = *this; |
| advance(); |
| return rv; |
| } |
| |
| // NOLINTNEXTLINE(readability-const-return-type) // PR #3263 |
| reference operator*() const { |
| if (m_ptr && !value.ptr()) { |
| auto& self = const_cast<iterator &>(*this); |
| self.advance(); |
| } |
| return value; |
| } |
| |
| pointer operator->() const { operator*(); return &value; } |
| |
| /** \rst |
| The value which marks the end of the iteration. ``it == iterator::sentinel()`` |
| is equivalent to catching ``StopIteration`` in Python. |
| |
| .. code-block:: cpp |
| |
| void foo(py::iterator it) { |
| while (it != py::iterator::sentinel()) { |
| // use `*it` |
| ++it; |
| } |
| } |
| \endrst */ |
| static iterator sentinel() { return {}; } |
| |
| 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: |
| void advance() { |
| value = reinterpret_steal<object>(PyIter_Next(m_ptr)); |
| if (PyErr_Occurred()) { throw error_already_set(); } |
| } |
| |
| private: |
| object value = {}; |
| }; |
| |
| |
| |
| class type : public object { |
| public: |
| PYBIND11_OBJECT(type, object, PyType_Check) |
| |
| /// Return a type handle from a handle or an object |
| static handle handle_of(handle h) { return handle((PyObject*) Py_TYPE(h.ptr())); } |
| |
| /// Return a type object from a handle or an object |
| static type of(handle h) { return type(type::handle_of(h), borrowed_t{}); } |
| |
| // Defined in pybind11/cast.h |
| /// Convert C++ type to handle if previously registered. Does not convert |
| /// standard types, like int, float. etc. yet. |
| /// See https://github.com/pybind/pybind11/issues/2486 |
| template<typename T> |
| static handle handle_of(); |
| |
| /// Convert C++ type to type if previously registered. Does not convert |
| /// standard types, like int, float. etc. yet. |
| /// See https://github.com/pybind/pybind11/issues/2486 |
| template<typename T> |
| static type of() {return type(type::handle_of<T>(), borrowed_t{}); } |
| }; |
| |
| class iterable : public object { |
| public: |
| PYBIND11_OBJECT_DEFAULT(iterable, object, detail::PyIterable_Check) |
| }; |
| |
| class bytes; |
| |
| class str : public object { |
| public: |
| PYBIND11_OBJECT_CVT(str, object, PYBIND11_STR_CHECK_FUN, raw_str) |
| |
| template <typename SzType, detail::enable_if_t<std::is_integral<SzType>::value, int> = 0> |
| str(const char *c, const SzType &n) |
| : object(PyUnicode_FromStringAndSize(c, ssize_t_cast(n)), stolen_t{}) { |
| if (!m_ptr) pybind11_fail("Could not allocate string object!"); |
| } |
| |
| // 'explicit' is explicitly omitted from the following constructors to allow implicit conversion to py::str from C++ string-like objects |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| str(const char *c = "") |
| : object(PyUnicode_FromString(c), stolen_t{}) { |
| if (!m_ptr) pybind11_fail("Could not allocate string object!"); |
| } |
| |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| str(const std::string &s) : str(s.data(), s.size()) { } |
| |
| explicit str(const bytes &b); |
| |
| /** \rst |
| Return a string representation of the object. This is analogous to |
| the ``str()`` function in Python. |
| \endrst */ |
| explicit str(handle h) : object(raw_str(h.ptr()), stolen_t{}) { if (!m_ptr) throw error_already_set(); } |
| |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| operator std::string() const { |
| object temp = *this; |
| if (PyUnicode_Check(m_ptr)) { |
| temp = reinterpret_steal<object>(PyUnicode_AsUTF8String(m_ptr)); |
| if (!temp) |
| throw error_already_set(); |
| } |
| char *buffer = nullptr; |
| ssize_t length = 0; |
| if (PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length)) |
| pybind11_fail("Unable to extract string contents! (invalid type)"); |
| return std::string(buffer, (size_t) length); |
| } |
| |
| template <typename... Args> |
| str format(Args &&...args) const { |
| return attr("format")(std::forward<Args>(args)...); |
| } |
| |
| private: |
| /// Return string representation -- always returns a new reference, even if already a str |
| static PyObject *raw_str(PyObject *op) { |
| PyObject *str_value = PyObject_Str(op); |
| #if PY_MAJOR_VERSION < 3 |
| if (!str_value) throw error_already_set(); |
| PyObject *unicode = PyUnicode_FromEncodedObject(str_value, "utf-8", nullptr); |
| Py_XDECREF(str_value); str_value = unicode; |
| #endif |
| return str_value; |
| } |
| }; |
| /// @} pytypes |
| |
| inline namespace literals { |
| /** \rst |
| String literal version of `str` |
| \endrst */ |
| inline str operator"" _s(const char *s, size_t size) { return {s, size}; } |
| } // namespace literals |
| |
| /// \addtogroup pytypes |
| /// @{ |
| class bytes : public object { |
| public: |
| PYBIND11_OBJECT(bytes, object, PYBIND11_BYTES_CHECK) |
| |
| // Allow implicit conversion: |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| bytes(const char *c = "") |
| : object(PYBIND11_BYTES_FROM_STRING(c), stolen_t{}) { |
| if (!m_ptr) pybind11_fail("Could not allocate bytes object!"); |
| } |
| |
| template <typename SzType, detail::enable_if_t<std::is_integral<SzType>::value, int> = 0> |
| bytes(const char *c, const SzType &n) |
| : object(PYBIND11_BYTES_FROM_STRING_AND_SIZE(c, ssize_t_cast(n)), stolen_t{}) { |
| if (!m_ptr) pybind11_fail("Could not allocate bytes object!"); |
| } |
| |
| // Allow implicit conversion: |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| bytes(const std::string &s) : bytes(s.data(), s.size()) { } |
| |
| explicit bytes(const pybind11::str &s); |
| |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| operator std::string() const { |
| char *buffer = nullptr; |
| ssize_t length = 0; |
| if (PYBIND11_BYTES_AS_STRING_AND_SIZE(m_ptr, &buffer, &length)) |
| pybind11_fail("Unable to extract bytes contents!"); |
| return std::string(buffer, (size_t) length); |
| } |
| }; |
| // Note: breathe >= 4.17.0 will fail to build docs if the below two constructors |
| // are included in the doxygen group; close here and reopen after as a workaround |
| /// @} pytypes |
| |
| inline bytes::bytes(const pybind11::str &s) { |
| object temp = s; |
| if (PyUnicode_Check(s.ptr())) { |
| temp = reinterpret_steal<object>(PyUnicode_AsUTF8String(s.ptr())); |
| if (!temp) |
| pybind11_fail("Unable to extract string contents! (encoding issue)"); |
| } |
| char *buffer = nullptr; |
| ssize_t length = 0; |
| if (PYBIND11_BYTES_AS_STRING_AND_SIZE(temp.ptr(), &buffer, &length)) |
| pybind11_fail("Unable to extract string contents! (invalid type)"); |
| auto obj = reinterpret_steal<object>(PYBIND11_BYTES_FROM_STRING_AND_SIZE(buffer, length)); |
| if (!obj) |
| pybind11_fail("Could not allocate bytes object!"); |
| m_ptr = obj.release().ptr(); |
| } |
| |
| inline str::str(const bytes& b) { |
| char *buffer = nullptr; |
| ssize_t length = 0; |
| if (PYBIND11_BYTES_AS_STRING_AND_SIZE(b.ptr(), &buffer, &length)) |
| pybind11_fail("Unable to extract bytes contents!"); |
| auto obj = reinterpret_steal<object>(PyUnicode_FromStringAndSize(buffer, length)); |
| if (!obj) |
| pybind11_fail("Could not allocate string object!"); |
| m_ptr = obj.release().ptr(); |
| } |
| |
| /// \addtogroup pytypes |
| /// @{ |
| class bytearray : public object { |
| public: |
| PYBIND11_OBJECT_CVT(bytearray, object, PyByteArray_Check, PyByteArray_FromObject) |
| |
| template <typename SzType, detail::enable_if_t<std::is_integral<SzType>::value, int> = 0> |
| bytearray(const char *c, const SzType &n) |
| : object(PyByteArray_FromStringAndSize(c, ssize_t_cast(n)), stolen_t{}) { |
| if (!m_ptr) pybind11_fail("Could not allocate bytearray object!"); |
| } |
| |
| bytearray() |
| : bytearray("", 0) {} |
| |
| explicit bytearray(const std::string &s) : bytearray(s.data(), s.size()) { } |
| |
| size_t size() const { return static_cast<size_t>(PyByteArray_Size(m_ptr)); } |
| |
| explicit operator std::string() const { |
| char *buffer = PyByteArray_AS_STRING(m_ptr); |
| ssize_t size = PyByteArray_GET_SIZE(m_ptr); |
| return std::string(buffer, static_cast<size_t>(size)); |
| } |
| }; |
| // Note: breathe >= 4.17.0 will fail to build docs if the below two constructors |
| // are included in the doxygen group; close here and reopen after as a workaround |
| /// @} pytypes |
| |
| /// \addtogroup pytypes |
| /// @{ |
| class none : public object { |
| public: |
| PYBIND11_OBJECT(none, object, detail::PyNone_Check) |
| none() : object(Py_None, borrowed_t{}) { } |
| }; |
| |
| class ellipsis : public object { |
| public: |
| PYBIND11_OBJECT(ellipsis, object, detail::PyEllipsis_Check) |
| ellipsis() : object(Py_Ellipsis, borrowed_t{}) { } |
| }; |
| |
| class bool_ : public object { |
| public: |
| PYBIND11_OBJECT_CVT(bool_, object, PyBool_Check, raw_bool) |
| bool_() : object(Py_False, borrowed_t{}) { } |
| // Allow implicit conversion from and to `bool`: |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| bool_(bool value) : object(value ? Py_True : Py_False, borrowed_t{}) { } |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| operator bool() const { return (m_ptr != nullptr) && PyLong_AsLong(m_ptr) != 0; } |
| |
| private: |
| /// Return the truth value of an object -- always returns a new reference |
| static PyObject *raw_bool(PyObject *op) { |
| const auto value = PyObject_IsTrue(op); |
| if (value == -1) return nullptr; |
| return handle(value != 0 ? Py_True : Py_False).inc_ref().ptr(); |
| } |
| }; |
| |
| PYBIND11_NAMESPACE_BEGIN(detail) |
| // Converts a value to the given unsigned type. If an error occurs, you get back (Unsigned) -1; |
| // otherwise you get back the unsigned long or unsigned long long value cast to (Unsigned). |
| // (The distinction is critically important when casting a returned -1 error value to some other |
| // unsigned type: (A)-1 != (B)-1 when A and B are unsigned types of different sizes). |
| template <typename Unsigned> |
| Unsigned as_unsigned(PyObject *o) { |
| if (PYBIND11_SILENCE_MSVC_C4127(sizeof(Unsigned) <= sizeof(unsigned long)) |
| #if PY_VERSION_HEX < 0x03000000 |
| || PyInt_Check(o) |
| #endif |
| ) { |
| unsigned long v = PyLong_AsUnsignedLong(o); |
| return v == (unsigned long) -1 && PyErr_Occurred() ? (Unsigned) -1 : (Unsigned) v; |
| } |
| unsigned long long v = PyLong_AsUnsignedLongLong(o); |
| return v == (unsigned long long) -1 && PyErr_Occurred() ? (Unsigned) -1 : (Unsigned) v; |
| } |
| PYBIND11_NAMESPACE_END(detail) |
| |
| class int_ : public object { |
| public: |
| PYBIND11_OBJECT_CVT(int_, object, PYBIND11_LONG_CHECK, PyNumber_Long) |
| int_() : object(PyLong_FromLong(0), stolen_t{}) { } |
| // Allow implicit conversion from C++ integral types: |
| template <typename T, |
| detail::enable_if_t<std::is_integral<T>::value, int> = 0> |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| int_(T value) { |
| if (PYBIND11_SILENCE_MSVC_C4127(sizeof(T) <= sizeof(long))) { |
| if (std::is_signed<T>::value) |
| m_ptr = PyLong_FromLong((long) value); |
| else |
| m_ptr = PyLong_FromUnsignedLong((unsigned long) value); |
| } else { |
| if (std::is_signed<T>::value) |
| m_ptr = PyLong_FromLongLong((long long) value); |
| else |
| m_ptr = PyLong_FromUnsignedLongLong((unsigned long long) value); |
| } |
| if (!m_ptr) pybind11_fail("Could not allocate int object!"); |
| } |
| |
| template <typename T, |
| detail::enable_if_t<std::is_integral<T>::value, int> = 0> |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| operator T() const { |
| return std::is_unsigned<T>::value |
| ? detail::as_unsigned<T>(m_ptr) |
| : sizeof(T) <= sizeof(long) |
| ? (T) PyLong_AsLong(m_ptr) |
| : (T) PYBIND11_LONG_AS_LONGLONG(m_ptr); |
| } |
| }; |
| |
| class float_ : public object { |
| public: |
| PYBIND11_OBJECT_CVT(float_, object, PyFloat_Check, PyNumber_Float) |
| // Allow implicit conversion from float/double: |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| float_(float value) : object(PyFloat_FromDouble((double) value), stolen_t{}) { |
| if (!m_ptr) pybind11_fail("Could not allocate float object!"); |
| } |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| float_(double value = .0) : object(PyFloat_FromDouble((double) value), stolen_t{}) { |
| if (!m_ptr) pybind11_fail("Could not allocate float object!"); |
| } |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| operator float() const { return (float) PyFloat_AsDouble(m_ptr); } |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| operator double() const { return (double) PyFloat_AsDouble(m_ptr); } |
| }; |
| |
| class weakref : public object { |
| public: |
| PYBIND11_OBJECT_CVT_DEFAULT(weakref, object, PyWeakref_Check, raw_weakref) |
| explicit weakref(handle obj, handle callback = {}) |
| : object(PyWeakref_NewRef(obj.ptr(), callback.ptr()), stolen_t{}) { |
| if (!m_ptr) pybind11_fail("Could not allocate weak reference!"); |
| } |
| |
| private: |
| static PyObject *raw_weakref(PyObject *o) { |
| return PyWeakref_NewRef(o, nullptr); |
| } |
| }; |
| |
| class slice : public object { |
| public: |
| PYBIND11_OBJECT_DEFAULT(slice, object, PySlice_Check) |
| slice(handle start, handle stop, handle step) { |
| m_ptr = PySlice_New(start.ptr(), stop.ptr(), step.ptr()); |
| if (!m_ptr) |
| pybind11_fail("Could not allocate slice object!"); |
| } |
| |
| #ifdef PYBIND11_HAS_OPTIONAL |
| slice(std::optional<ssize_t> start, std::optional<ssize_t> stop, std::optional<ssize_t> step) |
| : slice(index_to_object(start), index_to_object(stop), index_to_object(step)) {} |
| #else |
| slice(ssize_t start_, ssize_t stop_, ssize_t step_) |
| : slice(int_(start_), int_(stop_), int_(step_)) {} |
| #endif |
| |
| bool compute(size_t length, size_t *start, size_t *stop, size_t *step, |
| size_t *slicelength) const { |
| return PySlice_GetIndicesEx((PYBIND11_SLICE_OBJECT *) m_ptr, |
| (ssize_t) length, (ssize_t *) start, |
| (ssize_t *) stop, (ssize_t *) step, |
| (ssize_t *) slicelength) == 0; |
| } |
| bool compute(ssize_t length, ssize_t *start, ssize_t *stop, ssize_t *step, |
| ssize_t *slicelength) const { |
| return PySlice_GetIndicesEx((PYBIND11_SLICE_OBJECT *) m_ptr, |
| length, start, |
| stop, step, |
| slicelength) == 0; |
| } |
| |
| private: |
| template <typename T> |
| static object index_to_object(T index) { |
| return index ? object(int_(*index)) : object(none()); |
| } |
| }; |
| |
| class capsule : public object { |
| public: |
| PYBIND11_OBJECT_DEFAULT(capsule, object, PyCapsule_CheckExact) |
| PYBIND11_DEPRECATED("Use reinterpret_borrow<capsule>() or reinterpret_steal<capsule>()") |
| capsule(PyObject *ptr, bool is_borrowed) : object(is_borrowed ? object(ptr, borrowed_t{}) : object(ptr, stolen_t{})) { } |
| |
| explicit capsule(const void *value, const char *name = nullptr, void (*destructor)(PyObject *) = nullptr) |
| : object(PyCapsule_New(const_cast<void *>(value), name, destructor), stolen_t{}) { |
| if (!m_ptr) |
| pybind11_fail("Could not allocate capsule object!"); |
| } |
| |
| PYBIND11_DEPRECATED("Please pass a destructor that takes a void pointer as input") |
| capsule(const void *value, void (*destruct)(PyObject *)) |
| : object(PyCapsule_New(const_cast<void*>(value), nullptr, destruct), stolen_t{}) { |
| if (!m_ptr) |
| pybind11_fail("Could not allocate capsule object!"); |
| } |
| |
| capsule(const void *value, void (*destructor)(void *)) { |
| m_ptr = PyCapsule_New(const_cast<void *>(value), nullptr, [](PyObject *o) { |
| auto destructor = reinterpret_cast<void (*)(void *)>(PyCapsule_GetContext(o)); |
| void *ptr = PyCapsule_GetPointer(o, nullptr); |
| destructor(ptr); |
| }); |
| |
| if (!m_ptr) |
| pybind11_fail("Could not allocate capsule object!"); |
| |
| if (PyCapsule_SetContext(m_ptr, (void *) destructor) != 0) |
| pybind11_fail("Could not set capsule context!"); |
| } |
| |
| explicit capsule(void (*destructor)()) { |
| m_ptr = PyCapsule_New(reinterpret_cast<void *>(destructor), nullptr, [](PyObject *o) { |
| auto destructor = reinterpret_cast<void (*)()>(PyCapsule_GetPointer(o, nullptr)); |
| destructor(); |
| }); |
| |
| if (!m_ptr) |
| pybind11_fail("Could not allocate capsule object!"); |
| } |
| |
| // NOLINTNEXTLINE(google-explicit-constructor) |
| template <typename T> operator T *() const { |
| return get_pointer<T>(); |
| } |
| |
| /// Get the pointer the capsule holds. |
| template<typename T = void> |
| T* get_pointer() const { |
| auto name = this->name(); |
| T *result = static_cast<T *>(PyCapsule_GetPointer(m_ptr, name)); |
| if (!result) { |
| PyErr_Clear(); |
| pybind11_fail("Unable to extract capsule contents!"); |
| } |
| return result; |
| } |
| |
| /// Replaces a capsule's pointer *without* calling the destructor on the existing one. |
| void set_pointer(const void *value) { |
| if (PyCapsule_SetPointer(m_ptr, const_cast<void *>(value)) != 0) { |
| PyErr_Clear(); |
| pybind11_fail("Could not set capsule pointer"); |
| } |
| } |
| |
| const char *name() const { return PyCapsule_GetName(m_ptr); } |
| }; |
| |
| class tuple : public object { |
| public: |
| PYBIND11_OBJECT_CVT(tuple, object, PyTuple_Check, PySequence_Tuple) |
| template <typename SzType = ssize_t, |
| detail::enable_if_t<std::is_integral<SzType>::value, int> = 0> |
| // Some compilers generate link errors when using `const SzType &` here: |
| explicit tuple(SzType size = 0) : object(PyTuple_New(ssize_t_cast(size)), stolen_t{}) { |
| if (!m_ptr) pybind11_fail("Could not allocate tuple 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}; } |
| detail::item_accessor operator[](handle h) const { return object::operator[](h); } |
| detail::tuple_iterator begin() const { return {*this, 0}; } |
| detail::tuple_iterator end() const { return {*this, PyTuple_GET_SIZE(m_ptr)}; } |
| }; |
| |
| // We need to put this into a separate function because the Intel compiler |
| // fails to compile enable_if_t<all_of<is_keyword_or_ds<Args>...>::value> part below |
| // (tested with ICC 2021.1 Beta 20200827). |
| template <typename... Args> |
| constexpr bool args_are_all_keyword_or_ds() |
| { |
| return detail::all_of<detail::is_keyword_or_ds<Args>...>::value; |
| } |
| |
| class dict : public object { |
| public: |
| PYBIND11_OBJECT_CVT(dict, object, PyDict_Check, raw_dict) |
| dict() : object(PyDict_New(), stolen_t{}) { |
| if (!m_ptr) pybind11_fail("Could not allocate dict object!"); |
| } |
| template <typename... Args, |
| typename = detail::enable_if_t<args_are_all_keyword_or_ds<Args...>()>, |
| // MSVC workaround: it can't compile an out-of-line definition, so defer the collector |
| typename collector = detail::deferred_t<detail::unpacking_collector<>, Args...>> |
| explicit dict(Args &&...args) : dict(collector(std::forward<Args>(args)...).kwargs()) { } |
| |
| size_t size() const { return (size_t) PyDict_Size(m_ptr); } |
| bool empty() const { return size() == 0; } |
| detail::dict_iterator begin() const { return {*this, 0}; } |
| detail::dict_iterator end() const { return {}; } |
| void clear() /* py-non-const */ { PyDict_Clear(ptr()); } |
| template <typename T> bool contains(T &&key) const { |
| return PyDict_Contains(m_ptr, detail::object_or_cast(std::forward<T>(key)).ptr()) == 1; |
| } |
| |
| private: |
| /// Call the `dict` Python type -- always returns a new reference |
| static PyObject *raw_dict(PyObject *op) { |
| if (PyDict_Check(op)) |
| return handle(op).inc_ref().ptr(); |
| return PyObject_CallFunctionObjArgs((PyObject *) &PyDict_Type, op, nullptr); |
| } |
| }; |
| |
| class sequence : public object { |
| public: |
| PYBIND11_OBJECT_DEFAULT(sequence, object, PySequence_Check) |
| size_t size() const { |
| ssize_t result = PySequence_Size(m_ptr); |
| if (result == -1) |
| throw error_already_set(); |
| return (size_t) result; |
| } |
| bool empty() const { return size() == 0; } |
| detail::sequence_accessor operator[](size_t index) const { return {*this, index}; } |
| detail::item_accessor operator[](handle h) const { return object::operator[](h); } |
| detail::sequence_iterator begin() const { return {*this, 0}; } |
| detail::sequence_iterator end() const { return {*this, PySequence_Size(m_ptr)}; } |
| }; |
| |
| class list : public object { |
| public: |
| PYBIND11_OBJECT_CVT(list, object, PyList_Check, PySequence_List) |
| template <typename SzType = ssize_t, |
| detail::enable_if_t<std::is_integral<SzType>::value, int> = 0> |
| // Some compilers generate link errors when using `const SzType &` here: |
| explicit list(SzType size = 0) : object(PyList_New(ssize_t_cast(size)), stolen_t{}) { |
| if (!m_ptr) pybind11_fail("Could not allocate list 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}; } |
| detail::item_accessor operator[](handle h) const { return object::operator[](h); } |
| detail::list_iterator begin() const { return {*this, 0}; } |
| detail::list_iterator end() const { return {*this, PyList_GET_SIZE(m_ptr)}; } |
| template <typename T> void append(T &&val) /* py-non-const */ { |
| PyList_Append(m_ptr, detail::object_or_cast(std::forward<T>(val)).ptr()); |
| } |
| template <typename IdxType, |
| typename ValType, |
| detail::enable_if_t<std::is_integral<IdxType>::value, int> = 0> |
| void insert(const IdxType &index, ValType &&val) /* py-non-const */ { |
| PyList_Insert( |
| m_ptr, ssize_t_cast(index), detail::object_or_cast(std::forward<ValType>(val)).ptr()); |
| } |
| }; |
| |
| class args : public tuple { PYBIND11_OBJECT_DEFAULT(args, tuple, PyTuple_Check) }; |
| class kwargs : public dict { PYBIND11_OBJECT_DEFAULT(kwargs, dict, PyDict_Check) }; |
| |
| class set : public object { |
| public: |
| PYBIND11_OBJECT_CVT(set, object, PySet_Check, PySet_New) |
| set() : object(PySet_New(nullptr), stolen_t{}) { |
| if (!m_ptr) pybind11_fail("Could not allocate set object!"); |
| } |
| size_t size() const { return (size_t) PySet_Size(m_ptr); } |
| bool empty() const { return size() == 0; } |
| template <typename T> bool add(T &&val) /* py-non-const */ { |
| return PySet_Add(m_ptr, detail::object_or_cast(std::forward<T>(val)).ptr()) == 0; |
| } |
| void clear() /* py-non-const */ { PySet_Clear(m_ptr); } |
| template <typename T> bool contains(T &&val) const { |
| return PySet_Contains(m_ptr, detail::object_or_cast(std::forward<T>(val)).ptr()) == 1; |
| } |
| }; |
| |
| class function : public object { |
| public: |
| PYBIND11_OBJECT_DEFAULT(function, object, PyCallable_Check) |
| handle cpp_function() const { |
| handle fun = detail::get_function(m_ptr); |
| if (fun && PyCFunction_Check(fun.ptr())) |
| return fun; |
| return handle(); |
| } |
| bool is_cpp_function() const { return (bool) cpp_function(); } |
| }; |
| |
| class staticmethod : public object { |
| public: |
| PYBIND11_OBJECT_CVT(staticmethod, object, detail::PyStaticMethod_Check, PyStaticMethod_New) |
| }; |
| |
| class buffer : public object { |
| public: |
| PYBIND11_OBJECT_DEFAULT(buffer, object, PyObject_CheckBuffer) |
| |
| buffer_info request(bool writable = false) const { |
| int flags = PyBUF_STRIDES | PyBUF_FORMAT; |
| if (writable) flags |= PyBUF_WRITABLE; |
| auto *view = new Py_buffer(); |
| if (PyObject_GetBuffer(m_ptr, view, flags) != 0) { |
| delete view; |
| throw error_already_set(); |
| } |
| return buffer_info(view); |
| } |
| }; |
| |
| class memoryview : public object { |
| public: |
| PYBIND11_OBJECT_CVT(memoryview, object, PyMemoryView_Check, PyMemoryView_FromObject) |
| |
| /** \rst |
| Creates ``memoryview`` from ``buffer_info``. |
| |
| ``buffer_info`` must be created from ``buffer::request()``. Otherwise |
| throws an exception. |
| |
| For creating a ``memoryview`` from objects that support buffer protocol, |
| use ``memoryview(const object& obj)`` instead of this constructor. |
| \endrst */ |
| explicit memoryview(const buffer_info& info) { |
| if (!info.view()) |
| pybind11_fail("Prohibited to create memoryview without Py_buffer"); |
| // Note: PyMemoryView_FromBuffer never increments obj reference. |
| m_ptr = (info.view()->obj) ? |
| PyMemoryView_FromObject(info.view()->obj) : |
| PyMemoryView_FromBuffer(info.view()); |
| if (!m_ptr) |
| pybind11_fail("Unable to create memoryview from buffer descriptor"); |
| } |
| |
| /** \rst |
| Creates ``memoryview`` from static buffer. |
| |
| This method is meant for providing a ``memoryview`` for C/C++ buffer not |
| managed by Python. The caller is responsible for managing the lifetime |
| of ``ptr`` and ``format``, which MUST outlive the memoryview constructed |
| here. |
| |
| See also: Python C API documentation for `PyMemoryView_FromBuffer`_. |
| |
| .. _PyMemoryView_FromBuffer: https://docs.python.org/c-api/memoryview.html#c.PyMemoryView_FromBuffer |
| |
| :param ptr: Pointer to the buffer. |
| :param itemsize: Byte size of an element. |
| :param format: Pointer to the null-terminated format string. For |
| homogeneous Buffers, this should be set to |
| ``format_descriptor<T>::value``. |
| :param shape: Shape of the tensor (1 entry per dimension). |
| :param strides: Number of bytes between adjacent entries (for each |
| per dimension). |
| :param readonly: Flag to indicate if the underlying storage may be |
| written to. |
| \endrst */ |
| static memoryview from_buffer( |
| void *ptr, ssize_t itemsize, const char *format, |
| detail::any_container<ssize_t> shape, |
| detail::any_container<ssize_t> strides, bool readonly = false); |
| |
| static memoryview from_buffer( |
| const void *ptr, ssize_t itemsize, const char *format, |
| detail::any_container<ssize_t> shape, |
| detail::any_container<ssize_t> strides) { |
| return memoryview::from_buffer( |
| const_cast<void *>(ptr), itemsize, format, std::move(shape), std::move(strides), true); |
| } |
| |
| template<typename T> |
| static memoryview from_buffer( |
| T *ptr, detail::any_container<ssize_t> shape, |
| detail::any_container<ssize_t> strides, bool readonly = false) { |
| return memoryview::from_buffer( |
| reinterpret_cast<void*>(ptr), sizeof(T), |
| format_descriptor<T>::value, shape, strides, readonly); |
| } |
| |
| template<typename T> |
| static memoryview from_buffer( |
| const T *ptr, detail::any_container<ssize_t> shape, |
| detail::any_container<ssize_t> strides) { |
| return memoryview::from_buffer( |
| const_cast<T*>(ptr), shape, strides, true); |
| } |
| |
| #if PY_MAJOR_VERSION >= 3 |
| /** \rst |
| Creates ``memoryview`` from static memory. |
| |
| This method is meant for providing a ``memoryview`` for C/C++ buffer not |
| managed by Python. The caller is responsible for managing the lifetime |
| of ``mem``, which MUST outlive the memoryview constructed here. |
| |
| This method is not available in Python 2. |
| |
| See also: Python C API documentation for `PyMemoryView_FromBuffer`_. |
| |
| .. _PyMemoryView_FromMemory: https://docs.python.org/c-api/memoryview.html#c.PyMemoryView_FromMemory |
| \endrst */ |
| static memoryview from_memory(void *mem, ssize_t size, bool readonly = false) { |
| PyObject* ptr = PyMemoryView_FromMemory( |
| reinterpret_cast<char*>(mem), size, |
| (readonly) ? PyBUF_READ : PyBUF_WRITE); |
| if (!ptr) |
| pybind11_fail("Could not allocate memoryview object!"); |
| return memoryview(object(ptr, stolen_t{})); |
| } |
| |
| static memoryview from_memory(const void *mem, ssize_t size) { |
| return memoryview::from_memory(const_cast<void*>(mem), size, true); |
| } |
| #endif |
| }; |
| |
| #ifndef DOXYGEN_SHOULD_SKIP_THIS |
| inline memoryview memoryview::from_buffer( |
| void *ptr, ssize_t itemsize, const char* format, |
| detail::any_container<ssize_t> shape, |
| detail::any_container<ssize_t> strides, bool readonly) { |
| size_t ndim = shape->size(); |
| if (ndim != strides->size()) |
| pybind11_fail("memoryview: shape length doesn't match strides length"); |
| ssize_t size = ndim != 0u ? 1 : 0; |
| for (size_t i = 0; i < ndim; ++i) |
| size *= (*shape)[i]; |
| Py_buffer view; |
| view.buf = ptr; |
| view.obj = nullptr; |
| view.len = size * itemsize; |
| view.readonly = static_cast<int>(readonly); |
| view.itemsize = itemsize; |
| view.format = const_cast<char*>(format); |
| view.ndim = static_cast<int>(ndim); |
| view.shape = shape->data(); |
| view.strides = strides->data(); |
| view.suboffsets = nullptr; |
| view.internal = nullptr; |
| PyObject* obj = PyMemoryView_FromBuffer(&view); |
| if (!obj) |
| throw error_already_set(); |
| return memoryview(object(obj, stolen_t{})); |
| } |
| #endif // DOXYGEN_SHOULD_SKIP_THIS |
| /// @} pytypes |
| |
| /// \addtogroup python_builtins |
| /// @{ |
| |
| /// Get the length of a Python object. |
| inline size_t len(handle h) { |
| ssize_t result = PyObject_Length(h.ptr()); |
| if (result < 0) |
| throw error_already_set(); |
| return (size_t) result; |
| } |
| |
| /// Get the length hint of a Python object. |
| /// Returns 0 when this cannot be determined. |
| inline size_t len_hint(handle h) { |
| #if PY_VERSION_HEX >= 0x03040000 |
| ssize_t result = PyObject_LengthHint(h.ptr(), 0); |
| #else |
| ssize_t result = PyObject_Length(h.ptr()); |
| #endif |
| if (result < 0) { |
| // Sometimes a length can't be determined at all (eg generators) |
| // In which case simply return 0 |
| PyErr_Clear(); |
| return 0; |
| } |
| return (size_t) result; |
| } |
| |
| inline str repr(handle h) { |
| PyObject *str_value = PyObject_Repr(h.ptr()); |
| if (!str_value) throw error_already_set(); |
| #if PY_MAJOR_VERSION < 3 |
| PyObject *unicode = PyUnicode_FromEncodedObject(str_value, "utf-8", nullptr); |
| Py_XDECREF(str_value); str_value = unicode; |
| if (!str_value) throw error_already_set(); |
| #endif |
| return reinterpret_steal<str>(str_value); |
| } |
| |
| inline iterator iter(handle obj) { |
| PyObject *result = PyObject_GetIter(obj.ptr()); |
| if (!result) { throw error_already_set(); } |
| return reinterpret_steal<iterator>(result); |
| } |
| /// @} python_builtins |
| |
| PYBIND11_NAMESPACE_BEGIN(detail) |
| template <typename D> iterator object_api<D>::begin() const { return iter(derived()); } |
| template <typename D> iterator object_api<D>::end() const { return iterator::sentinel(); } |
| template <typename D> item_accessor object_api<D>::operator[](handle key) const { |
| return {derived(), reinterpret_borrow<object>(key)}; |
| } |
| template <typename D> item_accessor object_api<D>::operator[](const char *key) const { |
| return {derived(), pybind11::str(key)}; |
| } |
| template <typename D> obj_attr_accessor object_api<D>::attr(handle key) const { |
| return {derived(), reinterpret_borrow<object>(key)}; |
| } |
| template <typename D> str_attr_accessor object_api<D>::attr(const char *key) const { |
| return {derived(), key}; |
| } |
| template <typename D> args_proxy object_api<D>::operator*() const { |
| return args_proxy(derived().ptr()); |
| } |
| template <typename D> template <typename T> bool object_api<D>::contains(T &&item) const { |
| return attr("__contains__")(std::forward<T>(item)).template cast<bool>(); |
| } |
| |
| template <typename D> |
| pybind11::str object_api<D>::str() const { return pybind11::str(derived()); } |
| |
| template <typename D> |
| str_attr_accessor object_api<D>::doc() const { return attr("__doc__"); } |
| |
| template <typename D> |
| handle object_api<D>::get_type() const { return type::handle_of(derived()); } |
| |
| template <typename D> |
| bool object_api<D>::rich_compare(object_api const &other, int value) const { |
| int rv = PyObject_RichCompareBool(derived().ptr(), other.derived().ptr(), value); |
| if (rv == -1) |
| throw error_already_set(); |
| return rv == 1; |
| } |
| |
| #define PYBIND11_MATH_OPERATOR_UNARY(op, fn) \ |
| template <typename D> object object_api<D>::op() const { \ |
| object result = reinterpret_steal<object>(fn(derived().ptr())); \ |
| if (!result.ptr()) \ |
| throw error_already_set(); \ |
| return result; \ |
| } |
| |
| #define PYBIND11_MATH_OPERATOR_BINARY(op, fn) \ |
| template <typename D> \ |
| object object_api<D>::op(object_api const &other) const { \ |
| object result = reinterpret_steal<object>( \ |
| fn(derived().ptr(), other.derived().ptr())); \ |
| if (!result.ptr()) \ |
| throw error_already_set(); \ |
| return result; \ |
| } |
| |
| PYBIND11_MATH_OPERATOR_UNARY (operator~, PyNumber_Invert) |
| PYBIND11_MATH_OPERATOR_UNARY (operator-, PyNumber_Negative) |
| PYBIND11_MATH_OPERATOR_BINARY(operator+, PyNumber_Add) |
| PYBIND11_MATH_OPERATOR_BINARY(operator+=, PyNumber_InPlaceAdd) |
| PYBIND11_MATH_OPERATOR_BINARY(operator-, PyNumber_Subtract) |
| PYBIND11_MATH_OPERATOR_BINARY(operator-=, PyNumber_InPlaceSubtract) |
| PYBIND11_MATH_OPERATOR_BINARY(operator*, PyNumber_Multiply) |
| PYBIND11_MATH_OPERATOR_BINARY(operator*=, PyNumber_InPlaceMultiply) |
| PYBIND11_MATH_OPERATOR_BINARY(operator/, PyNumber_TrueDivide) |
| PYBIND11_MATH_OPERATOR_BINARY(operator/=, PyNumber_InPlaceTrueDivide) |
| PYBIND11_MATH_OPERATOR_BINARY(operator|, PyNumber_Or) |
| PYBIND11_MATH_OPERATOR_BINARY(operator|=, PyNumber_InPlaceOr) |
| PYBIND11_MATH_OPERATOR_BINARY(operator&, PyNumber_And) |
| PYBIND11_MATH_OPERATOR_BINARY(operator&=, PyNumber_InPlaceAnd) |
| PYBIND11_MATH_OPERATOR_BINARY(operator^, PyNumber_Xor) |
| PYBIND11_MATH_OPERATOR_BINARY(operator^=, PyNumber_InPlaceXor) |
| PYBIND11_MATH_OPERATOR_BINARY(operator<<, PyNumber_Lshift) |
| PYBIND11_MATH_OPERATOR_BINARY(operator<<=, PyNumber_InPlaceLshift) |
| PYBIND11_MATH_OPERATOR_BINARY(operator>>, PyNumber_Rshift) |
| PYBIND11_MATH_OPERATOR_BINARY(operator>>=, PyNumber_InPlaceRshift) |
| |
| #undef PYBIND11_MATH_OPERATOR_UNARY |
| #undef PYBIND11_MATH_OPERATOR_BINARY |
| |
| PYBIND11_NAMESPACE_END(detail) |
| PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) |