Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding commands for creating assignments (assigning exercises) and modifying assignments #15

Merged
merged 1 commit into from
Oct 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions recodex/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,12 @@ def solution_resubmit(self, solution_id, debug=False):
def delete_solution(self, solution_id):
return self.delete("assignment-solutions/{}".format(solution_id))

def create_assignment(self, exercise_id, group_id):
return self.post("exercise-assignments", data={"exerciseId": exercise_id, "groupId": group_id})

def set_assignment(self, assignment_id, **data):
return self.post("exercise-assignments/{}".format(assignment_id), data=data)

# Shadow Assignments

def create_shadow_assignment(self, group_id):
Expand Down
86 changes: 86 additions & 0 deletions recodex/plugins/assignments/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,89 @@ def get_solutions(api: ApiClient, assignment_id, useJson):
points = solution["overriddenPoints"] if solution["overriddenPoints"] else solution["actualPoints"]
click.echo("{} {} {}+{}/{} {}".format(solution["id"], solution["authorId"],
points, solution["bonusPoints"], solution["maxPoints"], ", ".join(flags)))

@cli.command()
@click.argument("exercise_id")
@click.argument("group_id")
@pass_api_client
def create(api: ApiClient, exercise_id, group_id):
"""
Creates an assignment of an exercise in specified group with default values.

Use update subcommand to modify the values.
"""

assignment = api.create_assignment(exercise_id, group_id)
click.echo(assignment['id'])

@cli.command()
@click.argument("assignment_id")
@click.option("--publish", "publish", default=None, is_flag=False, flag_value=True, help="False or True or timestamp to be visible from")
@click.option("--deadline1", "deadline1", default=0, help="Timestamp of first deadline")
@click.option("--maxPoints1", "max_points1", default=0, help="Points limit before first deadline")
@click.option("--deadline2", "deadline2", default=0, help="Timestamp of second deadline")
@click.option("--maxPoints2", "max_points2", default=0, help="Points limit before second deadline")
@click.option("--interpolatePoints/--no-interpolatePoints", "interpolate_points", default=None, help="Whether to interpolate points between deadlines")
@click.option("--minPercent", "min_percent", default=0.0, help="Minimal solution correctness")
@click.option("--submissionsCount", "submissions_count", default=0, help="Maximal number of submissions")
@click.option("--solutionFiles", "solution_files", default=0, help="Maximal number of files in submission")
@click.option("--solutionSize", "solution_size", default=0, help="Maximal total size of all files submitted")
@click.option("--showLimitRatios/--no-showLimitRatios", "show_limit_ratios", default=None, help="Whether to show memory and time")
@click.option("--showLimitValues/--no-showLimitValues", "show_limit_values", default=None, help="Whether to show absolute measurements")
@click.option("--showJudgeStdout/--no-showJudgeStdout", "show_judge_stdout", default=None, help="Whether to show stdout from judge")
@click.option("--showJudgeStderr/--no-showJudgeStderr", "show_judge_stderr", default=None, help="Whether to show stderr from judge")
@click.option("--notify/--no-notify", "notify", default=None, help="Whether to send email notification once assignment is public")
@click.option("--bonus/--no-bonus", "is_bonus", default=None, help="Whether the assignment is bonus")
@click.option("--exam/--no-exam", "is_exam", default=None, help="Whether the assignment is exam")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, this is not the usual way we handle updates of larger structures, but since this version of CLI will be replaced by an auto-generated version using OpenAPI, I will accept this for the time being.

@pass_api_client
def update(api: ApiClient, assignment_id, publish,
deadline1, max_points1, deadline2, max_points2, interpolate_points, min_percent,
submissions_count, solution_files, solution_size,
show_limit_ratios, show_limit_values, show_judge_stdout, show_judge_stderr,
notify, is_bonus, is_exam):
"""
Updates settings of specified assignment. If the option is not provided the value is not updated.
"""

def bool_or_argument(value, arg):
return value if value is not None else arg

assignment = api.get_assignment(assignment_id)

if publish is None:
is_public = assignment['isPublic']
visible_from = assignment['visibleFrom']
elif (lower := publish.lower()) in ['true', 'false']:
is_public = lower == "true"
visible_from = None
else:
is_public = True
visible_from = int(publish)

updates = {
'version': assignment['version'],
'isPublic': is_public,
'localizedTexts': assignment['localizedTexts'],
'firstDeadline': deadline1 or assignment['firstDeadline'],
'maxPointsBeforeFirstDeadline': max_points1 or assignment['maxPointsBeforeFirstDeadline'],
'submissionsCountLimit': submissions_count or assignment['submissionsCountLimit'],
'solutionFilesLimit': solution_files or assignment['solutionFilesLimit'],
'solutionSizeLimit': solution_size or assignment['solutionSizeLimit'],
'allowSecondDeadline': bool(deadline2 or assignment['secondDeadline']),
'visibleFrom': visible_from,
'canViewLimitRatios': bool_or_argument(show_limit_ratios, assignment['canViewLimitRatios']),
'canViewMeasuredValues': bool_or_argument(show_limit_values, assignment['canViewMeasuredValues']),
'canViewJudgeStdout': bool_or_argument(show_judge_stdout, assignment['canViewJudgeStdout']),
'canViewJudgeStderr': bool_or_argument(show_judge_stderr, assignment['canViewJudgeStderr']),
'secondDeadline': deadline2 or assignment['secondDeadline'],
'maxPointsBeforeSecondDeadline': max_points2 or assignment['maxPointsBeforeSecondDeadline'],
'maxPointsDeadlineInterpolation': bool_or_argument(interpolate_points, assignment['maxPointsDeadlineInterpolation']),
'isBonus': bool_or_argument(is_bonus, assignment['isBonus']),
'pointsPercentualThreshold': min_percent or assignment['pointsPercentualThreshold'],
'isExam': bool_or_argument(is_exam, assignment['isExam'])
}

if notify is not None:
updates = updates | { 'sendNotification': notify }

api.set_assignment(assignment['id'], **updates)
Loading