fix: Achieve 100% code coverage across all environments

Python 3 was just shy of 100%. Getting it up there required some slight
modifications to the way messages are logged to wsgi.errors, but this
should not break any apps.
This commit is contained in:
kgriffs
2013-04-27 10:15:01 -04:00
parent dc423d9980
commit 479ca94214
6 changed files with 38 additions and 40 deletions

View File

@@ -19,8 +19,9 @@ limitations under the License.
import re
from functools import wraps
from falcon import responders, HTTP_METHODS
import six
from falcon import responders, HTTP_METHODS
import falcon.status_codes as status
@@ -100,7 +101,8 @@ def get_body(resp):
resp: Instance of falcon.Response
Returns:
* If resp.body is not None, returns [resp.body], encoded as UTF-8.
* If resp.body is not None, returns [resp.body], encoded as UTF-8 if
it is a Unicode string. Bytestrings are returned as-is.
* If resp.data is not None, returns [resp.data]
* If resp.stream is not None, returns resp.stream
* Otherwise, returns []
@@ -110,9 +112,9 @@ def get_body(resp):
body = resp.body
if body is not None:
try:
if isinstance(body, six.text_type):
return [body.encode('utf-8')]
except UnicodeDecodeError:
else:
return [body]
elif resp.data is not None:

View File

@@ -21,7 +21,7 @@ import sys
if sys.version_info < (2, 7): # pragma: no cover
from ordereddict import OrderedDict
else:
else: # pragma: no cover
from collections import OrderedDict

View File

@@ -24,8 +24,8 @@ from falcon.exceptions import HTTPBadRequest
from falcon import util
from falcon import request_helpers as helpers
DEFAULT_ERROR_LOG_FORMAT = ('{0:%Y-%m-%d %H:%M:%S} [FALCON] [ERROR]'
' {1} {2}?{3} => {4}\n')
DEFAULT_ERROR_LOG_FORMAT = (u'{0:%Y-%m-%d %H:%M:%S} [FALCON] [ERROR]'
u' {1} {2}?{3} => ')
class InvalidHeaderValueError(HTTPBadRequest):
@@ -106,29 +106,32 @@ class Request(object):
self._headers = helpers.parse_headers(env)
def log_error(self, message):
def log_error(self, message): # pragma: no cover
"""Log an error to wsgi.error
Prepends timestamp and request info to message, and writes the
result out to the WSGI server's error stream (wsgi.error).
Args:
message: A string describing the problem. If a byte-string and
running under Python 2, the string is assumed to be encoded
as UTF-8.
message: A string describing the problem. If a byte-string it is
simply written out as-is. Unicode strings will be converted
to UTF-8.
"""
if not six.PY3 and isinstance(message, unicode):
message = message.encode('utf-8')
log_line = (
DEFAULT_ERROR_LOG_FORMAT.
format(datetime.now(), self.method, self.path,
self.query_string, message)
format(datetime.now(), self.method, self.path, self.query_string)
)
self._wsgierrors.write(log_line)
if six.PY3:
self._wsgierrors.write(log_line + message + '\n')
else:
if isinstance(message, unicode):
message = message.encode('utf-8')
self._wsgierrors.write(log_line.encode('utf-8'))
self._wsgierrors.write(message + '\n')
@property
def client_accepts_json(self):

View File

@@ -101,17 +101,14 @@ class TestHelloWorld(testing.TestBase):
self.assertEquals(resp.body, self.resource.sample_unicode)
self.assertEquals(body, [self.resource.sample_utf8])
if not six.PY3:
# On Python 3, strings are always Unicode,
# so only perform this test under Python 2.
def test_body_bytes(self):
body = self.simulate_request('/bytes')
resp = self.bytes_resource.resp
def test_body_bytes(self):
body = self.simulate_request('/bytes')
resp = self.bytes_resource.resp
self.assertEquals(self.srmock.status, self.resource.sample_status)
self.assertEquals(resp.status, self.resource.sample_status)
self.assertEquals(resp.body, self.resource.sample_utf8)
self.assertEquals(body, [self.resource.sample_utf8])
self.assertEquals(self.srmock.status, self.resource.sample_status)
self.assertEquals(resp.status, self.resource.sample_status)
self.assertEquals(resp.body, self.resource.sample_utf8)
self.assertEquals(body, [self.resource.sample_utf8])
def test_data(self):
body = self.simulate_request('/data')

View File

@@ -5,11 +5,6 @@ import six
unicode_message = u'Unicode: \x80'
if six.PY3:
str_message = 'Unicode all the way: \x80'
else:
str_message = 'UTF-8: \xc2\x80'
class LoggerResource:
@@ -17,7 +12,7 @@ class LoggerResource:
req.log_error(unicode_message)
def on_head(self, req, resp):
req.log_error(str_message)
req.log_error(unicode_message.encode('utf-8'))
class TestWSGIError(testing.TestBase):
@@ -38,19 +33,19 @@ class TestWSGIError(testing.TestBase):
# with undefined encoding, so do the encoding manually.
self.wsgierrors = self.wsgierrors_buffer
def test_responder_logged_unicode(self):
def test_responder_logged_bytestring(self):
self.simulate_request('/logger', wsgierrors=self.wsgierrors)
log = self.wsgierrors_buffer.getvalue()
self.assertIn(unicode_message.encode('utf-8'), log)
def test_responder_logged_str(self):
def test_responder_logged_unicode(self):
if six.PY3:
self.skipTest('Test only applies to Python 2')
self.simulate_request('/logger', wsgierrors=self.wsgierrors,
method='HEAD')
log = self.wsgierrors_buffer.getvalue()
if six.PY3:
self.assertIn(str_message.encode('utf-8'), log)
else:
self.assertIn(str_message, log)
self.assertIn(unicode_message, log.decode('utf-8'))

View File

@@ -7,6 +7,7 @@ with-coverage=true
cover-min-percentage=100
cover-package=falcon
cover-html=true
cover-html-dir=htmlcov
cover-erase=true
cover-inclusive=true
cover-branches=true