コード例 #1
0
ファイル: test_teams.py プロジェクト: repobee/repobee
    def test_run_with_extended_students_syntax(self, platform_url, tmp_path):
        students_file = tmp_path / "students.yml"
        students_file.write_text(
            """
some-team:
    members: [simon]
other-team:
    members: [eve, alice]
        """.strip(),
            encoding=sys.getdefaultencoding(),
        )
        expected_teams = [
            plug.StudentTeam(name="some-team", members=["simon"]),
            plug.StudentTeam(name="other-team", members=["eve", "alice"]),
        ]

        funcs.run_repobee(
            f"{plug.cli.CoreCommand.teams.create} --base-url {platform_url} "
            f"--students-file {students_file}",
            plugins=[_repobee.ext.studentsyml],
        )

        assert sorted(funcs.get_student_teams(platform_url)) == sorted(
            expected_teams
        )
コード例 #2
0
ファイル: parsing.py プロジェクト: tohanss/repobee
def _extract_groups(args: argparse.Namespace) -> List[plug.StudentTeam]:
    """Extract groups from args namespace.`

    Args:
        args: A namespace object.

    Returns:
        a list of student usernames, or None of neither `students` or
        `students_file` is in the namespace.
    """
    if "students" in args and args.students:
        students = [plug.StudentTeam(members=[s]) for s in args.students]
    elif "students_file" in args and args.students_file:
        students_file = pathlib.Path(args.students_file).resolve()
        if not students_file.is_file():
            raise exception.FileError(
                "'{!s}' is not a file".format(students_file))
        if not students_file.stat().st_size:
            raise exception.FileError("'{!s}' is empty".format(students_file))
        students = [
            plug.StudentTeam(members=[s for s in group.strip().split()])
            for group in students_file.read_text(
                encoding=sys.getdefaultencoding()).split(os.linesep)
            if group  # skip blank lines
        ]
    else:
        students = []

    return students
コード例 #3
0
ファイル: test_cli.py プロジェクト: dmusican/repobee
    def test_student_groups_parsed_correcly(
        self, empty_students_file, read_issue_mock, action, extra_args
    ):
        """Test that putting multiple students on the same line in the students
        file results in them being in the same group.
        """
        # arrange
        groupings = (
            ["study"],
            ["buddy", "shuddy"],
            ["grape"],
            ["cat", "dog", "mouse"],
        )
        expected_groups = sorted(
            plug.StudentTeam(members=group) for group in groupings
        )
        empty_students_file.write(
            os.linesep.join([" ".join(group) for group in groupings])
        )
        sys_args = [
            *action.as_name_tuple(),
            *BASE_ARGS,
            "--sf",
            str(empty_students_file),
            *extra_args,
        ]

        # act
        parsed_args, _ = _repobee.cli.parsing.handle_args(sys_args)

        # assert
        assert sorted(parsed_args.students) == expected_groups
コード例 #4
0
ファイル: conftest.py プロジェクト: repobee/repobee
def with_reviews(with_student_repos, tmpdir):
    assignment_name = assignment_names[1]
    expected_review_teams = [
        plug.StudentTeam(
            members=[],
            name=plug.generate_review_team_name(student_team_name,
                                                assignment_name),
        ) for student_team_name in STUDENT_TEAM_NAMES
    ]
    command = " ".join([
        *str(repobee_plug.cli.CoreCommand.reviews.assign).split(),
        *BASE_ARGS,
        "-a",
        assignment_name,
        *STUDENTS_ARG,
        "-n",
        "1",
    ])

    repobee_testhelpers.funcs.run_repobee(command,
                                          workdir=tmpdir,
                                          plugins=[_repobee.ext.gitlab])

    assert_on_groups(
        expected_review_teams,
        single_group_assertion=expected_num_members_group_assertion(1),
    )
    return (assignment_name, expected_review_teams)
