def _make_api_call(self, operation_name, operation_kwargs):
    "\n        This private method is here for two reasons:\n        1. It's faster to avoid using botocore's response parsing\n        2. It provides a place to monkey patch requests for unit testing\n        "
    operation_model = self.client._service_model.operation_model(operation_name)
    request_dict = self.client._convert_to_request_dict(operation_kwargs, operation_model)
    prepared_request = self._create_prepared_request(request_dict, operation_model)
    for i in range(0, (self._max_retry_attempts_exception + 1)):
        attempt_number = (i + 1)
        is_last_attempt_for_exceptions = (i == self._max_retry_attempts_exception)
        try:
            response = self.requests_session.send(prepared_request, timeout=self._request_timeout_seconds, proxies=self.client._endpoint.proxies)
            data = response.json()
        except (requests.RequestException, ValueError) as e:
            if is_last_attempt_for_exceptions:
                log.debug('Reached the maximum number of retry attempts: %s', attempt_number)
                raise
            else:
                log.debug('Retry needed for (%s) after attempt %s, retryable %s caught: %s', operation_name, attempt_number, e.__class__.__name__, e)
                continue
        if (response.status_code >= 300):
            code = data.get('__type', '')
            if ('#' in code):
                code = code.rsplit('#', 1)[1]
            botocore_expected_format = {'Error': {'Message': data.get('message', ''), 'Code': code}}
            verbose_properties = {'request_id': response.headers.get('x-amzn-RequestId')}
            if ('RequestItems' in operation_kwargs):
                verbose_properties['table_name'] = ','.join(operation_kwargs['RequestItems'])
            else:
                verbose_properties['table_name'] = operation_kwargs.get('TableName')
            try:
                raise VerboseClientError(botocore_expected_format, operation_name, verbose_properties)
            except VerboseClientError as e:
                if is_last_attempt_for_exceptions:
                    log.debug('Reached the maximum number of retry attempts: %s', attempt_number)
                    raise
                elif ((response.status_code < 500) and (code != 'ProvisionedThroughputExceededException')):
                    raise
                else:
                    sleep_time_ms = random.randint(0, (self._base_backoff_ms * (2 ** i)))
                    log.debug('Retry with backoff needed for (%s) after attempt %s,sleeping for %s milliseconds, retryable %s caught: %s', operation_name, attempt_number, sleep_time_ms, e.__class__.__name__, e)
                    time.sleep((sleep_time_ms / 1000.0))
                    continue
        return self._handle_binary_attributes(data)
This private method is here for two reasons:
1. It's faster to avoid using botocore's response parsing
2. It provides a place to monkey patch requests for unit testing
def _make_api_call(self, operation_name, operation_kwargs):
    "\n        This private method is here for two reasons:\n        1. It's faster to avoid using botocore's response parsing\n        2. It provides a place to monkey patch requests for unit testing\n        "
    operation_model = self.client._service_model.operation_model(operation_name)
    request_dict = self.client._convert_to_request_dict(operation_kwargs, operation_model)
    prepared_request = self._create_prepared_request(request_dict, operation_model)
    for i in range(0, (self._max_retry_attempts_exception + 1)):
        attempt_number = (i + 1)
        is_last_attempt_for_exceptions = (i == self._max_retry_attempts_exception)
        try:
            response = self.requests_session.send(prepared_request, timeout=self._request_timeout_seconds, proxies=self.client._endpoint.proxies)
            data = response.json()
        except (requests.RequestException, ValueError) as e:
            if is_last_attempt_for_exceptions:
                log.debug('Reached the maximum number of retry attempts: %s', attempt_number)
                raise
            else:
                log.debug('Retry needed for (%s) after attempt %s, retryable %s caught: %s', operation_name, attempt_number, e.__class__.__name__, e)
                continue
        if (response.status_code >= 300):
            code = data.get('__type', )
            if ('#' in code):
                code = code.rsplit('#', 1)[1]
            botocore_expected_format = {'Error': {'Message': data.get('message', ), 'Code': code}}
            verbose_properties = {'request_id': response.headers.get('x-amzn-RequestId')}
            if ('RequestItems' in operation_kwargs):
                verbose_properties['table_name'] = ','.join(operation_kwargs['RequestItems'])
            else:
                verbose_properties['table_name'] = operation_kwargs.get('TableName')
            try:
                raise VerboseClientError(botocore_expected_format, operation_name, verbose_properties)
            except VerboseClientError as e:
                if is_last_attempt_for_exceptions:
                    log.debug('Reached the maximum number of retry attempts: %s', attempt_number)
                    raise
                elif ((response.status_code < 500) and (code != 'ProvisionedThroughputExceededException')):
                    raise
                else:
                    sleep_time_ms = random.randint(0, (self._base_backoff_ms * (2 ** i)))
                    log.debug('Retry with backoff needed for (%s) after attempt %s,sleeping for %s milliseconds, retryable %s caught: %s', operation_name, attempt_number, sleep_time_ms, e.__class__.__name__, e)
                    time.sleep((sleep_time_ms / 1000.0))
                    continue
        return self._handle_binary_attributes(data)