예제 #1
0
def test_resultset_list_filter_by_date(webapp, test_repository, sample_resultset, jm, test_project):
    """
    test retrieving a resultset list, filtered by a date range
    """
    sample_resultset[3]["push_timestamp"] = utils.to_timestamp("2013-08-09")
    sample_resultset[4]["push_timestamp"] = utils.to_timestamp("2013-08-10")
    sample_resultset[5]["push_timestamp"] = utils.to_timestamp("2013-08-11")
    sample_resultset[6]["push_timestamp"] = utils.to_timestamp("2013-08-12")
    sample_resultset[7]["push_timestamp"] = utils.to_timestamp("2013-08-13")

    jm.store_result_set_data(sample_resultset)

    resp = webapp.get(
        reverse("resultset-list", kwargs={"project": jm.project}), {"startdate": "2013-08-10", "enddate": "2013-08-13"}
    )
    assert resp.status_int == 200
    results = resp.json["results"]
    meta = resp.json["meta"]
    assert len(results) == 4
    assert set([rs["revision"] for rs in results]) == {
        u"ce17cad5d554cfffddee13d1d8421ae9ec5aad82",
        u"7f417c3505e3d2599ac9540f02e3dbee307a3963",
        u"a69390334818373e2d7e6e9c8d626a328ed37d47",
        u"f361dcb60bbedaa01257fbca211452972f7a74b2",
    }
    assert meta == {
        u"count": 4,
        u"enddate": u"2013-08-13",
        u"filter_params": {u"push_timestamp__gte": 1376118000.0, u"push_timestamp__lt": 1376463600.0},
        u"repository": test_project,
        u"startdate": u"2013-08-10",
    }
예제 #2
0
 def to_representation(self, job):
     return {
         'build_architecture': job.build_platform.architecture,
         'build_os': job.build_platform.os_name,
         'build_platform': job.build_platform.platform,
         'build_platform_id': job.build_platform_id,
         'build_system_type': job.signature.build_system_type,
         'end_timestamp': to_timestamp(job.end_time),
         'failure_classification_id': job.failure_classification_id,
         'id': job.id,
         'job_coalesced_to_guid': job.coalesced_to_guid,
         'job_group_description': job.job_type.job_group.description,
         'job_group_id': job.job_type.job_group_id,
         'job_group_name': job.job_type.job_group.name,
         'job_group_symbol': job.job_type.job_group.symbol,
         'job_guid': job.guid,
         'job_type_description': job.job_type.description,
         'job_type_id': job.job_type_id,
         'job_type_name': job.job_type.name,
         'job_type_symbol': job.job_type.symbol,
         'last_modified': job.last_modified,
         'machine_name': job.machine.name,
         'machine_platform_architecture': job.machine_platform.architecture,
         'machine_platform_os': job.machine_platform.os_name,
         'option_collection_hash': job.option_collection_hash,
         'platform': job.machine_platform.platform,
         'push_id': job.push_id,
         'reason': job.reason,
         'ref_data_name': job.signature.name,
         'result': job.result,
         'result_set_id': job.push_id,
         'running_eta': job.running_eta,
         'signature': job.signature.signature,
         'start_timestamp': to_timestamp(job.start_time),
         'state': job.state,
         'submit_timestamp': to_timestamp(job.submit_time),
         'tier': job.tier,
         'who': job.who
     }