コード例 #5
0
ファイル: test_gitlab_system.py プロジェクト: repobee/repobee
    def test_setup_with_wrong_case_on_student(self, tmpdir):
        """User names are case insensitive on GitLab, and so setup should work
        fine even if the case of some character in a student's username is
        "incorrect".

        See https://github.com/repobee/repobee/issues/900
        """
        student = STUDENT_TEAMS[0].members[0]
        student_wrong_case = student.upper()
        assert (student !=
                student_wrong_case), "cases match, test is pointless :("

        command = " ".join([
            *repobee_plug.cli.CoreCommand.repos.setup.as_name_tuple(),
            *BASE_ARGS,
            *TEMPLATE_ORG_ARG,
            *MASTER_REPOS_ARG,
            "--students",
            student_wrong_case,
        ])

        run_repobee(command, workdir=tmpdir, plugins=[_repobee.ext.gitlab])

        assert_repos_exist([plug.StudentTeam(members=[student])],
                           assignment_names)
コード例 #6
0
ファイル: test_gitlab_system.py プロジェクト: repobee/repobee
    def test_assign_one_review(self, with_student_repos, tmpdir):
        assignment_name = assignment_names[1]
        expected_review_teams = [
            plug.StudentTeam(
                members=[],
                name=plug.generate_review_team_name(student_team_name,
                                                    assignment_name),
            ) for student_team_name in STUDENT_TEAM_NAMES
        ]
        command = " ".join([
            *repobee_plug.cli.CoreCommand.reviews.assign.as_name_tuple(),
            *BASE_ARGS,
            "-a",
            assignment_name,
            *STUDENTS_ARG,
            "-n",
            "1",
        ])
        group_assertion = expected_num_members_group_assertion(
            expected_num_members=1)

        run_repobee(command, workdir=tmpdir, plugins=[_repobee.ext.gitlab])

        assert_on_groups(expected_review_teams,
                         single_group_assertion=group_assertion)
        assert_num_issues(STUDENT_TEAMS, [assignment_name], 1)
        assert_issues_exist(
            STUDENT_TEAMS,
            [assignment_name],
            _repobee.command.peer.DEFAULT_REVIEW_ISSUE,
            expected_num_asignees=1,
        )
コード例 #7
0
ファイル: conftest.py プロジェクト: dmusican/repobee
def with_reviews(with_student_repos):
    assignment_name = assignment_names[1]
    expected_review_teams = [
        plug.StudentTeam(
            members=[],
            name=plug.generate_review_team_name(
                student_team_name, assignment_name
            ),
        )
        for student_team_name in STUDENT_TEAM_NAMES
    ]
    command = " ".join(
        [
            REPOBEE_GITLAB,
            *str(repobee_plug.cli.CoreCommand.reviews.assign).split(),
            *BASE_ARGS,
            "-a",
            assignment_name,
            *STUDENTS_ARG,
            "-n",
            "1",
        ]
    )

    result = run_in_docker(command)

    assert result.returncode == 0
    assert_on_groups(
        expected_review_teams,
        single_group_assertion=expected_num_members_group_assertion(1),
    )
    return (assignment_name, expected_review_teams)
コード例 #8
0
ファイル: repos.py プロジェクト: repobee/repobee
def _post_setup(
    pts: List[PushSpec], newly_created: bool, api: plug.PlatformAPI
) -> Mapping[Any, Any]:
    teams_and_repos = [
        (pt.metadata["team"], pt.metadata["repo"]) for pt in pts
    ]
    student_repos = [
        plug.StudentRepo(
            name=repo.name,
            url=repo.url,
            team=plug.StudentTeam(name=team.name, members=team.members),
        )
        for team, repo in teams_and_repos
    ]
    student_repos_iter = plug.cli.io.progress_bar(
        student_repos, desc="Executing post_setup hooks"
    )

    return plugin.execute_tasks(
        student_repos_iter,
        plug.manager.hook.post_setup,
        api,
        cwd=None,
        copy_repos=False,
        extra_kwargs=dict(newly_created=newly_created),
    )
