Пример #1
0
 def test_set_less_flags_through_constructor(self):
     self.set_session_pager('less')
     stream_factory = OutputStreamFactory(self.session,
                                          self.popen,
                                          self.environ,
                                          default_less_flags='ABC')
     with stream_factory.get_output_stream():
         self.assert_popen_call(expected_pager_cmd='less',
                                env={'LESS': 'ABC'})
Пример #2
0
 def _run_main(self, parsed_args, parsed_globals):
     factory = self._session.get_component('response_parser_factory')
     factory.set_parser_defaults(blob_parser=None)
     self._client = self._session.create_client(
         'dynamodb',
         region_name=parsed_globals.region,
         endpoint_url=parsed_globals.endpoint_url,
         verify=parsed_globals.verify_ssl)
     self._transformer = ParameterTransformer()
     self._serializer = TypeSerializer()
     self._deserializer = TypeDeserializer()
     self._extractor = AttributeExtractor()
     self._output_stream_factory = OutputStreamFactory(self._session)
Пример #3
0
 def setUp(self):
     self.session = mock.Mock(session.Session)
     self.popen = mock.Mock(subprocess.Popen)
     self.environ = {}
     self.stream_factory = OutputStreamFactory(
         session=self.session,
         popen=self.popen,
         environ=self.environ,
     )
     self.pager = 'mypager --option'
     self.set_session_pager(self.pager)
     self.patch_tty = mock.patch('awscli.utils.is_a_tty')
     self.mock_is_a_tty = self.patch_tty.start()
     self.mock_is_a_tty.return_value = True
Пример #4
0
class TestOutputStreamFactory(unittest.TestCase):
    def setUp(self):
        self.popen = mock.Mock(subprocess.Popen)
        self.stream_factory = OutputStreamFactory(self.popen)

    @mock.patch('awscli.utils.get_popen_kwargs_for_pager_cmd')
    def test_pager(self, mock_get_popen_pager):
        mock_get_popen_pager.return_value = {'args': ['mypager', '--option']}
        with self.stream_factory.get_pager_stream():
            mock_get_popen_pager.assert_called_with(None)
            self.assertEqual(self.popen.call_args_list, [
                mock.call(args=['mypager', '--option'], stdin=subprocess.PIPE)
            ])

    @mock.patch('awscli.utils.get_popen_kwargs_for_pager_cmd')
    def test_env_configured_pager(self, mock_get_popen_pager):
        mock_get_popen_pager.return_value = {'args': ['mypager', '--option']}
        with self.stream_factory.get_pager_stream('mypager --option'):
            mock_get_popen_pager.assert_called_with('mypager --option')
            self.assertEqual(self.popen.call_args_list, [
                mock.call(args=['mypager', '--option'], stdin=subprocess.PIPE)
            ])

    @mock.patch('awscli.utils.get_popen_kwargs_for_pager_cmd')
    def test_pager_using_shell(self, mock_get_popen_pager):
        mock_get_popen_pager.return_value = {
            'args': 'mypager --option',
            'shell': True
        }
        with self.stream_factory.get_pager_stream():
            mock_get_popen_pager.assert_called_with(None)
            self.assertEqual(self.popen.call_args_list, [
                mock.call(
                    args='mypager --option', stdin=subprocess.PIPE, shell=True)
            ])

    def test_exit_of_context_manager_for_pager(self):
        with self.stream_factory.get_pager_stream():
            pass
        returned_process = self.popen.return_value
        self.assertTrue(returned_process.communicate.called)

    @mock.patch('awscli.utils.get_binary_stdout')
    def test_stdout(self, mock_binary_out):
        with self.stream_factory.get_stdout_stream():
            self.assertTrue(mock_binary_out.called)

    def test_can_silence_io_error_from_pager(self):
        self.popen.return_value = MockProcess()
        try:
            # RuntimeError is caught here since a runtime error is raised
            # when an IOError is raised before the context manager yields.
            # If we ignore it like this we will actually see the IOError.
            with self.assertRaises(RuntimeError):
                with self.stream_factory.get_pager_stream():
                    pass
        except IOError:
            self.fail('Should not raise IOError')
