# Buggy code
def copyKeyMultipart(srcKey, dstBucketName, dstKeyName, headers=None):
    """
    Copies a key from a source key to a destination key in multiple parts. Note that if the
    destination key exists it will be overwritten implicitly, and if it does not exist a new
    key will be created.

    :param boto.s3.key.Key srcKey: The source key to be copied from.
    :param str dstBucketName: The name of the destination bucket for the copy.
    :param str dstKeyName: The name of the destination key that will be created or overwritten.
    :param dict headers: Any headers that should be passed.

    :rtype: boto.s3.multipart.CompletedMultiPartUpload
    :return: An object representing the completed upload.
    """
    partSize = defaultPartSize
    s3 = boto.connect_s3()
    headers = headers or {}
    totalSize = srcKey.size

    # initiate copy
    upload = s3.get_bucket(dstBucketName).initiate_multipart_upload(dstKeyName)
    try:
        start = 0
        partIndex = itertools.count()
        while start < totalSize:
            end = min(start + partSize, totalSize)
            upload.copy_part_from_key(
                src_bucket_name=srcKey.bucket.name,
                src_key_name=srcKey.name,
                part_num=next(partIndex) + 1,
                start=start,
                end=end - 1,
                headers=headers,
            )
            start += partSize
    except:
        upload.cancel_upload()
        raise
    else:
        return upload.complete_upload()


# Traceback (boto.exception.S3ResponseError)
2016-04-26 14:13:37,623 ERROR:root: Got exception 'S3ResponseError: 400 Bad Request
<Error><Code>InvalidRequest</Code><Message>The specified copy source is larger than the maximum allowable size for a copy source: 5368709120</Message><RequestId>CCB50A66B881B563</RequestId><HostId>1dAVKee/hXEaLCvisKyxUHlWtLbZwqcedEXOsKVSzAoE5ISrsuykzg9teW9vzidQaIqImJxbNgI=</HostId></Error>' while writing 's3://1000genomes/phase3/data/HG01977/sequence_read/SRR360135_1.filt.fastq.gz'
Traceback (most recent call last):
File "/usr/local/bin/cwltoil", line 9, in <module>
load_entry_point('toil==3.2.0a2', 'console_scripts', 'cwltoil')()
File "/usr/local/lib/python2.7/dist-packages/toil/cwl/cwltoil.py", line 580, in main
adjustFiles(builder.job, functools.partial(writeFile, toil.importFile, {}))
File "/usr/local/lib/python2.7/dist-packages/cwltool/process.py", line 128, in adjustFiles
adjustFiles(rec[d], op)
File "/usr/local/lib/python2.7/dist-packages/cwltool/process.py", line 131, in adjustFiles
adjustFiles(d, op)
File "/usr/local/lib/python2.7/dist-packages/cwltool/process.py", line 131, in adjustFiles
adjustFiles(d, op)
File "/usr/local/lib/python2.7/dist-packages/cwltool/process.py", line 126, in adjustFiles
rec["path"] = op(rec["path"])
File "/usr/local/lib/python2.7/dist-packages/toil/cwl/cwltoil.py", line 162, in writeFile
index[x] = (writeFunc(rp), os.path.basename(x))
File "/usr/local/lib/python2.7/dist-packages/toil/common.py", line 570, in importFile
return self.jobStore.importFile(srcUrl)
File "/usr/local/lib/python2.7/dist-packages/toil/jobStores/abstractJobStore.py", line 260, in importFile
return self._importFile(findJobStoreForUrl(url), url)
File "/usr/local/lib/python2.7/dist-packages/toil/jobStores/aws/jobStore.py", line 279, in _importFile
info.copyFrom(srcKey)
File "/usr/local/lib/python2.7/dist-packages/toil/jobStores/aws/jobStore.py", line 826, in copyFrom
headers=self._s3EncryptionHeaders()).version_id
File "/usr/local/lib/python2.7/dist-packages/toil/jobStores/aws/jobStore.py", line 865, in _copyKey
headers=headers)
File "/usr/local/lib/python2.7/dist-packages/boto/s3/bucket.py", line 888, in copy_key
response.reason, body)
boto.exception.S3ResponseError: S3ResponseError: 400 Bad Request
<Error><Code>InvalidRequest</Code><Message>The specified copy source is larger than the maximum allowable size for a copy source: 5368709120</Message><RequestId>CCB50A66B881B563</RequestId><HostId>1dAVKee/hXEaLCvisKyxUHlWtLbZwqcedEXOsKVSzAoE5ISrsuykzg9teW9vzidQaIqImJxbNgI=</HostId></Error>

# Fixed code
def copyKeyMultipart(srcKey, dstBucketName, dstKeyName, headers=None):
    """
    Copies a key from a source key to a destination key in multiple parts. Note that if the
    destination key exists it will be overwritten implicitly, and if it does not exist a new
    key will be created.

    :param boto.s3.key.Key srcKey: The source key to be copied from.
    :param str dstBucketName: The name of the destination bucket for the copy.
    :param str dstKeyName: The name of the destination key that will be created or overwritten.
    :param dict headers: Any headers that should be passed.

    :rtype: boto.s3.multipart.CompletedMultiPartUpload
    :return: An object representing the completed upload.
    """
    partSize = defaultPartSize
    s3 = boto.connect_s3()
    headers = headers or {}
    totalSize = srcKey.size

    # initiate copy
    upload = s3.get_bucket(dstBucketName).initiate_multipart_upload(
        dstKeyName, headers=headers
    )
    try:
        start = 0
        partIndex = itertools.count()
        while start < totalSize:
            end = min(start + partSize, totalSize)
            upload.copy_part_from_key(
                src_bucket_name=srcKey.bucket.name,
                src_key_name=srcKey.name,
                part_num=next(partIndex) + 1,
                start=start,
                end=end - 1,
                headers=headers,
            )
            start += partSize
    except:
        upload.cancel_upload()
        raise
    else:
        return upload.complete_upload()