Repository: jupyter/nbgrader

Issue:
Tests failing due to kernelspec validation on autograding
See #880 and https://travis-ci.org/jupyter/nbgrader/builds/270643170

Discussion:

Patch:
diff --git a/nbgrader/preprocessors/overwritekernelspec.py b/nbgrader/preprocessors/overwritekernelspec.py
index cff743e3..f8995051 100644
--- a/nbgrader/preprocessors/overwritekernelspec.py
+++ b/nbgrader/preprocessors/overwritekernelspec.py
@@ -14,9 +14,17 @@ class OverwriteKernelspec(NbGraderPreprocessor):
         db_url = resources['nbgrader']['db_url']
 
         with Gradebook(db_url) as gb:
-            kernelspec = gb.find_notebook(notebook_id, assignment_id).kernelspec
+            kernelspec = json.loads(
+                gb.find_notebook(notebook_id, assignment_id).kernelspec)
+            self.log.debug("Source notebook kernelspec: {}".format(kernelspec))
+            self.log.debug(
+                "Submitted notebook kernelspec: {}"
+                "".format(nb.metadata.get('kernelspec', None))
+            )
             if kernelspec:
                 self.log.debug(
-                    "Overwriting notebook kernelspec with: {}".format(kernelspec))
-                nb.metadata['kernelspec'] = json.loads(kernelspec)
+                    "Overwriting submitted notebook kernelspec: {}"
+                    "".format(kernelspec)
+                )
+                nb.metadata['kernelspec'] = kernelspec
         return nb, resources


Test patch:
diff --git a/nbgrader/tests/apps/test_nbgrader_autograde.py b/nbgrader/tests/apps/test_nbgrader_autograde.py
index 8d8576a9..eba18c8d 100644
--- a/nbgrader/tests/apps/test_nbgrader_autograde.py
+++ b/nbgrader/tests/apps/test_nbgrader_autograde.py
@@ -658,21 +658,49 @@ class TestNbGraderAutograde(BaseTestApp):
         assert not os.path.isfile(join(course_dir, "autograded", "foo", "ps1", "p1.ipynb"))
         assert not os.path.isfile(join(course_dir, "autograded", "foo", "ps1", "p2.ipynb"))
 
-    def test_handle_failure_missing_kernelspec(self, course_dir):
+    def test_missing_source_kernelspec(self, course_dir):
         with open("nbgrader_config.py", "a") as fh:
             fh.write("""c.CourseDirectory.db_assignments = [dict(name='ps1', duedate='2015-02-02 14:58:23.948203 PST')]\n""")
             fh.write("""c.CourseDirectory.db_students = [dict(id="foo"), dict(id="bar")]\n""")
             fh.write("""c.ClearSolutions.code_stub = {'python': '## Answer', 'blah': '## Answer'}""")
 
-        self._empty_notebook(join(course_dir, "source", "ps1", "p1.ipynb"), kernel="blah")
+        self._empty_notebook(join(course_dir, "source", "ps1", "p1.ipynb"))
         run_nbgrader(["assign", "ps1"])
 
-        self._empty_notebook(join(course_dir, "submitted", "foo", "ps1", "p1.ipynb"), kernel="blah")
-        self._empty_notebook(join(course_dir, "submitted", "bar", "ps1", "p1.ipynb"), kernel="python")
+        self._empty_notebook(join(course_dir, "submitted", "foo", "ps1", "p1.ipynb"), kernel="python")
+        run_nbgrader(["autograde", "ps1"])
+        assert os.path.exists(join(course_dir, "autograded", "foo", "ps1"))
+        assert os.path.isfile(join(course_dir, "autograded", "foo", "ps1", "p1.ipynb"))
+
+        self._empty_notebook(join(course_dir, "submitted", "bar", "ps1", "p1.ipynb"), kernel="blarg")
         run_nbgrader(["autograde", "ps1"], retcode=1)