Пример #5
0
class HistorySubcommand(BasicCommand):
    def __init__(self, session, db_reader=None, output_stream_factory=None):
        super(HistorySubcommand, self).__init__(session)
        self._db_reader = db_reader
        self._output_stream_factory = output_stream_factory
        if output_stream_factory is None:
            self._output_stream_factory = OutputStreamFactory()

    def _connect_to_history_db(self):
        if self._db_reader is None:
            connection = DatabaseConnection(self._get_history_db_filename())
            self._db_reader = DatabaseRecordReader(connection)

    def _close_history_db(self):
        self._db_reader.close()

    def _get_history_db_filename(self):
        filename = os.environ.get(
            HISTORY_FILENAME_ENV_VAR, DEFAULT_HISTORY_FILENAME)
        if not os.path.exists(filename):
            raise RuntimeError(
                'Could not locate history. Make sure cli_history is set to '
                'enabled in the ~/.aws/config file'
            )
        return filename

    def _should_use_color(self, parsed_globals):
        if parsed_globals.color == 'on':
            return True
        elif parsed_globals.color == 'off':
            return False
        return is_a_tty() and not is_windows

    def _get_output_stream(self, preferred_pager=None):
        if is_a_tty():
            return self._output_stream_factory.get_pager_stream(
                preferred_pager)
        return self._output_stream_factory.get_stdout_stream()
class HistorySubcommand(BasicCommand):
    def __init__(self, session, db_reader=None, output_stream_factory=None):
        super(HistorySubcommand, self).__init__(session)
        self._db_reader = db_reader
        self._output_stream_factory = output_stream_factory
        if output_stream_factory is None:
            self._output_stream_factory = OutputStreamFactory()

    def _connect_to_history_db(self):
        if self._db_reader is None:
            connection = DatabaseConnection(self._get_history_db_filename())
            self._db_reader = DatabaseRecordReader(connection)

    def _close_history_db(self):
        self._db_reader.close()

    def _get_history_db_filename(self):
        filename = os.environ.get(HISTORY_FILENAME_ENV_VAR,
                                  DEFAULT_HISTORY_FILENAME)
        if not os.path.exists(filename):
            raise RuntimeError(
                'Could not locate history. Make sure cli_history is set to '
                'enabled in the ~/.aws/config file')
        return filename

    def _should_use_color(self, parsed_globals):
        if parsed_globals.color == 'on':
            return True
        elif parsed_globals.color == 'off':
            return False
        return is_a_tty() and not is_windows

    def _get_output_stream(self, preferred_pager=None):
        if is_a_tty():
            return self._output_stream_factory.get_pager_stream(
                preferred_pager)
        return self._output_stream_factory.get_stdout_stream()
Пример #7
0
 def _get_default_output_stream_factory(self):
     return OutputStreamFactory(self._session, default_less_flags='SR')
Пример #8
0
 def setUp(self):
     self.popen = mock.Mock(subprocess.Popen)
     self.stream_factory = OutputStreamFactory(self.popen)
