def preprocess_cell(self, cell, resources, cell_index):
        if utils.is_grade(cell):
            # check for blank grade ids
            grade_id = cell.metadata.nbgrader.get("grade_id", "")
            if grade_id == "":
                raise RuntimeError("Blank grade id!")
            resources['grade_ids'].append(grade_id)

            # check for valid points
            points = cell.metadata.nbgrader.get("points", "")
            try:
                points = float(points)
            except ValueError:
                raise RuntimeError(
                    "Point value for grade cell {} is invalid: {}".format(
                        grade_id, points))

        # check that code cells are grade OR solution (not both)
        if cell.cell_type == "code" and utils.is_grade(cell) and utils.is_solution(cell):
            raise RuntimeError(
                "Code grade cell '{}' is also marked as a solution cell".format(
                    grade_id))

        # check that markdown cells are grade AND solution (not either/or)
        if cell.cell_type == "markdown" and utils.is_grade(cell) and not utils.is_solution(cell):
            raise RuntimeError(
                "Markdown grade cell '{}' is not marked as a solution cell".format(
                    grade_id))
        if cell.cell_type == "markdown" and not utils.is_grade(cell) and utils.is_solution(cell):
            raise RuntimeError(
                "Markdown solution cell (index {}) is not marked as a grade cell".format(
                    cell_index))

        return cell, resources
Example #2
0
    def preprocess_cell(self, cell, resources, cell_index):
        if utils.is_grade(cell) or utils.is_solution(cell):
            # check for invalid grade ids
            grade_id = cell.metadata.nbgrader.get("grade_id", "")
            if not re.match(r"^[a-zA-Z0-9_\-]+$", grade_id):
                raise RuntimeError("Invalid grade id: {}".format(grade_id))
            resources['grade_ids'].append(grade_id)

        if utils.is_grade(cell):
            # check for valid points
            points = cell.metadata.nbgrader.get("points", "")
            try:
                points = float(points)
            except ValueError:
                raise RuntimeError(
                    "Point value for grade cell {} is invalid: {}".format(
                        grade_id, points))

        # check that markdown cells are grade AND solution (not either/or)
        if cell.cell_type == "markdown" and utils.is_grade(cell) and not utils.is_solution(cell):
            raise RuntimeError(
                "Markdown grade cell '{}' is not marked as a solution cell".format(
                    grade_id))
        if cell.cell_type == "markdown" and not utils.is_grade(cell) and utils.is_solution(cell):
            raise RuntimeError(
                "Markdown solution cell (index {}) is not marked as a grade cell".format(
                    cell_index))

        return cell, resources
Example #3
0
 def test_is_solution(self):
     cell = self._create_code_cell()
     assert not utils.is_solution(cell)
     cell.metadata['nbgrader'] = {}
     assert not utils.is_solution(cell)
     cell.metadata['nbgrader']['solution'] = False
     assert not utils.is_solution(cell)
     cell.metadata['nbgrader']['solution'] = True
     assert utils.is_solution(cell)
Example #4
0
    def preprocess_cell(self, cell, resources, cell_index):
        if utils.is_grade(cell):
            self._create_grade_cell(cell)

        if utils.is_solution(cell):
            self._create_solution_cell(cell)

        if utils.is_grade(cell) or utils.is_solution(cell) or utils.is_locked(cell):
            self._create_source_cell(cell)

        return cell, resources
Example #5
0
    def preprocess_cell(self, cell, resources, cell_index):
        # compute checksums of grade cell and solution cells
        if utils.is_grade(cell) or utils.is_solution(cell) or utils.is_locked(cell):
            checksum = utils.compute_checksum(cell)
            cell.metadata.nbgrader['checksum'] = checksum

            if utils.is_grade(cell) or utils.is_solution(cell):
                self.log.debug(
                    "Checksum for '%s' is %s",
                    cell.metadata.nbgrader['grade_id'],
                    checksum)

        return cell, resources
Example #6
0
    def preprocess_cell(self, cell, resources, cell_index):
        if not utils.is_grade(cell):
            return cell, resources

        # if we're ignoring checksums, then remove the checksum from the
        # cell metadata
        if self.ignore_checksums and 'checksum' in cell.metadata.nbgrader:
            del cell.metadata.nbgrader['checksum']

        # verify checksums of cells
        if not utils.is_solution(cell) and 'checksum' in cell.metadata.nbgrader:
            old_checksum = cell.metadata.nbgrader['checksum']
            new_checksum = utils.compute_checksum(cell)
            if old_checksum != new_checksum:
                resources['nbgrader']['checksum_mismatch'].append(cell_index)

        # if it's a grade cell, the add a grade
        score, max_score = utils.determine_grade(cell)

        # it's a markdown cell, so we can't do anything
        if score is None:
            pass
        elif score < max_score:
            resources['nbgrader']['failed_cells'].append(cell_index)
        else:
            resources['nbgrader']['passed_cells'].append(cell_index)

        return cell, resources
