# Path: s3transfer/compat.py
# MAXINT = None
# 
# Path: s3transfer/exceptions.py
# class RetriesExceededError(Exception):
# class S3UploadFailedError(Exception):
# class InvalidSubscriberMethodError(Exception):
# class TransferNotDoneError(Exception):
# class FatalError(CancelledError):
#     def __init__(self, last_exception, msg='Max Retries Exceeded'):
# 
# Path: s3transfer/utils.py
# class FunctionContainer:
#     """An object that contains a function and any args or kwargs to call it
# 
#     When called the provided function will be called with provided args
#     and kwargs.
#     """
# 
#     def __init__(self, func, *args, **kwargs):
#         self._func = func
#         self._args = args
#         self._kwargs = kwargs
# 
#     def __repr__(self):
#         return 'Function: {} with args {} and kwargs {}'.format(
#             self._func, self._args, self._kwargs
#         )
# 
#     def __call__(self):
#         return self._func(*self._args, **self._kwargs)
# 
# class TaskSemaphore:
#     def __init__(self, count):
#         """A semaphore for the purpose of limiting the number of tasks
# 
#         :param count: The size of semaphore
#         """
#         self._semaphore = threading.Semaphore(count)
# 
#     def acquire(self, tag, blocking=True):
#         """Acquire the semaphore
# 
#         :param tag: A tag identifying what is acquiring the semaphore. Note
#             that this is not really needed to directly use this class but is
#             needed for API compatibility with the SlidingWindowSemaphore
#             implementation.
#         :param block: If True, block until it can be acquired. If False,
#             do not block and raise an exception if cannot be acquired.
# 
#         :returns: A token (can be None) to use when releasing the semaphore
#         """
#         logger.debug("Acquiring %s", tag)
#         if not self._semaphore.acquire(blocking):
#             raise NoResourcesAvailable("Cannot acquire tag '%s'" % tag)
# 
#     def release(self, tag, acquire_token):
#         """Release the semaphore
# 
#         :param tag: A tag identifying what is releasing the semaphore
#         :param acquire_token:  The token returned from when the semaphore was
#             acquired. Note that this is not really needed to directly use this
#             class but is needed for API compatibility with the
#             SlidingWindowSemaphore implementation.
#         """
#         logger.debug(f"Releasing acquire {tag}/{acquire_token}")
#         self._semaphore.release()


import copy
import logging
import sys
import threading
from collections import namedtuple
from concurrent import futures
from s3transfer.compat import MAXINT
from s3transfer.exceptions import CancelledError, TransferNotDoneError
from s3transfer.utils import FunctionContainer, TaskSemaphore

    def done(self):
        """Determines if a TransferFuture has completed

        :returns: False if status is equal to 'failed', 'cancelled', or
            'success'. True, otherwise
        """
        return self.status in ['failed', 'cancelled', 'success']

    def add_associated_future(self, future):
        """Adds a future to be associated with the TransferFuture"""
        with self._associated_futures_lock:
            self._associated_futures.add(future)

    def remove_associated_future(self, future):
        """Removes a future's association to the TransferFuture"""
        with self._associated_futures_lock:
            self._associated_futures.remove(future)

    def add_done_callback(self, function, *args, **kwargs):
        """Add a done callback to be invoked when transfer is done"""
        with self._done_callbacks_lock:
            self._done_callbacks.append(
                FunctionContainer(function, *args, **kwargs)
            )

    def add_failure_cleanup(self, function, *args, **kwargs):
        """Adds a callback to call upon failure"""
        with self._failure_cleanups_lock:
            self._failure_cleanups.append(

# Path: s3transfer/compat.py
# MAXINT = None
# 
# Path: s3transfer/exceptions.py
# class RetriesExceededError(Exception):
# class S3UploadFailedError(Exception):
# class InvalidSubscriberMethodError(Exception):
# class TransferNotDoneError(Exception):
# class FatalError(CancelledError):
#     def __init__(self, last_exception, msg='Max Retries Exceeded'):
# 
# Path: s3transfer/utils.py
# class FunctionContainer:
#     """An object that contains a function and any args or kwargs to call it
# 
#     When called the provided function will be called with provided args
#     and kwargs.
#     """
# 
#     def __init__(self, func, *args, **kwargs):
#         self._func = func
#         self._args = args
#         self._kwargs = kwargs
# 
#     def __repr__(self):
#         return 'Function: {} with args {} and kwargs {}'.format(
#             self._func, self._args, self._kwargs
#         )
# 
#     def __call__(self):
#         return self._func(*self._args, **self._kwargs)
# 
# class TaskSemaphore:
#     def __init__(self, count):
#         """A semaphore for the purpose of limiting the number of tasks
# 
#         :param count: The size of semaphore
#         """
#         self._semaphore = threading.Semaphore(count)
# 
#     def acquire(self, tag, blocking=True):
#         """Acquire the semaphore
# 
#         :param tag: A tag identifying what is acquiring the semaphore. Note
#             that this is not really needed to directly use this class but is
#             needed for API compatibility with the SlidingWindowSemaphore
#             implementation.
#         :param block: If True, block until it can be acquired. If False,
#             do not block and raise an exception if cannot be acquired.
# 
#         :returns: A token (can be None) to use when releasing the semaphore
#         """
#         logger.debug("Acquiring %s", tag)
#         if not self._semaphore.acquire(blocking):
#             raise NoResourcesAvailable("Cannot acquire tag '%s'" % tag)
# 
#     def release(self, tag, acquire_token):
#         """Release the semaphore
# 
#         :param tag: A tag identifying what is releasing the semaphore
#         :param acquire_token:  The token returned from when the semaphore was
#             acquired. Note that this is not really needed to directly use this
#             class but is needed for API compatibility with the
#             SlidingWindowSemaphore implementation.
#         """
#         logger.debug(f"Releasing acquire {tag}/{acquire_token}")
#         self._semaphore.release()


# Path: s3transfer/futures.py
import copy
import logging
import sys
import threading
from collections import namedtuple
from concurrent import futures
from s3transfer.compat import MAXINT
from s3transfer.exceptions import CancelledError, TransferNotDoneError
from s3transfer.utils import FunctionContainer, TaskSemaphore


    def done(self):
        """Determines if a TransferFuture has completed

        :returns: False if status is equal to 'failed', 'cancelled', or
            'success'. True, otherwise
        """
        return self.status in ['failed', 'cancelled', 'success']

    def add_associated_future(self, future):
        """Adds a future to be associated with the TransferFuture"""
        with self._associated_futures_lock:
            self._associated_futures.add(future)

    def remove_associated_future(self, future):
        """Removes a future's association to the TransferFuture"""
        with self._associated_futures_lock:
            self._associated_futures.remove(future)

    def add_done_callback(self, function, *args, **kwargs):
        """Add a done callback to be invoked when transfer is done"""
        with self._done_callbacks_lock:
            self._done_callbacks.append(
                FunctionContainer(function, *args, **kwargs)
            )

    def add_failure_cleanup(self, function, *args, **kwargs):
        """Adds a callback to call upon failure"""
        with self._failure_cleanups_lock:
            self._failure_cleanups.append(

                FunctionContainer(function, *args, **kwargs)