summaryrefslogtreecommitdiff
path: root/ext/pybind11/include/pybind11/pytypes.h
diff options
context:
space:
mode:
Diffstat (limited to 'ext/pybind11/include/pybind11/pytypes.h')
-rw-r--r--ext/pybind11/include/pybind11/pytypes.h196
1 files changed, 142 insertions, 54 deletions
diff --git a/ext/pybind11/include/pybind11/pytypes.h b/ext/pybind11/include/pybind11/pytypes.h
index 900c57564..d7fa17775 100644
--- a/ext/pybind11/include/pybind11/pytypes.h
+++ b/ext/pybind11/include/pybind11/pytypes.h
@@ -1,5 +1,5 @@
/*
- pybind11/typeid.h: Convenience wrapper classes for basic Python types
+ pybind11/pytypes.h: Convenience wrapper classes for basic Python types
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
@@ -9,11 +9,12 @@
#pragma once
-#include "common.h"
+#include "detail/common.h"
+#include "buffer_info.h"
#include <utility>
#include <type_traits>
-NAMESPACE_BEGIN(pybind11)
+NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
/* A few forward declarations */
class handle; class object;
@@ -43,7 +44,7 @@ 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, typename std::remove_reference<T>::type>;
+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.
@@ -109,11 +110,16 @@ public:
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; }
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())); }
/// Return a handle to the Python type object underlying the instance
@@ -166,10 +172,12 @@ public:
/// Return ``true`` when the `handle` wraps a valid Python object
explicit operator bool() const { return m_ptr != nullptr; }
/** \rst
- Check that the underlying pointers are the same.
+ 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; }
@@ -234,8 +242,8 @@ public:
protected:
// Tags for choosing constructors from raw PyObject *
- struct borrowed_t { }; static constexpr borrowed_t borrowed{};
- struct stolen_t { }; static constexpr stolen_t stolen{};
+ struct borrowed_t { };
+ struct stolen_t { };
template <typename T> friend T reinterpret_borrow(handle);
template <typename T> friend T reinterpret_steal(handle);
@@ -259,7 +267,7 @@ public:
// 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}; }
+template <typename T> T reinterpret_borrow(handle h) { return {h, object::borrowed_t{}}; }
/** \rst
Like `reinterpret_borrow`, but steals the reference.
@@ -269,7 +277,43 @@ template <typename T> T reinterpret_borrow(handle h) { return {h, object::borrow
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}; }
+template <typename T> T reinterpret_steal(handle h) { return {h, object::stolen_t{}}; }
+
+NAMESPACE_BEGIN(detail)
+inline std::string error_string();
+NAMESPACE_END(detail)
+
+/// 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 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(&type.ptr(), &value.ptr(), &trace.ptr());
+ }
+
+ inline ~error_already_set();
+
+ /// 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(type.release().ptr(), value.release().ptr(), trace.release().ptr()); }
+
+ // 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 ex) const { return PyErr_GivenExceptionMatches(ex.ptr(), type.ptr()); }
+
+private:
+ object type, value, trace;
+};
/** \defgroup python_builtins _
Unless stated otherwise, the following C++ functions behave the same
@@ -346,6 +390,13 @@ inline void setattr(handle obj, handle name, handle value) {
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
NAMESPACE_BEGIN(detail)
@@ -354,6 +405,7 @@ inline handle get_function(handle 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());
@@ -379,6 +431,8 @@ class accessor : public object_api<accessor<Policy>> {
public:
accessor(handle obj, key_type key) : obj(obj), key(std::move(key)) { }
+ accessor(const accessor &) = default;
+ accessor(accessor &&) = default;
// accessor overload required to override default assignment operator (templates are not allowed
// to replace default compiler-generated assignments).
@@ -674,9 +728,9 @@ NAMESPACE_END(detail)
#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) : Parent(h, stolen)) { } \
- Name(handle h, borrowed_t) : Parent(h, borrowed) { } \
- Name(handle h, stolen_t) : Parent(h, stolen) { } \
+ 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 && (bool) CheckFun(m_ptr); } \
static bool check_(handle h) { return h.ptr() != nullptr && CheckFun(h.ptr()); }
@@ -684,7 +738,14 @@ NAMESPACE_END(detail)
#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: */ \
- Name(const object &o) : Parent(ConvertFun(o.ptr()), stolen) { if (!m_ptr) throw error_already_set(); }
+ Name(const object &o) \
+ : Parent(check_(o) ? o.inc_ref().ptr() : ConvertFun(o.ptr()), stolen_t{}) \
+ { if (!m_ptr) throw error_already_set(); } \
+ Name(object &&o) \
+ : Parent(check_(o) ? o.release().ptr() : ConvertFun(o.ptr()), stolen_t{}) \
+ { if (!m_ptr) throw error_already_set(); } \
+ template <typename Policy_> \
+ Name(const ::pybind11::detail::accessor<Policy_> &a) : Name(object(a)) { }
#define PYBIND11_OBJECT(Name, Parent, CheckFun) \
PYBIND11_OBJECT_COMMON(Name, Parent, CheckFun) \
@@ -778,13 +839,13 @@ public:
PYBIND11_OBJECT_CVT(str, object, detail::PyUnicode_Check_Permissive, raw_str)
str(const char *c, size_t n)
- : object(PyUnicode_FromStringAndSize(c, (ssize_t) n), stolen) {
+ : object(PyUnicode_FromStringAndSize(c, (ssize_t) 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
str(const char *c = "")
- : object(PyUnicode_FromString(c), stolen) {
+ : object(PyUnicode_FromString(c), stolen_t{}) {
if (!m_ptr) pybind11_fail("Could not allocate string object!");
}
@@ -796,7 +857,7 @@ public:
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) { }
+ explicit str(handle h) : object(raw_str(h.ptr()), stolen_t{}) { }
operator std::string() const {
object temp = *this;
@@ -846,12 +907,12 @@ public:
// Allow implicit conversion:
bytes(const char *c = "")
- : object(PYBIND11_BYTES_FROM_STRING(c), stolen) {
+ : object(PYBIND11_BYTES_FROM_STRING(c), stolen_t{}) {
if (!m_ptr) pybind11_fail("Could not allocate bytes object!");
}
bytes(const char *c, size_t n)
- : object(PYBIND11_BYTES_FROM_STRING_AND_SIZE(c, (ssize_t) n), stolen) {
+ : object(PYBIND11_BYTES_FROM_STRING_AND_SIZE(c, (ssize_t) n), stolen_t{}) {
if (!m_ptr) pybind11_fail("Could not allocate bytes object!");
}
@@ -900,15 +961,15 @@ inline str::str(const bytes& b) {
class none : public object {
public:
PYBIND11_OBJECT(none, object, detail::PyNone_Check)
- none() : object(Py_None, borrowed) { }
+ none() : object(Py_None, borrowed_t{}) { }
};
class bool_ : public object {
public:
PYBIND11_OBJECT_CVT(bool_, object, PyBool_Check, raw_bool)
- bool_() : object(Py_False, borrowed) { }
+ bool_() : object(Py_False, borrowed_t{}) { }
// Allow implicit conversion from and to `bool`:
- bool_(bool value) : object(value ? Py_True : Py_False, borrowed) { }
+ bool_(bool value) : object(value ? Py_True : Py_False, borrowed_t{}) { }
operator bool() const { return m_ptr && PyLong_AsLong(m_ptr) != 0; }
private:
@@ -920,10 +981,32 @@ private:
}
};
+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 (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;
+ }
+ else {
+ unsigned long long v = PyLong_AsUnsignedLongLong(o);
+ return v == (unsigned long long) -1 && PyErr_Occurred() ? (Unsigned) -1 : (Unsigned) v;
+ }
+}
+NAMESPACE_END(detail)
+
class int_ : public object {
public:
PYBIND11_OBJECT_CVT(int_, object, PYBIND11_LONG_CHECK, PyNumber_Long)
- int_() : object(PyLong_FromLong(0), stolen) { }
+ 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>
@@ -945,17 +1028,11 @@ public:
template <typename T,
detail::enable_if_t<std::is_integral<T>::value, int> = 0>
operator T() const {
- if (sizeof(T) <= sizeof(long)) {
- if (std::is_signed<T>::value)
- return (T) PyLong_AsLong(m_ptr);
- else
- return (T) PyLong_AsUnsignedLong(m_ptr);
- } else {
- if (std::is_signed<T>::value)
- return (T) PYBIND11_LONG_AS_LONGLONG(m_ptr);
- else
- return (T) PYBIND11_LONG_AS_UNSIGNED_LONGLONG(m_ptr);
- }
+ 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);
}
};
@@ -963,10 +1040,10 @@ class float_ : public object {
public:
PYBIND11_OBJECT_CVT(float_, object, PyFloat_Check, PyNumber_Float)
// Allow implicit conversion from float/double:
- float_(float value) : object(PyFloat_FromDouble((double) value), stolen) {
+ float_(float value) : object(PyFloat_FromDouble((double) value), stolen_t{}) {
if (!m_ptr) pybind11_fail("Could not allocate float object!");
}
- float_(double value = .0) : object(PyFloat_FromDouble((double) value), stolen) {
+ float_(double value = .0) : object(PyFloat_FromDouble((double) value), stolen_t{}) {
if (!m_ptr) pybind11_fail("Could not allocate float object!");
}
operator float() const { return (float) PyFloat_AsDouble(m_ptr); }
@@ -977,7 +1054,7 @@ class weakref : public object {
public:
PYBIND11_OBJECT_DEFAULT(weakref, object, PyWeakref_Check)
explicit weakref(handle obj, handle callback = {})
- : object(PyWeakref_NewRef(obj.ptr(), callback.ptr()), stolen) {
+ : object(PyWeakref_NewRef(obj.ptr(), callback.ptr()), stolen_t{}) {
if (!m_ptr) pybind11_fail("Could not allocate weak reference!");
}
};
@@ -1003,17 +1080,17 @@ 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) : object(ptr, stolen)) { }
+ capsule(PyObject *ptr, bool is_borrowed) : object(is_borrowed ? object(ptr, borrowed_t{}) : object(ptr, stolen_t{})) { }
- explicit capsule(const void *value)
- : object(PyCapsule_New(const_cast<void *>(value), nullptr, nullptr), stolen) {
+ 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) {
+ : object(PyCapsule_New(const_cast<void*>(value), nullptr, destruct), stolen_t{}) {
if (!m_ptr)
pybind11_fail("Could not allocate capsule object!");
}
@@ -1043,16 +1120,19 @@ public:
}
template <typename T> operator T *() const {
- T * result = static_cast<T *>(PyCapsule_GetPointer(m_ptr, nullptr));
+ auto name = this->name();
+ T * result = static_cast<T *>(PyCapsule_GetPointer(m_ptr, name));
if (!result) pybind11_fail("Unable to extract capsule contents!");
return result;
}
+
+ const char *name() const { return PyCapsule_GetName(m_ptr); }
};
class tuple : public object {
public:
PYBIND11_OBJECT_CVT(tuple, object, PyTuple_Check, PySequence_Tuple)
- explicit tuple(size_t size = 0) : object(PyTuple_New((ssize_t) size), stolen) {
+ explicit tuple(size_t size = 0) : object(PyTuple_New((ssize_t) size), stolen_t{}) {
if (!m_ptr) pybind11_fail("Could not allocate tuple object!");
}
size_t size() const { return (size_t) PyTuple_Size(m_ptr); }
@@ -1064,7 +1144,7 @@ public:
class dict : public object {
public:
PYBIND11_OBJECT_CVT(dict, object, PyDict_Check, raw_dict)
- dict() : object(PyDict_New(), stolen) {
+ dict() : object(PyDict_New(), stolen_t{}) {
if (!m_ptr) pybind11_fail("Could not allocate dict object!");
}
template <typename... Args,
@@ -1101,7 +1181,7 @@ public:
class list : public object {
public:
PYBIND11_OBJECT_CVT(list, object, PyList_Check, PySequence_List)
- explicit list(size_t size = 0) : object(PyList_New((ssize_t) size), stolen) {
+ explicit list(size_t size = 0) : object(PyList_New((ssize_t) size), stolen_t{}) {
if (!m_ptr) pybind11_fail("Could not allocate list object!");
}
size_t size() const { return (size_t) PyList_Size(m_ptr); }
@@ -1119,7 +1199,7 @@ 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) {
+ 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); }
@@ -1132,10 +1212,13 @@ public:
class function : public object {
public:
PYBIND11_OBJECT_DEFAULT(function, object, PyCallable_Check)
- bool is_cpp_function() const {
+ handle cpp_function() const {
handle fun = detail::get_function(m_ptr);
- return fun && PyCFunction_Check(fun.ptr());
+ if (fun && PyCFunction_Check(fun.ptr()))
+ return fun;
+ return handle();
}
+ bool is_cpp_function() const { return (bool) cpp_function(); }
};
class buffer : public object {
@@ -1146,8 +1229,10 @@ public:
int flags = PyBUF_STRIDES | PyBUF_FORMAT;
if (writable) flags |= PyBUF_WRITABLE;
Py_buffer *view = new Py_buffer();
- if (PyObject_GetBuffer(m_ptr, view, flags) != 0)
+ if (PyObject_GetBuffer(m_ptr, view, flags) != 0) {
+ delete view;
throw error_already_set();
+ }
return buffer_info(view);
}
};
@@ -1160,15 +1245,15 @@ public:
static std::vector<Py_ssize_t> py_strides { };
static std::vector<Py_ssize_t> py_shape { };
buf.buf = info.ptr;
- buf.itemsize = (Py_ssize_t) info.itemsize;
+ buf.itemsize = info.itemsize;
buf.format = const_cast<char *>(info.format.c_str());
buf.ndim = (int) info.ndim;
- buf.len = (Py_ssize_t) info.size;
+ buf.len = info.size;
py_strides.clear();
py_shape.clear();
- for (size_t i = 0; i < info.ndim; ++i) {
- py_strides.push_back((Py_ssize_t) info.strides[i]);
- py_shape.push_back((Py_ssize_t) info.shape[i]);
+ for (size_t i = 0; i < (size_t) info.ndim; ++i) {
+ py_strides.push_back(info.strides[i]);
+ py_shape.push_back(info.shape[i]);
}
buf.strides = py_strides.data();
buf.shape = py_shape.data();
@@ -1238,7 +1323,10 @@ 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 (PyObject *) Py_TYPE(derived().ptr()); }
NAMESPACE_END(detail)
-NAMESPACE_END(pybind11)
+NAMESPACE_END(PYBIND11_NAMESPACE)