Example #7
0
    def preprocess_cell(self, cell, resources, cell_index):
        if utils.is_grade(cell):
            max_score = float(cell.metadata.nbgrader['points'])
            cell_type = cell.cell_type
            source = cell.source
            checksum = cell.metadata.nbgrader.get('checksum', None)

            grade_cell = self.gradebook.update_or_create_grade_cell(
                cell.metadata.nbgrader['grade_id'],
                self.notebook_id,
                self.assignment_id,
                max_score=max_score,
                source=source,
                checksum=checksum,
                cell_type=cell_type)

            self.log.debug("Recorded grade cell %s into database", grade_cell)

        if utils.is_solution(cell):
            cell_type = cell.cell_type
            source = cell.source
            checksum = cell.metadata.nbgrader.get('checksum', None)

            solution_cell = self.gradebook.update_or_create_solution_cell(
                self.comment_index,
                self.notebook_id,
                self.assignment_id,
                cell_type=cell_type,
                source=source,
                checksum=checksum)

            self.comment_index += 1
            self.log.debug("Recorded solution cell %s into database", solution_cell)

        return cell, resources
Example #8
0
 def preprocess_cell(self, cell, resources, cell_index):
     if is_solution(cell):
         if cell.cell_type == 'code':
             cell.input = '#' + self.solution_stub
         else:
             cell.input = self.solution_stub
     return cell, resources
Example #9
0
    def preprocess_cell(self, cell, resources, cell_index):
        is_hidden = utils.is_hidden(cell)
        if is_hidden:
            replaced_solution = self._replace_hidden_cell(cell)
        else:
            # replace solution regions with the relevant stubs
            replaced_solution = self._replace_solution_region(cell)

        # determine whether the cell is a solution/grade cell
        is_solution = utils.is_solution(cell)

        # check that it is marked as a solution cell if we replaced a solution
        # region -- if it's not, then this is a problem, because the cell needs
        # to be given an id
        if not (is_solution or is_hidden) and replaced_solution:
            raise RuntimeError(
                "Solution region detected in a non-solution cell; "
                "please make sure all solution regions are within "
                "solution cells")

        # replace solution cells with the code/text stub -- but not if
        # we already replaced a solution region, because that means
        # there are parts of the cells that should be preserved
        if is_solution and not replaced_solution:
            if cell.cell_type == 'code':
                cell.source = self.code_stub
            else:
                cell.source = self.text_stub

        return cell, resources
Example #10
0
 def preprocess_cell(self, cell, resources, cell_index):
     if self.lock_all_cells:
         cell.metadata['deletable'] = False
     elif self.lock_grade_cells and utils.is_grade(cell):
         cell.metadata['deletable'] = False
     elif self.lock_solution_cells and utils.is_solution(cell):
         cell.metadata['deletable'] = False
     return cell, resources
Example #11
0
    def preprocess_cell(self, cell, resources, cell_index):
        # if it's a grade cell, the add a grade
        if utils.is_grade(cell):
            self._add_score(cell, resources)

        if utils.is_solution(cell):
            self._add_comment(cell, resources)

        return cell, resources
Example #12
0
    def preprocess_cell(self, cell, resources, cell_index):
        if utils.is_grade(cell):
            grade_cell = self.gradebook.find_grade_cell(
                cell.metadata.nbgrader["grade_id"],
                self.notebook_id,
                self.assignment_id)

            cell.metadata.nbgrader['points'] = grade_cell.max_score

            # we only want the source and checksum for non-solution cells
            if not utils.is_solution(cell):
                old_checksum = grade_cell.checksum
                new_checksum = utils.compute_checksum(cell)

                if old_checksum != new_checksum:
                    self.log.warning("Checksum for grade cell %s has changed!", grade_cell.name)

                cell.source = grade_cell.source
                cell.metadata.nbgrader['checksum'] = grade_cell.checksum
                self.update_cell_type(cell, grade_cell.cell_type)

            self.log.debug("Overwrote grade cell %s", grade_cell.name)

        if utils.is_solution(cell):
            solution_cell = self.gradebook.find_solution_cell(
                self.comment_index,
                self.notebook_id,
                self.assignment_id)

            old_checksum = solution_cell.checksum
            new_checksum = utils.compute_checksum(cell)

            if cell.cell_type != solution_cell.cell_type:
                self.log.warning("Cell type for solution cell %s has changed!", solution_cell.name)

            cell.metadata.nbgrader['checksum'] = solution_cell.checksum
            self.update_cell_type(cell, solution_cell.cell_type)

            self.log.debug("Overwrote solution cell #%s", self.comment_index)

            self.comment_index += 1

        return cell, resources