Пример #9
0
class TestOutputStreamFactory(unittest.TestCase):
    def setUp(self):
        self.session = mock.Mock(session.Session)
        self.popen = mock.Mock(subprocess.Popen)
        self.environ = {}
        self.stream_factory = OutputStreamFactory(
            session=self.session,
            popen=self.popen,
            environ=self.environ,
        )
        self.pager = 'mypager --option'
        self.set_session_pager(self.pager)
        self.patch_tty = mock.patch('awscli.utils.is_a_tty')
        self.mock_is_a_tty = self.patch_tty.start()
        self.mock_is_a_tty.return_value = True

    def tearDown(self):
        self.patch_tty.stop()

    def set_session_pager(self, pager):
        self.session.get_component.return_value.\
            get_config_variable.return_value = pager

    def assert_popen_call(self, expected_pager_cmd, **override_args):
        popen_kwargs = {
            'stdin': subprocess.PIPE,
            'env': mock.ANY,
            'universal_newlines': True
        }
        if is_windows:
            popen_kwargs['args'] = expected_pager_cmd
            popen_kwargs['shell'] = True
        else:
            popen_kwargs['args'] = shlex.split(expected_pager_cmd)
        popen_kwargs.update(override_args)
        self.popen.assert_called_with(**popen_kwargs)

    def test_pager(self):
        self.set_session_pager('mypager --option')
        with self.stream_factory.get_pager_stream():
            self.assert_popen_call(expected_pager_cmd='mypager --option')

    def test_explicit_pager(self):
        self.set_session_pager('sessionpager --option')
        with self.stream_factory.get_pager_stream('mypager --option'):
            self.assert_popen_call(expected_pager_cmd='mypager --option')

    def test_exit_of_context_manager_for_pager(self):
        self.set_session_pager('mypager --option')
        with self.stream_factory.get_pager_stream():
            pass
        returned_process = self.popen.return_value
        self.assertTrue(returned_process.communicate.called)

    def test_propagates_exception_from_popen(self):
        self.popen.side_effect = PopenException
        with self.assertRaises(PopenException):
            with self.stream_factory.get_pager_stream():
                pass

    @mock.patch('awscli.utils.get_stdout_text_writer')
    def test_stdout(self, mock_stdout_writer):
        with self.stream_factory.get_stdout_stream():
            self.assertTrue(mock_stdout_writer.called)

    def test_can_silence_io_error_from_pager(self):
        self.popen.return_value = MockProcess()
        try:
            # RuntimeError is caught here since a runtime error is raised
            # when an IOError is raised before the context manager yields.
            # If we ignore it like this we will actually see the IOError.
            with self.assertRaises(RuntimeError):
                with self.stream_factory.get_pager_stream():
                    pass
        except IOError:
            self.fail('Should not raise IOError')

    def test_get_output_stream(self):
        self.set_session_pager('mypager --option')
        with self.stream_factory.get_output_stream():
            self.assert_popen_call(expected_pager_cmd='mypager --option')

    @mock.patch('awscli.utils.get_stdout_text_writer')
    def test_use_stdout_if_not_tty(self, mock_stdout_writer):
        self.mock_is_a_tty.return_value = False
        with self.stream_factory.get_output_stream():
            self.assertTrue(mock_stdout_writer.called)

    @mock.patch('awscli.utils.get_stdout_text_writer')
    def test_use_stdout_if_pager_set_to_empty_string(self, mock_stdout_writer):
        self.set_session_pager('')
        with self.stream_factory.get_output_stream():
            self.assertTrue(mock_stdout_writer.called)

    def test_adds_default_less_env_vars(self):
        self.set_session_pager('myless')
        with self.stream_factory.get_output_stream():
            self.assert_popen_call(expected_pager_cmd='myless',
                                   env={'LESS': 'FRX'})

    def test_does_not_clobber_less_env_var_if_in_env_vars(self):
        self.set_session_pager('less')
        self.environ['LESS'] = 'S'
        with self.stream_factory.get_output_stream():
            self.assert_popen_call(expected_pager_cmd='less',
                                   env={'LESS': 'S'})

    def test_set_less_flags_through_constructor(self):
        self.set_session_pager('less')
        stream_factory = OutputStreamFactory(self.session,
                                             self.popen,
                                             self.environ,
                                             default_less_flags='ABC')
        with stream_factory.get_output_stream():
            self.assert_popen_call(expected_pager_cmd='less',
                                   env={'LESS': 'ABC'})
Пример #10
0
 def __init__(self, session, db_reader=None, output_stream_factory=None):
     super(HistorySubcommand, self).__init__(session)
     self._db_reader = db_reader
     self._output_stream_factory = output_stream_factory
     if output_stream_factory is None:
         self._output_stream_factory = OutputStreamFactory()
Пример #11
0
class DDBCommand(BasicCommand):
    def _run_main(self, parsed_args, parsed_globals):
        factory = self._session.get_component('response_parser_factory')
        factory.set_parser_defaults(blob_parser=None)
        self._client = self._session.create_client(
            'dynamodb',
            region_name=parsed_globals.region,
            endpoint_url=parsed_globals.endpoint_url,
            verify=parsed_globals.verify_ssl)
        self._transformer = ParameterTransformer()
        self._serializer = TypeSerializer()
        self._deserializer = TypeDeserializer()
        self._extractor = AttributeExtractor()
        self._output_stream_factory = OutputStreamFactory(self._session)

    def _serialize(self, operation_name, data):
        service_model = self._client.meta.service_model
        operation_model = service_model.operation_model(
            self._client.meta.method_to_api_mapping.get(operation_name))
        self._transformer.transform(data, operation_model.input_shape,
                                    self._serializer.serialize,
                                    'AttributeValue')

    def _deserialize(self, operation_name, data):
        service_model = self._client.meta.service_model
        operation_model = service_model.operation_model(
            self._client.meta.method_to_api_mapping.get(operation_name))
        self._transformer.transform(data, operation_model.output_shape,
                                    self._deserializer.deserialize,
                                    'AttributeValue')

    def _make_api_call(self,
                       operation_name,
                       client_args,
                       should_paginate=True):
        self._serialize(operation_name, client_args)

        if self._client.can_paginate(operation_name) and should_paginate:
            paginator = self._client.get_paginator(operation_name)
            response = paginator.paginate(**client_args).build_full_result()
        else:
            response = getattr(self._client, operation_name)(**client_args)
        if 'ConsumedCapacity' in response and \
                response['ConsumedCapacity'] is None:
            del response['ConsumedCapacity']
        self._deserialize(operation_name, response)
        return response

    def _dump_yaml(self, operation_name, data, parsed_globals):
        if parsed_globals.output == 'yaml-stream':
            # TODO: In the future, we should support yaml-stream. However, it
            #  would require a larger refactoring. Right now we always build
            #  the full result when paginating prior to sending it to the
            #  formatter. We need to instead pass the page iterator and
            #  deserialize in the formatter. We cannot necessarily just
            #  convert these to client handlers because the DDB types we
            #  introduce do not play nicely with the pagination interfaces.
            #  For example, botocore cannot serialize our Binary types into
            #  a resume token when --max-items gets set.
            raise ParamValidationError(
                'yaml-stream output format is not supported for ddb commands')
        formatter = YAMLFormatter(parsed_globals, DynamoYAMLDumper())
        with self._output_stream_factory.get_output_stream() as stream:
            formatter(operation_name, data, stream)

    def _add_expression_args(self,
                             expression_name,
                             expression,
                             args,
                             substitution_count=0):
        result = self._extractor.extract(' '.join(expression),
                                         substitution_count)
        args[expression_name] = result['expression']

        if result['identifiers']:
            if 'ExpressionAttributeNames' not in args:
                args['ExpressionAttributeNames'] = {}
            args['ExpressionAttributeNames'].update(result['identifiers'])

        if result['values']:
            if 'ExpressionAttributeValues' not in args:
                args['ExpressionAttributeValues'] = {}
            args['ExpressionAttributeValues'].update(result['values'])

        return result['substitution_count']
 def __init__(self, session, db_reader=None, output_stream_factory=None):
     super(HistorySubcommand, self).__init__(session)
     self._db_reader = db_reader
     self._output_stream_factory = output_stream_factory
     if output_stream_factory is None:
         self._output_stream_factory = OutputStreamFactory()