コード例 #9
0
def _execute_post_setup_hook(push_tuples: List[git.Push],
                             api: plug.PlatformAPI) -> Mapping[Any, Any]:
    """Execute the post_setup hook on the given push tuples. Note that the push
    tuples are expected to have the "team" and "repo" keys set in the metadata.
    """
    post_setup_exists = any(
        ["post_setup" in dir(p) for p in plug.manager.get_plugins()])
    if not post_setup_exists or not push_tuples:
        return {}

    teams_and_repos = [(pt.metadata["team"], pt.metadata["repo"])
                       for pt in push_tuples]
    student_repos = [
        plug.StudentRepo(
            name=repo.name,
            url=repo.url,
            team=plug.StudentTeam(members=team.members),
        ) for team, repo in teams_and_repos
    ]
    student_repos_iter = plug.cli.io.progress_bar(
        student_repos, desc="Executing post_setup hooks")

    return plugin.execute_tasks(
        student_repos_iter,
        plug.manager.hook.post_setup,
        api,
        cwd=None,
        copy_repos=False,
    )
コード例 #10
0
    def test_assign_one_review(self, with_student_repos, extra_args):
        assignment_name = assignment_names[1]
        expected_review_teams = [
            plug.StudentTeam(
                members=[],
                name=plug.generate_review_team_name(student_team_name,
                                                    assignment_name),
            ) for student_team_name in STUDENT_TEAM_NAMES
        ]
        command = " ".join([
            REPOBEE_GITLAB,
            *repobee_plug.cli.CoreCommand.reviews.assign.as_name_tuple(),
            *BASE_ARGS,
            "-a",
            assignment_name,
            *STUDENTS_ARG,
            "-n",
            "1",
        ])
        group_assertion = expected_num_members_group_assertion(
            expected_num_members=1)

        result = run_in_docker_with_coverage(command, extra_args=extra_args)

        assert result.returncode == 0
        assert_on_groups(expected_review_teams,
                         single_group_assertion=group_assertion)
        assert_num_issues(STUDENT_TEAMS, [assignment_name], 1)
        assert_issues_exist(
            STUDENT_TEAMS,
            [assignment_name],
            _repobee.command.peer.DEFAULT_REVIEW_ISSUE,
            expected_num_asignees=1,
        )
コード例 #11
0
ファイル: parsing.py プロジェクト: repobee/repobee
def _extract_groups(args: argparse.Namespace) -> List[plug.StudentTeam]:
    """Extract groups from args namespace.`

    Args:
        args: A namespace object.

    Returns:
        a list of student usernames, or None of neither `students` or
        `students_file` is in the namespace.
    """
    if "students" in args and args.students:
        students = [plug.StudentTeam(members=[s]) for s in args.students]
    elif "students_file" in args and args.students_file:
        students_file = pathlib.Path(args.students_file).resolve()
        if not students_file.is_file():
            raise exception.FileError(f"'{students_file}' is not a file")
        if not students_file.stat().st_size:
            raise exception.FileError(f"'{students_file}' is empty")

        students = list(
            plug.manager.hook.parse_students_file(students_file=students_file))
    else:
        students = []

    return students
コード例 #12
0
def parse_students_file(
    students_file: pathlib.Path, ) -> Iterable[plug.StudentTeam]:
    return [
        plug.StudentTeam(members=[s for s in group.strip().split()])
        for group in students_file.read_text(
            encoding=sys.getdefaultencoding()).split(os.linesep)
        if group  # skip blank lines
    ]
コード例 #13
0
ファイル: test_gitlab_system.py プロジェクト: repobee/repobee
    def test_setup_with_token_owner_as_student(self, tmpdir):
        """Setting up with the token owner as a student should not cause
        a crash (see #812)
        """
        command = " ".join([
            *repobee_plug.cli.CoreCommand.repos.setup.as_name_tuple(),
            *BASE_ARGS,
            *TEMPLATE_ORG_ARG,
            *MASTER_REPOS_ARG,
            "--students",
            TEACHER,
        ])

        run_repobee(command, workdir=tmpdir, plugins=[_repobee.ext.gitlab])
        assert_repos_exist([plug.StudentTeam(members=[TEACHER])],
                           assignment_names)