Example #13
0
    def preprocess_cell(self, cell, resources, cell_index):
        if not (utils.is_grade(cell) or utils.is_solution(cell) or utils.is_locked(cell)):
            return cell, resources

        grade_id = cell.metadata.nbgrader['grade_id']
        if grade_id in self.grade_ids:
            self.log.warning("Cell with id '%s' exists multiple times!", grade_id)
            cell.metadata.nbgrader = {}
        else:
            self.grade_ids.add(grade_id)

        return cell, resources
Example #14
0
    def preprocess_cell(self, cell, resources, cell_index):
        if not (utils.is_grade(cell) or utils.is_solution(cell)
                or utils.is_locked(cell)):
            return cell, resources

        grade_id = cell.metadata.nbgrader['grade_id']
        if grade_id in self.grade_ids:
            self.log.warning("Cell with id '%s' exists multiple times!",
                             grade_id)
            cell.metadata.nbgrader = {}
        else:
            self.grade_ids.add(grade_id)

        return cell, resources
Example #15
0
    def preprocess_cell(self, cell, resources, cell_index):
        # replace solution regions with the relevant stubs
        replaced_solution = self._replace_solution_region(cell)

        # determine whether the cell is a solution cell
        is_solution = utils.is_solution(cell)

        # replace solution cells with the code/text stub -- but not if
        # we already replaced a solution region, because that means
        # there are parts of the cells that should be preserved
        if is_solution and not replaced_solution:
            if cell.cell_type == 'code':
                cell.input = self.code_stub
            else:
                cell.source = self.text_stub

        return cell, resources
Example #16
0
    def preprocess_cell(self, cell, resources, cell_index):
        # replace solution regions with the relevant stubs
        replaced_solution = self._replace_solution_region(cell)

        # determine whether the cell is a solution cell
        is_solution = utils.is_solution(cell)

        # replace solution cells with the code/text stub -- but not if
        # we already replaced a solution region, because that means
        # there are parts of the cells that should be preserved
        if is_solution and not replaced_solution:
            if cell.cell_type == 'code':
                cell.source = self.code_stub
            else:
                cell.source = self.text_stub

        return cell, resources
Example #17
0
    def preprocess_cell(self, cell, resources, cell_index):
        if utils.is_grade(cell):
            grade_cell = self.gradebook.find_or_create_grade_cell(
                grade_id=cell.metadata.nbgrader.grade_id,
                notebook_id=self.notebook_id,
                assignment=self.assignment)

            grade_cell.max_score = float(cell.metadata.nbgrader['points'])

            # we only want the source and checksum for non-solution cells
            if utils.is_solution(cell):
                grade_cell.source = None
                grade_cell.checksum = None
            else:
                grade_cell.source = cell.source
                grade_cell.checksum = cell.metadata.nbgrader['checksum']

            self.gradebook.update_grade_cell(grade_cell)
            self.log.debug("Recorded grade cell %s into database",
                           grade_cell.grade_id)

        return cell, resources
Example #18
0
    def preprocess_cell(self, cell, resources, cell_index):
        # replace solution regions with the relevant stubs
        replaced_solution = self._replace_solution_region(cell)

        # determine whether the cell is a solution cell
        is_solution = utils.is_solution(cell)

        # replace solution cells with the code/text stub -- but not if
        # we already replaced a solution region, because that means
        # there are parts of the cells that should be preserved
        if is_solution and not replaced_solution:
            if cell.cell_type == 'code':
                cell.source = self.code_stub
            else:
                cell.source = self.text_stub

        # if we replaced a solution region, then make sure the cell is marked
        # as a solution cell
        if replaced_solution:
            if 'nbgrader' not in cell.metadata:
                cell.metadata.nbgrader = {}
            cell.metadata.nbgrader['solution'] = True

        return cell, resources
Example #19
0
 def cell_changed(self, cell: NotebookNode):
     return not (is_solution(cell) and "checksum" in cell.metadata.nbgrader
                 and cell.metadata.nbgrader["checksum"]
                 == compute_checksum(cell))
Example #20
0
def is_solution_cell(cell):
    return is_nbgrader_cell(cell) and is_solution(cell)