diff --git a/awscli/clidriver.py b/awscli/clidriver.py index 0b9eaaeb404f..ca3dcaaf8771 100644 --- a/awscli/clidriver.py +++ b/awscli/clidriver.py @@ -43,17 +43,6 @@ LOG_FORMAT = ( '%(asctime)s - %(threadName)s - %(name)s - %(levelname)s - %(message)s') -# NOTE: this is temporary. -# Botocore now parsers timestamps to datetime.datetime objects. -# The AWS CLI has historically not parsed timestamp objects and treated -# them as strings. -# We will eventually want to allow for users to specify how to parse -# the timestamp formats, but for now, we set the default timestamp parser -# to be a noop. -# The eventual plan is to add a client option for providing a timestamp parser, -# and once the CLI has switched over to client objects we can remove this -# and set the timestamp parsing on a per client basis. -parsers.DEFAULT_TIMESTAMP_PARSER = lambda x: x def main(): diff --git a/awscli/customizations/scalarparse.py b/awscli/customizations/scalarparse.py new file mode 100644 index 000000000000..782b14aab1ce --- /dev/null +++ b/awscli/customizations/scalarparse.py @@ -0,0 +1,48 @@ +# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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. +"""Change the scalar response parsing behavior for the AWS CLI. + +The underlying library used by botocore has some response parsing +behavior that we'd like to modify in the AWS CLI. There are two: + + * Parsing binary content. + * Parsing timestamps (dates) + +For the first option we can't print binary content to the terminal, +so this customization leaves the binary content base64 encoded. If the +user wants the binary content, they can then base64 decode the appropriate +fields as needed. + +There's nothing currently done for timestamps, but this will change +in the future. + +""" +def register_scalar_parser(event_handlers): + event_handlers.register('building-command-table.main', + add_scalar_parsers) + + +def identity(x): + return x + + +def add_scalar_parsers(session, **kwargs): + factory = session.get_component('response_parser_factory') + # For backwards compatibility reasons, we replace botocore's timestamp + # parser (which parsers to a datetime.datetime object) with the identity + # function which prints the date exactly the same as it comes across the + # wire. We will eventually add a config option that allows for a user to + # have normalized datetime representation, but we can't change the default. + factory.set_parser_defaults( + blob_parser=identity, + timestamp_parser=identity) diff --git a/awscli/handlers.py b/awscli/handlers.py index 4e7510868c02..f4429cf86620 100644 --- a/awscli/handlers.py +++ b/awscli/handlers.py @@ -58,6 +58,7 @@ from awscli.customizations.configservice.getstatus import register_get_status from awscli.customizations.configservice.rename_cmd import \ register_rename_config +from awscli.customizations.scalarparse import register_scalar_parser def awscli_initialize(event_handlers): @@ -118,3 +119,4 @@ def awscli_initialize(event_handlers): register_subscribe(event_handlers) register_get_status(event_handlers) register_rename_config(event_handlers) + register_scalar_parser(event_handlers) diff --git a/tests/integration/test_smoke.py b/tests/integration/test_smoke.py index f07f3a23bf12..d394e1b0be25 100644 --- a/tests/integration/test_smoke.py +++ b/tests/integration/test_smoke.py @@ -40,6 +40,7 @@ 'emr list-clusters', 'iam list-users', 'kinesis list-streams', + 'kms generate-random --number-of-bytes 128', 'logs describe-log-groups', 'opsworks describe-stacks', 'rds describe-db-instances', diff --git a/tests/unit/customizations/test_scalarparse.py b/tests/unit/customizations/test_scalarparse.py new file mode 100644 index 000000000000..04d9331b28e6 --- /dev/null +++ b/tests/unit/customizations/test_scalarparse.py @@ -0,0 +1,39 @@ +# Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# 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.testutils import unittest +import six +import mock + +from awscli.customizations import scalarparse + + +class TestScalarParse(unittest.TestCase): + + def test_register_scalar_parser(self): + event_handers = mock.Mock() + scalarparse.register_scalar_parser(event_handers) + event_handers.register.assert_called_with( + 'building-command-table.main', scalarparse.add_scalar_parsers) + + def test_identity(self): + self.assertEqual(scalarparse.identity('foo'), 'foo') + self.assertEqual(scalarparse.identity(10), 10) + + def test_scalar_parsers_set(self): + session = mock.Mock() + scalarparse.add_scalar_parsers(session) + session.get_component.assert_called_with('response_parser_factory') + factory = session.get_component.return_value + factory.set_parser_defaults.assert_called_with( + blob_parser=scalarparse.identity, + timestamp_parser=scalarparse.identity)