示例#1
0
    def generate(self):
        needFiles = False
        if len(self.files) > 0:
            needFiles = True

        query = OperationQuery(self.client,
                               {
                                   "project": self.projects,
                                   "status": [ OperationQuery.STATUS_OPEN ],
                                   "branch": self.branches,
                                   "topic": self.topics,
                                   "reviewer": self.reviewers,
                               },
                               patches=OperationQuery.PATCHES_ALL,
                               approvals=True,
                               files=needFiles)

        def match_files(change):
            if len(self.files) == 0:
                return True
            for filere in self.files:
                for patch in change.patches:
                    for file in patch.files:
                        if re.search(filere, file.path):
                            return True
            return False

        table = self.new_table("Changes To Do List")
        def querycb(change):
            if self.filter(change) and match_files(change):
                table.add_row(change)

        query.run(querycb)

        return table
示例#2
0
    def generate(self):
        # We could query all projects at once, but if we do them
        # individually it means we get better hit rate against the
        # cache if the report is re-run for many different project
        # combinations
        reviewers = {}
        now = time.time()
        for project in self.projects:
            query = OperationQuery(self.client,
                                   {
                                       "project": [project],
                                   },
                                   patches=OperationQuery.PATCHES_ALL,
                                   approvals=True)


            def querycb(change):
                for patch in change.patches:
                    for approval in patch.approvals:
                        if approval.action == ModelApproval.ACTION_VERIFIED:
                            continue

                        user = approval.user
                        if user is None or user.username is None:
                            continue
                        username = user.username

                        if username not in reviewers:
                            reviewers[username] = { "total": 0}

                        agesecs = approval.get_age(now)
                        ageweeks = int(agesecs / (60 * 60 * 24 * 7)) + 1
                        key = "week%d" % ageweeks

                        if key not in reviewers[username]:
                            reviewers[username][key] = 0

                        reviewers[username][key] = reviewers[username][key] + 1

                        if ageweeks <= 52:
                            reviewers[username]["total"] = reviewers[username]["total"] + 1

            query.run(querycb)

        table = self.new_table("Daily review rates per week")

        for reviewer in reviewers.keys():
            userteam = ""
            for team in self.teams.keys():
                if reviewer in self.teams[team]:
                    userteam = team

            table.add_row([reviewer, userteam, reviewers[reviewer]])

        return table
示例#3
0
    def run(self, config, client, options):
        change = options.change

        query = OperationQuery(
            client, {"change": [change]}, patches=OperationQuery.PATCHES_ALL, approvals=True, files=True, comments=True
        )

        if options.all:
            bots = []
        else:
            bots = config.get_organization_bots()

        def mycb(change):
            self.format_change(change, bots, options.color, options.current, int(options.patch))

        query.run(mycb, limit=1)
示例#4
0
    def generate(self):
        query = OperationQuery(self.client,
                               {
                                   "project": self.projects,
                                   "status": [ OperationQuery.STATUS_OPEN ],
                                   "reviewer": self.reviewers,
                               },
                               patches=OperationQuery.PATCHES_ALL,
                               approvals=True)

        table = self.new_table("Changes To Do List")
        def querycb(change):
            if self.filter(change):
                table.add_row(change)

        query.run(querycb)

        return table
示例#5
0
    def generate(self):
        query = OperationQuery(self.client, {
            "project": self.projects,
            "status": [OperationQuery.STATUS_OPEN],
            "reviewer": self.reviewers,
        },
                               patches=OperationQuery.PATCHES_ALL,
                               approvals=True)

        table = self.new_table("Changes To Do List")

        def querycb(change):
            if self.filter(change):
                table.add_row(change)

        query.run(querycb)

        return table
示例#6
0
    def run(self, config, client, options):
        change = options.change

        query = OperationQuery(client,
                               {
                                   "change": [ change ],
                               },
                               patches=OperationQuery.PATCHES_ALL,
                               approvals=True,
                               files=True,
                               comments=True)

        if options.all:
            bots = []
        else:
            bots = config.get_organization_bots()

        def mycb(change):
            self.format_change(change, bots, options.color, options.current, int(options.patch))

        query.run(mycb, limit=1)
