Source code for grader_convert.nbgraderformat.common
import json
import os
import jsonschema
from jsonschema import ValidationError
from nbformat.notebooknode import NotebookNode
from traitlets.config import LoggingConfigurable
root = os.path.dirname(__file__)
[docs]class SchemaMismatchError(Exception):
def __init__(self, message, actual_version, expected_version):
super(SchemaMismatchError, self).__init__(message)
self.actual_version = actual_version
self.expected_version = expected_version
[docs]class BaseMetadataValidator(LoggingConfigurable):
def __init__(self) -> None:
with open(
os.path.join(root, "v{:d}.json".format(self.schema_version)), "r"
) as fh:
self.schema = json.loads(fh.read())
def _remove_extra_keys(self, cell: NotebookNode) -> None:
meta = cell.metadata["nbgrader"]
allowed = set(self.schema["properties"].keys())
keys = set(meta.keys()) - allowed
if len(keys) > 0:
self.log.warning(
"extra keys detected in metadata, these will be removed: {}".format(
keys
)
)
for key in keys:
del meta[key]
[docs] def upgrade_notebook_metadata(self, nb: NotebookNode) -> NotebookNode:
for cell in nb.cells:
self.upgrade_cell_metadata(cell)
return nb
[docs] def upgrade_cell_metadata(
self, cell: NotebookNode
) -> NotebookNode: # pragma: no cover
raise NotImplementedError("this method must be implemented by subclasses")
[docs] def validate_cell(self, cell: NotebookNode) -> None:
if "nbgrader" not in cell.metadata:
return
schema = cell.metadata["nbgrader"].get("schema_version", 0)
if schema < self.schema_version:
raise SchemaTooOldError(
"Outdated schema version: {} (expected {})".format(
schema, self.schema_version
),
schema,
self.schema_version,
)
elif schema > self.schema_version:
raise SchemaTooNewError(
"Schema version is too new: {} (expected {})".format(
schema, self.schema_version
),
schema,
self.schema_version,
)
jsonschema.validate(cell.metadata["nbgrader"], self.schema)
[docs] def validate_nb(self, nb: NotebookNode) -> None:
for cell in nb.cells:
self.validate_cell(cell)