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).
required: false
- type: Input
- type: input
id: version
attributes:
label: What version (or hash if on master) of pybind11 are you using?
validations:
required: true
- type: textarea
@ -52,7 +53,7 @@ body:
starting point for working out fixes.
render: text
- type: Input
- type: input
id: regression
attributes:
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
- name: Publish standard package
uses: pypa/gh-action-pypi-publish@v1.5.1
uses: pypa/gh-action-pypi-publish@v1.5.2
with:
password: ${{ secrets.pypi_password }}
packages_dir: standard/
- name: Publish global package
uses: pypa/gh-action-pypi-publish@v1.5.1
uses: pypa/gh-action-pypi-publish@v1.5.2
with:
password: ${{ secrets.pypi_password_global }}
packages_dir: global/

View File

@ -35,6 +35,9 @@
#endif
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
PYBIND11_NAMESPACE_BEGIN(detail)
#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
// `PyUnicode_AsUTF8AndSize`.
if (PYBIND11_SILENCE_MSVC_C4127(UTF_N == 8)) {
if (UTF_N == 8) {
Py_ssize_t size = -1;
const auto *buffer
= 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()));
size_t length = (size_t) PYBIND11_BYTES_SIZE(utfNbytes.ptr()) / sizeof(CharT);
// Skip BOM for UTF-16/32
if (PYBIND11_SILENCE_MSVC_C4127(UTF_N > 8)) {
if (UTF_N > 8) {
buffer++;
length--;
}
@ -606,7 +609,7 @@ public:
// 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
// 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]);
// low bits only: 0-127
// 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
// surrogate pair with total length 2 instantly indicates a range error (but not a "your
// 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]);
if (one_char >= 0xD800 && one_char < 0xE000) {
throw value_error("Character code point not in range(0x10000)");

View File

@ -17,8 +17,69 @@
// Additional convention: 0xD = dev
#define PYBIND11_VERSION_HEX 0x020B00D1
#define PYBIND11_NAMESPACE_BEGIN(name) namespace name {
#define PYBIND11_NAMESPACE_END(name) }
// Define some generic pybind11 helper macros for warning management.
//
// 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
// 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
#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)
# pragma warning(disable : 4505)
# if defined(_DEBUG) && !defined(Py_DEBUG)
// Workaround for a VS 2022 issue.
// NOTE: This workaround knowingly violates the Python.h include order requirement:
@ -236,7 +297,7 @@
# define _DEBUG
# undef PYBIND11_DEBUG_MARKER
# endif
# pragma warning(pop)
PYBIND11_WARNING_POP
#endif
#include <cstddef>
@ -1160,17 +1221,6 @@ constexpr
# define PYBIND11_WORKAROUND_INCORRECT_GCC_UNUSED_BUT_SET_PARAMETER(...)
#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__) \
&& (defined(__apple_build_version__) /* AppleClang 13.0.0.13000029 was the only data point \
available. */ \

View File

@ -13,6 +13,9 @@
#include "smart_holder_sfinae_hooks_only.h"
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
PYBIND11_NAMESPACE_BEGIN(detail)
template <>
@ -116,7 +119,7 @@ template <typename Class>
void construct(value_and_holder &v_h, Cpp<Class> *ptr, bool need_alias) {
PYBIND11_WORKAROUND_INCORRECT_MSVC_C4100(need_alias);
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
// 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
@ -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);
no_nullptr(ptr);
// 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 "
"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);
static_assert(std::is_move_constructible<Cpp<Class>>::value,
"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));
} else {
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();
#if defined(WITH_THREAD)
# if PY_VERSION_HEX < 0x03090000
PyEval_InitThreads();
# endif
PyThreadState *tstate = PyThreadState_Get();
if (!PYBIND11_TLS_KEY_CREATE(internals_ptr->tstate)) {
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/1741816/isystem-for-ms-visual-studio-c-compiler
*/
// The C4127 suppression was introduced for Eigen 3.4.0. In theory we could
// make it version specific, or even remove it later, but considering that
// 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
PYBIND11_WARNING_PUSH
PYBIND11_WARNING_DISABLE_MSVC(5054) // https://github.com/pybind/pybind11/pull/3741
// C5054: operator '&': deprecated between enumerations of different types
#elif defined(__MINGW32__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
PYBIND11_WARNING_DISABLE_GCC("-Wmaybe-uninitialized")
#include <Eigen/Core>
#include <Eigen/SparseCore>
#if defined(_MSC_VER)
# pragma warning(pop)
#elif defined(__MINGW32__)
# pragma GCC diagnostic pop
#endif
PYBIND11_WARNING_POP
// 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
@ -48,6 +34,8 @@ static_assert(EIGEN_VERSION_AT_LEAST(3, 2, 7),
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
// Provide a convenience alias for easier pass-by-ref usage with fully dynamic strides:
using EigenDStride = Eigen::Stride<Eigen::Dynamic, Eigen::Dynamic>;
template <typename MatrixType>
@ -189,8 +177,7 @@ struct EigenProps {
EigenIndex np_rows = a.shape(0), np_cols = a.shape(1),
np_rstride = a.strides(0) / 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)
|| (PYBIND11_SILENCE_MSVC_C4127(fixed_cols) && np_cols != cols)) {
if ((fixed_rows && np_rows != rows) || (fixed_cols && np_cols != cols)) {
return false;
}
@ -203,7 +190,7 @@ struct EigenProps {
stride = a.strides(0) / static_cast<ssize_t>(sizeof(Scalar));
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 {rows == 1 ? 1 : n, cols == 1 ? 1 : n, stride};
@ -220,7 +207,7 @@ struct EigenProps {
}
return {1, n, stride};
} // 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 {n, 1, stride};

View File

@ -13,28 +13,23 @@
static_assert(__GNUC__ > 5, "Eigen Tensor support in pybind11 requires GCC > 5.0");
#endif
#if defined(_MSC_VER)
# pragma warning(push)
# pragma warning(disable : 4554) // Tensor.h warning
# pragma warning(disable : 4127) // Tensor.h warning
#elif defined(__MINGW32__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif
// Disable warnings for Eigen
PYBIND11_WARNING_PUSH
PYBIND11_WARNING_DISABLE_MSVC(4554)
PYBIND11_WARNING_DISABLE_MSVC(4127)
PYBIND11_WARNING_DISABLE_GCC("-Wmaybe-uninitialized")
#include <unsupported/Eigen/CXX11/Tensor>
#if defined(_MSC_VER)
# pragma warning(pop)
#elif defined(__MINGW32__)
# pragma GCC diagnostic pop
#endif
PYBIND11_WARNING_POP
static_assert(EIGEN_VERSION_AT_LEAST(3, 3, 0),
"Eigen Tensor support in pybind11 requires Eigen >= 3.3.0");
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
PYBIND11_NAMESPACE_BEGIN(detail)
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.
#if defined(__GNUC__)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wtype-limits"
#endif
PYBIND11_WARNING_PUSH
PYBIND11_WARNING_DISABLE_GCC("-Wtype-limits")
template <typename T, int size>
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;
}
#if defined(__GNUC__)
# pragma GCC diagnostic pop
#endif
PYBIND11_WARNING_POP
template <typename Type>
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;
if (PYBIND11_SILENCE_MSVC_C4127(is_aligned) && !is_tensor_aligned(arr.data())) {
if (is_aligned && !is_tensor_aligned(arr.data())) {
return false;
}
@ -403,7 +394,7 @@ struct type_caster<Eigen::TensorMap<Type, Options>,
return false;
}
if (PYBIND11_SILENCE_MSVC_C4127(needs_writeable) && !arr.writeable()) {
if (needs_writeable && !arr.writeable()) {
return false;
}

View File

@ -86,38 +86,26 @@ inline wchar_t *widen_chars(const char *safe_arg) {
return widened_arg;
}
PYBIND11_NAMESPACE_END(detail)
/** \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) {
inline void precheck_interpreter() {
if (Py_IsInitialized() != 0) {
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);
# 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
// 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();
PySys_SetArgvEx(argc, pysys_argv, static_cast<int>(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;
}
#endif
PyStatus status = PyConfig_SetBytesArgv(&config, argc, const_cast<char *const *>(argv));
if (PyStatus_Exception(status)) {
PYBIND11_NAMESPACE_END(detail)
#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
// interpreter out of memory. Give up.
PyConfig_Clear(&config);
throw std::runtime_error(PyStatus_IsError(status) ? status.err_msg
PyConfig_Clear(config);
throw std::runtime_error(PyStatus_IsError(status) != 0 ? status.err_msg
: "Failed to prepare CPython");
}
status = Py_InitializeFromConfig(&config);
PyConfig_Clear(&config);
if (PyStatus_Exception(status)) {
throw std::runtime_error(PyStatus_IsError(status) ? status.err_msg
status = Py_InitializeFromConfig(config);
if (PyStatus_Exception(status) != 0) {
PyConfig_Clear(config);
throw std::runtime_error(PyStatus_IsError(status) != 0 ? status.err_msg
: "Failed to init CPython");
}
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])) "
"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
}
@ -261,6 +290,15 @@ public:
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(scoped_interpreter &&other) noexcept { other.is_valid = false; }
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_WARNING_DISABLE_MSVC(4127)
class array; // Forward declaration
PYBIND11_NAMESPACE_BEGIN(detail)
@ -875,7 +877,7 @@ public:
*/
template <typename T, ssize_t Dims = -1>
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: "
+ std::to_string(ndim()) + "; expected "
+ std::to_string(Dims));
@ -893,7 +895,7 @@ public:
*/
template <typename T, ssize_t Dims = -1>
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: "
+ std::to_string(ndim()) + "; expected "
+ std::to_string(Dims));
@ -1865,9 +1867,10 @@ private:
}
auto result = returned_array::create(trivial, shape);
PYBIND11_WARNING_PUSH
#ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wreturn-std-move"
PYBIND11_WARNING_DISABLE_CLANG("-Wreturn-std-move")
#endif
if (size == 0) {
@ -1883,9 +1886,7 @@ private:
}
return result;
#ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING
# pragma clang diagnostic pop
#endif
PYBIND11_WARNING_POP
}
template <size_t... Index, size_t... VIndex, size_t... BIndex>

View File

@ -36,6 +36,8 @@
# include <cxxabi.h>
#endif
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
/* https://stackoverflow.com/questions/46798456/handling-gccs-noexcept-type-warning
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
@ -44,11 +46,10 @@
No other GCC version generates this warning.
*/
#if defined(__GNUC__) && __GNUC__ == 7
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wnoexcept-type"
PYBIND11_WARNING_DISABLE_GCC("-Wnoexcept-type")
#endif
PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
PYBIND11_WARNING_DISABLE_MSVC(4127)
PYBIND11_NAMESPACE_BEGIN(detail)
@ -178,22 +179,22 @@ protected:
auto *rec = unique_rec.get();
/* 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
enough space to use the placement new operator. However, the
'if' statement above ensures that this is the case. */
#if defined(__GNUG__) && __GNUC__ >= 6 && !defined(__clang__) && !defined(__INTEL_COMPILER)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wplacement-new"
PYBIND11_WARNING_PUSH
#if defined(__GNUG__) && __GNUC__ >= 6
PYBIND11_WARNING_DISABLE_GCC("-Wplacement-new")
#endif
new ((capture *) &rec->data) capture{std::forward<Func>(f)};
#if defined(__GNUG__) && __GNUC__ >= 6 && !defined(__clang__) && !defined(__INTEL_COMPILER)
# pragma GCC diagnostic pop
#endif
#if defined(__GNUG__) && !PYBIND11_HAS_STD_LAUNDER && !defined(__INTEL_COMPILER)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
#if !PYBIND11_HAS_STD_LAUNDER
PYBIND11_WARNING_DISABLE_GCC("-Wstrict-aliasing")
#endif
// 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) {
@ -203,9 +204,7 @@ protected:
data->~capture();
};
}
#if defined(__GNUG__) && !PYBIND11_HAS_STD_LAUNDER && !defined(__INTEL_COMPILER)
# pragma GCC diagnostic pop
#endif
PYBIND11_WARNING_POP
} else {
rec->data[0] = new capture{std::forward<Func>(f)};
rec->free_data = [](function_record *r) { delete ((capture *) r->data[0]); };
@ -2087,8 +2086,7 @@ private:
if (holder_ptr) {
init_holder_from_existing(v_h, holder_ptr, std::is_copy_constructible<holder_type>());
v_h.set_holder_constructed();
} else if (PYBIND11_SILENCE_MSVC_C4127(detail::always_construct_holder<holder_type>::value)
|| inst->owned) {
} else if (detail::always_construct_holder<holder_type>::value || inst->owned) {
new (std::addressof(v_h.holder<holder_type>())) holder_type(v_h.value_ptr<type>());
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_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_WARNING_DISABLE_MSVC(4127)
/* A few forward declarations */
class handle;
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
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
PYBIND11_WARNING_PUSH
PYBIND11_WARNING_DISABLE_MSVC(4522) // warning C4522: multiple assignment operators specified
template <typename Policy>
class accessor : public object_api<accessor<Policy>> {
using key_type = typename Policy::key_type;
@ -951,9 +951,7 @@ private:
key_type key;
mutable object cache;
};
#if defined(_MSC_VER) && _MSC_VER < 1920
# pragma warning(pop)
#endif
PYBIND11_WARNING_POP
PYBIND11_NAMESPACE_BEGIN(accessor_policies)
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).
template <typename Unsigned>
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);
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>
// NOLINTNEXTLINE(google-explicit-constructor)
int_(T value) {
if (PYBIND11_SILENCE_MSVC_C4127(sizeof(T) <= sizeof(long))) {
if (sizeof(T) <= sizeof(long)) {
if (std::is_signed<T>::value) {
m_ptr = PyLong_FromLong((long) value);
} else {

View File

@ -7,6 +7,8 @@ Adds docstring and exceptions message sanitizers.
import contextlib
import difflib
import gc
import multiprocessing
import os
import re
import textwrap
@ -15,6 +17,22 @@ import pytest
# Early diagnostic for failed imports
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")
_hexadecimal = re.compile(r"0x[0-9a-fA-F]+")

View File

@ -80,6 +80,9 @@ PYBIND11_NAMESPACE_END(detail)
PYBIND11_NAMESPACE_END(pybind11)
TEST_SUBMODULE(builtin_casters, m) {
PYBIND11_WARNING_PUSH
PYBIND11_WARNING_DISABLE_MSVC(4127)
// test_simple_string
m.def("string_roundtrip", [](const char *s) { return s; });
@ -93,7 +96,7 @@ TEST_SUBMODULE(builtin_casters, m) {
std::wstring wstr;
wstr.push_back(0x61); // a
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_2);
} // 𝐀, utf16
@ -120,7 +123,7 @@ TEST_SUBMODULE(builtin_casters, m) {
// Under Python 2.7, invalid unicode UTF-32 characters didn't appear to trigger
// UnicodeDecodeError
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", [=]() {
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"); },
py::return_value_policy::_return_as_bytes);
#endif
PYBIND11_WARNING_POP
}

View File

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

View File

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

View File

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

View File

@ -9,7 +9,9 @@
#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>
void reset_tensor(M &x) {
@ -90,7 +92,7 @@ struct CustomExample {
template <int Options>
void init_tensor_module(pybind11::module &m) {
const char *needed_options = "";
if (PYBIND11_SILENCE_MSVC_C4127(Options == Eigen::ColMajor)) {
if (Options == Eigen::ColMajor) {
needed_options = "F";
} else {
needed_options = "C";
@ -330,4 +332,4 @@ void test_module(py::module_ &m) {
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>
#ifdef _MSC_VER
// 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).
# pragma warning(disable : 4996)
#endif
PYBIND11_WARNING_DISABLE_MSVC(4996)
// Catch uses _ internally, which breaks gettext style defines
#ifdef _

View File

@ -1,10 +1,8 @@
#include <pybind11/embed.h>
#ifdef _MSC_VER
// 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).
# pragma warning(disable : 4996)
#endif
PYBIND11_WARNING_DISABLE_MSVC(4996)
#include <catch.hpp>
#include <cstdlib>
@ -16,6 +14,11 @@
namespace py = pybind11;
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 {
public:
explicit Widget(std::string message) : message(std::move(message)) {}
@ -168,6 +171,70 @@ TEST_CASE("There can be only one 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() {
auto builtins = py::handle(PyEval_GetBuiltins());
return builtins.contains(PYBIND11_INTERNALS_ID);

View File

@ -5,6 +5,7 @@ import time
import pytest
import env
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,)
SKIP_IF_DEADLOCK = True # See PR #4216
def _run_in_process(target, *args, **kwargs):
@ -181,7 +181,7 @@ def _run_in_process(target, *args, **kwargs):
elif process.exitcode is None:
assert t_delta > 0.9 * timeout
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)
raise RuntimeError(msg)
return process.exitcode

View File

@ -44,14 +44,13 @@ TEST_SUBMODULE(kwargs_and_defaults, m) {
// test_args_and_kwargs
m.def("args_function", [](py::args args) -> py::tuple {
PYBIND11_WARNING_PUSH
#ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING
# pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wreturn-std-move"
PYBIND11_WARNING_DISABLE_CLANG("-Wreturn-std-move")
#endif
return args;
#ifdef PYBIND11_DETECTED_CLANG_WITH_MISLEADING_CALL_STD_MOVE_EXPLICITLY_WARNING
# pragma clang diagnostic pop
#endif
PYBIND11_WARNING_POP
});
m.def("args_kwargs_function", [](const py::args &args, const py::kwargs &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.
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
// `-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
// 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)
# pragma GCC diagnostic ignored "-Wself-assign-overloaded"
PYBIND11_WARNING_DISABLE_CLANG("-Wself-assign-overloaded")
# endif
# elif defined(__clang__)
#elif defined(__clang__)
# if (__clang_major__ >= 7)
# pragma GCC diagnostic ignored "-Wself-assign-overloaded"
# endif
PYBIND11_WARNING_DISABLE_CLANG("-Wself-assign-overloaded")
# endif
#endif
@ -283,6 +279,3 @@ TEST_SUBMODULE(operators, m) {
m.def("get_unhashable_HashMe_set", []() { return std::unordered_set<HashMe>{{"one"}}; });
}
#if !defined(_MSC_VER) && !defined(__INTEL_COMPILER)
# pragma GCC diagnostic pop
#endif