Allan Crooks  committed bb85cb9

Use is_iterator function to determine if the response content is iterable, rather than just testing if it is a generator.

This is in preparation for a fix for #1288. Note - we could test against
collections.Iterator, but this seems like a cleaner way of doing it for now.

  • Participants
  • Parent commits 4537fd4
  • Branches cp4

Comments (0)

Files changed (3)

File cherrypy/lib/

 # Deprecated in CherryPy 3.2 -- remove in CherryPy 3.3
 from cherrypy.lib.reprconf import unrepr, modules, attributes
+def is_iterator(obj):
+    '''Returns a boolean indicating if the object provided implements
+     the iterator protocol (i.e. like a generator). This will return
+     false for objects which iterable, but not iterators themselves.'''
+    from types import GeneratorType
+    if isinstance(obj, GeneratorType):
+        return True
+    elif not hasattr(obj, '__iter__'):
+        return False
+    else:
+        # Types which implement the protocol must return themselves when
+        # invoking 'iter' upon them.
+        return iter(obj) is obj
 class file_generator(object):
     """Yield the given input (a file object) in chunks (default 64k). (Core)"""

File cherrypy/lib/tools/

 import cherrypy
+from cherrypy.lib import is_iterator
 def flatten(debug=False):
     This allows cherrypy.response.body to consist of 'nested generators';
     that is, a set of generators that yield generators.
-    import types
     def flattener(input):
         numchunks = 0
         for x in input:
-            if not isinstance(x, types.GeneratorType):
+            if not is_iterator(x):
                 numchunks += 1
                 yield x

File cherrypy/lib/tools/sessions/

 import datetime
 import os
 import time
-import types
 from magicbus.plugins.tasks import Monitor
 import cherrypy
 from import Tool
-from cherrypy.lib import httputil
+from cherrypy.lib import httputil, is_iterator
 missing = object()
         # If the body is not being streamed, we save the data now
         # (so we can release the lock).
-        if isinstance(response.body, types.GeneratorType):
+        if is_iterator(response.body):
 save.failsafe = True