def parts(self):
        parts = []
        upserts = dict()
        deletes = []
        max_upload_size = 700000
        base_part_size = 118
        if not self.replace_all:
            base_part_size += 1
        part_size = base_part_size
        for value in self.upserts:
            if (part_size + self.upserts_size[value]) >= max_upload_size:
                parts.append(BatchPart(self.replace_all, upserts, deletes))
                upserts = dict()
                deletes = []
                part_size = base_part_size
            upserts[self.lower_val_to_val[value]] = self.upserts[value]
            part_size += self.upserts_size[value]
        for value in self.deletes:
            if (part_size + len(value) + 4) >= max_upload_size:
                parts.append(BatchPart(self.replace_all, upserts, deletes))
                upserts = dict()
                deletes = []
                part_size = base_part_size
            deletes.append({'value': self.lower_val_to_val[value]})
            part_size += len(value) + 4
        if len(upserts) + len(deletes) > 0:
            parts.append(BatchPart(self.replace_all, upserts, deletes))
        if len(parts) == 0:
            if not self.replace_all:
                raise ValueError("Batch has no data, and 'replace_all' is False")
            parts.append(BatchPart(self.replace_all, dict(), []))
        parts[-1].set_last_part()
        return parts