Standardisation 7
This commit is contained in:
+128
-1
@@ -11,7 +11,7 @@ import unittest
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from contextlib import redirect_stderr
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
from unittest.mock import Mock, patch
|
||||
|
||||
from PIL import Image
|
||||
from pypdf import PdfReader, PdfWriter
|
||||
@@ -310,6 +310,9 @@ class StandardCliTests(unittest.TestCase):
|
||||
"page_splitter.py", "page_splitter"
|
||||
),
|
||||
"plotting": load_script_module("plotting.py", "plotting"),
|
||||
"gemini_for_labels": load_script_module(
|
||||
"gemini_for_labels.py", "gemini_for_labels"
|
||||
),
|
||||
"copies_tools": load_script_module(
|
||||
"copies_tools.py", "copienator_copies_tools_test"
|
||||
),
|
||||
@@ -351,6 +354,7 @@ class StandardCliTests(unittest.TestCase):
|
||||
"splitting_int": [missing],
|
||||
"page_splitter": [missing],
|
||||
"plotting": [missing],
|
||||
"gemini_for_labels": [missing],
|
||||
}
|
||||
for name, arguments in invocations.items():
|
||||
with self.subTest(script=name), redirect_stderr(io.StringIO()):
|
||||
@@ -463,6 +467,11 @@ class StandardCliTests(unittest.TestCase):
|
||||
"default",
|
||||
{"target": evaluation},
|
||||
),
|
||||
"gemini_for_labels": (
|
||||
"labels",
|
||||
"default",
|
||||
{"target": evaluation, "overwrite": True},
|
||||
),
|
||||
}
|
||||
for module_name, (step_id, variant_id, values) in cases.items():
|
||||
step = steps[step_id]
|
||||
@@ -773,6 +782,124 @@ class StandardCliTests(unittest.TestCase):
|
||||
self.assertIsNone(json_path)
|
||||
self.assertEqual(metadata, {"worker_error": "worker failed"})
|
||||
|
||||
def test_label_detection_resolves_copy_and_cutleft_targets(self) -> None:
|
||||
module = self.modules["gemini_for_labels"]
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
evaluation = Path(directory) / "Exam"
|
||||
copy_pdf = evaluation / "Copies" / "Copie01.pdf"
|
||||
image_one = evaluation / "Cutleft" / "Copie01_01.jpg"
|
||||
image_two = evaluation / "Cutleft" / "Copie01_02.jpg"
|
||||
copy_pdf.parent.mkdir(parents=True)
|
||||
image_one.parent.mkdir()
|
||||
copy_pdf.write_bytes(b"pdf")
|
||||
image_one.write_bytes(b"image")
|
||||
image_two.write_bytes(b"image")
|
||||
workspace = EvaluationWorkspace(evaluation)
|
||||
|
||||
images, warnings = module.selected_images(workspace, [copy_pdf])
|
||||
self.assertEqual(images, [image_one, image_two])
|
||||
self.assertEqual(warnings, [])
|
||||
images, warnings = module.selected_images(workspace, [image_two])
|
||||
self.assertEqual(images, [image_two])
|
||||
self.assertEqual(warnings, [])
|
||||
|
||||
def test_label_detection_preserves_context_and_writes_atomically(self) -> None:
|
||||
module = self.modules["gemini_for_labels"]
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
evaluation = Path(directory) / "Exam"
|
||||
copies = evaluation / "Copies"
|
||||
cutleft = evaluation / "Cutleft"
|
||||
copies.mkdir(parents=True)
|
||||
cutleft.mkdir()
|
||||
first = cutleft / "Copie01_01.jpg"
|
||||
second = cutleft / "Copie01_02.jpg"
|
||||
first.write_bytes(b"first image")
|
||||
second.write_bytes(b"second image")
|
||||
atomic_write_json(
|
||||
copies / "Copie01_01.json",
|
||||
{
|
||||
"name": "Student",
|
||||
"list": [{"box_2d": [1, 2, 3, 4], "label": "Ex 1"}],
|
||||
},
|
||||
)
|
||||
response = Mock(
|
||||
text=(
|
||||
'{"name":"Continued","list":'
|
||||
'[{"box_2d":[10,20,30,40],"label":"Ex 2"}]}'
|
||||
)
|
||||
)
|
||||
client = Mock()
|
||||
client.models.generate_content.return_value = response
|
||||
|
||||
generated = module.process_copy_group(
|
||||
EvaluationWorkspace(evaluation),
|
||||
"Copie01",
|
||||
[first, second],
|
||||
client=client,
|
||||
labels_text="Ex 1\nEx 2\n",
|
||||
names_text="Student\n",
|
||||
valid_labels={"Ex 1", "Ex 2"},
|
||||
valid_names={"Student", "Continued", "Unknown"},
|
||||
overwrite=False,
|
||||
sleep=lambda _seconds: None,
|
||||
target_interval=0,
|
||||
)
|
||||
self.assertEqual(generated, 1)
|
||||
self.assertEqual(client.models.generate_content.call_count, 1)
|
||||
self.assertEqual(
|
||||
read_json(copies / "Copie01_02.json"),
|
||||
{
|
||||
"name": "Continued",
|
||||
"list": [{"box_2d": [10, 20, 30, 40], "label": "Ex 2"}],
|
||||
},
|
||||
)
|
||||
|
||||
def test_label_detection_retries_unknown_labels(self) -> None:
|
||||
module = self.modules["gemini_for_labels"]
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
evaluation = Path(directory) / "Exam"
|
||||
(evaluation / "Copies").mkdir(parents=True)
|
||||
image = evaluation / "Cutleft" / "Copie01_01.jpg"
|
||||
image.parent.mkdir()
|
||||
image.write_bytes(b"image")
|
||||
client = Mock()
|
||||
client.models.generate_content.side_effect = [
|
||||
Mock(
|
||||
text=(
|
||||
'{"name":"Student","list":'
|
||||
'[{"box_2d":[1,2,3,4],"label":"Wrong"}]}'
|
||||
)
|
||||
),
|
||||
Mock(
|
||||
text=(
|
||||
'{"name":"Student","list":'
|
||||
'[{"box_2d":[1,2,3,4],"label":"Ex 1"}]}'
|
||||
)
|
||||
),
|
||||
]
|
||||
sleeps = []
|
||||
module.process_copy_group(
|
||||
EvaluationWorkspace(evaluation),
|
||||
"Copie01",
|
||||
[image],
|
||||
client=client,
|
||||
labels_text="Ex 1\n",
|
||||
names_text="Student\n",
|
||||
valid_labels={"Ex 1"},
|
||||
valid_names={"Student", "Unknown", "Continued"},
|
||||
overwrite=True,
|
||||
sleep=sleeps.append,
|
||||
target_interval=0,
|
||||
)
|
||||
self.assertEqual(client.models.generate_content.call_count, 2)
|
||||
self.assertIn(10, sleeps)
|
||||
self.assertEqual(
|
||||
read_json(evaluation / "Copies" / "Copie01_01.json")["list"][0][
|
||||
"label"
|
||||
],
|
||||
"Ex 1",
|
||||
)
|
||||
|
||||
def test_post_correction_main_cleans_json_atomically(self) -> None:
|
||||
module = self.modules["post_correction"]
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
|
||||
Reference in New Issue
Block a user