def test_clients_inherit_handlers_from_session(self): # Even though clients get their own event emitters, they still # inherit any handlers that were registered on the event emitter # at the time the client was created. event_emitter = hooks.HierarchicalEmitter() creator = self.create_client_creator(event_emitter=event_emitter) # So if an event handler is registered before any clients are created: base_calls = [] base_handler = lambda **kwargs: base_calls.append(kwargs) event_emitter.register('before-call', base_handler) # Then any client created from this point forward from the # event_emitter passed into the ClientCreator will have this # handler. first_client = creator.create_client('myservice', 'us-west-2', credentials=self.credentials) first_client.test_operation(Foo='one', Bar='two') self.assertEqual(len(base_calls), 1) # Same thing if we create another client. second_client = creator.create_client('myservice', 'us-west-2', credentials=self.credentials) second_client.test_operation(Foo='one', Bar='two') self.assertEqual(len(base_calls), 2)
def test_client_method_called_event(self): event_emitter = hooks.HierarchicalEmitter() def inject_params(params, **kwargs): new_params = params.copy() new_params['Foo'] = 'zero' return new_params event_emitter.register('provide-client-params.myservice.TestOperation', inject_params) wrapped_emitter = mock.Mock(wraps=event_emitter) creator = self.create_client_creator(event_emitter=wrapped_emitter) service_client = creator.create_client('myservice', 'us-west-2', credentials=self.credentials) params = {'Foo': 'one', 'Bar': 'two'} service_client.test_operation(**params) # Ensure that the initial params were not modified in the handler self.assertEqual(params, {'Foo': 'one', 'Bar': 'two'}) # Ensure the handler passed on the correct param values. body = self.endpoint.make_request.call_args[0][1]['body'] self.assertEqual(body['Foo'], 'zero')
def create_client_creator(self, endpoint_creator=None, event_emitter=None, retry_handler_factory=None, retry_config_translator=None, response_parser_factory=None): if event_emitter is None: event_emitter = hooks.HierarchicalEmitter() if retry_handler_factory is None: retry_handler_factory = botocore.retryhandler if retry_config_translator is None: retry_config_translator = botocore.translate endpoint_resolver = mock.Mock() endpoint_resolver.construct_endpoint.return_value = { 'properties': {}, 'uri': 'http://foo' } if endpoint_creator is not None: self.endpoint_creator_cls.return_value = endpoint_creator creator = client.ClientCreator(self.loader, endpoint_resolver, 'user-agent', event_emitter, retry_handler_factory, retry_config_translator, response_parser_factory) return creator
def test_events_are_per_client(self): event_emitter = hooks.HierarchicalEmitter() creator = self.create_client_creator(event_emitter=event_emitter) first_calls = [] first_handler = lambda **kwargs: first_calls.append(kwargs) second_calls = [] second_handler = lambda **kwargs: second_calls.append(kwargs) first_client = creator.create_client('myservice', 'us-west-2', credentials=self.credentials) second_client = creator.create_client('myservice', 'us-west-2', credentials=self.credentials) first_client.meta.events.register('before-call', first_handler) second_client.meta.events.register('before-call', second_handler) # Now, if we invoke an operation from either client, only # the handlers registered with the specific client will be invoked. # So if we invoke the first client. first_client.test_operation(Foo='one', Bar='two') # Only first_calls is populated, not second_calls. self.assertEqual(len(first_calls), 1) self.assertEqual(len(second_calls), 0) # If we invoke an operation from the second client, # only second_calls will be populated, not first_calls. second_client.test_operation(Foo='one', Bar='two') # first_calls == 1 from the previous first_client.test_operation() # call. self.assertEqual(len(first_calls), 1) self.assertEqual(len(second_calls), 1)
def setUp(self): self.event_emitter = hooks.HierarchicalEmitter() self.client = mock.Mock() self.client.meta.events = self.event_emitter self.client.meta.method_to_api_mapping.get.return_value = 'foo' self.stubber = Stubber(self.client) self.validate_parameters_mock = mock.Mock() self.validate_parameters_patch = mock.patch( 'botocore.stub.validate_parameters', self.validate_parameters_mock) self.validate_parameters_patch.start()
def render_operation(self): # try and reuse botocore's sphinx doc infrastructure. method_doc = ClientMethodDocstring( operation_model=self.op, method_name=self.op.name, event_emitter=hooks.HierarchicalEmitter(), method_description=self.op.documentation, example_prefix="client.%s" % xform_name(self.op.name), include_signature=False, ) return self._render_docutils(method_doc)
def create_client_creator(self, endpoint_creator=None, event_emitter=None, response_parser_factory=None): if endpoint_creator is None: endpoint_creator = mock.Mock() if event_emitter is None: event_emitter = hooks.HierarchicalEmitter() creator = client.ClientCreator(self.loader, endpoint_creator, event_emitter, response_parser_factory) return creator
def test_event_emitted_when_invoked(self): event_emitter = hooks.HierarchicalEmitter() creator = self.create_client_creator(event_emitter=event_emitter) calls = [] handler = lambda **kwargs: calls.append(kwargs) event_emitter.register('before-call', handler) service_client = creator.create_client( 'myservice', 'us-west-2', credentials=self.credentials) service_client.test_operation(Foo='one', Bar='two') self.assertEqual(len(calls), 1)
def test_event_emitted_when_invoked(self): event_emitter = hooks.HierarchicalEmitter() endpoint_creator = mock.Mock() endpoint = mock.Mock() endpoint_creator.create_endpoint.return_value = endpoint endpoint.make_request.return_value = (mock.Mock(status_code=200), {}) creator = self.create_client_creator(endpoint_creator, event_emitter) calls = [] handler = lambda **kwargs: calls.append(kwargs) event_emitter.register('before-call', handler) service_client = creator.create_client('myservice', 'us-west-2') service_client.test_operation(Foo='one', Bar='two') self.assertEqual(len(calls), 1)
def create_client_creator(self, endpoint_creator=None, event_emitter=None, response_parser_factory=None): if endpoint_creator is None: endpoint_creator = mock.Mock() endpoint = mock.Mock() endpoint_creator.create_endpoint.return_value = endpoint endpoint.make_request.return_value = (mock.Mock(status_code=200), {}) if event_emitter is None: event_emitter = hooks.HierarchicalEmitter() creator = client.ClientCreator(self.loader, endpoint_creator, event_emitter, response_parser_factory) return creator
def test_client_created_emits_events(self): called = [] def on_client_create(class_attributes, **kwargs): called.append(class_attributes) event_emitter = hooks.HierarchicalEmitter() event_emitter.register('creating-client-class', on_client_create) creator = self.create_client_creator(event_emitter=event_emitter) creator.create_client('myservice', 'us-west-2', credentials=self.credentials) self.assertEqual(len(called), 1) self.assertIn('test_operation', called[0])
def render_operation(self, service_change, op_name): # try and reuse botocore's sphinx doc infrastructure. m = self._get_service_model(service_change) if m is None: log.error("couldnt find model %s", service_change) return "" opm = m.operation_model(op_name) method_doc = ClientMethodDocstring( operation_model=opm, method_name=opm.name, event_emitter=hooks.HierarchicalEmitter(), method_description=opm.documentation, example_prefix="client.%s" % xform_name(opm.name), include_signature=False, ) return self._render_docutils(method_doc)
def test_clients_inherit_only_at_create_time(self): # If event handlers are added to the copied event emitter # _after_ a client is created, we don't pick those up. event_emitter = hooks.HierarchicalEmitter() creator = self.create_client_creator(event_emitter=event_emitter) # 1. Create a client. first_client = creator.create_client('myservice', 'us-west-2') # 2. Now register an event handler from the originating event emitter. base_calls = [] base_handler = lambda **kwargs: base_calls.append(kwargs) event_emitter.register('before-call', base_handler) # 3. The client will _not_ see this because it already has its # own copy of the event handlers. first_client.test_operation(Foo='one', Bar='two') self.assertEqual(len(base_calls), 0)
def create_client_creator(self, endpoint_creator=None, event_emitter=None, retry_handler_factory=None, retry_config_translator=None, response_parser_factory=None): if event_emitter is None: event_emitter = hooks.HierarchicalEmitter() if retry_handler_factory is None: retry_handler_factory = botocore.retryhandler if retry_config_translator is None: retry_config_translator = botocore.translate if endpoint_creator is not None: self.endpoint_creator_cls.return_value = endpoint_creator creator = client.ClientCreator(self.loader, self.resolver, 'user-agent', event_emitter, retry_handler_factory, retry_config_translator, response_parser_factory) return creator
def test_client_can_be_cloned(self): # Even though we're verifying that clone_client() works, we want # to avoid testing internal attributes. # Instead we try to test this via the public API: # - Cloning the API with a new endpoint will use the new endopint. event_emitter = hooks.HierarchicalEmitter() creator = self.create_client_creator(event_emitter=event_emitter) new_endpoint = mock.Mock() new_endpoint.make_request.return_value = (mock.Mock(status_code=200), { 'type': 'from-replaced-endpoint' }) service_client = creator.create_client('myservice', 'us-west-2', credentials=self.credentials) cloned = service_client.clone_client(endpoint=new_endpoint) response = cloned.test_operation(Foo='one', Bar='two') self.assertEqual(response['type'], 'from-replaced-endpoint')
def test_client_register_seperate_unique_id_event(self): event_emitter = hooks.HierarchicalEmitter() creator = self.create_client_creator(event_emitter=event_emitter) client1 = creator.create_client('myservice', 'us-west-2') client2 = creator.create_client('myservice', 'us-west-2') def ping(**kwargs): return 'foo' client1.meta.events.register('some-event', ping, 'my-unique-id') client2.meta.events.register('some-event', ping, 'my-unique-id') # Ensure both clients can register a function with an unique id client1_responses = client1.meta.events.emit('some-event') self.assertEqual(len(client1_responses), 1) self.assertEqual(client1_responses[0][1], 'foo') client2_responses = client2.meta.events.emit('some-event') self.assertEqual(len(client2_responses), 1) self.assertEqual(client2_responses[0][1], 'foo') # Ensure when a client is unregistered the other client has # the unique-id event still registered. client1.meta.events.unregister('some-event', ping, 'my-unique-id') client1_responses = client1.meta.events.emit('some-event') self.assertEqual(len(client1_responses), 0) client2_responses = client2.meta.events.emit('some-event') self.assertEqual(len(client2_responses), 1) self.assertEqual(client2_responses[0][1], 'foo') # Ensure that the other client can unregister the event client2.meta.events.unregister('some-event', ping, 'my-unique-id') client2_responses = client2.meta.events.emit('some-event') self.assertEqual(len(client2_responses), 0)