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