コード例 #14
0
    def test_setup_with_token_owner_as_student(self, extra_args):
        """Setting up with the token owner as a student should not cause
        a crash (see #812)
        """
        command = " ".join([
            REPOBEE_GITLAB,
            *repobee_plug.cli.CoreCommand.repos.setup.as_name_tuple(),
            *BASE_ARGS,
            *TEMPLATE_ORG_ARG,
            *MASTER_REPOS_ARG,
            "--students",
            TEACHER,
        ])

        result = run_in_docker_with_coverage(command, extra_args=extra_args)
        assert result.returncode == 0
        assert_repos_exist([plug.StudentTeam(members=[TEACHER])],
                           assignment_names)
コード例 #15
0
def get_student_teams(
        platform_url: str,
        org_name: str = const.TARGET_ORG_NAME) -> List[plug.StudentTeam]:
    """Like :py:func:`get_platform_teams`, but converts each team to a
    :py:class:`~repobee_plug.StudentTeam`. for easier comparison.

    Args:
        platform_url: URL to the directory used by the
            :py:class:`fakeapi.FakeAPI`.
        org_name: The organization to get repos from.
    Returns:
        A list of student teams.
    """
    api = get_api(platform_url, org_name=org_name)
    return [
        plug.StudentTeam(members=[usr.username for usr in team.members])
        for team in api._teams[org_name].values()
    ]
コード例 #16
0
def _clone_to_student_repos(
    team_repo_tuples: List[Tuple[plug.Team, List[plug.Repo]]],
    workdir: pathlib.Path,
    clone_dir: pathlib.Path,
    api: plug.PlatformAPI,
) -> List[plug.StudentRepo]:
    student_repos = [
        plug.StudentRepo(
            name=repo.name,
            team=plug.StudentTeam(name=team.name, members=list(team.members)),
            url=repo.url,
            _path=workdir / team.name / repo.name,
        ) for team, repos in team_repo_tuples for repo in repos
    ]
    list(
        _repobee.git.clone_student_repos(student_repos,
                                         clone_dir,
                                         update_local=False,
                                         api=api))
    return student_repos
コード例 #17
0
ファイル: test_gitlab_system.py プロジェクト: repobee/repobee
    def test_setup_with_twice_with_wrong_case_on_second_setup(self, tmpdir):
        """User names on GitLab are case insensitive, and so setting up repos
        for the same student with two different cases of characters should work
        the same as setting up just once

        See
        https://github.com/repobee/repobee/issues/900#issuecomment-830075510
        for a bug where this was not the case.
        """
        student = STUDENT_TEAMS[0].members[0]
        student_lowercase = STUDENT_TEAMS[0].members[0].lower()
        # the original should be lowercase
        assert (student == student_lowercase
                ), "expected real student username to be lowercase"

        student_uppercase = student_lowercase.upper()
        base_command = [
            *repobee_plug.cli.CoreCommand.repos.setup.as_name_tuple(),
            *BASE_ARGS,
            *TEMPLATE_ORG_ARG,
            *MASTER_REPOS_ARG,
            "--students",
        ]

        def _cmd(student):
            return " ".join(base_command + [student])

        run_repobee(
            _cmd(student_lowercase),
            workdir=tmpdir,
            plugins=[_repobee.ext.gitlab],
        )
        run_repobee(
            _cmd(student_uppercase),
            workdir=tmpdir,
            plugins=[_repobee.ext.gitlab],
        )

        assert_repos_exist([plug.StudentTeam(members=[student])],
                           assignment_names)
