diff --git a/awscli/formatter.py b/awscli/formatter.py index 385927bdae40..6021bbc88155 100644 --- a/awscli/formatter.py +++ b/awscli/formatter.py @@ -12,7 +12,7 @@ # language governing permissions and limitations under the License. import logging import sys -import json +from botocore.compat import json from botocore.utils import set_value_from_jmespath @@ -42,14 +42,7 @@ def _remove_request_id(self, response_data): del response_data['ResponseMetadata'] def _get_default_stream(self): - if getattr(sys.stdout, 'encoding', None) is None: - # In python3, sys.stdout.encoding is always set. - # In python2, if you redirect to stdout, then - # encoding is not None. In this case we'll default - # to utf-8. - return compat.get_stdout_text_writer() - else: - return sys.stdout + return compat.get_stdout_text_writer() class FullyBufferedFormatter(Formatter): @@ -84,7 +77,8 @@ def _format_response(self, operation, response, stream): # that out to the user but other "falsey" values like an empty # dictionary should be printed. if response: - json.dump(response, stream, indent=4, default=json_encoder) + json.dump(response, stream, indent=4, default=json_encoder, + ensure_ascii=False) stream.write('\n') diff --git a/tests/unit/customizations/emr/test_create_default_role.py b/tests/unit/customizations/emr/test_create_default_role.py index 0b210be14e60..0871f1bd1149 100644 --- a/tests/unit/customizations/emr/test_create_default_role.py +++ b/tests/unit/customizations/emr/test_create_default_role.py @@ -13,7 +13,7 @@ import mock import awscli.customizations.emr.emrutils as emrutils -import json +from botocore.compat import json from botocore.vendored import requests from tests.unit.customizations.emr import EMRBaseAWSCommandParamsTest as \ BaseAWSCommandParamsTest diff --git a/tests/unit/output/test_json_output.py b/tests/unit/output/test_json_output.py index e2171e953ccb..5ce76ea4bdf4 100644 --- a/tests/unit/output/test_json_output.py +++ b/tests/unit/output/test_json_output.py @@ -11,8 +11,12 @@ # distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF # ANY KIND, either express or implied. See the License for the specific # language governing permissions and limitations under the License. +from botocore.compat import json +import mock +import six + from awscli.testutils import BaseAWSCommandParamsTest -import json +from awscli.compat import get_stdout_text_writer class TestGetPasswordData(BaseAWSCommandParamsTest): @@ -49,7 +53,7 @@ def setUp(self): "UserName": "testuser-51", "Path": "/", "CreateDate": "2012-10-14T23:53:39Z", - "UserId": "EXAMPLEUSERID", + "UserId": u"EXAMPLEUSERID\u2713", "Arn": "arn:aws:iam::123456:user/testuser2" }, ] @@ -76,3 +80,14 @@ def test_unknown_output_type_from_env_var(self): # output format from the env var still gives an error. self.environ['AWS_DEFAULT_OUTPUT'] = 'bad-output-type' self.run_cmd('iam list-users', expected_rc=255) + + def test_json_prints_unicode_chars(self): + output = self.run_cmd('iam list-users', expected_rc=0)[0] + with mock.patch('sys.stdout', six.StringIO()) as f: + out = get_stdout_text_writer() + out.write(u'\u2713') + expected = f.getvalue() + # We should not see the '\u' for of the unicode character. + # It should be encoded into the default encoding. + self.assertNotIn('\\u2713', output) + self.assertIn(expected, output)