diff --git a/src/scwidgets/exercise/_widget_exercise_registry.py b/src/scwidgets/exercise/_widget_exercise_registry.py index 030a8be..9b1257b 100644 --- a/src/scwidgets/exercise/_widget_exercise_registry.py +++ b/src/scwidgets/exercise/_widget_exercise_registry.py @@ -101,7 +101,7 @@ def load(self) -> Union[str, Exception]: raise ValueError( "No exercise key given on initialization, save cannot be used" ) - return self._exercise_registry.load_answer(self._exercise_key) + return self._exercise_registry.load_answer_from_loaded_file(self._exercise_key) @property def exercise_registry(self): @@ -341,26 +341,65 @@ def create_new_file_from_student_name(self, student_name: str): self._loaded_file_name = answers_filename - def load_answer(self, exercise_key: Hashable) -> str: + def load_answer_from_student_name( + self, student_name: str, exercise_key: Union[Hashable, ExerciseWidget] + ): """ - Only works when file has been loaded + Loads the answer with key `exercise_key` from the file corresponding to + `student_name`. - :param exercise_key: - unique exercise key for widget to store, so it can be reloaded persistently - after a restart of the python kernel + :raises KeyError: Corresponding widget to exercise_key cannot be found + :raises KeyError: Corresponding key in file cannot be found + :raises FileNotFoundError: If the file cannot be found + :param student_name: The name of the student + :param exercise_key: Unique exercise key for widget to store, so it can + be reloaded persistently after a restart of the python kernel + """ + self.load_answer(self.get_answer_filename(student_name), exercise_key) + + def load_answer_from_loaded_file( + self, exercise_key: Union[Hashable, ExerciseWidget] + ) -> str: + """ + Loads the answer with key `exercise_key` from the currently loaded file. + + :raises ValueError: No have has been loaded + :raises KeyError: Corresponding widget to exercise_key cannot be found + :raises KeyError: Corresponding key in file cannot be found + :raises FileNotFoundError: If the file cannot be found + :param exercise_key: Unique exercise key for widget to store, so it can + be reloaded persistently after a restart of the python kernel """ + if self._loaded_file_name is None: + raise ValueError("No file has been loaded.") + + self.load_answer(self._loaded_file_name, exercise_key) + return f"Exercise has been loaded from file {self._loaded_file_name!r}." + + def load_answer( + self, answers_filename: str, exercise_key: Union[Hashable, ExerciseWidget] + ): + """ + Loads the answer with key `exercise_key` from the `answer_filename`. + + :raises KeyError: Corresponding widget to exercise_key cannot be found + :raises KeyError: Corresponding key in file cannot be found + :raises FileNotFoundError: If the file cannot be found + :param answers_filename: The file with the answer + :param exercise_key: Unique exercise key for widget to store, so it can + be reloaded persistently after a restart of the python kernel + """ + if isinstance(exercise_key, ExerciseWidget): + exercise_key = exercise_key.exercise_key + if exercise_key not in self._widgets.keys(): raise KeyError( f"There is no widget registered with exercise key {exercise_key!r}." ) - if self._loaded_file_name is None: - raise ValueError("No file has been selected in the dropdown list.") - - answers_filename = self._loaded_file_name if not (os.path.exists(answers_filename)): raise FileNotFoundError( - "Selected file does not exist anymore. Maybe you have renamed " + f"The file {answers_filename!r} does not exist. Maybe you have renamed " "or deleted it? Please choose another file or create a new one." ) @@ -375,9 +414,6 @@ def load_answer(self, exercise_key: Hashable) -> str: else: self._widgets[exercise_key].answer = answers[exercise_key] self._loaded_file_name = answers_filename - return f"Exercise has been loaded from file {answers_filename!r}." - - self._answers_files_dropdown.value def load_file_from_dropdown(self) -> str: """ @@ -410,7 +446,7 @@ def load_file(self, answers_filename: str): if not (os.path.exists(answers_filename)): raise FileNotFoundError( - "Selected file does not exist anymore. Maybe you have renamed " + f"The file {answers_filename!r} does not exist. Maybe you have renamed " "or deleted it? Please choose another file or create a new one." ) diff --git a/tests/test_answer.py b/tests/test_answer.py index 9636d5a..fca4aa5 100644 --- a/tests/test_answer.py +++ b/tests/test_answer.py @@ -213,7 +213,8 @@ def test_load_file_from_dropdown(self): # Tests if error is raised on moved file os.rename(f"{self.prefix}-{self.student_name}.json", "tmp.json") with pytest.raises( - FileNotFoundError, match=r".*Selected file does not exist anymore.*" + FileNotFoundError, + match=r".*The file 'pytest-test-answer-registry.json' does not exist.*", ): answer_registry.load_file_from_dropdown() os.rename("tmp.json", f"{self.prefix}-{self.student_name}.json") @@ -236,18 +237,26 @@ def test_load_file_from_dropdown(self): assert answer_widget_1.answer == "update_1" assert answer_widget_2.answer == "update_2" - def test_load_answer(self): + def test_load_answer_from_loaded_file(self): answers = {"exercise_1": "answer_1", "exercise_2": "answer_2"} with open(f"{self.prefix}-{self.student_name}.json", "w") as answer_file: json.dump(answers, answer_file) answer_registry = ExerciseRegistry(filename_prefix=self.prefix) + with pytest.raises( + ValueError, + match=r".*No file has been loaded*", + ): + answer_registry.load_answer_from_loaded_file("notkey") + # To avoid the no loaded file error + answer_registry._loaded_file_name = "some" with pytest.raises( KeyError, match=r".*There is no widget registered with exercise key 'notkey'.*", ): - answer_registry.load_answer("notkey") + answer_registry.load_answer_from_loaded_file("notkey") + answer_registry._loaded_file_name = None exercise_key_1 = "exercise_1" answer_widget_1 = mock_answer_widget(answer_registry, exercise_key_1) @@ -259,10 +268,8 @@ def test_load_answer(self): answer_registry._answers_files_dropdown.value = ( answer_registry._create_new_file_dropdown_option() ) - with pytest.raises( - ValueError, match=r".*No file has been selected in the dropdown list.*" - ): - answer_registry.load_answer(exercise_key_1) + with pytest.raises(ValueError, match=r".*No file has been loaded.*"): + answer_registry.load_answer_from_loaded_file(exercise_key_1) # select back file to load answer_registry._answers_files_dropdown.value = ( f"{self.prefix}-{self.student_name}.json" @@ -272,15 +279,16 @@ def test_load_answer(self): # Tests if error is raised on moved file os.rename(f"{self.prefix}-{self.student_name}.json", "tmp.json") with pytest.raises( - FileNotFoundError, match=r".*Selected file does not exist anymore.*" + FileNotFoundError, + match=r".*The file 'pytest-test-answer-registry.json' does not exist.*", ): - answer_registry.load_answer(exercise_key_1) + answer_registry.load_answer_from_loaded_file(exercise_key_1) os.rename("tmp.json", f"{self.prefix}-{self.student_name}.json") # Test that file is contains only the updated answer answer_widget_1.answer = "update_1" answer_widget_2.answer = "update_2" - result = answer_registry.load_answer(exercise_key_1) + result = answer_registry.load_answer_from_loaded_file(exercise_key_1) assert ( result == "Exercise has been loaded from file " "'pytest-test-answer-registry.json'."