コード例 #18
0
    def test_students_missing_from_grades_file_causes_crash(
            self, tmp_grades_file, mocked_hook_results):
        """Test that if a specified student is missing from the grades
        file, there is a crash.
        """
        missing_team = plug.StudentTeam(members=["randomdude"])
        args = argparse.Namespace(
            students=list(TEAMS) + [missing_team],
            hook_results_file="",  # don't care, read_results_file is mocked
            grades_file=tmp_grades_file,
            assignments="week-1 week-2 week-4 week-6".split(),
            edit_msg_file=str(tmp_grades_file.parent / "editmsg.txt"),
            teachers=list(TEACHERS),
            grade_specs=[PASS_GRADESPEC_FORMAT],
            allow_other_states=False,
        )

        with pytest.raises(_exception.FileError) as exc_info:
            csvgrades.callback(args=args)

        assert "student(s) {} missing from the grades file".format(
            missing_team.members[0]) in str(exc_info.value)
コード例 #19
0
def assign_peer_reviews(
    assignment_names: Iterable[str],
    teams: Iterable[plug.StudentTeam],
    num_reviews: int,
    issue: Optional[plug.Issue],
    double_blind_key: Optional[str],
    api: plug.PlatformAPI,
) -> None:
    """Assign peer reviewers among the students to each student repo. Each
    student is assigned to review num_reviews repos, and consequently, each
    repo gets reviewed by num_reviews reviewers.

    In practice, each student repo has a review team generated (called
    <student-repo-name>-review), to which num_reviews _other_ students are
    assigned. The team itself is given pull-access to the student repo, so
    that reviewers can view code and open issues, but cannot modify the
    contents of the repo.

    Args:
        assignment_names: Names of assginments.
        teams: Team objects specifying student groups.
        num_reviews: Amount of reviews each student should perform
            (consequently, the amount of reviews of each repo)
        issue: An issue with review instructions to be opened in the considered
            repos.
        double_blind_key: If provided, use key to make double-blind review
            allocation.
        api: An implementation of :py:class:`repobee_plug.PlatformAPI` used to
            interface with the platform (e.g. GitHub or GitLab) instance.
    """
    issue = issue or DEFAULT_REVIEW_ISSUE
    expected_repo_names = set(plug.generate_repo_names(teams,
                                                       assignment_names))
    fetched_teams = progresswrappers.get_teams(teams,
                                               api,
                                               desc="Fetching teams and repos")
    team_repo_tuples = [(team, list(api.get_team_repos(team)))
                        for team in fetched_teams]
    fetched_repos = list(
        itertools.chain.from_iterable(repos for _, repos in team_repo_tuples))
    fetched_repo_dict = {r.name: r for r in fetched_repos}

    missing = expected_repo_names - fetched_repo_dict.keys()
    if missing:
        raise plug.NotFoundError(f"Can't find repos: {', '.join(missing)}")

    if double_blind_key:
        plug.log.info(f"Creating anonymous repos with key: {double_blind_key}")
        fetched_repo_dict = _create_anonymized_repos(
            [(team, _only_expected_repos(repos, expected_repo_names))
             for team, repos in team_repo_tuples],
            double_blind_key,
            api,
        )

    allocations_for_output = []
    for assignment_name in assignment_names:
        plug.echo("Allocating reviews")
        allocations = plug.manager.hook.generate_review_allocations(
            teams=teams, num_reviews=num_reviews)
        # adjust names of review teams
        review_team_specs, reviewed_team_names = list(
            zip(*[(
                plug.StudentTeam(
                    members=alloc.review_team.members,
                    name=_review_team_name(
                        alloc.reviewed_team,
                        assignment_name,
                        key=double_blind_key,
                    ),
                ),
                alloc.reviewed_team,
            ) for alloc in allocations]))

        review_teams = _repobee.command.teams.create_teams(
            review_team_specs, plug.TeamPermission.PULL, api)
        review_teams_progress = plug.cli.io.progress_bar(
            review_teams,
            desc="Creating review teams",
            total=len(review_team_specs),
        )

        for review_team, reviewed_team_name in zip(review_teams_progress,
                                                   reviewed_team_names):
            reviewed_repo = fetched_repo_dict[plug.generate_repo_name(
                reviewed_team_name, assignment_name)]

            review_teams_progress.write(  # type: ignore
                f"Assigning {' and '.join(review_team.members)} "
                f"to review {reviewed_repo.name}")
            api.assign_repo(review_team, reviewed_repo,
                            plug.TeamPermission.PULL)
            api.create_issue(
                issue.title,
                issue.body,
                reviewed_repo,
                # It's not possible to assign users with read-access in Gitea
                # FIXME redesign so Gitea does not require special handling
                assignees=review_team.members
                if not isinstance(api, _repobee.ext.gitea.GiteaAPI) else None,
            )

            allocations_for_output.append({
                "reviewed_repo": {
                    "name": reviewed_repo.name,
                    "url": reviewed_repo.url,
                },
                "review_team": {
                    "name": review_team.name,
                    "members": review_team.members,
                },
            })

        if featflags.is_feature_enabled(
                featflags.FeatureFlag.REPOBEE_4_REVIEW_COMMANDS):
            output = dict(allocations=allocations_for_output,
                          num_reviews=num_reviews)
            pathlib.Path("review_allocations.json").write_text(
                json.dumps(output, indent=4),
                encoding=sys.getdefaultencoding(),
            )