예제 #3
0
def test_resultset_list_filter_by_date(webapp, initial_data,
                                       sample_resultset, jm):
    """
    test retrieving a resultset list, filtered by a date range
    """
    sample_resultset[3]["push_timestamp"] = utils.to_timestamp("2013-08-09")
    sample_resultset[4]["push_timestamp"] = utils.to_timestamp("2013-08-10")
    sample_resultset[5]["push_timestamp"] = utils.to_timestamp("2013-08-11")
    sample_resultset[6]["push_timestamp"] = utils.to_timestamp("2013-08-12")
    sample_resultset[7]["push_timestamp"] = utils.to_timestamp("2013-08-13")

    jm.store_result_set_data(sample_resultset)

    resp = webapp.get(
        reverse("resultset-list", kwargs={"project": jm.project}),
        {"startdate": "2013-08-10", "enddate": "2013-08-13"}
    )
    assert resp.status_int == 200
    results = resp.json['results']
    meta = resp.json['meta']
    assert len(results) == 4
    assert set([rs["revision"] for rs in results]) == set(
        ["909f55c626a8", "71d49fee325a", "bb57e9f67223", "668424578a0d"]
    )
    assert(meta == {
        u'count': 4,
        u'enddate': u'2013-08-13',
        u'filter_params': {
            u'push_timestamp__gte': 1376118000.0,
            u'push_timestamp__lt': 1376463600.0
        },
        u'repository': u'test_treeherder',
        u'startdate': u'2013-08-10'}
    )

    jm.disconnect()
예제 #4
0
def test_push_list_filter_by_date(client,
                                  test_repository,
                                  sample_push):
    """
    test retrieving a push list, filtered by a date range
    """
    for (i, datestr) in zip([3, 4, 5, 6, 7], ["2013-08-09", "2013-08-10",
                                              "2013-08-11", "2013-08-12",
                                              "2013-08-13"]):
        sample_push[i]['push_timestamp'] = utils.to_timestamp(
            utils.to_datetime(datestr))

    store_push_data(test_repository, sample_push)

    resp = client.get(
        reverse("push-list", kwargs={"project": test_repository.name}),
        {"startdate": "2013-08-10", "enddate": "2013-08-13"}
    )
    assert resp.status_code == 200
    # The .json() method of the Django test client doesn't handle unicode properly on
    # Python 2, so we have to deserialize ourselves. TODO: Clean up once on Python 3.
    data = json.loads(resp.content)
    results = data['results']
    meta = data['meta']
    assert len(results) == 4
    assert set([rs["revision"] for rs in results]) == {
        u'ce17cad5d554cfffddee13d1d8421ae9ec5aad82',
        u'7f417c3505e3d2599ac9540f02e3dbee307a3963',
        u'a69390334818373e2d7e6e9c8d626a328ed37d47',
        u'f361dcb60bbedaa01257fbca211452972f7a74b2'
    }
    assert(meta == {
        u'count': 4,
        u'enddate': u'2013-08-13',
        u'filter_params': {
            u'push_timestamp__gte': 1376092800.0,
            u'push_timestamp__lt': 1376438400.0
        },
        u'repository': test_repository.name,
        u'startdate': u'2013-08-10'}
    )
예제 #5
0
def test_push_list_filter_by_date(webapp,
                                  test_repository,
                                  sample_push):
    """
    test retrieving a push list, filtered by a date range
    """
    for (i, datestr) in zip([3, 4, 5, 6, 7], ["2013-08-09", "2013-08-10",
                                              "2013-08-11", "2013-08-12",
                                              "2013-08-13"]):
        sample_push[i]['push_timestamp'] = utils.to_timestamp(
            utils.to_datetime(datestr))

    store_push_data(test_repository, sample_push)

    resp = webapp.get(
        reverse("push-list", kwargs={"project": test_repository.name}),
        {"startdate": "2013-08-10", "enddate": "2013-08-13"}
    )
    assert resp.status_int == 200
    results = resp.json['results']
    meta = resp.json['meta']
    assert len(results) == 4
    assert set([rs["revision"] for rs in results]) == {
        u'ce17cad5d554cfffddee13d1d8421ae9ec5aad82',
        u'7f417c3505e3d2599ac9540f02e3dbee307a3963',
        u'a69390334818373e2d7e6e9c8d626a328ed37d47',
        u'f361dcb60bbedaa01257fbca211452972f7a74b2'
    }
    assert(meta == {
        u'count': 4,
        u'enddate': u'2013-08-13',
        u'filter_params': {
            u'push_timestamp__gte': 1376092800.0,
            u'push_timestamp__lt': 1376438400.0
        },
        u'repository': test_repository.name,
        u'startdate': u'2013-08-10'}
    )
