diff --git a/e2xgrader/converters/__init__.py b/e2xgrader/converters/__init__.py
deleted file mode 100644
index 51ac4676..00000000
--- a/e2xgrader/converters/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-from .converter import Converter
-from .generateexercise import GenerateExercise
-
-__all__ = ["Converter", "GenerateExercise"]
diff --git a/e2xgrader/converters/converter.py b/e2xgrader/converters/converter.py
deleted file mode 100644
index c4c890ab..00000000
--- a/e2xgrader/converters/converter.py
+++ /dev/null
@@ -1,28 +0,0 @@
-from traitlets import List
-from traitlets.config import Config, LoggingConfigurable
-from traitlets.utils.importstring import import_item
-
-
-class Converter(LoggingConfigurable):
- preprocessors = List([], help="List of preprocessors for the converter")
-
- def __init__(self, config=None):
- with_default_config = self.default_config()
- if config:
- with_default_config.merge(config)
- self.init_preprocessors()
-
- def init_preprocessors(self):
- self._preprocessors = []
- for preprocessor in self.preprocessors:
- if isinstance(preprocessor, type):
- self._preprocessors.append(preprocessor())
- else:
- self._preprocessors.append(import_item(preprocessor)())
-
- def default_config(self):
- return Config()
-
- def convert(self, resources):
- for preprocessor in self._preprocessors:
- preprocessor.preprocess(resources)
diff --git a/e2xgrader/converters/generateexercise.py b/e2xgrader/converters/generateexercise.py
deleted file mode 100644
index 3b02618c..00000000
--- a/e2xgrader/converters/generateexercise.py
+++ /dev/null
@@ -1,40 +0,0 @@
-import tempfile
-
-from traitlets import List
-
-from ..preprocessors.authoring import (
- AddTaskHeader,
- CopyFiles,
- CopyNotebooks,
- FillTemplate,
- GenerateTaskIDs,
- MakeExercise,
- RemoveExercise,
-)
-from .converter import Converter
-
-
-class GenerateExercise(Converter):
- preprocessors = List(
- [
- RemoveExercise,
- CopyNotebooks,
- FillTemplate,
- CopyFiles,
- GenerateTaskIDs,
- AddTaskHeader,
- MakeExercise,
- ]
- )
-
- def __init__(self, coursedir, config=None):
- super(GenerateExercise, self).__init__(config=config)
- self.coursedir = coursedir
-
- def convert(self, resources):
- with tempfile.TemporaryDirectory() as tmp:
- resources["tmp_dir"] = tmp
- resources["course_prefix"] = self.coursedir.root
- resources["source_dir"] = self.coursedir.source_directory
- for preprocessor in self._preprocessors:
- preprocessor.preprocess(resources)
diff --git a/e2xgrader/models/__init__.py b/e2xgrader/models/__init__.py
deleted file mode 100644
index 61da332f..00000000
--- a/e2xgrader/models/__init__.py
+++ /dev/null
@@ -1,17 +0,0 @@
-from .assignmentmodel import AssignmentModel
-from .basemodel import BaseModel
-from .exercisemodel import ExerciseModel
-from .presetmodel import PresetModel
-from .taskmodel import TaskModel
-from .taskpoolmodel import TaskPoolModel
-from .templatemodel import TemplateModel
-
-__all__ = [
- "TaskModel",
- "TemplateModel",
- "TaskPoolModel",
- "AssignmentModel",
- "ExerciseModel",
- "PresetModel",
- "BaseModel",
-]
diff --git a/e2xgrader/models/assignmentmodel.py b/e2xgrader/models/assignmentmodel.py
deleted file mode 100644
index b7baeb64..00000000
--- a/e2xgrader/models/assignmentmodel.py
+++ /dev/null
@@ -1,34 +0,0 @@
-import glob
-import os
-
-from traitlets import Unicode
-
-from .basemodel import BaseModel
-
-
-class AssignmentModel(BaseModel):
- directory = Unicode("source", help="The directory where assignments go.")
-
- def __get_assignment_info(self, assignment):
- return len(glob.glob(os.path.join(self.base_path(), assignment, "*.ipynb")))
-
- def list(self, **kwargs):
- if not os.path.isdir(self.base_path()):
- os.makedirs(self.base_path(), exist_ok=True)
- assignmentfolders = os.listdir(self.base_path())
- assignments = []
- for assignmentfolder in assignmentfolders:
- if assignmentfolder.startswith("."):
- continue
- exercises = self.__get_assignment_info(assignmentfolder)
- assignments.append(
- {
- "name": assignmentfolder,
- "exercises": exercises,
- "link": os.path.join(
- "taskcreator", "assignments", assignmentfolder
- ),
- }
- )
-
- return assignments
diff --git a/e2xgrader/models/basemodel.py b/e2xgrader/models/basemodel.py
deleted file mode 100644
index 5e8205a6..00000000
--- a/e2xgrader/models/basemodel.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import re
-
-from traitlets import Unicode
-from traitlets.config import LoggingConfigurable
-
-from ..utils import get_nbgrader_config
-
-
-class BaseModel(LoggingConfigurable):
- directory = Unicode(".", help="The directory of the model")
-
- def __init__(self, coursedir):
- self.coursedir = coursedir
- self.__pattern = re.compile(r"^\w+[\w\s]*\w+$")
- self.config = get_nbgrader_config()
-
- def base_path(self):
- return self.coursedir.format_path(self.directory, ".", ".")
-
- def is_valid_name(self, name):
- return self.__pattern.match(name) is not None
diff --git a/e2xgrader/models/exercisemodel.py b/e2xgrader/models/exercisemodel.py
deleted file mode 100644
index ec0fb8c0..00000000
--- a/e2xgrader/models/exercisemodel.py
+++ /dev/null
@@ -1,44 +0,0 @@
-import glob
-import os
-import shutil
-
-from traitlets import Unicode
-
-from .basemodel import BaseModel
-
-
-class ExerciseModel(BaseModel):
- directory = Unicode("source", help="The directory where assignments go.")
-
- def get(self, **kwargs):
- return {"name": kwargs["name"], "assignment": kwargs["assignment"]}
-
- def remove(self, **kwargs):
- assignment = kwargs["assignment"]
- name = kwargs["name"]
- base_path = os.path.join(self.base_path(), assignment)
- exercise_files = os.path.join(base_path, "{}_files".format(name))
- if os.path.exists(exercise_files):
- shutil.rmtree(exercise_files)
- exercise = os.path.join(base_path, "{}.ipynb".format(name))
- if os.path.exists(exercise):
- os.remove(exercise)
-
- def list(self, **kwargs):
- assignment = kwargs["assignment"]
- base_path = os.path.join(self.base_path(), assignment)
- exercisenbs = glob.glob(os.path.join(base_path, "*.ipynb"))
- exercises = []
- for exercisenb in exercisenbs:
- name = os.path.split(exercisenb)[-1].replace(".ipynb", "")
- exercises.append(
- {
- "name": name,
- "assignment": assignment,
- "link": os.path.join(
- "taskcreator", "assignments", assignment, name
- ),
- }
- )
-
- return exercises
diff --git a/e2xgrader/models/presetmodel.py b/e2xgrader/models/presetmodel.py
deleted file mode 100644
index fc5eb528..00000000
--- a/e2xgrader/models/presetmodel.py
+++ /dev/null
@@ -1,71 +0,0 @@
-import os
-
-import nbformat
-from traitlets import Unicode
-
-from .basemodel import BaseModel
-
-
-class PresetModel(BaseModel):
- task_preset_path = Unicode(
- os.path.join(os.path.dirname(__file__), "presets", "questions")
- ).tag(config=True)
-
- template_preset_path = Unicode(
- os.path.join(
- os.path.dirname(__file__),
- "presets",
- "template",
- )
- ).tag(config=True)
-
- extra_task_preset_path = Unicode(default_value=None, allow_none=True).tag(
- config=True
- )
-
- extra_template_preset_path = Unicode(default_value=None, allow_none=True).tag(
- config=True
- )
-
- def list_presets(self, preset_path):
- presets = []
- if not os.path.exists(preset_path):
- return presets
- for item in os.listdir(preset_path):
- if ".ipynb_checkpoints" in item:
- continue
- if os.path.isfile(os.path.join(preset_path, item)) and item.endswith(
- ".ipynb"
- ):
- presets.append(os.path.splitext(item)[0])
- return sorted(presets)
-
- def get_preset(self, preset_path, preset_name):
- path = os.path.join(preset_path, "{}.ipynb".format(preset_name))
- if os.path.isfile(path):
- nb = nbformat.read(path, as_version=4)
- return nb.cells
-
- def list_question_presets(self):
- presets = self.list_presets(self.task_preset_path)
- if self.extra_task_preset_path is not None:
- presets.extend(self.list_presets(self.extra_task_preset_path))
- return presets
-
- def get_question_preset(self, preset_name):
- if preset_name in self.list_presets(self.task_preset_path):
- return self.get_preset(self.task_preset_path, preset_name)
- elif self.extra_task_preset_path is not None:
- return self.get_preset(self.extra_task_preset_path, preset_name)
-
- def list_template_presets(self):
- presets = self.list_presets(self.template_preset_path)
- if self.extra_template_preset_path is not None:
- presets.extend(self.list_presets(self.extra_template_preset_path))
- return presets
-
- def get_template_preset(self, preset_name):
- if preset_name in self.list_presets(self.template_preset_path):
- return self.get_preset(self.template_preset_path, preset_name)
- elif self.extra_template_preset_path is not None:
- return self.get_preset(self.extra_template_preset_path, preset_name)
diff --git a/e2xgrader/models/presets/questions/Code (Autograded).ipynb b/e2xgrader/models/presets/questions/Code (Autograded).ipynb
deleted file mode 100644
index 25a8d01b..00000000
--- a/e2xgrader/models/presets/questions/Code (Autograded).ipynb
+++ /dev/null
@@ -1,92 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "nbgrader": {
- "grade": false,
- "grade_id": "task_question",
- "locked": true,
- "schema_version": 3,
- "solution": false,
- "task": false
- }
- },
- "source": [
- "## Question\n",
- "\n",
- "Please write your question here!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "nbgrader": {
- "grade": false,
- "grade_id": "task",
- "locked": false,
- "schema_version": 3,
- "solution": true,
- "task": false
- }
- },
- "outputs": [],
- "source": [
- "### BEGIN SOLUTION\n",
- "# Answer\n",
- "\n",
- "# Please write your code answer here!\n",
- "\n",
- "### END SOLUTION"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "nbgrader": {
- "grade": true,
- "grade_id": "test_task",
- "locked": true,
- "points": 0,
- "schema_version": 3,
- "solution": false,
- "task": false
- }
- },
- "outputs": [],
- "source": [
-
- "### BEGIN HIDDEN TESTS\n",
- "# Test\n",
- "\n",
- "# Please write your code test here!\n",
- "\n",
- "### END HIDDEN TESTS"
- ]
- }
- ],
- "metadata": {
- "celltoolbar": "Create Assignment",
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/e2xgrader/models/presets/questions/Code (Manual).ipynb b/e2xgrader/models/presets/questions/Code (Manual).ipynb
deleted file mode 100644
index ea23430e..00000000
--- a/e2xgrader/models/presets/questions/Code (Manual).ipynb
+++ /dev/null
@@ -1,68 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "nbgrader": {
- "grade": false,
- "grade_id": "task_question",
- "locked": true,
- "schema_version": 3,
- "solution": false,
- "task": false
- }
- },
- "source": [
- "## Question\n",
- "\n",
- "Please write your question here!"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "nbgrader": {
- "grade": true,
- "grade_id": "task",
- "locked": false,
- "points": 0,
- "schema_version": 3,
- "solution": true,
- "task": false
- }
- },
- "outputs": [],
- "source": [
- "### BEGIN SOLUTION\n",
- "# Answer\n",
- "\n",
- "# Please write your code answer here!\n",
- "\n",
- "### END SOLUTION"
- ]
- }
- ],
- "metadata": {
- "celltoolbar": "Create Assignment",
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/e2xgrader/models/presets/questions/Diagram.ipynb b/e2xgrader/models/presets/questions/Diagram.ipynb
deleted file mode 100644
index 3cf51c61..00000000
--- a/e2xgrader/models/presets/questions/Diagram.ipynb
+++ /dev/null
@@ -1,73 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "nbgrader": {
- "grade": false,
- "grade_id": "task_question",
- "locked": true,
- "schema_version": 3,
- "solution": false,
- "task": false
- }
- },
- "source": [
- "## Question\n",
- "\n",
- "Please write your question here!"
- ]
- },
- {
- "attachments": {
- "diagram.png": {
- "image/png": "iVBORw0KGgoAAAANSUhEUgAAAUAAAADwCAYAAABxLb1rAAAABHNCSVQICAgIfAhkiAAAAylJREFUeJzt1DEBACAMwDDAv+chY0cTBb16Z2YOQNDbDgDYYoBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZBghkGSCQZYBAlgECWQYIZBkgkGWAQJYBAlkGCGQZIJBlgECWAQJZH97eBdx+cY1yAAAAAElFTkSuQmCC"
- }
- },
- "cell_type": "markdown",
- "metadata": {
- "extended_cell": {
- "type": "diagram"
- },
- "nbgrader": {
- "grade": true,
- "grade_id": "task",
- "locked": false,
- "points": 0,
- "schema_version": 3,
- "solution": true,
- "task": false
- }
- },
- "source": [
- "# Answer\n",
- "\n",
- "\n",
- "\n",
- "![diagram](attachment:diagram.png)"
- ]
- }
- ],
- "metadata": {
- "celltoolbar": "Create Assignment",
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.12"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/e2xgrader/models/presets/questions/Freetext.ipynb b/e2xgrader/models/presets/questions/Freetext.ipynb
deleted file mode 100644
index 1b53425a..00000000
--- a/e2xgrader/models/presets/questions/Freetext.ipynb
+++ /dev/null
@@ -1,63 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "nbgrader": {
- "grade": false,
- "grade_id": "task_question",
- "locked": true,
- "schema_version": 3,
- "solution": false,
- "task": false
- }
- },
- "source": [
- "## Question\n",
- "\n",
- "Please write your question here!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "nbgrader": {
- "grade": true,
- "grade_id": "task",
- "locked": false,
- "points": 0,
- "schema_version": 3,
- "solution": true,
- "task": false
- }
- },
- "source": [
- "## Answer\n",
- "\n",
- "Please write your answer here!"
- ]
- }
- ],
- "metadata": {
- "celltoolbar": "Create Assignment",
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/e2xgrader/models/presets/questions/Multiple Choice.ipynb b/e2xgrader/models/presets/questions/Multiple Choice.ipynb
deleted file mode 100644
index df212192..00000000
--- a/e2xgrader/models/presets/questions/Multiple Choice.ipynb
+++ /dev/null
@@ -1,54 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "extended_cell": {
- "choice": [],
- "num_of_choices": 3,
- "type": "multiplechoice"
- },
- "nbgrader": {
- "grade": true,
- "grade_id": "task",
- "locked": false,
- "points": 0,
- "schema_version": 3,
- "solution": true,
- "task": false
- }
- },
- "source": [
- "## Multiplechoice Question\n",
- "\n",
- "- Choice 1\n",
- "- Choice 2\n",
- "- Choice 3\n",
- "\n",
- "Hint: Add the choices as list items, then select the correct answer!"
- ]
- }
- ],
- "metadata": {
- "celltoolbar": "Create Assignment",
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/e2xgrader/models/presets/questions/Single Choice.ipynb b/e2xgrader/models/presets/questions/Single Choice.ipynb
deleted file mode 100644
index 5dbf876a..00000000
--- a/e2xgrader/models/presets/questions/Single Choice.ipynb
+++ /dev/null
@@ -1,52 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "extended_cell": {
- "type": "singlechoice"
- },
- "nbgrader": {
- "grade": true,
- "grade_id": "task",
- "locked": false,
- "points": 0,
- "schema_version": 3,
- "solution": true,
- "task": false
- }
- },
- "source": [
- "## Singlechoice Question\n",
- "\n",
- "- Choice 1\n",
- "- Choice 2\n",
- "- Choice 3\n",
- "\n",
- "Hint: Add the choices as list items, then select the correct answer!"
- ]
- }
- ],
- "metadata": {
- "celltoolbar": "Create Assignment",
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/e2xgrader/models/presets/questions/Upload Files.ipynb b/e2xgrader/models/presets/questions/Upload Files.ipynb
deleted file mode 100644
index d9edd428..00000000
--- a/e2xgrader/models/presets/questions/Upload Files.ipynb
+++ /dev/null
@@ -1,64 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "nbgrader": {
- "grade": false,
- "grade_id": "task_question",
- "locked": true,
- "schema_version": 3,
- "solution": false,
- "task": false
- }
- },
- "source": [
- "## Question\n",
- "\n",
- "Please write your question here!"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {
- "extended_cell": {
- "type": "attachments"
- },
- "nbgrader": {
- "grade": true,
- "grade_id": "task",
- "locked": false,
- "points": 0,
- "schema_version": 3,
- "solution": true,
- "task": false
- }
- },
- "source": [
- "# Answer"
- ]
- }
- ],
- "metadata": {
- "celltoolbar": "Create Assignment",
- "kernelspec": {
- "display_name": "Python 3 (ipykernel)",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.9.12"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/e2xgrader/models/presets/template/Footer.ipynb b/e2xgrader/models/presets/template/Footer.ipynb
deleted file mode 100644
index 788b7146..00000000
--- a/e2xgrader/models/presets/template/Footer.ipynb
+++ /dev/null
@@ -1,47 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "nbassignment": {
- "type": "footer"
- },
- "nbgrader": {
- "grade": false,
- "grade_id": "footer",
- "locked": true,
- "schema_version": 3,
- "solution": false,
- "task": false
- }
- },
- "source": [
- "### This is a footer cell\n",
- "\n",
- "All footer cells will always appear at the bottom of the notebook"
- ]
- }
- ],
- "metadata": {
- "celltoolbar": "Create Assignment",
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/e2xgrader/models/presets/template/Group Info.ipynb b/e2xgrader/models/presets/template/Group Info.ipynb
deleted file mode 100644
index c0665b19..00000000
--- a/e2xgrader/models/presets/template/Group Info.ipynb
+++ /dev/null
@@ -1,42 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "nbassignment": {
- "type": "group_info"
- }
- },
- "outputs": [],
- "source": [
- "# Please fill in the usernames of all your team members\n",
- "\n",
- "member1 = ''\n",
- "member2 = ''"
- ]
- }
- ],
- "metadata": {
- "celltoolbar": "Edit Metadata",
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/e2xgrader/models/presets/template/Header.ipynb b/e2xgrader/models/presets/template/Header.ipynb
deleted file mode 100644
index 66c4862f..00000000
--- a/e2xgrader/models/presets/template/Header.ipynb
+++ /dev/null
@@ -1,47 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {
- "nbassignment": {
- "type": "header"
- },
- "nbgrader": {
- "grade": false,
- "grade_id": "header",
- "locked": true,
- "schema_version": 3,
- "solution": false,
- "task": false
- }
- },
- "source": [
- "### This is a header cell\n",
- "\n",
- "It will always appear at the top of the notebook"
- ]
- }
- ],
- "metadata": {
- "celltoolbar": "Create Assignment",
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/e2xgrader/models/presets/template/Student Info.ipynb b/e2xgrader/models/presets/template/Student Info.ipynb
deleted file mode 100644
index 9995b1ea..00000000
--- a/e2xgrader/models/presets/template/Student Info.ipynb
+++ /dev/null
@@ -1,41 +0,0 @@
-{
- "cells": [
- {
- "cell_type": "code",
- "execution_count": null,
- "metadata": {
- "nbassignment": {
- "type": "student_info"
- }
- },
- "outputs": [],
- "source": [
- "# Please fill in your matriculation number\n",
- "\n",
- "matriculation = ''"
- ]
- }
- ],
- "metadata": {
- "celltoolbar": "Edit Metadata",
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.5"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 4
-}
diff --git a/e2xgrader/models/taskmodel.py b/e2xgrader/models/taskmodel.py
deleted file mode 100644
index 16faf6f9..00000000
--- a/e2xgrader/models/taskmodel.py
+++ /dev/null
@@ -1,127 +0,0 @@
-import os
-import shutil
-from textwrap import dedent
-
-import nbformat
-from traitlets import Unicode
-
-from ..utils.nbgrader_cells import get_valid_name
-from .basemodel import BaseModel
-
-
-class TaskModel(BaseModel):
- directory = Unicode("pools", help="The directory where the task pools go.")
-
- def new_taskbook(self, name):
- nb = nbformat.v4.new_notebook()
-
- nb.metadata["nbassignment"] = {"type": "task"}
- header = nbformat.v4.new_markdown_cell()
-
- header.source = dedent(
- """
- # {}
-
- Here you should give the general information about the task.
-
- Then add questions via the menu above.
-
- A task should be self contained.
- """.format(
- name
- )
- )
-
- header.metadata["nbgrader"] = {
- "grade_id": "{}_Header".format(get_valid_name(name)),
- "locked": True,
- "solution": False,
- "grade": False,
- "task": False,
- "schema_version": 3,
- }
-
- nb.cells = [header]
-
- return nb
-
- def new(self, **kwargs):
- name = kwargs["name"]
- pool = kwargs["pool"]
- if self.is_valid_name(name):
- path = os.path.join(self.base_path(), pool, name)
- if os.path.exists(path):
- return {
- "success": False,
- "error": f"A task with the name {name} already exists!",
- }
- else:
- base_path = os.path.join(self.base_path(), pool)
- os.makedirs(os.path.join(base_path, name, "img"), exist_ok=True)
- os.makedirs(os.path.join(base_path, name, "data"), exist_ok=True)
- filename = "{}.ipynb".format(name)
- nb = self.new_taskbook(name)
- path = os.path.join(base_path, name, filename)
- nbformat.write(nb, path)
- return {"success": True, "path": os.path.join("notebooks", path)}
- else:
- return {"success": False, "error": "Invalid name"}
-
- def remove(self, **kwargs):
- name = kwargs["name"]
- pool = kwargs["pool"]
- base_path = os.path.join(self.base_path(), pool)
- shutil.rmtree(os.path.join(base_path, name))
-
- def get(self, **kwargs):
- name = kwargs["name"]
- pool = kwargs["pool"]
- points, questions = self.__get_task_info(name, pool)
- return {
- "name": name,
- "points": points,
- "questions": questions,
- "pool": pool,
- }
-
- def list(self, **kwargs):
- pool = kwargs["pool"]
- base_path = os.path.join(self.base_path(), pool)
- if not os.path.exists(base_path):
- return []
- taskfolders = os.listdir(base_path)
- tasks = []
- for taskfolder in taskfolders:
- if taskfolder.startswith("."):
- continue
- points, questions = self.__get_task_info(taskfolder, pool)
- tasks.append(
- {
- "name": taskfolder,
- "points": points,
- "questions": questions,
- "pool": pool,
- "link": os.path.join("tree", base_path, taskfolder),
- }
- )
-
- return tasks
-
- def __get_task_info(self, task, pool):
- base_path = os.path.join(self.base_path(), pool)
- notebooks = [
- file
- for file in os.listdir(os.path.join(base_path, task))
- if file.endswith(".ipynb")
- ]
-
- points = 0
- questions = 0
-
- for notebook in notebooks:
- nb = nbformat.read(os.path.join(base_path, task, notebook), as_version=4)
- for cell in nb.cells:
- if "nbgrader" in cell.metadata and cell.metadata.nbgrader.grade:
- points += cell.metadata.nbgrader.points
- questions += 1
- return points, questions
diff --git a/e2xgrader/models/taskpoolmodel.py b/e2xgrader/models/taskpoolmodel.py
deleted file mode 100644
index 3f00221c..00000000
--- a/e2xgrader/models/taskpoolmodel.py
+++ /dev/null
@@ -1,61 +0,0 @@
-import os
-import shutil
-
-from traitlets import Unicode
-
-from .basemodel import BaseModel
-
-
-class TaskPoolModel(BaseModel):
- directory = Unicode("pools", help="The directory where the task pools go.")
-
- def new(self, **kwargs):
- name = kwargs["name"]
- if self.is_valid_name(name):
- path = os.path.join(self.base_path(), name)
- if os.path.exists(path):
- return {
- "success": False,
- "error": f"A pool with the name {name} already exists!",
- }
- else:
- os.makedirs(path, exist_ok=True)
- return {"success": True, "path": path}
- else:
- return {"success": False, "error": "Invalid name"}
-
- def remove(self, **kwargs):
- name = kwargs["name"]
- path = os.path.join(self.base_path(), name)
- shutil.rmtree(path)
-
- def get(self, **kwargs):
- name = kwargs["name"]
- tasks = self.__get_pool_info(name)
- return {
- "name": name,
- "tasks": tasks,
- "link": os.path.join("taskcreator", "pools", name),
- }
-
- def list(self, **kwargs):
- if not os.path.isdir(self.base_path()):
- os.makedirs(self.base_path(), exist_ok=True)
- poolfolders = os.listdir(self.base_path())
- pools = []
- for poolfolder in poolfolders:
- if poolfolder.startswith("."):
- continue
- tasks = self.__get_pool_info(poolfolder)
- pools.append(
- {
- "name": poolfolder,
- "tasks": tasks,
- "link": os.path.join("taskcreator", "pools", poolfolder),
- }
- )
-
- return pools
-
- def __get_pool_info(self, name):
- return len(os.listdir(os.path.join(self.base_path(), name)))
diff --git a/e2xgrader/models/templatemodel.py b/e2xgrader/models/templatemodel.py
deleted file mode 100644
index 70c47fd9..00000000
--- a/e2xgrader/models/templatemodel.py
+++ /dev/null
@@ -1,67 +0,0 @@
-import os
-import shutil
-
-import nbformat
-from traitlets import Unicode
-
-from ..utils.nbgrader_cells import new_read_only_cell
-from .basemodel import BaseModel
-
-
-class TemplateModel(BaseModel):
- directory = Unicode("templates", help="The directory where the templates go.")
-
- def __init__(self, course_prefix):
- super().__init__(course_prefix)
- os.makedirs(self.base_path(), exist_ok=True)
-
- def new(self, **kwargs):
- name = kwargs["name"]
- if self.is_valid_name(name):
- path = os.path.join(self.base_path(), name)
- if os.path.exists(path):
- return {
- "success": False,
- "error": f"A template with the name {name} already exists!",
- }
- else:
- self.log.info("Creating a new template")
- self.log.info(name)
- os.makedirs(os.path.join(self.base_path(), name, "img"), exist_ok=True)
- os.makedirs(os.path.join(self.base_path(), name, "data"), exist_ok=True)
- filename = "{}.ipynb".format(name)
- nb = nbformat.v4.new_notebook()
- nb.metadata["nbassignment"] = {"type": "template"}
- cell = new_read_only_cell(
- grade_id="HeaderA",
- source=(
- "### This is a header cell\n\n"
- "It will always appear at the top of the notebook"
- ),
- )
- cell.metadata["nbassignment"] = {"type": "header"}
- nb.cells = [cell]
- path = os.path.join(self.base_path(), name, filename)
- nbformat.write(nb, path)
- return {"success": True, "path": os.path.join("notebooks", path)}
- else:
- return {"success": False, "error": "Invalid name"}
-
- def remove(self, **kwargs):
- name = kwargs["name"]
- shutil.rmtree(os.path.join(self.base_path(), name))
-
- def list(self, **kwargs):
- templatefolders = os.listdir(self.base_path())
- templates = []
- for templatefolder in templatefolders:
- if templatefolder.startswith("."):
- continue
- templates.append(
- {
- "name": templatefolder,
- "link": os.path.join("tree", self.base_path(), templatefolder),
- }
- )
-
- return templates
diff --git a/e2xgrader/preprocessors/authoring/__init__.py b/e2xgrader/preprocessors/authoring/__init__.py
deleted file mode 100644
index 6e30c266..00000000
--- a/e2xgrader/preprocessors/authoring/__init__.py
+++ /dev/null
@@ -1,19 +0,0 @@
-from .addtaskheader import AddTaskHeader
-from .copyfiles import CopyFiles
-from .copynotebooks import CopyNotebooks
-from .filltemplate import FillTemplate
-from .generatetaskids import GenerateTaskIDs
-from .makeexercise import MakeExercise
-from .preprocessor import Preprocessor
-from .removeexercise import RemoveExercise
-
-__all__ = [
- "Preprocessor",
- "RemoveExercise",
- "CopyNotebooks",
- "CopyFiles",
- "GenerateTaskIDs",
- "MakeExercise",
- "FillTemplate",
- "AddTaskHeader",
-]
diff --git a/e2xgrader/preprocessors/authoring/addtaskheader.py b/e2xgrader/preprocessors/authoring/addtaskheader.py
deleted file mode 100644
index f60762e8..00000000
--- a/e2xgrader/preprocessors/authoring/addtaskheader.py
+++ /dev/null
@@ -1,98 +0,0 @@
-import os
-from textwrap import dedent
-
-import nbformat
-
-from ...utils.nbgrader_cells import get_points, get_task_info
-from .preprocessor import Preprocessor
-
-
-class AddTaskHeader(Preprocessor):
- def get_header(self, idx, points):
- header = nbformat.v4.new_markdown_cell()
- header.metadata["nbgrader"] = {
- "grade_id": "taskheader_{}".format(idx),
- "locked": True,
- "solution": False,
- "grade": False,
- "task": False,
- "schema_version": 3,
- }
- header.source = dedent(
- """
- # Task {}
-
- **[{} Point(s)]**
- """.format(
- idx, points
- )
- ).strip()
- return header
-
- def get_sub_header(self, idx, sub_idx, points):
- header = nbformat.v4.new_markdown_cell()
- header.metadata["nbgrader"] = {
- "grade_id": "taskheader_{}_{}".format(idx, sub_idx),
- "locked": True,
- "solution": False,
- "grade": False,
- "task": False,
- "schema_version": 3,
- }
- header.source = dedent(
- """
- ## Task {}.{}
-
- **[{} Point(s)]**
- """.format(
- idx, sub_idx, points
- )
- ).strip()
- return header
-
- def add_headers(self, nb, idx):
- total_points = sum([get_points(cell) for cell in nb.cells])
- task = get_task_info(nb)
-
- if len(task["subtasks"]) < 1:
- return nb
-
- new_cells = []
- header = self.get_header(idx, total_points)
- new_cells.append(header)
- if "header" in task:
- new_cells.append(nb.cells[task["header"]])
-
- if len(task["subtasks"]) == 1:
- new_cells.extend([nb.cells[i] for i in task["subtasks"][0]])
- if "other" in task:
- new_cells.extend([nb.cells[i] for i in task["other"]])
- nb.cells = new_cells
- return nb
-
- if len(task["subtasks"]) > 1:
- for sub_idx, subtask in enumerate(task["subtasks"]):
- points = sum([get_points(nb.cells[i]) for i in subtask])
- new_cells.append(self.get_sub_header(idx, sub_idx + 1, points))
- new_cells.extend([nb.cells[i] for i in subtask])
-
- if "other" in task:
- new_cells.extend([nb.cells[i] for i in task["other"]])
- nb.cells = new_cells
- return nb
-
- def preprocess(self, resources):
- if not resources["exercise_options"]["task-headers"]:
- return
- idx = 0
- for task_dict in resources["tasks"]:
- task = os.path.join(task_dict["pool"], task_dict["task"])
- task_path = os.path.join(resources["tmp_dir"], "tasks", task)
- notebooks = [
- file for file in os.listdir(task_path) if file.endswith(".ipynb")
- ]
- for nb_file in notebooks:
- idx += 1
- task_nb = nbformat.read(os.path.join(task_path, nb_file), as_version=4)
- task_nb = self.add_headers(task_nb, idx)
- nbformat.write(task_nb, os.path.join(task_path, nb_file))
diff --git a/e2xgrader/preprocessors/authoring/copyfiles.py b/e2xgrader/preprocessors/authoring/copyfiles.py
deleted file mode 100644
index a933f129..00000000
--- a/e2xgrader/preprocessors/authoring/copyfiles.py
+++ /dev/null
@@ -1,91 +0,0 @@
-import filecmp
-import glob
-import os
-import shutil
-
-import nbformat
-
-from .preprocessor import Preprocessor
-
-
-class CopyFiles(Preprocessor):
- def rename(self, task, old_name, new_name):
- old_file_name = os.path.split(old_name)[1]
- new_file_name = os.path.split(new_name)[1]
- for nb_file in glob.glob(os.path.join(task, "*.ipynb")):
- nb = nbformat.read(nb_file, as_version=4)
- for cell in nb.cells:
- cell.source = cell.source.replace(old_name, new_name)
- if old_file_name != new_file_name:
- cell.source = cell.source.replace(old_file_name, new_file_name)
- nbformat.write(nb, nb_file)
-
- def get_new_name(self, file, dst):
- suffix = 1
- name, extension = os.path.splitext(file)
- new_name = "{}_{}{}".format(name, suffix, extension)
- while os.path.exists(os.path.join(dst, new_name)):
- suffix += 1
- new_name = "{}_{}{}".format(name, suffix, extension)
- return new_name
-
- def get_files(self, task):
- finds = []
- for subdir in ["img", "data"]:
- for root, dirs, files in os.walk(os.path.join(task, subdir)):
- dirs[:] = [d for d in dirs if d not in [".ipynb_checkpoints"]]
- for file in files:
- finds.append(os.path.relpath(os.path.join(root, file), task))
- return finds
-
- def copyfile(self, src, dst):
- """
- Copy file
-
- Arguments:
- src -- source file
- dst -- destination file
- Returns:
- status -- True if dst does not exists or is equal to src,
- False if dst exists and differs from src.
- In this case nothing is copied
- """
- if os.path.exists(dst):
- return filecmp.cmp(src, dst)
- dirs = os.path.split(dst)[0]
- os.makedirs(dirs, exist_ok=True)
- shutil.copyfile(src, dst)
- return True
-
- def copyfiles(self, src, dst, resources):
- exercise_base = "{}_files".format(resources["exercise"])
- for file in self.get_files(src):
- src_file = os.path.join(src, file)
- dst_file = os.path.join(dst, file)
- new_name = os.path.join(exercise_base, file)
- if not self.copyfile(src_file, dst_file):
- # File with that name already exists
- renamed = self.get_new_name(file, dst)
- self.copyfile(src_file, os.path.join(dst, renamed))
- new_name = os.path.join(exercise_base, renamed)
- # Rename in notebook
- self.rename(src, file, new_name)
-
- def preprocess(self, resources):
- file_folder = os.path.join(
- resources["course_prefix"],
- resources["source_dir"],
- resources["assignment"],
- "{}_files".format(resources["exercise"]),
- )
- os.makedirs(file_folder, exist_ok=True)
-
- for task_dict in resources["tasks"]:
- task = os.path.join(task_dict["pool"], task_dict["task"])
- task_path = os.path.join(resources["tmp_dir"], "tasks", task)
- self.copyfiles(task_path, file_folder, resources)
-
- template_path = os.path.join(
- resources["tmp_dir"], "template", resources["template"]
- )
- self.copyfiles(template_path, file_folder, resources)
diff --git a/e2xgrader/preprocessors/authoring/copynotebooks.py b/e2xgrader/preprocessors/authoring/copynotebooks.py
deleted file mode 100644
index 1895ef39..00000000
--- a/e2xgrader/preprocessors/authoring/copynotebooks.py
+++ /dev/null
@@ -1,21 +0,0 @@
-import os
-import shutil
-
-from .preprocessor import Preprocessor
-
-
-class CopyNotebooks(Preprocessor):
- def preprocess(self, resources):
- for task_dict in resources["tasks"]:
- task = task_dict["task"]
- pool = task_dict["pool"]
- task = os.path.join(pool, task)
- src = os.path.join(resources["course_prefix"], self.task_path, task)
- dst = os.path.join(resources["tmp_dir"], "tasks", task)
- shutil.copytree(src, dst)
- src = os.path.join(
- resources["course_prefix"], self.template_path, resources["template"]
- )
- dst = os.path.join(resources["tmp_dir"], "template", resources["template"])
- shutil.copytree(src, dst)
- return resources
diff --git a/e2xgrader/preprocessors/authoring/filltemplate.py b/e2xgrader/preprocessors/authoring/filltemplate.py
deleted file mode 100644
index 87c8b7e9..00000000
--- a/e2xgrader/preprocessors/authoring/filltemplate.py
+++ /dev/null
@@ -1,37 +0,0 @@
-import os
-import re
-
-import nbformat
-
-from .preprocessor import Preprocessor
-
-
-class FillTemplate(Preprocessor):
- def __init__(self):
- self.__pattern = re.compile(r"({{\s*(\w+)\s*}})")
-
- def replace(self, nb, replacements):
- replaced = nbformat.v4.new_notebook()
- variables = []
- for cell in nb.cells:
- source = cell.source
- variables = self.__pattern.findall(source)
- new_cell = cell.copy()
- for variable in variables:
- new_cell.source = new_cell.source.replace(
- variable[0], replacements[variable[1]]
- )
- replaced.cells.append(new_cell)
- return replaced
-
- def preprocess(self, resources):
- template_path = os.path.join(
- resources["tmp_dir"],
- "template",
- resources["template"],
- "{}.ipynb".format(resources["template"]),
- )
-
- template_nb = nbformat.read(template_path, as_version=4)
- template_nb = self.replace(template_nb, resources["template-options"])
- nbformat.write(template_nb, template_path)
diff --git a/e2xgrader/preprocessors/authoring/generatetaskids.py b/e2xgrader/preprocessors/authoring/generatetaskids.py
deleted file mode 100644
index 65f866b3..00000000
--- a/e2xgrader/preprocessors/authoring/generatetaskids.py
+++ /dev/null
@@ -1,60 +0,0 @@
-import glob
-import os
-
-import nbformat
-
-from ...utils.nbgrader_cells import (
- get_task_info,
- get_valid_name,
- is_description,
- is_grade,
- is_solution,
-)
-from .preprocessor import Preprocessor
-
-
-class GenerateTaskIDs(Preprocessor):
- def generate_ids(self, nb, name):
- task = get_task_info(nb)
-
- ids = []
- suffix = ord("A")
-
- for subtask in task["subtasks"]:
- subtask_id = "{}_{}".format(name, chr(suffix))
- ids.append(subtask_id)
- suffix += 1
- tests = 0
- headers = 0
- for idx in subtask:
- cell = nb.cells[idx]
- if is_description(cell):
- cell.metadata.nbgrader.grade_id = "{}_Description{}".format(
- subtask_id, headers
- )
- headers += 1
- elif is_solution(cell):
- cell.metadata.nbgrader.grade_id = subtask_id
- elif is_grade(cell):
- cell.metadata.nbgrader.grade_id = "test_{}{}".format(
- subtask_id, tests
- )
- tests += 1
-
- if "header" in task:
- header = nb.cells[task["header"]]
- header.metadata.nbgrader.grade_id = "{}_Header".format("".join(ids))
-
- return nb
-
- def preprocess(self, resources):
- for task_dict in resources["tasks"]:
- task = os.path.join(task_dict["pool"], task_dict["task"])
- task_path = os.path.join(resources["tmp_dir"], "tasks", task)
- nb_files = glob.glob(os.path.join(task_path, "*.ipynb"))
- for nb_file in nb_files:
- nb = nbformat.read(nb_file, as_version=4)
- name = os.path.splitext(os.path.basename(nb_file))[0]
- name = get_valid_name(name)
- self.generate_ids(nb, name)
- nbformat.write(nb, nb_file)
diff --git a/e2xgrader/preprocessors/authoring/makeexercise.py b/e2xgrader/preprocessors/authoring/makeexercise.py
deleted file mode 100644
index 6e99ecd3..00000000
--- a/e2xgrader/preprocessors/authoring/makeexercise.py
+++ /dev/null
@@ -1,73 +0,0 @@
-import os
-
-import nbformat
-from jupyter_client.kernelspec import KernelSpecManager
-
-from .preprocessor import Preprocessor
-
-
-class MakeExercise(Preprocessor):
- def new_notebook(self, resources):
- if "kernel" in resources["exercise_options"]:
- kernelspec = (
- KernelSpecManager()
- .get_kernel_spec(resources["exercise_options"]["kernel"])
- .to_dict()
- )
- return nbformat.v4.new_notebook(
- metadata={
- "kernelspec": {
- "name": resources["exercise_options"]["kernel"],
- "display_name": kernelspec["display_name"],
- }
- }
- )
- else:
- return nbformat.v4.new_notebook()
-
- def get_cell_type(self, cell):
- if ("nbassignment" in cell.metadata) and ("type" in cell.metadata.nbassignment):
- return cell.metadata.nbassignment.type
-
- def preprocess(self, resources):
- exercise = self.new_notebook(resources)
- template_path = os.path.join(
- resources["tmp_dir"],
- "template",
- resources["template"],
- "{}.ipynb".format(resources["template"]),
- )
-
- template_nb = nbformat.read(template_path, as_version=4)
- header = [
- cell
- for cell in template_nb.cells
- if self.get_cell_type(cell) in ["header", "student_info", "group_info"]
- ]
- footer = [
- cell for cell in template_nb.cells if self.get_cell_type(cell) == "footer"
- ]
-
- exercise.cells.extend(header)
-
- for task_dict in resources["tasks"]:
- task = os.path.join(task_dict["pool"], task_dict["task"])
- task_path = os.path.join(resources["tmp_dir"], "tasks", task)
- notebooks = [
- file for file in os.listdir(task_path) if file.endswith(".ipynb")
- ]
- for notebook in notebooks:
- task_nb = nbformat.read(os.path.join(task_path, notebook), as_version=4)
- exercise.cells.extend(task_nb.cells)
-
- exercise.cells.extend(footer)
-
- nbformat.write(
- exercise,
- os.path.join(
- resources["course_prefix"],
- resources["source_dir"],
- resources["assignment"],
- "{}.ipynb".format(resources["exercise"]),
- ),
- )
diff --git a/e2xgrader/preprocessors/authoring/preprocessor.py b/e2xgrader/preprocessors/authoring/preprocessor.py
deleted file mode 100644
index 04b511f7..00000000
--- a/e2xgrader/preprocessors/authoring/preprocessor.py
+++ /dev/null
@@ -1,10 +0,0 @@
-from traitlets import Unicode
-from traitlets.config import LoggingConfigurable
-
-
-class Preprocessor(LoggingConfigurable):
- template_path = Unicode("templates")
- task_path = Unicode("pools")
-
- def preprocess(self, resources):
- raise NotImplementedError
diff --git a/e2xgrader/preprocessors/authoring/removeexercise.py b/e2xgrader/preprocessors/authoring/removeexercise.py
deleted file mode 100644
index 03c9ded1..00000000
--- a/e2xgrader/preprocessors/authoring/removeexercise.py
+++ /dev/null
@@ -1,19 +0,0 @@
-import os
-import shutil
-
-from .preprocessor import Preprocessor
-
-
-class RemoveExercise(Preprocessor):
- def preprocess(self, resources):
- base_path = os.path.join(
- resources["course_prefix"], resources["source_dir"], resources["assignment"]
- )
- exercise_files = os.path.join(
- base_path, "{}_files".format(resources["exercise"])
- )
- if os.path.exists(exercise_files):
- shutil.rmtree(exercise_files)
- exercise_nb = os.path.join(base_path, "{}.ipynb".format(resources["exercise"]))
- if os.path.exists(exercise_nb):
- os.remove(exercise_nb)
diff --git a/e2xgrader/server_extensions/apps/authoring/__init__.py b/e2xgrader/server_extensions/apps/authoring/__init__.py
deleted file mode 100644
index 6ca25a4f..00000000
--- a/e2xgrader/server_extensions/apps/authoring/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from .authoring import AuthoringApp
-
-__all__ = ["AuthoringApp"]
diff --git a/e2xgrader/server_extensions/apps/authoring/apihandlers.py b/e2xgrader/server_extensions/apps/authoring/apihandlers.py
deleted file mode 100644
index 95dbb5f9..00000000
--- a/e2xgrader/server_extensions/apps/authoring/apihandlers.py
+++ /dev/null
@@ -1,166 +0,0 @@
-import json
-import os
-
-from e2xcore import urljoin
-from jupyter_client.kernelspec import KernelSpecManager
-from nbgrader.server_extensions.formgrader.base import check_xsrf
-from tornado import web
-
-from e2xgrader.converters import GenerateExercise
-from e2xgrader.models import (
- AssignmentModel,
- ExerciseModel,
- PresetModel,
- TaskModel,
- TaskPoolModel,
- TemplateModel,
-)
-
-from ..e2xgraderapi.base import E2xApiHandler
-from .notebookvariableextractor import NotebookVariableExtractor
-
-
-class BaseApiManageHandler(E2xApiHandler):
- def initialize(self, model_cls):
- self.__model = model_cls(self.coursedir)
-
- @web.authenticated
- @check_xsrf
- def post(self, **kwargs):
- self.write(self.__model.new(**kwargs))
-
- @web.authenticated
- @check_xsrf
- def delete(self, **kwargs):
- self.__model.remove(**kwargs)
- self.write({"status": True})
-
- @web.authenticated
- @check_xsrf
- def get(self, **kwargs):
- self.write(json.dumps(self.__model.get(**kwargs)))
-
- @web.authenticated
- @check_xsrf
- def put(self, **kwargs):
- self.write(self.__model.new(**kwargs))
-
-
-class BaseApiListHandler(E2xApiHandler):
- def initialize(self, model_cls):
- self.__model = model_cls(self.coursedir)
-
- @web.authenticated
- @check_xsrf
- def get(self, **kwargs):
- self.write(json.dumps(self.__model.list(**kwargs)))
-
-
-class PresetHandler(E2xApiHandler):
- def initialize(self):
- self.__model = PresetModel(self.coursedir)
-
- def _list_template(self):
- self.write(json.dumps(self.__model.list_template_presets()))
-
- def _get_template(self):
- name = self.get_argument("name")
- self.write(json.dumps(self.__model.get_template_preset(name)))
-
- def _list_question(self):
- self.write(json.dumps(self.__model.list_question_presets()))
-
- def _get_question(self):
- name = self.get_argument("name")
- self.write(json.dumps(self.__model.get_question_preset(name)))
-
- @web.authenticated
- @check_xsrf
- def get(self):
- action = self.get_argument("action")
- preset_type = self.get_argument("type")
- handler = getattr(self, "_{}_{}".format(action, preset_type))
- handler()
-
-
-class TemplateVariableHandler(E2xApiHandler):
- @web.authenticated
- @check_xsrf
- def get(self):
- template = self.get_argument("template")
- variables = NotebookVariableExtractor().extract(
- os.path.join(
- self.url_prefix, "templates", template, "{}.ipynb".format(template)
- )
- )
- self.write(json.dumps(variables))
-
-
-class KernelSpecHandler(E2xApiHandler):
- @web.authenticated
- @check_xsrf
- def get(self):
- self.write(json.dumps(KernelSpecManager().get_all_specs()))
-
-
-class GenerateExerciseHandler(E2xApiHandler):
- @web.authenticated
- @check_xsrf
- def get(self):
- resources = json.loads(self.get_argument("resources"))
- GenerateExercise(coursedir=self.coursedir).convert(resources)
- self.write({"status": True})
-
-
-pool_regex = r"(?P");
- row.append($(" ").addClass("assignment-name"));
- row.append($(" ").addClass("number-of-exercises"));
- table.append(row);
- return row;
-}
-
-function loadAssignments() {
- console.log("Loading the assignments");
- let tbl = $("#main_table");
- models = new Assignments();
- views = [];
- models.loaded = false;
- models.fetch({
- success: function () {
- tbl.empty();
- models.each(function (model) {
- let view = new AssignmentUI({
- model: model,
- el: insertRow(tbl),
- });
- views.push(view);
- });
- tbl.parent().DataTable();
-
- models.loaded = true;
- },
- });
-}
-
-let models = undefined;
-let views = [];
-
-$(window).on("load", function () {
- loadAssignments();
-});
diff --git a/e2xgrader/server_extensions/apps/authoring/static/js/base.js b/e2xgrader/server_extensions/apps/authoring/static/js/base.js
deleted file mode 100644
index bec8dec9..00000000
--- a/e2xgrader/server_extensions/apps/authoring/static/js/base.js
+++ /dev/null
@@ -1,150 +0,0 @@
-let Assignment = Backbone.Model.extend({
- idAttribute: "name",
- urlRoot: base_url + "/e2x/authoring/api/assignment",
-});
-
-let Assignments = Backbone.Collection.extend({
- model: Assignment,
- url: base_url + "/e2x/authoring/api/assignments",
-});
-
-let Exercise = Backbone.Model.extend({
- idAttribute: "name",
- initialize: function (options) {
- this.urlRoot =
- base_url + "/e2x/authoring/api/exercise/" + options.assignment;
- },
-});
-
-let Exercises = Backbone.Collection.extend({
- model: Exercise,
- initialize: function (options) {
- this.url =
- base_url + "/e2x/authoring/api/assignments/" + options.assignment;
- },
-});
-
-let Pool = Backbone.Model.extend({
- idAttribute: "name",
- urlRoot: base_url + "/e2x/authoring/api/pool",
-});
-
-let Pools = Backbone.Collection.extend({
- model: Pool,
- url: base_url + "/e2x/authoring/api/pools/",
- comparator: "name",
-});
-
-let Task = Backbone.Model.extend({
- idAttribute: "name",
- initialize: function (options) {
- this.urlRoot = base_url + "/e2x/authoring/api/task/" + options.pool;
- },
-});
-
-let Tasks = Backbone.Collection.extend({
- model: Task,
- initialize: function (options) {
- this.url = base_url + "/e2x/authoring/api/pools/" + options.pool;
- },
- comparator: "name",
-});
-
-let Template = Backbone.Model.extend({
- idAttribute: "name",
- urlRoot: base_url + "/e2x/authoring/api/template",
-});
-
-let Templates = Backbone.Collection.extend({
- model: Template,
- url: base_url + "/e2x/authoring/api/templates/",
-});
-
-let BaseUI = Backbone.View.extend({
- events: {},
-
- initialize: function () {
- this.fields = [];
- },
-
- clear: function () {
- this.fields.forEach((field) => field.empty());
- },
-
- openRemoveModal: function (body, title) {
- let footer = $("");
- footer.append(
- $("").addClass("btn btn-danger save").text("Delete")
- );
- footer.append(
- $("")
- .addClass("btn ")
- .attr("data-dismiss", "modal")
- .text("Cancel")
- );
-
- let $modal = createModal("remove-pool-modal", title, body, footer);
- let $modal_save = $modal.find("button.save");
- let that = this;
- $modal_save.click(function () {
- that.removeModel();
- $modal.modal("hide");
- });
- },
-
- removeModel: function () {
- this.model.destroy();
- this.remove();
- dataTable.row(this.$el).remove().draw();
- },
-});
-
-function insertRow(table, classes) {
- let row = $(" ");
- classes.forEach(function (cls) {
- row.append($(" ").addClass(cls));
- });
- table.append(row);
- return row;
-}
-
-function getNewModalElements(element_name) {
- let body = $("").append(
- $("
Here you can choose which assignment you want to create an exercise for. An exercise is a single Jupyter Notebook consisting of tasks. Assignments have to be created via nbgrader.
-{% endblock help %} - -{% block table_head %} -The name can contain upper and lower case letters. etc
-Name | - |
Template | - |
You can define variables in templates by enclosing them in curly braces (e.g. {{ var }}
). You can set the values here.
Variable | Value | - -
---|
Pool | - |
Selected Tasks | Controls | Available Tasks |
---|---|---|
- - | -
-
-
-
-
- |
- - - | -
Option | Value | - -
---|---|
Add Task Headers | |
Kernel |
Here you can choose or create an exercise. An exercise is a single Jupyter Notebook consisting of tasks..
-{% endblock help %} - -{% block table_head %} -Task pools are collections of tasks about the same topic. A task consists of a collection of related questions.
-{% endblock help %} - -{% block table_head %} -A task is a single Jupyter notebook consisting of a task with questions (i.e. Task 1.1, Task 1.2, Task1.3).
-{% endblock help %} - -{% block table_head %} -Templates are used for creating exercises. A template consists of header and footer cells and special cells like student info. -You can use variables in templates by enclosing them in double curly braces (e.g. {{ my_var }}. -When creating an exercise you can set the values for those variables.
-{% endblock help %} - - -{% block table_head %} -