コード例 #20
0
    DIR_PATHS_WITH_SPACES.exists()), "test pre-reference error, dir must exit"
assert ABSTRACT_TEST_REPO.exists(), "test pre-reference error, dir must exit"

JUNIT_PATH = str(envvars.JUNIT_PATH)
HAMCREST_PATH = str(envvars.HAMCREST_PATH)

RTD = str(CUR_DIR / "reference-tests")
IGNORE_TESTS = ["FiboTest"]
CLASSPATH = "some-stuf:nice/path:path/to/unimportant/lib.jar"

CLASSPATH_WITH_JARS = CLASSPATH + ":{}:{}".format(JUNIT_PATH, HAMCREST_PATH)

NUM_PRIME_CHECKER_TESTS = 3
NUM_FIBO_TESTS = 2

DUMMY_TEAM = plug.StudentTeam(members=[], name="dummy")


def setup_hooks(
    reference_tests_dir=RTD,
    assignments=ASSIGNMENT_NAMES,
    ignore_tests=[],
    hamcrest_path=HAMCREST_PATH,
    junit_path=JUNIT_PATH,
    verbose=False,
    very_verbose=False,
    disable_security=False,
    run_student_tests=False,
    timeout=10,
):
    """Return an instance of JUnit4Hooks with pre-configured arguments."""
コード例 #21
0
ファイル: giteamanager.py プロジェクト: repobee/repobee
    "docker-compose down",
    "docker network rm development",
    f"rm -rf {str(DOCKER_VOLUME)}",
    f"git checkout {DOCKER_VOLUME}",
]

TEACHER_USER = "******"
TEACHER_TOKEN = ((CURRENT_DIR /
                  "teacher_token.txt").read_text(encoding="utf8").strip())

ADMIN_USER = "******"
ADMIN_TOKEN = ((CURRENT_DIR /
                "admin_token.txt").read_text(encoding="utf8").strip())

STUDENT_TEAMS = [
    plug.StudentTeam(members=line.strip().split())
    for line in (CURRENT_DIR /
                 "students.txt").read_text("utf8").strip().split("\n")
]


def main(args: List[str]) -> None:
    def _usage():
        print("usage: python giteamanager.py <prime|setup|teardown>")
        sys.exit()

    if len(args) != 2:
        _usage()

    cmd = args[1]
    if cmd == "prime":
コード例 #22
0
import argparse
import sys
import pathlib
import random
from unittest import mock

import pytest
from _repobee import plugin
import repobee_plug as plug

from repobee_feedback import feedback

