def get_completed(self, after, before):
        """
        Return scores of tasks completed in the specified time range.

        This takes care of using the analysis API's pagination
        to make sure it gets all tasks.

        :param after: datetime.datetime
        :param before: datetime.datetime

        :yield: sequence of `CompletedTask`

        :raise: InvalidAnalysisAPIResponse if response
            does not have the format we expect
        """
        try:
            while True:
                result = self.__analysis_client.get_completed(
                    after=after,
                    before=before,
                    include_score=True)

                data = result["data"]
                tasks = data["tasks"]
                if not tasks:
                    break

                for task_uuid, score  in tasks.iteritems():
                    yield CompletedTask(task_uuid=task_uuid,
                                        score=score)

                more = int(data["more_results_available"])
                if not more:
                    break

                last_ts = parse_datetime(data["before"])
                if last_ts >= before:
                    break

                after = last_ts

        except (KeyError, ValueError, __HOLE__, AttributeError):
            # attributeError needed in case iteritems is missing (not a dict)
            # let's give it the trace of the original exception, so we know
            # what the specific problem is!
            trace = sys.exc_info()[2]
            raise InvalidAnalysisAPIResponse("Unable to parse response to get_completed()"), None, trace
dataset/ETHPy150Open StackStorm/st2contrib/packs/lastline/actions/lib/analysis_apiclient.py/TaskCompletion.get_completed