Submit purge request(s) to the CCU API

        Since a purge call may require multiple API requests and may trigger rate-limiting
        this method uses a generator to provide the results of each request, allowing you to
        communicate request progress or implement a custom rate-limiting response::

            for url_batch, response in purge_request.purge():
                if response.ok:
                    # update progress
                elif response.status_code == 507:
                    # Rate-limiting. Do something?

        If you simply want a function which blocks until all of the purge requests have been
        issued, use `purge_all()`.

        Both `purge()` and `purge_all()` will raise HTTP exceptions for any error response
        other than rate-limiting.

def purge(self):
        """Submit purge request(s) to the CCU API

        Since a purge call may require multiple API requests and may trigger rate-limiting
        this method uses a generator to provide the results of each request, allowing you to
        communicate request progress or implement a custom rate-limiting response::

            for url_batch, response in purge_request.purge():
                if response.ok:
                    # update progress
                elif response.status_code == 507:
                    # Rate-limiting. Do something?

        If you simply want a function which blocks until all of the purge requests have been
        issued, use `purge_all()`.

        Both `purge()` and `purge_all()` will raise HTTP exceptions for any error response
        other than rate-limiting.
        """

        purge_url = urljoin('https://%s' % self.host, '/ccu/v3/%s/url/%s' % (self.action, self.network))

        while self.urls:
            # We'll accumulate
            batch = []
            batch_size = 0

            while self.urls and batch_size < self.MAX_REQUEST_SIZE:
                next_url = self.urls.pop()

                if not isinstance(next_url, bytes):
                    next_url = next_url.encode('utf-8')

                batch.append(next_url)
                batch_size += len(next_url)

            if batch:
                data = {'objects': batch}

                logger.debug('Requesting Akamai purge %d URLs', len(batch))

                response = requests.post(url=purge_url, auth=self.auth, data=json.dumps(data),
                                         headers={'Content-Type': 'application/json'})

                if not response.ok:
                    # We'll return the current batch to the queue so they can be retried later:
                    self.urls.extend(batch)

                    # Raise an exception for errors other than rate-limiting:
                    if response.status_code != 507:
                        response.raise_for_status()

                yield batch, response