예제 #6
0
    def list(self, request, project):
        """
        GET method for list of ``resultset`` records with revisions
        """
        # What is the upper limit on the number of resultsets returned by the api
        MAX_RESULTS_COUNT = 1000

        # make a mutable copy of these params
        filter_params = request.query_params.copy()

        # This will contain some meta data about the request and results
        meta = {}

        # support ranges for date as well as revisions(changes) like old tbpl
        for param in ["fromchange", "tochange", "startdate", "enddate", "revision"]:
            v = filter_params.get(param, None)
            if v:
                del(filter_params[param])
                meta[param] = v

        try:
            repository = Repository.objects.get(name=project)
        except Repository.DoesNotExist:
            return Response({
                "detail": "No project with name {}".format(project)
            }, status=HTTP_404_NOT_FOUND)

        pushes = Push.objects.filter(repository=repository).order_by('-time')

        for (param, value) in meta.iteritems():
            if param == 'fromchange':
                frompush_time = Push.objects.values_list('time', flat=True).get(
                    repository=repository, revision__startswith=value)
                pushes = pushes.filter(time__gte=frompush_time)
                filter_params.update({
                    "push_timestamp__gte": to_timestamp(frompush_time)
                })

            elif param == 'tochange':
                topush_time = Push.objects.values_list('time', flat=True).get(
                    repository=repository, revision__startswith=value)
                pushes = pushes.filter(time__lte=topush_time)
                filter_params.update({
                    "push_timestamp__lte": to_timestamp(topush_time)
                })
            elif param == 'startdate':
                pushes = pushes.filter(time__gte=to_datetime(value))
                filter_params.update({
                    "push_timestamp__gte": to_timestamp(to_datetime(value))
                })
            elif param == 'enddate':
                real_end_date = to_datetime(value) + datetime.timedelta(days=1)
                pushes = pushes.filter(time__lte=real_end_date)
                filter_params.update({
                    "push_timestamp__lt": to_timestamp(real_end_date)
                })
            elif param == 'revision':
                # revision can be either the revision of the push itself, or
                # any of the commits it refers to
                pushes = pushes.filter(commits__revision__startswith=value)
                rev_key = "revisions_long_revision" \
                          if len(meta['revision']) == 40 else "revisions_short_revision"
                filter_params.update({rev_key: meta['revision']})

        for param in ['push_timestamp__lt', 'push_timestamp__lte',
                      'push_timestamp__gt', 'push_timestamp__gte']:
            if filter_params.get(param):
                # translate push timestamp directly into a filter
                try:
                    value = datetime.datetime.fromtimestamp(
                        float(filter_params.get(param)))
                except ValueError:
                    return Response({
                        "error": "Invalid timestamp specified for {}".format(
                            param)
                    }, status=HTTP_400_BAD_REQUEST)
                pushes = pushes.filter(**{
                    param.replace('push_timestamp', 'time'): value
                })

        for param in ['id__lt', 'id__lte', 'id__gt', 'id__gte', 'id']:
            try:
                value = int(filter_params.get(param, 0))
            except ValueError:
                return Response({
                    "error": "Invalid timestamp specified for {}".format(
                        param)
                }, status=HTTP_400_BAD_REQUEST)
            if value:
                pushes = pushes.filter(**{param: value})

        id_in = filter_params.get("id__in")
        if id_in:
            try:
                id_in_list = [int(id) for id in id_in.split(',')]
            except ValueError:
                return Response({"error": "Invalid id__in specification"},
                                status=HTTP_400_BAD_REQUEST)
            pushes = pushes.filter(id__in=id_in_list)

        author = filter_params.get("author")
        if author:
            pushes = pushes.filter(author=author)

        count = int(filter_params.get("count", 10))

        if count > MAX_RESULTS_COUNT:
            msg = "Specified count exceeds api limit: {}".format(MAX_RESULTS_COUNT)
            return Response({"error": msg}, status=HTTP_400_BAD_REQUEST)

        # we used to have a "full" parameter for this endpoint so you could
        # specify to not fetch the revision information if it was set to
        # false. however AFAIK no one ever used it (default was to fetch
        # everything), so let's just leave it out. it doesn't break
        # anything to send extra data when not required.
        pushes = pushes.select_related('repository').prefetch_related('commits')[:count]
        serializer = PushSerializer(pushes, many=True)

        meta['count'] = len(pushes)
        meta['repository'] = project
        meta['filter_params'] = filter_params

        resp = {
            'meta': meta,
            'results': serializer.data
        }

        return Response(resp)
