def check_reviews_repobee_4(allocations_file: pathlib.Path, title_regex: str, api: plug.PlatformAPI) -> None: """Preview version of the `reviews check` command for RepoBee 4.""" data = json.loads(allocations_file.read_text(sys.getdefaultencoding())) review_allocations = data["allocations"] num_reviews = int(data["num_reviews"]) expected_reviewers = { allocation["reviewed_repo"]["url"]: allocation["review_team"]["members"] for allocation in review_allocations } reviewed_repos = progresswrappers.get_repos(expected_reviewers.keys(), api) reviews = collections.defaultdict(list) for reviewed_repo in reviewed_repos: review_issue_authors = { issue.author for issue in api.get_repo_issues(reviewed_repo) if re.match(title_regex, issue.title) } for expected_reviewer in expected_reviewers[reviewed_repo.url]: reviews[expected_reviewer].append( plug.Review( repo=reviewed_repo.name, done=expected_reviewer in review_issue_authors, )) plug.echo( formatters.format_peer_review_progress_output( reviews, list(itertools.chain.from_iterable(expected_reviewers.values())), num_reviews, ))
def close_issue( title_regex: str, repos: Iterable[plug.StudentRepo], api: plug.PlatformAPI ) -> None: """Close issues whose titles match the title_regex in student repos. Args: title_regex: A regex to match against issue titles. assignment_names: Names of assignments. teams: Team objects specifying student groups. api: An implementation of :py:class:`repobee_plug.PlatformAPI` used to interface with the platform (e.g. GitHub or GitLab) instance. """ repo_urls = (repo.url for repo in repos) platform_repos = progresswrappers.get_repos(repo_urls, api) for repo in platform_repos: to_close = [ issue for issue in api.get_repo_issues(repo) if re.match(title_regex, issue.title) and issue.state == plug.IssueState.OPEN ] for issue in to_close: api.close_issue(issue) msg = f"Closed {repo.name}/#{issue.number}='{issue.title}'" platform_repos.write(msg) # type: ignore plug.log.info(msg)
def check_peer_review_progress( assignment_names: Iterable[str], teams: Iterable[plug.Team], title_regex: str, num_reviews: int, api: plug.PlatformAPI, ) -> None: """Check which teams have opened peer review issues in their allotted review repos Args: assignment_names: Names of assignments. teams: An iterable of student teams. title_regex: A regex to match against issue titles. num_reviews: Amount of reviews each student is expected to have made. api: An implementation of :py:class:`repobee_plug.PlatformAPI` used to interface with the platform (e.g. GitHub or GitLab) instance. """ teams = list(teams) reviews = collections.defaultdict(list) review_team_names = [ plug.generate_review_team_name(team, assignment_name) for team in teams for assignment_name in assignment_names ] review_teams = progresswrappers.get_teams(review_team_names, api, desc="Processing review teams") for review_team in review_teams: repos = list(api.get_team_repos(review_team)) if len(repos) != 1: plug.log.warning( f"Expected {review_team.name} to have 1 associated " f"repo, found {len(repos)}. " f"Skipping...") continue reviewed_repo = repos[0] expected_reviewers = set(review_team.members) reviewing_teams = _extract_reviewing_teams(teams, expected_reviewers) review_issue_authors = { issue.author for issue in api.get_repo_issues(reviewed_repo) if re.match(title_regex, issue.title) } for team in reviewing_teams: reviews[str(team)].append( plug.Review( repo=reviewed_repo.name, done=any( map(review_issue_authors.__contains__, team.members)), )) plug.echo( formatters.format_peer_review_progress_output( reviews, [team.name for team in teams], num_reviews))
def _get_issue_generator( repos: Iterable[plug.Repo], title_regex: str, author: Optional[str], state: plug.IssueState, api: plug.PlatformAPI, ) -> Iterable[Tuple[str, Iterable[plug.Issue]]]: issues_per_repo = ( ( repo.name, [ issue for issue in api.get_repo_issues(repo) if re.match(title_regex, issue.title) and (state == plug.IssueState.ALL or state == issue.state) and (not author or issue.author == author) ], ) for repo in repos ) return issues_per_repo
def _get_issue_generator( repos: Iterable[plug.StudentRepo], title_regex: str, author: Optional[str], state: plug.IssueState, double_blind_key: Optional[str], api: plug.PlatformAPI, ) -> Iterable[Tuple[plug.StudentRepo, Iterable[plug.Issue]]]: for repo in repos: if double_blind_key: team_name = _hash_if_key(repo.team.name, double_blind_key) repo_name = _hash_if_key(repo.name, double_blind_key) platform_repo = api.get_repo(repo_name, team_name) else: platform_repo = api.get_repo(repo.name, repo.team.name) yield repo, [ issue for issue in api.get_repo_issues(platform_repo) if re.match(title_regex, issue.title) and ( state == plug.IssueState.ALL or state == issue.state) and ( not author or issue.author == author) ]