dev-tools/report/report.py (181 lines of code) (raw):

#!/usr/bin/env python3 # -*- coding: utf-8 -*- # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from datetime import datetime from jira_github import Jira from .formatter import Formatter def daydiff(a, b): return (a - b).days class Report: now = datetime.utcnow() def __init__(self, header=''): self.header = header # if padding starts with - it puts padding before contents, otherwise after @staticmethod def _build_tuple(contents, padding=''): if padding: out = [] for i in range(len(contents)): out += [padding[1:] + str(contents[i])] if padding[0] == '-' else [str(contents[i]) + padding] return tuple(out) return contents # calls the native print function with the following format. Text1,Text2,... has the correct spacing # print("%s%s%s" % ("Text1, Text2, Text3)) def print_(self, formatter, row_tuple): print(formatter.format % formatter.row_str_format(row_tuple)) class JiraReport(Report): def __init__(self, issues, header=''): Report.__init__(self, header) self.issues = issues def view(self, excluded): issues_view = dict(self.issues) for key in excluded: issues_view.pop(key, None) return issues_view def keys_view(self, excluded): return self.view(excluded).keys().sort(Jira.storm_jira_cmp, reverse=True) def values_view(self, excluded=None): temp_dic = dict(self.issues) if excluded is None else self.view(excluded) return sorted(temp_dic.values(), key=lambda jira: jira.get_id_num(), reverse=True) @staticmethod def _row_tuple(jira): return (jira.get_id(), jira.get_trimmed_summary(), daydiff(Report.now, jira.get_created()), daydiff(Report.now, jira.get_updated())) def _min_width_tuple(self): return -1, 43, -1, -1 def print_report(self): print(f"{self.header} (Count = {len(self.issues)}) ") jiras = self.values_view() fields_tuple = ('Jira Id', 'Summary', 'Created', 'Last Updated (Days)') row_tuple = self._row_tuple(jiras[0]) formatter = Formatter(fields_tuple, row_tuple, self._min_width_tuple()) self.print_(formatter, fields_tuple) for jira in jiras: row_tuple = self._row_tuple(jira) self.print_(formatter, row_tuple) @staticmethod def build_jira_url(jira_id): BASE_URL = "https://issues.apache.org/jira/browse/" return BASE_URL + jira_id class GitHubReport(Report): def __init__(self, pull_requests=None, header=''): Report.__init__(self, header) if pull_requests is None: self.pull_requests = [] self.type = '' else: self.pull_requests = pull_requests self.type = type def _row_tuple(self, pull): return self._build_tuple( (pull.html_url(), pull.trimmed_title(), daydiff(Report.now, pull.created_at()), daydiff(Report.now, pull.updated_at()), pull.user()), '') def _min_width_tuple(self): return -1, 43, -1, -1, -1 def print_report(self): print("%s (Count = %s) " % (self.header, len(self.pull_requests))) fields_tuple = self._build_tuple(('URL', 'Title', 'Created', 'Last Updated (Days)', 'User'), '') if len(self.pull_requests) > 0: row_tuple = self._row_tuple(self.pull_requests[0]) formatter = Formatter(fields_tuple, row_tuple, self._min_width_tuple()) self.print_(formatter, fields_tuple) for pull in self.pull_requests: row_tuple = self._row_tuple(pull) self.print_(formatter, row_tuple) def jira_ids(self): """ :return: sorted list of JIRA ids present in Git pull requests """ jira_ids = list() for pull in self.pull_requests: jira_ids.append(pull.jira_id()) return sorted(jira_ids) class JiraGitHubCombinedReport(Report): def __init__(self, jira_report, github_report, header='', print_comments=False): Report.__init__(self, header) self.jira_report = jira_report self.github_report = github_report self.print_comments = print_comments def _jira_comments(self, jira_id): return None if jira_id is None else self.jira_report.issues[jira_id].get_comments() def _idx_1st_comment_with_vote(self): g = 0 for pull in self.github_report.pull_requests: c = 0 for comment in self._jira_comments(pull.jira_id()): if comment.has_vote(): return(g,) + (c,) c += 1 g += 1 def _pull_request(self, pull_idx): pull = self.github_report.pull_requests[pull_idx] return pull def _jira_id(self, pull_idx): pull = self._pull_request(pull_idx) return str(pull.jira_id()) def _jira_issue(self, jira_id): return self.jira_report.issues[jira_id] def _row_tuple(self, pull_idx): pull = self._pull_request(pull_idx) jira_id = self._jira_id(pull_idx) jira_issue = self._jira_issue(jira_id) return (jira_id, str(pull) if pull else "No PR", jira_issue.get_trimmed_summary(), daydiff(Report.now, jira_issue.get_created()), daydiff(Report.now, pull.created_at() if pull else "No PR"), daydiff(Report.now, jira_issue.get_updated()), daydiff(Report.now, pull.updated_at() if pull else "No PR"), jira_issue.get_status(), pull.user()) def _row_tuple_1(self, pull_idx, comment_idx): row_tuple_1 = None jira_id = self._jira_id(pull_idx) jira_comments = self._jira_comments(jira_id) comment = jira_comments[comment_idx] if comment.has_vote(): row_tuple_1 = (comment.get_vote(), comment.get_author(), comment.get_pull(), daydiff(Report.now, comment.get_created())) return row_tuple_1 # variables and method names ending with _1 correspond to the comments part def print_report(self, print_comments=False): pull_request_cnt = len(self.github_report.pull_requests) print("%s (Count = %s) " % (self.header, pull_request_cnt)) if not pull_request_cnt: return fields_tuple = ('JIRA ID', 'Pull Request', 'Jira Summary', 'JIRA Age', 'Pull Age', 'JIRA Update Age', 'Pull Update Age (Days)', 'JIRA Status', 'GitHub user') row_tuple = self._row_tuple(0) formatter = Formatter(fields_tuple, row_tuple) self.print_(formatter, fields_tuple) if print_comments or self.print_comments: fields_tuple_1 = self._build_tuple(('Comment Vote', 'Comment Author', 'Pull URL', 'Comment Age'), '-\t\t') row_tuple_1 = self._build_tuple(self._row_tuple_1(*self._idx_1st_comment_with_vote()), '-\t\t') formatter_1 = Formatter(fields_tuple_1, row_tuple_1) self.print_(formatter_1, fields_tuple_1) print('') for p in range(0, len(self.github_report.pull_requests)): row_tuple = self._row_tuple(p) self.print_(formatter, row_tuple) if print_comments or self.print_comments: has_vote = False comments = self._jira_comments(self._jira_id(p)) for c in range(len(comments)): # Check cleaner way comment = comments[c] if comment.has_vote(): row_tuple_1 = self._build_tuple(self._row_tuple_1(p, c), '-\t\t') if row_tuple_1 is not None: formatter_1 = Formatter() self.print_(formatter_1, row_tuple_1) has_vote = True if has_vote: print('') class CompleteReport(Report): def __init__(self, header=''): Report.__init__(self, header) self.jira_reports = [] self.github_reports = [] self.jira_github_combined_reports = [] def print_all(self): if self.header: print(self.header) self._print_github_reports() self._print_jira_github_combined_reports() self._print_jira_reports() def _print_jira_reports(self): for jira in self.jira_reports: jira.print_report() def _print_github_reports(self): for github in self.github_reports: github.print_report() def _print_jira_github_combined_reports(self): for jira_github_combined in self.jira_github_combined_reports: jira_github_combined.print_report()