+        assert not os.path.exists(join(course_dir, "autograded", "bar", "ps1"))
+
+    def test_incorrect_source_kernelspec(self, course_dir):
+        with open("nbgrader_config.py", "a") as fh:
+            fh.write("""c.CourseDirectory.db_assignments = [dict(name='ps1', duedate='2015-02-02 14:58:23.948203 PST')]\n""")
+            fh.write("""c.CourseDirectory.db_students = [dict(id="foo"), dict(id="bar")]\n""")
+            fh.write("""c.ClearSolutions.code_stub = {'python': '## Answer', 'blah': '## Answer'}""")
+
+        self._empty_notebook(join(course_dir, "source", "ps1", "p1.ipynb"), kernel="blah")
+        run_nbgrader(["assign", "ps1"])
 
+        self._empty_notebook(join(course_dir, "submitted", "foo", "ps1", "p1.ipynb"), kernel="python")
+        run_nbgrader(["autograde", "ps1"], retcode=1)
         assert not os.path.exists(join(course_dir, "autograded", "foo", "ps1"))
-        assert not os.path.exists(join(course_dir, "autograded", "bar", "ps1"))
+
+    def test_incorrect_submitted_kernelspec(self, db, course_dir):
+        with open("nbgrader_config.py", "a") as fh:
+            fh.write("""c.CourseDirectory.db_assignments = [dict(name='ps1', duedate='2015-02-02 14:58:23.948203 PST')]\n""")
+            fh.write("""c.CourseDirectory.db_students = [dict(id="foo"), dict(id="bar")]""")
+
+        self._empty_notebook(join(course_dir, "source", "ps1", "p1.ipynb"), kernel="python")
+        run_nbgrader(["assign", "ps1"])
+
+        self._empty_notebook(join(course_dir, "submitted", "foo", "ps1", "p1.ipynb"), kernel="blah")
+        run_nbgrader(["autograde", "ps1"])
+        assert os.path.exists(join(course_dir, "autograded", "foo", "ps1"))
+        assert os.path.isfile(join(course_dir, "autograded", "foo", "ps1", "p1.ipynb"))
 
     def test_no_execute(self, course_dir):
         with open("nbgrader_config.py", "a") as fh:
@@ -771,23 +799,6 @@ class TestNbGraderAutograde(BaseTestApp):
 
         assert not os.path.isfile(join(course_dir, "autograded", "foo", "ps1", "p1.ipynb"))
 
-    def test_overwrite_kernelspec(self, db, course_dir):
-        with open("nbgrader_config.py", "a") as fh:
-            fh.write("""c.CourseDirectory.db_assignments = [dict(name='ps1', duedate='2015-02-02 14:58:23.948203 PST')]\n""")
-            fh.write("""c.CourseDirectory.db_students = [dict(id="foo"), dict(id="bar")]""")
-
-        self._empty_notebook(join(course_dir, "source", "ps1", "p1.ipynb"))
-        run_nbgrader(["assign", "ps1"])
-
-        self._empty_notebook(join(course_dir, "submitted", "foo", "ps1", "p1.ipynb"))
-        self._empty_notebook(join(course_dir, "submitted", "bar", "ps1", "p1.ipynb"), kernel="blah")
-        run_nbgrader(["autograde", "ps1"])
-
-        assert os.path.exists(join(course_dir, "autograded", "foo", "ps1"))
-        assert os.path.isfile(join(course_dir, "autograded", "foo", "ps1", "p1.ipynb"))
-        assert os.path.exists(join(course_dir, "autograded", "bar", "ps1"))
-        assert os.path.isfile(join(course_dir, "autograded", "bar", "ps1", "p1.ipynb"))
-
     def test_missing_files(self, db, course_dir):
         with open("nbgrader_config.py", "a") as fh:
             fh.write("""c.CourseDirectory.db_assignments = [dict(name='ps1', duedate='2015-02-02 14:58:23.948203 PST')]\n""")