예제 #7
0
    def list(self, request, project, jm):
        """
        GET method for list of ``resultset`` records with revisions

        """
        # What is the upper limit on the number of resultsets returned by the api
        MAX_RESULTS_COUNT = 1000

        # make a mutable copy of these params
        filter_params = request.query_params.copy()

        # This will contain some meta data about the request and results
        meta = {}

        # support ranges for date as well as revisions(changes) like old tbpl
        for param in ["fromchange", "tochange", "startdate", "enddate", "revision"]:
            v = filter_params.get(param, None)
            if v:
                del(filter_params[param])
                meta[param] = v

        # create a timestamp lookup based on the from/to change params that may
        # exist. This means we only make 1 DB query rather than 2, if we have
        # both a ``fromchange`` and a ``tochange`` value.
        ts_lookup = jm.get_resultset_all_revision_lookup(
            [meta[x] for x in ['fromchange', 'tochange'] if x in meta]
        )

        # translate these params into our own filtering mechanism
        if 'fromchange' in meta:
            filter_params.update({
                "push_timestamp__gte": ts_lookup[meta['fromchange']]["push_timestamp"]

            })
        if 'tochange' in meta:
            filter_params.update({
                "push_timestamp__lte": ts_lookup[meta['tochange']]["push_timestamp"]
            })
        if 'startdate' in meta:
            filter_params.update({
                "push_timestamp__gte": to_timestamp(meta['startdate'])
            })
        if 'enddate' in meta:

            # add a day because we aren't supplying a time, just a date.  So
            # we're doing ``less than``, rather than ``less than or equal to``.
            filter_params.update({
                "push_timestamp__lt": to_timestamp(meta['enddate']) + 86400
            })
        if 'revision' in meta:
            # Allow the user to search by either the short or long version of
            # a revision.
            rev_key = "revisions_long_revision" \
                if len(meta['revision']) == 40 else "revisions_short_revision"
            filter_params.update({rev_key: meta['revision']})

        meta['filter_params'] = filter_params

        filter = UrlQueryFilter(filter_params)

        offset_id = int(filter.pop("id__lt", 0))
        count = int(filter.pop("count", 10))

        if count > MAX_RESULTS_COUNT:
            msg = "Specified count exceeds api limit: {}".format(MAX_RESULTS_COUNT)
            return Response({"error": msg}, status=HTTP_400_BAD_REQUEST)

        full = filter.pop('full', 'true').lower() == 'true'

        results = jm.get_result_set_list(
            offset_id,
            count,
            full,
            filter.conditions
        )

        for rs in results:
            rs["revisions_uri"] = reverse("resultset-revisions",
                                          kwargs={"project": jm.project, "pk": rs["id"]})

        meta['count'] = len(results)
        meta['repository'] = project

        resp = {
            'meta': meta,
            'results': results
        }

        return Response(resp)
