1# -*- coding: utf-8 -*- 2# (c) 2007 Philip Jenvey; written for Paste (http://pythonpaste.org) 3# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php 4import cgi 5from paste.fixture import TestApp 6from paste.wsgiwrappers import WSGIRequest, WSGIResponse 7import six 8 9class AssertApp(object): 10 def __init__(self, assertfunc): 11 self.assertfunc = assertfunc 12 13 def __call__(self, environ, start_response): 14 start_response('200 OK', [('Content-type','text/plain')]) 15 self.assertfunc(environ) 16 return ['Passed'] 17 18no_encoding = object() 19def valid_name(name, encoding=no_encoding, post=False): 20 def assert_valid_name(environ): 21 if encoding is not no_encoding: 22 WSGIRequest.defaults._push_object(dict(content_type='text/html', 23 charset=encoding)) 24 try: 25 request = WSGIRequest(environ) 26 if post: 27 params = request.POST 28 else: 29 params = request.GET 30 assert params['name'] == name 31 assert request.params['name'] == name 32 finally: 33 if encoding is not no_encoding: 34 WSGIRequest.defaults._pop_object() 35 return assert_valid_name 36 37def test_wsgirequest_charset(): 38 # Jose, 'José' 39 app = TestApp(AssertApp(assertfunc=valid_name(u'José', encoding='UTF-8'))) 40 res = app.get('/?name=Jos%C3%A9') 41 42 # Tanaka, '田中' 43 app = TestApp(AssertApp(assertfunc=valid_name(u'田中', encoding='UTF-8'))) 44 res = app.get('/?name=%E7%94%B0%E4%B8%AD') 45 46 # Nippon (Japan), '日本' 47 app = TestApp(AssertApp(assertfunc=valid_name(u'日本', encoding='UTF-8', 48 post=True))) 49 res = app.post('/', params=dict(name='日本')) 50 51 # WSGIRequest will determine the charset from the Content-Type header when 52 # unicode is expected. 53 # No encoding specified: not expecting unicode 54 app = TestApp(AssertApp(assertfunc=valid_name('日本', post=True))) 55 content_type = 'application/x-www-form-urlencoded; charset=%s' 56 res = app.post('/', params=dict(name='日本'), 57 headers={'content-type': content_type % 'UTF-8'}) 58 59 # Encoding specified: expect unicode. Shiftjis is the default encoding, but 60 # params become UTF-8 because the browser specified so 61 app = TestApp(AssertApp(assertfunc=valid_name(u'日本', post=True, 62 encoding='shiftjis'))) 63 res = app.post('/', params=dict(name='日本'), 64 headers={'content-type': content_type % 'UTF-8'}) 65 66 # Browser did not specify: parse params as the fallback shiftjis 67 app = TestApp(AssertApp(assertfunc=valid_name(u'日本', post=True, 68 encoding='shiftjis'))) 69 res = app.post('/', params=dict(name=u'日本'.encode('shiftjis'))) 70 71def test_wsgirequest_charset_fileupload(): 72 def handle_fileupload(environ, start_response): 73 start_response('200 OK', [('Content-type','text/plain')]) 74 request = WSGIRequest(environ) 75 76 assert len(request.POST) == 1 77 assert isinstance(request.POST.keys()[0], str) 78 fs = request.POST['thefile'] 79 assert isinstance(fs, cgi.FieldStorage) 80 assert isinstance(fs.filename, str) 81 assert fs.filename == '寿司.txt' 82 assert fs.value == b'Sushi' 83 84 request.charset = 'UTF-8' 85 assert len(request.POST) == 1 86 assert isinstance(request.POST.keys()[0], str) 87 fs = request.POST['thefile'] 88 assert isinstance(fs, cgi.FieldStorage) 89 assert isinstance(fs.filename, six.text_type) 90 assert fs.filename == u'寿司.txt' 91 assert fs.value == b'Sushi' 92 93 request.charset = None 94 assert fs.value == b'Sushi' 95 return [] 96 97 app = TestApp(handle_fileupload) 98 res = app.post('/', upload_files=[('thefile', '寿司.txt', b'Sushi')]) 99 100def test_wsgiresponse_charset(): 101 response = WSGIResponse(mimetype='text/html; charset=UTF-8') 102 assert response.content_type == 'text/html' 103 assert response.charset == 'UTF-8' 104 response.write(u'test') 105 response.write(u'test2') 106 response.write('test3') 107 status, headers, content = response.wsgi_response() 108 for data in content: 109 assert isinstance(data, six.binary_type) 110 111 WSGIResponse.defaults._push_object(dict(content_type='text/html', 112 charset='iso-8859-1')) 113 try: 114 response = WSGIResponse() 115 response.write(u'test') 116 response.write(u'test2') 117 response.write('test3') 118 status, headers, content = response.wsgi_response() 119 for data in content: 120 assert isinstance(data, six.binary_type) 121 finally: 122 WSGIResponse.defaults._pop_object() 123 124 # WSGIResponse will allow unicode to pass through when no charset is 125 # set 126 WSGIResponse.defaults._push_object(dict(content_type='text/html', 127 charset=None)) 128 try: 129 response = WSGIResponse(u'test') 130 response.write(u'test1') 131 status, headers, content = response.wsgi_response() 132 for data in content: 133 assert isinstance(data, six.text_type) 134 finally: 135 WSGIResponse.defaults._pop_object() 136 137 WSGIResponse.defaults._push_object(dict(content_type='text/html', 138 charset='')) 139 try: 140 response = WSGIResponse(u'test') 141 response.write(u'test1') 142 status, headers, content = response.wsgi_response() 143 for data in content: 144 assert isinstance(data, six.text_type) 145 finally: 146 WSGIResponse.defaults._pop_object() 147