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'})
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 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
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')
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()
def _get_default_output_stream_factory(self): return OutputStreamFactory(self._session, default_less_flags='SR')
def setUp(self): self.popen = mock.Mock(subprocess.Popen) self.stream_factory = OutputStreamFactory(self.popen)
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'})
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()
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']
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')
def _get_default_output_stream_factory(self): return OutputStreamFactory(self._session)