예제 #8
0
    def list(self, request, project, jm):
        """
        GET method for list of ``resultset`` records with revisions

        """
        # make a mutable copy of these params
        filter_params = request.query_params.copy()

        # This will contain some meta data about the request and results
        meta = {}

        # support ranges for date as well as revisions(changes) like old tbpl
        for param in ["fromchange", "tochange", "startdate", "enddate", "revision"]:
            v = filter_params.get(param, None)
            if v:
                del(filter_params[param])
                meta[param] = v

        # translate these params into our own filtering mechanism
        if 'fromchange' in meta:
            filter_params.update({
                "push_timestamp__gte": jm.get_revision_timestamp(meta['fromchange'])
            })
        if 'tochange' in meta:
            filter_params.update({
                "push_timestamp__lte": jm.get_revision_timestamp(meta['tochange'])
            })
        if 'startdate' in meta:
            filter_params.update({
                "push_timestamp__gte": to_timestamp(meta['startdate'])
            })
        if 'enddate' in meta:

            # add a day because we aren't supplying a time, just a date.  So
            # we're doing ``less than``, rather than ``less than or equal to``.
            filter_params.update({
                "push_timestamp__lt": to_timestamp(meta['enddate']) + 86400
            })
        if 'revision' in meta:
            # TODO: modify to use ``short_revision`` or ``long_revision`` fields
            # when addressing Bug 1079796
            # It ends up that we store sometimes long, sometimes short
            # revisions in the ``revision`` field, depending on the repo/source.
            # (gaia, for instance).  So we must search
            # for EITHER the short or long, when long is passed in.
            if len(meta['revision']) > 12:
                filter_params.update(
                    {"revision__in": "{},{}".format(meta['revision'], meta['revision'][:12])}
                )
            else:
                filter_params.update({"revision": meta['revision']})

        meta['filter_params'] = filter_params

        filter = UrlQueryFilter(filter_params)

        offset_id = int(filter.pop("id__lt", 0))
        count = min(int(filter.pop("count", 10)), 1000)

        full = filter.pop('full', 'true').lower() == 'true'

        results = jm.get_result_set_list(
            offset_id,
            count,
            full,
            filter.conditions
        )

        for rs in results:
            rs["revisions_uri"] = reverse("resultset-revisions",
                                          kwargs={"project": jm.project, "pk": rs["id"]})

        meta['count'] = len(results)
        meta['repository'] = project

        resp = {
            'meta': meta,
            'results': results
        }

        return Response(resp)
예제 #9
0
    def list(self, request, project, jm):
        """
        GET method for list of ``resultset`` records with revisions

        """
        # make a mutable copy of these params
        filter_params = request.QUERY_PARAMS.copy()

        # This will contain some meta data about the request and results
        meta = {}

        # support ranges for date as well as revisions(changes) like old tbpl
        for param in ["fromchange", "tochange", "startdate", "enddate"]:
            v = filter_params.get(param, None)
            if v:
                del(filter_params[param])
                meta[param] = v

        # translate these params into our own filtering mechanism
        if 'fromchange' in meta:
            filter_params.update({
                "push_timestamp__gte": jm.get_revision_timestamp(meta['fromchange'])
            })
        if 'tochange' in meta:
            filter_params.update({
                "push_timestamp__lte": jm.get_revision_timestamp(meta['tochange'])
            })
        if 'startdate' in meta:
            filter_params.update({
                "push_timestamp__gte": to_timestamp(meta['startdate'])
            })
        if 'enddate' in meta:

            # add a day because we aren't supplying a time, just a date.  So
            # we're doing ``less than``, rather than ``less than or equal to``.
            filter_params.update({
                "push_timestamp__lt": to_timestamp(meta['enddate']) + 86400
            })

        meta['filter_params'] = filter_params

        filter = UrlQueryFilter(filter_params)

        offset_id = int(filter.pop("id__lt", 0))
        count = min(int(filter.pop("count", 10)), 1000)

        full = filter.pop('full', 'true').lower() == 'true'

        results = jm.get_result_set_list(
            offset_id,
            count,
            full,
            filter.conditions
        )

        for rs in results:
            rs["revisions_uri"] = reverse("resultset-revisions",
                                          kwargs={"project": jm.project, "pk": rs["id"]})

        meta['count'] = len(results)
        meta['repository'] = project

        resp = {
            'meta': meta,
            'results': results
        }

        return Response(resp)
예제 #10
0
 def get_push_timestamp(self, push):
     return to_timestamp(push.time)
 def to_representation(self, value):
     return to_timestamp(value.time)
