def list()

in treeherder/webapp/api/performance_data.py [0:0]


    def list(self, request, project):
        repository = models.Repository.objects.get(name=project)

        signature_hashes = request.query_params.getlist("signatures")  # deprecated
        signature_ids = request.query_params.getlist("signature_id")
        push_ids = request.query_params.getlist("push_id")
        no_retriggers = request.query_params.get("no_retriggers", False)
        no_retriggers = OptionalBooleanField().to_internal_value(no_retriggers)

        try:
            job_ids = [int(job_id) for job_id in request.query_params.getlist("job_id")]
        except ValueError:
            return Response(
                {"message": "Job id(s) must be specified as integers"}, status=HTTP_400_BAD_REQUEST
            )

        if not (signature_ids or signature_hashes or push_ids or job_ids):
            raise exceptions.ValidationError(
                "Need to specify either signature_id, signatures, push_id, or job_id"
            )
        if signature_ids and signature_hashes:
            raise exceptions.ValidationError(
                "Can't specify both signature_id and signatures in same query"
            )

        datums = PerformanceDatum.objects.filter(repository=repository).select_related(
            "signature", "push"
        )

        if signature_hashes:
            signature_ids = PerformanceSignature.objects.filter(
                repository=repository, signature_hash__in=signature_hashes
            ).values_list("id", flat=True)

            datums = datums.filter(signature__id__in=list(signature_ids))
        elif signature_ids:
            datums = datums.filter(signature__id__in=list(signature_ids))
        if push_ids:
            datums = datums.filter(push_id__in=push_ids)
        if job_ids:
            datums = datums.filter(job_id__in=job_ids)

        frameworks = request.query_params.getlist("framework")
        if frameworks:
            datums = datums.filter(signature__framework__in=frameworks)

        interval = request.query_params.get("interval")
        start_date = request.query_params.get("start_date")  # 'YYYY-MM-DDTHH:MM:SS
        end_date = request.query_params.get("end_date")  # 'YYYY-MM-DDTHH:MM:SS'
        if interval and (start_date or end_date):
            return Response(
                {"message": "Provide either interval only -or- start (and end) date"},
                status=HTTP_400_BAD_REQUEST,
            )

        if interval:
            datums = datums.filter(
                push_timestamp__gt=datetime.datetime.utcfromtimestamp(
                    int(time.time() - int(interval))
                )
            )

        if start_date:
            datums = datums.filter(push_timestamp__gt=start_date)
        if end_date:
            datums = datums.filter(push_timestamp__lt=end_date)

        ret, seen_push_ids = defaultdict(list), defaultdict(set)
        values_list = datums.values_list(
            "id",
            "signature_id",
            "signature__signature_hash",
            "job_id",
            "push_id",
            "push_timestamp",
            "value",
            "push__revision",
        )
        for (
            id,
            signature_id,
            signature_hash,
            job_id,
            push_id,
            push_timestamp,
            value,
            push__revision,
        ) in values_list:
            should_include_datum = True
            if no_retriggers:
                if push_id in seen_push_ids[signature_hash]:
                    should_include_datum = False
                else:
                    seen_push_ids[signature_hash].add(push_id)

            if should_include_datum:
                ret[signature_hash].append(
                    {
                        "id": id,
                        "signature_id": signature_id,
                        "job_id": job_id,
                        "push_id": push_id,
                        "revision": push__revision,
                        "push_timestamp": int(time.mktime(push_timestamp.timetuple())),
                        "value": round(value, 2),  # round to 2 decimal places
                    }
                )

        return Response(ret)