# Path: aiobotocore/utils.py
# RETRYABLE_HTTP_ERRORS = (aiohttp.client_exceptions.ClientError, asyncio.TimeoutError)
# class AioIMDSFetcher(IMDSFetcher):
#     class Response(object):
# class AioInstanceMetadataFetcher(AioIMDSFetcher, InstanceMetadataFetcher):
# class AioS3RegionRedirector(S3RegionRedirector):
# class AioContainerMetadataFetcher(ContainerMetadataFetcher):
#         def __init__(self, status_code, text, url):
#     def __init__(self, *args, session=None, **kwargs):
#     async def _fetch_metadata_token(self):
#     async def _get_request(self, url_path, retry_func, token=None):
#     async def retrieve_iam_role_credentials(self):
#     async def _get_iam_role(self, token=None):
#     async def _get_credentials(self, role_name, token=None):
#     async def redirect_from_error(self, request_dict, response, operation, **kwargs):
#     async def get_bucket_region(self, bucket, response):
#     def __init__(self, session=None, sleep=asyncio.sleep):
#     async def retrieve_full_uri(self, full_url, headers=None):
#     async def retrieve_uri(self, relative_uri):
#     async def _retrieve_credentials(self, full_url, extra_headers=None):
#     async def _get_response(self, full_url, headers, timeout):
# 
# Path: aiobotocore/utils.py
# class AioInstanceMetadataFetcher(AioIMDSFetcher, InstanceMetadataFetcher):
#     async def retrieve_iam_role_credentials(self):
#         try:
#             token = await self._fetch_metadata_token()
#             role_name = await self._get_iam_role(token)
#             credentials = await self._get_credentials(role_name, token)
#             if self._contains_all_credential_fields(credentials):
#                 return {
#                     'role_name': role_name,
#                     'access_key': credentials['AccessKeyId'],
#                     'secret_key': credentials['SecretAccessKey'],
#                     'token': credentials['Token'],
#                     'expiry_time': credentials['Expiration'],
#                 }
#             else:
#                 if 'Code' in credentials and 'Message' in credentials:
#                     logger.debug('Error response received when retrieving'
#                                  'credentials: %s.', credentials)
#                 return {}
#         except self._RETRIES_EXCEEDED_ERROR_CLS:
#             logger.debug("Max number of attempts exceeded (%s) when "
#                          "attempting to retrieve data from metadata service.",
#                          self._num_attempts)
#         except BadIMDSRequestError as e:
#             logger.debug("Bad IMDS request: %s", e.request)
#         return {}
# 
#     async def _get_iam_role(self, token=None):
#         r = await self._get_request(
#             url_path=self._URL_PATH,
#             retry_func=self._needs_retry_for_role_name,
#             token=token
#         )
#         return r.text
# 
#     async def _get_credentials(self, role_name, token=None):
#         r = await self._get_request(
#             url_path=self._URL_PATH + role_name,
#             retry_func=self._needs_retry_for_credentials,
#             token=token
#         )
#         return json.loads(r.text)


import asyncio
import pytest
import json
import itertools
import unittest
import yarl
from unittest import mock
from typing import Union, List, Tuple
from aiohttp.client_reqrep import ClientResponse, RequestInfo
from aiohttp.helpers import TimerNoop
from aiohttp.client_exceptions import ClientConnectionError
from aiobotocore import utils
from aiobotocore.utils import AioInstanceMetadataFetcher
from botocore.utils import MetadataRetrievalError, BadIMDSRequestError
        self.add_get_token_imds_response(token='token')
        self.add_imds_response(body=b'')
        self.add_get_role_name_imds_response()
        self.add_get_credentials_imds_response()
        result = await AioInstanceMetadataFetcher(
            num_attempts=2).retrieve_iam_role_credentials()
        self.assertEqual(result, self._expected_creds)

    @pytest.mark.moto
    @pytest.mark.asyncio
    async def test_non_200_response_is_retried(self):
        self.add_get_token_imds_response(token='token')
        self.add_get_role_name_imds_response()
        # Response for creds that has a 200 status code but has an empty
        # body should be retried.
        self.add_imds_response(
            status_code=429, body=b'{"message": "Slow down"}')
        self.add_get_credentials_imds_response()
        result = await AioInstanceMetadataFetcher(
            num_attempts=2).retrieve_iam_role_credentials()
        self.assertEqual(result, self._expected_creds)

    @pytest.mark.moto
    @pytest.mark.asyncio
    async def test_http_connection_errors_is_retried(self):
        self.add_get_token_imds_response(token='token')
        self.add_get_role_name_imds_response()
        # Connection related errors should be retried
        self.add_imds_connection_error(ClientConnectionError(''))
        self.add_get_credentials_imds_response()

