mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
Compare commits
4 Commits
414c1acc58
...
976f9066d6
Author | SHA1 | Date | |
---|---|---|---|
|
976f9066d6 | ||
|
83b92ceb35 | ||
|
655708f434 | ||
|
efbd12c6a5 |
@ -31,6 +31,9 @@
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
|
||||
PYBIND11_WARNING_DISABLE_MSVC(4127)
|
||||
#if PYBIND11_HAS_IF_CONSTEXPR
|
||||
PYBIND11_WARNING_DISABLE_MSVC(4702)
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
@ -138,24 +141,25 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
#if !defined(PYPY_VERSION)
|
||||
auto index_check = [](PyObject *o) { return PyIndex_Check(o); };
|
||||
#else
|
||||
// In PyPy 7.3.3, `PyIndex_Check` is implemented by calling `__index__`,
|
||||
// while CPython only considers the existence of `nb_index`/`__index__`.
|
||||
auto index_check = [](PyObject *o) { return hasattr(o, "__index__"); };
|
||||
#endif
|
||||
|
||||
if (std::is_floating_point<T>::value) {
|
||||
if PYBIND11_IF_CONSTEXPR (std::is_floating_point<T>::value) {
|
||||
if (convert || PyFloat_Check(src.ptr())) {
|
||||
py_value = (py_type) PyFloat_AsDouble(src.ptr());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else if (PyFloat_Check(src.ptr())
|
||||
|| (!convert && !PYBIND11_LONG_CHECK(src.ptr()) && !index_check(src.ptr()))) {
|
||||
return false;
|
||||
} else {
|
||||
#if !defined(PYPY_VERSION)
|
||||
auto index_check = [](PyObject *o) { return PyIndex_Check(o); };
|
||||
#else
|
||||
// In PyPy 7.3.3, `PyIndex_Check` is implemented by calling `__index__`,
|
||||
// while CPython only considers the existence of `nb_index`/`__index__`.
|
||||
auto index_check = [](PyObject *o) { return hasattr(o, "__index__"); };
|
||||
#endif
|
||||
if (PyFloat_Check(src.ptr())
|
||||
|| (!convert && !PYBIND11_LONG_CHECK(src.ptr()) && !index_check(src.ptr()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
handle src_or_index = src;
|
||||
// PyPy: 7.3.7's 3.8 does not implement PyLong_*'s __index__ calls.
|
||||
#if defined(PYPY_VERSION)
|
||||
@ -171,7 +175,7 @@ public:
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if (std::is_unsigned<py_type>::value) {
|
||||
if PYBIND11_IF_CONSTEXPR (std::is_unsigned<py_type>::value) {
|
||||
py_value = as_unsigned<py_type>(src_or_index.ptr());
|
||||
} else { // signed integer:
|
||||
py_value = sizeof(T) <= sizeof(long)
|
||||
@ -405,7 +409,7 @@ struct string_caster {
|
||||
|
||||
// For UTF-8 we avoid the need for a temporary `bytes` object by using
|
||||
// `PyUnicode_AsUTF8AndSize`.
|
||||
if (UTF_N == 8) {
|
||||
if PYBIND11_IF_CONSTEXPR (UTF_N == 8) {
|
||||
Py_ssize_t size = -1;
|
||||
const auto *buffer
|
||||
= reinterpret_cast<const CharT *>(PyUnicode_AsUTF8AndSize(load_src.ptr(), &size));
|
||||
@ -432,7 +436,7 @@ struct string_caster {
|
||||
= reinterpret_cast<const CharT *>(PYBIND11_BYTES_AS_STRING(utfNbytes.ptr()));
|
||||
size_t length = (size_t) PYBIND11_BYTES_SIZE(utfNbytes.ptr()) / sizeof(CharT);
|
||||
// Skip BOM for UTF-16/32
|
||||
if (UTF_N > 8) {
|
||||
if PYBIND11_IF_CONSTEXPR (UTF_N > 8) {
|
||||
buffer++;
|
||||
length--;
|
||||
}
|
||||
@ -559,7 +563,7 @@ public:
|
||||
}
|
||||
|
||||
static handle cast(CharT src, return_value_policy policy, handle parent) {
|
||||
if (std::is_same<char, CharT>::value) {
|
||||
if PYBIND11_IF_CONSTEXPR (std::is_same<char, CharT>::value) {
|
||||
handle s = PyUnicode_DecodeLatin1((const char *) &src, 1, nullptr);
|
||||
if (!s) {
|
||||
throw error_already_set();
|
||||
|
@ -123,6 +123,14 @@
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if defined(__cpp_if_constexpr)
|
||||
# define PYBIND11_HAS_IF_CONSTEXPR 1
|
||||
# define PYBIND11_IF_CONSTEXPR constexpr
|
||||
#else
|
||||
# define PYBIND11_HAS_IF_CONSTEXPR 0
|
||||
# define PYBIND11_IF_CONSTEXPR
|
||||
#endif
|
||||
|
||||
#if defined(PYBIND11_CPP20)
|
||||
# define PYBIND11_CONSTINIT constinit
|
||||
# define PYBIND11_DTOR_CONSTEXPR constexpr
|
||||
|
@ -33,6 +33,9 @@ static_assert(EIGEN_VERSION_AT_LEAST(3, 3, 0),
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
|
||||
PYBIND11_WARNING_DISABLE_MSVC(4127)
|
||||
#if PYBIND11_HAS_IF_CONSTEXPR
|
||||
PYBIND11_WARNING_DISABLE_MSVC(4702)
|
||||
#endif
|
||||
|
||||
PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
|
||||
@ -272,10 +275,9 @@ struct type_caster<Type, typename eigen_tensor_helper<Type>::ValidType> {
|
||||
bool writeable = false;
|
||||
switch (policy) {
|
||||
case return_value_policy::move:
|
||||
if (std::is_const<C>::value) {
|
||||
if PYBIND11_IF_CONSTEXPR (std::is_const<C>::value) {
|
||||
pybind11_fail("Cannot move from a constant reference");
|
||||
}
|
||||
|
||||
src = Helper::alloc(std::move(*src));
|
||||
|
||||
parent_object
|
||||
@ -284,13 +286,12 @@ struct type_caster<Type, typename eigen_tensor_helper<Type>::ValidType> {
|
||||
break;
|
||||
|
||||
case return_value_policy::take_ownership:
|
||||
if (std::is_const<C>::value) {
|
||||
if PYBIND11_IF_CONSTEXPR (std::is_const<C>::value) {
|
||||
// This cast is ugly, and might be UB in some cases, but we don't have an
|
||||
// alternative here as we must free that memory
|
||||
Helper::free(const_cast<Type *>(src));
|
||||
pybind11_fail("Cannot take ownership of a const reference");
|
||||
}
|
||||
|
||||
parent_object
|
||||
= capsule(src, [](void *ptr) { Helper::free(reinterpret_cast<Type *>(ptr)); });
|
||||
writeable = true;
|
||||
|
@ -204,7 +204,7 @@ protected:
|
||||
auto *rec = unique_rec.get();
|
||||
|
||||
/* Store the capture object directly in the function record if there is enough space */
|
||||
if (sizeof(capture) <= sizeof(rec->data)) {
|
||||
if PYBIND11_IF_CONSTEXPR (sizeof(capture) <= sizeof(rec->data)) {
|
||||
/* Without these pragmas, GCC warns that there might not be
|
||||
enough space to use the placement new operator. However, the
|
||||
'if' statement above ensures that this is the case. */
|
||||
@ -222,7 +222,7 @@ protected:
|
||||
|
||||
// UB without std::launder, but without breaking ABI and/or
|
||||
// a significant refactoring it's "impossible" to solve.
|
||||
if (!std::is_trivially_destructible<capture>::value) {
|
||||
if PYBIND11_IF_CONSTEXPR (!std::is_trivially_destructible<capture>::value) {
|
||||
rec->free_data = [](function_record *r) {
|
||||
auto data = PYBIND11_STD_LAUNDER((capture *) &r->data);
|
||||
(void) data;
|
||||
@ -342,7 +342,7 @@ protected:
|
||||
using FunctionType = Return (*)(Args...);
|
||||
constexpr bool is_function_ptr
|
||||
= std::is_convertible<Func, FunctionType>::value && sizeof(capture) == sizeof(void *);
|
||||
if (is_function_ptr) {
|
||||
if PYBIND11_IF_CONSTEXPR (is_function_ptr) {
|
||||
rec->is_stateless = true;
|
||||
rec->data[1]
|
||||
= const_cast<void *>(reinterpret_cast<const void *>(&typeid(FunctionType)));
|
||||
@ -1614,7 +1614,7 @@ public:
|
||||
|
||||
generic_type::initialize(record);
|
||||
|
||||
if (has_alias) {
|
||||
if PYBIND11_IF_CONSTEXPR (has_alias) {
|
||||
with_internals([&](internals &internals) {
|
||||
auto &instances = record.module_local ? get_local_internals().registered_types_cpp
|
||||
: internals.registered_types_cpp;
|
||||
@ -2020,7 +2020,8 @@ inline str enum_name(handle arg) {
|
||||
struct enum_base {
|
||||
enum_base(const handle &base, const handle &parent) : m_base(base), m_parent(parent) {}
|
||||
|
||||
PYBIND11_NOINLINE void init(bool is_arithmetic, bool is_convertible) {
|
||||
template <bool is_arithmetic, bool is_convertible>
|
||||
PYBIND11_NOINLINE void init() {
|
||||
m_base.attr("__entries") = dict();
|
||||
auto property = handle((PyObject *) &PyProperty_Type);
|
||||
auto static_property = handle((PyObject *) get_internals().static_property_type);
|
||||
@ -2126,11 +2127,11 @@ struct enum_base {
|
||||
arg("other"), \
|
||||
pos_only())
|
||||
|
||||
if (is_convertible) {
|
||||
if PYBIND11_IF_CONSTEXPR (is_convertible) {
|
||||
PYBIND11_ENUM_OP_CONV_LHS("__eq__", !b.is_none() && a.equal(b));
|
||||
PYBIND11_ENUM_OP_CONV_LHS("__ne__", b.is_none() || !a.equal(b));
|
||||
|
||||
if (is_arithmetic) {
|
||||
if PYBIND11_IF_CONSTEXPR (is_arithmetic) {
|
||||
PYBIND11_ENUM_OP_CONV("__lt__", a < b);
|
||||
PYBIND11_ENUM_OP_CONV("__gt__", a > b);
|
||||
PYBIND11_ENUM_OP_CONV("__le__", a <= b);
|
||||
@ -2151,7 +2152,7 @@ struct enum_base {
|
||||
PYBIND11_ENUM_OP_STRICT("__eq__", int_(a).equal(int_(b)), return false);
|
||||
PYBIND11_ENUM_OP_STRICT("__ne__", !int_(a).equal(int_(b)), return true);
|
||||
|
||||
if (is_arithmetic) {
|
||||
if PYBIND11_IF_CONSTEXPR (is_arithmetic) {
|
||||
#define PYBIND11_THROW throw type_error("Expected an enumeration of matching type!");
|
||||
PYBIND11_ENUM_OP_STRICT("__lt__", int_(a) < int_(b), PYBIND11_THROW);
|
||||
PYBIND11_ENUM_OP_STRICT("__gt__", int_(a) > int_(b), PYBIND11_THROW);
|
||||
@ -2262,7 +2263,7 @@ public:
|
||||
: class_<Type>(scope, name, extra...), m_base(*this, scope) {
|
||||
constexpr bool is_arithmetic = detail::any_of<std::is_same<arithmetic, Extra>...>::value;
|
||||
constexpr bool is_convertible = std::is_convertible<Type, Underlying>::value;
|
||||
m_base.init(is_arithmetic, is_convertible);
|
||||
m_base.init<is_arithmetic, is_convertible>();
|
||||
|
||||
def(init([](Scalar i) { return static_cast<Type>(i); }), arg("value"));
|
||||
def_property_readonly("value", [](Type value) { return (Scalar) value; }, pos_only());
|
||||
|
@ -34,6 +34,9 @@
|
||||
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
|
||||
|
||||
PYBIND11_WARNING_DISABLE_MSVC(4127)
|
||||
#if PYBIND11_HAS_IF_CONSTEXPR
|
||||
PYBIND11_WARNING_DISABLE_MSVC(4702)
|
||||
#endif
|
||||
|
||||
/* A few forward declarations */
|
||||
class handle;
|
||||
@ -1835,7 +1838,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)
|
||||
// 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 PYBIND11_IF_CONSTEXPR (sizeof(Unsigned) <= sizeof(unsigned long)) {
|
||||
unsigned long v = PyLong_AsUnsignedLong(o);
|
||||
return v == (unsigned long) -1 && PyErr_Occurred() ? (Unsigned) -1 : (Unsigned) v;
|
||||
}
|
||||
@ -1852,14 +1855,14 @@ public:
|
||||
template <typename T, detail::enable_if_t<std::is_integral<T>::value, int> = 0>
|
||||
// NOLINTNEXTLINE(google-explicit-constructor)
|
||||
int_(T value) {
|
||||
if (sizeof(T) <= sizeof(long)) {
|
||||
if (std::is_signed<T>::value) {
|
||||
if PYBIND11_IF_CONSTEXPR (sizeof(T) <= sizeof(long)) {
|
||||
if PYBIND11_IF_CONSTEXPR (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) {
|
||||
if PYBIND11_IF_CONSTEXPR (std::is_signed<T>::value) {
|
||||
m_ptr = PyLong_FromLongLong((long long) value);
|
||||
} else {
|
||||
m_ptr = PyLong_FromUnsignedLongLong((unsigned long long) value);
|
||||
|
@ -189,7 +189,7 @@ public:
|
||||
|
||||
template <typename T>
|
||||
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
||||
if (!std::is_lvalue_reference<T>::value) {
|
||||
if PYBIND11_IF_CONSTEXPR (!std::is_lvalue_reference<T>::value) {
|
||||
policy = return_value_policy_override<Key>::policy(policy);
|
||||
}
|
||||
pybind11::set s;
|
||||
@ -256,7 +256,7 @@ public:
|
||||
dict d;
|
||||
return_value_policy policy_key = policy;
|
||||
return_value_policy policy_value = policy;
|
||||
if (!std::is_lvalue_reference<T>::value) {
|
||||
if PYBIND11_IF_CONSTEXPR (!std::is_lvalue_reference<T>::value) {
|
||||
policy_key = return_value_policy_override<Key>::policy(policy_key);
|
||||
policy_value = return_value_policy_override<Value>::policy(policy_value);
|
||||
}
|
||||
@ -324,7 +324,7 @@ private:
|
||||
public:
|
||||
template <typename T>
|
||||
static handle cast(T &&src, return_value_policy policy, handle parent) {
|
||||
if (!std::is_lvalue_reference<T>::value) {
|
||||
if PYBIND11_IF_CONSTEXPR (!std::is_lvalue_reference<T>::value) {
|
||||
policy = return_value_policy_override<Value>::policy(policy);
|
||||
}
|
||||
list l(src.size());
|
||||
@ -513,7 +513,7 @@ struct optional_caster {
|
||||
if (!src) {
|
||||
return none().release();
|
||||
}
|
||||
if (!std::is_lvalue_reference<T>::value) {
|
||||
if PYBIND11_IF_CONSTEXPR (!std::is_lvalue_reference<T>::value) {
|
||||
policy = return_value_policy_override<Value>::policy(policy);
|
||||
}
|
||||
// NOLINTNEXTLINE(bugprone-unchecked-optional-access)
|
||||
|
@ -312,8 +312,16 @@ void print_created(T *inst, Values &&...values) {
|
||||
}
|
||||
template <class T, typename... Values>
|
||||
void print_destroyed(T *inst, Values &&...values) { // Prints but doesn't store given values
|
||||
/*
|
||||
* On GraalPy, destructors can trigger anywhere and this can cause random
|
||||
* failures in unrelated tests.
|
||||
*/
|
||||
#if !defined(GRAALVM_PYTHON)
|
||||
print_constr_details(inst, "destroyed", values...);
|
||||
track_destroyed(inst);
|
||||
#else
|
||||
py::detail::silence_unused_warnings(inst, values...);
|
||||
#endif
|
||||
}
|
||||
template <class T, typename... Values>
|
||||
void print_values(T *inst, Values &&...values) {
|
||||
|
@ -6,14 +6,8 @@ from io import StringIO
|
||||
|
||||
import pytest
|
||||
|
||||
import env # noqa: F401
|
||||
from pybind11_tests import iostream as m
|
||||
|
||||
pytestmark = pytest.mark.skipif(
|
||||
"env.GRAALPY",
|
||||
reason="Delayed prints from finalizers from other tests can end up in the output",
|
||||
)
|
||||
|
||||
|
||||
def test_captured(capsys):
|
||||
msg = "I've been redirected to Python, I hope!"
|
||||
|
Loading…
Reference in New Issue
Block a user