Skip to content

Commit e76dff7

Browse files
allanlealwjakob
authored andcommitted
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<string> #1258" (#1258) * Added tests for fix of issue #1258 * Changelog: stl string auto-conversion
1 parent 0f404a5 commit e76dff7

File tree

4 files changed

+22
-1
lines changed

4 files changed

+22
-1
lines changed

docs/changelog.rst

+3
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ v2.3.0 (Not yet released)
4747
* ``pybind11_add_module()``: allow including Python as a ``SYSTEM`` include path.
4848
`#1416 <https://github.com/pybind/pybind11/pull/1416>`_.
4949

50+
* ``pybind11/stl.h`` does not convert strings to ``vector<string>`` anymore.
51+
`#1258 <https://github.com/pybind/pybind11/issues/1258>`_.
52+
5053
v2.2.4 (September 11, 2018)
5154
-----------------------------------------------------
5255

include/pybind11/stl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ template <typename Type, typename Value> struct list_caster {
138138
using value_conv = make_caster<Value>;
139139

140140
bool load(handle src, bool convert) {
141-
if (!isinstance<sequence>(src))
141+
if (!isinstance<sequence>(src) || isinstance<str>(src))
142142
return false;
143143
auto s = reinterpret_borrow<sequence>(src);
144144
value.clear();

tests/test_stl.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111
#include "constructor_stats.h"
1212
#include <pybind11/stl.h>
1313

14+
#include <vector>
15+
#include <string>
16+
1417
// Test with `std::variant` in C++17 mode, or with `boost::variant` in C++11/14
1518
#if PYBIND11_HAS_VARIANT
1619
using std::variant;
@@ -33,6 +36,8 @@ struct visit_helper<boost::variant> {
3336
}} // namespace pybind11::detail
3437
#endif
3538

39+
PYBIND11_MAKE_OPAQUE(std::vector<std::string, std::allocator<std::string>>);
40+
3641
/// Issue #528: templated constructor
3742
struct TplCtorClass {
3843
template <typename T> TplCtorClass(const T &) { }
@@ -237,6 +242,11 @@ TEST_SUBMODULE(stl, m) {
237242
// test_stl_pass_by_pointer
238243
m.def("stl_pass_by_pointer", [](std::vector<int>* v) { return *v; }, "v"_a=nullptr);
239244

245+
// #1258: pybind11/stl.h converts string to vector<string>
246+
m.def("func_with_string_or_vector_string_arg_overload", [](std::vector<std::string>) { return 1; });
247+
m.def("func_with_string_or_vector_string_arg_overload", [](std::list<std::string>) { return 2; });
248+
m.def("func_with_string_or_vector_string_arg_overload", [](std::string) { return 3; });
249+
240250
class Placeholder {
241251
public:
242252
Placeholder() { print_created(this); }

tests/test_stl.py

+8
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,14 @@ def test_missing_header_message():
201201
assert expected_message in str(excinfo.value)
202202

203203

204+
def test_function_with_string_and_vector_string_arg():
205+
"""Check if a string is NOT implicitly converted to a list, which was the
206+
behavior before fix of issue #1258"""
207+
assert m.func_with_string_or_vector_string_arg_overload(('A', 'B', )) == 2
208+
assert m.func_with_string_or_vector_string_arg_overload(['A', 'B']) == 2
209+
assert m.func_with_string_or_vector_string_arg_overload('A') == 3
210+
211+
204212
def test_stl_ownership():
205213
cstats = ConstructorStats.get(m.Placeholder)
206214
assert cstats.alive() == 0

0 commit comments

Comments
 (0)