Skip to content

Commit

Permalink
Merge branch 'unicode-user-data' into develop
Browse files Browse the repository at this point in the history
* unicode-user-data:
  Fix issue #765 with non ascii characters in user-data
  • Loading branch information
jamesls committed May 14, 2014
2 parents 9de9d09 + 1a27e2c commit af9fb38
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 3 deletions.
2 changes: 1 addition & 1 deletion awscli/argprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,4 +448,4 @@ def unpack_scalar_cli_arg(parameter, value):
return False
return bool(value)
else:
return six.text_type(value)
return value
26 changes: 26 additions & 0 deletions awscli/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,31 @@
import six

if six.PY3:
import locale

def get_stdout_text_writer():
return sys.stdout

def compat_open(filename, mode='r', encoding=None):
"""Back-port open() that accepts an encoding argument.
In python3 this uses the built in open() and in python2 this
uses the io.open() function.
If the file is not being opened in binary mode, then we'll
use locale.getpreferredencoding() to find the preferred
encoding.
"""
if 'b' not in mode:
encoding = locale.getpreferredencoding()
return open(filename, mode, encoding=encoding)

else:
import codecs
import locale
import io

def get_stdout_text_writer():
# In python3, all the sys.stdout/sys.stderr streams are in text
# mode. This means they expect unicode, and will encode the
Expand All @@ -31,3 +51,9 @@ def get_stdout_text_writer():
# just returns sys.stdout in the PY3 section above because python3
# handles this.
return codecs.getwriter(locale.getpreferredencoding())(sys.stdout)

def compat_open(filename, mode='r', encoding=None):
# See docstring for compat_open in the PY3 section above.
if 'b' not in mode:
encoding = locale.getpreferredencoding()
return io.open(filename, mode, encoding=encoding)
4 changes: 3 additions & 1 deletion awscli/paramfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
from botocore.vendored import requests
import six

from awscli.compat import compat_open


logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -50,7 +52,7 @@ def get_file(prefix, path):
if not os.path.isfile(file_path):
raise ResourceLoadingError("file does not exist: %s" % file_path)
try:
with open(file_path) as f:
with compat_open(file_path, 'r') as f:
return f.read()
except (OSError, IOError) as e:
raise ResourceLoadingError('Unable to load paramfile %s: %s' % (
Expand Down
2 changes: 1 addition & 1 deletion tests/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,12 @@
import mock
from botocore.hooks import HierarchicalEmitter
from botocore.session import Session
import botocore.loaders

import awscli.clidriver
from awscli.plugin import load_plugins
from awscli.clidriver import CLIDriver
from awscli import EnvironmentVariables
import botocore.loaders


# The unittest module got a significant overhaul
Expand Down
19 changes: 19 additions & 0 deletions tests/unit/ec2/test_run_instances.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
# 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 awscli.compat import compat_open

from tests import temporary_file
from tests.unit import BaseAWSCommandParamsTest


Expand Down Expand Up @@ -38,6 +41,22 @@ def test_count_scalar(self):
}
self.assert_params_for_cmd(args_list, result)

def test_user_data(self):
data = u'\u0039'
with temporary_file('r+') as tmp:
with compat_open(tmp.name, 'w') as f:
f.write(data)
f.flush()
args = (
self.prefix +
' --image-id foo --user-data file://%s' % f.name)
result = {'ImageId': 'foo',
'MaxCount': '1',
'MinCount': '1',
# base64 encoded content of utf-8 encoding of data.
'UserData': 'OQ=='}
self.assert_params_for_cmd(args, result)

def test_count_range(self):
args = ' --image-id ami-foobar --count 5:10'
args_list = (self.prefix + args).split()
Expand Down

0 comments on commit af9fb38

Please sign in to comment.