def test_boolean_arg_groups(self): builder = DenormalizedStructureBuilder() input_model = builder.with_members({ 'Flag': {'type': 'boolean'} }).build_model() argument_model = input_model.members['Flag'] argument_model.name = 'Flag' self.arg_table['flag'] = mock.Mock( cli_type_name='boolean', argument_model=argument_model) self.arg_table['no-flag'] = mock.Mock( cli_type_name='boolean', argument_model=argument_model) # The --no-flag should not be used in the translation. self.assertEqual( self.operation_handler.build_translation_map(), {'Flag': 'flag'} )
def test_nested_structure(self): # Internally this doesn't use an OrderedDict so we can't # test the full output, but we can test whether the # parameters are all included as expected with the correct # types. shape = DenormalizedStructureBuilder().with_members({ 'Param1': { 'type': 'list', 'member': { 'type': 'structure', 'members': { 'Param2': { 'type': 'string' }, 'Param3': { 'type': 'float' } } } }, 'Param4': { 'type': 'blob' } }).build_model() doc = document_structure('Test', shape) self.assertIn("'Param1': [", doc) self.assertIn("'Param2': STRING", doc) self.assertIn("'Param3': FLOAT", doc) self.assertIn("'Param4': BYTES", doc)
def setUp(self): self.session = mock.Mock() # Create a mock service operation object self.service_operation = mock.Mock() # Make an arbitrary input model shape. self.input_shape = { 'A': { 'type': 'structure', 'members': { 'B': { 'type': 'string' }, } } } shape = DenormalizedStructureBuilder().with_members( self.input_shape).build_model() self.operation_model = mock.Mock(input_shape=shape) self.argument = GenerateCliSkeletonArgument(self.session, self.operation_model) # This is what the json should should look like after being # generated to standard output. self.ref_json_output = \ '{\n "A": {\n "B": ""\n }\n}\n'
def test_nested_structure(self): shape = DenormalizedStructureBuilder().with_members( load_json('''{ "Param1": { "type": "list", "member": { "type": "structure", "members": { "Param2": { "type": "string" }, "Param3": { "type": "float" } } } }, "Param4": { "type": "blob" }, "Param5": { "type": "list", "member": { "type": "string" } }, "Param6": { "type": "map", "key": { "type": "string" }, "value": { "type": "integer" } } }''')).build_model() expected = fix_whitespace(''' { 'Param1': [ { 'Param2': STRING, 'Param3': FLOAT }, ... ], 'Param4': BYTES, 'Param5': [ STRING, ... ], 'Param6': { STRING: INTEGER } } ''') doc = document_param_response('Test', shape) self.assertEqual(doc, expected)
def test_resource_aliases_identifiers(self, action_cls): model = { 'shape': 'TestShape', 'identifiers': [{ 'name': 'id', 'memberName': 'foo_id' }] } shape = DenormalizedStructureBuilder().with_members({ 'foo_id': { 'type': 'string', }, 'bar': { 'type': 'string' }, }).build_model() service_model = mock.Mock() service_model.shape_for.return_value = shape shape_id = 'baz' resource = self.load('test', model, service_model=service_model)(shape_id) try: assert resource.id == shape_id assert resource.foo_id == shape_id except ResourceLoadException: self.fail("Load attempted on identifier alias.")
def test_generate_json_skeleton_with_timestamp(self): parsed_args = mock.Mock() parsed_args.generate_cli_skeleton = 'input' input_shape = { 'A': { 'type': 'structure', 'members': { 'B': { 'type': 'timestamp' }, } } } shape = DenormalizedStructureBuilder().with_members( input_shape).build_model() operation_model = mock.Mock(input_shape=shape) argument = GenerateCliSkeletonArgument(self.session, operation_model) with mock.patch('sys.stdout', six.StringIO()) as mock_stdout: rc = argument.generate_json_skeleton(call_parameters=None, parsed_args=parsed_args, parsed_globals=None) self.assertEqual( '{\n' ' "A": {\n' ' "B": "1970-01-01T00:00:00"\n' ' }\n' '}\n', mock_stdout.getvalue()) self.assertEqual(rc, 0)
def test_resource_lazy_properties_missing_load(self, action_cls): model = { 'shape': 'TestShape', 'identifiers': [{ 'name': 'Url' }] # Note the lack of a `load` method. These resources # are usually loaded via a call on a parent resource. } shape = DenormalizedStructureBuilder().with_members({ 'ETag': { 'type': 'string', }, 'LastModified': { 'type': 'string' }, 'Url': { 'type': 'string' } }).build_model() service_model = mock.Mock() service_model.shape_for.return_value = shape action = action_cls.return_value action.return_value = {'ETag': 'tag', 'LastModified': 'never'} resource = self.load('test', model, service_model=service_model)('url') with pytest.raises(ResourceLoadException): resource.last_modified
def test_factory_creates_properties(self): model = { 'shape': 'TestShape', 'load': { 'request': { 'operation': 'DescribeTest', } } } shape = DenormalizedStructureBuilder().with_members({ 'ETag': { 'type': 'string', }, 'LastModified': { 'type': 'string' } }).build_model() service_model = mock.Mock() service_model.shape_for.return_value = shape TestResource = self.load('test', model, service_model=service_model) self.assertTrue(hasattr(TestResource, 'e_tag'), 'ETag shape member not available on resource') self.assertTrue(hasattr(TestResource, 'last_modified'), 'LastModified shape member not available on resource')
def test_dangling_resource_loads_data(self): # Given a loadable resource instance that contains a reference # to another resource which has a resource data path, the # referenced resource should be loaded with all of the data # contained at that path. This allows loading references # which would otherwise not be loadable (missing load method) # and prevents extra load calls for others when we already # have the data available. self.defs = { 'Instance': { 'identifiers': [{'name': 'Id'}], 'has': { 'NetworkInterface': { 'resource': { 'type': 'NetworkInterface', 'identifiers': [ {'target': 'Id', 'source': 'data', 'path': 'NetworkInterface.Id'} ], 'path': 'NetworkInterface' } } } }, 'NetworkInterface': { 'identifiers': [{'name': 'Id'}], 'shape': 'NetworkInterfaceShape' } } self.model = self.defs['Instance'] shape = DenormalizedStructureBuilder().with_members({ 'Id': { 'type': 'string', }, 'PublicIp': { 'type': 'string' } }).build_model() service_model = mock.Mock() service_model.shape_for.return_value = shape cls = self.load('test', 'Instance', self.model, self.defs, service_model) instance = cls('instance-id') # Set some data as if we had completed a load action. def set_meta_data(): instance.meta.data = { 'NetworkInterface': { 'Id': 'network-interface-id', 'PublicIp': '127.0.0.1' } } instance.load = mock.Mock(side_effect=set_meta_data) # Now, get the reference and make sure it has its data # set as expected. interface = instance.network_interface self.assertIsNotNone(interface.meta.data) self.assertEqual(interface.public_ip, '127.0.0.1')
def test_does_not_alias_parameter_for_not_modeled_member(self): value = 'value' params = {self.alias_name: value} request_shape = DenormalizedStructureBuilder().with_members( {'foo': {'type': 'string'}}).build_model() self.operation_model.input_shape = request_shape self.parameter_alias.alias_parameter_in_call( params, self.operation_model) self.assertEqual(params, {self.alias_name: value})
def test_multiple(self): # This tests a bunch of different renames working together model = ResourceModel( 'test', { 'identifiers': [{ 'name': 'Foo' }], 'actions': { 'Foo': {} }, 'has': { 'Foo': { 'resource': { 'type': 'Frob', 'identifiers': [{ 'target': 'Id', 'source': 'data', 'path': 'FrobId' }] } } }, 'hasMany': { 'Foo': {} }, 'waiters': { 'Foo': {} } }, {'Frob': {}}) shape = DenormalizedStructureBuilder().with_members({ 'Foo': { 'type': 'string', }, 'Bar': { 'type': 'string' } }).build_model() model.load_rename_map(shape) assert model.identifiers[0].name == 'foo' assert model.actions[0].name == 'foo_action' assert model.references[0].name == 'foo_reference' assert model.collections[0].name == 'foo_collection' assert model.waiters[0].name == 'wait_until_foo' # If an identifier and an attribute share the same name, then # the attribute is essentially hidden. assert 'foo_attribute' not in model.get_attributes(shape) # Other attributes need to be there, though assert 'bar' in model.get_attributes(shape)
def test_resource_lazy_loads_properties(self, action_cls): model = { 'shape': 'TestShape', 'identifiers': [ {'name': 'Url'} ], 'load': { 'request': { 'operation': 'DescribeTest', } } } shape = DenormalizedStructureBuilder().with_members({ 'ETag': { 'type': 'string', 'shape_name': 'ETag' }, 'LastModified': { 'type': 'string', 'shape_name': 'LastModified' }, 'Url': { 'type': 'string', 'shape_name': 'Url' } }).build_model() service_model = mock.Mock() service_model.shape_for.return_value = shape action = action_cls.return_value action.return_value = {'ETag': 'tag', 'LastModified': 'never'} resource = self.load( 'test', model, service_model=service_model)('url') # Accessing an identifier should not call load, even if it's in # the shape members. resource.url action.assert_not_called() # Accessing a property should call load self.assertEqual(resource.e_tag, 'tag', 'ETag property returned wrong value') self.assertEqual(action.call_count, 1) # Both params should have been loaded into the data bag self.assertIn('ETag', resource.meta.data) self.assertIn('LastModified', resource.meta.data) # Accessing another property should use cached value # instead of making a second call. self.assertEqual(resource.last_modified, 'never', 'LastModified property returned wrong value') self.assertEqual(action.call_count, 1)
def setUp(self): self.original_name = 'original' self.alias_name = 'alias' self.parameter_alias = handlers.ParameterAlias( self.original_name, self.alias_name) self.operation_model = mock.Mock() request_shape = DenormalizedStructureBuilder().with_members( {self.original_name: {'type': 'string'}}).build_model() self.operation_model.input_shape = request_shape self.sample_section = DocumentStructure('') self.event_emitter = HierarchicalEmitter()
def test_waiter_beats_attribute(self): model = ResourceModel('test', {'waiters': {'Foo': {}}}, {'Frob': {}}) shape = DenormalizedStructureBuilder().with_members({ 'WaitUntilFoo': { 'type': 'string', } }).build_model() model.load_rename_map(shape) assert model.waiters[0].name == 'wait_until_foo' assert 'wait_until_foo_attribute' in model.get_attributes(shape)
def assert_skeleton_from_model_is(self, model, generated_skeleton): shape = DenormalizedStructureBuilder().with_members( model).build_model() actual = self.arg_generator.generate_skeleton(shape) self.assertEqual(actual, generated_skeleton)
def create_argument(self, input_shape): builder = DenormalizedStructureBuilder().with_members(input_shape) operation_model = mock.Mock(input_shape=builder.build_model()) return GenerateCliSkeletonArgument(self.session, operation_model)