'Execute a full multipart upload on a file
Returns the seq/etag dict
TODO use num_processes to thread it'

def upload_all_parts(self, extra_label=''):

    if (not self.upload_id):
        raise RuntimeError('Attempting    to    use    a    multipart    upload    that    has    not    been    initiated.')
    self.chunk_size = ((self.s3.config.multipart_chunk_size_mb * 1024) * 1024)
    filename = self.file_stream.stream_name
    if (filename != u'<stdin>'):
        size_left = file_size = os.stat(deunicodise(filename))[ST_SIZE]
        nr_parts = ((file_size // self.chunk_size) + ((file_size % self.chunk_size) and 1))
        debug(('MultiPart:    Uploading    %s    in    %d    parts' % (filename, nr_parts)))
    else:
        debug(('MultiPart:    Uploading    from    %s' % filename))
    remote_statuses = dict()
    if self.s3.config.put_continue:
        remote_statuses = self.get_parts_information(self.uri, self.upload_id)
    if extra_label:
        extra_label = (u'    ' + extra_label)
    seq = 1
    if (filename != u'<stdin>'):
        while (size_left > 0):
            offset = (self.chunk_size * (seq - 1))
            current_chunk_size = min((file_size - offset), self.chunk_size)
            size_left -= current_chunk_size
            labels = {'source': filename, 'destination': self.uri.uri(), 'extra': ('[part    %d    of    %d,    %s]%s' % (seq, nr_parts, ('%d%sB' % formatSize(current_chunk_size, human_readable=True)), extra_label))}
            try:
                self.upload_part(seq, offset, current_chunk_size, labels, remote_status=remote_statuses.get(seq))
            except:
                error((u"\nUpload    of    '%s'    part    %d    failed.    Use\n        %s    abortmp    %s    %s\nto    abort    the    upload,    or\n        %s    --upload-id    %s    put    ...\nto    continue    the    upload." % (filename, seq, sys.argv[0], self.uri, self.upload_id, sys.argv[0], self.upload_id)))
                raise
            seq += 1
    else:
        while True:
            buffer = self.file_stream.read(self.chunk_size)
            offset = 0
            current_chunk_size = len(buffer)
            labels = {'source': filename, 'destination': self.uri.uri(), 'extra': ('[part    %d,    %s]' % (seq, ('%d%sB' % formatSize(current_chunk_size, human_readable=True))))}
            if (len(buffer) == 0):
                break
            try:
                self.upload_part(seq, offset, current_chunk_size, labels, buffer, remote_status=remote_statuses.get(seq))
            except:
                error((u"\nUpload    of    '%s'    part    %d    failed.    Use\n        %s    abortmp    %s    %s\nto    abort,    or\n        %s    --upload-id    %s    put    ...\nto    continue    the    upload." % (filename, seq, sys.argv[0], self.uri, self.upload_id, sys.argv[0], self.upload_id)))
                raise
            seq += 1
    debug('MultiPart:    Upload    finished:    %d    parts', (seq - 1))