ASSIGNMENT_NAMES = ("task-1", "task-2")
STUDENT_TEAMS = tuple([
    plug.StudentTeam(members=members)
    for members in (["slarse"], ["glassey"], ["grundb", "glennol"])
])
STUDENT_TEAM_NAMES = tuple(map(str, STUDENT_TEAMS))

PASS_ISSUE = plug.Issue(title="Pass", body="Well done!\nAbsolutely flawless!")
KOMP_ISSUE = plug.Issue(title="Komplettering",
                        body="Not perfect, you need to fix this.")
FAIL_ISSUE = plug.Issue(title="Fail",
                        body="Unfortunately, there are severe errors.")
ISSUES = (PASS_ISSUE, KOMP_ISSUE, FAIL_ISSUE)

random.seed(512)


def _write_issue(issue: plug.Issue, path: pathlib.Path):
    text = "{}\n{}".format(issue.title, issue.body)
コード例 #23
0
import pathlib

import repobee_plug as plug

from repobee_testhelpers._internal.templates import TEMPLATE_REPOS_DIR

DIR = pathlib.Path(__file__).resolve().parent
TOKEN = (DIR.parent / "token").read_text(encoding="utf-8").strip()
ADMIN_TOKEN = "".join(reversed(TOKEN))
OAUTH_USER = "******"
BASE_DOMAIN = "localhost:3000"
BASE_URL = "https://" + BASE_DOMAIN
ORG_NAME = "dd1337-fall2020"
TEMPLATE_ORG_NAME = "dd1337-master"
TEACHER = "ric"
assignment_names = [p.name for p in TEMPLATE_REPOS_DIR.iterdir() if p.is_dir()]
TEMPLATE_REPO_PATHS = list(dir_.absolute()
                           for dir_ in TEMPLATE_REPOS_DIR.iterdir()
                           if dir_.is_dir())
STUDENT_TEAMS = [
    plug.StudentTeam(members=[s.strip()])
    for s in (DIR.parent / "students.txt").read_text().strip().split("\n")
]
STUDENT_TEAM_NAMES = [str(t) for t in STUDENT_TEAMS]
STUDENT_REPO_NAMES = plug.generate_repo_names(STUDENT_TEAMS, assignment_names)
BASE_ARGS_NO_TB = ["--bu", BASE_URL, "-o", ORG_NAME, "-t", TOKEN]
BASE_ARGS = [*BASE_ARGS_NO_TB, "--tb"]
STUDENTS_ARG = ["-s", " ".join(STUDENT_TEAM_NAMES)]
MASTER_REPOS_ARG = ["-a", " ".join(assignment_names)]
TEMPLATE_ORG_ARG = ["--template-org-name", TEMPLATE_ORG_NAME]
コード例 #24
0
ファイル: genreviews.py プロジェクト: repobee/repobee
 def merge_teams(teams):
     members = list(
         itertools.chain.from_iterable([team.members for team in teams])
     )
     return plug.StudentTeam(members=members)
コード例 #25
0
ファイル: studentsyml.py プロジェクト: repobee/repobee
def _to_student_team(name: str, data: dict) -> plug.StudentTeam:
    if _MEMBERS_KEY not in data:
        raise plug.PlugError(f"Missing members mapping for '{name}'")
    return plug.StudentTeam(name=name, members=data[_MEMBERS_KEY])
