From e76dff7751847df560bc0aea79abae814d39b475 Mon Sep 17 00:00:00 2001 From: Allan Leal Date: Thu, 11 Oct 2018 10:28:12 +0200 Subject: [PATCH] Fix for Issue #1258 (#1298) * Fix for Issue #1258 list_caster::load method will now check for a Python string and prevent its automatic conversion to a list. This should fix the issue "pybind11/stl.h converts string to vector #1258" (https://github.com/pybind/pybind11/issues/1258) * Added tests for fix of issue #1258 * Changelog: stl string auto-conversion --- docs/changelog.rst | 3 +++ include/pybind11/stl.h | 2 +- tests/test_stl.cpp | 10 ++++++++++ tests/test_stl.py | 8 ++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/docs/changelog.rst b/docs/changelog.rst index eb25578c..606be413 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -47,6 +47,9 @@ v2.3.0 (Not yet released) * ``pybind11_add_module()``: allow including Python as a ``SYSTEM`` include path. `#1416 `_. +* ``pybind11/stl.h`` does not convert strings to ``vector`` anymore. + `#1258 `_. + v2.2.4 (September 11, 2018) ----------------------------------------------------- diff --git a/include/pybind11/stl.h b/include/pybind11/stl.h index faa7087e..659505d8 100644 --- a/include/pybind11/stl.h +++ b/include/pybind11/stl.h @@ -138,7 +138,7 @@ template struct list_caster { using value_conv = make_caster; bool load(handle src, bool convert) { - if (!isinstance(src)) + if (!isinstance(src) || isinstance(src)) return false; auto s = reinterpret_borrow(src); value.clear(); diff --git a/tests/test_stl.cpp b/tests/test_stl.cpp index cd0985d0..8736ea86 100644 --- a/tests/test_stl.cpp +++ b/tests/test_stl.cpp @@ -11,6 +11,9 @@ #include "constructor_stats.h" #include +#include +#include + // Test with `std::variant` in C++17 mode, or with `boost::variant` in C++11/14 #if PYBIND11_HAS_VARIANT using std::variant; @@ -33,6 +36,8 @@ struct visit_helper { }} // namespace pybind11::detail #endif +PYBIND11_MAKE_OPAQUE(std::vector>); + /// Issue #528: templated constructor struct TplCtorClass { template TplCtorClass(const T &) { } @@ -237,6 +242,11 @@ TEST_SUBMODULE(stl, m) { // test_stl_pass_by_pointer m.def("stl_pass_by_pointer", [](std::vector* v) { return *v; }, "v"_a=nullptr); + // #1258: pybind11/stl.h converts string to vector + m.def("func_with_string_or_vector_string_arg_overload", [](std::vector) { return 1; }); + m.def("func_with_string_or_vector_string_arg_overload", [](std::list) { return 2; }); + m.def("func_with_string_or_vector_string_arg_overload", [](std::string) { return 3; }); + class Placeholder { public: Placeholder() { print_created(this); } diff --git a/tests/test_stl.py b/tests/test_stl.py index 2c5e995f..b78f86a2 100644 --- a/tests/test_stl.py +++ b/tests/test_stl.py @@ -201,6 +201,14 @@ def test_missing_header_message(): assert expected_message in str(excinfo.value) +def test_function_with_string_and_vector_string_arg(): + """Check if a string is NOT implicitly converted to a list, which was the + behavior before fix of issue #1258""" + assert m.func_with_string_or_vector_string_arg_overload(('A', 'B', )) == 2 + assert m.func_with_string_or_vector_string_arg_overload(['A', 'B']) == 2 + assert m.func_with_string_or_vector_string_arg_overload('A') == 3 + + def test_stl_ownership(): cstats = ConstructorStats.get(m.Placeholder) assert cstats.alive() == 0