def setUp(self): self.model = { "metadata": { 'endpointPrefix': 'myservice', 'serviceFullName': 'MyService', }, 'operations': { 'OperationName': { 'name': 'OperationName', 'errors': [ { 'shape': 'ExceptionMissingCode' }, { 'shape': 'ExceptionWithModeledCode' }, ], }, 'AnotherOperationName': { 'name': 'AnotherOperationName', 'errors': [ { 'shape': 'ExceptionForAnotherOperation' }, { 'shape': 'ExceptionWithModeledCode' }, ], } }, 'shapes': { 'ExceptionWithModeledCode': { 'type': 'structure', 'members': {}, 'error': { 'code': 'ModeledCode' }, 'exception': True, }, 'ExceptionMissingCode': { 'type': 'structure', 'members': {}, 'exception': True, }, 'ExceptionForAnotherOperation': { 'type': 'structure', 'members': {}, 'exception': True, } } } self.service_model = ServiceModel(self.model) self.exceptions_factory = ClientExceptionsFactory()
def parse_client(session: Session, service_name: ServiceName, shape_parser: ShapeParser) -> Client: """ Parse boto3 client to a structure. Arguments: session -- boto3 session. service_name -- Target service name. Returns: Client structure. """ client = get_boto3_client(session, service_name) public_methods = get_public_methods(client) # remove methods that will be overriden if "get_paginator" in public_methods: del public_methods["get_paginator"] if "get_waiter" in public_methods: del public_methods["get_waiter"] result = Client( name=Client.get_class_name(service_name), service_name=service_name, boto3_client=client, ) shape_method_map = shape_parser.get_client_method_map() result.methods.append(result.get_exceptions_property()) for method_name, public_method in public_methods.items(): if method_name in shape_method_map: method = shape_method_map[method_name] else: method = parse_method("Client", method_name, public_method, service_name) docstring = get_short_docstring(inspect.getdoc(public_method) or "") method.docstring = docstring result.methods.append(method) service_model = client.meta.service_model client_exceptions = ClientExceptionsFactory().create_client_exceptions(service_model) for exception_class_name in dir(client_exceptions): if exception_class_name.startswith("_"): continue if not exception_class_name[0].isupper(): continue result.exceptions_class.attributes.append( Attribute( exception_class_name, TypeSubscript( Type.Type, [InternalImport("BotocoreClientError", stringify=False)], ), ) ) result.attributes.append(Attribute("meta", TypeClass(ClientMeta))) return result
def setUp(self): self.model = { "metadata": { 'endpointPrefix': 'myservice', 'serviceFullName': 'MyService', }, 'operations': { 'OperationName': { 'name': 'OperationName', 'errors': [ {'shape': 'ExceptionMissingCode'}, {'shape': 'ExceptionWithModeledCode'}, ], }, 'AnotherOperationName': { 'name': 'AnotherOperationName', 'errors': [ {'shape': 'ExceptionForAnotherOperation'}, {'shape': 'ExceptionWithModeledCode'}, ], } }, 'shapes': { 'ExceptionWithModeledCode': { 'type': 'structure', 'members': {}, 'error': { 'code': 'ModeledCode' }, 'exception': True, }, 'ExceptionMissingCode': { 'type': 'structure', 'members': {}, 'exception': True, }, 'ExceptionForAnotherOperation': { 'type': 'structure', 'members': {}, 'exception': True, } } } self.service_model = ServiceModel(self.model) self.exceptions_factory = ClientExceptionsFactory()
def _register_exceptions_factory(self): self._components.register_component('exceptions_factory', ClientExceptionsFactory())
class TestClientExceptionsFactory(unittest.TestCase): def setUp(self): self.model = { "metadata": { 'endpointPrefix': 'myservice', 'serviceFullName': 'MyService', }, 'operations': { 'OperationName': { 'name': 'OperationName', 'errors': [ { 'shape': 'ExceptionMissingCode' }, { 'shape': 'ExceptionWithModeledCode' }, ], }, 'AnotherOperationName': { 'name': 'AnotherOperationName', 'errors': [ { 'shape': 'ExceptionForAnotherOperation' }, { 'shape': 'ExceptionWithModeledCode' }, ], } }, 'shapes': { 'ExceptionWithModeledCode': { 'type': 'structure', 'members': {}, 'error': { 'code': 'ModeledCode' }, 'exception': True, }, 'ExceptionMissingCode': { 'type': 'structure', 'members': {}, 'exception': True, }, 'ExceptionForAnotherOperation': { 'type': 'structure', 'members': {}, 'exception': True, } } } self.service_model = ServiceModel(self.model) self.exceptions_factory = ClientExceptionsFactory() def test_class_name(self): exceptions = self.exceptions_factory.create_client_exceptions( self.service_model) self.assertEqual(exceptions.__class__.__name__, 'MyServiceExceptions') def test_creates_modeled_exception(self): exceptions = self.exceptions_factory.create_client_exceptions( self.service_model) self.assertTrue(hasattr(exceptions, 'ExceptionWithModeledCode')) modeled_exception = exceptions.ExceptionWithModeledCode self.assertEqual(modeled_exception.__name__, 'ExceptionWithModeledCode') self.assertTrue(issubclass(modeled_exception, ClientError)) def test_collects_modeled_exceptions_for_all_operations(self): exceptions = self.exceptions_factory.create_client_exceptions( self.service_model) # Make sure exceptions were added for all operations by checking # an exception only found on an a different operation. self.assertTrue(hasattr(exceptions, 'ExceptionForAnotherOperation')) modeled_exception = exceptions.ExceptionForAnotherOperation self.assertEqual(modeled_exception.__name__, 'ExceptionForAnotherOperation') self.assertTrue(issubclass(modeled_exception, ClientError)) def test_creates_modeled_exception_mapping_that_has_code(self): exceptions = self.exceptions_factory.create_client_exceptions( self.service_model) exception = exceptions.from_code('ModeledCode') self.assertEqual(exception.__name__, 'ExceptionWithModeledCode') self.assertTrue(issubclass(exception, ClientError)) def test_creates_modeled_exception_mapping_that_has_no_code(self): exceptions = self.exceptions_factory.create_client_exceptions( self.service_model) # For exceptions that do not have an explicit code associated to them, # the code is the name of the exception. exception = exceptions.from_code('ExceptionMissingCode') self.assertEqual(exception.__name__, 'ExceptionMissingCode') self.assertTrue(issubclass(exception, ClientError))
class TestClientExceptionsFactory(unittest.TestCase): def setUp(self): self.model = { "metadata": { 'endpointPrefix': 'myservice', 'serviceFullName': 'MyService', }, 'operations': { 'OperationName': { 'name': 'OperationName', 'errors': [ {'shape': 'ExceptionMissingCode'}, {'shape': 'ExceptionWithModeledCode'}, ], }, 'AnotherOperationName': { 'name': 'AnotherOperationName', 'errors': [ {'shape': 'ExceptionForAnotherOperation'}, {'shape': 'ExceptionWithModeledCode'}, ], } }, 'shapes': { 'ExceptionWithModeledCode': { 'type': 'structure', 'members': {}, 'error': { 'code': 'ModeledCode' }, 'exception': True, }, 'ExceptionMissingCode': { 'type': 'structure', 'members': {}, 'exception': True, }, 'ExceptionForAnotherOperation': { 'type': 'structure', 'members': {}, 'exception': True, } } } self.service_model = ServiceModel(self.model) self.exceptions_factory = ClientExceptionsFactory() def test_class_name(self): exceptions = self.exceptions_factory.create_client_exceptions( self.service_model) self.assertEqual(exceptions.__class__.__name__, 'MyServiceExceptions') def test_creates_modeled_exception(self): exceptions = self.exceptions_factory.create_client_exceptions( self.service_model) self.assertTrue(hasattr(exceptions, 'ExceptionWithModeledCode')) modeled_exception = exceptions.ExceptionWithModeledCode self.assertEqual( modeled_exception.__name__, 'ExceptionWithModeledCode') self.assertTrue(issubclass(modeled_exception, ClientError)) def test_collects_modeled_exceptions_for_all_operations(self): exceptions = self.exceptions_factory.create_client_exceptions( self.service_model) # Make sure exceptions were added for all operations by checking # an exception only found on an a different operation. self.assertTrue(hasattr(exceptions, 'ExceptionForAnotherOperation')) modeled_exception = exceptions.ExceptionForAnotherOperation self.assertEqual( modeled_exception.__name__, 'ExceptionForAnotherOperation') self.assertTrue(issubclass(modeled_exception, ClientError)) def test_creates_modeled_exception_mapping_that_has_code(self): exceptions = self.exceptions_factory.create_client_exceptions( self.service_model) exception = exceptions.from_code('ModeledCode') self.assertEqual(exception.__name__, 'ExceptionWithModeledCode') self.assertTrue(issubclass(exception, ClientError)) def test_creates_modeled_exception_mapping_that_has_no_code(self): exceptions = self.exceptions_factory.create_client_exceptions( self.service_model) # For exceptions that do not have an explicit code associated to them, # the code is the name of the exception. exception = exceptions.from_code('ExceptionMissingCode') self.assertEqual(exception.__name__, 'ExceptionMissingCode') self.assertTrue(issubclass(exception, ClientError))
def parse_client(session: Session, service_name: ServiceName, shape_parser: ShapeParser) -> Client: """ Parse boto3 client to a structure. Arguments: session -- boto3 session. service_name -- Target service name. Returns: Client structure. """ client = get_boto3_client(session, service_name) public_methods = get_public_methods(client) # remove methods that will be overriden if "get_paginator" in public_methods: del public_methods["get_paginator"] if "get_waiter" in public_methods: del public_methods["get_waiter"] result = Client( name=f"{service_name.class_name}Client", service_name=service_name, boto3_client=client, docstring=(f"[{service_name.class_name}.Client documentation]" f"({service_name.doc_link}.Client)"), ) shape_method_map = shape_parser.get_client_method_map() for method_name, public_method in public_methods.items(): if method_name in shape_method_map: method = shape_method_map[method_name] else: method = parse_method("Client", method_name, public_method, service_name) method.docstring = (f"[Client.{method_name} documentation]" f"({service_name.doc_link}.Client.{method_name})") result.methods.append(method) service_model = client.meta.service_model client_exceptions = ClientExceptionsFactory().create_client_exceptions( service_model) for exception_class_name in dir(client_exceptions): if exception_class_name.startswith("_"): continue if not exception_class_name[0].isupper(): continue result.exceptions_class.attributes.append( Attribute( exception_class_name, TypeSubscript( Type.Type, [TypeClass(ClientError, alias="Boto3ClientError")]), )) result.attributes.append( Attribute( "exceptions", InternalImport( name=result.exceptions_class.name, module_name=ServiceModuleName.client, service_name=service_name, stringify=False, ), )) return result