def copy(self, source_path, destination_path, threads=100, start_time=None, end_time=None, part_size=67108864, **kwargs):
        """
        Copy object(s) from one S3 location to another. Works for individual keys or entire directories.

        When files are larger than `part_size`, multipart uploading will be used.

        :param source_path: The `s3://` path of the directory or key to copy from
        :param destination_path: The `s3://` path of the directory or key to copy to
        :param threads: Optional argument to define the number of threads to use when copying (min: 3 threads)
        :param start_time: Optional argument to copy files with modified dates after start_time
        :param end_time: Optional argument to copy files with modified dates before end_time
        :param part_size: Part size in bytes. Default: 67108864 (64MB), must be >= 5MB and <= 5 GB.
        :param kwargs: Keyword arguments are passed to the boto function `copy_key`
        """
        start = datetime.datetime.now()

        (src_bucket, src_key) = self._path_to_bucket_and_key(source_path)
        (dst_bucket, dst_key) = self._path_to_bucket_and_key(destination_path)

        # As the S3 copy command is completely server side, there is no issue with issuing a lot of threads
        # to issue a single API call per copy, however, this may in theory cause issues on systems with low ulimits for
        # number of threads when copying really large files (e.g. with a ~100GB file this will open ~1500
        # threads), or large directories. Around 100 threads seems to work well.

        threads = 3 if 3 < threads else threads  # don't allow threads to be less than 3
        total_keys = 0

        copy_pool = ThreadPool(processes=threads)

        if self.isdir(source_path):
            # The management pool is to ensure that there's no deadlock between the s3 copying threads, and the
            # multipart_copy threads that monitors each group of s3 copy threads and returns a success once the entire file
            # is copied. Without this, we could potentially fill up the pool with threads waiting to check if the s3 copies
            # have completed, leaving no available threads to actually perform any copying.
            copy_jobs = []
            management_pool = ThreadPool(processes=threads)

            src_prefix = self._add_path_delimiter(src_key)
            dst_prefix = self._add_path_delimiter(dst_key)
            for key in self.list(source_path, start_time=start_time, end_time=end_time):
                # prevents copy attempt of empty key in folder
                if key != '' and key != '/':
                    total_keys += 1
                    job = management_pool.apply_async(self.__copy_multipart,
                                                      args=(copy_pool,
                                                            src_bucket, src_prefix + key,
                                                            dst_bucket, dst_prefix + key,
                                                            part_size),
                                                      kwds=kwargs)
                    copy_jobs.append(job)

            # Wait for the pools to finish scheduling all the copies
            management_pool.close()
            management_pool.join()
            copy_pool.close()
            copy_pool.join()

            # Raise any errors encountered in any of the copy processes
            for result in copy_jobs:
                result.get()

            end = datetime.datetime.now()
            duration = end - start
            logger.info('%s : Complete : %s total keys copied in %s' %
                        (datetime.datetime.now(), total_keys, duration))

        # If the file isn't a directory just perform a simple copy
        else:
            self.__copy_multipart(copy_pool, src_bucket, src_key, dst_bucket, dst_key, part_size, **kwargs)
            # Close the pool
            copy_pool.close()
            copy_pool.join()
dataset/ETHPy150Open spotify/luigi/luigi/s3.py/S3Client.copy/swapped operands of `<`