예제 #12
0
    def list(self, request, project, jm):
        """
        GET method for list of ``resultset`` records with revisions

        """
        # make a mutable copy of these params
        filter_params = request.query_params.copy()

        # This will contain some meta data about the request and results
        meta = {}

        # support ranges for date as well as revisions(changes) like old tbpl
        for param in ["fromchange", "tochange", "startdate", "enddate", "revision"]:
            v = filter_params.get(param, None)
            if v:
                del(filter_params[param])
                meta[param] = v

        # translate these params into our own filtering mechanism
        if 'fromchange' in meta:
            filter_params.update({
                "push_timestamp__gte": jm.get_revision_timestamp(meta['fromchange'])
            })
        if 'tochange' in meta:
            filter_params.update({
                "push_timestamp__lte": jm.get_revision_timestamp(meta['tochange'])
            })
        if 'startdate' in meta:
            filter_params.update({
                "push_timestamp__gte": to_timestamp(meta['startdate'])
            })
        if 'enddate' in meta:

            # add a day because we aren't supplying a time, just a date.  So
            # we're doing ``less than``, rather than ``less than or equal to``.
            filter_params.update({
                "push_timestamp__lt": to_timestamp(meta['enddate']) + 86400
            })
        if 'revision' in meta:
            # TODO: modify to use ``short_revision`` or ``long_revision`` fields
            # when addressing Bug 1079796
            # It ends up that we store sometimes long, sometimes short
            # revisions in the ``revision`` field, depending on the repo/source.
            # (gaia, for instance).  So we must search
            # for EITHER the short or long, when long is passed in.
            if len(meta['revision']) > 12:
                filter_params.update(
                    {"revision__in": "{},{}".format(meta['revision'], meta['revision'][:12])}
                )
            else:
                filter_params.update({"revision": meta['revision']})

        meta['filter_params'] = filter_params

        filter = UrlQueryFilter(filter_params)

        offset_id = int(filter.pop("id__lt", 0))
        count = min(int(filter.pop("count", 10)), 1000)

        full = filter.pop('full', 'true').lower() == 'true'

        results = jm.get_result_set_list(
            offset_id,
            count,
            full,
            filter.conditions
        )

        for rs in results:
            rs["revisions_uri"] = reverse("resultset-revisions",
                                          kwargs={"project": jm.project, "pk": rs["id"]})

        meta['count'] = len(results)
        meta['repository'] = project

        resp = {
            'meta': meta,
            'results': results
        }

        return Response(resp)
예제 #13
0
    def list(self, request, project, jm):
        """
        GET method for list of ``resultset`` records with revisions

        """
        # make a mutable copy of these params
        filter_params = request.QUERY_PARAMS.copy()

        # This will contain some meta data about the request and results
        meta = {}

        # support ranges for date as well as revisions(changes) like old tbpl
        for param in ["fromchange", "tochange", "startdate", "enddate"]:
            v = filter_params.get(param, None)
            if v:
                del (filter_params[param])
                meta[param] = v

        # translate these params into our own filtering mechanism
        if 'fromchange' in meta:
            filter_params.update({
                "push_timestamp__gte":
                jm.get_revision_timestamp(meta['fromchange'])
            })
        if 'tochange' in meta:
            filter_params.update({
                "push_timestamp__lte":
                jm.get_revision_timestamp(meta['tochange'])
            })
        if 'startdate' in meta:
            filter_params.update(
                {"push_timestamp__gte": to_timestamp(meta['startdate'])})
        if 'enddate' in meta:

            # add a day because we aren't supplying a time, just a date.  So
            # we're doing ``less than``, rather than ``less than or equal to``.
            filter_params.update(
                {"push_timestamp__lt": to_timestamp(meta['enddate']) + 86400})

        meta['filter_params'] = filter_params

        filter = UrlQueryFilter(filter_params)

        offset_id = filter.pop("id__lt", 0)
        count = min(int(filter.pop("count", 10)), 1000)

        full = filter.pop('full', 'true').lower() == 'true'
        with_jobs = filter.pop('with_jobs', 'true').lower() == 'true'

        debug = request.QUERY_PARAMS.get('debug', None)

        objs = jm.get_result_set_list(offset_id, count, full,
                                      filter.conditions)

        if with_jobs:
            results = self.get_resultsets_with_jobs(jm, objs, full, {}, debug)
        else:

            for rs in objs:
                rs["revisions_uri"] = reverse("resultset-revisions",
                                              kwargs={
                                                  "project": jm.project,
                                                  "pk": rs["id"]
                                              })

            results = objs

        meta['count'] = len(results)
        meta['repository'] = project

        resp = {
            'meta': meta,
            'results': results,
        }

        if with_jobs:
            resp['job_property_names'] = JOB_PROPERTY_RETURN_KEY

        return Response(resp)
