Skip to content

Commit

Permalink
Don't print unicode escape sequences for non-ascii chars
Browse files Browse the repository at this point in the history
Also, we need to use the get_stdout_text_writer because of a
bug in py2.6 in which the `.encoding` attribute is not honored
for `sys.stdout` (http://bugs.python.org/issue4947).

Fixes #1048.
  • Loading branch information
jamesls committed Dec 9, 2014
1 parent 12a8305 commit e5ddf48
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 13 deletions.
14 changes: 4 additions & 10 deletions awscli/formatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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')


Expand Down
2 changes: 1 addition & 1 deletion tests/unit/customizations/emr/test_create_default_role.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
19 changes: 17 additions & 2 deletions tests/unit/output/test_json_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down Expand Up @@ -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"
},
]
Expand All @@ -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<hex>' for of the unicode character.
# It should be encoded into the default encoding.
self.assertNotIn('\\u2713', output)
self.assertIn(expected, output)

0 comments on commit e5ddf48

Please sign in to comment.