#25576: HttpResponse can't be wrapped by io.TextIOWrapper; add required IOBase
methods
-------------------------------+--------------------
     Reporter:  jdufresne      |      Owner:  nobody
         Type:  Bug            |     Status:  new
    Component:  HTTP handling  |    Version:  master
     Severity:  Normal         |   Keywords:
 Triage Stage:  Unreviewed     |  Has patch:  0
Easy pickings:  0              |      UI/UX:  0
-------------------------------+--------------------
 In Python3, the stdlib CSV writer [1] is expected to write to a text file,
 not a binary file. Observe writing to a bytes buffer:

 {{{
 import io
 import csv

 b = io.BytesIO()
 w = csv.writer(b)
 w.writerow(['a', 'b', 'c'])
 }}}

 {{{
 Traceback (most recent call last):
   File "test.py", line 8, in <module>
     w.writerow(['a', 'b', 'c'])
 TypeError: 'str' does not support the buffer interface
 }}}

 To handle this, one should use the stdlib's {{{io.TextIOWrapper}}} [2]:

 {{{
 import io
 import csv

 b = io.BytesIO()
 wrapper = io.TextIOWrapper(b, 'utf-8', newline='')
 w = csv.writer(wrapper)
 w.writerow(['a', 'b', 'c'])
 wrapper.flush()
 print(b.getvalue())
 }}}

 {{{
 b'a,b,c\r\n'
 }}}

 As Django's HttpResponse uses a binary file-like interface, I'd expect the
 same to work. That is, wrap the response in a {{{io.TextIOWrapper}}} and
 write the CSV document to the wrapper. However, this fails:

 {{{
 import io
 import csv
 from django.http.response import HttpResponse

 r = HttpResponse()
 wrapper = io.TextIOWrapper(r, 'utf-8', newline='')
 w = csv.writer(wrapper)
 w.writerow(['a', 'b', 'c'])
 wrapper.flush()
 print(r)
 }}}

 {{{
 Traceback (most recent call last):
   File "/home/jon/test.py", line 8, in <module>
     wrapper = io.TextIOWrapper(r, 'utf-8')
 AttributeError: 'HttpResponse' object has no attribute 'readable'
 }}}

 As HttpResponse is a binary file-like interface, I'm suggesting the
 necessary methods/members be added so that it can be wrapped by
 {{{io.TextIOWrapper}}}. These methods/members are documented in
 io.BaseIO() [3]. From initial testing, only {{{readable()}}} and
 {{{seekable()}}} are required for my use case.

 This will make it easier to integrate text-only file interfaces to the
 binary nature of the response.

 [1] https://docs.python.org/3/library/csv.html#csv.writer
 [2] https://docs.python.org/3/library/io.html#io.TextIOWrapper
 [3] https://docs.python.org/3/library/io.html#io.IOBase

--
Ticket URL: <https://code.djangoproject.com/ticket/25576>
Django <https://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 unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/052.0d18180ecdb3300ca286c4b4b06924ee%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to