66
77#include " libpy/any.h"
88#include " libpy/char_sequence.h"
9- #include " libpy/dense_hash_map.h"
109#include " libpy/itertools.h"
1110#include " libpy/meta.h"
1211#include " libpy/numpy_utils.h"
@@ -21,162 +20,26 @@ using namespace py::cs::literals;
2120
2221class to_object : public with_python_interpreter {};
2322
24- template <typename T>
25- std::array<T, 3 > examples ();
26-
27- template <>
28- std::array<std::int64_t , 3 > examples () {
29- return {-200 , 0 , 1000 };
30- }
31-
32- template <>
33- std::array<std::string, 3 > examples () {
34- return {" foo" , " " , " arglebargle" };
35- }
36-
37- template <>
38- std::array<std::array<char , 3 >, 3 > examples () {
39- std::array<char , 3 > foo{' f' , ' o' , ' o' };
40- std::array<char , 3 > bar{' b' , ' a' , ' r' };
41- std::array<char , 3 > baz{' b' , ' a' , ' z' };
42- return {foo, bar, baz};
43- }
44-
45- template <>
46- std::array<bool , 3 > examples () {
47- return {true , false , true };
48- }
49-
50- template <>
51- std::array<double , 3 > examples () {
52- return {-1.0 , -0.0 , 100.0 };
53- }
54-
55- template <>
56- std::array<py::owned_ref<>, 3 > examples () {
57- Py_INCREF (Py_True);
58- Py_INCREF (Py_False);
59- Py_INCREF (Py_None);
60- return {py::owned_ref<>(Py_True),
61- py::owned_ref<>(Py_False),
62- py::owned_ref<>(Py_None)};
63- }
64-
65- template <typename M>
66- void test_map_to_object_impl (M m) {
67-
68- // Fill the map with some example values.
69- auto it = py::zip (examples<typename M::key_type>(),
70- examples<typename M::mapped_type>());
71- for (auto [key, value] : it) {
72- m[key] = value;
73- }
74-
75- auto check_python_map = [&](py::owned_ref<PyObject> ob) {
76- ASSERT_TRUE (ob) << " to_object should not return null" ;
77- EXPECT_TRUE (PyDict_Check (ob.get ()));
78-
79- // Python map should be the same length as C++ map.
80- Py_ssize_t len = PyDict_Size (ob.get ());
81- EXPECT_EQ (std::size_t (len), m.size ())
82- << " Python dict length should match C++ map length." ;
83-
84- // Key/Value pairs in the python map should match the result of calling
85- // to_object on each key/value pair in the C++ map.
86- for (auto & [cxx_key, cxx_value] : m) {
87- auto py_key = py::to_object (cxx_key);
88- auto py_value = py::to_object (cxx_value);
89-
90- py::borrowed_ref result = PyDict_GetItem (ob.get (), py_key.get ());
91- ASSERT_TRUE (result) << " Key should have been in the map" ;
92-
93- bool values_equal =
94- PyObject_RichCompareBool (py_value.get (), result.get (), Py_EQ);
95- EXPECT_EQ (values_equal, 1 ) << " Dict values were not equal" ;
96- }
97- };
98-
99- // Check to_object with value, const value, and rvalue reference.
100-
101- py::owned_ref<PyObject> result = py::to_object (m);
102- check_python_map (result);
103-
104- const M& const_ref = m;
105- py::owned_ref<PyObject> constref_result = py::to_object (const_ref);
106- check_python_map (constref_result);
107-
108- M copy = m; // Make a copy before moving b/c the lambda above uses ``m``.
109- py::owned_ref<PyObject> rvalueref_result = py::to_object (std::move (copy));
110- check_python_map (rvalueref_result);
111- }
112-
11323TEST_F (to_object, map_to_object) {
114- // NOTE: This test takes a long time to compile (about a .5s per entry in this
115- // tuple). This is just enough coverage to test all three of our hash table types,
116- // and a few important key/value types.
117- auto maps = std::make_tuple (py::dense_hash_map<std::string, py::owned_ref<PyObject>>(
118- " missing_value" s),
119- py::sparse_hash_map<std::int64_t , std::array<char , 3 >>(),
120- std::unordered_map<std::string, bool >());
121-
122- // Call test_map_to_object_impl on each entry in ``maps``.
123- std::apply ([&](auto ... map) { (test_map_to_object_impl (map), ...); }, maps);
124- }
125-
126- template <typename V>
127- void test_sequence_to_object_impl (V v) {
128- auto check_python_list = [&](py::owned_ref<PyObject> ob) {
129- ASSERT_TRUE (ob) << " to_object should not return null" ;
130- EXPECT_EQ (PyList_Check (ob.get ()), 1 ) << " ob should be a list" ;
131-
132- Py_ssize_t len = PyList_GET_SIZE (ob.get ());
133- EXPECT_EQ (std::size_t (len), v.size ())
134- << " Python list length should match C++ vector length." ;
135-
136- // Values in Python list should be the result of calling to_object on each entry
137- // in the C++ vector.
138- for (auto [i, cxx_value] : py::enumerate (v)) {
139- auto py_value = py::to_object (cxx_value);
140-
141- py::borrowed_ref result = PyList_GetItem (ob.get (), i);
142- ASSERT_TRUE (result) << " Should have had a value at index " << i;
143-
144- bool values_equal =
145- PyObject_RichCompareBool (py_value.get (), result.get (), Py_EQ);
146- EXPECT_EQ (values_equal, 1 )
147- << " List values at index " << i << " were not equal" ;
148- }
149- };
150-
151- // Check to_object with value, const value, and rvalue reference.
152-
153- py::owned_ref<PyObject> result = py::to_object (v);
154- check_python_list (result);
155-
156- const V& const_ref = v;
157- py::owned_ref<PyObject> constref_result = py::to_object (const_ref);
158- check_python_list (constref_result);
159-
160- V copy = v; // Make a copy before moving b/c the lambda above uses ``v``.
161- py::owned_ref<PyObject> rvalueref_result = py::to_object (std::move (copy));
162- check_python_list (rvalueref_result);
24+ auto map = std::unordered_map<std::string, bool >();
25+ py_test::test_map_to_object_impl (map);
16326}
16427
16528TEST_F (to_object, vector_to_object) {
16629 auto to_vec = [](const auto & arr) { return std::vector (arr.begin (), arr.end ()); };
167- auto vectors = std::make_tuple (to_vec (examples<std::string>()),
168- to_vec (examples<double >()),
169- to_vec (examples<py::owned_ref<>>()));
30+ auto vectors = std::make_tuple (to_vec (py_test:: examples<std::string>()),
31+ to_vec (py_test:: examples<double >()),
32+ to_vec (py_test:: examples<py::owned_ref<>>()));
17033 // Call test_sequence_to_object_impl on each entry in `vectors`.
171- std::apply ([&](auto ... vec) { (test_sequence_to_object_impl (vec), ...); }, vectors);
34+ std::apply ([&](auto ... vec) { (py_test:: test_sequence_to_object_impl (vec), ...); }, vectors);
17235}
17336
17437TEST_F (to_object, array_to_object) {
175- auto arrays = std::make_tuple (examples<std::string>(),
176- examples<double >(),
177- examples<py::owned_ref<>>());
38+ auto arrays = std::make_tuple (py_test:: examples<std::string>(),
39+ py_test:: examples<double >(),
40+ py_test:: examples<py::owned_ref<>>());
17841 // Call test_sequence_to_object_impl on each entry in `arrays`.
179- std::apply ([&](auto ... arr) { (test_sequence_to_object_impl (arr), ...); }, arrays);
42+ std::apply ([&](auto ... arr) { (py_test:: test_sequence_to_object_impl (arr), ...); }, arrays);
18043}
18144
18245template <typename R, typename T>
0 commit comments