def test_reference_beats_collection(self): model = ResourceModel('test', { 'has': { 'Foo': { 'resource': { 'type': 'Frob', 'identifiers': [ {'target':'Id', 'source':'data', 'path': 'FrobId'} ] } } }, 'hasMany': { 'Foo': { 'resource': { 'type': 'Frob' } } } }, {'Frob': {}}) model.load_rename_map() self.assertEqual(model.references[0].name, 'foo') self.assertEqual(model.collections[0].name, 'foo_collection')
def test_action_beats_reference(self): model = ResourceModel('test', { 'actions': { 'Foo': { 'request': { 'operation': 'GetFoo' } } }, 'has': { 'Foo': { 'resource': { 'type': 'Frob', 'identifiers': [ {'target':'Id', 'source':'data', 'path': 'FrobId'} ] } } } }, {'Frob': {}}) model.load_rename_map() self.assertEqual(model.actions[0].name, 'foo') self.assertEqual(model.references[0].name, 'foo_reference')
def test_action_beats_reference(self): model = ResourceModel( 'test', { 'actions': { 'Foo': { 'request': { 'operation': 'GetFoo' } } }, 'has': { 'Foo': { 'resource': { 'type': 'Frob', 'identifiers': [{ 'target': 'Id', 'source': 'data', 'path': 'FrobId' }] } } } }, {'Frob': {}}) model.load_rename_map() assert model.actions[0].name == 'foo' assert model.references[0].name == 'foo_reference'
def test_reference_beats_collection(self): model = ResourceModel( 'test', { 'has': { 'Foo': { 'resource': { 'type': 'Frob', 'identifiers': [{ 'target': 'Id', 'source': 'data', 'path': 'FrobId' }] } } }, 'hasMany': { 'Foo': { 'resource': { 'type': 'Frob' } } } }, {'Frob': {}}) model.load_rename_map() assert model.references[0].name == 'foo' assert model.collections[0].name == 'foo_collection'
def test_meta_beats_identifier(self): model = ResourceModel('test', { 'identifiers': [{'name': 'Meta'}] }, {}) model.load_rename_map() self.assertEqual(model.identifiers[0].name, 'meta_identifier')
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_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 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) self.assertEqual(model.identifiers[0].name, 'foo') self.assertEqual(model.actions[0].name, 'foo_action') self.assertEqual(model.references[0].name, 'foo_reference') self.assertEqual(model.collections[0].name, 'foo_collection') self.assertEqual(model.waiters[0].name, 'wait_until_foo') # If an identifier and an attribute share the same name, then # the attribute is essentially hidden. self.assertNotIn('foo_attribute', model.get_attributes(shape)) # Other attributes need to be there, though self.assertIn('bar', model.get_attributes(shape))
def test_load_beats_identifier(self): model = ResourceModel('test', { 'identifiers': [{'name': 'Load'}], 'load': { 'request': { 'operation': 'GetFrobs' } } }, {}) model.load_rename_map() self.assertTrue(model.load) self.assertEqual(model.identifiers[0].name, 'load_identifier')
def test_collection_beats_waiter(self): model = ResourceModel( 'test', { 'hasMany': {'WaitUntilFoo': {'resource': {'type': 'Frob'}}}, 'waiters': {'Foo': {}}, }, {'Frob': {}}, ) model.load_rename_map() assert model.collections[0].name == 'wait_until_foo' assert model.waiters[0].name == 'wait_until_foo_waiter'
def test_identifier_beats_action(self): model = ResourceModel( 'test', { 'identifiers': [{'name': 'foo'}], 'actions': {'Foo': {'request': {'operation': 'GetFoo'}}}, }, {}, ) model.load_rename_map() assert model.identifiers[0].name == 'foo' assert model.actions[0].name == 'foo_action'
def test_load_beats_identifier(self): model = ResourceModel( 'test', { 'identifiers': [{'name': 'Load'}], 'load': {'request': {'operation': 'GetFrobs'}}, }, {}, ) model.load_rename_map() assert model.load assert model.identifiers[0].name == 'load_identifier'
def test_identifier_beats_action(self): model = ResourceModel('test', { 'identifiers': [{'name': 'foo'}], 'actions': { 'Foo': { 'request': { 'operation': 'GetFoo' } } } }, {}) model.load_rename_map() self.assertEqual(model.identifiers[0].name, 'foo') self.assertEqual(model.actions[0].name, 'foo_action')
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) self.assertEqual(model.waiters[0].name, 'wait_until_foo') self.assertIn('wait_until_foo_attribute', model.get_attributes(shape))
def test_collection_beats_waiter(self): model = ResourceModel('test', { 'hasMany': { 'WaitUntilFoo': { 'resource': { 'type': 'Frob' } } }, 'waiters': { 'Foo': {} } }, {'Frob': {}}) model.load_rename_map() self.assertEqual(model.collections[0].name, 'wait_until_foo') self.assertEqual(model.waiters[0].name, 'wait_until_foo_waiter')
async def load_from_definition(self, resource_name, single_resource_json_definition, service_context): logger.debug('Loading %s:%s', service_context.service_name, resource_name) # Using the loaded JSON create a ResourceModel object. resource_model = ResourceModel( resource_name, single_resource_json_definition, service_context.resource_json_definitions) # Do some renaming of the shape if there was a naming collision # that needed to be accounted for. shape = None if resource_model.shape: shape = service_context.service_model.shape_for( resource_model.shape) resource_model.load_rename_map(shape) # Set some basic info meta = ResourceMeta(service_context.service_name, resource_model=resource_model) attrs = { 'meta': meta, } # Create and load all of attributes of the resource class based # on the models. # Identifiers self._load_identifiers(attrs=attrs, meta=meta, resource_name=resource_name, resource_model=resource_model) # Load/Reload actions self._load_actions(attrs=attrs, resource_name=resource_name, resource_model=resource_model, service_context=service_context) # Attributes that get auto-loaded self._load_attributes(attrs=attrs, meta=meta, resource_name=resource_name, resource_model=resource_model, service_context=service_context) # Collections and their corresponding methods self._load_collections(attrs=attrs, resource_model=resource_model, service_context=service_context) # References and Subresources self._load_has_relations(attrs=attrs, resource_name=resource_name, resource_model=resource_model, service_context=service_context) # Waiter resource actions self._load_waiters(attrs=attrs, resource_name=resource_name, resource_model=resource_model, service_context=service_context) # Create the name based on the requested service and resource cls_name = resource_name if service_context.service_name == resource_name: cls_name = 'ServiceResource' cls_name = service_context.service_name + '.' + cls_name base_classes = [AIOBoto3ServiceResource] if self._emitter is not None: await self._emitter.emit('creating-resource-class.%s' % cls_name, class_attributes=attrs, base_classes=base_classes, service_context=service_context) return type(str(cls_name), tuple(base_classes), attrs)
def load_from_definition(self, resource_name, single_resource_json_definition, service_context): """ Loads a resource from a model, creating a new :py:class:`~boto3.resources.base.ServiceResource` subclass with the correct properties and methods, named based on the service and resource name, e.g. EC2.Instance. :type resource_name: string :param resource_name: Name of the resource to look up. For services, this should match the ``service_name``. :type single_resource_json_definition: dict :param single_resource_json_definition: The loaded json of a single service resource or resource definition. :type service_context: :py:class:`~boto3.utils.ServiceContext` :param service_context: Context about the AWS service :rtype: Subclass of :py:class:`~boto3.resources.base.ServiceResource` :return: The service or resource class. """ logger.debug('Loading %s:%s', service_context.service_name, resource_name) # Using the loaded JSON create a ResourceModel object. resource_model = ResourceModel( resource_name, single_resource_json_definition, service_context.resource_json_definitions ) # Do some renaming of the shape if there was a naming collision # that needed to be accounted for. shape = None if resource_model.shape: shape = service_context.service_model.shape_for( resource_model.shape) resource_model.load_rename_map(shape) # Set some basic info meta = ResourceMeta( service_context.service_name, resource_model=resource_model) attrs = { 'meta': meta, } # Create and load all of attributes of the resource class based # on the models. # Identifiers self._load_identifiers( attrs=attrs, meta=meta, resource_name=resource_name, resource_model=resource_model ) # Load/Reload actions self._load_actions( attrs=attrs, resource_name=resource_name, resource_model=resource_model, service_context=service_context ) # Attributes that get auto-loaded self._load_attributes( attrs=attrs, meta=meta, resource_name=resource_name, resource_model=resource_model, service_context=service_context) # Collections and their corresponding methods self._load_collections( attrs=attrs, resource_model=resource_model, service_context=service_context) # References and Subresources self._load_has_relations( attrs=attrs, resource_name=resource_name, resource_model=resource_model, service_context=service_context ) # Waiter resource actions self._load_waiters( attrs=attrs, resource_name=resource_name, resource_model=resource_model, service_context=service_context ) # Create the name based on the requested service and resource cls_name = resource_name if service_context.service_name == resource_name: cls_name = 'ServiceResource' cls_name = service_context.service_name + '.' + cls_name base_classes = [AIOBoto3ServiceResource] if self._emitter is not None: self._emitter.emit( 'creating-resource-class.%s' % cls_name, class_attributes=attrs, base_classes=base_classes, service_context=service_context) return type(str(cls_name), tuple(base_classes), attrs)