示例#7
0
    def generate(self):
        needFiles = False
        if len(self.files) > 0:
            needFiles = True

        query = OperationQuery(self.client,
                               {
                                   "project": self.projects,
                                   "owner": self.owners,
                                   "message": self.messages,
                                   "branch": self.branches,
                                   "topic": self.topics,
                                   "status": self.status,
                                   "reviewer": self.reviewers,
                               },
                               rawquery=self.rawquery,
                               patches=OperationQuery.PATCHES_CURRENT,
                               approvals=True,
                               files=needFiles)

        def match_files(change):
            if len(self.files) == 0:
                return True
            for filere in self.files:
                for patch in change.patches:
                    for file in patch.files:
                        if re.search(filere, file.path):
                            return True
            return False

        table = self.new_table("Changes")
        def querycb(change):
            if match_files(change):
                table.add_row(change)

        query.run(querycb)

        return table
示例#8
0
    def generate(self):
        needFiles = False
        if len(self.files) > 0:
            needFiles = True

        query = OperationQuery(self.client, {
            "project": self.projects,
            "owner": self.owners,
            "message": self.messages,
            "branch": self.branches,
            "status": self.status,
            "reviewer": self.reviewers,
        },
                               rawquery=self.rawquery,
                               patches=OperationQuery.PATCHES_CURRENT,
                               approvals=True,
                               files=needFiles)

        def match_files(change):
            if len(self.files) == 0:
                return True
            for filere in self.files:
                for patch in change.patches:
                    for file in patch.files:
                        if re.search(filere, file.path):
                            return True
            return False

        table = self.new_table("Changes")

        def querycb(change):
            if match_files(change):
                table.add_row(change)

        query.run(querycb)

        return table
示例#9
0
    def generate(self):
        # We could query all projects at once, but if we do them
        # individually it means we get better hit rate against the
        # cache if the report is re-run for many different project
        # combinations
        reviews = []
        cutoff = time.time() - (self.maxagedays * 24 * 60 * 60)
        for project in self.projects:
            query = OperationQuery(self.client,
                                   {
                                       "project": [project],
                                   },
                                   patches=OperationQuery.PATCHES_ALL,
                                   approvals=True)


            def querycb(change):
                for patch in change.patches:
                    for approval in patch.approvals:
                        if approval.is_newer_than(cutoff):
                            reviews.append(approval)

            query.run(querycb)

        reviewers = {}
        for review in reviews:
            if review.action != ModelApproval.ACTION_REVIEWED or review.user is None:
                continue

            reviewer = review.user.username
            if reviewer is None:
                reviewer = review.user.name
                if reviewer is None:
                    continue

            if reviewer.lower() in ["jenkins", "smokestack"]:
                continue

            reviewers.setdefault(reviewer,
                                 {
                                     'votes': {'flag-m2': 0, 'flag-m1': 0, 'flag-p1': 0, 'flag-p2': 0},
                                     'total': 0,
                                 })
            reviewers[reviewer]['total'] = reviewers[reviewer]['total'] + 1
            votes = { "-2" : "flag-m2",
                      "-1" : "flag-m1",
                      "1" : "flag-p1",
                      "2" : "flag-p2" }
            cur = reviewers[reviewer]['votes'][votes[str(review.value)]]
            reviewers[reviewer]['votes'][votes[str(review.value)]] = cur + 1

        compound = ReportOutputCompound()
        table = self.new_table("Review statistics")
        compound.add_report(table)

        for user, votes in reviewers.items():
            userteam = ""
            for team in self.teams.keys():
                if user in self.teams[team]:
                    userteam = team

            table.add_row([user, votes, userteam])

        summary = ReportOutputList([
            ReportOutputColumn("nreviews", "Total reviews", format="%d",
                               mapfunc=lambda rep, col, row: row[0]),
            ReportOutputColumn("nreviewers", "Total rviewers", format="%d",
                               mapfunc=lambda rep, col, row: row[1])
        ], title="Review summary")
        summary.set_row([len(reviews), len(reviewers.keys())])
        compound.add_report(summary)

        return compound
