# Path: ingenico/connect/sdk/pooled_connection.py
# class PooledConnection(Connection):
#     """
#     Represents a pooled connection to the Ingenico ePayments platform server.
#     Instead of setting up a new HTTP connection for each request, this
#     connection uses a pool of HTTP connections.
#     """
# 
#     def close_idle_connections(self, idle_time):
#         """
#         Closes all HTTP connections that have been idle for the specified time.
#         This should also include all expired HTTP connections.
# 
#         :param idle_time: a datetime.timedelta object indicating the idle time
#         """
#         raise NotImplementedError
# 
#     def close_expired_connections(self):
#         """
#         Closes all expired HTTP connections.
#         """
#         raise NotImplementedError
# 
# Path: ingenico/connect/sdk/request_header.py
# class RequestHeader:
#     """
#     A single request header. Immutable.
#     """
# 
#     def __init__(self, name, value):
#         if name is None or not name.strip():
#             raise ValueError("name is required")
#         self.__name = name
#         self.__value = value
# 
#     @property
#     def name(self):
#         """
#         :return: The header name.
#         """
#         return self.__name
# 
#     @property
#     def value(self):
#         """
#         :return: The un-encoded value.
#         """
#         return self.__value.decode('utf-8') if isinstance(self.__value, bytes) else self.__value
# 
#     def __str__(self):
#         return self.__name + ":" + str(self.__value)
# 
# Path: ingenico/connect/sdk/response_exception.py
# class ResponseException(RuntimeError):
#     """
#     Thrown when a response was received from the Ingenico ePayments platform which
#     indicates an error.
#     """
# 
#     def __init__(self, status, body, headers):
#         super(ResponseException, self).__init__(
#             "the Ingenico ePayments platform returned an error response")
#         self.__status_code = status
#         self.__headers = headers if headers is not None else {}
#         self.__body = body
# 
#     @property
#     def status_code(self):
#         """
#         :return: The HTTP status code that was returned by the Ingenico ePayments
#          platform.
#         """
#         return self.__status_code
# 
#     @property
#     def body(self):
#         """
#         :return: The raw response body that was returned by the Ingenico ePayments
#          platform.
#         """
#         return self.__body
# 
#     @property
#     def headers(self):
#         """
#         :return: The headers that were returned by the Ingenico ePayments platform.
#          Never None.
#         """
#         return self.__headers
# 
#     def get_header(self, header_name):
#         """
#         :return: The header with the given name, or None if there was no such
#          header.
#         """
#         return get_header(self.__headers, header_name)
# 
#     def get_header_value(self, header_name):
#         """
#         :return: The value header with the given name, or None if there was no
#          such header.
#         """
#         return get_header_value(self.__headers, header_name)
# 
#     def __str__(self):
#         string = super(ResponseException, self).__str__()
#         status_code = self.__status_code
#         if status_code > 0:
#             string += "; status_code=" + str(status_code)
#         response_body = self.__body
#         if response_body:
#             string += "; response_body='" + response_body + "'"
#         return str(string)
# 
# Path: ingenico/connect/sdk/response_header.py
# def get_header_value(headers, header_name):
#     """
#     :return: The value of the header with the given name, or None if there
#      was no such header.
#     """
#     if headers is None:
#         return None
#     for name, value in headers.items():
#         if name.lower() == header_name.lower():
#             return value
#     return None


from datetime import datetime
from urllib.parse import quote
from urllib.parse import urlparse
from .communication_exception import CommunicationException
from ingenico.connect.sdk.log.logging_capable import LoggingCapable
from .not_found_exception import NotFoundException
from .pooled_connection import PooledConnection
from .multipart_form_data_object import MultipartFormDataObject
from .multipart_form_data_request import MultipartFormDataRequest
from .request_header import RequestHeader
from .response_exception import ResponseException
from .response_header import get_header_value
                    flag = True
                else:
                    uri += "&"
                uri += quote(nvp.name) + "=" + quote(nvp.value)
        # no need to revalidate that uri has a valid scheme and netloc
        return urlparse(uri)

    def _add_generic_headers(self, http_method, uri, request_headers, context):
        """
        Adds the necessary headers to the given list of headers. This includes
        the authorization header, which uses other headers, so when you need to
        override this method, make sure to call super.addGenericHeaders at the
        end of your overridden method.
        """
        # add server meta info header
        request_headers.extend(
            self.__session.meta_data_provider.meta_data_headers)
        # add date header
        request_headers.append(
            RequestHeader("Date", self._get_header_date_string()))
        if context is not None and context.idempotence_key is not None:
            # add context specific headers
            request_headers.append(
                RequestHeader("X-GCS-Idempotence-Key",
                              context.idempotence_key))
        # add signature
        authenticator = self.__session.authenticator
        authentication_signature = \
            authenticator.create_simple_authentication_signature(
                http_method, uri, request_headers)