예제 #14
0
 def to_representation(self, value):
     return to_timestamp(value.time)
예제 #15
0
 def get_duration(submit_time, start_time, end_time):
     endtime = end_time if to_timestamp(end_time) else datetime.datetime.now()
     starttime = start_time if to_timestamp(start_time) else submit_time
     seconds = max((endtime - starttime).total_seconds(), 60)
     return max(round(seconds / 60), 1)
예제 #16
0
파일: push.py 프로젝트: xeniorac/treeherder
    def list(self, request, project):
        """
        GET method for list of ``push`` records with revisions
        """
        # What is the upper limit on the number of pushes returned by the api
        MAX_PUSH_COUNT = 1000

        # make a mutable copy of these params
        filter_params = request.query_params.copy()

        # This will contain some meta data about the request and results
        meta = {}

        # support ranges for date as well as revisions(changes) like old tbpl
        for param in [
                "fromchange", "tochange", "startdate", "enddate", "revision"
        ]:
            v = filter_params.get(param, None)
            if v:
                del filter_params[param]
                meta[param] = v

        try:
            repository = Repository.objects.get(name=project)
        except Repository.DoesNotExist:
            return Response(
                {"detail": "No project with name {}".format(project)},
                status=HTTP_404_NOT_FOUND)

        pushes = Push.objects.filter(repository=repository).order_by('-time')

        for (param, value) in iteritems(meta):
            if param == 'fromchange':
                frompush_time = Push.objects.values_list(
                    'time', flat=True).get(repository=repository,
                                           revision__startswith=value)
                pushes = pushes.filter(time__gte=frompush_time)
                filter_params.update(
                    {"push_timestamp__gte": to_timestamp(frompush_time)})

            elif param == 'tochange':
                topush_time = Push.objects.values_list('time', flat=True).get(
                    repository=repository, revision__startswith=value)
                pushes = pushes.filter(time__lte=topush_time)
                filter_params.update(
                    {"push_timestamp__lte": to_timestamp(topush_time)})
            elif param == 'startdate':
                pushes = pushes.filter(time__gte=to_datetime(value))
                filter_params.update(
                    {"push_timestamp__gte": to_timestamp(to_datetime(value))})
            elif param == 'enddate':
                real_end_date = to_datetime(value) + datetime.timedelta(days=1)
                pushes = pushes.filter(time__lte=real_end_date)
                filter_params.update(
                    {"push_timestamp__lt": to_timestamp(real_end_date)})
            elif param == 'revision':
                # revision can be either the revision of the push itself, or
                # any of the commits it refers to
                pushes = pushes.filter(commits__revision__startswith=value)
                rev_key = "revisions_long_revision" \
                          if len(meta['revision']) == 40 else "revisions_short_revision"
                filter_params.update({rev_key: meta['revision']})

        for param in [
                'push_timestamp__lt', 'push_timestamp__lte',
                'push_timestamp__gt', 'push_timestamp__gte'
        ]:
            if filter_params.get(param):
                # translate push timestamp directly into a filter
                try:
                    value = datetime.datetime.fromtimestamp(
                        float(filter_params.get(param)))
                except ValueError:
                    return Response(
                        {
                            "detail":
                            "Invalid timestamp specified for {}".format(param)
                        },
                        status=HTTP_400_BAD_REQUEST)
                pushes = pushes.filter(
                    **{param.replace('push_timestamp', 'time'): value})

        for param in ['id__lt', 'id__lte', 'id__gt', 'id__gte', 'id']:
            try:
                value = int(filter_params.get(param, 0))
            except ValueError:
                return Response(
                    {
                        "detail":
                        "Invalid timestamp specified for {}".format(param)
                    },
                    status=HTTP_400_BAD_REQUEST)
            if value:
                pushes = pushes.filter(**{param: value})

        id_in = filter_params.get("id__in")
        if id_in:
            try:
                id_in_list = [int(id) for id in id_in.split(',')]
            except ValueError:
                return Response({"detail": "Invalid id__in specification"},
                                status=HTTP_400_BAD_REQUEST)
            pushes = pushes.filter(id__in=id_in_list)

        author = filter_params.get("author")
        if author:
            pushes = pushes.filter(author=author)

        try:
            count = int(filter_params.get("count", 10))
        except ValueError:
            return Response({"detail": "Valid count value required"},
                            status=HTTP_400_BAD_REQUEST)

        if count > MAX_PUSH_COUNT:
            msg = "Specified count exceeds api limit: {}".format(
                MAX_PUSH_COUNT)
            return Response({"detail": msg}, status=HTTP_400_BAD_REQUEST)

        # we used to have a "full" parameter for this endpoint so you could
        # specify to not fetch the revision information if it was set to
        # false. however AFAIK no one ever used it (default was to fetch
        # everything), so let's just leave it out. it doesn't break
        # anything to send extra data when not required.
        pushes = pushes.select_related('repository').prefetch_related(
            'commits')[:count]
        serializer = PushSerializer(pushes, many=True)

        meta['count'] = len(pushes)
        meta['repository'] = project
        meta['filter_params'] = filter_params

        resp = {'meta': meta, 'results': serializer.data}

        return Response(resp)
