from typing import Dict, Iterable, List, Set, Tuple from github_client import GitHubClient, GitHubError from issues import issue_key, matching_candidates from model import Issue, Occurrence, RemoteIssue GroupedOccurrences = Dict[Tuple[str, str, str], List[Occurrence]] def _snapshot(client: GitHubClient, remote: RemoteIssue, include_comments: bool) -> Issue: comments = tuple(comment.body or "" for comment in client.comments(remote.number)) if include_comments else () return Issue(remote.number, remote.state, remote.body or "", comments, remote.closed_at, remote.labels) def snapshots(client: GitHubClient, comment_numbers: Iterable[int] = ()) -> List[Issue]: comment_numbers = set(comment_numbers) return [_snapshot(client, remote, remote.number in comment_numbers) for remote in client.issues()] def _complete_snapshots(client: GitHubClient, grouped: GroupedOccurrences) -> List[Issue]: issue_list = snapshots(client) comment_numbers: Set[int] = set() for (branch, classname, testcase_name), occurrences in grouped.items(): latest = occurrences[-1] comment_numbers.update(issue.number for issue in matching_candidates(latest.repository, branch, classname, testcase_name, issue_list)) if not comment_numbers: return issue_list comments = {number: tuple(comment.body or "" for comment in client.comments(number)) for number in comment_numbers} return [Issue(issue.number, issue.state, issue.body, comments.get(issue.number, ()), issue.closed_at, issue.labels) for issue in issue_list] def lookup_issue_candidates(client: GitHubClient, grouped: GroupedOccurrences) -> List[Issue]: candidates: Dict[int, Issue] = {} try: for (branch, classname, testcase_name), occurrences in grouped.items(): latest = occurrences[-1] number = client.search_issue(issue_key(latest.repository, branch, classname, testcase_name)) if number is None: return _complete_snapshots(client, grouped) remote = client.issue(number) candidate = _snapshot(client, remote, False) if remote.is_pull_request or len(matching_candidates(latest.repository, branch, classname, testcase_name, (candidate,))) != 1: return _complete_snapshots(client, grouped) candidates[candidate.number] = candidate except GitHubError: return _complete_snapshots(client, grouped) return [Issue(candidate.number, candidate.state, candidate.body, tuple(comment.body or "" for comment in client.comments(candidate.number)), candidate.closed_at, candidate.labels) for candidate in candidates.values()]