From ff97f101d96cc780ce348ac6b4b4464982578929 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 26 Jul 2021 11:28:36 -0700 Subject: [PATCH 1/4] Removing MSVC C4996 from pragma block at the top of pybind11.h (#3129) * Removing MSVC C4996 from pragma block at the top of pybind11.h * localtime_thread_safe, PYBIND11_COMPAT_STRDUP * Adding #include (attempt to fix MSVC 2015, 2017 errors). --- include/pybind11/chrono.h | 33 +++++++++++++++++++++++--------- include/pybind11/detail/common.h | 5 +++++ include/pybind11/pybind11.h | 19 ++++++++++++------ 3 files changed, 42 insertions(+), 15 deletions(-) diff --git a/include/pybind11/chrono.h b/include/pybind11/chrono.h index d32b5b0569..c4e81f5720 100644 --- a/include/pybind11/chrono.h +++ b/include/pybind11/chrono.h @@ -11,9 +11,14 @@ #pragma once #include "pybind11.h" + +#include #include #include -#include +#include + +#include + #include // Backport the PyDateTime_DELTA functions from Python3.3 if required @@ -95,6 +100,22 @@ template class duration_caster { PYBIND11_TYPE_CASTER(type, _("datetime.timedelta")); }; +inline std::tm *localtime_thread_safe(const std::time_t *time, std::tm *buf) { +#if defined(__STDC_WANT_LIB_EXT1__) || defined(_MSC_VER) + if (localtime_s(buf, time)) + return nullptr; + return buf; +#else + static std::mutex mtx; + std::lock_guard lock(mtx); + std::tm *tm_ptr = localtime(time); + if (tm_ptr != nullptr) { + *buf = *tm_ptr; + } + return tm_ptr; +#endif +} + // This is for casting times on the system clock into datetime.datetime instances template class type_caster> { public: @@ -162,16 +183,10 @@ template class type_caster(src - us)); - // std::localtime returns a pointer to a static internal std::tm object on success, - // or null pointer otherwise - std::tm *localtime_ptr = std::localtime(&tt); + std::tm localtime; + std::tm *localtime_ptr = localtime_thread_safe(&tt, &localtime); if (!localtime_ptr) throw cast_error("Unable to represent system_clock in local time"); - - // this function uses static memory so it's best to copy it out asap just in case - // otherwise other code that is using localtime may break this (not just python code) - std::tm localtime = *localtime_ptr; - return PyDateTime_FromDateAndTime(localtime.tm_year + 1900, localtime.tm_mon + 1, localtime.tm_mday, diff --git a/include/pybind11/detail/common.h b/include/pybind11/detail/common.h index 52b0193350..3faf3ea327 100644 --- a/include/pybind11/detail/common.h +++ b/include/pybind11/detail/common.h @@ -125,6 +125,11 @@ # endif #endif +// https://en.cppreference.com/w/c/chrono/localtime +#if defined(__STDC_LIB_EXT1__) && !defined(__STDC_WANT_LIB_EXT1__) +# define __STDC_WANT_LIB_EXT1__ +#endif + #include #include #include diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 0c25ca1a23..696e7cd377 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -19,7 +19,6 @@ # pragma warning(disable: 4100) // warning C4100: Unreferenced formal parameter # pragma warning(disable: 4127) // warning C4127: Conditional expression is constant # pragma warning(disable: 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning) -# pragma warning(disable: 4996) // warning C4996: The POSIX name for this item is deprecated. Instead, use the ISO C and C++ conformant name # pragma warning(disable: 4522) // warning C4522: multiple assignment operators specified # pragma warning(disable: 4505) // warning C4505: 'PySlice_GetIndicesEx': unreferenced local function has been removed (PyPy only) #elif defined(__GNUG__) && !defined(__clang__) @@ -43,6 +42,8 @@ #include #include +#include + #if defined(__cpp_lib_launder) && !(defined(_MSC_VER) && (_MSC_VER < 1914)) # define PYBIND11_STD_LAUNDER std::launder # define PYBIND11_HAS_STD_LAUNDER 1 @@ -76,8 +77,13 @@ inline bool apply_exception_translators(std::forward_list& return false; } -PYBIND11_NAMESPACE_END(detail) +#if defined(_MSC_VER) +# define PYBIND11_COMPAT_STRDUP _strdup +#else +# define PYBIND11_COMPAT_STRDUP strdup +#endif +PYBIND11_NAMESPACE_END(detail) /// Wraps an arbitrary C++ function/method/lambda function/.. into a callable Python object class cpp_function : public function { @@ -276,7 +282,7 @@ class cpp_function : public function { std::free(s); } char *operator()(const char *s) { - auto t = strdup(s); + auto t = PYBIND11_COMPAT_STRDUP(s); strings.push_back(t); return t; } @@ -520,7 +526,8 @@ class cpp_function : public function { auto *func = (PyCFunctionObject *) m_ptr; std::free(const_cast(func->m_ml->ml_doc)); // Install docstring if it's non-empty (when at least one option is enabled) - func->m_ml->ml_doc = signatures.empty() ? nullptr : strdup(signatures.c_str()); + func->m_ml->ml_doc + = signatures.empty() ? nullptr : PYBIND11_COMPAT_STRDUP(signatures.c_str()); if (rec->is_method) { m_ptr = PYBIND11_INSTANCE_METHOD_NEW(m_ptr, rec->scope.ptr()); @@ -1525,7 +1532,7 @@ class class_ : public detail::generic_type { detail::process_attributes::init(extra..., rec_fget); if (rec_fget->doc && rec_fget->doc != doc_prev) { free(doc_prev); - rec_fget->doc = strdup(rec_fget->doc); + rec_fget->doc = PYBIND11_COMPAT_STRDUP(rec_fget->doc); } } if (rec_fset) { @@ -1533,7 +1540,7 @@ class class_ : public detail::generic_type { detail::process_attributes::init(extra..., rec_fset); if (rec_fset->doc && rec_fset->doc != doc_prev) { free(doc_prev); - rec_fset->doc = strdup(rec_fset->doc); + rec_fset->doc = PYBIND11_COMPAT_STRDUP(rec_fset->doc); } if (! rec_active) rec_active = rec_fset; } From 7904ba1a5c600ea8455b16c1010a1d46181d3148 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 26 Jul 2021 12:02:50 -0700 Subject: [PATCH 2/4] Adding pragma warning(disable: 4522) for MSVC <= 2017. (#3142) --- include/pybind11/pybind11.h | 1 - include/pybind11/pytypes.h | 7 +++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 696e7cd377..9c0b723839 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -19,7 +19,6 @@ # pragma warning(disable: 4100) // warning C4100: Unreferenced formal parameter # pragma warning(disable: 4127) // warning C4127: Conditional expression is constant # pragma warning(disable: 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning) -# pragma warning(disable: 4522) // warning C4522: multiple assignment operators specified # pragma warning(disable: 4505) // warning C4505: 'PySlice_GetIndicesEx': unreferenced local function has been removed (PyPy only) #elif defined(__GNUG__) && !defined(__clang__) # pragma GCC diagnostic push diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index b483fb323c..3329982777 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -532,6 +532,10 @@ object object_or_cast(T &&o); // Match a PyObject*, which we want to convert directly to handle via its converting constructor inline handle object_or_cast(PyObject *ptr) { return ptr; } +#if defined(_MSC_VER) && _MSC_VER < 1920 +# pragma warning(push) +# pragma warning(disable: 4522) // warning C4522: multiple assignment operators specified +#endif template class accessor : public object_api> { using key_type = typename Policy::key_type; @@ -580,6 +584,9 @@ class accessor : public object_api> { key_type key; mutable object cache; }; +#if defined(_MSC_VER) && _MSC_VER < 1920 +# pragma warning(pop) +#endif PYBIND11_NAMESPACE_BEGIN(accessor_policies) struct obj_attr { From 7f76d79508475ef2e8f17941e350b1dfa8d828b4 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 26 Jul 2021 15:05:58 -0400 Subject: [PATCH 3/4] [pre-commit.ci] pre-commit autoupdate (#3143) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/asottile/pyupgrade: v2.21.2 → v2.23.0](https://github.com/asottile/pyupgrade/compare/v2.21.2...v2.23.0) Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aa7b4774e3..510b841260 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -31,7 +31,7 @@ repos: exclude: ^noxfile.py$ - repo: https://github.com/asottile/pyupgrade - rev: v2.21.2 + rev: v2.23.0 hooks: - id: pyupgrade From a0f862d428acd11dacb344ce9690e420d98cde53 Mon Sep 17 00:00:00 2001 From: "Ralf W. Grosse-Kunstleve" Date: Mon, 26 Jul 2021 13:26:36 -0700 Subject: [PATCH 4/4] Removing MSVC C4800 from pragma block at the top of pybind11.h (#3141) * Adding PYBIND11_COMPAT_BOOL_CAST to appease MSVC 2015 warning C4800. * Replacing PYBIND11_COMPAT_BOOL_CAST with simpler != 0 * Extra parentheses (almost all compilers failed without these). --- include/pybind11/buffer_info.h | 2 +- include/pybind11/cast.h | 2 +- include/pybind11/detail/type_caster_base.h | 4 ++-- include/pybind11/pybind11.h | 1 - include/pybind11/pytypes.h | 6 ++++-- 5 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/pybind11/buffer_info.h b/include/pybind11/buffer_info.h index 47dc39d4ea..eba68d1aa1 100644 --- a/include/pybind11/buffer_info.h +++ b/include/pybind11/buffer_info.h @@ -83,7 +83,7 @@ struct buffer_info { view->strides ? std::vector(view->strides, view->strides + view->ndim) : detail::c_strides({view->shape, view->shape + view->ndim}, view->itemsize), - view->readonly) { + (view->readonly != 0)) { this->m_view = view; this->ownview = ownview; } diff --git a/include/pybind11/cast.h b/include/pybind11/cast.h index a748c77c0f..1da432358f 100644 --- a/include/pybind11/cast.h +++ b/include/pybind11/cast.h @@ -322,7 +322,7 @@ template <> class type_caster { } #endif if (res == 0 || res == 1) { - value = (bool) res; + value = (res != 0); return true; } PyErr_Clear(); diff --git a/include/pybind11/detail/type_caster_base.h b/include/pybind11/detail/type_caster_base.h index bdf3a39822..a6b6bea6a3 100644 --- a/include/pybind11/detail/type_caster_base.h +++ b/include/pybind11/detail/type_caster_base.h @@ -231,7 +231,7 @@ struct value_and_holder { return reinterpret_cast(vh[0]); } // True if this `value_and_holder` has a non-null value pointer - explicit operator bool() const { return value_ptr(); } + explicit operator bool() const { return value_ptr() != nullptr; } template H &holder() const { return reinterpret_cast(vh[1]); @@ -252,7 +252,7 @@ struct value_and_holder { bool instance_registered() const { return inst->simple_layout ? inst->simple_instance_registered - : inst->nonsimple.status[index] & instance::status_instance_registered; + : ((inst->nonsimple.status[index] & instance::status_instance_registered) != 0); } void set_instance_registered(bool v = true) const { if (inst->simple_layout) diff --git a/include/pybind11/pybind11.h b/include/pybind11/pybind11.h index 9c0b723839..93b920d852 100644 --- a/include/pybind11/pybind11.h +++ b/include/pybind11/pybind11.h @@ -18,7 +18,6 @@ # pragma warning(push) # pragma warning(disable: 4100) // warning C4100: Unreferenced formal parameter # pragma warning(disable: 4127) // warning C4127: Conditional expression is constant -# pragma warning(disable: 4800) // warning C4800: 'int': forcing value to bool 'true' or 'false' (performance warning) # pragma warning(disable: 4505) // warning C4505: 'PySlice_GetIndicesEx': unreferenced local function has been removed (PyPy only) #elif defined(__GNUG__) && !defined(__clang__) # pragma GCC diagnostic push diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index 3329982777..cea4e7eb01 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -367,7 +367,9 @@ class PYBIND11_EXPORT error_already_set : public std::runtime_error { /// Check if the currently trapped error type matches the given Python exception class (or a /// subclass thereof). May also be passed a tuple to search for any exception class matches in /// the given tuple. - bool matches(handle exc) const { return PyErr_GivenExceptionMatches(m_type.ptr(), exc.ptr()); } + bool matches(handle exc) const { + return (PyErr_GivenExceptionMatches(m_type.ptr(), exc.ptr()) != 0); + } const object& type() const { return m_type; } const object& value() const { return m_value; } @@ -853,7 +855,7 @@ PYBIND11_NAMESPACE_END(detail) Name(handle h, borrowed_t) : Parent(h, borrowed_t{}) { } \ Name(handle h, stolen_t) : Parent(h, stolen_t{}) { } \ PYBIND11_DEPRECATED("Use py::isinstance(obj) instead") \ - bool check() const { return m_ptr != nullptr && (bool) CheckFun(m_ptr); } \ + bool check() const { return m_ptr != nullptr && (CheckFun(m_ptr) != 0); } \ static bool check_(handle h) { return h.ptr() != nullptr && CheckFun(h.ptr()); } \ template \ Name(const ::pybind11::detail::accessor &a) : Name(object(a)) { }