Michael Merickel
2016-08-17 1dd4ded2da5deab9ac361223dfa2bc0e56d5e3e2
Merge pull request #2747 from mmerickel/fix/2744-backport-1.7-branch

Fix #2744 by reverting #2706 on 1.7-branch.
4 files modified
64 ■■■■■ changed files
CHANGES.txt 12 ●●●●● patch | view | raw | blame | history
pyramid/renderers.py 17 ●●●● patch | view | raw | blame | history
pyramid/tests/test_config/test_views.py 4 ●●●● patch | view | raw | blame | history
pyramid/tests/test_renderers.py 31 ●●●● patch | view | raw | blame | history
CHANGES.txt
@@ -1,3 +1,15 @@
unreleased
==========
Bug Fixes
---------
- Revert changes from #2706 released in Pyramid 1.7.1. JSON renderers will
  continue to return unicode data instead of UTF-8 encoded bytes. This means
  that WebOb responses are still expected to handle unicode data even though
  JSON does not have a charset.
  See https://github.com/Pylons/pyramid/issues/2744
.. _changes_1.7.1:
1.7.1 (2016-08-16)
pyramid/renderers.py
@@ -1,7 +1,6 @@
import json
import os
import re
import warnings
from zope.interface import (
    implementer,
@@ -273,7 +272,7 @@
                if ct == response.default_content_type:
                    response.content_type = 'application/json'
            default = self._make_default(request)
            return self.serializer(value, default=default, **self.kw).encode('UTF-8')
            return self.serializer(value, default=default, **self.kw)
        return _render
@@ -380,7 +379,7 @@
                        raise HTTPBadRequest('Invalid JSONP callback function name.')
                    ct = 'application/javascript'
                    body = '/**/{0}({1});'.format(callback, val).encode('UTF-8')
                    body = '/**/{0}({1});'.format(callback, val)
                response = request.response
                if response.content_type == response.default_content_type:
                    response.content_type = ct
@@ -468,17 +467,7 @@
        if result is not None:
            if isinstance(result, text_type):
                if response.charset is None:
                    warnings.warn(
                        "Renderer returned a result of type {0}, "
                        "however the response Content-Type <{1}> does not "
                        "have a charset. Implicitly encoding the result as "
                        "UTF-8.".format(type(result), response.content_type),
                        RuntimeWarning
                    )
                    response.body = result.encode('UTF-8')
                else:
                    response.text = result
                response.text = result
            elif isinstance(result, bytes):
                response.body = result
            elif hasattr(result, '__iter__'):
pyramid/tests/test_config/test_views.py
@@ -2168,7 +2168,7 @@
                                     ctx_iface=implementedBy(HTTPNotFound),
                                     request_iface=IRequest)
        result = view(None, request)
        self._assertBody(result, b'{}')
        self._assertBody(result, '{}')
    def test_add_forbidden_view_with_renderer(self):
        from zope.interface import implementedBy
@@ -2185,7 +2185,7 @@
                                     ctx_iface=implementedBy(HTTPForbidden),
                                     request_iface=IRequest)
        result = view(None, request)
        self._assertBody(result, b'{}')
        self._assertBody(result, '{}')
    def test_set_view_mapper(self):
        from pyramid.interfaces import IViewMapperFactory
pyramid/tests/test_renderers.py
@@ -18,7 +18,7 @@
    def test_it(self):
        renderer = self._makeOne()(None)
        result = renderer({'a':1}, {})
        self.assertEqual(result, b'{"a": 1}')
        self.assertEqual(result, '{"a": 1}')
    def test_with_request_content_type_notset(self):
        request = testing.DummyRequest()
@@ -43,7 +43,7 @@
        renderer = self._makeOne()
        renderer.add_adapter(datetime, adapter)
        result = renderer(None)({'a':now}, {'request':request})
        self.assertEqual(result, '{{"a": "{0}"}}'.format(now.isoformat()).encode('UTF-8'))
        self.assertEqual(result, '{"a": "%s"}' % now.isoformat())
    def test_with_custom_adapter2(self):
        request = testing.DummyRequest()
@@ -54,7 +54,7 @@
        now = datetime.utcnow()
        renderer = self._makeOne(adapters=((datetime, adapter),))
        result = renderer(None)({'a':now}, {'request':request})
        self.assertEqual(result, '{{"a": "{0}"}}'.format(now.isoformat()).encode('UTF-8'))
        self.assertEqual(result, '{"a": "%s"}' % now.isoformat())
    def test_with_custom_serializer(self):
        class Serializer(object):
@@ -66,7 +66,7 @@
        renderer = self._makeOne(serializer=serializer, baz=5)
        obj = {'a':'b'}
        result = renderer(None)(obj, {})
        self.assertEqual(result, b'foo')
        self.assertEqual(result, 'foo')
        self.assertEqual(serializer.obj, obj)
        self.assertEqual(serializer.kw['baz'], 5)
        self.assertTrue('default' in serializer.kw)
@@ -84,7 +84,7 @@
        objects = [MyObject(1), MyObject(2)]
        renderer = self._makeOne()(None)
        result = renderer(objects, {'request':request})
        self.assertEqual(result, b'[{"x": 1}, {"x": 2}]')
        self.assertEqual(result, '[{"x": 1}, {"x": 2}]')
    def test_with_object_adapter_no___json__(self):
        class MyObject(object):
@@ -290,19 +290,6 @@
        response = helper._make_response(la.encode('utf-8'), request)
        self.assertEqual(response.body, la.encode('utf-8'))
    def test__make_response_result_is_str_no_charset(self):
        from pyramid.response import Response
        request = testing.DummyRequest()
        request.response = Response(content_type='application/json', charset=None)
        self.assertIsNone(request.response.charset)
        helper = self._makeOne('loo.foo')
        la = text_('/La Pe\xc3\xb1a', 'utf-8')
        response = helper._make_response(la, request)
        self.assertIsNone(response.charset)
        self.assertEqual(response.body, la.encode('utf-8'))
    def test__make_response_result_is_iterable(self):
        from pyramid.response import Response
        request = testing.DummyRequest()
@@ -505,7 +492,7 @@
        request.response = response
        # use a json renderer, which will mutate the response
        result = self._callFUT('json', dict(a=1), request=request)
        self.assertEqual(result, b'{"a": 1}')
        self.assertEqual(result, '{"a": 1}')
        self.assertEqual(request.response, response)
    def test_no_response_to_preserve(self):
@@ -520,7 +507,7 @@
        request = DummyRequestWithClassResponse()
        # use a json renderer, which will mutate the response
        result = self._callFUT('json', dict(a=1), request=request)
        self.assertEqual(result, b'{"a": 1}')
        self.assertEqual(result, '{"a": 1}')
        self.assertFalse('response' in request.__dict__)
class Test_render_to_response(unittest.TestCase):
@@ -640,7 +627,7 @@
        request = testing.DummyRequest()
        request.GET['callback'] = 'callback'
        result = renderer({'a':'1'}, {'request':request})
        self.assertEqual(result, b'/**/callback({"a": "1"});')
        self.assertEqual(result, '/**/callback({"a": "1"});')
        self.assertEqual(request.response.content_type,
                         'application/javascript')
@@ -650,7 +637,7 @@
        request = testing.DummyRequest()
        request.GET['callback'] = 'angular.callbacks._0'
        result = renderer({'a':'1'}, {'request':request})
        self.assertEqual(result, b'/**/angular.callbacks._0({"a": "1"});')
        self.assertEqual(result, '/**/angular.callbacks._0({"a": "1"});')
        self.assertEqual(request.response.content_type,
                         'application/javascript')