app: Fixed an issue with unicode responses in Python 2.7
If a controller callable returns a string, it needs to be wrapped in a Response object. To determine if this is the case, the Application tests to see if the returned object is an instance of `basestring`. Since `basestring` doesn't exist in Python 3, only `str` is a valid return type. Unfortunately, my way of testing whether the `basestring` type existed was flawed. Instead of raising `NameError` when it doesn't exist, `UnboundLocalError` (a subclass `NameError`) is *always* raised. Since the exception handler sets `basestring` equal to `str` assuming this is Python 3, most of the time this isn't a problem. If, however, the controller returns a `unicode` object in Python 2, the `isinstance` call returns `False`, so the response is not wrapped in a Response object. Rather than try to reassign the `basestring` name, now we just use `_string`, which will either be `basestring` (in Python 2) or `str` (in Python 3). Apparently, the unit tests didn't cover this case...master
parent
a2d8f6f098
commit
cf94a4d600
|
@ -103,12 +103,11 @@ class Application(object):
|
|||
# but we need to wrap it in a Response object
|
||||
try:
|
||||
# In Python 2, it could be a str or a unicode object
|
||||
basestring = basestring #@UndefinedVariable
|
||||
_string = basestring
|
||||
except NameError:
|
||||
# Python 3 has no unicode objects and thus no need for
|
||||
# basestring so we, just make it an alias for str
|
||||
basestring = str
|
||||
if isinstance(response, basestring) or not response:
|
||||
# In Python 3, we are only interested in str objects
|
||||
_string = str
|
||||
if isinstance(response, _string) or not response:
|
||||
response = request.ResponseClass(response)
|
||||
|
||||
if not start_response_wrapper.called:
|
||||
|
|
|
@ -3,13 +3,31 @@
|
|||
:Created: Nov 27, 2012
|
||||
:Author: dustin
|
||||
'''
|
||||
from unittest.case import SkipTest
|
||||
import functools
|
||||
import milla.app
|
||||
import milla.dispatch
|
||||
import nose.tools
|
||||
import sys
|
||||
import wsgiref.util
|
||||
import webob.exc
|
||||
|
||||
def python2_only(test):
|
||||
@functools.wraps(test)
|
||||
def wrapper():
|
||||
if sys.version_info[0] != 2:
|
||||
raise SkipTest
|
||||
return test()
|
||||
return wrapper
|
||||
|
||||
def python3_only(test):
|
||||
@functools.wraps(test)
|
||||
def wrapper():
|
||||
if sys.version_info[0] != 3:
|
||||
raise SkipTest
|
||||
return test()
|
||||
return wrapper
|
||||
|
||||
class StubResolver(object):
|
||||
'''Stub resolver for testing purposes'''
|
||||
|
||||
|
@ -145,6 +163,64 @@ def test_emulated_method():
|
|||
response.finish_response(app_iter)
|
||||
assert response.headers.startswith('HTTP/1.1 200'), response.headers
|
||||
|
||||
def test_return_none():
|
||||
'''Controllers can return None
|
||||
'''
|
||||
|
||||
def controller(request):
|
||||
return None
|
||||
|
||||
app = milla.app.Application(StubResolver(controller))
|
||||
environ = environ_for_testing()
|
||||
response = ResponseMaker()
|
||||
app_iter = app(environ, response.start_response)
|
||||
response.finish_response(app_iter)
|
||||
assert not response.body, response.body
|
||||
|
||||
def test_return_str():
|
||||
'''Controllers can return str objects
|
||||
'''
|
||||
|
||||
def controller(request):
|
||||
return 'Hello, world'
|
||||
|
||||
app = milla.app.Application(StubResolver(controller))
|
||||
environ = environ_for_testing()
|
||||
response = ResponseMaker()
|
||||
app_iter = app(environ, response.start_response)
|
||||
response.finish_response(app_iter)
|
||||
assert response.body == b'Hello, world', response.body
|
||||
|
||||
@python2_only
|
||||
def test_return_unicode():
|
||||
'''Controllers can return unicode objects
|
||||
'''
|
||||
|
||||
def controller(request):
|
||||
return unicode('Hello, world')
|
||||
|
||||
app = milla.app.Application(StubResolver(controller))
|
||||
environ = environ_for_testing()
|
||||
response = ResponseMaker()
|
||||
app_iter = app(environ, response.start_response)
|
||||
response.finish_response(app_iter)
|
||||
assert response.body == unicode('Hello, world'), response.body
|
||||
|
||||
@nose.tools.raises(AttributeError)
|
||||
@python3_only
|
||||
def test_return_bytes():
|
||||
'''Controllers cannot return bytes objects
|
||||
'''
|
||||
|
||||
def controller(request):
|
||||
return b'Hello, world'
|
||||
|
||||
app = milla.app.Application(StubResolver(controller))
|
||||
environ = environ_for_testing()
|
||||
response = ResponseMaker()
|
||||
app_iter = app(environ, response.start_response)
|
||||
response.finish_response(app_iter)
|
||||
|
||||
@nose.tools.raises(BeforeCalled)
|
||||
def test_function_before():
|
||||
'''__before__ attribute is called for controller functions
|
||||
|
@ -484,4 +560,3 @@ def test_static_resource_undefined():
|
|||
app_iter = app(environ, response.start_response)
|
||||
response.finish_response(app_iter)
|
||||
assert response.body == b'/image.png', response.body
|
||||
|
Loading…
Reference in New Issue