# -*- coding: utf-8 -*- # (c) 2007 Philip Jenvey; written for Paste (http://pythonpaste.org) # Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php import cgi from paste.fixture import TestApp from paste.wsgiwrappers import WSGIRequest, WSGIResponse import six class AssertApp(object): def __init__(self, assertfunc): self.assertfunc = assertfunc def __call__(self, environ, start_response): start_response('200 OK', [('Content-type','text/plain')]) self.assertfunc(environ) return [b'Passed'] no_encoding = object() def valid_name(name, encoding=no_encoding, post=False): def assert_valid_name(environ): if encoding is not no_encoding: WSGIRequest.defaults._push_object(dict(content_type='text/html', charset=encoding)) try: request = WSGIRequest(environ) if post: params = request.POST else: params = request.GET assert params['name'] == name assert request.params['name'] == name finally: if encoding is not no_encoding: WSGIRequest.defaults._pop_object() return assert_valid_name def test_wsgirequest_charset(): # Jose, 'José' app = TestApp(AssertApp(assertfunc=valid_name(u'José', encoding='UTF-8'))) res = app.get('/?name=Jos%C3%A9') # Tanaka, '田中' app = TestApp(AssertApp(assertfunc=valid_name(u'田中', encoding='UTF-8'))) res = app.get('/?name=%E7%94%B0%E4%B8%AD') # Nippon (Japan), '日本' app = TestApp(AssertApp(assertfunc=valid_name(u'日本', encoding='UTF-8', post=True))) res = app.post('/', params=dict(name='日本')) # WSGIRequest will determine the charset from the Content-Type header when # unicode is expected. # No encoding specified: not expecting unicode app = TestApp(AssertApp(assertfunc=valid_name('日本', post=True))) content_type = 'application/x-www-form-urlencoded; charset=%s' res = app.post('/', params=dict(name='日本'), headers={'content-type': content_type % 'UTF-8'}) # Encoding specified: expect unicode. Shiftjis is the default encoding, but # params become UTF-8 because the browser specified so app = TestApp(AssertApp(assertfunc=valid_name(u'日本', post=True, encoding='shiftjis'))) res = app.post('/', params=dict(name='日本'), headers={'content-type': content_type % 'UTF-8'}) # Browser did not specify: parse params as the fallback shiftjis app = TestApp(AssertApp(assertfunc=valid_name(u'日本', post=True, encoding='shiftjis'))) res = app.post('/', params=dict(name=u'日本'.encode('shiftjis'))) def test_wsgirequest_charset_fileupload(): def handle_fileupload(environ, start_response): start_response('200 OK', [('Content-type','text/plain')]) request = WSGIRequest(environ) assert len(request.POST) == 1 assert isinstance(request.POST.keys()[0], str) fs = request.POST['thefile'] assert isinstance(fs, cgi.FieldStorage) assert isinstance(fs.filename, str) assert fs.filename == '寿司.txt' assert fs.value == b'Sushi' request.charset = 'UTF-8' assert len(request.POST) == 1 assert isinstance(request.POST.keys()[0], str) fs = request.POST['thefile'] assert isinstance(fs, cgi.FieldStorage) assert isinstance(fs.filename, six.text_type) assert fs.filename == u'寿司.txt' assert fs.value == b'Sushi' request.charset = None assert fs.value == b'Sushi' return [] app = TestApp(handle_fileupload) res = app.post('/', upload_files=[('thefile', '寿司.txt', b'Sushi')]) def test_wsgiresponse_charset(): response = WSGIResponse(mimetype='text/html; charset=UTF-8') assert response.content_type == 'text/html' assert response.charset == 'UTF-8' response.write(u'test') response.write(u'test2') response.write('test3') status, headers, content = response.wsgi_response() for data in content: assert isinstance(data, six.binary_type) WSGIResponse.defaults._push_object(dict(content_type='text/html', charset='iso-8859-1')) try: response = WSGIResponse() response.write(u'test') response.write(u'test2') response.write('test3') status, headers, content = response.wsgi_response() for data in content: assert isinstance(data, six.binary_type) finally: WSGIResponse.defaults._pop_object() # WSGIResponse will allow unicode to pass through when no charset is # set WSGIResponse.defaults._push_object(dict(content_type='text/html', charset=None)) try: response = WSGIResponse(u'test') response.write(u'test1') status, headers, content = response.wsgi_response() for data in content: assert isinstance(data, six.text_type) finally: WSGIResponse.defaults._pop_object() WSGIResponse.defaults._push_object(dict(content_type='text/html', charset='')) try: response = WSGIResponse(u'test') response.write(u'test1') status, headers, content = response.wsgi_response() for data in content: assert isinstance(data, six.text_type) finally: WSGIResponse.defaults._pop_object()