Skip to content

Commit

Permalink
Merge pull request #664 from chrispyles/assign-summary
Browse files Browse the repository at this point in the history
  • Loading branch information
chrispyles committed Jul 16, 2023
2 parents 4b7165d + 9fae880 commit 62ceab1
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 4 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* Use Otter Grade CLI flags to update `otter_config.json` values in the grading container per [#395](https://github.com/ucbds-infra/otter-grader/issues/395)
* Removed `linux/amd64` platform specification for Docker images in Otter Grade
* Updated Otter Assign to normalize notebooks before writing them with `nbformat.validator.normalize` per [#658](https://github.com/ucbds-infra/otter-grader/issues/658)
* Added summary of assignment questions to Otter Assign logging per [#564](https://github.com/ucbds-infra/otter-grader/issues/564)

**v4.4.0:**

Expand Down
8 changes: 7 additions & 1 deletion otter/assign/output.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,10 @@
from .tests_manager import AssignmentTestsManager
from .utils import get_notebook_language

from ..utils import NBFORMAT_VERSION
from ..utils import loggers, NBFORMAT_VERSION


LOGGER = loggers.get_logger(__name__)


def write_output_dir(
Expand Down Expand Up @@ -122,3 +125,6 @@ def write_output_directories(assignment):
# populate directories
write_output_dir(transformed_nb, autograder_dir, assignment, False)
write_output_dir(transformed_nb, student_dir, assignment, True)

# print assignment summary
LOGGER.info(nb_transformer.tests_mgr.generate_assignment_summary())
35 changes: 32 additions & 3 deletions otter/assign/tests_manager.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
"""Assignment tests manager for Otter Assign"""

import os
import pandas as pd
import pprint
import re
import yaml
Expand Down Expand Up @@ -375,17 +376,45 @@ def determine_question_point_value(self, question):
``int | float``: the point value of the question
"""
test_cases = self._tests_by_question.get(question.name, [])

points = question.points
if isinstance(points, dict):
points = points.get('each', 1) * len(test_cases)

if len(test_cases) == 0:
if question.points is None and question.manual:
if points is None and question.manual:
raise ValueError(
f"Point value unspecified for question with no test cases: {question.name}")

return question.points if question.points is not None else 1
return points if points is not None else 1

try:
resolved_test_cases = TestFile.resolve_test_file_points(question.points, test_cases)
resolved_test_cases = TestFile.resolve_test_file_points(points, test_cases)
except Exception as e:
raise type(e)(f"Error in \"{question.name}\" test cases: {e}")

points = round(sum(tc.points for tc in resolved_test_cases), 5)
return int(points) if points % 1 == 0 else points

def generate_assignment_summary(self):
"""
Generate a summary of the assignment's questions.
Returns:
``str``: the summary
"""
rows, manual, autograded, total = [], 0, 0, 0
for question_name in sorted(self._tests_by_question.keys()):
config = self._questions[question_name]
points = self.determine_question_point_value(config)
rows.append({"name": question_name, "points": points})
total += points
if config.manual: manual += points
else: autograded += points

summary = f"Assignment summary:\n"
summary += f"Total points: {total}\n"
summary += f"Autograded: {autograded}\n"
summary += f"Manual: {manual}\n\n"
summary += str(pd.DataFrame(rows))
return summary

0 comments on commit 62ceab1

Please sign in to comment.