Merge branch 'master' into sh_merge_master_3

This commit is contained in:
Ralf W. Grosse-Kunstleve 2022-12-02 05:28:58 -08:00
commit 10d4aa7476
23 changed files with 347 additions and 214 deletions

View File

@ -21,10 +21,11 @@ body:
- label: Consider asking first in the [Gitter chat room](https://gitter.im/pybind/Lobby) or in a [Discussion](https:/pybind/pybind11/discussions/new). - label: Consider asking first in the [Gitter chat room](https://gitter.im/pybind/Lobby) or in a [Discussion](https:/pybind/pybind11/discussions/new).
required: false required: false
- type: Input - type: input
id: version id: version
attributes: attributes:
label: What version (or hash if on master) of pybind11 are you using? label: What version (or hash if on master) of pybind11 are you using?
validations:
required: true required: true
- type: textarea - type: textarea
@ -52,7 +53,7 @@ body:
starting point for working out fixes. starting point for working out fixes.
render: text render: text
- type: Input - type: input
id: regression id: regression
attributes: attributes:
label: Is this a regression? Put the last known working version here if it is. label: Is this a regression? Put the last known working version here if it is.

View File

@ -99,13 +99,13 @@ jobs:
- uses: actions/download-artifact@v3 - uses: actions/download-artifact@v3
- name: Publish standard package - name: Publish standard package
uses: pypa/gh-action-pypi-publish@v1.5.1 uses: pypa/gh-action-pypi-publish@v1.5.2
with: with:
password: ${{ secrets.pypi_password }} password: ${{ secrets.pypi_password }}
packages_dir: standard/ packages_dir: standard/
- name: Publish global package - name: Publish global package
uses: pypa/gh-action-pypi-publish@v1.5.1 uses: pypa/gh-action-pypi-publish@v1.5.2
with: with:
password: ${{ secrets.pypi_password_global }} password: ${{ secrets.pypi_password_global }}
packages_dir: global/ packages_dir: global/

View File

@ -35,6 +35,9 @@
#endif #endif
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
PYBIND11_NAMESPACE_BEGIN(detail) PYBIND11_NAMESPACE_BEGIN(detail)
#ifndef PYBIND11_USE_SMART_HOLDER_AS_DEFAULT #ifndef PYBIND11_USE_SMART_HOLDER_AS_DEFAULT
@ -419,7 +422,7 @@ struct string_caster {
// For UTF-8 we avoid the need for a temporary `bytes` object by using // For UTF-8 we avoid the need for a temporary `bytes` object by using
// `PyUnicode_AsUTF8AndSize`. // `PyUnicode_AsUTF8AndSize`.
if (PYBIND11_SILENCE_MSVC_C4127(UTF_N == 8)) { if (UTF_N == 8) {
Py_ssize_t size = -1; Py_ssize_t size = -1;
const auto *buffer const auto *buffer
= reinterpret_cast<const CharT *>(PyUnicode_AsUTF8AndSize(load_src.ptr(), &size)); = reinterpret_cast<const CharT *>(PyUnicode_AsUTF8AndSize(load_src.ptr(), &size));
@ -446,7 +449,7 @@ struct string_caster {
= reinterpret_cast<const CharT *>(PYBIND11_BYTES_AS_STRING(utfNbytes.ptr())); = reinterpret_cast<const CharT *>(PYBIND11_BYTES_AS_STRING(utfNbytes.ptr()));
size_t length = (size_t) PYBIND11_BYTES_SIZE(utfNbytes.ptr()) / sizeof(CharT); size_t length = (size_t) PYBIND11_BYTES_SIZE(utfNbytes.ptr()) / sizeof(CharT);
// Skip BOM for UTF-16/32 // Skip BOM for UTF-16/32
if (PYBIND11_SILENCE_MSVC_C4127(UTF_N > 8)) { if (UTF_N > 8) {
buffer++; buffer++;
length--; length--;
} }
@ -606,7 +609,7 @@ public:
// figure out how long the first encoded character is in bytes to distinguish between these // figure out how long the first encoded character is in bytes to distinguish between these
// two errors. We also allow want to allow unicode characters U+0080 through U+00FF, as // two errors. We also allow want to allow unicode characters U+0080 through U+00FF, as
// those can fit into a single char value. // those can fit into a single char value.
if (PYBIND11_SILENCE_MSVC_C4127(StringCaster::UTF_N == 8) && str_len > 1 && str_len <= 4) { if (StringCaster::UTF_N == 8 && str_len > 1 && str_len <= 4) {
auto v0 = static_cast<unsigned char>(value[0]); auto v0 = static_cast<unsigned char>(value[0]);
// low bits only: 0-127 // low bits only: 0-127
// 0b110xxxxx - start of 2-byte sequence // 0b110xxxxx - start of 2-byte sequence
@ -632,7 +635,7 @@ public:
// UTF-16 is much easier: we can only have a surrogate pair for values above U+FFFF, thus a // UTF-16 is much easier: we can only have a surrogate pair for values above U+FFFF, thus a
// surrogate pair with total length 2 instantly indicates a range error (but not a "your // surrogate pair with total length 2 instantly indicates a range error (but not a "your
// string was too long" error). // string was too long" error).
else if (PYBIND11_SILENCE_MSVC_C4127(StringCaster::UTF_N == 16) && str_len == 2) { else if (StringCaster::UTF_N == 16 && str_len == 2) {
one_char = static_cast<CharT>(value[0]); one_char = static_cast<CharT>(value[0]);
if (one_char >= 0xD800 && one_char < 0xE000) { if (one_char >= 0xD800 && one_char < 0xE000) {
throw value_error("Character code point not in range(0x10000)"); throw value_error("Character code point not in range(0x10000)");

View File

@ -17,8 +17,69 @@
// Additional convention: 0xD = dev // Additional convention: 0xD = dev
#define PYBIND11_VERSION_HEX 0x020B00D1 #define PYBIND11_VERSION_HEX 0x020B00D1
#define PYBIND11_NAMESPACE_BEGIN(name) namespace name { // Define some generic pybind11 helper macros for warning management.
#define PYBIND11_NAMESPACE_END(name) } //
// Note that compiler-specific push/pop pairs are baked into the
// PYBIND11_NAMESPACE_BEGIN/PYBIND11_NAMESPACE_END pair of macros. Therefore manual
// PYBIND11_WARNING_PUSH/PYBIND11_WARNING_POP are usually only needed in `#include` sections.
//
// If you find you need to suppress a warning, please try to make the suppression as local as
// possible using these macros. Please also be sure to push/pop with the pybind11 macros. Please
// only use compiler specifics if you need to check specific versions, e.g. Apple Clang vs. vanilla
// Clang.
#if defined(_MSC_VER)
# define PYBIND11_COMPILER_MSVC
# define PYBIND11_PRAGMA(...) __pragma(__VA_ARGS__)
# define PYBIND11_WARNING_PUSH PYBIND11_PRAGMA(warning(push))
# define PYBIND11_WARNING_POP PYBIND11_PRAGMA(warning(pop))
#elif defined(__INTEL_COMPILER)
# define PYBIND11_COMPILER_INTEL
# define PYBIND11_PRAGMA(...) _Pragma(# __VA_ARGS__)
# define PYBIND11_WARNING_PUSH PYBIND11_PRAGMA(warning push)
# define PYBIND11_WARNING_POP PYBIND11_PRAGMA(warning pop)
#elif defined(__clang__)
# define PYBIND11_COMPILER_CLANG
# define PYBIND11_PRAGMA(...) _Pragma(# __VA_ARGS__)
# define PYBIND11_WARNING_PUSH PYBIND11_PRAGMA(clang diagnostic push)
# define PYBIND11_WARNING_POP PYBIND11_PRAGMA(clang diagnostic push)
#elif defined(__GNUC__)
# define PYBIND11_COMPILER_GCC
# define PYBIND11_PRAGMA(...) _Pragma(# __VA_ARGS__)
# define PYBIND11_WARNING_PUSH PYBIND11_PRAGMA(GCC diagnostic push)
# define PYBIND11_WARNING_POP PYBIND11_PRAGMA(GCC diagnostic pop)
#endif
#ifdef PYBIND11_COMPILER_MSVC
# define PYBIND11_WARNING_DISABLE_MSVC(name) PYBIND11_PRAGMA(warning(disable : name))
#else
# define PYBIND11_WARNING_DISABLE_MSVC(name)
#endif
#ifdef PYBIND11_COMPILER_CLANG
# define PYBIND11_WARNING_DISABLE_CLANG(name) PYBIND11_PRAGMA(clang diagnostic ignored name)
#else
# define PYBIND11_WARNING_DISABLE_CLANG(name)
#endif
#ifdef PYBIND11_COMPILER_GCC
# define PYBIND11_WARNING_DISABLE_GCC(name) PYBIND11_PRAGMA(GCC diagnostic ignored name)
#else
# define PYBIND11_WARNING_DISABLE_GCC(name)
#endif
#ifdef PYBIND11_COMPILER_INTEL
# define PYBIND11_WARNING_DISABLE_INTEL(name) PYBIND11_PRAGMA(warning disable name)
#else
# define PYBIND11_WARNING_DISABLE_INTEL(name)
#endif
#define PYBIND11_NAMESPACE_BEGIN(name) \
namespace name { \
PYBIND11_WARNING_PUSH
#define PYBIND11_NAMESPACE_END(name) \
PYBIND11_WARNING_POP \
}
// Robust support for some features and loading modules compiled against different pybind versions // Robust support for some features and loading modules compiled against different pybind versions
// requires forcing hidden visibility on pybind code, so we enforce this by setting the attribute // requires forcing hidden visibility on pybind code, so we enforce this by setting the attribute
@ -151,9 +212,9 @@
/// Include Python header, disable linking to pythonX_d.lib on Windows in debug mode /// Include Python header, disable linking to pythonX_d.lib on Windows in debug mode
#if defined(_MSC_VER) #if defined(_MSC_VER)
# pragma warning(push) PYBIND11_WARNING_PUSH
PYBIND11_WARNING_DISABLE_MSVC(4505)
// C4505: 'PySlice_GetIndicesEx': unreferenced local function has been removed (PyPy only) // C4505: 'PySlice_GetIndicesEx': unreferenced local function has been removed (PyPy only)
# pragma warning(disable : 4505)
# if defined(_DEBUG) && !defined(Py_DEBUG) # if defined(_DEBUG) && !defined(Py_DEBUG)
// Workaround for a VS 2022 issue. // Workaround for a VS 2022 issue.
// NOTE: This workaround knowingly violates the Python.h include order requirement: // NOTE: This workaround knowingly violates the Python.h include order requirement:
@ -236,7 +297,7 @@
# define _DEBUG # define _DEBUG
# undef PYBIND11_DEBUG_MARKER # undef PYBIND11_DEBUG_MARKER
# endif # endif
# pragma warning(pop) PYBIND11_WARNING_POP
#endif #endif
#include <cstddef> #include <cstddef>
@ -1160,17 +1221,6 @@ constexpr
# define PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(...) # define PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(...)
#endif #endif
#if defined(_MSC_VER) // All versions (as of July 2021).
// warning C4127: Conditional expression is constant
constexpr inline bool silence_msvc_c4127(bool cond) { return cond; }
# define PYBIND11_SILENCE_MSVC_C4127(...) ::pybind11::detail::silence_msvc_c4127(__VA_ARGS__)
#else
# define PYBIND11_SILENCE_MSVC_C4127(...) __VA_ARGS__
#endif
#if defined(__clang__) \ #if defined(__clang__) \
&& (defined(__apple_build_version__) /* AppleClang 13.0.0.13000029 was the only data point \ && (defined(__apple_build_version__) /* AppleClang 13.0.0.13000029 was the only data point \
available. */ \ available. */ \

View File

@ -13,6 +13,9 @@
#include "smart_holder_sfinae_hooks_only.h" #include "smart_holder_sfinae_hooks_only.h"
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
PYBIND11_NAMESPACE_BEGIN(detail) PYBIND11_NAMESPACE_BEGIN(detail)
template <> template <>
@ -116,7 +119,7 @@ template <typename Class>
void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) { void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) {
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias); PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
no_nullptr(ptr); no_nullptr(ptr);
if (PYBIND11_SILENCE_MSVC_C4127(Class::has_alias) && need_alias && !is_alias<Class>(ptr)) { if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) {
// We're going to try to construct an alias by moving the cpp type. Whether or not // We're going to try to construct an alias by moving the cpp type. Whether or not
// that succeeds, we still need to destroy the original cpp pointer (either the // that succeeds, we still need to destroy the original cpp pointer (either the
// moved away leftover, if the alias construction works, or the value itself if we // moved away leftover, if the alias construction works, or the value itself if we
@ -162,7 +165,7 @@ void construct(value_and_holder &v_h, Holder<Class> holder, bool need_alias) {
auto *ptr = holder_helper<Holder<Class>>::get(holder); auto *ptr = holder_helper<Holder<Class>>::get(holder);
no_nullptr(ptr); no_nullptr(ptr);
// If we need an alias, check that the held pointer is actually an alias instance // If we need an alias, check that the held pointer is actually an alias instance
if (PYBIND11_SILENCE_MSVC_C4127(Class::has_alias) && need_alias && !is_alias<Class>(ptr)) { if (Class::has_alias && need_alias && !is_alias<Class>(ptr)) {
throw type_error("pybind11::init(): construction failed: returned holder-wrapped instance " throw type_error("pybind11::init(): construction failed: returned holder-wrapped instance "
"is not an alias instance"); "is not an alias instance");
} }
@ -180,7 +183,7 @@ void construct(value_and_holder &v_h, Cpp<Class> &&result, bool need_alias) {
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias); PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
static_assert(std::is_move_constructible<Cpp<Class>>::value, static_assert(std::is_move_constructible<Cpp<Class>>::value,
"pybind11::init() return-by-value factory function requires a movable class"); "pybind11::init() return-by-value factory function requires a movable class");
if (PYBIND11_SILENCE_MSVC_C4127(Class::has_alias) && need_alias) { if (Class::has_alias && need_alias) {
construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(result)); construct_alias_from_cpp<Class>(is_alias_constructible<Class>{}, v_h, std::move(result));
} else { } else {
v_h.value_ptr() = new Cpp<Class>(std::move(result)); v_h.value_ptr() = new Cpp<Class>(std::move(result));

View File

@ -479,9 +479,6 @@ PYBIND11_NOINLINE internals &get_internals() {
internals_ptr = new internals(); internals_ptr = new internals();
#if defined(WITH_THREAD) #if defined(WITH_THREAD)
# if PY_VERSION_HEX < 0x03090000
PyEval_InitThreads();
# endif
PyThreadState *tstate = PyThreadState_Get(); PyThreadState *tstate = PyThreadState_Get();
if (!PYBIND11_TLS_KEY_CREATE(internals_ptr->tstate)) { if (!PYBIND11_TLS_KEY_CREATE(internals_ptr->tstate)) {
pybind11_fail("get_internals: could not successfully initialize the tstate TSS key!"); pybind11_fail("get_internals: could not successfully initialize the tstate TSS key!");

View File

@ -16,29 +16,15 @@
https://stackoverflow.com/questions/2579576/i-dir-vs-isystem-dir https://stackoverflow.com/questions/2579576/i-dir-vs-isystem-dir
https://stackoverflow.com/questions/1741816/isystem-for-ms-visual-studio-c-compiler https://stackoverflow.com/questions/1741816/isystem-for-ms-visual-studio-c-compiler
*/ */
// The C4127 suppression was introduced for Eigen 3.4.0. In theory we could PYBIND11_WARNING_PUSH
// make it version specific, or even remove it later, but considering that PYBIND11_WARNING_DISABLE_MSVC(5054) // https://github.com/pybind/pybind11/pull/3741
// 1. C4127 is generally far more distracting than useful for modern template code, and
// 2. we definitely want to ignore any MSVC warnings originating from Eigen code,
// it is probably best to keep this around indefinitely.
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable : 4127) // C4127: conditional expression is constant
# pragma warning(disable : 5054) // https://github.com/pybind/pybind11/pull/3741
// C5054: operator '&': deprecated between enumerations of different types // C5054: operator '&': deprecated between enumerations of different types
#elif defined(__MINGW32__) PYBIND11_WARNING_DISABLE_GCC("-Wmaybe-uninitialized")
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
#include <Eigen/Core> #include <Eigen/Core>
#include <Eigen/SparseCore> #include <Eigen/SparseCore>
#if defined(_MSC_VER) PYBIND11_WARNING_POP
# pragma warning(pop)
#elif defined(__MINGW32__)
# pragma GCC diagnostic pop
#endif
// Eigen prior to 3.2.7 doesn't have proper move constructors--but worse, some classes get implicit // Eigen prior to 3.2.7 doesn't have proper move constructors--but worse, some classes get implicit
// move constructors that break things. We could detect this an explicitly copy, but an extra copy // move constructors that break things. We could detect this an explicitly copy, but an extra copy
@ -48,6 +34,8 @@ static_assert(EIGEN_VERSION_AT_LEAST(3, 2, 7),
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
// Provide a convenience alias for easier pass-by-ref usage with fully dynamic strides: // Provide a convenience alias for easier pass-by-ref usage with fully dynamic strides:
using EigenDStride = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>; using EigenDStride = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
template <typename MatrixType> template <typename MatrixType>
@ -189,8 +177,7 @@ struct EigenProps {
EigenIndex np_rows = a.shape(0), np_cols = a.shape(1), EigenIndex np_rows = a.shape(0), np_cols = a.shape(1),
np_rstride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar)), np_rstride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar)),
np_cstride = a.strides(1) / static_cast<ssize_t>(sizeof(Scalar)); np_cstride = a.strides(1) / static_cast<ssize_t>(sizeof(Scalar));
if ((PYBIND11_SILENCE_MSVC_C4127(fixed_rows) && np_rows != rows) if ((fixed_rows && np_rows != rows) || (fixed_cols && np_cols != cols)) {
|| (PYBIND11_SILENCE_MSVC_C4127(fixed_cols) && np_cols != cols)) {
return false; return false;
} }
@ -203,7 +190,7 @@ struct EigenProps {
stride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar)); stride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar));
if (vector) { // Eigen type is a compile-time vector if (vector) { // Eigen type is a compile-time vector
if (PYBIND11_SILENCE_MSVC_C4127(fixed) && size != n) { if (fixed && size != n) {
return false; // Vector size mismatch return false; // Vector size mismatch
} }
return {rows == 1 ? 1 : n, cols == 1 ? 1 : n, stride}; return {rows == 1 ? 1 : n, cols == 1 ? 1 : n, stride};
@ -220,7 +207,7 @@ struct EigenProps {
} }
return {1, n, stride}; return {1, n, stride};
} // Otherwise it's either fully dynamic, or column dynamic; both become a column vector } // Otherwise it's either fully dynamic, or column dynamic; both become a column vector
if (PYBIND11_SILENCE_MSVC_C4127(fixed_rows) && rows != n) { if (fixed_rows && rows != n) {
return false; return false;
} }
return {n, 1, stride}; return {n, 1, stride};

View File

@ -13,28 +13,23 @@
static_assert(__GNUC__ > 5, "Eigen Tensor support in pybind11 requires GCC > 5.0"); static_assert(__GNUC__ > 5, "Eigen Tensor support in pybind11 requires GCC > 5.0");
#endif #endif
#if defined(_MSC_VER) // Disable warnings for Eigen
# pragma warning(push) PYBIND11_WARNING_PUSH
# pragma warning(disable : 4554) // Tensor.h warning PYBIND11_WARNING_DISABLE_MSVC(4554)
# pragma warning(disable : 4127) // Tensor.h warning PYBIND11_WARNING_DISABLE_MSVC(4127)
#elif defined(__MINGW32__) PYBIND11_WARNING_DISABLE_GCC("-Wmaybe-uninitialized")
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
#include <unsupported/Eigen/CXX11/Tensor> #include <unsupported/Eigen/CXX11/Tensor>
#if defined(_MSC_VER) PYBIND11_WARNING_POP
# pragma warning(pop)
#elif defined(__MINGW32__)
# pragma GCC diagnostic pop
#endif
static_assert(EIGEN_VERSION_AT_LEAST(3, 3, 0), static_assert(EIGEN_VERSION_AT_LEAST(3, 3, 0),
"Eigen Tensor support in pybind11 requires Eigen >= 3.3.0"); "Eigen Tensor support in pybind11 requires Eigen >= 3.3.0");
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
PYBIND11_NAMESPACE_BEGIN(detail) PYBIND11_NAMESPACE_BEGIN(detail)
inline bool is_tensor_aligned(const void *data) { inline bool is_tensor_aligned(const void *data) {
@ -138,10 +133,8 @@ struct get_tensor_descriptor {
// //
// We need to disable the type-limits warning for the inner loop when size = 0. // We need to disable the type-limits warning for the inner loop when size = 0.
#if defined(__GNUC__) PYBIND11_WARNING_PUSH
# pragma GCC diagnostic push PYBIND11_WARNING_DISABLE_GCC("-Wtype-limits")
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
template <typename T, int size> template <typename T, int size>
std::vector<T> convert_dsizes_to_vector(const Eigen::DSizes<T, size> &arr) { std::vector<T> convert_dsizes_to_vector(const Eigen::DSizes<T, size> &arr) {
@ -165,9 +158,7 @@ Eigen::DSizes<T, size> get_shape_for_array(const array &arr) {
return result; return result;
} }
#if defined(__GNUC__) PYBIND11_WARNING_POP
# pragma GCC diagnostic pop
#endif
template <typename Type> template <typename Type>
struct type_caster<Type, typename eigen_tensor_helper<Type>::ValidType> { struct type_caster<Type, typename eigen_tensor_helper<Type>::ValidType> {
@ -393,7 +384,7 @@ struct type_caster<Eigen::TensorMap<Type, Options>,
constexpr bool is_aligned = (Options & Eigen::Aligned) != 0; constexpr bool is_aligned = (Options & Eigen::Aligned) != 0;
if (PYBIND11_SILENCE_MSVC_C4127(is_aligned) && !is_tensor_aligned(arr.data())) { if (is_aligned && !is_tensor_aligned(arr.data())) {
return false; return false;
} }
@ -403,7 +394,7 @@ struct type_caster<Eigen::TensorMap<Type, Options>,
return false; return false;
} }
if (PYBIND11_SILENCE_MSVC_C4127(needs_writeable) && !arr.writeable()) { if (needs_writeable && !arr.writeable()) {
return false; return false;
} }

View File

@ -86,38 +86,26 @@ inline wchar_t *widen_chars(const char *safe_arg) {
return widened_arg; return widened_arg;
} }
PYBIND11_NAMESPACE_END(detail) inline void precheck_interpreter() {
/** \rst
Initialize the Python interpreter. No other pybind11 or CPython API functions can be
called before this is done; with the exception of `PYBIND11_EMBEDDED_MODULE`. The
optional `init_signal_handlers` parameter can be used to skip the registration of
signal handlers (see the `Python documentation`_ for details). Calling this function
again after the interpreter has already been initialized is a fatal error.
If initializing the Python interpreter fails, then the program is terminated. (This
is controlled by the CPython runtime and is an exception to pybind11's normal behavior
of throwing exceptions on errors.)
The remaining optional parameters, `argc`, `argv`, and `add_program_dir_to_path` are
used to populate ``sys.argv`` and ``sys.path``.
See the |PySys_SetArgvEx documentation|_ for details.
.. _Python documentation: https://docs.python.org/3/c-api/init.html#c.Py_InitializeEx
.. |PySys_SetArgvEx documentation| replace:: ``PySys_SetArgvEx`` documentation
.. _PySys_SetArgvEx documentation: https://docs.python.org/3/c-api/init.html#c.PySys_SetArgvEx
\endrst */
inline void initialize_interpreter(bool init_signal_handlers = true,
int argc = 0,
const char *const *argv = nullptr,
bool add_program_dir_to_path = true) {
if (Py_IsInitialized() != 0) { if (Py_IsInitialized() != 0) {
pybind11_fail("The interpreter is already running"); pybind11_fail("The interpreter is already running");
} }
}
#if PY_VERSION_HEX < 0x030B0000 #if !defined(PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX)
# define PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX (0x03080000)
#endif
#if PY_VERSION_HEX < PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
inline void initialize_interpreter_pre_pyconfig(bool init_signal_handlers,
int argc,
const char *const *argv,
bool add_program_dir_to_path) {
detail::precheck_interpreter();
Py_InitializeEx(init_signal_handlers ? 1 : 0); Py_InitializeEx(init_signal_handlers ? 1 : 0);
# if defined(WITH_THREAD) && PY_VERSION_HEX < 0x03070000
PyEval_InitThreads();
# endif
// Before it was special-cased in python 3.8, passing an empty or null argv // Before it was special-cased in python 3.8, passing an empty or null argv
// caused a segfault, so we have to reimplement the special case ourselves. // caused a segfault, so we have to reimplement the special case ourselves.
@ -147,25 +135,29 @@ inline void initialize_interpreter(bool init_signal_handlers = true,
auto *pysys_argv = widened_argv.get(); auto *pysys_argv = widened_argv.get();
PySys_SetArgvEx(argc, pysys_argv, static_cast<int>(add_program_dir_to_path)); PySys_SetArgvEx(argc, pysys_argv, static_cast<int>(add_program_dir_to_path));
#else }
PyConfig config; #endif
PyConfig_InitIsolatedConfig(&config);
config.isolated = 0;
config.use_environment = 1;
config.install_signal_handlers = init_signal_handlers ? 1 : 0;
PyStatus status = PyConfig_SetBytesArgv(&config, argc, const_cast<char *const *>(argv)); PYBIND11_NAMESPACE_END(detail)
if (PyStatus_Exception(status)) {
#if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
inline void initialize_interpreter(PyConfig *config,
int argc = 0,
const char *const *argv = nullptr,
bool add_program_dir_to_path = true) {
detail::precheck_interpreter();
PyStatus status = PyConfig_SetBytesArgv(config, argc, const_cast<char *const *>(argv));
if (PyStatus_Exception(status) != 0) {
// A failure here indicates a character-encoding failure or the python // A failure here indicates a character-encoding failure or the python
// interpreter out of memory. Give up. // interpreter out of memory. Give up.
PyConfig_Clear(&config); PyConfig_Clear(config);
throw std::runtime_error(PyStatus_IsError(status) ? status.err_msg throw std::runtime_error(PyStatus_IsError(status) != 0 ? status.err_msg
: "Failed to prepare CPython"); : "Failed to prepare CPython");
} }
status = Py_InitializeFromConfig(&config); status = Py_InitializeFromConfig(config);
PyConfig_Clear(&config); if (PyStatus_Exception(status) != 0) {
if (PyStatus_Exception(status)) { PyConfig_Clear(config);
throw std::runtime_error(PyStatus_IsError(status) ? status.err_msg throw std::runtime_error(PyStatus_IsError(status) != 0 ? status.err_msg
: "Failed to init CPython"); : "Failed to init CPython");
} }
if (add_program_dir_to_path) { if (add_program_dir_to_path) {
@ -174,6 +166,43 @@ inline void initialize_interpreter(bool init_signal_handlers = true,
"os.path.abspath(os.path.dirname(sys.argv[0])) " "os.path.abspath(os.path.dirname(sys.argv[0])) "
"if sys.argv and os.path.exists(sys.argv[0]) else '')"); "if sys.argv and os.path.exists(sys.argv[0]) else '')");
} }
PyConfig_Clear(config);
}
#endif
/** \rst
Initialize the Python interpreter. No other pybind11 or CPython API functions can be
called before this is done; with the exception of `PYBIND11_EMBEDDED_MODULE`. The
optional `init_signal_handlers` parameter can be used to skip the registration of
signal handlers (see the `Python documentation`_ for details). Calling this function
again after the interpreter has already been initialized is a fatal error.
If initializing the Python interpreter fails, then the program is terminated. (This
is controlled by the CPython runtime and is an exception to pybind11's normal behavior
of throwing exceptions on errors.)
The remaining optional parameters, `argc`, `argv`, and `add_program_dir_to_path` are
used to populate ``sys.argv`` and ``sys.path``.
See the |PySys_SetArgvEx documentation|_ for details.
.. _Python documentation: https://docs.python.org/3/c-api/init.html#c.Py_InitializeEx
.. |PySys_SetArgvEx documentation| replace:: ``PySys_SetArgvEx`` documentation
.. _PySys_SetArgvEx documentation: https://docs.python.org/3/c-api/init.html#c.PySys_SetArgvEx
\endrst */
inline void initialize_interpreter(bool init_signal_handlers = true,
int argc = 0,
const char *const *argv = nullptr,
bool add_program_dir_to_path = true) {
#if PY_VERSION_HEX < PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
detail::initialize_interpreter_pre_pyconfig(
init_signal_handlers, argc, argv, add_program_dir_to_path);
#else
PyConfig config;
PyConfig_InitIsolatedConfig(&config);
config.isolated = 0;
config.use_environment = 1;
config.install_signal_handlers = init_signal_handlers ? 1 : 0;
initialize_interpreter(&config, argc, argv, add_program_dir_to_path);
#endif #endif
} }
@ -261,6 +290,15 @@ public:
initialize_interpreter(init_signal_handlers, argc, argv, add_program_dir_to_path); initialize_interpreter(init_signal_handlers, argc, argv, add_program_dir_to_path);
} }
#if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
explicit scoped_interpreter(PyConfig *config,
int argc = 0,
const char *const *argv = nullptr,
bool add_program_dir_to_path = true) {
initialize_interpreter(config, argc, argv, add_program_dir_to_path);
}
#endif
scoped_interpreter(const scoped_interpreter &) = delete; scoped_interpreter(const scoped_interpreter &) = delete;
scoped_interpreter(scoped_interpreter &&other) noexcept { other.is_valid = false; } scoped_interpreter(scoped_interpreter &&other) noexcept { other.is_valid = false; }
scoped_interpreter &operator=(const scoped_interpreter &) = delete; scoped_interpreter &operator=(const scoped_interpreter &) = delete;

View File

@ -36,6 +36,8 @@ static_assert(std::is_signed<Py_intptr_t>::value, "Py_intptr_t must be signed");
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
class array; // Forward declaration class array; // Forward declaration
PYBIND11_NAMESPACE_BEGIN(detail) PYBIND11_NAMESPACE_BEGIN(detail)
@ -875,7 +877,7 @@ public:
*/ */
template <typename T, ssize_t Dims = -1> template <typename T, ssize_t Dims = -1>
detail::unchecked_mutable_reference<T, Dims> mutable_unchecked() & { detail::unchecked_mutable_reference<T, Dims> mutable_unchecked() & {
if (PYBIND11_SILENCE_MSVC_C4127(Dims >= 0) && ndim() != Dims) { if (Dims >= 0 && ndim() != Dims) {
throw std::domain_error("array has incorrect number of dimensions: " throw std::domain_error("array has incorrect number of dimensions: "
+ std::to_string(ndim()) + "; expected " + std::to_string(ndim()) + "; expected "
+ std::to_string(Dims)); + std::to_string(Dims));
@ -893,7 +895,7 @@ public:
*/ */
template <typename T, ssize_t Dims = -1> template <typename T, ssize_t Dims = -1>
detail::unchecked_reference<T, Dims> unchecked() const & { detail::unchecked_reference<T, Dims> unchecked() const & {
if (PYBIND11_SILENCE_MSVC_C4127(Dims >= 0) && ndim() != Dims) { if (Dims >= 0 && ndim() != Dims) {
throw std::domain_error("array has incorrect number of dimensions: " throw std::domain_error("array has incorrect number of dimensions: "
+ std::to_string(ndim()) + "; expected " + std::to_string(ndim()) + "; expected "
+ std::to_string(Dims)); + std::to_string(Dims));
@ -1865,9 +1867,10 @@ private:
} }
auto result = returned_array::create(trivial, shape); auto result = returned_array::create(trivial, shape);
PYBIND11_WARNING_PUSH
#ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING #ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING
# pragma clang diagnostic push PYBIND11_WARNING_DISABLE_CLANG("-Wreturn-std-move")
# pragma clang diagnostic ignored "-Wreturn-std-move"
#endif #endif
if (size == 0) { if (size == 0) {
@ -1883,9 +1886,7 @@ private:
} }
return result; return result;
#ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING PYBIND11_WARNING_POP
# pragma clang diagnostic pop
#endif
} }
template <size_t... Index, size_t... VIndex, size_t... BIndex> template <size_t... Index, size_t... VIndex, size_t... BIndex>

View File

@ -36,6 +36,8 @@
# include <cxxabi.h> # include <cxxabi.h>
#endif #endif
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
/* https://stackoverflow.com/questions/46798456/handling-gccs-noexcept-type-warning /* https://stackoverflow.com/questions/46798456/handling-gccs-noexcept-type-warning
This warning is about ABI compatibility, not code health. This warning is about ABI compatibility, not code health.
It is only actually needed in a couple places, but apparently GCC 7 "generates this warning if It is only actually needed in a couple places, but apparently GCC 7 "generates this warning if
@ -44,11 +46,10 @@
No other GCC version generates this warning. No other GCC version generates this warning.
*/ */
#if defined(__GNUC__) && __GNUC__ == 7 #if defined(__GNUC__) && __GNUC__ == 7
# pragma GCC diagnostic push PYBIND11_WARNING_DISABLE_GCC("-Wnoexcept-type")
# pragma GCC diagnostic ignored "-Wnoexcept-type"
#endif #endif
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_WARNING_DISABLE_MSVC(4127)
PYBIND11_NAMESPACE_BEGIN(detail) PYBIND11_NAMESPACE_BEGIN(detail)
@ -178,22 +179,22 @@ protected:
auto *rec = unique_rec.get(); auto *rec = unique_rec.get();
/* Store the capture object directly in the function record if there is enough space */ /* Store the capture object directly in the function record if there is enough space */
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(capture) <= sizeof(rec->data))) { if (sizeof(capture) <= sizeof(rec->data)) {
/* Without these pragmas, GCC warns that there might not be /* Without these pragmas, GCC warns that there might not be
enough space to use the placement new operator. However, the enough space to use the placement new operator. However, the
'if' statement above ensures that this is the case. */ 'if' statement above ensures that this is the case. */
#if defined(__GNUG__) && __GNUC__ >= 6 && !defined(__clang__) && !defined(__INTEL_COMPILER) PYBIND11_WARNING_PUSH
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wplacement-new" #if defined(__GNUG__) && __GNUC__ >= 6
PYBIND11_WARNING_DISABLE_GCC("-Wplacement-new")
#endif #endif
new ((capture *) &rec->data) capture{std::forward<Func>(f)}; new ((capture *) &rec->data) capture{std::forward<Func>(f)};
#if defined(__GNUG__) && __GNUC__ >= 6 && !defined(__clang__) && !defined(__INTEL_COMPILER)
# pragma GCC diagnostic pop #if !PYBIND11_HAS_STD_LAUNDER
#endif PYBIND11_WARNING_DISABLE_GCC("-Wstrict-aliasing")
#if defined(__GNUG__) && !PYBIND11_HAS_STD_LAUNDER && !defined(__INTEL_COMPILER)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
#endif #endif
// UB without std::launder, but without breaking ABI and/or // UB without std::launder, but without breaking ABI and/or
// a significant refactoring it's "impossible" to solve. // a significant refactoring it's "impossible" to solve.
if (!std::is_trivially_destructible<capture>::value) { if (!std::is_trivially_destructible<capture>::value) {
@ -203,9 +204,7 @@ protected:
data->~capture(); data->~capture();
}; };
} }
#if defined(__GNUG__) && !PYBIND11_HAS_STD_LAUNDER && !defined(__INTEL_COMPILER) PYBIND11_WARNING_POP
# pragma GCC diagnostic pop
#endif
} else { } else {
rec->data[0] = new capture{std::forward<Func>(f)}; rec->data[0] = new capture{std::forward<Func>(f)};
rec->free_data = [](function_record *r) { delete ((capture *) r->data[0]); }; rec->free_data = [](function_record *r) { delete ((capture *) r->data[0]); };
@ -2087,8 +2086,7 @@ private:
if (holder_ptr) { if (holder_ptr) {
init_holder_from_existing(v_h, holder_ptr, std::is_copy_constructible<holder_type>()); init_holder_from_existing(v_h, holder_ptr, std::is_copy_constructible<holder_type>());
v_h.set_holder_constructed(); v_h.set_holder_constructed();
} else if (PYBIND11_SILENCE_MSVC_C4127(detail::always_construct_holder<holder_type>::value) } else if (detail::always_construct_holder<holder_type>::value || inst->owned) {
|| inst->owned) {
new (std::addressof(v_h.holder<holder_type>())) holder_type(v_h.value_ptr<type>()); new (std::addressof(v_h.holder<holder_type>())) holder_type(v_h.value_ptr<type>());
v_h.set_holder_constructed(); v_h.set_holder_constructed();
} }
@ -3131,7 +3129,3 @@ inline function get_overload(const T *this_ptr, const char *name) {
PYBIND11_OVERRIDE_PURE(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), fn, __VA_ARGS__); PYBIND11_OVERRIDE_PURE(PYBIND11_TYPE(ret_type), PYBIND11_TYPE(cname), fn, __VA_ARGS__);
PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_END(PYBIND11_NAMESPACE)
#if defined(__GNUC__) && __GNUC__ == 7
# pragma GCC diagnostic pop // -Wnoexcept-type
#endif

View File

@ -33,6 +33,8 @@
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE) PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
/* A few forward declarations */ /* A few forward declarations */
class handle; class handle;
class object; class object;
@ -884,10 +886,8 @@ object object_or_cast(T &&o);
// Match a PyObject*, which we want to convert directly to handle via its converting constructor // Match a PyObject*, which we want to convert directly to handle via its converting constructor
inline handle object_or_cast(PyObject *ptr) { return ptr; } inline handle object_or_cast(PyObject *ptr) { return ptr; }
#if defined(_MSC_VER) && _MSC_VER < 1920 PYBIND11_WARNING_PUSH
# pragma warning(push) PYBIND11_WARNING_DISABLE_MSVC(4522) // warning C4522: multiple assignment operators specified
# pragma warning(disable : 4522) // warning C4522: multiple assignment operators specified
#endif
template <typename Policy> template <typename Policy>
class accessor : public object_api<accessor<Policy>> { class accessor : public object_api<accessor<Policy>> {
using key_type = typename Policy::key_type; using key_type = typename Policy::key_type;
@ -951,9 +951,7 @@ private:
key_type key; key_type key;
mutable object cache; mutable object cache;
}; };
#if defined(_MSC_VER) && _MSC_VER < 1920 PYBIND11_WARNING_POP
# pragma warning(pop)
#endif
PYBIND11_NAMESPACE_BEGIN(accessor_policies) PYBIND11_NAMESPACE_BEGIN(accessor_policies)
struct obj_attr { struct obj_attr {
@ -1693,7 +1691,7 @@ PYBIND11_NAMESPACE_BEGIN(detail)
// unsigned type: (A)-1 != (B)-1 when A and B are unsigned types of different sizes). // unsigned type: (A)-1 != (B)-1 when A and B are unsigned types of different sizes).
template <typename Unsigned> template <typename Unsigned>
Unsigned as_unsigned(PyObject *o) { Unsigned as_unsigned(PyObject *o) {
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(Unsigned) <= sizeof(unsigned long))) { if (sizeof(Unsigned) <= sizeof(unsigned long)) {
unsigned long v = PyLong_AsUnsignedLong(o); unsigned long v = PyLong_AsUnsignedLong(o);
return v == (unsigned long) -1 && PyErr_Occurred() ? (Unsigned) -1 : (Unsigned) v; return v == (unsigned long) -1 && PyErr_Occurred() ? (Unsigned) -1 : (Unsigned) v;
} }
@ -1710,7 +1708,7 @@ public:
template <typename T, detail::enable_if_t<std::is_integral<T>::value, int> = 0> template <typename T, detail::enable_if_t<std::is_integral<T>::value, int> = 0>
// NOLINTNEXTLINE(google-explicit-constructor) // NOLINTNEXTLINE(google-explicit-constructor)
int_(T value) { int_(T value) {
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(T) <= sizeof(long))) { if (sizeof(T) <= sizeof(long)) {
if (std::is_signed<T>::value) { if (std::is_signed<T>::value) {
m_ptr = PyLong_FromLong((long) value); m_ptr = PyLong_FromLong((long) value);
} else { } else {

View File

@ -7,6 +7,8 @@ Adds docstring and exceptions message sanitizers.
import contextlib import contextlib
import difflib import difflib
import gc import gc
import multiprocessing
import os
import re import re
import textwrap import textwrap
@ -15,6 +17,22 @@ import pytest
# Early diagnostic for failed imports # Early diagnostic for failed imports
import pybind11_tests import pybind11_tests
@pytest.fixture(scope="session", autouse=True)
def always_forkserver_on_unix():
if os.name == "nt":
return
# Full background: https://github.com/pybind/pybind11/issues/4105#issuecomment-1301004592
# In a nutshell: fork() after starting threads == flakiness in the form of deadlocks.
# It is actually a well-known pitfall, unfortunately without guard rails.
# "forkserver" is more performant than "spawn" (~9s vs ~13s for tests/test_gil_scoped.py,
# visit the issuecomment link above for details).
# Windows does not have fork() and the associated pitfall, therefore it is best left
# running with defaults.
multiprocessing.set_start_method("forkserver")
_long_marker = re.compile(r"([0-9])L") _long_marker = re.compile(r"([0-9])L")
_hexadecimal = re.compile(r"0x[0-9a-fA-F]+") _hexadecimal = re.compile(r"0x[0-9a-fA-F]+")

View File

@ -80,6 +80,9 @@ PYBIND11_NAMESPACE_END(detail)
PYBIND11_NAMESPACE_END(pybind11) PYBIND11_NAMESPACE_END(pybind11)
TEST_SUBMODULE(builtin_casters, m) { TEST_SUBMODULE(builtin_casters, m) {
PYBIND11_WARNING_PUSH
PYBIND11_WARNING_DISABLE_MSVC(4127)
// test_simple_string // test_simple_string
m.def("string_roundtrip", [](const char *s) { return s; }); m.def("string_roundtrip", [](const char *s) { return s; });
@ -93,7 +96,7 @@ TEST_SUBMODULE(builtin_casters, m) {
std::wstring wstr; std::wstring wstr;
wstr.push_back(0x61); // a wstr.push_back(0x61); // a
wstr.push_back(0x2e18); // ⸘ wstr.push_back(0x2e18); // ⸘
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(wchar_t) == 2)) { if (sizeof(wchar_t) == 2) {
wstr.push_back(mathbfA16_1); wstr.push_back(mathbfA16_1);
wstr.push_back(mathbfA16_2); wstr.push_back(mathbfA16_2);
} // 𝐀, utf16 } // 𝐀, utf16
@ -120,7 +123,7 @@ TEST_SUBMODULE(builtin_casters, m) {
// Under Python 2.7, invalid unicode UTF-32 characters didn't appear to trigger // Under Python 2.7, invalid unicode UTF-32 characters didn't appear to trigger
// UnicodeDecodeError // UnicodeDecodeError
m.def("bad_utf32_string", [=]() { return std::u32string({a32, char32_t(0xd800), z32}); }); m.def("bad_utf32_string", [=]() { return std::u32string({a32, char32_t(0xd800), z32}); });
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(wchar_t) == 2)) { if (sizeof(wchar_t) == 2) {
m.def("bad_wchar_string", [=]() { m.def("bad_wchar_string", [=]() {
return std::wstring({wchar_t(0x61), wchar_t(0xd800)}); return std::wstring({wchar_t(0x61), wchar_t(0xd800)});
}); });
@ -415,4 +418,6 @@ TEST_SUBMODULE(builtin_casters, m) {
[]() { return std::string_view("\xba\xd0\xba\xd0"); }, []() { return std::string_view("\xba\xd0\xba\xd0"); },
py::return_value_policy::_return_as_bytes); py::return_value_policy::_return_as_bytes);
#endif #endif
PYBIND11_WARNING_POP
} }

View File

@ -22,10 +22,8 @@
#include <utility> #include <utility>
#if defined(_MSC_VER) PYBIND11_WARNING_DISABLE_MSVC(4324)
# pragma warning(disable : 4324)
// warning C4324: structure was padded due to alignment specifier // warning C4324: structure was padded due to alignment specifier
#endif
namespace { namespace {

View File

@ -52,15 +52,12 @@ int f1(int x) noexcept { return x + 1; }
#endif #endif
int f2(int x) noexcept(true) { return x + 2; } int f2(int x) noexcept(true) { return x + 2; }
int f3(int x) noexcept(false) { return x + 3; } int f3(int x) noexcept(false) { return x + 3; }
#if defined(__GNUG__) && !defined(__INTEL_COMPILER) PYBIND11_WARNING_PUSH
# pragma GCC diagnostic push PYBIND11_WARNING_DISABLE_GCC("-Wdeprecated")
# pragma GCC diagnostic ignored "-Wdeprecated" PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated")
#endif
// NOLINTNEXTLINE(modernize-use-noexcept) // NOLINTNEXTLINE(modernize-use-noexcept)
int f4(int x) throw() { return x + 4; } // Deprecated equivalent to noexcept(true) int f4(int x) throw() { return x + 4; } // Deprecated equivalent to noexcept(true)
#if defined(__GNUG__) && !defined(__INTEL_COMPILER) PYBIND11_WARNING_POP
# pragma GCC diagnostic pop
#endif
struct C { struct C {
int m1(int x) noexcept { return x - 1; } int m1(int x) noexcept { return x - 1; }
int m2(int x) const noexcept { return x - 2; } int m2(int x) const noexcept { return x - 2; }
@ -68,17 +65,14 @@ struct C {
int m4(int x) const noexcept(true) { return x - 4; } int m4(int x) const noexcept(true) { return x - 4; }
int m5(int x) noexcept(false) { return x - 5; } int m5(int x) noexcept(false) { return x - 5; }
int m6(int x) const noexcept(false) { return x - 6; } int m6(int x) const noexcept(false) { return x - 6; }
#if defined(__GNUG__) && !defined(__INTEL_COMPILER) PYBIND11_WARNING_PUSH
# pragma GCC diagnostic push PYBIND11_WARNING_DISABLE_GCC("-Wdeprecated")
# pragma GCC diagnostic ignored "-Wdeprecated" PYBIND11_WARNING_DISABLE_CLANG("-Wdeprecated")
#endif
// NOLINTNEXTLINE(modernize-use-noexcept) // NOLINTNEXTLINE(modernize-use-noexcept)
int m7(int x) throw() { return x - 7; } int m7(int x) throw() { return x - 7; }
// NOLINTNEXTLINE(modernize-use-noexcept) // NOLINTNEXTLINE(modernize-use-noexcept)
int m8(int x) const throw() { return x - 8; } int m8(int x) const throw() { return x - 8; }
#if defined(__GNUG__) && !defined(__INTEL_COMPILER) PYBIND11_WARNING_POP
# pragma GCC diagnostic pop
#endif
}; };
} // namespace test_exc_sp } // namespace test_exc_sp
@ -126,14 +120,12 @@ TEST_SUBMODULE(constants_and_functions, m) {
.def("m8", &C::m8); .def("m8", &C::m8);
m.def("f1", f1); m.def("f1", f1);
m.def("f2", f2); m.def("f2", f2);
#if defined(__INTEL_COMPILER)
# pragma warning push PYBIND11_WARNING_PUSH
# pragma warning disable 878 // incompatible exception specifications PYBIND11_WARNING_DISABLE_INTEL(878) // incompatible exception specifications
#endif
m.def("f3", f3); m.def("f3", f3);
#if defined(__INTEL_COMPILER) PYBIND11_WARNING_POP
# pragma warning pop
#endif
m.def("f4", f4); m.def("f4", f4);
// test_function_record_leaks // test_function_record_leaks

View File

@ -13,9 +13,7 @@
#include "constructor_stats.h" #include "constructor_stats.h"
#include "pybind11_tests.h" #include "pybind11_tests.h"
#if defined(_MSC_VER) PYBIND11_WARNING_DISABLE_MSVC(4996)
# pragma warning(disable : 4996) // C4996: std::unary_negation is deprecated
#endif
#include <Eigen/Cholesky> #include <Eigen/Cholesky>

View File

@ -9,7 +9,9 @@
#include "pybind11_tests.h" #include "pybind11_tests.h"
namespace PYBIND11_TEST_EIGEN_TENSOR_NAMESPACE { PYBIND11_NAMESPACE_BEGIN(PYBIND11_TEST_EIGEN_TENSOR_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
template <typename M> template <typename M>
void reset_tensor(M &x) { void reset_tensor(M &x) {
@ -90,7 +92,7 @@ struct CustomExample {
template <int Options> template <int Options>
void init_tensor_module(pybind11::module &m) { void init_tensor_module(pybind11::module &m) {
const char *needed_options = ""; const char *needed_options = "";
if (PYBIND11_SILENCE_MSVC_C4127(Options == Eigen::ColMajor)) { if (Options == Eigen::ColMajor) {
needed_options = "F"; needed_options = "F";
} else { } else {
needed_options = "C"; needed_options = "C";
@ -330,4 +332,4 @@ void test_module(py::module_ &m) {
init_tensor_module<Eigen::RowMajor>(c_style); init_tensor_module<Eigen::RowMajor>(c_style);
} }
} // namespace PYBIND11_TEST_EIGEN_TENSOR_NAMESPACE PYBIND11_NAMESPACE_END(PYBIND11_TEST_EIGEN_TENSOR_NAMESPACE)

View File

@ -3,11 +3,9 @@
#include <pybind11/embed.h> #include <pybind11/embed.h>
#ifdef _MSC_VER
// Silence MSVC C++17 deprecation warning from Catch regarding std::uncaught_exceptions (up to // Silence MSVC C++17 deprecation warning from Catch regarding std::uncaught_exceptions (up to
// catch 2.0.1; this should be fixed in the next catch release after 2.0.1). // catch 2.0.1; this should be fixed in the next catch release after 2.0.1).
# pragma warning(disable : 4996) PYBIND11_WARNING_DISABLE_MSVC(4996)
#endif
// Catch uses _ internally, which breaks gettext style defines // Catch uses _ internally, which breaks gettext style defines
#ifdef _ #ifdef _

View File

@ -1,10 +1,8 @@
#include <pybind11/embed.h> #include <pybind11/embed.h>
#ifdef _MSC_VER
// Silence MSVC C++17 deprecation warning from Catch regarding std::uncaught_exceptions (up to // Silence MSVC C++17 deprecation warning from Catch regarding std::uncaught_exceptions (up to
// catch 2.0.1; this should be fixed in the next catch release after 2.0.1). // catch 2.0.1; this should be fixed in the next catch release after 2.0.1).
# pragma warning(disable : 4996) PYBIND11_WARNING_DISABLE_MSVC(4996)
#endif
#include <catch.hpp> #include <catch.hpp>
#include <cstdlib> #include <cstdlib>
@ -16,6 +14,11 @@
namespace py = pybind11; namespace py = pybind11;
using namespace py::literals; using namespace py::literals;
size_t get_sys_path_size() {
auto sys_path = py::module::import("sys").attr("path");
return py::len(sys_path);
}
class Widget { class Widget {
public: public:
explicit Widget(std::string message) : message(std::move(message)) {} explicit Widget(std::string message) : message(std::move(message)) {}
@ -168,6 +171,70 @@ TEST_CASE("There can be only one interpreter") {
py::initialize_interpreter(); py::initialize_interpreter();
} }
#if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
TEST_CASE("Custom PyConfig") {
py::finalize_interpreter();
PyConfig config;
PyConfig_InitPythonConfig(&config);
REQUIRE_NOTHROW(py::scoped_interpreter{&config});
{
py::scoped_interpreter p{&config};
REQUIRE(py::module_::import("widget_module").attr("add")(1, 41).cast<int>() == 42);
}
py::initialize_interpreter();
}
TEST_CASE("Custom PyConfig with argv") {
py::finalize_interpreter();
{
PyConfig config;
PyConfig_InitIsolatedConfig(&config);
char *argv[] = {strdup("a.out")};
py::scoped_interpreter argv_scope{&config, 1, argv};
std::free(argv[0]);
auto module = py::module::import("test_interpreter");
auto py_widget = module.attr("DerivedWidget")("The question");
const auto &cpp_widget = py_widget.cast<const Widget &>();
REQUIRE(cpp_widget.argv0() == "a.out");
}
py::initialize_interpreter();
}
#endif
TEST_CASE("Add program dir to path pre-PyConfig") {
py::finalize_interpreter();
size_t path_size_add_program_dir_to_path_false = 0;
{
py::scoped_interpreter scoped_interp{true, 0, nullptr, false};
path_size_add_program_dir_to_path_false = get_sys_path_size();
}
{
py::scoped_interpreter scoped_interp{};
REQUIRE(get_sys_path_size() == path_size_add_program_dir_to_path_false + 1);
}
py::initialize_interpreter();
}
#if PY_VERSION_HEX >= PYBIND11_PYCONFIG_SUPPORT_PY_VERSION_HEX
TEST_CASE("Add program dir to path using PyConfig") {
py::finalize_interpreter();
size_t path_size_add_program_dir_to_path_false = 0;
{
PyConfig config;
PyConfig_InitPythonConfig(&config);
py::scoped_interpreter scoped_interp{&config, 0, nullptr, false};
path_size_add_program_dir_to_path_false = get_sys_path_size();
}
{
PyConfig config;
PyConfig_InitPythonConfig(&config);
py::scoped_interpreter scoped_interp{&config};
REQUIRE(get_sys_path_size() == path_size_add_program_dir_to_path_false + 1);
}
py::initialize_interpreter();
}
#endif
bool has_pybind11_internals_builtin() { bool has_pybind11_internals_builtin() {
auto builtins = py::handle(PyEval_GetBuiltins()); auto builtins = py::handle(PyEval_GetBuiltins());
return builtins.contains(PYBIND11_INTERNALS_ID); return builtins.contains(PYBIND11_INTERNALS_ID);

View File

@ -5,6 +5,7 @@ import time
import pytest import pytest
import env
from pybind11_tests import gil_scoped as m from pybind11_tests import gil_scoped as m
@ -144,7 +145,6 @@ def _intentional_deadlock():
ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK = ALL_BASIC_TESTS + (_intentional_deadlock,) ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK = ALL_BASIC_TESTS + (_intentional_deadlock,)
SKIP_IF_DEADLOCK = True # See PR #4216
def _run_in_process(target, *args, **kwargs): def _run_in_process(target, *args, **kwargs):
@ -181,7 +181,7 @@ def _run_in_process(target, *args, **kwargs):
elif process.exitcode is None: elif process.exitcode is None:
assert t_delta > 0.9 * timeout assert t_delta > 0.9 * timeout
msg = "DEADLOCK, most likely, exactly what this test is meant to detect." msg = "DEADLOCK, most likely, exactly what this test is meant to detect."
if SKIP_IF_DEADLOCK: if env.PYPY and env.WIN:
pytest.skip(msg) pytest.skip(msg)
raise RuntimeError(msg) raise RuntimeError(msg)
return process.exitcode return process.exitcode

View File

@ -44,14 +44,13 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
// test_args_and_kwargs // test_args_and_kwargs
m.def("args_function", [](py::args args) -> py::tuple { m.def("args_function", [](py::args args) -> py::tuple {
PYBIND11_WARNING_PUSH
#ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING #ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING
# pragma clang diagnostic push PYBIND11_WARNING_DISABLE_CLANG("-Wreturn-std-move")
# pragma clang diagnostic ignored "-Wreturn-std-move"
#endif #endif
return args; return args;
#ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING PYBIND11_WARNING_POP
# pragma clang diagnostic pop
#endif
}); });
m.def("args_kwargs_function", [](const py::args &args, const py::kwargs &kwargs) { m.def("args_kwargs_function", [](const py::args &args, const py::kwargs &kwargs) {
return py::make_tuple(args, kwargs); return py::make_tuple(args, kwargs);

View File

@ -132,22 +132,18 @@ struct hash<HashMe> {
// Not a good abs function, but easy to test. // Not a good abs function, but easy to test.
std::string abs(const Vector2 &) { return "abs(Vector2)"; } std::string abs(const Vector2 &) { return "abs(Vector2)"; }
// MSVC & Intel warns about unknown pragmas, and warnings are errors.
#if !defined(_MSC_VER) && !defined(__INTEL_COMPILER)
# pragma GCC diagnostic push
// clang 7.0.0 and Apple LLVM 10.0.1 introduce `-Wself-assign-overloaded` to // clang 7.0.0 and Apple LLVM 10.0.1 introduce `-Wself-assign-overloaded` to
// `-Wall`, which is used here for overloading (e.g. `py::self += py::self `). // `-Wall`, which is used here for overloading (e.g. `py::self += py::self `).
// Here, we suppress the warning using `#pragma diagnostic`. // Here, we suppress the warning
// Taken from: https://github.com/RobotLocomotion/drake/commit/aaf84b46 // Taken from: https://github.com/RobotLocomotion/drake/commit/aaf84b46
// TODO(eric): This could be resolved using a function / functor (e.g. `py::self()`). // TODO(eric): This could be resolved using a function / functor (e.g. `py::self()`).
# if defined(__APPLE__) && defined(__clang__) #if defined(__APPLE__) && defined(__clang__)
# if (__clang_major__ >= 10) # if (__clang_major__ >= 10)
# pragma GCC diagnostic ignored "-Wself-assign-overloaded" PYBIND11_WARNING_DISABLE_CLANG("-Wself-assign-overloaded")
# endif # endif
# elif defined(__clang__) #elif defined(__clang__)
# if (__clang_major__ >= 7) # if (__clang_major__ >= 7)
# pragma GCC diagnostic ignored "-Wself-assign-overloaded" PYBIND11_WARNING_DISABLE_CLANG("-Wself-assign-overloaded")
# endif
# endif # endif
#endif #endif
@ -283,6 +279,3 @@ TEST_SUBMODULE(operators, m) {
m.def("get_unhashable_HashMe_set", []() { return std::unordered_set<HashMe>{{"one"}}; }); m.def("get_unhashable_HashMe_set", []() { return std::unordered_set<HashMe>{{"one"}}; });
} }
#if !defined(_MSC_VER) && !defined(__INTEL_COMPILER)
# pragma GCC diagnostic pop
#endif