コード例 #26
0
def assign_peer_reviews(
    assignment_names: Iterable[str],
    teams: Iterable[plug.StudentTeam],
    num_reviews: int,
    issue: Optional[plug.Issue],
    api: plug.PlatformAPI,
) -> None:
    """Assign peer reviewers among the students to each student repo. Each
    student is assigned to review num_reviews repos, and consequently, each
    repo gets reviewed by num_reviews reviewers.

    In practice, each student repo has a review team generated (called
    <student-repo-name>-review), to which num_reviews _other_ students are
    assigned. The team itself is given pull-access to the student repo, so
    that reviewers can view code and open issues, but cannot modify the
    contents of the repo.

    Args:
        assignment_names: Names of assginments.
        teams: Team objects specifying student groups.
        num_reviews: Amount of reviews each student should perform
            (consequently, the amount of reviews of each repo)
        issue: An issue with review instructions to be opened in the considered
            repos.
        api: An implementation of :py:class:`repobee_plug.PlatformAPI` used to
            interface with the platform (e.g. GitHub or GitLab) instance.
    """
    issue = issue or DEFAULT_REVIEW_ISSUE
    expected_repo_names = plug.generate_repo_names(teams, assignment_names)
    fetched_teams = progresswrappers.get_teams(teams,
                                               api,
                                               desc="Fetching teams and repos")
    fetched_repos = list(
        itertools.chain.from_iterable(map(api.get_team_repos, fetched_teams)))
    fetched_repo_dict = {r.name: r for r in fetched_repos}

    missing = set(expected_repo_names) - set(fetched_repo_dict.keys())
    if missing:
        raise plug.NotFoundError(f"Can't find repos: {', '.join(missing)}")

    for assignment_name in assignment_names:
        plug.echo("Allocating reviews")
        allocations = plug.manager.hook.generate_review_allocations(
            teams=teams, num_reviews=num_reviews)
        # adjust names of review teams
        review_team_specs, reviewed_team_names = list(
            zip(*[(
                plug.StudentTeam(
                    members=alloc.review_team.members,
                    name=plug.generate_review_team_name(
                        str(alloc.reviewed_team), assignment_name),
                ),
                alloc.reviewed_team,
            ) for alloc in allocations]))

        review_teams = _repobee.command.teams.create_teams(
            review_team_specs, plug.TeamPermission.PULL, api)
        review_teams_progress = plug.cli.io.progress_bar(
            review_teams,
            desc="Creating review teams",
            total=len(review_team_specs),
        )

        for review_team, reviewed_team_name in zip(review_teams_progress,
                                                   reviewed_team_names):
            reviewed_repo = fetched_repo_dict[plug.generate_repo_name(
                reviewed_team_name, assignment_name)]
            review_teams_progress.write(  # type: ignore
                f"Assigning {' and '.join(review_team.members)} "
                f"to review {reviewed_repo.name}")
            api.assign_repo(review_team, reviewed_repo,
                            plug.TeamPermission.PULL)
            api.create_issue(
                issue.title,
                issue.body,
                reviewed_repo,
                assignees=review_team.members,
            )
コード例 #27
0
ファイル: test_github.py プロジェクト: repobee/repobee
def review_student_teams():
    return [
        plug.StudentTeam(members=[student])
        for student in ("ham", "spam", "bacon", "eggs")
    ]
コード例 #28
0
ファイル: constants.py プロジェクト: tohanss/repobee
"""Module for constants used throughout the test suite."""
import string
import collections
from datetime import datetime
from itertools import permutations

import repobee_plug as plug

USER = "******"
ORG_NAME = "test-org"
TEMPLATE_ORG_NAME = "test-master-org"
HOST_URL = "https://some_enterprise_host"
BASE_URL = "{}/api/v3".format(HOST_URL)

# 5! = 120 different students
STUDENTS = tuple(
    plug.StudentTeam(members=["".join(perm)])
    for perm in permutations(string.ascii_lowercase[:5]))
ISSUE_PATH = "some/issue/path"
ISSUE = plug.Issue(title="Best title", body="This is the body of the issue.")
PLUGINS = ["javac", "pylint"]
TOKEN = "besttoken1337"
CONFIG_TOKEN = "bestconfigtoken"
FIXED_DATETIME = datetime(2009, 11, 22)

User = collections.namedtuple("User", ("login", ))
コード例 #29
0
ファイル: test_localreps.py プロジェクト: repobee/repobee
 def test_constructor_lowercases_member_names(self):
     members = ["siMON", "alIce", "EVE"]
     members_lowercase = ["simon", "alice", "eve"]
     team = plug.StudentTeam(members=members)
     assert team.members == members_lowercase