Question

Here's the code. When I send both fields it fails.

import unittest

class UnicodeTestCase(unittest.TestCase):
    def test_unicode(self):
        from cStringIO import StringIO
        from flask import Flask, request

        app = Flask(__name__)
        app.config['TESTING'] = True

        @app.route('/', methods=["POST"])
        def test_view():
            print request.values, request.files
            return "OK"

        file = (StringIO("0" * 1000), "filename.txt")
        string = u"∆_∆"

        client = app.test_client(use_cookies=False)
        self.assertEquals(200, client.post('/', data={'file': file}).status_code)
        self.assertEquals(200, client.post('/', data={'string': string}).status_code)
        self.assertEquals(200, client.post('/', data={'file': file, 'string': string}).status_code)

On the last assert it fails with:

Error
Traceback (most recent call last):
  File "/Users/user1/tests/test_uni.py", line 108, in test_unicode
    self.assertEquals(200, client.post('/', data={'file': file, 'string': string}).status_code)
  File "/Users/user1/.virtualenvs/test/lib/python2.7/site-packages/werkzeug/test.py", line 771, in post
    return self.open(*args, **kw)
  File "/Users/user1/.virtualenvs/test/lib/python2.7/site-packages/flask/testing.py", line 108, in open
    follow_redirects=follow_redirects)
  File "/Users/user1/.virtualenvs/test/lib/python2.7/site-packages/werkzeug/test.py", line 725, in open
    environ = args[0].get_environ()
  File "/Users/user1/.virtualenvs/test/lib/python2.7/site-packages/werkzeug/test.py", line 535, in get_environ
    stream_encode_multipart(values, charset=self.charset)
  File "/Users/user1/.virtualenvs/test/lib/python2.7/site-packages/werkzeug/test.py", line 104, in stream_encode_multipart
    write('\r\n\r\n' + value)
  File "/Users/user1/.virtualenvs/test/lib/python2.7/site-packages/werkzeug/test.py", line 71, in write
    write_binary(string.encode(charset))
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 4: ordinal not in range(128)

It works fine when I'm sending both fields with the Postman (a Google Chrome extension).

Is it OK and should I wrap fields with unicode with base64 or something else? Or is it a bug in the werkzeug test client?

Was it helpful?

Solution

Look like test client bug, I already have another bug with test client when direct request work fine, but test client has unexpected result.

For me in https://github.com/mitsuhiko/werkzeug/blob/master/werkzeug/test.py#L71 I have string type as str. For string only this method not called, for file only this method do not called with your string. You can try temporary update this method with next for python 2 only:

def write(string):
    if isinstance(string, str):
        write_binary(string)
    else:
        write_binary(string.encode(charset))

I created bug for your example: https://github.com/mitsuhiko/flask/issues/973.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top