@@ -166,13 +166,38 @@ struct list_caster {
166166 using value_conv = make_caster<Value>;
167167
168168 bool load (handle src, bool convert) {
169- if (!isinstance<sequence>(src) || isinstance<bytes>(src) || isinstance<str>(src)) {
169+ if (isinstance<bytes>(src) || isinstance<str>(src)) {
170170 return false ;
171171 }
172- auto s = reinterpret_borrow<sequence>(src);
172+ if (isinstance<sequence>(src)) {
173+ return convert_elements (src, convert);
174+ }
175+ if (!convert) {
176+ return false ;
177+ }
178+ if (PyGen_Check (src.ptr ())) {
179+ // Designed to be behavior-equivalent to passing tuple(src) from Python:
180+ // The conversion to a tuple will first exhaust the generator object, to ensure that
181+ // the generator is not left in an unpredictable (to the caller) partially-consumed
182+ // state.
183+ assert (isinstance<iterable>(src));
184+ return convert_elements (tuple (reinterpret_borrow<iterable>(src)), convert);
185+ }
186+ return false ;
187+ }
188+
189+ private:
190+ template <typename T = Type, enable_if_t <has_reserve_method<T>::value, int > = 0 >
191+ void reserve_maybe (const sequence &s, Type *) {
192+ value.reserve (s.size ());
193+ }
194+ void reserve_maybe (const sequence &, void *) {}
195+
196+ bool convert_elements (handle seq, bool convert) {
197+ auto s = reinterpret_borrow<sequence>(seq);
173198 value.clear ();
174199 reserve_maybe (s, &value);
175- for (auto it : s ) {
200+ for (auto it : seq ) {
176201 value_conv conv;
177202 if (!conv.load (it, convert)) {
178203 return false ;
@@ -182,13 +207,6 @@ struct list_caster {
182207 return true ;
183208 }
184209
185- private:
186- template <typename T = Type, enable_if_t <has_reserve_method<T>::value, int > = 0 >
187- void reserve_maybe (const sequence &s, Type *) {
188- value.reserve (s.size ());
189- }
190- void reserve_maybe (const sequence &, void *) {}
191-
192210public:
193211 template <typename T>
194212 static handle cast (T &&src, return_value_policy policy, handle parent) {
0 commit comments