From 758d9165a32aef94b9dea175bca2e6d2093b5c9b Mon Sep 17 00:00:00 2001 From: Chris Pyles Date: Fri, 21 Jul 2023 13:32:15 -0700 Subject: [PATCH] add force-save to otter assign for r notebooks --- CHANGELOG.md | 5 ++++ otter/assign/assignment.py | 6 ++++- otter/assign/notebook_transformer.py | 4 ---- otter/assign/r_adapter/cell_factory.py | 23 ++++++++++++++----- otter/generate/__init__.py | 2 +- .../r-correct/autograder/r-example.ipynb | 5 ++-- .../files/r-correct/student/r-example.ipynb | 5 ++-- test/test_assign/files/r-example.ipynb | 1 + .../files/rmd-autograder-correct/setup.sh | 2 +- .../files/autograder-r-correct/setup.sh | 2 +- .../setup.sh | 2 +- 11 files changed, 36 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7c9393cc..989e41b18 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # Changelog +**v5.1.0 (unreleased):** + +* Added notebook force-save to R notebook assignments per [#474](https://github.com/ucbds-infra/otter-grader/issues/474) +* Updated default version of `ottr` to v1.4.0 + **v5.0.1:** * Added `nbconvert` as a required dependency for non-WASM environments diff --git a/otter/assign/assignment.py b/otter/assign/assignment.py index 30e28953e..76c5e791e 100644 --- a/otter/assign/assignment.py +++ b/otter/assign/assignment.py @@ -244,9 +244,11 @@ def __init__(self, user_config: Dict[str, Any] = {}, **kwargs) -> None: self._logger.debug(f"Initializing with config: {user_config}") super().__init__(user_config, **kwargs) - # convert a boolean to a config object for self.generate if indicated + # convert true values masking subkey contains to those containers if self.generate is True: self.generate = AutograderConfig() + if self.export_cell is True: + self.export_cell = type(self).ExportCellValue() if self.variables: warnings.warn( @@ -258,6 +260,8 @@ def update(self, user_config: Dict[str, Any]): ret = super().update(user_config) if self.generate is True: self.generate = AutograderConfig() + if self.export_cell is True: + self.export_cell = type(self).ExportCellValue() return ret @property diff --git a/otter/assign/notebook_transformer.py b/otter/assign/notebook_transformer.py index 68c1da3d4..c780c9690 100644 --- a/otter/assign/notebook_transformer.py +++ b/otter/assign/notebook_transformer.py @@ -109,10 +109,6 @@ def transform_notebook(self, nb) -> "TransformedNotebookContainer": transformed_cells += self.cell_factory.create_check_all_cells() if self.assignment.export_cell: - export_cell = self.assignment.export_cell - if export_cell is True: - export_cell = {} - transformed_cells += self.cell_factory.create_export_cells() transformed_nb = copy.deepcopy(nb) diff --git a/otter/assign/r_adapter/cell_factory.py b/otter/assign/r_adapter/cell_factory.py index 57c0f47e1..e0396d59a 100644 --- a/otter/assign/r_adapter/cell_factory.py +++ b/otter/assign/r_adapter/cell_factory.py @@ -29,22 +29,33 @@ def create_export_cells(self): if not self.assignment.export_cell: return [] + force_save = not self.assignment.is_rmd and self.assignment.export_cell.force_save + instructions = nbformat.v4.new_markdown_cell() instructions.source = "## Submission\n\nMake sure you have run all cells in your " \ "notebook in order before running the cell below, so that all images/graphs appear " \ - "in the output. The cell below will generate a zip file for you to submit. **Please " \ - "save before exporting!**" + "in the output. The cell below will generate a zip file for you to submit." + + if not force_save: instructions.source += " **Please save before exporting!**" if self.assignment.export_cell.instructions: instructions.source += '\n\n' + self.assignment.export_cell.instructions - pdf_arg = "" + args = [] if self.assignment.export_cell.pdf: - pdf_arg = ", pdf = TRUE" + args.append("pdf = TRUE") + if force_save: + args.append("force_save = TRUE") + + if args: + args = ", " + ", ".join(args) + else: + args = "" export = nbformat.v4.new_code_cell() - source_lines = ["# Save your notebook first, then run this cell to export your submission."] - source_lines.append(f'ottr::export("{self.assignment.notebook_basename}"{pdf_arg})') + source_lines = [] if force_save else \ + ["# Save your notebook first, then run this cell to export your submission."] + source_lines.append(f'ottr::export("{self.assignment.notebook_basename}"{args})') export.source = "\n".join(source_lines) lock(instructions) diff --git a/otter/generate/__init__.py b/otter/generate/__init__.py index 0aec5afe2..f51eb0596 100644 --- a/otter/generate/__init__.py +++ b/otter/generate/__init__.py @@ -24,7 +24,7 @@ DEFAULT_PYTHON_VERSION = "3.9" OTTER_ENV_NAME = "otter-env" -OTTR_VERSION = "1.2.0" +OTTR_VERSION = "1.4.0" TEMPLATE_DIR = pkg_resources.resource_filename(__name__, "templates") GENERAL_TEMPLATE_DIR = os.path.join(TEMPLATE_DIR, "general") diff --git a/test/test_assign/files/r-correct/autograder/r-example.ipynb b/test/test_assign/files/r-correct/autograder/r-example.ipynb index f444a0bb4..ebd7e2f48 100644 --- a/test/test_assign/files/r-correct/autograder/r-example.ipynb +++ b/test/test_assign/files/r-correct/autograder/r-example.ipynb @@ -433,7 +433,7 @@ "source": [ "## Submission\n", "\n", - "Make sure you have run all cells in your notebook in order before running the cell below, so that all images/graphs appear in the output. The cell below will generate a zip file for you to submit. **Please save before exporting!**" + "Make sure you have run all cells in your notebook in order before running the cell below, so that all images/graphs appear in the output. The cell below will generate a zip file for you to submit." ] }, { @@ -445,8 +445,7 @@ }, "outputs": [], "source": [ - "# Save your notebook first, then run this cell to export your submission.\n", - "ottr::export(\"r-example.ipynb\")" + "ottr::export(\"r-example.ipynb\", force_save = TRUE)" ] }, { diff --git a/test/test_assign/files/r-correct/student/r-example.ipynb b/test/test_assign/files/r-correct/student/r-example.ipynb index 27021025f..5ef03de05 100644 --- a/test/test_assign/files/r-correct/student/r-example.ipynb +++ b/test/test_assign/files/r-correct/student/r-example.ipynb @@ -298,7 +298,7 @@ "source": [ "## Submission\n", "\n", - "Make sure you have run all cells in your notebook in order before running the cell below, so that all images/graphs appear in the output. The cell below will generate a zip file for you to submit. **Please save before exporting!**" + "Make sure you have run all cells in your notebook in order before running the cell below, so that all images/graphs appear in the output. The cell below will generate a zip file for you to submit." ] }, { @@ -310,8 +310,7 @@ }, "outputs": [], "source": [ - "# Save your notebook first, then run this cell to export your submission.\n", - "ottr::export(\"r-example.ipynb\")" + "ottr::export(\"r-example.ipynb\", force_save = TRUE)" ] }, { diff --git a/test/test_assign/files/r-example.ipynb b/test/test_assign/files/r-example.ipynb index 8420c750c..c7f87f82a 100644 --- a/test/test_assign/files/r-example.ipynb +++ b/test/test_assign/files/r-example.ipynb @@ -11,6 +11,7 @@ "solutions_pdf: true\n", "export_cell:\n", " pdf: false\n", + " force_save: true\n", "files:\n", " - data.csv" ] diff --git a/test/test_assign/files/rmd-autograder-correct/setup.sh b/test/test_assign/files/rmd-autograder-correct/setup.sh index 650e04100..beebd8663 100644 --- a/test/test_assign/files/rmd-autograder-correct/setup.sh +++ b/test/test_assign/files/rmd-autograder-correct/setup.sh @@ -33,4 +33,4 @@ mamba env create -f /autograder/source/environment.yml mamba init --all # install ottr -mamba run -n otter-env Rscript -e 'install.packages("https://cran.r-project.org/package=ottr&version=1.2.0", dependencies=TRUE, repos=NULL)' +mamba run -n otter-env Rscript -e 'install.packages("https://cran.r-project.org/package=ottr&version=1.4.0", dependencies=TRUE, repos=NULL)' diff --git a/test/test_generate/files/autograder-r-correct/setup.sh b/test/test_generate/files/autograder-r-correct/setup.sh index 30dea6d3c..d56b73b9d 100644 --- a/test/test_generate/files/autograder-r-correct/setup.sh +++ b/test/test_generate/files/autograder-r-correct/setup.sh @@ -32,4 +32,4 @@ mamba env create -f /autograder/source/environment.yml mamba init --all # install ottr -mamba run -n otter-env Rscript -e 'install.packages("https://cran.r-project.org/package=ottr&version=1.2.0", dependencies=TRUE, repos=NULL)' +mamba run -n otter-env Rscript -e 'install.packages("https://cran.r-project.org/package=ottr&version=1.4.0", dependencies=TRUE, repos=NULL)' diff --git a/test/test_generate/files/autograder-r-requirements-correct/setup.sh b/test/test_generate/files/autograder-r-requirements-correct/setup.sh index 8860784b8..1dc985549 100644 --- a/test/test_generate/files/autograder-r-requirements-correct/setup.sh +++ b/test/test_generate/files/autograder-r-requirements-correct/setup.sh @@ -33,4 +33,4 @@ mamba run -n otter-env Rscript /autograder/source/requirements.r mamba init --all # install ottr -mamba run -n otter-env Rscript -e 'install.packages("https://cran.r-project.org/package=ottr&version=1.2.0", dependencies=TRUE, repos=NULL)' +mamba run -n otter-env Rscript -e 'install.packages("https://cran.r-project.org/package=ottr&version=1.4.0", dependencies=TRUE, repos=NULL)'