# Path: ingenico/connect/sdk/pooled_connection.py
# class PooledConnection(Connection):
#     """
#     Represents a pooled connection to the Ingenico ePayments platform server.
#     Instead of setting up a new HTTP connection for each request, this
#     connection uses a pool of HTTP connections.
#     """
# 
#     def close_idle_connections(self, idle_time):
#         """
#         Closes all HTTP connections that have been idle for the specified time.
#         This should also include all expired HTTP connections.
# 
#         :param idle_time: a datetime.timedelta object indicating the idle time
#         """
#         raise NotImplementedError
# 
#     def close_expired_connections(self):
#         """
#         Closes all expired HTTP connections.
#         """
#         raise NotImplementedError
# 
# Path: ingenico/connect/sdk/request_header.py
# class RequestHeader:
#     """
#     A single request header. Immutable.
#     """
# 
#     def __init__(self, name, value):
#         if name is None or not name.strip():
#             raise ValueError("name is required")
#         self.__name = name
#         self.__value = value
# 
#     @property
#     def name(self):
#         """
#         :return: The header name.
#         """
#         return self.__name
# 
#     @property
#     def value(self):
#         """
#         :return: The un-encoded value.
#         """
#         return self.__value.decode('utf-8') if isinstance(self.__value, bytes) else self.__value
# 
#     def __str__(self):
#         return self.__name + ":" + str(self.__value)
# 
# Path: ingenico/connect/sdk/response_exception.py
# class ResponseException(RuntimeError):
#     """
#     Thrown when a response was received from the Ingenico ePayments platform which
#     indicates an error.
#     """
# 
#     def __init__(self, status, body, headers):
#         super(ResponseException, self).__init__(
#             "the Ingenico ePayments platform returned an error response")
#         self.__status_code = status
#         self.__headers = headers if headers is not None else {}
#         self.__body = body
# 
#     @property
#     def status_code(self):
#         """
#         :return: The HTTP status code that was returned by the Ingenico ePayments
#          platform.
#         """
#         return self.__status_code
# 
#     @property
#     def body(self):
#         """
#         :return: The raw response body that was returned by the Ingenico ePayments
#          platform.
#         """
#         return self.__body
# 
#     @property
#     def headers(self):
#         """
#         :return: The headers that were returned by the Ingenico ePayments platform.
#          Never None.
#         """
#         return self.__headers
# 
#     def get_header(self, header_name):
#         """
#         :return: The header with the given name, or None if there was no such
#          header.
#         """
#         return get_header(self.__headers, header_name)
# 
#     def get_header_value(self, header_name):
#         """
#         :return: The value header with the given name, or None if there was no
#          such header.
#         """
#         return get_header_value(self.__headers, header_name)
# 
#     def __str__(self):
#         string = super(ResponseException, self).__str__()
#         status_code = self.__status_code
#         if status_code > 0:
#             string += "; status_code=" + str(status_code)
#         response_body = self.__body
#         if response_body:
#             string += "; response_body='" + response_body + "'"
#         return str(string)
# 
# Path: ingenico/connect/sdk/response_header.py
# def get_header_value(headers, header_name):
#     """
#     :return: The value of the header with the given name, or None if there
#      was no such header.
#     """
#     if headers is None:
#         return None
#     for name, value in headers.items():
#         if name.lower() == header_name.lower():
#             return value
#     return None


# Path: ingenico/connect/sdk/communicator.py
from datetime import datetime
from urllib.parse import quote
from urllib.parse import urlparse
from .communication_exception import CommunicationException
from ingenico.connect.sdk.log.logging_capable import LoggingCapable
from .not_found_exception import NotFoundException
from .pooled_connection import PooledConnection
from .multipart_form_data_object import MultipartFormDataObject
from .multipart_form_data_request import MultipartFormDataRequest
from .request_header import RequestHeader
from .response_exception import ResponseException
from .response_header import get_header_value

                    flag = True
                else:
                    uri += "&"
                uri += quote(nvp.name) + "=" + quote(nvp.value)
        # no need to revalidate that uri has a valid scheme and netloc
        return urlparse(uri)

    def _add_generic_headers(self, http_method, uri, request_headers, context):
        """
        Adds the necessary headers to the given list of headers. This includes
        the authorization header, which uses other headers, so when you need to
        override this method, make sure to call super.addGenericHeaders at the
        end of your overridden method.
        """
        # add server meta info header
        request_headers.extend(
            self.__session.meta_data_provider.meta_data_headers)
        # add date header
        request_headers.append(
            RequestHeader("Date", self._get_header_date_string()))
        if context is not None and context.idempotence_key is not None:
            # add context specific headers
            request_headers.append(
                RequestHeader("X-GCS-Idempotence-Key",
                              context.idempotence_key))
        # add signature
        authenticator = self.__session.authenticator
        authentication_signature = \
            authenticator.create_simple_authentication_signature(
                http_method, uri, request_headers)

        request_headers.append(RequestHeader("Authorization",