calculates a multipart upload etag in the same way as amazon s3
            args:
                source_path -- The file to calculate the etage for
                chunk_size -- The chunk size to calculate for.
                expected -- optional If passed a string, the string
                will be compared to the resulting etag and raise an
                exception if they don't match

def calculate_etag(self, expected=None):
        """
            calculates a multipart upload etag in the same way as amazon s3
            args:
                source_path -- The file to calculate the etage for
                chunk_size -- The chunk size to calculate for.
                expected -- optional If passed a string, the string
                will be compared to the resulting etag and raise an
                exception if they don't match
        """
        md5s = []
        with open(self.filepath, 'rb') as fp:
            while True:
                data = fp.read(CHUNK_SIZE)
                if not data:
                    break
                md5s.append(hashlib.md5(data))

        digests = b"".join(m.digest() for m in md5s)

        new_md5 = hashlib.md5(digests)
        new_etag = '%s-%s' % (new_md5.hexdigest(),len(md5s))
        self.etag = new_etag

        return new_etag