예제 #17
0
 def get_push_timestamp(self, push):
     return to_timestamp(push.time)
예제 #18
0
    def list(self, request, project, jm):
        """
        GET method for list of ``resultset`` records with revisions

        """
        # make a mutable copy of these params
        filter_params = request.query_params.copy()

        # This will contain some meta data about the request and results
        meta = {}

        # support ranges for date as well as revisions(changes) like old tbpl
        for param in [
                "fromchange", "tochange", "startdate", "enddate", "revision"
        ]:
            v = filter_params.get(param, None)
            if v:
                del (filter_params[param])
                meta[param] = v

        # create a timestamp lookup based on the from/to change params that may
        # exist. This means we only make 1 DB query rather than 2, if we have
        # both a ``fromchange`` and a ``tochange`` value.
        ts_lookup = jm.get_resultset_all_revision_lookup(
            [meta[x] for x in ['fromchange', 'tochange'] if x in meta])

        # translate these params into our own filtering mechanism
        if 'fromchange' in meta:
            filter_params.update({
                "push_timestamp__gte":
                ts_lookup[meta['fromchange']]["push_timestamp"]
            })
        if 'tochange' in meta:
            filter_params.update({
                "push_timestamp__lte":
                ts_lookup[meta['tochange']]["push_timestamp"]
            })
        if 'startdate' in meta:
            filter_params.update(
                {"push_timestamp__gte": to_timestamp(meta['startdate'])})
        if 'enddate' in meta:

            # add a day because we aren't supplying a time, just a date.  So
            # we're doing ``less than``, rather than ``less than or equal to``.
            filter_params.update(
                {"push_timestamp__lt": to_timestamp(meta['enddate']) + 86400})
        if 'revision' in meta:
            # Allow the user to search by either the short or long version of
            # a revision.
            rev_key = "revisions_long_revision" \
                if len(meta['revision']) == 40 else "revisions_short_revision"
            filter_params.update({rev_key: meta['revision']})

        meta['filter_params'] = filter_params

        filter = UrlQueryFilter(filter_params)

        offset_id = int(filter.pop("id__lt", 0))
        count = min(int(filter.pop("count", 10)), 1000)

        full = filter.pop('full', 'true').lower() == 'true'

        results = jm.get_result_set_list(offset_id, count, full,
                                         filter.conditions)

        for rs in results:
            rs["revisions_uri"] = reverse("resultset-revisions",
                                          kwargs={
                                              "project": jm.project,
                                              "pk": rs["id"]
                                          })

        meta['count'] = len(results)
        meta['repository'] = project

        resp = {'meta': meta, 'results': results}

        return Response(resp)