# Path: aiobotocore/utils.py
# RETRYABLE_HTTP_ERRORS = (aiohttp.client_exceptions.ClientError, asyncio.TimeoutError)
# class AioIMDSFetcher(IMDSFetcher):
#     class Response(object):
# class AioInstanceMetadataFetcher(AioIMDSFetcher, InstanceMetadataFetcher):
# class AioS3RegionRedirector(S3RegionRedirector):
# class AioContainerMetadataFetcher(ContainerMetadataFetcher):
#         def __init__(self, status_code, text, url):
#     def __init__(self, *args, session=None, **kwargs):
#     async def _fetch_metadata_token(self):
#     async def _get_request(self, url_path, retry_func, token=None):
#     async def retrieve_iam_role_credentials(self):
#     async def _get_iam_role(self, token=None):
#     async def _get_credentials(self, role_name, token=None):
#     async def redirect_from_error(self, request_dict, response, operation, **kwargs):
#     async def get_bucket_region(self, bucket, response):
#     def __init__(self, session=None, sleep=asyncio.sleep):
#     async def retrieve_full_uri(self, full_url, headers=None):
#     async def retrieve_uri(self, relative_uri):
#     async def _retrieve_credentials(self, full_url, extra_headers=None):
#     async def _get_response(self, full_url, headers, timeout):
# 
# Path: aiobotocore/utils.py
# class AioInstanceMetadataFetcher(AioIMDSFetcher, InstanceMetadataFetcher):
#     async def retrieve_iam_role_credentials(self):
#         try:
#             token = await self._fetch_metadata_token()
#             role_name = await self._get_iam_role(token)
#             credentials = await self._get_credentials(role_name, token)
#             if self._contains_all_credential_fields(credentials):
#                 return {
#                     'role_name': role_name,
#                     'access_key': credentials['AccessKeyId'],
#                     'secret_key': credentials['SecretAccessKey'],
#                     'token': credentials['Token'],
#                     'expiry_time': credentials['Expiration'],
#                 }
#             else:
#                 if 'Code' in credentials and 'Message' in credentials:
#                     logger.debug('Error response received when retrieving'
#                                  'credentials: %s.', credentials)
#                 return {}
#         except self._RETRIES_EXCEEDED_ERROR_CLS:
#             logger.debug("Max number of attempts exceeded (%s) when "
#                          "attempting to retrieve data from metadata service.",
#                          self._num_attempts)
#         except BadIMDSRequestError as e:
#             logger.debug("Bad IMDS request: %s", e.request)
#         return {}
# 
#     async def _get_iam_role(self, token=None):
#         r = await self._get_request(
#             url_path=self._URL_PATH,
#             retry_func=self._needs_retry_for_role_name,
#             token=token
#         )
#         return r.text
# 
#     async def _get_credentials(self, role_name, token=None):
#         r = await self._get_request(
#             url_path=self._URL_PATH + role_name,
#             retry_func=self._needs_retry_for_credentials,
#             token=token
#         )
#         return json.loads(r.text)


# Path: tests/botocore/test_utils.py
import asyncio
import pytest
import json
import itertools
import unittest
import yarl
from unittest import mock
from typing import Union, List, Tuple
from aiohttp.client_reqrep import ClientResponse, RequestInfo
from aiohttp.helpers import TimerNoop
from aiohttp.client_exceptions import ClientConnectionError
from aiobotocore import utils
from aiobotocore.utils import AioInstanceMetadataFetcher
from botocore.utils import MetadataRetrievalError, BadIMDSRequestError

        self.add_get_token_imds_response(token='token')
        self.add_imds_response(body=b'')
        self.add_get_role_name_imds_response()
        self.add_get_credentials_imds_response()
        result = await AioInstanceMetadataFetcher(
            num_attempts=2).retrieve_iam_role_credentials()
        self.assertEqual(result, self._expected_creds)

    @pytest.mark.moto
    @pytest.mark.asyncio
    async def test_non_200_response_is_retried(self):
        self.add_get_token_imds_response(token='token')
        self.add_get_role_name_imds_response()
        # Response for creds that has a 200 status code but has an empty
        # body should be retried.
        self.add_imds_response(
            status_code=429, body=b'{"message": "Slow down"}')
        self.add_get_credentials_imds_response()
        result = await AioInstanceMetadataFetcher(
            num_attempts=2).retrieve_iam_role_credentials()
        self.assertEqual(result, self._expected_creds)

    @pytest.mark.moto
    @pytest.mark.asyncio
    async def test_http_connection_errors_is_retried(self):
        self.add_get_token_imds_response(token='token')
        self.add_get_role_name_imds_response()
        # Connection related errors should be retried
        self.add_imds_connection_error(ClientConnectionError(''))
        self.add_get_credentials_imds_response()

        result = await AioInstanceMetadataFetcher(