示例#10
0
    def generate(self):
        # We could query all projects at once, but if we do them
        # individually it means we get better hit rate against the
        # cache if the report is re-run for many different project
        # combinations
        agecurrent = {}
        agefirst = {}
        agenonnacked = {}
        wait_reviewer = []
        wait_submitter = []
        changes = {}
        for project in self.projects:
            query = OperationQuery(self.client,
                                   {
                                       "project": [project],
                                       "status": [OperationQuery.STATUS_OPEN],
                                       "branch": [self.branch],
                                       "topic": [self.topic],
                                   },
                                   patches=OperationQuery.PATCHES_ALL,
                                   approvals=True)


            def querycb(change):
                if change.status != "NEW":
                    return

                now = time.time()
                current = change.get_current_patch()
                first = change.get_first_patch()
                nonnacked = change.get_reviewer_not_nacked_patch()

                changes[change.id] = change

                if current.is_nacked():
                    wait_submitter.append(change.id)
                else:
                    wait_reviewer.append(change.id)

                agecurrent[change.id] = current.get_age(now)
                agefirst[change.id] = first.get_age(now)
                if nonnacked:
                    agenonnacked[change.id] = nonnacked.get_age(now)
                else:
                    agenonnacked[change.id] = 0

            query.run(querycb)

        compound = ReportOutputCompound()
        summary = ReportOutputList([
            ReportOutputColumn("nreviews", "Total open reviews", format="%d",
                               mapfunc=lambda rep, col, row: row[0] + row [1]),
            ReportOutputColumn("waitsubmitter", "Waiting on submitter", format="%d",
                               mapfunc=lambda rep, col, row: row[0]),
            ReportOutputColumn("waitreviewer", "Waiting on reviewer", format="%d",
                               mapfunc=lambda rep, col, row: row[1]),
        ], title="Review summary")
        summary.set_row([len(wait_submitter), len(wait_reviewer)])
        compound.add_report(summary)

        lastrev = ReportOutputList([
            ReportOutputColumn("average", "Average wait time",
                               mapfunc=lambda rep, col, row: row[0]),
            ReportOutputColumn("median", "Median wait time",
                               mapfunc=lambda rep, col, row: row[1]),
            ReportOutputColumn("stale", "Older than %d days" % self.days, format="%d",
                               mapfunc=lambda rep, col, row: row[2]),
        ], title="Summary since current revision")
        lastrev.set_row([self.average_age(wait_reviewer, agecurrent),
                         self.median_age(wait_reviewer, agecurrent),
                         self.older_than(wait_reviewer, agecurrent, self.days)])
        compound.add_report(lastrev)


        firstrev = ReportOutputList([
            ReportOutputColumn("average", "Average wait time",
                               mapfunc=lambda rep, col, row: row[0]),
            ReportOutputColumn("median", "Median wait time",
                               mapfunc=lambda rep, col, row: row[1]),
        ], title="Summary since first revision")
        firstrev.set_row([self.average_age(wait_reviewer, agefirst),
                          self.median_age(wait_reviewer, agefirst)])
        compound.add_report(firstrev)


        nonnackedrev = ReportOutputList([
            ReportOutputColumn("average", "Average wait time",
                               mapfunc=lambda rep, col, row: row[0]),
            ReportOutputColumn("median", "Median wait time",
                               mapfunc=lambda rep, col, row: row[1]),
        ], title="Summary since last revision without -1/-2 from reviewer")
        nonnackedrev.set_row([self.average_age(wait_reviewer, agenonnacked),
                              self.median_age(wait_reviewer, agenonnacked)])
        compound.add_report(nonnackedrev)


        def waitlastmap(rep, col, row):
            return format_delta(row.get_current_age())

        def waitlastsort(rep, col, row):
            return row.get_current_age()

        waitlastrev = self.new_table("Longest waiting since current revision")
        waitlastrev.add_column(ReportOutputColumn("age", "Age",
                                                  sortfunc=waitlastsort,
                                                  mapfunc=waitlastmap))
        waitlastrev.sortcol = "age"
        waitlastrev.reverse = True
        for change in self.get_longest_changes(wait_reviewer, changes, agecurrent, 5):
            waitlastrev.add_row(change)
        compound.add_report(waitlastrev)


        def waitfirstmap(rep, col, row):
            return format_delta(row.get_first_age())

        def waitfirstsort(rep, col, row):
            return row.get_first_age()

        waitfirstrev = self.new_table("Longest waiting since first revision")
        waitfirstrev.add_column(ReportOutputColumn("age", "Age",
                                                   sortfunc=waitfirstsort,
                                                   mapfunc=waitfirstmap))
        waitfirstrev.sortcol = "age"
        waitfirstrev.reverse = True
        for change in self.get_longest_changes(wait_reviewer, changes, agefirst, 5):
            waitfirstrev.add_row(change)
        compound.add_report(waitfirstrev)


        def waitnonnackedmap(rep, col, row):
            return format_delta(row.get_reviewer_not_nacked_age())

        def waitnonnackedsort(rep, col, row):
            return row.get_reviewer_not_nacked_age()

        waitnonnackedrev = self.new_table("Longest waiting since last revision without -1/-2 from reviewer")
        waitnonnackedrev.add_column(ReportOutputColumn("age", "Age",
                                                       sortfunc=waitnonnackedsort,
                                                       mapfunc=waitnonnackedmap))
        waitnonnackedrev.sortcol = "age"
        waitnonnackedrev.reverse = True
        for change in self.get_longest_changes(wait_reviewer, changes, agenonnacked, 5):
            waitnonnackedrev.add_row(change)
        compound.add_report(waitnonnackedrev)

        return compound
