#13222: unexpected HttpResponse iteration behavior
---------------------------+------------------------------------------------
 Reporter:  teepark        |       Owner:  nobody    
   Status:  new            |   Milestone:            
Component:  HTTP handling  |     Version:  1.1       
 Keywords:                 |       Stage:  Unreviewed
Has_patch:  0              |  
---------------------------+------------------------------------------------
 For all the builtin iterables, and most from libraries, the `__iter__`
 method returns something representing one and only one iteration.
 `django.http.HttpResponse.__iter__` sets an iterator attribute on itself,
 then returns self (it also defines a `next` method so it is its own
 iterator). This is bad behavior for an iterable and causes problems when
 trying to do anything but basic iteration.

 A use case (and where I encountered this issue) is in a WSGI server that
 pulls off the first item in the iterable app return value, prefixes
 anything that was sent via `write` calls, and then rebuilds the iterable
 with `itertools.chain`:

 {{{
 if prefix:
     body_iterator = iter(body)
     try:
         first_chunk = body_iterator.next()
     except StopIteration:
         first_chunk = ''
     body = itertools.chain((prefix + first_chunk,), body_iterator)
 }}}

 Using `django.core.handlers.wsgi.WSGIHandler` (which just returns the
 HttpResponse, since it's iterable) with this server, the first chunk of
 the HttpResponse gets doubled because `itertools.chain` calls `iter` on
 its arguments, and that resets the HttpResponse's iterator.

 To compare with some builtins and other libraries:

 {{{
 >>> it = iter(["foobar"])
 >>> list(it), list(it)
 (['foobar'], [])
 >>> it = iter("foobar" for i in [1])
 >>> list(it), list(it)
 (['foobar'], [])
 >>> import werkzeug
 >>> it = iter(werkzeug.Response("foobar").response)
 >>> list(it), list(it)
 (['foobar'], [])
 >>> import webob
 >>> it = iter(webob.Response("foobar").app_iter)
 >>> list(it), list(it)
 (['foobar'], [])
 >>> import django.http
 >>> it = iter(django.http.HttpResponse("foobar"))
 >>> list(it), list(it)
 (['foobar'], ['foobar'])
 }}}

-- 
Ticket URL: <http://code.djangoproject.com/ticket/13222>
Django <http://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to django-upda...@googlegroups.com.
To unsubscribe from this group, send email to 
django-updates+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.

Reply via email to