Repository: marshmallow-code/marshmallow

Issue:
2.x: Nested(many=True) eats first element from generator value when dumping
As reproduced in Python 3.6.8:

```py
from marshmallow import Schema, fields

class O(Schema):
    i = fields.Int()

class P(Schema):
    os = fields.Nested(O, many=True)

def gen():
    yield {'i': 1}
    yield {'i': 0}

p = P()
p.dump({'os': gen()})
# MarshalResult(data={'os': [{'i': 0}]}, errors={})
```

Problematic code is here:

https://github.com/marshmallow-code/marshmallow/blob/2.x-line/src/marshmallow/fields.py#L447

And here:

https://github.com/marshmallow-code/marshmallow/blob/2.x-line/src/marshmallow/schema.py#L832

The easiest solution would be to cast `nested_obj` to list before calling `schema._update_fields`, just like a normal Schema with `many=True` does.

Discussion:

Patch:
diff --git a/AUTHORS.rst b/AUTHORS.rst
index 2892e5c3..9eecb9f5 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -89,3 +89,4 @@ Contributors (chronological)
 - Jan Margeta `@jmargeta <https://github.com/jmargeta>`_
 - AlexV `@asmodehn <https://github.com/asmodehn>`_
 - `@miniscruff <https://github.com/miniscruff>`_
+- Kim Gustyr `@khvn26 <https://github.com/khvn26>`_
diff --git a/src/marshmallow/fields.py b/src/marshmallow/fields.py
index ce5eeec5..ddda20d0 100755
--- a/src/marshmallow/fields.py
+++ b/src/marshmallow/fields.py
@@ -443,6 +443,8 @@ class Nested(Field):
         schema = self.schema
         if nested_obj is None:
             return None
+        if self.many and utils.is_iterable_but_not_string(nested_obj):
+            nested_obj = list(nested_obj)
         if not self.__updated_fields:
             schema._update_fields(obj=nested_obj, many=self.many)
             self.__updated_fields = True
diff --git a/src/marshmallow/schema.py b/src/marshmallow/schema.py
index acf728fd..b370035d 100644
--- a/src/marshmallow/schema.py
+++ b/src/marshmallow/schema.py
@@ -816,23 +816,14 @@ class BaseSchema(base.SchemaABC):
 
         :param set field_names: Field names to include in the final
             return dictionary.
+        :param object|Mapping|list obj The object to base filtered fields on.
         :returns: An dict of field_name:field_obj pairs.
         """
         if obj and many:
-            try:  # Homogeneous collection
-                # Prefer getitem over iter to prevent breaking serialization
-                # of objects for which iter will modify position in the collection
-                # e.g. Pymongo cursors
-                if hasattr(obj, '__getitem__') and callable(getattr(obj, '__getitem__')):
-                    try:
-                        obj_prototype = obj[0]
-                    except KeyError:
-                        obj_prototype = next(iter(obj))
-                else:
-                    obj_prototype = next(iter(obj))
-            except (StopIteration, IndexError):  # Nothing to serialize
+            try:  # list
+                obj = obj[0]
+            except IndexError:  # Nothing to serialize
                 return dict((k, v) for k, v in self.declared_fields.items() if k in field_names)
-            obj = obj_prototype
         ret = self.dict_class()
         for key in field_names:
             if key in self.declared_fields:


Test patch:
diff --git a/tests/test_serialization.py b/tests/test_serialization.py
index 8ed9ac1e..f188386a 100644
--- a/tests/test_serialization.py
+++ b/tests/test_serialization.py
@@ -782,3 +782,21 @@ def test_serializing_slice():
 
     serialized = ValueSchema(many=True).dump(slice).data
     assert serialized == values
+
+
+# https://github.com/marshmallow-code/marshmallow/issues/1163
+def test_nested_field_many_serializing_generator():
+    class MySchema(Schema):
+        name = fields.Str()
+
+    class OtherSchema(Schema):
+        objects = fields.Nested(MySchema, many=True)
+
+    def gen():
+        yield {'name': 'foo'}
+        yield {'name': 'bar'}
+
+    obj = {'objects': gen()}
+    data, _ = OtherSchema().dump(obj)
+
+    assert data.get('objects') == [{'name': 'foo'}, {'name': 'bar'}]