示例#11
0
    def generate(self):
        # We could query all projects at once, but if we do them
        # individually it means we get better hit rate against the
        # cache if the report is re-run for many different project
        # combinations
        agecurrent = {}
        agefirst = {}
        agenonnacked = {}
        wait_reviewer = []
        wait_submitter = []
        changes = {}
        for project in self.projects:
            query = OperationQuery(self.client, {
                "project": [project],
                "status": [OperationQuery.STATUS_OPEN],
                "branch": [self.branch],
            },
                                   patches=OperationQuery.PATCHES_ALL,
                                   approvals=True)

            def querycb(change):
                if change.status != "NEW":
                    return

                now = time.time()
                current = change.get_current_patch()
                first = change.get_first_patch()
                nonnacked = change.get_reviewer_not_nacked_patch()

                changes[change.id] = change

                if current.is_nacked():
                    wait_submitter.append(change.id)
                else:
                    wait_reviewer.append(change.id)

                agecurrent[change.id] = current.get_age(now)
                agefirst[change.id] = first.get_age(now)
                if nonnacked:
                    agenonnacked[change.id] = nonnacked.get_age(now)
                else:
                    agenonnacked[change.id] = 0

            query.run(querycb)

        compound = ReportOutputCompound()
        summary = ReportOutputList([
            ReportOutputColumn("nreviews",
                               "Total open reviews",
                               format="%d",
                               mapfunc=lambda rep, col, row: row[0] + row[1]),
            ReportOutputColumn("waitsubmitter",
                               "Waiting on submitter",
                               format="%d",
                               mapfunc=lambda rep, col, row: row[0]),
            ReportOutputColumn("waitreviewer",
                               "Waiting on reviewer",
                               format="%d",
                               mapfunc=lambda rep, col, row: row[1]),
        ],
                                   title="Review summary")
        summary.set_row([len(wait_submitter), len(wait_reviewer)])
        compound.add_report(summary)

        lastrev = ReportOutputList([
            ReportOutputColumn("average",
                               "Average wait time",
                               mapfunc=lambda rep, col, row: row[0]),
            ReportOutputColumn("median",
                               "Median wait time",
                               mapfunc=lambda rep, col, row: row[1]),
            ReportOutputColumn("stale",
                               "Older than %d days" % self.days,
                               format="%d",
                               mapfunc=lambda rep, col, row: row[2]),
        ],
                                   title="Summary since current revision")
        lastrev.set_row([
            self.average_age(wait_reviewer, agecurrent),
            self.median_age(wait_reviewer, agecurrent),
            self.older_than(wait_reviewer, agecurrent, self.days)
        ])
        compound.add_report(lastrev)

        firstrev = ReportOutputList([
            ReportOutputColumn("average",
                               "Average wait time",
                               mapfunc=lambda rep, col, row: row[0]),
            ReportOutputColumn("median",
                               "Median wait time",
                               mapfunc=lambda rep, col, row: row[1]),
        ],
                                    title="Summary since first revision")
        firstrev.set_row([
            self.average_age(wait_reviewer, agefirst),
            self.median_age(wait_reviewer, agefirst)
        ])
        compound.add_report(firstrev)

        nonnackedrev = ReportOutputList(
            [
                ReportOutputColumn("average",
                                   "Average wait time",
                                   mapfunc=lambda rep, col, row: row[0]),
                ReportOutputColumn("median",
                                   "Median wait time",
                                   mapfunc=lambda rep, col, row: row[1]),
            ],
            title="Summary since last revision without -1/-2 from reviewer")
        nonnackedrev.set_row([
            self.average_age(wait_reviewer, agenonnacked),
            self.median_age(wait_reviewer, agenonnacked)
        ])
        compound.add_report(nonnackedrev)

        def waitlastmap(rep, col, row):
            return format_delta(row.get_current_age())

        def waitlastsort(rep, col, row):
            return row.get_current_age()

        waitlastrev = self.new_table("Longest waiting since current revision")
        waitlastrev.add_column(
            ReportOutputColumn("age",
                               "Age",
                               sortfunc=waitlastsort,
                               mapfunc=waitlastmap))
        waitlastrev.sortcol = "age"
        waitlastrev.reverse = True
        for change in self.get_longest_changes(wait_reviewer, changes,
                                               agecurrent, 5):
            waitlastrev.add_row(change)
        compound.add_report(waitlastrev)

        def waitfirstmap(rep, col, row):
            return format_delta(row.get_first_age())

        def waitfirstsort(rep, col, row):
            return row.get_first_age()

        waitfirstrev = self.new_table("Longest waiting since first revision")
        waitfirstrev.add_column(
            ReportOutputColumn("age",
                               "Age",
                               sortfunc=waitfirstsort,
                               mapfunc=waitfirstmap))
        waitfirstrev.sortcol = "age"
        waitfirstrev.reverse = True
        for change in self.get_longest_changes(wait_reviewer, changes,
                                               agefirst, 5):
            waitfirstrev.add_row(change)
        compound.add_report(waitfirstrev)

        def waitnonnackedmap(rep, col, row):
            return format_delta(row.get_reviewer_not_nacked_age())

        def waitnonnackedsort(rep, col, row):
            return row.get_reviewer_not_nacked_age()

        waitnonnackedrev = self.new_table(
            "Longest waiting since last revision without -1/-2 from reviewer")
        waitnonnackedrev.add_column(
            ReportOutputColumn("age",
                               "Age",
                               sortfunc=waitnonnackedsort,
                               mapfunc=waitnonnackedmap))
        waitnonnackedrev.sortcol = "age"
        waitnonnackedrev.reverse = True
        for change in self.get_longest_changes(wait_reviewer, changes,
                                               agenonnacked, 5):
            waitnonnackedrev.add_row(change)
        compound.add_report(waitnonnackedrev)

        return compound