Пример #13
0
 def setUp(self):
     self.popen = mock.Mock(subprocess.Popen)
     self.stream_factory = OutputStreamFactory(self.popen)
Пример #14
0
class TestOutputStreamFactory(unittest.TestCase):
    def setUp(self):
        self.popen = mock.Mock(subprocess.Popen)
        self.stream_factory = OutputStreamFactory(self.popen)

    @mock.patch('awscli.utils.get_popen_kwargs_for_pager_cmd')
    def test_pager(self, mock_get_popen_pager):
        mock_get_popen_pager.return_value = {
                'args': ['mypager', '--option']
        }
        with self.stream_factory.get_pager_stream():
            mock_get_popen_pager.assert_called_with(None)
            self.assertEqual(
                self.popen.call_args_list,
                [mock.call(
                    args=['mypager', '--option'],
                    stdin=subprocess.PIPE)]
            )

    @mock.patch('awscli.utils.get_popen_kwargs_for_pager_cmd')
    def test_env_configured_pager(self, mock_get_popen_pager):
        mock_get_popen_pager.return_value = {
            'args': ['mypager', '--option']
        }
        with self.stream_factory.get_pager_stream('mypager --option'):
            mock_get_popen_pager.assert_called_with('mypager --option')
            self.assertEqual(
                self.popen.call_args_list,
                [mock.call(
                    args=['mypager', '--option'],
                    stdin=subprocess.PIPE)]
            )

    @mock.patch('awscli.utils.get_popen_kwargs_for_pager_cmd')
    def test_pager_using_shell(self, mock_get_popen_pager):
        mock_get_popen_pager.return_value = {
            'args': 'mypager --option', 'shell': True
        }
        with self.stream_factory.get_pager_stream():
            mock_get_popen_pager.assert_called_with(None)
            self.assertEqual(
                self.popen.call_args_list,
                [mock.call(
                    args='mypager --option',
                    stdin=subprocess.PIPE,
                    shell=True)]
            )

    def test_exit_of_context_manager_for_pager(self):
        with self.stream_factory.get_pager_stream():
            pass
        returned_process = self.popen.return_value
        self.assertTrue(returned_process.communicate.called)

    @mock.patch('awscli.utils.get_binary_stdout')
    def test_stdout(self, mock_binary_out):
        with self.stream_factory.get_stdout_stream():
            self.assertTrue(mock_binary_out.called)

    def test_can_silence_io_error_from_pager(self):
        self.popen.return_value = MockProcess()
        try:
            # RuntimeError is caught here since a runtime error is raised
            # when an IOError is raised before the context manager yields.
            # If we ignore it like this we will actually see the IOError.
            with self.assertRaises(RuntimeError):
                with self.stream_factory.get_pager_stream():
                    pass
        except IOError:
            self.fail('Should not raise IOError')
Пример #15
0
 def _get_default_output_stream_factory(self):
     return OutputStreamFactory(self._session)