Miscs improvements (Interro02)
This commit is contained in:
@@ -11,7 +11,10 @@ from PIL import Image
|
||||
from copienator import EvaluationWorkspace, atomic_write_json, configuration, read_json
|
||||
from copienator.commands import annotating, giving_names
|
||||
from copienator.commands import reading_grouped_annotations as reader
|
||||
from copienator.return_answers import publish_answer_returns
|
||||
from copienator.return_answers import (
|
||||
publish_answer_returns,
|
||||
save_return_answer_options,
|
||||
)
|
||||
|
||||
|
||||
class AnswerReturnTests(unittest.TestCase):
|
||||
@@ -54,7 +57,7 @@ class AnswerReturnTests(unittest.TestCase):
|
||||
), patch.object(annotating, "make_base_image", side_effect=self.supplement):
|
||||
publish_answer_returns(self.root, self.source, self.destination)
|
||||
files = sorted((self.destination / "answers").glob("*.jpg"))
|
||||
self.assertEqual([p.name for p in files], ["001 - Ex 1.jpg", "002 - Ex 2.jpg"])
|
||||
self.assertEqual([p.name for p in files], ["Ex 1.jpg", "Ex 2.jpg"])
|
||||
with Image.open(files[0]) as image:
|
||||
self.assertEqual(image.size, (100, 30 + 20 * sum((context, question, solution))))
|
||||
colors = []
|
||||
@@ -70,6 +73,38 @@ class AnswerReturnTests(unittest.TestCase):
|
||||
self.assertTrue(all(abs(a - b) < 10 for a, b in zip(pixel, color)))
|
||||
self.assertEqual(read_json(self.destination / "info.json"), read_json(self.source / "info.json"))
|
||||
|
||||
def test_saved_reading_options_override_configuration_for_answers(self):
|
||||
save_return_answer_options(
|
||||
self.root,
|
||||
context=True,
|
||||
question=False,
|
||||
solution=True,
|
||||
)
|
||||
with patch.multiple(
|
||||
configuration,
|
||||
RETURN_ANSWERS_ENABLED=True,
|
||||
RETURN_ANSWERS_CONTEXT=False,
|
||||
RETURN_ANSWERS_QUESTION=True,
|
||||
RETURN_ANSWERS_SOLUTION=False,
|
||||
), patch.object(
|
||||
annotating, "make_base_image", side_effect=self.supplement
|
||||
):
|
||||
publish_answer_returns(self.root, self.source, self.destination)
|
||||
|
||||
with Image.open(self.destination / "answers" / "Ex 1.jpg") as image:
|
||||
self.assertEqual(image.size, (100, 70))
|
||||
for y, color in (
|
||||
(10, (0, 0, 255)),
|
||||
(30, (255, 255, 0)),
|
||||
(50, (255, 0, 0)),
|
||||
):
|
||||
self.assertTrue(
|
||||
all(
|
||||
abs(actual - expected) < 10
|
||||
for actual, expected in zip(image.getpixel((50, y)), color)
|
||||
)
|
||||
)
|
||||
|
||||
def test_missing_supplement_is_optional_and_failure_preserves_old_answers(self):
|
||||
with patch.multiple(configuration, RETURN_ANSWERS_ENABLED=True,
|
||||
RETURN_ANSWERS_CONTEXT=False, RETURN_ANSWERS_QUESTION=True,
|
||||
@@ -78,7 +113,7 @@ class AnswerReturnTests(unittest.TestCase):
|
||||
):
|
||||
(self.root / "Text2" / "Ex 1.pdf").unlink()
|
||||
publish_answer_returns(self.root, self.source, self.destination)
|
||||
path = self.destination / "answers" / "001 - Ex 1.jpg"
|
||||
path = self.destination / "answers" / "Ex 1.jpg"
|
||||
with Image.open(path) as image:
|
||||
self.assertEqual(image.size, (100, 30))
|
||||
original = path.read_bytes()
|
||||
@@ -86,7 +121,7 @@ class AnswerReturnTests(unittest.TestCase):
|
||||
with self.assertRaises(FileNotFoundError):
|
||||
publish_answer_returns(self.root, self.source, self.destination)
|
||||
self.assertEqual(path.read_bytes(), original)
|
||||
self.assertTrue((self.destination / "answers" / "002 - Ex 2.jpg").exists())
|
||||
self.assertTrue((self.destination / "answers" / "Ex 2.jpg").exists())
|
||||
|
||||
def test_disabling_clears_individual_images_but_retains_info(self):
|
||||
with patch.multiple(configuration, RETURN_ANSWERS_ENABLED=True,
|
||||
@@ -135,8 +170,99 @@ class AnswerReturnTests(unittest.TestCase):
|
||||
self.assertEqual(giving_names.run(workspace, annotation_dir="BGnot"), 0)
|
||||
self.assertEqual({p.name for p in self.destination.iterdir()}, {"answers", "score.json", "info.json"})
|
||||
|
||||
def test_update_uses_copy_id_from_renamed_folder_and_touches_only_answers(self):
|
||||
workspace = EvaluationWorkspace(self.root)
|
||||
workspace.copies_dir.mkdir()
|
||||
atomic_write_json(workspace.copies_dir / "Copie01.json", {"name": "Student"})
|
||||
renamed = self.destination.with_name("Nom modifié manuellement (01)")
|
||||
self.destination.rename(renamed)
|
||||
(renamed / "Nom personnalisé.jpg").write_bytes(b"keep-jpeg")
|
||||
(renamed / "Nom personnalisé.pdf").write_bytes(b"keep-pdf")
|
||||
(renamed / "score.json").write_bytes(b"keep-score")
|
||||
(renamed / "info.json").write_bytes(b"keep-info")
|
||||
answers = renamed / "answers"
|
||||
answers.mkdir()
|
||||
(answers / "obsolete.jpg").write_bytes(b"obsolete")
|
||||
preserved = {
|
||||
path.name: path.read_bytes()
|
||||
for path in renamed.iterdir()
|
||||
if path.is_file()
|
||||
}
|
||||
|
||||
with patch.multiple(
|
||||
configuration,
|
||||
RETURN_ANSWERS_ENABLED=True,
|
||||
RETURN_ANSWERS_CONTEXT=False,
|
||||
RETURN_ANSWERS_QUESTION=False,
|
||||
RETURN_ANSWERS_SOLUTION=False,
|
||||
), contextlib.redirect_stdout(io.StringIO()):
|
||||
self.assertEqual(
|
||||
giving_names.run(workspace, annotation_dir="BGnot", update=True),
|
||||
0,
|
||||
)
|
||||
|
||||
self.assertFalse((workspace.return_dir / "Student (01)").exists())
|
||||
self.assertEqual(
|
||||
{
|
||||
path.name: path.read_bytes()
|
||||
for path in renamed.iterdir()
|
||||
if path.is_file()
|
||||
},
|
||||
preserved,
|
||||
)
|
||||
self.assertEqual(
|
||||
sorted(path.name for path in answers.iterdir()),
|
||||
["Ex 1.jpg", "Ex 2.jpg"],
|
||||
)
|
||||
|
||||
|
||||
class CompiledMembershipTests(unittest.TestCase):
|
||||
def test_update_score_preserves_file_and_manual_value_wins(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
workspace = EvaluationWorkspace(Path(directory))
|
||||
output = workspace.root / "BGnot" / "Copie01"
|
||||
output.mkdir(parents=True)
|
||||
original_score = b'{\n "Ex 1": "3.5"\n}\n'
|
||||
(output / "score.json").write_bytes(original_score)
|
||||
answer = workspace.root / "answer.pdf"
|
||||
answer.touch()
|
||||
data = {
|
||||
"01": {
|
||||
"Ex 1": {
|
||||
"result": {"score": 1, "feedback": []},
|
||||
"pdf_path": answer,
|
||||
"coordinates": (0, 0),
|
||||
}
|
||||
}
|
||||
}
|
||||
rendered_scores = []
|
||||
|
||||
def compose(base, label, result, *args, **kwargs):
|
||||
rendered_scores.append(result["score"])
|
||||
return Image.new("RGB", (100, 50), "white"), 0
|
||||
|
||||
with patch.object(
|
||||
annotating, "make_base_image", return_value=(None, 0, 0)
|
||||
), patch.object(
|
||||
annotating, "compose_label_image", side_effect=compose
|
||||
), patch.object(
|
||||
reader, "get_extra_pdfs_as_images", return_value=[]
|
||||
), patch.object(reader, "save_paginated_pdf"):
|
||||
status, _ = reader.apply_actions_and_regenerate_grouped(
|
||||
workspace,
|
||||
data,
|
||||
"01",
|
||||
[{"label": "Ex 1", "type": "score", "value": "2"}],
|
||||
{},
|
||||
["Ex 1"],
|
||||
update_score=True,
|
||||
)
|
||||
|
||||
self.assertEqual(status, 0)
|
||||
self.assertEqual(rendered_scores, ["3.5"])
|
||||
self.assertEqual((output / "score.json").read_bytes(), original_score)
|
||||
self.assertEqual(read_json(output / "info.json")["Ex 1"]["score"], "3.5")
|
||||
|
||||
def test_membership_matches_actual_groups_and_saves_every_nonempty_answer(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
root = Path(directory)
|
||||
|
||||
Reference in New Issue
Block a user