def list()

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


    def list(self, request):
        query_params = PerformanceQueryParamsSerializer(data=request.query_params)
        if not query_params.is_valid():
            return Response(data=query_params.errors, status=HTTP_400_BAD_REQUEST)

        startday = query_params.validated_data["startday"]
        endday = query_params.validated_data["endday"]
        revision = query_params.validated_data["revision"]
        repository_name = query_params.validated_data["repository"]
        interval = query_params.validated_data["interval"]
        frameworks = query_params.validated_data["framework"]
        parent_signature = query_params.validated_data["parent_signature"]
        signature = query_params.validated_data["signature"]
        no_subtests = query_params.validated_data["no_subtests"]
        all_data = query_params.validated_data["all_data"]
        no_retriggers = query_params.validated_data["no_retriggers"]
        replicates = query_params.validated_data["replicates"]

        signature_data = PerformanceSignature.objects.select_related(
            "framework", "repository", "platform", "push", "job"
        ).filter(repository__name=repository_name)

        # TODO deprecate signature hash support
        if signature and len(signature) == 40:
            signature_data = signature_data.filter(signature_hash=signature)
        elif signature:
            signature_data = signature_data.filter(id=signature)
        else:
            signature_data = signature_data.filter(parent_signature__isnull=no_subtests)

        if frameworks:
            signature_data = signature_data.filter(framework__in=frameworks)

        if parent_signature:
            signature_data = signature_data.filter(parent_signature_id=parent_signature)

        # we do this so all relevant signature data is returned even if there isn't performance data
        # and it's also not needed since this param is used to filter directly on signature_id
        if interval and not all_data:
            signature_data = signature_data.filter(
                last_updated__gte=datetime.datetime.utcfromtimestamp(
                    int(time.time() - int(interval))
                )
            )

        # TODO signature_hash is being returned for legacy support - should be removed at some point
        self.queryset = signature_data.values(
            "framework_id",
            "id",
            "lower_is_better",
            "has_subtests",
            "extra_options",
            "suite",
            "signature_hash",
            "platform__platform",
            "test",
            "option_collection_id",
            "parent_signature_id",
            "repository_id",
            "tags",
            "measurement_unit",
            "application",
            "should_alert",
            "alert_change_type",
            "alert_threshold",
            "parent_signature__should_alert",
        )

        self.check_and_update_should_alert()

        signature_ids = [item["id"] for item in list(self.queryset)]

        data = (
            PerformanceDatum.objects.select_related("push", "repository", "job")
            .filter(signature_id__in=signature_ids, repository__name=repository_name)
            .order_by("job_id", "id")
        )

        if revision:
            data = data.filter(push__revision=revision)
        elif interval and not startday and not endday:
            data = data.filter(
                push_timestamp__gt=datetime.datetime.utcfromtimestamp(
                    int(time.time() - int(interval))
                )
            )
        else:
            data = data.filter(push_timestamp__gt=startday, push_timestamp__lt=endday)

        # more efficient than creating a join on option_collection and option
        option_collection = OptionCollection.objects.select_related("option").values(
            "id", "option__name"
        )
        option_collection_map = {
            item["id"]: item["option__name"] for item in list(option_collection)
        }

        if signature and all_data:
            for item in self.queryset:
                if replicates:
                    item["data"] = list()
                    for (
                        value,
                        job_id,
                        datum_id,
                        push_id,
                        push_timestamp,
                        push_revision,
                        replicate_value,
                        submit_time,
                    ) in data.values_list(
                        "value",
                        "job_id",
                        "id",
                        "push_id",
                        "push_timestamp",
                        "push__revision",
                        "performancedatumreplicate__value",
                        "job__submit_time",
                    ).order_by("push_timestamp", "push_id", "job_id"):
                        if replicate_value is not None:
                            item["data"].append(
                                {
                                    "value": replicate_value,
                                    "job_id": job_id,
                                    "id": datum_id,
                                    "push_id": push_id,
                                    "push_timestamp": push_timestamp,
                                    "push__revision": push_revision,
                                    "submit_time": submit_time,
                                }
                            )
                        elif value is not None:
                            item["data"].append(
                                {
                                    "value": value,
                                    "job_id": job_id,
                                    "id": datum_id,
                                    "push_id": push_id,
                                    "push_timestamp": push_timestamp,
                                    "push__revision": push_revision,
                                    "submit_time": submit_time,
                                }
                            )
                else:
                    item["data"] = data.values(
                        "value",
                        "job_id",
                        "id",
                        "push_id",
                        "push_timestamp",
                        "push__revision",
                        "job__submit_time",
                    ).order_by("push_timestamp", "push_id", "job_id")

                item["option_name"] = option_collection_map[item["option_collection_id"]]
                item["repository_name"] = repository_name

        else:
            grouped_values = defaultdict(list)
            grouped_job_ids = defaultdict(list)
            grouped_submit_times = defaultdict(list)
            if replicates:
                for signature_id, value, job_id, replicate_value, submit_time in data.values_list(
                    "signature_id",
                    "value",
                    "job_id",
                    "performancedatumreplicate__value",
                    "job__submit_time",
                ):
                    if replicate_value is not None:
                        grouped_values[signature_id].append(replicate_value)
                        grouped_job_ids[signature_id].append(job_id)
                        grouped_submit_times[signature_id].append(submit_time)
                    elif value is not None:
                        grouped_values[signature_id].append(value)
                        grouped_job_ids[signature_id].append(job_id)
                        grouped_submit_times[signature_id].append(submit_time)
            else:
                for signature_id, value, job_id, submit_time in data.values_list(
                    "signature_id", "value", "job_id", "job__submit_time"
                ):
                    if value is not None:
                        grouped_values[signature_id].append(value)
                        grouped_job_ids[signature_id].append(job_id)
                        grouped_submit_times[signature_id].append(submit_time)

            # name field is created in the serializer
            for item in self.queryset:
                item["values"] = grouped_values.get(item["id"], [])
                item["job_ids"] = grouped_job_ids.get(item["id"], [])
                item["submit_times"] = grouped_submit_times.get(item["id"], [])
                item["option_name"] = option_collection_map[item["option_collection_id"]]
                item["repository_name"] = repository_name

        serializer = self.get_serializer(self.queryset, many=True)
        serialized_data = serializer.data

        if no_retriggers:
            serialized_data = self._filter_out_retriggers(serialized_data)

        return Response(data=serialized_data)