示例#12
0
    def generate(self):
        # We could query all projects at once, but if we do them
        # individually it means we get better hit rate against the
        # cache if the report is re-run for many different project
        # combinations
        reviews = []
        cutoff = time.time() - (self.maxagedays * 24 * 60 * 60)
        for project in self.projects:
            query = OperationQuery(self.client, {
                "project": [project],
            },
                                   patches=OperationQuery.PATCHES_ALL,
                                   approvals=True)

            def querycb(change):
                for patch in change.patches:
                    for approval in patch.approvals:
                        if approval.is_newer_than(cutoff):
                            reviews.append(approval)

            query.run(querycb)

        reviewers = {}
        for review in reviews:
            if review.action != ModelApproval.ACTION_REVIEWED or review.user is None:
                continue

            reviewer = review.user.username
            if reviewer is None:
                reviewer = review.user.name
                if reviewer is None:
                    continue

            if reviewer.lower() in ["jenkins", "smokestack"]:
                continue

            reviewers.setdefault(
                reviewer, {
                    'votes': {
                        'flag-m2': 0,
                        'flag-m1': 0,
                        'flag-p1': 0,
                        'flag-p2': 0
                    },
                    'total': 0,
                })
            reviewers[reviewer]['total'] = reviewers[reviewer]['total'] + 1
            votes = {
                "-2": "flag-m2",
                "-1": "flag-m1",
                "1": "flag-p1",
                "2": "flag-p2"
            }
            cur = reviewers[reviewer]['votes'][votes[str(review.value)]]
            reviewers[reviewer]['votes'][votes[str(review.value)]] = cur + 1

        compound = ReportOutputCompound()
        table = self.new_table("Review statistics")
        compound.add_report(table)

        for user, votes in reviewers.items():
            userteam = ""
            for team in self.teams.keys():
                if user in self.teams[team]:
                    userteam = team

            table.add_row([user, votes, userteam])

        summary = ReportOutputList([
            ReportOutputColumn("nreviews",
                               "Total reviews",
                               format="%d",
                               mapfunc=lambda rep, col, row: row[0]),
            ReportOutputColumn("nreviewers",
                               "Total rviewers",
                               format="%d",
                               mapfunc=lambda rep, col, row: row[1])
        ],
                                   title="Review summary")
        summary.set_row([len(reviews), len(reviewers.keys())])
        compound.add_report(summary)

        return compound